## Context A gap was introduced when we refactored the menu rendering as Logout menu item was handled differently in its own NavigationDrawer section which added the gap. To fix that we are moving the Logout to the menu rendering logic in useSettingsNavigationItems hook, allowing items to have onClick prop instead of a path. Before <img width="213" alt="Screenshot 2025-03-04 at 14 36 55" src="https://github.com/user-attachments/assets/23b63673-a9c4-47de-af71-7dda74469e9f" /> After <img width="225" alt="Screenshot 2025-03-04 at 14 36 38" src="https://github.com/user-attachments/assets/053c0c0d-8876-40b6-ae2c-b68124393f7f" />
210 lines
5.7 KiB
TypeScript
210 lines
5.7 KiB
TypeScript
import {
|
|
IconApps,
|
|
IconAt,
|
|
IconCalendarEvent,
|
|
IconCode,
|
|
IconColorSwatch,
|
|
IconComponent,
|
|
IconCurrencyDollar,
|
|
IconDoorEnter,
|
|
IconFlask,
|
|
IconFunction,
|
|
IconHierarchy2,
|
|
IconKey,
|
|
IconLock,
|
|
IconMail,
|
|
IconRocket,
|
|
IconServer,
|
|
IconSettings,
|
|
IconUserCircle,
|
|
IconUsers,
|
|
} from 'twenty-ui';
|
|
|
|
import { SettingsPath } from '@/types/SettingsPath';
|
|
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
|
import { SettingsPermissions } from '~/generated/graphql';
|
|
|
|
import { useAuth } from '@/auth/hooks/useAuth';
|
|
import { currentUserState } from '@/auth/states/currentUserState';
|
|
import { billingState } from '@/client-config/states/billingState';
|
|
import { labPublicFeatureFlagsState } from '@/client-config/states/labPublicFeatureFlagsState';
|
|
import { useSettingsPermissionMap } from '@/settings/roles/hooks/useSettingsPermissionMap';
|
|
import { NavigationDrawerItemIndentationLevel } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
|
|
import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap';
|
|
import { t } from '@lingui/core/macro';
|
|
import { useRecoilValue } from 'recoil';
|
|
|
|
export type SettingsNavigationSection = {
|
|
label: string;
|
|
items: SettingsNavigationItem[];
|
|
isAdvanced?: boolean;
|
|
};
|
|
|
|
export type SettingsNavigationItem = {
|
|
label: string;
|
|
path?: SettingsPath;
|
|
onClick?: () => void;
|
|
Icon: IconComponent;
|
|
indentationLevel?: NavigationDrawerItemIndentationLevel;
|
|
matchSubPages?: boolean;
|
|
isHidden?: boolean;
|
|
subItems?: SettingsNavigationItem[];
|
|
isAdvanced?: boolean;
|
|
soon?: boolean;
|
|
};
|
|
|
|
const useSettingsNavigationItems = (): SettingsNavigationSection[] => {
|
|
const billing = useRecoilValue(billingState);
|
|
|
|
const isFunctionSettingsEnabled = false;
|
|
const isBillingEnabled = billing?.isBillingEnabled ?? false;
|
|
const currentUser = useRecoilValue(currentUserState);
|
|
const isAdminEnabled =
|
|
(currentUser?.canImpersonate || currentUser?.canAccessFullAdminPanel) ??
|
|
false;
|
|
const labPublicFeatureFlags = useRecoilValue(labPublicFeatureFlagsState);
|
|
|
|
const featureFlags = useFeatureFlagsMap();
|
|
const permissionMap = useSettingsPermissionMap();
|
|
const { signOut } = useAuth();
|
|
return [
|
|
{
|
|
label: t`User`,
|
|
items: [
|
|
{
|
|
label: t`Profile`,
|
|
path: SettingsPath.ProfilePage,
|
|
Icon: IconUserCircle,
|
|
},
|
|
{
|
|
label: t`Experience`,
|
|
path: SettingsPath.Experience,
|
|
Icon: IconColorSwatch,
|
|
},
|
|
{
|
|
label: t`Accounts`,
|
|
path: SettingsPath.Accounts,
|
|
Icon: IconAt,
|
|
matchSubPages: false,
|
|
subItems: [
|
|
{
|
|
label: t`Emails`,
|
|
path: SettingsPath.AccountsEmails,
|
|
Icon: IconMail,
|
|
indentationLevel: 2,
|
|
},
|
|
{
|
|
label: t`Calendars`,
|
|
path: SettingsPath.AccountsCalendars,
|
|
Icon: IconCalendarEvent,
|
|
indentationLevel: 2,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: t`Workspace`,
|
|
items: [
|
|
{
|
|
label: t`General`,
|
|
path: SettingsPath.Workspace,
|
|
Icon: IconSettings,
|
|
isHidden: !permissionMap[SettingsPermissions.WORKSPACE],
|
|
},
|
|
{
|
|
label: t`Members`,
|
|
path: SettingsPath.WorkspaceMembersPage,
|
|
Icon: IconUsers,
|
|
isHidden: !permissionMap[SettingsPermissions.WORKSPACE_MEMBERS],
|
|
},
|
|
{
|
|
label: t`Billing`,
|
|
path: SettingsPath.Billing,
|
|
Icon: IconCurrencyDollar,
|
|
isHidden:
|
|
!isBillingEnabled || !permissionMap[SettingsPermissions.WORKSPACE],
|
|
},
|
|
{
|
|
label: t`Roles`,
|
|
path: SettingsPath.Roles,
|
|
Icon: IconLock,
|
|
isHidden:
|
|
!featureFlags[FeatureFlagKey.IsPermissionsEnabled] ||
|
|
!permissionMap[SettingsPermissions.ROLES],
|
|
},
|
|
{
|
|
label: t`Data model`,
|
|
path: SettingsPath.Objects,
|
|
Icon: IconHierarchy2,
|
|
isHidden: !permissionMap[SettingsPermissions.DATA_MODEL],
|
|
},
|
|
{
|
|
label: t`Integrations`,
|
|
path: SettingsPath.Integrations,
|
|
Icon: IconApps,
|
|
isHidden: !permissionMap[SettingsPermissions.API_KEYS_AND_WEBHOOKS],
|
|
},
|
|
{
|
|
label: t`Security`,
|
|
path: SettingsPath.Security,
|
|
Icon: IconKey,
|
|
isAdvanced: true,
|
|
isHidden: !permissionMap[SettingsPermissions.SECURITY],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: t`Developers`,
|
|
isAdvanced: true,
|
|
items: [
|
|
{
|
|
label: t`API & Webhooks`,
|
|
path: SettingsPath.Developers,
|
|
Icon: IconCode,
|
|
isAdvanced: true,
|
|
isHidden: !permissionMap[SettingsPermissions.API_KEYS_AND_WEBHOOKS],
|
|
},
|
|
{
|
|
label: t`Functions`,
|
|
path: SettingsPath.ServerlessFunctions,
|
|
Icon: IconFunction,
|
|
isHidden: !isFunctionSettingsEnabled,
|
|
isAdvanced: true,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: t`Other`,
|
|
items: [
|
|
{
|
|
label: t`Server Admin`,
|
|
path: SettingsPath.AdminPanel,
|
|
Icon: IconServer,
|
|
isHidden: !isAdminEnabled,
|
|
},
|
|
{
|
|
label: t`Lab`,
|
|
path: SettingsPath.Lab,
|
|
Icon: IconFlask,
|
|
isHidden:
|
|
!labPublicFeatureFlags.length ||
|
|
!permissionMap[SettingsPermissions.WORKSPACE],
|
|
},
|
|
{
|
|
label: t`Releases`,
|
|
path: SettingsPath.Releases,
|
|
Icon: IconRocket,
|
|
},
|
|
{
|
|
label: t`Logout`,
|
|
onClick: signOut,
|
|
Icon: IconDoorEnter,
|
|
},
|
|
],
|
|
},
|
|
];
|
|
};
|
|
|
|
export { useSettingsNavigationItems };
|