Skip to content

Commit

Permalink
feat(admin): add server runtime config settings
Browse files Browse the repository at this point in the history
  • Loading branch information
JimmFly committed Aug 8, 2024
1 parent 097091b commit 9bbc8cd
Show file tree
Hide file tree
Showing 17 changed files with 762 additions and 223 deletions.
4 changes: 4 additions & 0 deletions packages/frontend/admin/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ export const router = _createBrowserRouter(
path: '/admin/config',
lazy: () => import('./modules/config'),
},
{
path: '/admin/settings',
lazy: () => import('./modules/settings'),
},
],
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function CreateUserPanel() {

return (
<div className="flex flex-col h-full gap-1">
<div className="flex justify-between items-center py-[10px] px-6">
<div className="flex-grow-0 flex-shrink-0 h-[56px] flex justify-between items-center py-[10px] px-6">
<Button
type="button"
size="icon"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function DataTable<TData, TValue>({
}, [data]);

return (
<div className="space-y-4 py-5 px-6 h-full">
<div className="flex flex-col gap-4 py-5 px-6 h-full">
<DataTableToolbar setDataTable={setTableData} data={data} />
<ScrollArea className="rounded-md border max-h-[75vh] h-full">
<Table>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function EditPanel({

return (
<div className="flex flex-col h-full gap-1">
<div className="flex justify-between items-center py-[10px] px-6">
<div className="flex-grow-0 flex-shrink-0 h-[56px] flex justify-between items-center py-[10px] px-6 ">
<Button
type="button"
size="icon"
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/admin/src/modules/accounts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export function AccountPage() {
});

return (
<div className=" h-screen flex-1 space-y-1 flex-col flex">
<div className="flex items-center justify-between px-6 py-3 max-md:ml-9">
<div className=" h-screen flex-1 flex-col flex">
<div className="flex items-center justify-between px-6 py-3 max-md:ml-9 max-md:mt-[2px]">
<div className="text-base font-medium">Accounts</div>
</div>
<Separator />
Expand Down
102 changes: 38 additions & 64 deletions packages/frontend/admin/src/modules/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,13 @@ import {
import { Separator } from '@affine/admin/components/ui/separator';
import { TooltipProvider } from '@affine/admin/components/ui/tooltip';
import { cn } from '@affine/admin/utils';
import {
AlignJustifyIcon,
ClipboardList,
Cpu,
Settings,
Users,
} from 'lucide-react';
import { AlignJustifyIcon } from 'lucide-react';
import type { ReactNode, RefObject } from 'react';
import {
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
Expand All @@ -35,7 +28,7 @@ import {
SheetTrigger,
} from '../components/ui/sheet';
import { Logo } from './accounts/components/logo';
import type { NavProp } from './nav/nav';
import { NavContext } from './nav/context';
import { Nav } from './nav/nav';

interface LayoutProps {
Expand All @@ -50,33 +43,11 @@ interface RightPanelContextType {
openPanel: () => void;
closePanel: () => void;
}

const RightPanelContext = createContext<RightPanelContextType | undefined>(
undefined
);

const navLinks: NavProp[] = [
{
title: 'Accounts',
icon: Users,
to: '/admin/accounts',
},
{
title: 'AI',
icon: Cpu,
to: '/admin/ai',
},
{
title: 'Config',
icon: ClipboardList,
to: '/admin/config',
},
{
title: 'Settings',
icon: Settings,
to: '/admin/settings',
},
];

export const useRightPanel = () => {
const context = useContext(RightPanelContext);

Expand Down Expand Up @@ -110,6 +81,10 @@ export function Layout({ content }: LayoutProps) {
const [open, setOpen] = useState(false);
const rightPanelRef = useRef<ImperativePanelHandle>(null);

const [activeTab, setActiveTab] = useState('Accounts');
const [activeSubTab, setActiveSubTab] = useState('auth');
const [currentModule, setCurrentModule] = useState('auth');

const handleExpand = useCallback(() => {
if (rightPanelRef.current?.getSize() === 0) {
rightPanelRef.current?.resize(30);
Expand Down Expand Up @@ -139,15 +114,6 @@ export function Layout({ content }: LayoutProps) {
[closePanel, openPanel]
);

const activeTab = useMemo(() => {
const path = window.location.pathname;

return (
navLinks.find(link => path.endsWith(link.title.toLocaleLowerCase()))
?.title || ''
);
}, []);

return (
<RightPanelContext.Provider
value={{
Expand All @@ -159,37 +125,45 @@ export function Layout({ content }: LayoutProps) {
closePanel,
}}
>
<TooltipProvider delayDuration={0}>
<div className="flex">
<LeftPanel activeTab={activeTab} />
<ResizablePanelGroup direction="horizontal">
<ResizablePanel id="0" order={0} minSize={50}>
{content}
</ResizablePanel>
<RightPanel
rightPanelRef={rightPanelRef}
onExpand={handleExpand}
onCollapse={handleCollapse}
/>
</ResizablePanelGroup>
</div>
</TooltipProvider>
<NavContext.Provider
value={{
activeTab,
activeSubTab,
currentModule,
setActiveTab,
setActiveSubTab,
setCurrentModule,
}}
>
<TooltipProvider delayDuration={0}>
<div className="flex">
<LeftPanel />
<ResizablePanelGroup direction="horizontal">
<ResizablePanel id="0" order={0} minSize={50}>
{content}
</ResizablePanel>
<RightPanel
rightPanelRef={rightPanelRef}
onExpand={handleExpand}
onCollapse={handleCollapse}
/>
</ResizablePanelGroup>
</div>
</TooltipProvider>
</NavContext.Provider>
</RightPanelContext.Provider>
);
}

export const LeftPanel = ({ activeTab }: { activeTab: string }) => {
export const LeftPanel = () => {
const isSmallScreen = useMediaQuery('(max-width: 768px)');

if (isSmallScreen) {
return (
<Sheet>
<SheetTrigger asChild>
<Button
variant="ghost"
className="fixed top-[14px] left-6 p-0 h-5 w-5"
>
<AlignJustifyIcon />
<Button variant="ghost" className="fixed top-4 left-6 p-0 h-5 w-5">
<AlignJustifyIcon size={20} />
</Button>
</SheetTrigger>
<SheetHeader className="hidden">
Expand All @@ -209,7 +183,7 @@ export const LeftPanel = ({ activeTab }: { activeTab: string }) => {
AFFiNE
</div>
<Separator />
<Nav links={navLinks} activeTab={activeTab} />
<Nav />
</div>
</SheetContent>
</Sheet>
Expand All @@ -227,7 +201,7 @@ export const LeftPanel = ({ activeTab }: { activeTab: string }) => {
AFFiNE
</div>
<Separator />
<Nav links={navLinks} activeTab={activeTab} />
<Nav />
</div>
);
};
Expand Down
67 changes: 67 additions & 0 deletions packages/frontend/admin/src/modules/nav/collapsible-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from '@affine/admin/components/ui/accordion';
import { useCallback } from 'react';
import { Link } from 'react-router-dom';

import { useNav } from './context';

export const CollapsibleItem = ({
items,
title,
changeModule,
}: {
title: string;
items: string[];
changeModule?: (module: string) => void;
}) => {
const { activeSubTab, setActiveSubTab } = useNav();
const handleClick = useCallback(
(id: string) => {
const targetElement = document.getElementById(id);
if (targetElement) {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
}
changeModule?.(title);
setActiveSubTab(id);
},
[changeModule, setActiveSubTab, title]
);

return (
<Accordion type="multiple" className="w-full ">
<AccordionItem value="item-1" className="border-b-0">
<Link to={`/admin/settings#${title}`}>
<AccordionTrigger
onClick={() => handleClick(title)}
className={`py-2 px-3 rounded ${activeSubTab === title ? 'bg-zinc-100' : ''}`}
>
{title}
</AccordionTrigger>
</Link>
<AccordionContent className=" flex flex-col gap-2">
{items.map((item, index) => (
<Link
key={index}
to={`/admin/settings#${item}`}
className="px-3 overflow-hidden"
>
<AccordionContent
onClick={() => handleClick(item)}
className={`py-1 px-2 rounded text-ellipsis whitespace-nowrap overflow-hidden ${activeSubTab === item ? 'bg-zinc-100' : ''}`}
>
{item}
</AccordionContent>
</Link>
))}
</AccordionContent>
</AccordionItem>
</Accordion>
);
};
21 changes: 21 additions & 0 deletions packages/frontend/admin/src/modules/nav/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createContext, useContext } from 'react';

interface NavContextType {
activeTab: string;
activeSubTab: string;
currentModule: string;
setActiveTab: (tab: string) => void;
setActiveSubTab: (tab: string) => void;
setCurrentModule: (module: string) => void;
}

export const NavContext = createContext<NavContextType | undefined>(undefined);
export const useNav = () => {
const context = useContext(NavContext);

if (!context) {
throw new Error('useNav must be used within a NavProvider');
}

return context;
};
Loading

0 comments on commit 9bbc8cd

Please sign in to comment.