From 04662c653f59ff67c5b2f73a0e4a37f53598ff80 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Fri, 14 Mar 2025 09:12:30 -0700 Subject: [PATCH 1/3] ui - instantly show changes to create key table --- .../src/components/all_keys_table.tsx | 18 ++++++++++++++++++ .../src/components/create_key_button.tsx | 5 +++++ .../src/components/view_key_table.tsx | 13 +++++++++++++ 3 files changed, 36 insertions(+) diff --git a/ui/litellm-dashboard/src/components/all_keys_table.tsx b/ui/litellm-dashboard/src/components/all_keys_table.tsx index 75820d093b..b0313c241f 100644 --- a/ui/litellm-dashboard/src/components/all_keys_table.tsx +++ b/ui/litellm-dashboard/src/components/all_keys_table.tsx @@ -32,6 +32,7 @@ interface AllKeysTableProps { userRole: string | null; organizations: Organization[] | null; setCurrentOrg: React.Dispatch>; + refresh?: () => void; } // Define columns similar to our logs table @@ -98,6 +99,7 @@ export function AllKeysTable({ userRole, organizations, setCurrentOrg, + refresh, }: AllKeysTableProps) { const [selectedKeyId, setSelectedKeyId] = useState(null); const [userList, setUserList] = useState([]); @@ -131,6 +133,22 @@ export function AllKeysTable({ } }, [accessToken, keys]); + // Add a useEffect to call refresh when a key is created + useEffect(() => { + if (refresh) { + const handleStorageChange = () => { + refresh(); + }; + + // Listen for storage events that might indicate a key was created + window.addEventListener('storage', handleStorageChange); + + return () => { + window.removeEventListener('storage', handleStorageChange); + }; + } + }, [refresh]); + const columns: ColumnDef[] = [ { id: "expander", diff --git a/ui/litellm-dashboard/src/components/create_key_button.tsx b/ui/litellm-dashboard/src/components/create_key_button.tsx index 205d4226dc..a641596cb3 100644 --- a/ui/litellm-dashboard/src/components/create_key_button.tsx +++ b/ui/litellm-dashboard/src/components/create_key_button.tsx @@ -266,6 +266,11 @@ const CreateKey: React.FC = ({ message.success("API Key Created"); form.resetFields(); localStorage.removeItem("userData" + userID); + + // Add this line to refresh the keys list immediately + if (window.refreshKeysList) { + window.refreshKeysList(); + } } catch (error) { console.log("error in create key:", error); message.error(`Error creating the key: ${error}`); diff --git a/ui/litellm-dashboard/src/components/view_key_table.tsx b/ui/litellm-dashboard/src/components/view_key_table.tsx index 22e786dcbc..968b7cf4c8 100644 --- a/ui/litellm-dashboard/src/components/view_key_table.tsx +++ b/ui/litellm-dashboard/src/components/view_key_table.tsx @@ -182,6 +182,11 @@ const ViewKeyTable: React.FC = ({ accessToken, }); + // Make refresh function available globally so CreateKey can access it + if (typeof window !== 'undefined') { + window.refreshKeysList = refresh; + } + const handlePageChange = (newPage: number) => { refresh({ page: newPage }); }; @@ -421,6 +426,7 @@ const ViewKeyTable: React.FC = ({ userRole={userRole} organizations={organizations} setCurrentOrg={setCurrentOrg} + refresh={refresh} /> {isDeleteModalOpen && ( @@ -619,4 +625,11 @@ const ViewKeyTable: React.FC = ({ ); }; +// Add this type declaration at the top of the file to avoid TypeScript errors +declare global { + interface Window { + refreshKeysList?: () => void; + } +} + export default ViewKeyTable; From 43b7460968ee8fcbdfce692a15ddb9b0018d0207 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Fri, 14 Mar 2025 09:18:22 -0700 Subject: [PATCH 2/3] ui - instantly show new ui keys --- .../src/components/create_key_button.tsx | 18 +++++++++++---- .../components/key_team_helpers/key_list.tsx | 23 +++++++++++++++---- .../src/components/view_key_table.tsx | 11 ++++++--- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/ui/litellm-dashboard/src/components/create_key_button.tsx b/ui/litellm-dashboard/src/components/create_key_button.tsx index a641596cb3..cce52ab3d9 100644 --- a/ui/litellm-dashboard/src/components/create_key_button.tsx +++ b/ui/litellm-dashboard/src/components/create_key_button.tsx @@ -260,17 +260,25 @@ const CreateKey: React.FC = ({ const response = await keyCreateCall(accessToken, userID, formValues); console.log("key create Response:", response); - setData((prevData) => (prevData ? [...prevData, response] : [response])); // Check if prevData is null + + // Update the data state in this component + setData((prevData) => (prevData ? [...prevData, response] : [response])); + + // Also directly update the keys list in AllKeysTable without an API call + if (window.addNewKeyToList) { + window.addNewKeyToList(response); + } + setApiKey(response["key"]); setSoftBudget(response["soft_budget"]); message.success("API Key Created"); form.resetFields(); localStorage.removeItem("userData" + userID); - // Add this line to refresh the keys list immediately - if (window.refreshKeysList) { - window.refreshKeysList(); - } + // We don't need to call refresh anymore since we're directly updating the state + // if (window.refreshKeysList) { + // window.refreshKeysList(); + // } } catch (error) { console.log("error in create key:", error); message.error(`Error creating the key: ${error}`); diff --git a/ui/litellm-dashboard/src/components/key_team_helpers/key_list.tsx b/ui/litellm-dashboard/src/components/key_team_helpers/key_list.tsx index fd9d1ef245..4c2a18d2b5 100644 --- a/ui/litellm-dashboard/src/components/key_team_helpers/key_list.tsx +++ b/ui/litellm-dashboard/src/components/key_team_helpers/key_list.tsx @@ -100,6 +100,7 @@ isLoading: boolean; error: Error | null; pagination: PaginationData; refresh: (params?: Record) => Promise; +setKeys: (newKeysOrUpdater: KeyResponse[] | ((prevKeys: KeyResponse[]) => KeyResponse[])) => void; } const useKeyList = ({ @@ -149,16 +150,30 @@ const useKeyList = ({ console.log("selectedTeam", selectedTeam, "currentOrg", currentOrg, "accessToken", accessToken); }, [selectedTeam, currentOrg, accessToken]); + const setKeys = (newKeysOrUpdater: KeyResponse[] | ((prevKeys: KeyResponse[]) => KeyResponse[])) => { + setKeyData(prevData => { + const newKeys = typeof newKeysOrUpdater === 'function' + ? newKeysOrUpdater(prevData.keys) + : newKeysOrUpdater; + + return { + ...prevData, + keys: newKeys + }; + }); + }; + return { keys: keyData.keys, isLoading, error, pagination: { - currentPage: keyData.current_page, - totalPages: keyData.total_pages, - totalCount: keyData.total_count + currentPage: keyData.current_page, + totalPages: keyData.total_pages, + totalCount: keyData.total_count }, - refresh: fetchKeys + refresh: fetchKeys, + setKeys }; }; diff --git a/ui/litellm-dashboard/src/components/view_key_table.tsx b/ui/litellm-dashboard/src/components/view_key_table.tsx index 968b7cf4c8..f3661c8c64 100644 --- a/ui/litellm-dashboard/src/components/view_key_table.tsx +++ b/ui/litellm-dashboard/src/components/view_key_table.tsx @@ -176,15 +176,19 @@ const ViewKeyTable: React.FC = ({ // Build a memoized filters object for the backend call. // Pass filters into the hook so the API call includes these query parameters. - const { keys, isLoading, error, pagination, refresh } = useKeyList({ + const { keys, isLoading, error, pagination, refresh, setKeys } = useKeyList({ selectedTeam, currentOrg, accessToken, }); - // Make refresh function available globally so CreateKey can access it + // Make both refresh and addKey functions available globally if (typeof window !== 'undefined') { window.refreshKeysList = refresh; + window.addNewKeyToList = (newKey) => { + // Add the new key to the keys list without making an API call + setKeys((prevKeys) => [newKey, ...prevKeys]); + }; } const handlePageChange = (newPage: number) => { @@ -625,10 +629,11 @@ const ViewKeyTable: React.FC = ({ ); }; -// Add this type declaration at the top of the file to avoid TypeScript errors +// Update the type declaration to include the new function declare global { interface Window { refreshKeysList?: () => void; + addNewKeyToList?: (newKey: any) => void; } } From 558c37ca06fe61ce1312a9a69df5f14826d29bf5 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Fri, 14 Mar 2025 09:18:37 -0700 Subject: [PATCH 3/3] fix ui --- ui/litellm-dashboard/src/components/create_key_button.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ui/litellm-dashboard/src/components/create_key_button.tsx b/ui/litellm-dashboard/src/components/create_key_button.tsx index cce52ab3d9..c94acc4486 100644 --- a/ui/litellm-dashboard/src/components/create_key_button.tsx +++ b/ui/litellm-dashboard/src/components/create_key_button.tsx @@ -274,11 +274,7 @@ const CreateKey: React.FC = ({ message.success("API Key Created"); form.resetFields(); localStorage.removeItem("userData" + userID); - - // We don't need to call refresh anymore since we're directly updating the state - // if (window.refreshKeysList) { - // window.refreshKeysList(); - // } + } catch (error) { console.log("error in create key:", error); message.error(`Error creating the key: ${error}`);