diff --git a/packages/backend/server/src/core/workspaces/resolvers/admin.ts b/packages/backend/server/src/core/workspaces/resolvers/admin.ts index d6ae1ed0f..338e6d322 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/admin.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/admin.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { Args, Field, @@ -189,6 +189,12 @@ class AdminUpdateWorkspaceInput extends PartialType( export class AdminWorkspaceResolver { constructor(private readonly models: Models) {} + private assertCloudOnly() { + if (env.selfhosted) { + throw new NotFoundException(); + } + } + @Query(() => [AdminWorkspace], { description: 'List workspaces for admin', }) @@ -196,6 +202,7 @@ export class AdminWorkspaceResolver { @Args('filter', { type: () => ListWorkspaceInput }) filter: ListWorkspaceInput ) { + this.assertCloudOnly(); const { rows } = await this.models.workspace.adminListWorkspaces({ first: filter.first, skip: filter.skip, @@ -219,6 +226,7 @@ export class AdminWorkspaceResolver { @Args('filter', { type: () => ListWorkspaceInput }) filter: ListWorkspaceInput ) { + this.assertCloudOnly(); const total = await this.models.workspace.adminCountWorkspaces({ keyword: filter.keyword, features: filter.features, @@ -238,6 +246,7 @@ export class AdminWorkspaceResolver { nullable: true, }) async adminWorkspace(@Args('id') id: string) { + this.assertCloudOnly(); const { rows } = await this.models.workspace.adminListWorkspaces({ first: 1, skip: 0, @@ -318,6 +327,7 @@ export class AdminWorkspaceResolver { @Args('input', { type: () => AdminUpdateWorkspaceInput }) input: AdminUpdateWorkspaceInput ) { + this.assertCloudOnly(); const { id, features, ...updates } = input; if (Object.keys(updates).length) { diff --git a/packages/frontend/admin/src/app.tsx b/packages/frontend/admin/src/app.tsx index 3089dfa35..5e7831ab4 100644 --- a/packages/frontend/admin/src/app.tsx +++ b/packages/frontend/admin/src/app.tsx @@ -99,7 +99,13 @@ export const App = () => { } /> } + element={ + environment.isSelfHosted ? ( + + ) : ( + + ) + } /> } /> } /> diff --git a/packages/frontend/admin/src/modules/nav/collapsible-item.tsx b/packages/frontend/admin/src/modules/nav/collapsible-item.tsx index f82f1fe95..292ea421f 100644 --- a/packages/frontend/admin/src/modules/nav/collapsible-item.tsx +++ b/packages/frontend/admin/src/modules/nav/collapsible-item.tsx @@ -8,14 +8,17 @@ export const NormalSubItem = ({ module, title, changeModule, + indent = 'normal', }: { module: string; title: string; changeModule?: (module: string) => void; + indent?: 'normal' | 'nested'; }) => { const handleClick = useCallback(() => { changeModule?.(module); }, [changeModule, module]); + const indentClassName = indent === 'nested' ? 'ml-12' : 'ml-8'; return (
- } - label="Workspaces" - isCollapsed={isCollapsed} - /> + {environment.isSelfHosted ? null : ( + } + label="Workspaces" + isCollapsed={isCollapsed} + /> + )} } diff --git a/packages/frontend/admin/src/modules/nav/settings-item.tsx b/packages/frontend/admin/src/modules/nav/settings-item.tsx index ed1b3482c..e2eaf9622 100644 --- a/packages/frontend/admin/src/modules/nav/settings-item.tsx +++ b/packages/frontend/admin/src/modules/nav/settings-item.tsx @@ -76,6 +76,11 @@ export const SettingsItem = ({ isCollapsed }: { isCollapsed: boolean }) => { ))} + {UNKNOWN_CONFIG_GROUPS.length ? ( +
  • + Experimental +
  • + ) : null} {UNKNOWN_CONFIG_GROUPS.map(group => (
  • { buttonVariants({ variant: 'ghost', className: - 'p-2 rounded-[6px] text-[14px] w-full justify-start font-normal', + 'p-2 pl-6 rounded-[6px] text-[14px] w-full justify-start font-normal', }) )} style={({ isActive }) => ({ @@ -154,23 +159,26 @@ export const SettingsItem = ({ isCollapsed }: { isCollapsed: boolean }) => { changeModule={setCurrentModule} /> ))} - - - - Experimental - - - {UNKNOWN_CONFIG_GROUPS.map(group => ( - - ))} - - - + {UNKNOWN_CONFIG_GROUPS.length ? ( + + + + Experimental + + + {UNKNOWN_CONFIG_GROUPS.map(group => ( + + ))} + + + + ) : null} = { const IGNORED_MODULES: (keyof AppConfig)[] = []; if (environment.isSelfHosted) { - IGNORED_MODULES.push('payment'); + IGNORED_MODULES.push( + 'payment', + 'customerIo', + 'captcha', + 'telemetry', + 'metrics' + ); } const ALL_CONFIGURABLE_MODULES = Object.keys(CONFIG_DESCRIPTORS).filter(