mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-04 08:38:34 +00:00
feat: improve admin panel styles (#14318)
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 />} />
|
||||
|
||||
@@ -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'
|
||||
),
|
||||
})
|
||||
);
|
||||
}}
|
||||
|
||||
@@ -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} />}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user