diff --git a/ui/litellm-dashboard/src/app/page.tsx b/ui/litellm-dashboard/src/app/page.tsx index c56dd5a682a..a667cbcd9d2 100644 --- a/ui/litellm-dashboard/src/app/page.tsx +++ b/ui/litellm-dashboard/src/app/page.tsx @@ -20,17 +20,15 @@ import Usage from "../components/usage"; import CacheDashboard from "@/components/cache_dashboard"; import { jwtDecode } from "jwt-decode"; import { Typography } from "antd"; -import { setGlobalLitellmHeaderName } from "../components/networking" +import { setGlobalLitellmHeaderName } from "../components/networking"; function getCookie(name: string) { - console.log("COOKIES", document.cookie) const cookieValue = document.cookie - .split('; ') - .find(row => row.startsWith(name + '=')); - return cookieValue ? cookieValue.split('=')[1] : null; + .split("; ") + .find((row) => row.startsWith(name + "=")); + return cookieValue ? cookieValue.split("=")[1] : null; } - function formatUserRole(userRole: string) { if (!userRole) { return "Undefined Role"; @@ -68,7 +66,8 @@ const CreateKeyPage = () => { const { Title, Paragraph } = Typography; const [userRole, setUserRole] = useState(""); const [premiumUser, setPremiumUser] = useState(false); - const [disabledPersonalKeyCreation, setDisabledPersonalKeyCreation] = useState(false); + const [disabledPersonalKeyCreation, setDisabledPersonalKeyCreation] = + useState(false); const [userEmail, setUserEmail] = useState(null); const [teams, setTeams] = useState(null); const [keys, setKeys] = useState(null); @@ -80,244 +79,244 @@ const CreateKeyPage = () => { const [showSSOBanner, setShowSSOBanner] = useState(true); const searchParams = useSearchParams()!; const [modelData, setModelData] = useState({ data: [] }); + const [token, setToken] = useState(null); + const userID = searchParams.get("userID"); const invitation_id = searchParams.get("invitation_id"); - const token = getCookie('token'); // Get page from URL, default to 'api-keys' if not present const [page, setPage] = useState(() => { - return searchParams.get('page') || 'api-keys'; + return searchParams.get("page") || "api-keys"; }); // Custom setPage function that updates URL const updatePage = (newPage: string) => { // Update URL without full page reload const newSearchParams = new URLSearchParams(searchParams); - newSearchParams.set('page', newPage); - + newSearchParams.set("page", newPage); + // Use Next.js router to update URL - window.history.pushState( - null, - '', - `?${newSearchParams.toString()}` - ); - + window.history.pushState(null, "", `?${newSearchParams.toString()}`); + setPage(newPage); }; const [accessToken, setAccessToken] = useState(null); useEffect(() => { - if (token) { - const decoded = jwtDecode(token) as { [key: string]: any }; - if (decoded) { - // cast decoded to dictionary - console.log("Decoded token:", decoded); + const token = getCookie("token"); + setToken(token); + }, []); - console.log("Decoded key:", decoded.key); - // set accessToken - setAccessToken(decoded.key); + useEffect(() => { + if (!token) { + return; + } - setDisabledPersonalKeyCreation(decoded.disabled_non_admin_personal_key_creation); + const decoded = jwtDecode(token) as { [key: string]: any }; + if (decoded) { + // cast decoded to dictionary + console.log("Decoded token:", decoded); - // check if userRole is defined - if (decoded.user_role) { - const formattedUserRole = formatUserRole(decoded.user_role); - console.log("Decoded user_role:", formattedUserRole); - setUserRole(formattedUserRole); - if (formattedUserRole == "Admin Viewer") { - setPage("usage"); - } - } else { - console.log("User role not defined"); + console.log("Decoded key:", decoded.key); + // set accessToken + setAccessToken(decoded.key); + + setDisabledPersonalKeyCreation( + decoded.disabled_non_admin_personal_key_creation, + ); + + // check if userRole is defined + if (decoded.user_role) { + const formattedUserRole = formatUserRole(decoded.user_role); + console.log("Decoded user_role:", formattedUserRole); + setUserRole(formattedUserRole); + if (formattedUserRole == "Admin Viewer") { + setPage("usage"); } + } else { + console.log("User role not defined"); + } - if (decoded.user_email) { - setUserEmail(decoded.user_email); - } else { - console.log(`User Email is not set ${decoded}`); - } + if (decoded.user_email) { + setUserEmail(decoded.user_email); + } else { + console.log(`User Email is not set ${decoded}`); + } - if (decoded.login_method) { - setShowSSOBanner( - decoded.login_method == "username_password" ? true : false - ); - } else { - console.log(`User Email is not set ${decoded}`); - } + if (decoded.login_method) { + setShowSSOBanner( + decoded.login_method == "username_password" ? true : false, + ); + } else { + console.log(`User Email is not set ${decoded}`); + } - if (decoded.premium_user) { - setPremiumUser(decoded.premium_user); - } + if (decoded.premium_user) { + setPremiumUser(decoded.premium_user); + } - if (decoded.auth_header_name) { - setGlobalLitellmHeaderName(decoded.auth_header_name); - } - + if (decoded.auth_header_name) { + setGlobalLitellmHeaderName(decoded.auth_header_name); } } }, [token]); return ( Loading...}> - { - invitation_id ? ( - - ) : ( -
- -
-
+ ) : ( +
+ +
+
-
+ /> +
- {page == "api-keys" ? ( - - ) : page == "models" ? ( - - ) : page == "llm-playground" ? ( - - ) : page == "users" ? ( - - ) : page == "teams" ? ( - - ) : page == "organizations" ? ( - - ) : page == "admin-panel" ? ( - - ) : page == "api_ref" ? ( - - ) : page == "settings" ? ( - - ) : page == "budgets" ? ( - - ) : page == "general-settings" ? ( - - ) : page == "model-hub" ? ( - - ) : page == "caching" ? ( - - ) : page == "pass-through-settings" ? ( - - ) : ( - - )} + {page == "api-keys" ? ( + + ) : page == "models" ? ( + + ) : page == "llm-playground" ? ( + + ) : page == "users" ? ( + + ) : page == "teams" ? ( + + ) : page == "organizations" ? ( + + ) : page == "admin-panel" ? ( + + ) : page == "api_ref" ? ( + + ) : page == "settings" ? ( + + ) : page == "budgets" ? ( + + ) : page == "general-settings" ? ( + + ) : page == "model-hub" ? ( + + ) : page == "caching" ? ( + + ) : page == "pass-through-settings" ? ( + + ) : ( + + )} +
-
- ) - } - + )} ); }; diff --git a/ui/litellm-dashboard/src/components/create_user_button.tsx b/ui/litellm-dashboard/src/components/create_user_button.tsx index ade39699b55..380396ad238 100644 --- a/ui/litellm-dashboard/src/components/create_user_button.tsx +++ b/ui/litellm-dashboard/src/components/create_user_button.tsx @@ -53,11 +53,9 @@ const Createuser: React.FC = ({ useState(null); const router = useRouter(); const isLocal = process.env.NODE_ENV === "development"; - if (isLocal != true) { - console.log = function() {}; - } + const [baseUrl, setBaseUrl] = useState( - isLocal ? "http://localhost:4000" : "" + isLocal ? "http://localhost:4000" : "", ); // get all models useEffect(() => { @@ -67,7 +65,7 @@ const Createuser: React.FC = ({ const modelDataResponse = await modelAvailableCall( accessToken, userID, - userRole + userRole, ); // Assuming modelDataResponse.data contains an array of model objects with a 'model_name' property const availableModels = []; @@ -81,27 +79,26 @@ const Createuser: React.FC = ({ // Assuming modelDataResponse.data contains an array of model names setUserModels(availableModels); - // get ui settings + // get ui settings const uiSettingsResponse = await getProxyUISettings(accessToken); console.log("uiSettingsResponse:", uiSettingsResponse); - + setUISettings(uiSettingsResponse); } catch (error) { console.error("Error fetching model data:", error); } }; - - fetchData(); // Call the function to fetch model data when the component mounts }, []); // Empty dependency array to run only once useEffect(() => { - if (router) { - const { protocol, host } = window.location; - const baseUrl = `${protocol}/${host}`; - setBaseUrl(baseUrl); + if (!router) { + return; } + + const base = new URL("/", window.location.href); + setBaseUrl(base.toString()); }, [router]); const handleOk = () => { setIsModalVisible(false); @@ -123,7 +120,7 @@ const Createuser: React.FC = ({ console.log("user create Response:", response); setApiuser(response["key"]); const user_id = response.data?.user_id || response.user_id; - + // only do invite link flow if sso is not enabled if (!uiSettings?.SSO_ENABLED) { invitationCreateCall(accessToken, user_id).then((data) => { @@ -132,7 +129,7 @@ const Createuser: React.FC = ({ setIsInvitationLinkModalVisible(true); }); } else { - // create an InvitationLink Object for this user for the SSO flow + // create an InvitationLink Object for this user for the SSO flow // for SSO the invite link is the proxy base url since the User just needs to login const invitationLink: InvitationLink = { id: crypto.randomUUID(), // Generate a unique ID @@ -198,7 +195,7 @@ const Createuser: React.FC = ({

- ) + ), )} diff --git a/ui/litellm-dashboard/src/components/onboarding_link.tsx b/ui/litellm-dashboard/src/components/onboarding_link.tsx index 78f0dff8acc..36aa4fc0a41 100644 --- a/ui/litellm-dashboard/src/components/onboarding_link.tsx +++ b/ui/litellm-dashboard/src/components/onboarding_link.tsx @@ -1,16 +1,8 @@ -import React, { useState, useEffect } from "react"; -import { - Button as Button2, - Modal, - Form, - Input, - Select as Select2, - InputNumber, - message, - Typography, -} from "antd"; +import React from "react"; +import { Modal, message, Typography } from "antd"; import { CopyToClipboard } from "react-copy-to-clipboard"; import { Text, Button } from "@tremor/react"; + export interface InvitationLink { id: string; user_id: string; @@ -33,12 +25,12 @@ interface OnboardingProps { invitationLinkData: InvitationLink | null; } -const OnboardingModal: React.FC = ({ +export default function OnboardingModal({ isInvitationLinkModalVisible, setIsInvitationLinkModalVisible, baseUrl, invitationLinkData, -}) => { +}: OnboardingProps) { const { Title, Paragraph } = Typography; const handleInvitationOk = () => { setIsInvitationLinkModalVisible(false); @@ -50,9 +42,9 @@ const OnboardingModal: React.FC = ({ const getInvitationUrl = () => { if (invitationLinkData?.has_user_setup_sso) { - return `${baseUrl}/ui`; + return new URL("/ui", baseUrl).toString(); } - return `${baseUrl}/ui?invitation_id=${invitationLinkData?.id}`; + return new URL(`/ui?invitation_id=${invitationLinkData?.id}`, baseUrl).toString(); }; return ( @@ -64,7 +56,6 @@ const OnboardingModal: React.FC = ({ onOk={handleInvitationOk} onCancel={handleInvitationCancel} > - {/* {JSON.stringify(invitationLinkData)} */} Copy and send the generated link to onboard this user to the proxy. @@ -75,11 +66,10 @@ const OnboardingModal: React.FC = ({
Invitation Link - {getInvitationUrl()} + {getInvitationUrl()}
-
message.success("Copied!")} @@ -89,6 +79,4 @@ const OnboardingModal: React.FC = ({
); -}; - -export default OnboardingModal; +}