Unverified Commit a49443cd authored by Lemon-miaow's avatar Lemon-miaow
Browse files

refactor(panel): simplify sidebar

parent b512a18d
Loading
Loading
Loading
Loading
+7 −6
Changes for panel/src/App.tsx: 7 added lines, 6 removed lines.
Original line number Diff line number Diff line
@@ -10,10 +10,8 @@ import { Dashboard } from "@/pages/Dashboard";
import { MyServers } from "@/pages/MyServers";
import { ServerConsole } from "@/pages/ServerConsole";
import { Account } from "@/pages/Account";
import { AdminHome } from "@/pages/admin/AdminHome";
import { ServerAdmin } from "@/pages/admin/ServerAdmin";
import { ImageAdmin } from "@/pages/admin/ImageAdmin";
import { OpsOverview } from "@/pages/ops/OpsOverview";
import { FleetTable } from "@/pages/ops/FleetTable";

// Three UX surfaces over two Zero-Trust tiers (DESIGN-WEB-3SIDES):
@@ -45,16 +43,19 @@ export default function App() {
              <Route path="servers/:name" element={<ServerConsole />} />
              <Route path="account" element={<Account />} />

              {/* Admin-Side — admin-tier (server & content ops) */}
              {/* Admin-Side — admin-tier (server & content ops).
                  /admin has no landing page; redirect to the first concrete view
                  so the section root and any stale bookmarks land somewhere useful. */}
              <Route path="admin" element={<RequireAdmin />}>
                <Route index element={<AdminHome />} />
                <Route index element={<Navigate to="/admin/servers" replace />} />
                <Route path="servers" element={<ServerAdmin />} />
                <Route path="images" element={<ImageAdmin />} />
              </Route>

              {/* SysAdmin-Side — admin-tier (platform observability) */}
              {/* SysAdmin-Side — admin-tier (platform observability).
                  Same redirect treatment as /admin — fleet is the meaningful view. */}
              <Route path="ops" element={<RequireAdmin />}>
                <Route index element={<OpsOverview />} />
                <Route index element={<Navigate to="/ops/fleet" replace />} />
                <Route path="fleet" element={<FleetTable />} />
              </Route>

+43 −28
Changes for panel/src/components/AppShell.tsx: 43 added lines, 28 removed lines.
Original line number Diff line number Diff line
@@ -5,10 +5,49 @@ import { useTranslation } from "react-i18next";
import * as SelectPrimitive from "@radix-ui/react-select";
import { cn } from "@/lib/utils";
import { useTier } from "@/lib/tier";
import { visibleSections } from "@/lib/nav";
import { visibleSections, type NavSection } from "@/lib/nav";
import { Select, SelectContent, SelectItem } from "@/components/ui/select";
import { useTheme } from "@/lib/theme";

function SectionGroup({ section, isFirst }: { section: NavSection; isFirst: boolean }) {
  const { t } = useTranslation("navigation");

  return (
    <div
      className={cn(
        "flex flex-col gap-0.5",
        // Sections after the first get a thin divider with breathing room above,
        // which reads as a structural break without needing a loud heading.
        !isFirst && "mt-3 border-t border-border/50 pt-3",
      )}
    >
      {section.titleKey && (
        <div className="mb-1 px-3 text-[11px] font-medium text-muted-foreground/70">
          {t(section.titleKey)}
        </div>
      )}
      {section.items.map((item) => (
        <NavLink
          key={item.to}
          to={item.to}
          end={item.end}
          className={({ isActive }) =>
            cn(
              "flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors",
              isActive
                ? "bg-primary/15 text-primary"
                : "text-muted-foreground hover:bg-accent hover:text-foreground",
            )
          }
        >
          <item.icon className="h-4 w-4" />
          {t(item.key)}
        </NavLink>
      ))}
    </div>
  );
}

function LangToggle() {
  const { i18n } = useTranslation();

@@ -67,33 +106,9 @@ export function AppShell() {
          <span className="text-lg font-semibold tracking-tight">{t("common:brand_name")}</span>
        </div>

        <nav className="flex flex-col gap-4">
          {sections.map((section) => (
            <div key={section.id} className="flex flex-col gap-1">
              {section.titleKey && (
                <div className="px-3 pb-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground/70">
                  {t(section.titleKey)}
                </div>
              )}
              {section.items.map((item) => (
                <NavLink
                  key={item.to}
                  to={item.to}
                  end={item.end}
                  className={({ isActive }) =>
                    cn(
                      "flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors",
                      isActive
                        ? "bg-primary/15 text-primary"
                        : "text-muted-foreground hover:bg-accent hover:text-foreground",
                    )
                  }
                >
                  <item.icon className="h-4 w-4" />
                  {t(item.key)}
                </NavLink>
              ))}
            </div>
        <nav className="flex flex-col">
          {sections.map((section, i) => (
            <SectionGroup key={section.id} section={section} isFirst={i === 0} />
          ))}
        </nav>

+0 −2
Changes for panel/src/i18n/resources/en-US/navigation.json: 0 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -3,10 +3,8 @@
  "my_servers": "My servers",
  "account": "Account",
  "admin_section": "Admin",
  "admin_overview": "Overview",
  "admin_servers": "Servers",
  "admin_images": "Images",
  "sysadmin_section": "SysAdmin",
  "sysadmin_overview": "Overview",
  "sysadmin_fleet": "Fleet"
}
+0 −2
Changes for panel/src/i18n/resources/zh-CN/navigation.json: 0 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -3,10 +3,8 @@
  "my_servers": "我的服务器",
  "account": "账户",
  "admin_section": "管理",
  "admin_overview": "概览",
  "admin_servers": "服务器",
  "admin_images": "镜像",
  "sysadmin_section": "系统管理",
  "sysadmin_overview": "概览",
  "sysadmin_fleet": "全平台服务器"
}
+1 −5
Changes for panel/src/lib/nav.ts: 1 added line, 5 removed lines.
Original line number Diff line number Diff line
@@ -2,10 +2,8 @@ import {
  LayoutDashboard,
  Server,
  UserRound,
  ShieldCheck,
  ServerCog,
  Boxes,
  Gauge,
  Network,
  type LucideIcon,
} from "lucide-react";
@@ -31,7 +29,7 @@ export interface NavItem {

export interface NavSection {
  id: "user" | "admin" | "ops";
  /** Section heading key; null renders no heading (User-Side). */
  /** Section heading key; null renders no heading (User-Side flat list). */
  titleKey: string | null;
  /** When true the section is shown only to admins (is_admin === true). */
  adminOnly: boolean;
@@ -54,7 +52,6 @@ export const NAV_SECTIONS: NavSection[] = [
    titleKey: "admin_section",
    adminOnly: true,
    items: [
      { to: "/admin", key: "admin_overview", icon: ShieldCheck, end: true },
      { to: "/admin/servers", key: "admin_servers", icon: ServerCog },
      { to: "/admin/images", key: "admin_images", icon: Boxes },
    ],
@@ -64,7 +61,6 @@ export const NAV_SECTIONS: NavSection[] = [
    titleKey: "sysadmin_section",
    adminOnly: true,
    items: [
      { to: "/ops", key: "sysadmin_overview", icon: Gauge, end: true },
      { to: "/ops/fleet", key: "sysadmin_fleet", icon: Network },
    ],
  },
Loading