Adjusting new badges

This commit is contained in:
yuneng-jiang
2026-01-29 13:36:38 -08:00
parent 42081a57db
commit 6b77060bbd
4 changed files with 303 additions and 297 deletions
@@ -1,7 +1,13 @@
import { Badge } from "antd";
import { useDisableShowNewBadge } from "@/app/(dashboard)/hooks/useDisableShowNewBadge";
export default function NewBadge({ children }: { children?: React.ReactNode }) {
export default function NewBadge({
children,
dot = false
}: {
children?: React.ReactNode;
dot?: boolean;
}) {
const disableShowNewBadge = useDisableShowNewBadge();
if (disableShowNewBadge) {
@@ -9,10 +15,10 @@ export default function NewBadge({ children }: { children?: React.ReactNode }) {
}
return children ? (
<Badge color="blue" count="New">
<Badge color="blue" count={dot ? undefined : "New"} dot={dot}>
{children}
</Badge>
) : (
<Badge color="blue" count="New" />
<Badge color="blue" count={dot ? undefined : "New"} dot={dot} />
);
}
+261 -261
View File
@@ -62,260 +62,260 @@ interface MenuGroup {
// Menu groups organized by category - defined outside component for export
const menuGroups: MenuGroup[] = [
{
groupLabel: "AI GATEWAY",
items: [
{
key: "api-keys",
page: "api-keys",
label: "Virtual Keys",
icon: <KeyOutlined />,
},
{
key: "llm-playground",
page: "llm-playground",
label: "Playground",
icon: <PlayCircleOutlined />,
roles: rolesWithWriteAccess,
},
{
key: "models",
page: "models",
label: "Models + Endpoints",
icon: <BlockOutlined />,
roles: rolesWithWriteAccess,
},
{
key: "agents",
page: "agents",
label: "Agents",
icon: <RobotOutlined />,
roles: rolesWithWriteAccess,
},
{
key: "mcp-servers",
page: "mcp-servers",
label: "MCP Servers",
icon: <ToolOutlined />,
},
{
key: "guardrails",
page: "guardrails",
label: "Guardrails",
icon: <SafetyOutlined />,
roles: all_admin_roles,
},
{
key: "policies",
page: "policies",
label: (
<span className="flex items-center gap-4">
Policies <NewBadge />
</span>
),
icon: <AuditOutlined />,
roles: all_admin_roles,
},
{
key: "tools",
page: "tools",
label: "Tools",
icon: <ToolOutlined />,
children: [
{
key: "search-tools",
page: "search-tools",
label: "Search Tools",
icon: <SearchOutlined />,
},
{
key: "vector-stores",
page: "vector-stores",
label: "Vector Stores",
icon: <DatabaseOutlined />,
},
],
},
],
},
{
groupLabel: "OBSERVABILITY",
items: [
{
key: "new_usage",
page: "new_usage",
icon: <BarChartOutlined />,
roles: [...all_admin_roles, ...internalUserRoles],
label: "Usage",
},
{
key: "logs",
page: "logs",
label: (
<span className="flex items-center gap-4">
Logs <NewBadge />
</span>
),
icon: <LineChartOutlined />,
},
],
},
{
groupLabel: "ACCESS CONTROL",
items: [
{
key: "users",
page: "users",
label: "Internal Users",
icon: <UserOutlined />,
roles: all_admin_roles,
},
{
key: "teams",
page: "teams",
label: "Teams",
icon: <TeamOutlined />,
},
{
key: "organizations",
page: "organizations",
label: "Organizations",
icon: <BankOutlined />,
roles: all_admin_roles,
},
{
key: "budgets",
page: "budgets",
label: "Budgets",
icon: <CreditCardOutlined />,
roles: all_admin_roles,
},
],
},
{
groupLabel: "DEVELOPER TOOLS",
items: [
{
key: "api_ref",
page: "api_ref",
label: "API Reference",
icon: <ApiOutlined />,
},
{
key: "model-hub-table",
page: "model-hub-table",
label: "AI Hub",
icon: <AppstoreOutlined />,
},
{
key: "learning-resources",
page: "learning-resources",
label: "Learning Resources",
icon: <BookOutlined />,
external_url: "https://models.litellm.ai/cookbook",
},
{
key: "experimental",
page: "experimental",
label: "Experimental",
icon: <ExperimentOutlined />,
children: [
{
key: "caching",
page: "caching",
label: "Caching",
icon: <DatabaseOutlined />,
roles: all_admin_roles,
},
{
key: "prompts",
page: "prompts",
label: "Prompts",
icon: <FileTextOutlined />,
roles: all_admin_roles,
},
{
key: "transform-request",
page: "transform-request",
label: "API Playground",
icon: <ApiOutlined />,
roles: [...all_admin_roles, ...internalUserRoles],
},
{
key: "tag-management",
page: "tag-management",
label: "Tag Management",
icon: <TagsOutlined />,
roles: all_admin_roles,
},
{
key: "claude-code-plugins",
page: "claude-code-plugins",
label: "Claude Code Plugins",
icon: <ToolOutlined />,
roles: all_admin_roles,
},
{
key: "4",
page: "usage",
label: "Old Usage",
icon: <BarChartOutlined />,
}
],
},
],
},
{
groupLabel: "SETTINGS",
roles: all_admin_roles,
items: [
{
key: "settings",
page: "settings",
label: <span className="flex items-center gap-4">Settings</span>,
icon: <SettingOutlined />,
roles: all_admin_roles,
children: [
{
key: "router-settings",
page: "router-settings",
label: "Router Settings",
icon: <SettingOutlined />,
roles: all_admin_roles,
},
{
key: "logging-and-alerts",
page: "logging-and-alerts",
label: "Logging & Alerts",
icon: <SettingOutlined />,
roles: all_admin_roles,
},
{
key: "admin-panel",
page: "admin-panel",
label: "Admin Settings",
icon: <SettingOutlined />,
roles: all_admin_roles,
},
{
key: "cost-tracking",
page: "cost-tracking",
label: "Cost Tracking",
icon: <BarChartOutlined />,
roles: all_admin_roles,
},
{
key: "ui-theme",
page: "ui-theme",
label: "UI Theme",
icon: <BgColorsOutlined />,
roles: all_admin_roles,
},
],
},
],
},
];
{
groupLabel: "AI GATEWAY",
items: [
{
key: "api-keys",
page: "api-keys",
label: "Virtual Keys",
icon: <KeyOutlined />,
},
{
key: "llm-playground",
page: "llm-playground",
label: "Playground",
icon: <PlayCircleOutlined />,
roles: rolesWithWriteAccess,
},
{
key: "models",
page: "models",
label: "Models + Endpoints",
icon: <BlockOutlined />,
roles: rolesWithWriteAccess,
},
{
key: "agents",
page: "agents",
label: "Agents",
icon: <RobotOutlined />,
roles: rolesWithWriteAccess,
},
{
key: "mcp-servers",
page: "mcp-servers",
label: "MCP Servers",
icon: <ToolOutlined />,
},
{
key: "guardrails",
page: "guardrails",
label: "Guardrails",
icon: <SafetyOutlined />,
roles: all_admin_roles,
},
{
key: "policies",
page: "policies",
label: (
<span className="flex items-center gap-4">
Policies
</span>
),
icon: <AuditOutlined />,
roles: all_admin_roles,
},
{
key: "tools",
page: "tools",
label: "Tools",
icon: <ToolOutlined />,
children: [
{
key: "search-tools",
page: "search-tools",
label: "Search Tools",
icon: <SearchOutlined />,
},
{
key: "vector-stores",
page: "vector-stores",
label: "Vector Stores",
icon: <DatabaseOutlined />,
},
],
},
],
},
{
groupLabel: "OBSERVABILITY",
items: [
{
key: "new_usage",
page: "new_usage",
icon: <BarChartOutlined />,
roles: [...all_admin_roles, ...internalUserRoles],
label: "Usage",
},
{
key: "logs",
page: "logs",
label: (
<span className="flex items-center gap-4">
Logs <NewBadge />
</span>
),
icon: <LineChartOutlined />,
},
],
},
{
groupLabel: "ACCESS CONTROL",
items: [
{
key: "users",
page: "users",
label: "Internal Users",
icon: <UserOutlined />,
roles: all_admin_roles,
},
{
key: "teams",
page: "teams",
label: "Teams",
icon: <TeamOutlined />,
},
{
key: "organizations",
page: "organizations",
label: "Organizations",
icon: <BankOutlined />,
roles: all_admin_roles,
},
{
key: "budgets",
page: "budgets",
label: "Budgets",
icon: <CreditCardOutlined />,
roles: all_admin_roles,
},
],
},
{
groupLabel: "DEVELOPER TOOLS",
items: [
{
key: "api_ref",
page: "api_ref",
label: "API Reference",
icon: <ApiOutlined />,
},
{
key: "model-hub-table",
page: "model-hub-table",
label: "AI Hub",
icon: <AppstoreOutlined />,
},
{
key: "learning-resources",
page: "learning-resources",
label: "Learning Resources",
icon: <BookOutlined />,
external_url: "https://models.litellm.ai/cookbook",
},
{
key: "experimental",
page: "experimental",
label: "Experimental",
icon: <ExperimentOutlined />,
children: [
{
key: "caching",
page: "caching",
label: "Caching",
icon: <DatabaseOutlined />,
roles: all_admin_roles,
},
{
key: "prompts",
page: "prompts",
label: "Prompts",
icon: <FileTextOutlined />,
roles: all_admin_roles,
},
{
key: "transform-request",
page: "transform-request",
label: "API Playground",
icon: <ApiOutlined />,
roles: [...all_admin_roles, ...internalUserRoles],
},
{
key: "tag-management",
page: "tag-management",
label: "Tag Management",
icon: <TagsOutlined />,
roles: all_admin_roles,
},
{
key: "claude-code-plugins",
page: "claude-code-plugins",
label: "Claude Code Plugins",
icon: <ToolOutlined />,
roles: all_admin_roles,
},
{
key: "4",
page: "usage",
label: "Old Usage",
icon: <BarChartOutlined />,
}
],
},
],
},
{
groupLabel: "SETTINGS",
roles: all_admin_roles,
items: [
{
key: "settings",
page: "settings",
label: <span className="flex items-center gap-4">Settings</span>,
icon: <SettingOutlined />,
roles: all_admin_roles,
children: [
{
key: "router-settings",
page: "router-settings",
label: "Router Settings",
icon: <SettingOutlined />,
roles: all_admin_roles,
},
{
key: "logging-and-alerts",
page: "logging-and-alerts",
label: "Logging & Alerts",
icon: <SettingOutlined />,
roles: all_admin_roles,
},
{
key: "admin-panel",
page: "admin-panel",
label: "Admin Settings",
icon: <SettingOutlined />,
roles: all_admin_roles,
},
{
key: "cost-tracking",
page: "cost-tracking",
label: "Cost Tracking",
icon: <BarChartOutlined />,
roles: all_admin_roles,
},
{
key: "ui-theme",
page: "ui-theme",
label: "UI Theme",
icon: <BgColorsOutlined />,
roles: all_admin_roles,
},
],
},
],
},
];
const Sidebar: React.FC<SidebarProps> = ({ setPage, defaultSelectedKey, collapsed = false, enabledPagesInternalUsers }) => {
const { userId, accessToken, userRole } = useAuthorized();
@@ -377,7 +377,7 @@ const Sidebar: React.FC<SidebarProps> = ({ setPage, defaultSelectedKey, collapse
if (!isAdmin && enabledPagesInternalUsers !== null && enabledPagesInternalUsers !== undefined) {
// If item has children, check if any children are visible
if (item.children && item.children.length > 0) {
const hasVisibleChildren = item.children.some((child) =>
const hasVisibleChildren = item.children.some((child) =>
enabledPagesInternalUsers.includes(child.page)
);
if (hasVisibleChildren) {
@@ -385,7 +385,7 @@ const Sidebar: React.FC<SidebarProps> = ({ setPage, defaultSelectedKey, collapse
return true;
}
}
const isIncluded = enabledPagesInternalUsers.includes(item.page);
console.log(`[LeftNav] Page "${item.page}" (${item.key}): ${isIncluded ? "VISIBLE" : "HIDDEN"}`);
return isIncluded;
@@ -444,12 +444,12 @@ const Sidebar: React.FC<SidebarProps> = ({ setPage, defaultSelectedKey, collapse
})),
onClick: !item.children
? () => {
if (item.external_url) {
window.open(item.external_url, "_blank");
} else {
navigateToPage(item.page);
}
if (item.external_url) {
window.open(item.external_url, "_blank");
} else {
navigateToPage(item.page);
}
}
: undefined,
})),
});
@@ -1,10 +1,11 @@
"use client";
import { StoreRequestInSpendLogsParams, useStoreRequestInSpendLogs } from "@/app/(dashboard)/hooks/storeRequestInSpendLogs/useStoreRequestInSpendLogs";
import NewBadge from "@/components/common_components/NewBadge";
import NotificationsManager from "@/components/molecules/notifications_manager";
import { parseErrorMessage } from "@/components/shared/errorUtils";
import { ClockCircleOutlined } from "@ant-design/icons";
import { Button, Form, Input, Modal, Space, Switch } from "antd";
import { Button, Form, Input, Modal, Space, Switch, Typography } from "antd";
import React from "react";
interface SpendLogsSettingsModalProps {
@@ -42,7 +43,7 @@ const SpendLogsSettingsModal: React.FC<SpendLogsSettingsModalProps> = ({ isVisib
return (
<Modal
title="Spend Logs Settings"
title={<span className="flex gap-2"><Typography.Title level={5}>Spend Logs Settings</Typography.Title><NewBadge /></span>}
open={isVisible}
width={600}
footer={
@@ -1,38 +1,36 @@
import { useQuery, useQueryClient } from "@tanstack/react-query";
import moment from "moment";
import { useQuery } from "@tanstack/react-query";
import { useState, useRef, useEffect, useCallback } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { useCallback, useEffect, useRef, useState } from "react";
import { uiSpendLogsCall, keyInfoV1Call, sessionSpendLogsCall, keyListCall, allEndUsersCall } from "../networking";
import { DataTable } from "./table";
import { columns, LogEntry } from "./columns";
import { Row } from "@tanstack/react-table";
import { prefetchLogDetails } from "./prefetch";
import { RequestResponsePanel } from "./RequestResponsePanel";
import { ErrorViewer } from "./ErrorViewer";
import { internalUserRoles } from "../../utils/roles";
import { ConfigInfoMessage } from "./ConfigInfoMessage";
import { Button, Tooltip } from "antd";
import { KeyResponse, Team } from "../key_team_helpers/key_list";
import KeyInfoView from "../templates/key_info_view";
import { SessionView } from "./SessionView";
import { VectorStoreViewer } from "./VectorStoreViewer";
import GuardrailViewer from "@/components/view_logs/GuardrailViewer/GuardrailViewer";
import { CostBreakdownViewer } from "./CostBreakdownViewer";
import FilterComponent from "../molecules/filter";
import { FilterOption } from "../molecules/filter";
import { useLogFilterLogic } from "./log_filter_logic";
import { fetchAllKeyAliases } from "../key_team_helpers/filter_helpers";
import { Tab, TabGroup, TabList, TabPanels, TabPanel, Switch } from "@tremor/react";
import AuditLogs from "./audit_logs";
import { getTimeRangeDisplay } from "./logs_utils";
import { formatNumberWithCommas } from "@/utils/dataUtils";
import { truncateString } from "@/utils/textUtils";
import { SettingOutlined } from "@ant-design/icons";
import { Row } from "@tanstack/react-table";
import { Switch, Tab, TabGroup, TabList, TabPanel, TabPanels } from "@tremor/react";
import { Button, Tooltip } from "antd";
import { internalUserRoles } from "../../utils/roles";
import DeletedKeysPage from "../DeletedKeysPage/DeletedKeysPage";
import DeletedTeamsPage from "../DeletedTeamsPage/DeletedTeamsPage";
import NewBadge from "../common_components/NewBadge";
import { fetchAllKeyAliases } from "../key_team_helpers/filter_helpers";
import { KeyResponse, Team } from "../key_team_helpers/key_list";
import FilterComponent, { FilterOption } from "../molecules/filter";
import { allEndUsersCall, keyInfoV1Call, keyListCall, sessionSpendLogsCall, uiSpendLogsCall } from "../networking";
import KeyInfoView from "../templates/key_info_view";
import AuditLogs from "./audit_logs";
import { columns, LogEntry } from "./columns";
import { ConfigInfoMessage } from "./ConfigInfoMessage";
import { CostBreakdownViewer } from "./CostBreakdownViewer";
import { ErrorViewer } from "./ErrorViewer";
import { useLogFilterLogic } from "./log_filter_logic";
import { getTimeRangeDisplay } from "./logs_utils";
import { prefetchLogDetails } from "./prefetch";
import { RequestResponsePanel } from "./RequestResponsePanel";
import { SessionView } from "./SessionView";
import SpendLogsSettingsModal from "./SpendLogsSettingsModal/SpendLogsSettingsModal";
import { SettingOutlined } from "@ant-design/icons";
import { DataTable } from "./table";
import { VectorStoreViewer } from "./VectorStoreViewer";
import NewBadge from "../common_components/NewBadge";
interface SpendLogsTableProps {
accessToken: string | null;
@@ -513,8 +511,8 @@ export default function SpendLogsTable({
<TabList>
<Tab>Request Logs</Tab>
<Tab>Audit Logs</Tab>
<Tab><>Deleted Keys <NewBadge /></></Tab>
<Tab><>Deleted Teams <NewBadge /></></Tab>
<Tab>Deleted Keys</Tab>
<Tab>Deleted Teams</Tab>
</TabList>
<TabPanels>
<TabPanel>
@@ -535,11 +533,12 @@ export default function SpendLogsTable({
)}
</h1>
{!selectedSessionId && (
<Button
<NewBadge dot><Button
icon={<SettingOutlined />}
onClick={() => setIsSpendLogsSettingsModalVisible(true)}
title="Spend Logs Settings"
/>
/></NewBadge>
)}
</div>
{selectedKeyInfo && selectedKeyIdInfoView && selectedKeyInfo.api_key === selectedKeyIdInfoView ? (