Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useMutation, useQuery, useQueryClient } from "react-query";
import { useParams } from "react-router";
import { toast } from "sonner";
import { getErrorDetail, getErrorMessage } from "#/api/errors";
import { updateOrganization } from "#/api/queries/organizations";
import { deleteOrganizationRole, organizationRoles } from "#/api/queries/roles";
import type { Role } from "#/api/typesGenerated";
import { DeleteDialog } from "#/components/Dialogs/DeleteDialog/DeleteDialog";
Expand All @@ -12,6 +13,7 @@ import {
SettingsHeaderDescription,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { useDashboard } from "#/modules/dashboard/useDashboard";
import { useFeatureVisibility } from "#/modules/dashboard/useFeatureVisibility";
import { useOrganizationSettings } from "#/modules/management/OrganizationSettingsLayout";
import { RequirePermission } from "#/modules/permissions/RequirePermission";
Expand All @@ -25,6 +27,10 @@ const CustomRolesPage: FC = () => {
organization: string;
};
const { organization, organizationPermissions } = useOrganizationSettings();
const { experiments, entitlements } = useDashboard();
const defaultRolesEnabled = experiments.includes("minimum-implicit-member");
const defaultRolesEntitled =
entitlements.features.multiple_organizations.enabled;

const [roleToDelete, setRoleToDelete] = useState<Role>();

Expand All @@ -39,6 +45,9 @@ const CustomRolesPage: FC = () => {
const deleteRoleMutation = useMutation(
deleteOrganizationRole(queryClient, organizationName),
);
const updateOrganizationMutation = useMutation(
updateOrganization(queryClient),
);

useEffect(() => {
if (organizationRolesQuery.error) {
Expand Down Expand Up @@ -80,13 +89,33 @@ const CustomRolesPage: FC = () => {
</div>

<CustomRolesPageView
organization={organization}
builtInRoles={builtInRoles}
customRoles={customRoles}
onDeleteRole={setRoleToDelete}
canCreateOrgRole={organizationPermissions?.createOrgRoles ?? false}
canUpdateOrgRole={organizationPermissions?.updateOrgRoles ?? false}
canDeleteOrgRole={organizationPermissions?.deleteOrgRoles ?? false}
canEditDefaultRoles={organizationPermissions?.editSettings ?? false}
isCustomRolesEnabled={isCustomRolesEnabled}
defaultRolesEnabled={defaultRolesEnabled}
defaultRolesEntitled={defaultRolesEntitled}
availableOrgRoles={organizationRolesQuery.data}
isUpdatingDefaultRoles={updateOrganizationMutation.isPending}
onUpdateDefaultRoles={async (roles) => {
try {
await updateOrganizationMutation.mutateAsync({
organizationId: organization.id,
req: { default_org_member_roles: roles },
});
toast.success("Default roles updated.");
} catch (error) {
toast.error(
getErrorMessage(error, "Failed to update default roles."),
{ description: getErrorDetail(error) },
);
}
}}
Comment on lines +105 to +118

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small nit and unsure of other frontend peep's opinions on this, but I think I'd prefer to have this try/catch logic moved out of the markup (or removed entirely).

I think we should either:

  • Update the existing useMutation to define onSuccess and onError handlers (although making sure to not overwrite the original onSuccess and onError definitions).
  • Make use of mutate's onSuccess and onError call arguments to achieve this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see it was just copying the pattern below for DeleteDialog.
I am going to leave this pattern right here so this CustomRolesPage is consistent with itself. Any fix should do both

/>

<DeleteDialog
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,59 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { action } from "storybook/actions";
import { expect, userEvent, within } from "storybook/test";
import type { AssignableRoles } from "#/api/typesGenerated";
import {
MockOrganization,
MockOrganizationAuditorRole,
MockRoleWithOrgPermissions,
} from "#/testHelpers/entities";
import { CustomRolesPageView } from "./CustomRolesPageView";

const mockOrgRoles: AssignableRoles[] = [
{
name: "organization-workspace-access",
display_name: "Organization Workspace Access",
organization_id: MockOrganization.id,
site_permissions: [],
organization_permissions: [],
organization_member_permissions: [],
user_permissions: [],
assignable: true,
built_in: true,
},
{
name: "organization-admin",
display_name: "Organization Admin",
organization_id: MockOrganization.id,
site_permissions: [],
organization_permissions: [],
organization_member_permissions: [],
user_permissions: [],
assignable: true,
built_in: true,
},
{
name: "agents-access",
display_name: "Agents Access",
organization_id: MockOrganization.id,
site_permissions: [],
organization_permissions: [],
organization_member_permissions: [],
user_permissions: [],
assignable: true,
built_in: true,
},
];

const meta: Meta<typeof CustomRolesPageView> = {
title: "pages/OrganizationCustomRolesPage",
component: CustomRolesPageView,
args: {
organization: MockOrganization,
builtInRoles: [MockRoleWithOrgPermissions],
customRoles: [MockRoleWithOrgPermissions],
canCreateOrgRole: true,
canEditDefaultRoles: true,
isCustomRolesEnabled: true,
},
};
Expand Down Expand Up @@ -66,3 +108,98 @@ export const EmptyTableUserWithPermission: Story = {
customRoles: [],
},
};

export const DefaultRolesHidden: Story = {
args: {
defaultRolesEnabled: false,
availableOrgRoles: mockOrgRoles,
onUpdateDefaultRoles: async () => {
action("onUpdateDefaultRoles")();
},
},
play: async ({ canvasElement }) => {
const body = within(canvasElement.ownerDocument.body);
expect(body.queryByText("Default Roles")).toBeNull();
},
};

export const DefaultRolesEnabled: Story = {
args: {
defaultRolesEnabled: true,
defaultRolesEntitled: true,
availableOrgRoles: mockOrgRoles,
onUpdateDefaultRoles: async () => {
action("onUpdateDefaultRoles")();
},
},
};

export const DefaultRolesNotEntitled: Story = {
args: {
defaultRolesEnabled: true,
defaultRolesEntitled: false,
availableOrgRoles: mockOrgRoles,
onUpdateDefaultRoles: async () => {
action("onUpdateDefaultRoles")();
},
},
play: async ({ canvasElement }) => {
const body = within(canvasElement.ownerDocument.body);
const editButton = await body.findByRole("button", {
name: /edit default roles/i,
});
expect(editButton).toBeDisabled();
await body.findByText(/requires a Premium license/i);
},
};

export const DefaultRolesEmpty: Story = {
args: {
organization: {
...MockOrganization,
default_org_member_roles: [],
},
defaultRolesEnabled: true,
defaultRolesEntitled: true,
availableOrgRoles: mockOrgRoles,
onUpdateDefaultRoles: async () => {
action("onUpdateDefaultRoles")();
},
},
};

export const DefaultRolesHiddenWithoutEditPermission: Story = {
args: {
defaultRolesEnabled: true,
defaultRolesEntitled: true,
canEditDefaultRoles: false,
availableOrgRoles: mockOrgRoles,
onUpdateDefaultRoles: async () => {
action("onUpdateDefaultRoles")();
},
},
play: async ({ canvasElement }) => {
const body = within(canvasElement.ownerDocument.body);
expect(body.queryByText("Default Roles")).toBeNull();
},
};

export const DefaultRolesEditDialog: Story = {
args: {
defaultRolesEnabled: true,
defaultRolesEntitled: true,
availableOrgRoles: mockOrgRoles,
onUpdateDefaultRoles: async () => {
action("onUpdateDefaultRoles")();
},
},
play: async ({ canvasElement }) => {
const user = userEvent.setup();
const body = within(canvasElement.ownerDocument.body);
const editButton = await body.findByRole("button", {
name: /edit default roles/i,
});
await user.click(editButton);
await body.findByRole("heading", { name: /edit default roles/i });
},
};
Loading