mirror of
https://github.com/tiennm99/litellm.git
synced 2026-07-11 07:05:00 +00:00
move the menu button to top nav+ change the icon size
This commit is contained in:
@@ -136,6 +136,11 @@ export default function CreateKeyPage() {
|
||||
}
|
||||
|
||||
const [accessToken, setAccessToken] = useState<string | null>(null)
|
||||
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
||||
|
||||
const toggleSidebar = () => {
|
||||
setSidebarCollapsed(!sidebarCollapsed);
|
||||
};
|
||||
|
||||
const addKey = (data: any) => {
|
||||
setKeys((prevData) => (prevData ? [...prevData, data] : [data]))
|
||||
@@ -248,14 +253,17 @@ export default function CreateKeyPage() {
|
||||
proxySettings={proxySettings}
|
||||
accessToken={accessToken}
|
||||
isPublicPage={false}
|
||||
sidebarCollapsed={sidebarCollapsed}
|
||||
onToggleSidebar={toggleSidebar}
|
||||
/>
|
||||
<div className="flex flex-1 overflow-auto">
|
||||
<div className="mt-8">
|
||||
<div className="mt-2">
|
||||
<Sidebar
|
||||
accessToken={accessToken}
|
||||
setPage={updatePage}
|
||||
userRole={userRole}
|
||||
defaultSelectedKey={page}
|
||||
collapsed={sidebarCollapsed}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
import { old_admin_roles, v2_admin_role_names, all_admin_roles, rolesAllowedToSeeUsage, rolesWithWriteAccess, internalUserRoles, isAdminRole } from '../utils/roles';
|
||||
import UsageIndicator from './usage_indicator';
|
||||
import { ConfigProvider } from 'antd';
|
||||
const { Sider } = Layout;
|
||||
|
||||
// Define the props type
|
||||
@@ -38,6 +39,7 @@ interface SidebarProps {
|
||||
setPage: (page: string) => void;
|
||||
userRole: string;
|
||||
defaultSelectedKey: string;
|
||||
collapsed?: boolean;
|
||||
}
|
||||
|
||||
// Create a more comprehensive menu item configuration
|
||||
@@ -57,65 +59,73 @@ const Sidebar: React.FC<SidebarProps> = ({
|
||||
setPage,
|
||||
userRole,
|
||||
defaultSelectedKey,
|
||||
collapsed = false,
|
||||
}) => {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
|
||||
const toggleCollapse = () => {
|
||||
setCollapsed(!collapsed);
|
||||
};
|
||||
// Note: If a menu item does not have a role, it is visible to all roles.
|
||||
const menuItems: MenuItem[] = [
|
||||
{ key: "1", page: "api-keys", label: "Virtual Keys", icon: <KeyOutlined /> },
|
||||
{ key: "3", page: "llm-playground", label: "Test Key", icon: <PlayCircleOutlined />, roles: rolesWithWriteAccess },
|
||||
{ key: "2", page: "models", label: "Models + Endpoints", icon: <BlockOutlined />, roles: rolesWithWriteAccess },
|
||||
{ key: "12", page: "new_usage", label: "Usage", icon: <BarChartOutlined />, roles: [...all_admin_roles, ...internalUserRoles] },
|
||||
{ key: "6", page: "teams", label: "Teams", icon: <TeamOutlined /> },
|
||||
{ key: "17", page: "organizations", label: "Organizations", icon: <BankOutlined />, roles: all_admin_roles },
|
||||
{ key: "5", page: "users", label: "Internal Users", icon: <UserOutlined />, roles: all_admin_roles },
|
||||
{ key: "14", page: "api_ref", label: "API Reference", icon: <ApiOutlined /> },
|
||||
{
|
||||
key: "1",
|
||||
page: "api-keys",
|
||||
label: "Virtual Keys",
|
||||
icon: <KeyOutlined style={{ fontSize: '18px' }} />
|
||||
},
|
||||
{
|
||||
key: "3",
|
||||
page: "llm-playground",
|
||||
label: "Test Key",
|
||||
icon: <PlayCircleOutlined style={{ fontSize: '18px' }} />,
|
||||
roles: rolesWithWriteAccess
|
||||
},
|
||||
{ key: "2", page: "models", label: "Models + Endpoints", icon: <BlockOutlined style={{ fontSize: '18px' }} />, roles: rolesWithWriteAccess },
|
||||
{ key: "12", page: "new_usage", label: "Usage", icon: <BarChartOutlined style={{ fontSize: '18px' }} />, roles: [...all_admin_roles, ...internalUserRoles] },
|
||||
{ key: "6", page: "teams", label: "Teams", icon: <TeamOutlined style={{ fontSize: '18px' }} /> },
|
||||
{ key: "17", page: "organizations", label: "Organizations", icon: <BankOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
{ key: "5", page: "users", label: "Internal Users", icon: <UserOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
{ key: "14", page: "api_ref", label: "API Reference", icon: <ApiOutlined style={{ fontSize: '18px' }} /> },
|
||||
{
|
||||
key: "16",
|
||||
page: "model-hub-table",
|
||||
label: "Model Hub",
|
||||
icon: <AppstoreOutlined />
|
||||
icon: <AppstoreOutlined style={{ fontSize: '18px' }} />
|
||||
},
|
||||
{ key: "15", page: "logs", label: "Logs", icon: <LineChartOutlined />},
|
||||
{ key: "11", page: "guardrails", label: "Guardrails", icon: <SafetyOutlined />, roles: all_admin_roles },
|
||||
{ key: "15", page: "logs", label: "Logs", icon: <LineChartOutlined style={{ fontSize: '18px' }} />},
|
||||
{ key: "11", page: "guardrails", label: "Guardrails", icon: <SafetyOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
{
|
||||
key: "26",
|
||||
page: "tools",
|
||||
label: "Tools",
|
||||
icon: <ToolOutlined />,
|
||||
icon: <ToolOutlined style={{ fontSize: '18px' }} />,
|
||||
children: [
|
||||
{ key: "18", page: "mcp-servers", label: "MCP Servers", icon: <ToolOutlined /> },
|
||||
{ key: "21", page: "vector-stores", label: "Vector Stores", icon: <DatabaseOutlined />, roles: all_admin_roles },
|
||||
{ key: "18", page: "mcp-servers", label: "MCP Servers", icon: <ToolOutlined style={{ fontSize: '18px' }} /> },
|
||||
{ key: "21", page: "vector-stores", label: "Vector Stores", icon: <DatabaseOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "experimental",
|
||||
page: "experimental",
|
||||
label: "Experimental",
|
||||
icon: <ExperimentOutlined />,
|
||||
icon: <ExperimentOutlined style={{ fontSize: '18px' }} />,
|
||||
children: [
|
||||
{ key: "9", page: "caching", label: "Caching", icon: <DatabaseOutlined />, roles: all_admin_roles },
|
||||
{ key: "25", page: "prompts", label: "Prompts", icon: <FileTextOutlined />, roles: all_admin_roles },
|
||||
{ key: "10", page: "budgets", label: "Budgets", icon: <BankOutlined />, roles: all_admin_roles },
|
||||
{ key: "20", page: "transform-request", label: "API Playground", icon: <ApiOutlined />, roles: [...all_admin_roles, ...internalUserRoles] },
|
||||
{ key: "19", page: "tag-management", label: "Tag Management", icon: <TagsOutlined />, roles: all_admin_roles },
|
||||
{ key: "4", page: "usage", label: "Old Usage", icon: <BarChartOutlined /> },
|
||||
{ key: "9", page: "caching", label: "Caching", icon: <DatabaseOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
{ key: "25", page: "prompts", label: "Prompts", icon: <FileTextOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
{ key: "10", page: "budgets", label: "Budgets", icon: <BankOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
{ key: "20", page: "transform-request", label: "API Playground", icon: <ApiOutlined style={{ fontSize: '18px' }} />, roles: [...all_admin_roles, ...internalUserRoles] },
|
||||
{ key: "19", page: "tag-management", label: "Tag Management", icon: <TagsOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
{ key: "4", page: "usage", label: "Old Usage", icon: <BarChartOutlined style={{ fontSize: '18px' }} /> },
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "settings",
|
||||
page: "settings",
|
||||
label: "Settings",
|
||||
icon: <SettingOutlined />,
|
||||
icon: <SettingOutlined style={{ fontSize: '18px' }} />,
|
||||
roles: all_admin_roles,
|
||||
children: [
|
||||
{ key: "11", page: "general-settings", label: "Router Settings", icon: <SettingOutlined />, roles: all_admin_roles },
|
||||
{ key: "8", page: "settings", label: "Logging & Alerts", icon: <SettingOutlined />, roles: all_admin_roles },
|
||||
{ key: "13", page: "admin-panel", label: "Admin Settings", icon: <SettingOutlined />, roles: all_admin_roles },
|
||||
{ key: "14", page: "ui-theme", label: "UI Theme", icon: <BgColorsOutlined />, roles: all_admin_roles },
|
||||
{ key: "11", page: "general-settings", label: "Router Settings", icon: <SettingOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
{ key: "8", page: "settings", label: "Logging & Alerts", icon: <SettingOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
{ key: "13", page: "admin-panel", label: "Admin Settings", icon: <SettingOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
{ key: "14", page: "ui-theme", label: "UI Theme", icon: <BgColorsOutlined style={{ fontSize: '18px' }} />, roles: all_admin_roles },
|
||||
]
|
||||
}
|
||||
];
|
||||
@@ -166,83 +176,32 @@ const Sidebar: React.FC<SidebarProps> = ({
|
||||
collapsible
|
||||
trigger={null}
|
||||
style={{
|
||||
transition: 'all 0.2s',
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)', // Material Design easing
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={[selectedMenuKey]}
|
||||
defaultOpenKeys={collapsed ? [] : ["llm-tools"]}
|
||||
inlineCollapsed={collapsed}
|
||||
style={{
|
||||
borderRight: 0,
|
||||
backgroundColor: 'transparent',
|
||||
fontSize: '14px',
|
||||
}}
|
||||
items={[
|
||||
// Expand button row when collapsed, or first menu item when expanded
|
||||
collapsed ? {
|
||||
key: 'expand-toggle',
|
||||
icon: <MenuUnfoldOutlined />,
|
||||
label: '',
|
||||
onClick: toggleCollapse,
|
||||
style: {
|
||||
cursor: 'pointer',
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
components: {
|
||||
Menu: {
|
||||
iconSize: 18,
|
||||
fontSize: 14,
|
||||
},
|
||||
title: "Expand navigation sidebar"
|
||||
} : {
|
||||
key: filteredMenuItems[0]?.key,
|
||||
icon: filteredMenuItems[0]?.icon,
|
||||
label: (
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%'
|
||||
}}>
|
||||
<span>{filteredMenuItems[0]?.label}</span>
|
||||
<div
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
toggleCollapse();
|
||||
}}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
padding: '8px 12px',
|
||||
borderRadius: '4px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontSize: '12px',
|
||||
color: '#888',
|
||||
transition: 'all 0.2s',
|
||||
marginLeft: '8px',
|
||||
marginRight: '-8px',
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.background = 'rgba(0, 0, 0, 0.04)';
|
||||
e.currentTarget.style.color = '#666';
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = 'transparent';
|
||||
e.currentTarget.style.color = '#888';
|
||||
}}
|
||||
title="Collapse navigation sidebar"
|
||||
>
|
||||
<MenuFoldOutlined />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
onClick: !filteredMenuItems[0]?.children ? () => {
|
||||
const newSearchParams = new URLSearchParams(window.location.search);
|
||||
newSearchParams.set('page', filteredMenuItems[0]?.page || '');
|
||||
window.history.pushState(null, '', `?${newSearchParams.toString()}`);
|
||||
setPage(filteredMenuItems[0]?.page || '');
|
||||
} : undefined
|
||||
},
|
||||
// Rest of the menu items (or all items when collapsed)
|
||||
...(collapsed ? filteredMenuItems : filteredMenuItems.slice(1)).map(item => ({
|
||||
}}
|
||||
>
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={[selectedMenuKey]}
|
||||
defaultOpenKeys={collapsed ? [] : ["llm-tools"]}
|
||||
inlineCollapsed={collapsed}
|
||||
className="custom-sidebar-menu"
|
||||
style={{
|
||||
borderRight: 0,
|
||||
backgroundColor: 'transparent',
|
||||
fontSize: '14px',
|
||||
}}
|
||||
items={filteredMenuItems.map(item => ({
|
||||
key: item.key,
|
||||
icon: item.icon,
|
||||
label: item.label,
|
||||
@@ -263,9 +222,9 @@ const Sidebar: React.FC<SidebarProps> = ({
|
||||
window.history.pushState(null, '', `?${newSearchParams.toString()}`);
|
||||
setPage(item.page);
|
||||
} : undefined
|
||||
}))
|
||||
]}
|
||||
/>
|
||||
}))}
|
||||
/>
|
||||
</ConfigProvider>
|
||||
{
|
||||
isAdminRole(userRole) && !collapsed && (
|
||||
<UsageIndicator accessToken={accessToken} width={220}/>
|
||||
|
||||
@@ -11,7 +11,9 @@ import {
|
||||
BgColorsOutlined,
|
||||
CrownOutlined,
|
||||
MailOutlined,
|
||||
SafetyOutlined
|
||||
SafetyOutlined,
|
||||
MenuFoldOutlined,
|
||||
MenuUnfoldOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { clearTokenCookies } from "@/utils/cookieUtils"
|
||||
import { fetchProxySettings } from "@/utils/proxyUtils"
|
||||
@@ -23,10 +25,12 @@ interface NavbarProps {
|
||||
userEmail: string | null;
|
||||
userRole: string | null;
|
||||
premiumUser: boolean;
|
||||
setProxySettings: React.Dispatch<React.SetStateAction<any>>;
|
||||
proxySettings: any;
|
||||
setProxySettings: React.Dispatch<React.SetStateAction<any>>;
|
||||
accessToken: string | null;
|
||||
isPublicPage: boolean;
|
||||
sidebarCollapsed?: boolean;
|
||||
onToggleSidebar?: () => void;
|
||||
}
|
||||
|
||||
const Navbar: React.FC<NavbarProps> = ({
|
||||
@@ -38,6 +42,8 @@ const Navbar: React.FC<NavbarProps> = ({
|
||||
setProxySettings,
|
||||
accessToken,
|
||||
isPublicPage = false,
|
||||
sidebarCollapsed = false,
|
||||
onToggleSidebar,
|
||||
}) => {
|
||||
const baseUrl = getProxyBaseUrl();
|
||||
const [logoutUrl, setLogoutUrl] = useState("");
|
||||
@@ -128,14 +134,27 @@ const Navbar: React.FC<NavbarProps> = ({
|
||||
return (
|
||||
<nav className="bg-white border-b border-gray-200 sticky top-0 z-10">
|
||||
<div className="w-full">
|
||||
<div className="flex items-center h-12 px-4">
|
||||
{/* Left side with correct logo positioning */}
|
||||
<div className="flex items-center h-14 px-4"> {/* Increased height from h-12 to h-14 */}
|
||||
{/* Left side with collapse toggle and logo */}
|
||||
<div className="flex items-center flex-shrink-0">
|
||||
{/* Collapse/Expand Toggle Button - Larger */}
|
||||
{onToggleSidebar && (
|
||||
<button
|
||||
onClick={onToggleSidebar}
|
||||
className="flex items-center justify-center w-10 h-10 mr-2 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded transition-colors"
|
||||
title={sidebarCollapsed ? "Expand sidebar" : "Collapse sidebar"}
|
||||
>
|
||||
<span className="text-lg">
|
||||
{sidebarCollapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<Link href="/" className="flex items-center">
|
||||
<img
|
||||
src={imageUrl}
|
||||
alt="LiteLLM Brand"
|
||||
className="h-8 w-auto"
|
||||
className="h-10 w-auto"
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
@@ -146,7 +165,7 @@ const Navbar: React.FC<NavbarProps> = ({
|
||||
href="https://docs.litellm.ai/docs/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-[13px] text-gray-600 hover:text-gray-900 transition-colors"
|
||||
className="text-sm text-gray-600 hover:text-gray-900 transition-colors"
|
||||
>
|
||||
Docs
|
||||
</a>
|
||||
@@ -167,10 +186,10 @@ const Navbar: React.FC<NavbarProps> = ({
|
||||
minWidth: '200px'
|
||||
}}
|
||||
>
|
||||
<button className="inline-flex items-center text-[13px] text-gray-600 hover:text-gray-900 transition-colors">
|
||||
<button className="inline-flex items-center text-sm text-gray-600 hover:text-gray-900 transition-colors">
|
||||
User
|
||||
<svg
|
||||
className="ml-1 w-4 h-4 text-gray-500"
|
||||
className="ml-1 w-5 h-5 text-gray-500"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
|
||||
@@ -354,7 +354,7 @@ const UserDashboard: React.FC<UserDashboardProps> = ({
|
||||
console.log("All cookies after redirect:", document.cookie)
|
||||
return (
|
||||
<div className="w-full mx-4 h-[75vh]">
|
||||
<Grid numItems={1} className="gap-2 p-8 w-full mt-2">
|
||||
<Grid numItems={1} className="gap-2 p-2 w-full mt-2">
|
||||
<Col numColSpan={1} className="flex flex-col gap-2">
|
||||
<CreateKey
|
||||
key={selectedTeam ? selectedTeam.team_id : null}
|
||||
|
||||
Reference in New Issue
Block a user