import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Navigate, Outlet, useLocation, useNavigate } from "react-router-dom"; import { CloudServerOutlined as CloudServerOutlinedIcon, GlobalOutlined as GlobalOutlinedIcon, HomeOutlined as HomeOutlinedIcon, LogoutOutlined as LogoutOutlinedIcon, MenuOutlined as MenuOutlinedIcon, MoonOutlined as MoonOutlinedIcon, NodeIndexOutlined as NodeIndexOutlinedIcon, SafetyOutlined as SafetyOutlinedIcon, SettingOutlined as SettingOutlinedIcon, SunOutlined as SunOutlinedIcon, } from "@ant-design/icons"; import { Alert, Button, type ButtonProps, Drawer, Dropdown, Layout, Menu, type MenuProps, Tooltip, theme } from "antd"; import Show from "@/components/Show"; import Version from "@/components/Version"; import { useBrowserTheme, useTriggerElement } from "@/hooks"; import { getAuthStore } from "@/repository/admin"; import { isBrowserHappy } from "@/utils/browser"; const ConsoleLayout = () => { const navigate = useNavigate(); const { t } = useTranslation(); const { token: themeToken } = theme.useToken(); const handleLogoutClick = () => { auth.clear(); navigate("/login"); }; const auth = getAuthStore(); if (!auth.isValid || !auth.isSuperuser) { return ; } return (
} size="large" />} />
); }; const SiderMenu = memo(({ onSelect }: { onSelect?: (key: string) => void }) => { const location = useLocation(); const navigate = useNavigate(); const { t } = useTranslation(); const MENU_KEY_HOME = "/"; const MENU_KEY_WORKFLOWS = "/workflows"; const MENU_KEY_CERTIFICATES = "/certificates"; const MENU_KEY_ACCESSES = "/accesses"; const MENU_KEY_SETTINGS = "/settings"; const menuItems: Required["items"] = [ [MENU_KEY_HOME, , t("dashboard.page.title")], [MENU_KEY_WORKFLOWS, , t("workflow.page.title")], [MENU_KEY_CERTIFICATES, , t("certificate.page.title")], [MENU_KEY_ACCESSES, , t("access.page.title")], [MENU_KEY_SETTINGS, , t("settings.page.title")], ].map(([key, icon, label]) => { return { key: key as string, icon: icon, label: label, onClick: () => { navigate(key as string); onSelect?.(key as string); }, }; }); const [menuSelectedKey, setMenuSelectedKey] = useState(); const getActiveMenuItem = () => { const item = menuItems.find((item) => item!.key === location.pathname) ?? menuItems.find((item) => item!.key !== MENU_KEY_HOME && location.pathname.startsWith(item!.key as string)); return item; }; useEffect(() => { const item = getActiveMenuItem(); if (item) { setMenuSelectedKey(item.key as string); } else { setMenuSelectedKey(undefined); } }, [location.pathname]); useEffect(() => { if (menuSelectedKey && menuSelectedKey !== getActiveMenuItem()?.key) { navigate(menuSelectedKey); } }, [menuSelectedKey]); return ( <>
Certimate
{ setMenuSelectedKey(key); }} />
); }); const SiderMenuDrawer = memo(({ trigger }: { trigger: React.ReactNode }) => { const { token: themeToken } = theme.useToken(); const [siderOpen, setSiderOpen] = useState(false); const triggerEl = useTriggerElement(trigger, { onClick: () => setSiderOpen(true) }); return ( <> {triggerEl} setSiderOpen(false)} > setSiderOpen(false)} /> ); }); const ThemeToggleButton = memo(({ size }: { size?: ButtonProps["size"] }) => { const { t } = useTranslation(); const { theme, themeMode, setThemeMode } = useBrowserTheme(); const items: Required["items"] = [ ["light", t("common.theme.light")], ["dark", t("common.theme.dark")], ["system", t("common.theme.system")], ].map(([key, label]) => { return { key: key as string, label: label, onClick: () => { setThemeMode(key as Parameters[0]); if (key !== themeMode) { window.location.reload(); } }, }; }); return (