mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-18 10:36:22 +08:00
fix(admin): adjust admin panel settings style (#11291)
Adjusted the style of some runtime configurations to match the new parameters. Adjusted the style of dialog and right sidebar. close AF-2411 AF-2412 AF-2413 AF-2422
This commit is contained in:
@@ -7,6 +7,9 @@ import {
|
||||
import { useCallback } from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import { buttonVariants } from '../../components/ui/button';
|
||||
import { cn } from '../../utils';
|
||||
|
||||
export const CollapsibleItem = ({
|
||||
title,
|
||||
changeModule,
|
||||
@@ -14,22 +17,12 @@ export const CollapsibleItem = ({
|
||||
title: string;
|
||||
changeModule?: (module: string) => void;
|
||||
}) => {
|
||||
const handleClick = useCallback(
|
||||
(id: string) => {
|
||||
const targetElement = document.getElementById(id);
|
||||
if (targetElement) {
|
||||
targetElement.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center',
|
||||
});
|
||||
}
|
||||
changeModule?.(title);
|
||||
},
|
||||
[changeModule, title]
|
||||
);
|
||||
const handleClick = useCallback(() => {
|
||||
changeModule?.(title);
|
||||
}, [changeModule, title]);
|
||||
return (
|
||||
<Accordion type="multiple" className="w-full ">
|
||||
<AccordionItem value="item-1" className="border-b-0 ml-7 ">
|
||||
<Accordion type="multiple" className="w-full">
|
||||
<AccordionItem value="item-1" className="border-b-0 ml-7">
|
||||
<NavLink
|
||||
to={`/admin/settings/${title}`}
|
||||
className={({ isActive }) => {
|
||||
@@ -39,7 +32,7 @@ export const CollapsibleItem = ({
|
||||
}}
|
||||
>
|
||||
<AccordionTrigger
|
||||
onClick={() => handleClick(title)}
|
||||
onClick={handleClick}
|
||||
className="py-2 px-2 rounded [&[data-state=closed]>svg]:rotate-270 [&[data-state=open]>svg]:rotate-360"
|
||||
>
|
||||
{title}
|
||||
@@ -50,6 +43,36 @@ export const CollapsibleItem = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const NormalSubItem = ({
|
||||
title,
|
||||
changeModule,
|
||||
}: {
|
||||
title: string;
|
||||
changeModule?: (module: string) => void;
|
||||
}) => {
|
||||
const handleClick = useCallback(() => {
|
||||
changeModule?.(title);
|
||||
}, [changeModule, title]);
|
||||
return (
|
||||
<div className="w-full flex">
|
||||
<NavLink
|
||||
to={`/admin/settings/${title}`}
|
||||
onClick={handleClick}
|
||||
className={({ isActive }) => {
|
||||
return cn(
|
||||
buttonVariants({
|
||||
variant: 'ghost',
|
||||
className: `ml-8 px-2 w-full justify-start ${isActive ? 'bg-zinc-100' : ''}`,
|
||||
})
|
||||
);
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</NavLink>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const OtherModules = ({
|
||||
moduleList,
|
||||
changeModule,
|
||||
@@ -58,14 +81,14 @@ export const OtherModules = ({
|
||||
changeModule?: (module: string) => void;
|
||||
}) => {
|
||||
return (
|
||||
<Accordion type="multiple" className="w-full ">
|
||||
<Accordion type="multiple" className="w-full">
|
||||
<AccordionItem value="item-1" className="border-b-0">
|
||||
<AccordionTrigger className="ml-7 py-2 px-2 rounded [&[data-state=closed]>svg]:rotate-270 [&[data-state=open]>svg]:rotate-360">
|
||||
<AccordionTrigger className="ml-8 py-2 px-2 rounded [&[data-state=closed]>svg]:rotate-270 [&[data-state=open]>svg]:rotate-360">
|
||||
Other
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="flex flex-col gap-2 py-1">
|
||||
<AccordionContent className="flex flex-col gap-1 py-1">
|
||||
{moduleList.map(module => (
|
||||
<CollapsibleItem
|
||||
<NormalSubItem
|
||||
key={module}
|
||||
title={module}
|
||||
changeModule={changeModule}
|
||||
|
||||
@@ -33,12 +33,15 @@ export const ServerVersion = () => {
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className="flex items-center justify-between pt-2 border-t px-2 text-xs"
|
||||
className="inline-flex items-center justify-between pt-2 border-t px-2 text-xs flex-nowrap gap-1"
|
||||
style={{
|
||||
color: cssVarV2('text/tertiary'),
|
||||
}}
|
||||
>
|
||||
ServerVersion<span>v{version}</span>
|
||||
<span>ServerVersion</span>
|
||||
<span className="overflow-hidden text-ellipsis" title={version}>
|
||||
v{version}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import { ALL_CONFIGURABLE_MODULES } from '../settings/config';
|
||||
import { CollapsibleItem, OtherModules } from './collapsible-item';
|
||||
import { NormalSubItem, OtherModules } from './collapsible-item';
|
||||
import { useNav } from './context';
|
||||
|
||||
const authModule = ALL_CONFIGURABLE_MODULES.find(module => module === 'auth');
|
||||
@@ -53,13 +53,35 @@ export const SettingsItem = ({ isCollapsed }: { isCollapsed: boolean }) => {
|
||||
</NavigationMenuPrimitive.Trigger>
|
||||
<NavigationMenuPrimitive.Content>
|
||||
<ul
|
||||
className="border rounded-lg w-full flex flex-col p-1"
|
||||
className="border rounded-lg w-full flex flex-col p-1 min-w-[160px] max-h-[200px] overflow-y-auto"
|
||||
style={{
|
||||
backgroundColor: cssVarV2('layer/background/overlayPanel'),
|
||||
borderColor: cssVarV2('layer/insideBorder/blackBorder'),
|
||||
}}
|
||||
>
|
||||
{ALL_CONFIGURABLE_MODULES.map(module => (
|
||||
{authModule ? (
|
||||
<li key={authModule} className="flex">
|
||||
<NavLink
|
||||
to={`/admin/settings/${authModule}`}
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
variant: 'ghost',
|
||||
className:
|
||||
'p-2 rounded-[6px] text-[14px] w-full justify-start font-normal',
|
||||
})
|
||||
)}
|
||||
style={({ isActive }) => ({
|
||||
backgroundColor: isActive
|
||||
? cssVarV2('selfhost/button/sidebarButton/bg/select')
|
||||
: undefined,
|
||||
})}
|
||||
onClick={() => setCurrentModule?.(authModule)}
|
||||
>
|
||||
{authModule}
|
||||
</NavLink>
|
||||
</li>
|
||||
) : null}
|
||||
{otherModules.map(module => (
|
||||
<li key={module} className="flex">
|
||||
<NavLink
|
||||
to={`/admin/settings/${module}`}
|
||||
@@ -67,7 +89,7 @@ export const SettingsItem = ({ isCollapsed }: { isCollapsed: boolean }) => {
|
||||
buttonVariants({
|
||||
variant: 'ghost',
|
||||
className:
|
||||
'p-1.5 rounded-[6px] text-[14px] w-full justify-start',
|
||||
'p-2 rounded-[6px] text-[14px] w-full justify-start font-normal',
|
||||
})
|
||||
)}
|
||||
style={({ isActive }) => ({
|
||||
@@ -91,7 +113,7 @@ export const SettingsItem = ({ isCollapsed }: { isCollapsed: boolean }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Accordion type="multiple" className="w-full h-full overflow-hidden">
|
||||
<Accordion type="multiple" className="w-full overflow-hidden">
|
||||
<AccordionItem
|
||||
value="item-1"
|
||||
className="border-b-0 h-full flex flex-col gap-1 w-full"
|
||||
@@ -130,7 +152,7 @@ export const SettingsItem = ({ isCollapsed }: { isCollapsed: boolean }) => {
|
||||
>
|
||||
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit] [&>div]:!block">
|
||||
{authModule && (
|
||||
<CollapsibleItem
|
||||
<NormalSubItem
|
||||
title={authModule}
|
||||
changeModule={setCurrentModule}
|
||||
/>
|
||||
|
||||
@@ -24,6 +24,40 @@ interface UserDropdownProps {
|
||||
isCollapsed: boolean;
|
||||
}
|
||||
|
||||
const UserInfo = ({
|
||||
name,
|
||||
email,
|
||||
avatarUrl,
|
||||
}: {
|
||||
email: string;
|
||||
avatarUrl: string | null;
|
||||
name?: string;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<Avatar className="w-8 h-8">
|
||||
<AvatarImage src={avatarUrl ?? undefined} />
|
||||
<AvatarFallback>
|
||||
<CircleUser size={32} />
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex flex-col font-medium gap-1">
|
||||
{name ?? email.split('@')[0]}
|
||||
<span
|
||||
className="w-fit rounded px-2 py-0.5 text-xs h-5 border text-center inline-flex items-center font-normal"
|
||||
style={{
|
||||
borderRadius: '4px',
|
||||
backgroundColor: cssVarV2('chip/label/blue'),
|
||||
borderColor: cssVarV2('layer/insideBorder/border'),
|
||||
}}
|
||||
>
|
||||
Admin
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export function UserDropdown({ isCollapsed }: UserDropdownProps) {
|
||||
const currentUser = useCurrentUser();
|
||||
const relative = useRevalidateCurrentUser();
|
||||
@@ -53,7 +87,15 @@ export function UserDropdown({ isCollapsed }: UserDropdownProps) {
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" side="right">
|
||||
<DropdownMenuLabel>{currentUser?.name}</DropdownMenuLabel>
|
||||
<DropdownMenuLabel className="flex items-center gap-2">
|
||||
{currentUser ? (
|
||||
<UserInfo
|
||||
email={currentUser.email}
|
||||
name={currentUser.name}
|
||||
avatarUrl={currentUser.avatarUrl}
|
||||
/>
|
||||
) : null}
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onSelect={handleLogout}>Logout</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
@@ -104,25 +146,13 @@ export function UserDropdown({ isCollapsed }: UserDropdownProps) {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" side="right">
|
||||
<DropdownMenuLabel className="flex items-center gap-2">
|
||||
<Avatar className="w-8 h-8">
|
||||
<AvatarImage src={currentUser?.avatarUrl ?? undefined} />
|
||||
<AvatarFallback>
|
||||
<CircleUser size={32} />
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex flex-col font-medium gap-1">
|
||||
{currentUser?.name ?? currentUser?.email.split('@')[0]}
|
||||
<span
|
||||
className="w-fit rounded px-2 py-0.5 text-xs h-5 border text-center inline-flex items-center font-normal"
|
||||
style={{
|
||||
borderRadius: '4px',
|
||||
backgroundColor: cssVarV2('chip/label/blue'),
|
||||
borderColor: cssVarV2('layer/insideBorder/border'),
|
||||
}}
|
||||
>
|
||||
Admin
|
||||
</span>
|
||||
</div>
|
||||
{currentUser ? (
|
||||
<UserInfo
|
||||
email={currentUser.email}
|
||||
name={currentUser.name}
|
||||
avatarUrl={currentUser.avatarUrl}
|
||||
/>
|
||||
) : null}
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onSelect={handleLogout}>Logout</DropdownMenuItem>
|
||||
|
||||
Reference in New Issue
Block a user