feat: improve admin panel styles (#14318)

This commit is contained in:
DarkSky
2026-01-27 04:44:21 +08:00
committed by GitHub
parent 7d47cc52b6
commit 3b4b0bad22
6 changed files with 67 additions and 28 deletions

View File

@@ -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) {

View File

@@ -99,7 +99,13 @@ export const App = () => {
<Route path={ROUTES.admin.accounts} element={<Accounts />} />
<Route
path={ROUTES.admin.workspaces}
element={<Workspaces />}
element={
environment.isSelfHosted ? (
<Navigate to={ROUTES.admin.accounts} replace />
) : (
<Workspaces />
)
}
/>
<Route path={`${ROUTES.admin.queue}/*`} element={<Queue />} />
<Route path={ROUTES.admin.ai} element={<AI />} />

View File

@@ -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 (
<div className="w-full flex">
<NavLink
@@ -25,7 +28,11 @@ export const NormalSubItem = ({
return cn(
buttonVariants({
variant: 'ghost',
className: `ml-8 px-2 w-full justify-start ${isActive ? 'bg-zinc-100' : ''}`,
className: cn(
indentClassName,
'px-2 w-full justify-start',
isActive && 'bg-zinc-100'
),
})
);
}}

View File

@@ -91,12 +91,14 @@ export function Nav({ isCollapsed = false }: NavProps) {
label="Accounts"
isCollapsed={isCollapsed}
/>
{environment.isSelfHosted ? null : (
<NavItem
to="/admin/workspaces"
icon={<LayoutDashboardIcon size={18} />}
label="Workspaces"
isCollapsed={isCollapsed}
/>
)}
<NavItem
to="/admin/queue"
icon={<ListChecksIcon size={18} />}

View File

@@ -76,6 +76,11 @@ export const SettingsItem = ({ isCollapsed }: { isCollapsed: boolean }) => {
</NavLink>
</li>
))}
{UNKNOWN_CONFIG_GROUPS.length ? (
<li className="flex px-2 pt-1 pb-0.5 text-xs font-medium opacity-70">
Experimental
</li>
) : null}
{UNKNOWN_CONFIG_GROUPS.map(group => (
<li key={group.module} className="flex">
<NavLink
@@ -84,7 +89,7 @@ export const SettingsItem = ({ isCollapsed }: { isCollapsed: boolean }) => {
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,6 +159,7 @@ export const SettingsItem = ({ isCollapsed }: { isCollapsed: boolean }) => {
changeModule={setCurrentModule}
/>
))}
{UNKNOWN_CONFIG_GROUPS.length ? (
<Accordion type="multiple" className="w-full">
<AccordionItem value="item-1" className="border-b-0">
<AccordionTrigger className="ml-8 py-2 px-2 rounded [&[data-state=closed]>svg]:rotate-270 [&[data-state=open]>svg]:rotate-360">
@@ -166,11 +172,13 @@ export const SettingsItem = ({ isCollapsed }: { isCollapsed: boolean }) => {
module={group.module}
title={group.name}
changeModule={setCurrentModule}
indent="nested"
/>
))}
</AccordionContent>
</AccordionItem>
</Accordion>
) : null}
</ScrollAreaPrimitive.Viewport>
<ScrollAreaPrimitive.ScrollAreaScrollbar
className={cn(

View File

@@ -37,7 +37,13 @@ type ConfigGroup<T extends AppConfigModule> = {
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(