add role update (#11217)
## Context This PR introduces the new Create and Edit role components, behind the PERMISSIONS_ENABLED_V2 feature flag.
This commit is contained in:
@ -0,0 +1,15 @@
|
||||
import { SettingsRolesQueryEffect } from '@/settings/roles/components/SettingsRolesQueryEffect';
|
||||
import { SettingsRole } from '@/settings/roles/role/components/SettingsRole';
|
||||
import { SettingsRoleCreateEffect } from '@/settings/roles/role/components/SettingsRoleCreateEffect';
|
||||
|
||||
export const PENDING_ROLE_ID = 'pending-role-id';
|
||||
|
||||
export const SettingsRoleCreate = () => {
|
||||
return (
|
||||
<>
|
||||
<SettingsRolesQueryEffect />
|
||||
<SettingsRoleCreateEffect roleId={PENDING_ROLE_ID} />
|
||||
<SettingsRole roleId={PENDING_ROLE_ID} isCreateMode={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -1,119 +1,21 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useEffect } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { H3Title, IconLockOpen, IconSettings, IconUserPlus } from 'twenty-ui';
|
||||
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { RoleAssignment } from '@/settings/roles/role-assignment/components/RoleAssignment';
|
||||
import { RolePermissions } from '@/settings/roles/role-permissions/components/RolePermissions';
|
||||
import { RoleSettings } from '@/settings/roles/role-settings/components/RoleSettings';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||
import { TabList } from '@/ui/layout/tab/components/TabList';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab/states/activeTabIdComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useGetRolesQuery } from '~/generated/graphql';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
|
||||
export const SETTINGS_ROLE_DETAIL_TABS = {
|
||||
COMPONENT_INSTANCE_ID: 'settings-role-detail-tabs',
|
||||
TABS_IDS: {
|
||||
ASSIGNMENT: 'assignment',
|
||||
PERMISSIONS: 'permissions',
|
||||
SETTINGS: 'settings',
|
||||
},
|
||||
} as const;
|
||||
import { SettingsRolesQueryEffect } from '@/settings/roles/components/SettingsRolesQueryEffect';
|
||||
import { SettingsRole } from '@/settings/roles/role/components/SettingsRole';
|
||||
import { SettingsRoleEditEffect } from '@/settings/roles/role/components/SettingsRoleEditEffect';
|
||||
import { Navigate, useParams } from 'react-router-dom';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SettingsRoleEdit = () => {
|
||||
const { roleId = '' } = useParams();
|
||||
const navigateSettings = useNavigateSettings();
|
||||
const { data: rolesData, loading: rolesLoading } = useGetRolesQuery({
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
const { roleId } = useParams();
|
||||
|
||||
const role = rolesData?.getRoles.find((r) => r.id === roleId);
|
||||
|
||||
const activeTabId = useRecoilComponentValueV2(
|
||||
activeTabIdComponentState,
|
||||
SETTINGS_ROLE_DETAIL_TABS.COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!rolesLoading && !role) {
|
||||
navigateSettings(SettingsPath.Roles);
|
||||
}
|
||||
}, [role, navigateSettings, rolesLoading]);
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
id: SETTINGS_ROLE_DETAIL_TABS.TABS_IDS.ASSIGNMENT,
|
||||
title: t`Assignment`,
|
||||
Icon: IconUserPlus,
|
||||
hide: false,
|
||||
},
|
||||
{
|
||||
id: SETTINGS_ROLE_DETAIL_TABS.TABS_IDS.PERMISSIONS,
|
||||
title: t`Permissions`,
|
||||
Icon: IconLockOpen,
|
||||
hide: false,
|
||||
},
|
||||
{
|
||||
id: SETTINGS_ROLE_DETAIL_TABS.TABS_IDS.SETTINGS,
|
||||
title: t`Settings`,
|
||||
Icon: IconSettings,
|
||||
hide: false,
|
||||
},
|
||||
];
|
||||
|
||||
const renderActiveTabContent = () => {
|
||||
if (!role) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (activeTabId) {
|
||||
case SETTINGS_ROLE_DETAIL_TABS.TABS_IDS.ASSIGNMENT:
|
||||
return <RoleAssignment role={role} />;
|
||||
case SETTINGS_ROLE_DETAIL_TABS.TABS_IDS.PERMISSIONS:
|
||||
return <RolePermissions role={role} />;
|
||||
case SETTINGS_ROLE_DETAIL_TABS.TABS_IDS.SETTINGS:
|
||||
return <RoleSettings role={role} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
if (!isDefined(roleId)) {
|
||||
return <Navigate to="/settings/roles" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<SubMenuTopBarContainer
|
||||
title={role && <H3Title title={role.label} />}
|
||||
links={[
|
||||
{
|
||||
children: 'Workspace',
|
||||
href: getSettingsPath(SettingsPath.Workspace),
|
||||
},
|
||||
{
|
||||
children: 'Roles',
|
||||
href: getSettingsPath(SettingsPath.Roles),
|
||||
},
|
||||
{
|
||||
children: role?.label,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{!rolesLoading && role ? (
|
||||
<SettingsPageContainer>
|
||||
<TabList
|
||||
tabs={tabs}
|
||||
className="tab-list"
|
||||
componentInstanceId={
|
||||
SETTINGS_ROLE_DETAIL_TABS.COMPONENT_INSTANCE_ID
|
||||
}
|
||||
/>
|
||||
{renderActiveTabContent()}
|
||||
</SettingsPageContainer>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</SubMenuTopBarContainer>
|
||||
<>
|
||||
<SettingsRolesQueryEffect />
|
||||
<SettingsRoleEditEffect roleId={roleId} />
|
||||
<SettingsRole roleId={roleId} isCreateMode={false} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,39 +1,11 @@
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { Roles } from '@/settings/roles/components/Roles';
|
||||
import { RolesDefaultRole } from '@/settings/roles/components/RolesDefaultRole';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||
import { H3Title } from 'twenty-ui';
|
||||
import { useGetRolesQuery } from '~/generated/graphql';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
import { SettingsRolesContainer } from '@/settings/roles/components/SettingsRolesContainer';
|
||||
import { SettingsRolesQueryEffect } from '@/settings/roles/components/SettingsRolesQueryEffect';
|
||||
|
||||
export const SettingsRoles = () => {
|
||||
const { t } = useLingui();
|
||||
const { data: rolesData, loading: rolesLoading } = useGetRolesQuery({
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
|
||||
return (
|
||||
<SubMenuTopBarContainer
|
||||
title={rolesData && <H3Title title={t`Roles`} />}
|
||||
links={[
|
||||
{
|
||||
children: <Trans>Workspace</Trans>,
|
||||
href: getSettingsPath(SettingsPath.Workspace),
|
||||
},
|
||||
{ children: <Trans>Roles</Trans> },
|
||||
]}
|
||||
>
|
||||
<SettingsPageContainer>
|
||||
{!rolesLoading && rolesData && (
|
||||
<>
|
||||
<Roles roles={rolesData.getRoles ?? []} />
|
||||
<RolesDefaultRole roles={rolesData.getRoles ?? []} />
|
||||
</>
|
||||
)}
|
||||
</SettingsPageContainer>
|
||||
</SubMenuTopBarContainer>
|
||||
<>
|
||||
<SettingsRolesQueryEffect />
|
||||
<SettingsRolesContainer />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SettingsRoleCreate } from '../SettingsRoleCreate';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Roles/SettingsRoleCreate',
|
||||
component: SettingsRoleCreate,
|
||||
decorators: [PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/roles/create',
|
||||
},
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export type Story = StoryObj<typeof SettingsRoleCreate>;
|
||||
|
||||
export const Default: Story = {};
|
||||
@ -6,13 +6,18 @@ import {
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { GET_ROLES } from '@/settings/roles/graphql/queries/getRolesQuery';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { graphql, HttpResponse } from 'msw';
|
||||
import { SettingsRoles } from '../SettingsRoles';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Roles/SettingsRoles',
|
||||
component: SettingsRoles,
|
||||
decorators: [PageDecorator],
|
||||
args: { routePath: '/settings/roles' },
|
||||
args: {
|
||||
routePath: '/settings/roles',
|
||||
},
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
},
|
||||
@ -23,3 +28,19 @@ export default meta;
|
||||
export type Story = StoryObj<typeof SettingsRoles>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const NoRoles: Story = {
|
||||
parameters: {
|
||||
msw: {
|
||||
handlers: [
|
||||
graphql.query(getOperationName(GET_ROLES) ?? '', () => {
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
getRoles: [],
|
||||
},
|
||||
});
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user