OrganizationSettingsLayout.tsx238 lines · main
| 1 | import { useFlag, useParams } from 'common' |
| 2 | import { PropsWithChildren } from 'react' |
| 3 | |
| 4 | import { useIsPlatformWebhooksEnabled } from '@/components/interfaces/App/FeaturePreview/FeaturePreviewContext' |
| 5 | import type { SidebarSection } from '@/components/layouts/AccountLayout/AccountLayout.types' |
| 6 | import { WithSidebar } from '@/components/layouts/AccountLayout/WithSidebar' |
| 7 | import { useCurrentPath } from '@/hooks/misc/useCurrentPath' |
| 8 | import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled' |
| 9 | |
| 10 | interface OrganizationSettingsMenuItemsProps { |
| 11 | slug?: string |
| 12 | showSecuritySettings?: boolean |
| 13 | showSsoSettings?: boolean |
| 14 | showLegalDocuments?: boolean |
| 15 | showPlatformWebhooks?: boolean |
| 16 | showPrivateApps?: boolean |
| 17 | } |
| 18 | |
| 19 | interface OrganizationSettingsSectionsProps extends OrganizationSettingsMenuItemsProps { |
| 20 | currentPath: string |
| 21 | } |
| 22 | |
| 23 | export const normalizeOrganizationSettingsPath = (path: string) => path.split('#')[0] |
| 24 | |
| 25 | export const generateOrganizationSettingsMenuItems = ({ |
| 26 | slug, |
| 27 | showSecuritySettings = true, |
| 28 | showSsoSettings = true, |
| 29 | showLegalDocuments = true, |
| 30 | showPlatformWebhooks = true, |
| 31 | showPrivateApps: _showPrivateApps = false, |
| 32 | }: OrganizationSettingsMenuItemsProps) => [ |
| 33 | { |
| 34 | key: 'general', |
| 35 | label: 'General', |
| 36 | href: `/org/${slug}/general`, |
| 37 | }, |
| 38 | ...(showSecuritySettings |
| 39 | ? [ |
| 40 | { |
| 41 | key: 'security', |
| 42 | label: 'Security', |
| 43 | href: `/org/${slug}/security`, |
| 44 | }, |
| 45 | ] |
| 46 | : []), |
| 47 | { |
| 48 | key: 'apps', |
| 49 | label: 'OAuth Apps', |
| 50 | href: `/org/${slug}/apps`, |
| 51 | }, |
| 52 | ...(showSsoSettings |
| 53 | ? [ |
| 54 | { |
| 55 | key: 'sso', |
| 56 | label: 'SSO', |
| 57 | href: `/org/${slug}/sso`, |
| 58 | }, |
| 59 | ] |
| 60 | : []), |
| 61 | ...(showPlatformWebhooks |
| 62 | ? [ |
| 63 | { |
| 64 | key: 'webhooks', |
| 65 | label: 'Webhooks', |
| 66 | href: `/org/${slug}/webhooks`, |
| 67 | }, |
| 68 | ] |
| 69 | : []), |
| 70 | { |
| 71 | key: 'audit', |
| 72 | label: 'Audit Logs', |
| 73 | href: `/org/${slug}/audit`, |
| 74 | }, |
| 75 | ...(showLegalDocuments |
| 76 | ? [ |
| 77 | { |
| 78 | key: 'documents', |
| 79 | label: 'Legal Documents', |
| 80 | href: `/org/${slug}/documents`, |
| 81 | }, |
| 82 | ] |
| 83 | : []), |
| 84 | ] |
| 85 | |
| 86 | export const generateOrganizationSettingsSections = ({ |
| 87 | currentPath, |
| 88 | slug, |
| 89 | showSecuritySettings = true, |
| 90 | showSsoSettings = true, |
| 91 | showLegalDocuments = true, |
| 92 | showPlatformWebhooks = true, |
| 93 | showPrivateApps = false, |
| 94 | }: OrganizationSettingsSectionsProps): SidebarSection[] => { |
| 95 | const isLinkActive = (key: string, href: string) => |
| 96 | key === 'webhooks' |
| 97 | ? currentPath === href || currentPath.startsWith(`${href}/`) |
| 98 | : currentPath === href |
| 99 | |
| 100 | const configurationLinks = [ |
| 101 | { |
| 102 | key: 'general', |
| 103 | label: 'General', |
| 104 | href: `/org/${slug}/general`, |
| 105 | }, |
| 106 | ...(showSecuritySettings |
| 107 | ? [ |
| 108 | { |
| 109 | key: 'security', |
| 110 | label: 'Security', |
| 111 | href: `/org/${slug}/security`, |
| 112 | }, |
| 113 | ] |
| 114 | : []), |
| 115 | ...(showSsoSettings |
| 116 | ? [ |
| 117 | { |
| 118 | key: 'sso', |
| 119 | label: 'SSO', |
| 120 | href: `/org/${slug}/sso`, |
| 121 | }, |
| 122 | ] |
| 123 | : []), |
| 124 | ] |
| 125 | |
| 126 | const connectionsLinks = [ |
| 127 | { |
| 128 | key: 'apps', |
| 129 | label: 'OAuth Apps', |
| 130 | href: `/org/${slug}/apps`, |
| 131 | }, |
| 132 | ...(showPrivateApps |
| 133 | ? [ |
| 134 | { |
| 135 | key: 'private-apps', |
| 136 | label: 'Private Apps', |
| 137 | href: `/org/${slug}/private-apps`, |
| 138 | }, |
| 139 | ] |
| 140 | : []), |
| 141 | ...(showPlatformWebhooks |
| 142 | ? [ |
| 143 | { |
| 144 | key: 'webhooks', |
| 145 | label: 'Webhooks', |
| 146 | href: `/org/${slug}/webhooks`, |
| 147 | }, |
| 148 | ] |
| 149 | : []), |
| 150 | ] |
| 151 | |
| 152 | const complianceLinks = [ |
| 153 | { |
| 154 | key: 'audit', |
| 155 | label: 'Audit Logs', |
| 156 | href: `/org/${slug}/audit`, |
| 157 | }, |
| 158 | ...(showLegalDocuments |
| 159 | ? [ |
| 160 | { |
| 161 | key: 'documents', |
| 162 | label: 'Legal Documents', |
| 163 | href: `/org/${slug}/documents`, |
| 164 | }, |
| 165 | ] |
| 166 | : []), |
| 167 | ] |
| 168 | |
| 169 | return [ |
| 170 | { |
| 171 | key: 'configuration', |
| 172 | heading: 'Configuration', |
| 173 | links: configurationLinks.map((item) => ({ |
| 174 | ...item, |
| 175 | isActive: isLinkActive(item.key, item.href), |
| 176 | })), |
| 177 | }, |
| 178 | { |
| 179 | key: 'connections', |
| 180 | heading: 'Connections', |
| 181 | links: connectionsLinks.map((item) => ({ |
| 182 | ...item, |
| 183 | isActive: isLinkActive(item.key, item.href), |
| 184 | })), |
| 185 | }, |
| 186 | { |
| 187 | key: 'compliance', |
| 188 | heading: 'Compliance', |
| 189 | links: complianceLinks.map((item) => ({ |
| 190 | ...item, |
| 191 | isActive: isLinkActive(item.key, item.href), |
| 192 | })), |
| 193 | }, |
| 194 | ] |
| 195 | } |
| 196 | |
| 197 | export function OrganizationSettingsLayout({ children }: PropsWithChildren) { |
| 198 | const { slug } = useParams() |
| 199 | const showPlatformWebhooks = useIsPlatformWebhooksEnabled() |
| 200 | const showPrivateApps = useFlag('privateApps') |
| 201 | const fullCurrentPath = useCurrentPath() |
| 202 | const currentPath = normalizeOrganizationSettingsPath(fullCurrentPath) |
| 203 | |
| 204 | const { |
| 205 | organizationShowSsoSettings: showSsoSettings, |
| 206 | organizationShowSecuritySettings: showSecuritySettings, |
| 207 | organizationShowLegalDocuments: showLegalDocuments, |
| 208 | } = useIsFeatureEnabled([ |
| 209 | 'organization:show_sso_settings', |
| 210 | 'organization:show_security_settings', |
| 211 | 'organization:show_legal_documents', |
| 212 | ]) |
| 213 | |
| 214 | const sections = generateOrganizationSettingsSections({ |
| 215 | currentPath, |
| 216 | slug, |
| 217 | showSecuritySettings, |
| 218 | showSsoSettings, |
| 219 | showLegalDocuments, |
| 220 | showPlatformWebhooks, |
| 221 | showPrivateApps, |
| 222 | }) |
| 223 | |
| 224 | // Browser titles for org settings routes are set by OrganizationLayout. |
| 225 | return ( |
| 226 | <WithSidebar |
| 227 | title="Organization Settings" |
| 228 | sections={sections} |
| 229 | header={ |
| 230 | <div className="border-default flex min-h-(--header-height) items-center border-b px-6"> |
| 231 | <h4 className="text-lg">Settings</h4> |
| 232 | </div> |
| 233 | } |
| 234 | > |
| 235 | {children} |
| 236 | </WithSidebar> |
| 237 | ) |
| 238 | } |