diff --git a/dev_config.yaml b/dev_config.yaml new file mode 100644 index 0000000000..64e3c14703 --- /dev/null +++ b/dev_config.yaml @@ -0,0 +1,13 @@ +model_list: + - model_name: fake-openai-endpoint + litellm_params: + model: openai/fake-model + api_key: fake-key + api_base: https://exampleopenaiendpoint-production.up.railway.app/ + +general_settings: + master_key: sk-1234 + +litellm_settings: + drop_params: True + telemetry: False diff --git a/ui/litellm-dashboard/src/app/(dashboard)/components/Sidebar2.tsx b/ui/litellm-dashboard/src/app/(dashboard)/components/Sidebar2.tsx index a74d3c108d..b3829d0a8f 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/components/Sidebar2.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/components/Sidebar2.tsx @@ -374,6 +374,27 @@ const Sidebar2: React.FC = ({ accessToken, userRole, defaultSelect router.push(href); }; + // Wrap label in so every nav item supports right-click → "Open in new tab" + // and Ctrl/Cmd+click to open in a new tab, while preserving SPA navigation for normal clicks. + const renderNavLink = (label: string, page: string): React.ReactNode => { + const href = toHref(page); + return ( + { + if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) { + e.stopPropagation(); + return; + } + e.preventDefault(); + }} + style={{ color: "inherit", textDecoration: "none" }} + > + {label} + + ); + }; + return ( = ({ accessToken, userRole, defaultSelect items={filteredMenuItems.map((item) => ({ key: item.key, icon: item.icon, - label: item.label, + label: renderNavLink(item.label, item.page), children: item.children?.map((child) => ({ key: child.key, icon: child.icon, - label: child.label, + label: renderNavLink(child.label, child.page), onClick: () => goTo(child.page), })), onClick: !item.children ? () => goTo(item.page) : undefined, diff --git a/ui/litellm-dashboard/src/components/leftnav.tsx b/ui/litellm-dashboard/src/components/leftnav.tsx index e84b6e86e4..e09a95d15b 100644 --- a/ui/litellm-dashboard/src/components/leftnav.tsx +++ b/ui/litellm-dashboard/src/components/leftnav.tsx @@ -374,6 +374,46 @@ const Sidebar: React.FC = ({ setPage, defaultSelectedKey, collapse setPage(page); }; + // Wrap label in so every nav item supports right-click → "Open in new tab" + // and Ctrl/Cmd+click to open in a new tab, while preserving SPA navigation for normal clicks. + const renderNavLink = ( + label: React.ReactNode, + page: string, + externalUrl?: string, + ): React.ReactNode => { + if (externalUrl) { + return ( + e.stopPropagation()} + style={{ color: "inherit", textDecoration: "none" }} + > + {label} + + ); + } + const params = new URLSearchParams(window.location.search); + params.set("page", page); + const href = `?${params.toString()}`; + return ( + { + if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) { + e.stopPropagation(); + return; + } + e.preventDefault(); + }} + style={{ color: "inherit", textDecoration: "none" }} + > + {label} + + ); + }; + // Filter items based on user role and enabled pages for internal users const filterItemsByRole = (items: MenuItem[]): MenuItem[] => { const isAdmin = isAdminRole(userRole); @@ -469,11 +509,11 @@ const Sidebar: React.FC = ({ setPage, defaultSelectedKey, collapse children: filteredItems.map((item) => ({ key: item.key, icon: item.icon, - label: item.label, + label: renderNavLink(item.label, item.page, item.external_url), children: item.children?.map((child) => ({ key: child.key, icon: child.icon, - label: child.label, + label: renderNavLink(child.label, child.page, child.external_url), onClick: () => { if (child.external_url) { window.open(child.external_url, "_blank");