mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-12 23:01:41 +00:00
feat(ui): migrate the self-contained leaf pages to App Router path routing
Bulk Wave B cutover for the 20 leaf pages whose only dependency is the auth context (budgets, caching, cost-tracking, guardrails, guardrails-monitor, logs, mcp-servers, memory, policies, projects, prompts, search-tools, skills, tag-management, tool-policies, api-playground/transform-request, ui-theme, vector-stores, workflows, access-groups). Each gets a thin (dashboard)/<segment>/page.tsx that sources its data from useAuthorized and renders the existing component; the legacy switch arm and import are removed from page.tsx, and a map entry is added to MIGRATED_PAGES (skills and claude-code-plugins both map to /ui/skills). A data-driven test pins every forward mapping and reverse lookup.
This commit is contained in:
parent
69a7bdb247
commit
ef8fa82136
23 changed files with 257 additions and 72 deletions
|
|
@ -0,0 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { AccessGroupsPage } from "@/components/AccessGroups/AccessGroupsPage";
|
||||
|
||||
export default function AccessGroupsRoute() {
|
||||
return <AccessGroupsPage />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import BudgetPanel from "@/components/budgets/budget_panel";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function BudgetsRoute() {
|
||||
const { accessToken } = useAuthorized();
|
||||
return <BudgetPanel accessToken={accessToken} />;
|
||||
}
|
||||
17
ui/litellm-dashboard/src/app/(dashboard)/caching/page.tsx
Normal file
17
ui/litellm-dashboard/src/app/(dashboard)/caching/page.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
"use client";
|
||||
|
||||
import CacheDashboard from "@/components/cache_dashboard";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function CachingRoute() {
|
||||
const { accessToken, userId, userRole, token, premiumUser } = useAuthorized();
|
||||
return (
|
||||
<CacheDashboard
|
||||
userID={userId}
|
||||
userRole={userRole}
|
||||
token={token}
|
||||
accessToken={accessToken}
|
||||
premiumUser={premiumUser}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import { CostTrackingSettings } from "@/components/CostTrackingSettings";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function CostTrackingRoute() {
|
||||
const { accessToken, userId, userRole } = useAuthorized();
|
||||
return <CostTrackingSettings userID={userId} userRole={userRole} accessToken={accessToken} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import GuardrailsMonitorView from "@/components/GuardrailsMonitor/GuardrailsMonitorView";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function GuardrailsMonitorRoute() {
|
||||
const { accessToken } = useAuthorized();
|
||||
return <GuardrailsMonitorView accessToken={accessToken} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import GuardrailsPanel from "@/components/guardrails";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function GuardrailsRoute() {
|
||||
const { accessToken, userRole } = useAuthorized();
|
||||
return <GuardrailsPanel accessToken={accessToken} userRole={userRole} />;
|
||||
}
|
||||
17
ui/litellm-dashboard/src/app/(dashboard)/logs/page.tsx
Normal file
17
ui/litellm-dashboard/src/app/(dashboard)/logs/page.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
"use client";
|
||||
|
||||
import SpendLogsTable from "@/components/view_logs";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function LogsRoute() {
|
||||
const { accessToken, userId, userRole, token, premiumUser } = useAuthorized();
|
||||
return (
|
||||
<SpendLogsTable
|
||||
userID={userId}
|
||||
userRole={userRole}
|
||||
token={token}
|
||||
accessToken={accessToken}
|
||||
premiumUser={premiumUser}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import { MCPServers } from "@/components/mcp_tools";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function McpServersRoute() {
|
||||
const { accessToken, userId, userRole } = useAuthorized();
|
||||
return <MCPServers accessToken={accessToken} userRole={userRole} userID={userId} />;
|
||||
}
|
||||
9
ui/litellm-dashboard/src/app/(dashboard)/memory/page.tsx
Normal file
9
ui/litellm-dashboard/src/app/(dashboard)/memory/page.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import { MemoryView } from "@/components/MemoryView";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function MemoryRoute() {
|
||||
const { accessToken, userId, userRole } = useAuthorized();
|
||||
return <MemoryView accessToken={accessToken} userID={userId} userRole={userRole} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import PoliciesPanel from "@/components/policies";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function PoliciesRoute() {
|
||||
const { accessToken, userRole } = useAuthorized();
|
||||
return <PoliciesPanel accessToken={accessToken} userRole={userRole} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { ProjectsPage } from "@/components/Projects/ProjectsPage";
|
||||
|
||||
export default function ProjectsRoute() {
|
||||
return <ProjectsPage />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import PromptsPanel from "@/components/prompts";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function PromptsRoute() {
|
||||
const { accessToken, userRole } = useAuthorized();
|
||||
return <PromptsPanel accessToken={accessToken} userRole={userRole} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import { SearchTools } from "@/components/SearchTools";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function SearchToolsRoute() {
|
||||
const { accessToken, userId, userRole } = useAuthorized();
|
||||
return <SearchTools accessToken={accessToken} userRole={userRole} userID={userId} />;
|
||||
}
|
||||
9
ui/litellm-dashboard/src/app/(dashboard)/skills/page.tsx
Normal file
9
ui/litellm-dashboard/src/app/(dashboard)/skills/page.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import ClaudeCodePluginsPanel from "@/components/claude_code_plugins";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function SkillsRoute() {
|
||||
const { accessToken, userRole } = useAuthorized();
|
||||
return <ClaudeCodePluginsPanel accessToken={accessToken} userRole={userRole} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import TagManagement from "@/components/tag_management";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function TagManagementRoute() {
|
||||
const { accessToken, userId, userRole } = useAuthorized();
|
||||
return <TagManagement accessToken={accessToken} userRole={userRole} userID={userId} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import ToolPoliciesView from "@/components/ToolPoliciesView";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function ToolPoliciesRoute() {
|
||||
const { accessToken, userRole } = useAuthorized();
|
||||
return <ToolPoliciesView accessToken={accessToken} userRole={userRole} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import TransformRequestPanel from "@/components/transform_request";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function TransformRequestRoute() {
|
||||
const { accessToken } = useAuthorized();
|
||||
return <TransformRequestPanel accessToken={accessToken} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import UIThemeSettings from "@/components/ui_theme_settings";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function UiThemeRoute() {
|
||||
const { accessToken, userId, userRole } = useAuthorized();
|
||||
return <UIThemeSettings userID={userId} userRole={userRole} accessToken={accessToken} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import VectorStoreManagement from "@/components/vector_store_management";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function VectorStoresRoute() {
|
||||
const { accessToken, userId, userRole } = useAuthorized();
|
||||
return <VectorStoreManagement accessToken={accessToken} userRole={userRole} userID={userId} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import WorkflowRuns from "@/components/workflow_runs";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
export default function WorkflowsRoute() {
|
||||
const { accessToken } = useAuthorized();
|
||||
return <WorkflowRuns accessToken={accessToken} />;
|
||||
}
|
||||
|
|
@ -5,18 +5,10 @@ import OldModelDashboard from "@/app/(dashboard)/models-and-endpoints/ModelsAndE
|
|||
import PlaygroundPage from "@/app/(dashboard)/playground/page";
|
||||
import AdminPanel from "@/components/AdminPanel";
|
||||
import AgentsPanel from "@/components/agents";
|
||||
import BudgetPanel from "@/components/budgets/budget_panel";
|
||||
import CacheDashboard from "@/components/cache_dashboard";
|
||||
import ClaudeCodePluginsPanel from "@/components/claude_code_plugins";
|
||||
import { teamListCall as v2TeamListCall } from "@/app/(dashboard)/hooks/teams/useTeams";
|
||||
import LoadingScreen from "@/components/common_components/LoadingScreen";
|
||||
import { CostTrackingSettings } from "@/components/CostTrackingSettings";
|
||||
import GeneralSettings from "@/components/general_settings";
|
||||
import GuardrailsMonitorView from "@/components/GuardrailsMonitor/GuardrailsMonitorView";
|
||||
import GuardrailsPanel from "@/components/guardrails";
|
||||
import PoliciesPanel from "@/components/policies";
|
||||
import { Team } from "@/components/key_team_helpers/key_list";
|
||||
import { MCPServers } from "@/components/mcp_tools";
|
||||
import ModelHubTable from "@/components/AIHub/ModelHubTable";
|
||||
import Navbar from "@/components/navbar";
|
||||
import { Organization, proxyBaseUrl, getInProductNudgesCall } from "@/components/networking";
|
||||
|
|
@ -25,23 +17,11 @@ import OldTeams from "@/components/OldTeams";
|
|||
import { fetchUserModels, CreateKeyPrefillData } from "@/components/organisms/create_key_button";
|
||||
import Organizations, { fetchOrganizations } from "@/components/organizations";
|
||||
import PassThroughSettings from "@/components/pass_through_settings";
|
||||
import PromptsPanel from "@/components/prompts";
|
||||
import PublicModelHub from "@/components/public_model_hub";
|
||||
import { SearchTools } from "@/components/SearchTools";
|
||||
import Settings from "@/components/settings";
|
||||
import { SurveyPrompt, SurveyModal, ClaudeCodePrompt, ClaudeCodeModal } from "@/components/survey";
|
||||
import TagManagement from "@/components/tag_management";
|
||||
import TransformRequestPanel from "@/components/transform_request";
|
||||
import UIThemeSettings from "@/components/ui_theme_settings";
|
||||
import Usage from "@/components/usage";
|
||||
import UserDashboard from "@/components/user_dashboard";
|
||||
import { AccessGroupsPage } from "@/components/AccessGroups/AccessGroupsPage";
|
||||
import { ProjectsPage } from "@/components/Projects/ProjectsPage";
|
||||
import VectorStoreManagement from "@/components/vector_store_management";
|
||||
import ToolPoliciesView from "@/components/ToolPoliciesView";
|
||||
import { MemoryView } from "@/components/MemoryView";
|
||||
import WorkflowRuns from "@/components/workflow_runs";
|
||||
import SpendLogsTable from "@/components/view_logs";
|
||||
import ViewUserDashboard from "@/components/view_users";
|
||||
import { ThemeProvider } from "@/contexts/ThemeContext";
|
||||
import { useAuth } from "@/contexts/AuthContext";
|
||||
|
|
@ -442,18 +422,8 @@ function CreateKeyPageContent() {
|
|||
<AdminPanel proxySettings={proxySettings} />
|
||||
) : page == "logging-and-alerts" ? (
|
||||
<Settings userID={userID} userRole={userRole} accessToken={accessToken} premiumUser={premiumUser} />
|
||||
) : page == "budgets" ? (
|
||||
<BudgetPanel accessToken={accessToken} />
|
||||
) : page == "guardrails" ? (
|
||||
<GuardrailsPanel accessToken={accessToken} userRole={userRole} />
|
||||
) : page == "policies" ? (
|
||||
<PoliciesPanel accessToken={accessToken} userRole={userRole} />
|
||||
) : page == "agents" ? (
|
||||
<AgentsPanel accessToken={accessToken} userRole={userRole} teams={teams} />
|
||||
) : page == "prompts" ? (
|
||||
<PromptsPanel accessToken={accessToken} userRole={userRole} />
|
||||
) : page == "transform-request" ? (
|
||||
<TransformRequestPanel accessToken={accessToken} />
|
||||
) : page == "router-settings" ? (
|
||||
<GeneralSettings
|
||||
userID={userID}
|
||||
|
|
@ -461,10 +431,6 @@ function CreateKeyPageContent() {
|
|||
accessToken={accessToken}
|
||||
modelData={modelData}
|
||||
/>
|
||||
) : page == "ui-theme" ? (
|
||||
<UIThemeSettings userID={userID} userRole={userRole} accessToken={accessToken} />
|
||||
) : page == "cost-tracking" ? (
|
||||
<CostTrackingSettings userID={userID} userRole={userRole} accessToken={accessToken} />
|
||||
) : page == "model-hub-table" ? (
|
||||
isAdminRole(userRole) ? (
|
||||
<ModelHubTable
|
||||
|
|
@ -476,14 +442,6 @@ function CreateKeyPageContent() {
|
|||
) : (
|
||||
<PublicModelHub accessToken={accessToken} isEmbedded={true} />
|
||||
)
|
||||
) : page == "caching" ? (
|
||||
<CacheDashboard
|
||||
userID={userID}
|
||||
userRole={userRole}
|
||||
token={token}
|
||||
accessToken={accessToken}
|
||||
premiumUser={premiumUser}
|
||||
/>
|
||||
) : page == "pass-through-settings" ? (
|
||||
<PassThroughSettings
|
||||
userID={userID}
|
||||
|
|
@ -492,36 +450,6 @@ function CreateKeyPageContent() {
|
|||
modelData={modelData}
|
||||
premiumUser={premiumUser}
|
||||
/>
|
||||
) : page == "logs" ? (
|
||||
<SpendLogsTable
|
||||
userID={userID}
|
||||
userRole={userRole}
|
||||
token={token}
|
||||
accessToken={accessToken}
|
||||
premiumUser={premiumUser}
|
||||
/>
|
||||
) : page == "mcp-servers" ? (
|
||||
<MCPServers accessToken={accessToken} userRole={userRole} userID={userID} />
|
||||
) : page == "search-tools" ? (
|
||||
<SearchTools accessToken={accessToken} userRole={userRole} userID={userID} />
|
||||
) : page == "tag-management" ? (
|
||||
<TagManagement accessToken={accessToken} userRole={userRole} userID={userID} />
|
||||
) : page == "skills" || page == "claude-code-plugins" ? (
|
||||
<ClaudeCodePluginsPanel accessToken={accessToken} userRole={userRole} />
|
||||
) : page == "access-groups" ? (
|
||||
<AccessGroupsPage />
|
||||
) : page == "projects" ? (
|
||||
<ProjectsPage />
|
||||
) : page == "vector-stores" ? (
|
||||
<VectorStoreManagement accessToken={accessToken} userRole={userRole} userID={userID} />
|
||||
) : page == "tool-policies" ? (
|
||||
<ToolPoliciesView accessToken={accessToken} userRole={userRole} />
|
||||
) : page == "workflows" ? (
|
||||
<WorkflowRuns accessToken={accessToken} />
|
||||
) : page == "memory" ? (
|
||||
<MemoryView accessToken={accessToken} userID={userID} userRole={userRole} />
|
||||
) : page == "guardrails-monitor" ? (
|
||||
<GuardrailsMonitorView accessToken={accessToken} />
|
||||
) : page == "new_usage" ? (
|
||||
<NewUsagePage
|
||||
teams={(teams as Team[]) ?? []}
|
||||
|
|
|
|||
|
|
@ -67,3 +67,47 @@ describe("legacyKeyForPathname", () => {
|
|||
expect(legacyKeyForPathname("/ui/api-reference")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("MIGRATED_PAGES leaf cutover", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
it("routes every migrated leaf page to its segment and back to a sidebar key", async () => {
|
||||
vi.doMock("@/components/networking", () => ({ serverRootPath: "/" }));
|
||||
const { MIGRATED_PAGES, legacyKeyForPathname } = await import("./migratedPages");
|
||||
|
||||
const cases: [string, string][] = [
|
||||
["budgets", "budgets"],
|
||||
["caching", "caching"],
|
||||
["cost-tracking", "cost-tracking"],
|
||||
["guardrails", "guardrails"],
|
||||
["guardrails-monitor", "guardrails-monitor"],
|
||||
["logs", "logs"],
|
||||
["mcp-servers", "mcp-servers"],
|
||||
["memory", "memory"],
|
||||
["policies", "policies"],
|
||||
["projects", "projects"],
|
||||
["prompts", "prompts"],
|
||||
["search-tools", "search-tools"],
|
||||
["skills", "skills"],
|
||||
["claude-code-plugins", "skills"],
|
||||
["tag-management", "tag-management"],
|
||||
["tool-policies", "tool-policies"],
|
||||
["transform-request", "transform-request"],
|
||||
["ui-theme", "ui-theme"],
|
||||
["vector-stores", "vector-stores"],
|
||||
["workflows", "workflows"],
|
||||
["access-groups", "access-groups"],
|
||||
];
|
||||
for (const [key, seg] of cases) {
|
||||
expect(MIGRATED_PAGES[key]).toBe(seg);
|
||||
expect(legacyKeyForPathname(`/ui/${seg}`)).not.toBeNull();
|
||||
expect(legacyKeyForPathname(`/ui/${seg}/`)).not.toBeNull();
|
||||
}
|
||||
|
||||
// The skills alias resolves to the "skills" sidebar key, not "claude-code-plugins".
|
||||
expect(legacyKeyForPathname("/ui/skills")).toBe("skills");
|
||||
expect(legacyKeyForPathname("/ui/budgets")).toBe("budgets");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,6 +12,27 @@ export const MIGRATED_PAGES: Record<string, string> = {
|
|||
api_ref: "api-reference",
|
||||
// Legacy alias: older bookmarks used the hyphenated ?page=api-reference form.
|
||||
"api-reference": "api-reference",
|
||||
budgets: "budgets",
|
||||
caching: "caching",
|
||||
"cost-tracking": "cost-tracking",
|
||||
guardrails: "guardrails",
|
||||
"guardrails-monitor": "guardrails-monitor",
|
||||
logs: "logs",
|
||||
"mcp-servers": "mcp-servers",
|
||||
memory: "memory",
|
||||
policies: "policies",
|
||||
projects: "projects",
|
||||
prompts: "prompts",
|
||||
"search-tools": "search-tools",
|
||||
skills: "skills",
|
||||
"claude-code-plugins": "skills",
|
||||
"tag-management": "tag-management",
|
||||
"tool-policies": "tool-policies",
|
||||
"transform-request": "transform-request",
|
||||
"ui-theme": "ui-theme",
|
||||
"vector-stores": "vector-stores",
|
||||
workflows: "workflows",
|
||||
"access-groups": "access-groups",
|
||||
};
|
||||
|
||||
function uiBase(): string {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue