From 06ee35f74cb3bbd7edd2b028b000561ca87a0e2f Mon Sep 17 00:00:00 2001 From: tanjiro <56165694+NANDINI-star@users.noreply.github.com> Date: Wed, 13 Aug 2025 22:32:57 +0900 Subject: [PATCH 1/2] replace text error with json error --- .../src/components/networking.tsx | 1015 +++++++++++------ 1 file changed, 636 insertions(+), 379 deletions(-) diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx index 93ae040c86..81829eef7c 100644 --- a/ui/litellm-dashboard/src/components/networking.tsx +++ b/ui/litellm-dashboard/src/components/networking.tsx @@ -368,12 +368,13 @@ export const modelCreateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - const errorMsg = errorData || "Network response was not ok"; - message.error(errorMsg); - throw new Error(errorMsg); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); @@ -409,11 +410,13 @@ export const modelSettingsCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -442,12 +445,13 @@ export const modelDeleteCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -483,11 +487,12 @@ export const budgetDeleteCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -518,12 +523,13 @@ export const budgetCreateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -557,12 +563,13 @@ export const budgetUpdateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -593,12 +600,13 @@ export const invitationCreateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -632,12 +640,13 @@ export const invitationClaimCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -667,11 +676,13 @@ export const alertingSettingsCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -889,11 +900,13 @@ export const keyDeleteCall = async (accessToken: String, user_key: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success("API Key Deleted"); @@ -925,11 +938,13 @@ export const userDeleteCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success("User(s) Deleted"); @@ -956,10 +971,12 @@ export const teamDeleteCall = async (accessToken: String, teamID: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -1050,11 +1067,13 @@ export const userListCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = (await response.json()) as UserListResponse; console.log("/user/list API Response:", data); return data; @@ -1111,11 +1130,13 @@ export const userInfoCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -1144,11 +1165,13 @@ export const teamInfoCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -1216,11 +1239,13 @@ export const v2TeamListCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("/v2/team/list API Response:", data); return data; @@ -1276,11 +1301,13 @@ export const teamListCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("/team/list API Response:", data); return data; @@ -1309,11 +1336,13 @@ export const availableTeamListCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("/team/available_teams API Response:", data); return data; @@ -1339,11 +1368,13 @@ export const organizationListCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -1373,11 +1404,13 @@ export const organizationInfoCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -1421,12 +1454,13 @@ export const organizationCreateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -1459,11 +1493,12 @@ export const organizationUpdateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Update Team Response:", data); return data; @@ -1530,11 +1565,13 @@ export const transformRequestCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -1575,11 +1612,13 @@ export const userDailyActivityCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -1624,11 +1663,13 @@ export const tagDailyActivityCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -1674,11 +1715,13 @@ export const teamDailyActivityCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -1704,11 +1747,13 @@ export const getTotalSpendCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; // Handle success - you might want to update some state or UI based on the created key @@ -1736,11 +1781,13 @@ export const getOnboardingCredentials = async (inviteUUID: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; // Handle success - you might want to update some state or UI based on the created key @@ -1774,10 +1821,12 @@ export const claimOnboardingToken = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -1808,11 +1857,13 @@ export const regenerateKeyCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Regenerate key Response:", data); return data; @@ -1898,10 +1949,13 @@ export const modelInfoV1Call = async (accessToken: String, modelId: String) => { }); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("modelInfoV1Call:", data); return data; @@ -1941,10 +1995,13 @@ export const modelHubCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("modelHubCall:", data); //message.info("Received model data"); @@ -1972,10 +2029,13 @@ export const getAllowedIPs = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - throw new Error(`Network response was not ok: ${errorData}`); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("getAllowedIPs:", data); return data.data; // Assuming the API returns { data: [...] } @@ -2002,10 +2062,13 @@ export const addAllowedIP = async (accessToken: String, ip: String) => { }); if (!response.ok) { - const errorData = await response.text(); - throw new Error(`Network response was not ok: ${errorData}`); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("addAllowedIP:", data); return data; @@ -2032,10 +2095,13 @@ export const deleteAllowedIP = async (accessToken: String, ip: String) => { }); if (!response.ok) { - const errorData = await response.text(); - throw new Error(`Network response was not ok: ${errorData}`); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("deleteAllowedIP:", data); return data; @@ -2073,10 +2139,12 @@ export const modelMetricsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); // message.info("Received model data"); return data; @@ -2112,10 +2180,12 @@ export const streamingModelMetricsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); // message.info("Received model data"); return data; @@ -2157,10 +2227,12 @@ export const modelMetricsSlowResponsesCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); // message.info("Received model data"); return data; @@ -2201,10 +2273,12 @@ export const modelExceptionsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); // message.info("Received model data"); return data; @@ -2227,10 +2301,12 @@ export const updateUsefulLinksCall = async (accessToken: String, useful_links: R body: JSON.stringify({ useful_links: useful_links }), }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + return await response.json(); } catch (error) { console.error("Failed to create key:", error); @@ -2281,11 +2357,13 @@ export const modelAvailableCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -2310,11 +2388,13 @@ export const keySpendLogsCall = async (accessToken: String, token: String) => { }, }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2338,11 +2418,13 @@ export const teamSpendLogsCall = async (accessToken: String) => { }, }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2381,10 +2463,13 @@ export const tagsSpendLogsCall = async ( }, }); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2409,10 +2494,13 @@ export const allTagNamesCall = async (accessToken: String) => { }, }); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2437,10 +2525,13 @@ export const allEndUsersCall = async (accessToken: String) => { }, }); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2474,10 +2565,12 @@ export const userFilterUICall = async ( }, }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + return await response.json(); } catch (error) { console.error("Failed to create key:", error); @@ -2510,11 +2603,13 @@ export const userSpendLogsCall = async ( }, }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success("Spend Logs received"); @@ -2571,11 +2666,13 @@ export const uiSpendLogsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Spend Logs Response:", data); return data; @@ -2600,11 +2697,13 @@ export const adminSpendLogsCall = async (accessToken: String) => { }, }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success("Spend Logs received"); @@ -2630,11 +2729,13 @@ export const adminTopKeysCall = async (accessToken: String) => { }, }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success("Spend Logs received"); @@ -2681,11 +2782,13 @@ export const adminTopEndUsersCall = async ( const response = await fetch(url, requestOptions); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success("Top End users received"); @@ -2725,11 +2828,13 @@ export const adminspendByProvider = async ( const response = await fetch(url, requestOptions); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2763,9 +2868,12 @@ export const adminGlobalActivity = async ( const response = await fetch(url, requestOptions); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2799,9 +2907,12 @@ export const adminGlobalCacheActivity = async ( const response = await fetch(url, requestOptions); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2835,9 +2946,12 @@ export const adminGlobalActivityPerModel = async ( const response = await fetch(url, requestOptions); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2876,9 +2990,12 @@ export const adminGlobalActivityExceptions = async ( const response = await fetch(url, requestOptions); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2917,9 +3034,12 @@ export const adminGlobalActivityExceptionsPerDeployment = async ( const response = await fetch(url, requestOptions); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -2944,11 +3064,13 @@ export const adminTopModelsCall = async (accessToken: String) => { }, }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success("Top Models received"); @@ -3160,11 +3282,13 @@ export const keyListCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("/team/list API Response:", data); return data; @@ -3187,11 +3311,13 @@ export const spendUsersCall = async (accessToken: String, userID: String) => { }, }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -3225,10 +3351,12 @@ export const userRequestModelCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success(""); @@ -3255,10 +3383,12 @@ export const userGetRequesedtModelsCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success(""); @@ -3313,11 +3443,13 @@ export const userDailyActivityAggregatedCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -3344,10 +3476,12 @@ export const userGetAllUsersCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success("Got all users"); @@ -3373,9 +3507,12 @@ export const getPossibleUserRoles = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = (await response.json()) as Record< string, Record @@ -3417,12 +3554,13 @@ export const teamCreateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -3462,12 +3600,13 @@ export const credentialCreateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -3495,11 +3634,13 @@ export const credentialListCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("/credentials API Response:", data); return data; @@ -3535,11 +3676,13 @@ export const credentialGetCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("/credentials API Response:", data); return data; @@ -3568,10 +3711,12 @@ export const credentialDeleteCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); return data; @@ -3614,12 +3759,13 @@ export const credentialUpdateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -4001,12 +4147,13 @@ export const teamMemberDeleteCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -4082,12 +4229,13 @@ export const organizationMemberDeleteCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -4121,12 +4269,13 @@ export const organizationMemberUpdateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("API Response:", data); return data; @@ -4160,12 +4309,13 @@ export const userUpdateUserCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = (await response.json()) as { user_id: string; data: UserInfo; @@ -4227,12 +4377,13 @@ export const userBulkUpdateUserCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = (await response.json()) as { results: Array<{ user_id?: string; @@ -4278,11 +4429,13 @@ export const PredictedSpendLogsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log(data); //message.success("Predicted Logs received"); @@ -4382,11 +4535,13 @@ export const getBudgetList = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -4415,11 +4570,13 @@ export const getBudgetSettings = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -4453,11 +4610,13 @@ export const getCallbacksCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -4484,11 +4643,13 @@ export const getGeneralSettingsCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -4515,11 +4676,13 @@ export const getPassThroughEndpointsCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -4549,10 +4712,13 @@ export const getConfigFieldSetting = async ( }); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; // Handle success - you might want to update some state or UI based on the created key @@ -4587,11 +4753,13 @@ export const updatePassThroughFieldSetting = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); message.success("Successfully updated value!"); @@ -4628,11 +4796,13 @@ export const createPassThroughEndpoint = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -4669,11 +4839,13 @@ export const updateConfigFieldSetting = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); message.success("Successfully updated value!"); @@ -4709,11 +4881,13 @@ export const deleteConfigFieldSetting = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); message.success("Field reset on proxy"); return data; @@ -4743,11 +4917,13 @@ export const deletePassThroughEndpointsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -4781,11 +4957,13 @@ export const setCallbacksCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -4813,11 +4991,13 @@ export const healthCheckCall = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -4849,10 +5029,13 @@ export const individualModelHealthCheckCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - throw new Error(errorData || "Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -4991,10 +5174,13 @@ export const getProxyUISettings = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); //message.info("Received model data"); return data; @@ -5019,11 +5205,13 @@ export const getGuardrailsList = async (accessToken: String) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -5046,11 +5234,13 @@ export const getPromptsList = async (accessToken: String) : Promise { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Fetched SSO settings:", data); return data; @@ -5394,11 +5600,13 @@ export const fetchMCPServers = async (accessToken: string) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Fetched MCP servers:", data); return data; @@ -5426,11 +5634,13 @@ export const fetchMCPAccessGroups = async (accessToken: string) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Fetched MCP access groups:", data); return data.access_groups || []; @@ -5463,10 +5673,10 @@ export const createMCPServer = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - console.error("Error response from the server:", errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } const data = await response.json(); @@ -5497,10 +5707,12 @@ export const updateMCPServer = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + return await response.json(); } catch (error) { console.error("Failed to update MCP server:", error); @@ -5525,10 +5737,12 @@ export const deleteMCPServer = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + } catch (error) { console.error("Failed to delete key:", error); throw error; @@ -5847,11 +6061,13 @@ export const getDefaultTeamSettings = async (accessToken: string) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Fetched default team settings:", data); return data; @@ -5883,11 +6099,13 @@ export const updateDefaultTeamSettings = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Updated default team settings:", data); message.success("Default team settings updated successfully"); @@ -5916,11 +6134,13 @@ export const getTeamPermissionsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Team permissions response:", data); return data; @@ -5953,11 +6173,13 @@ export const teamPermissionsUpdateCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Team permissions response:", data); return data; @@ -5988,11 +6210,13 @@ export const sessionSpendLogsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -6430,11 +6654,13 @@ export const getSSOSettings = async (accessToken: string) => { }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Fetched SSO configuration:", data); return data; @@ -6466,11 +6692,13 @@ export const updateSSOSettings = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); console.log("Updated SSO configuration:", data); return data; @@ -6513,11 +6741,13 @@ export const uiAuditLogsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -6586,11 +6816,13 @@ export const updatePassThroughEndpoint = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); message.success("Pass through endpoint updated successfully"); return data; @@ -6618,11 +6850,13 @@ export const getPassThroughEndpointInfo = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); const endpoints = data["endpoints"]; @@ -6661,11 +6895,13 @@ export const deleteCallback = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -6893,11 +7129,13 @@ export const userAgentAnalyticsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -6956,11 +7194,13 @@ export const tagDauCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -7018,11 +7258,13 @@ export const tagWauCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -7080,11 +7322,13 @@ export const tagMauCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -7113,11 +7357,13 @@ export const tagDistinctCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -7174,11 +7420,13 @@ export const userAgentSummaryCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -7227,11 +7475,13 @@ export const perUserAnalyticsCall = async ( }); if (!response.ok) { - const errorData = await response.text(); - handleError(errorData); - throw new Error("Network response was not ok"); + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); } + const data = await response.json(); return data; } catch (error) { @@ -7240,3 +7490,10 @@ export const perUserAnalyticsCall = async ( } }; +const deriveErrorMessage = (errorData: any): string => { + return (errorData?.error && (errorData.error.message || errorData.error)) || + errorData?.message || + errorData?.detail || + errorData?.error || + JSON.stringify(errorData); +}; From be109c2180a9586444a6dc99677ed525097336b9 Mon Sep 17 00:00:00 2001 From: tanjiro <56165694+NANDINI-star@users.noreply.github.com> Date: Wed, 13 Aug 2025 23:05:11 +0900 Subject: [PATCH 2/2] put the error toast on the ui --- ui/litellm-dashboard/src/components/SCIM.tsx | 5 +++-- .../src/components/SSOModals.tsx | 8 +++---- .../src/components/SSOSettings.tsx | 4 ++-- .../src/components/TeamSSOSettings.tsx | 5 +++-- .../src/components/UIAccessControlForm.tsx | 5 +++-- .../src/components/add_fallbacks.tsx | 5 +++-- .../add_model/add_auto_router_tab.tsx | 13 ++++++------ .../handle_add_auto_router_submit.tsx | 3 ++- .../add_model/handle_add_model_submit.tsx | 15 +++++++------ .../src/components/add_pass_through.tsx | 3 ++- .../src/components/admins.tsx | 13 ++++++------ .../src/components/budgets/budget_modal.tsx | 3 ++- .../components/budgets/edit_budget_modal.tsx | 3 ++- .../components/bulk_create_users_button.tsx | 3 ++- .../src/components/bulk_edit_user.tsx | 7 ++++--- .../src/components/chat_ui.tsx | 9 ++++---- .../chat_ui/llm_calls/anthropic_messages.tsx | 6 +++--- .../chat_ui/llm_calls/fetch_mcp_tools.tsx | 3 ++- .../chat_ui/llm_calls/image_edits.tsx | 3 ++- .../chat_ui/llm_calls/image_generation.tsx | 3 ++- .../chat_ui/llm_calls/responses_api.tsx | 3 ++- .../src/components/cloudzero_export_modal.tsx | 19 +++++++++-------- .../common_components/ModelAliasManager.tsx | 9 ++++---- .../src/components/create_user_button.tsx | 3 ++- .../edit_auto_router_modal.tsx | 5 +++-- .../src/components/email_settings.tsx | 10 ++++----- .../src/components/general_settings.tsx | 8 +++---- .../components/generic_key_value_manager.tsx | 5 +++-- .../src/components/guardrails.tsx | 3 ++- .../guardrails/add_guardrail_form.tsx | 9 ++++---- .../guardrails/edit_guardrail_form.tsx | 7 ++++--- .../components/guardrails/guardrail_info.tsx | 5 +++-- .../src/components/make_model_public_form.tsx | 7 ++++--- .../components/mcp_tools/ToolTestPanel.tsx | 6 +++--- .../mcp_tools/create_mcp_server.tsx | 5 +++-- .../components/mcp_tools/mcp_server_edit.tsx | 3 ++- .../src/components/mcp_tools/mcp_tools.tsx | 1 + .../src/components/model_dashboard.tsx | 7 ++++--- .../components/model_group_alias_settings.tsx | 11 +++++----- .../src/components/model_info_view.tsx | 7 ++++--- .../src/components/networking.tsx | 5 +++-- .../organisms/create_key_button.tsx | 5 +++-- .../organization/organization_view.tsx | 11 +++++----- .../src/components/pass_through_info.tsx | 7 ++++--- .../src/components/pass_through_settings.tsx | 3 ++- .../src/components/price_data_reload.tsx | 21 ++++++++++--------- .../src/components/prompts.tsx | 4 ++-- .../components/prompts/add_prompt_form.tsx | 11 +++++----- .../src/components/prompts/prompt_info.tsx | 5 +++-- .../src/components/provider_info_helpers.tsx | 1 + .../src/components/tag_management/index.tsx | 9 ++++---- .../components/tag_management/tag_info.tsx | 5 +++-- .../src/components/team/available_teams.tsx | 3 ++- .../src/components/team/edit_membership.tsx | 3 ++- .../components/team/member_permissions.tsx | 5 +++-- .../src/components/team/team_info.tsx | 11 +++++----- ui/litellm-dashboard/src/components/teams.tsx | 2 +- .../src/components/transform_request.tsx | 7 ++++--- .../src/components/ui_theme_settings.tsx | 5 +++-- .../components/useful_links_management.tsx | 11 +++++----- .../VectorStoreForm.tsx | 5 +++-- .../VectorStoreTester.tsx | 3 ++- .../vector_store_management/index.tsx | 7 ++++--- .../vector_store_info.tsx | 7 ++++--- .../view_logs/RequestResponsePanel.tsx | 5 +++-- .../src/components/view_users.tsx | 9 ++++---- .../components/view_users/user_info_view.tsx | 11 +++++----- ui/litellm-dashboard/src/utils/dataUtils.ts | 3 ++- 68 files changed, 247 insertions(+), 189 deletions(-) diff --git a/ui/litellm-dashboard/src/components/SCIM.tsx b/ui/litellm-dashboard/src/components/SCIM.tsx index 21cf16fb77..4a9260a79e 100644 --- a/ui/litellm-dashboard/src/components/SCIM.tsx +++ b/ui/litellm-dashboard/src/components/SCIM.tsx @@ -21,6 +21,7 @@ import { PlusCircleOutlined } from "@ant-design/icons"; import { parseErrorMessage } from "./shared/errorUtils"; +import NotificationManager from "./molecules/notifications_manager"; interface SCIMConfigProps { accessToken: string | null; @@ -51,7 +52,7 @@ const SCIMConfig: React.FC = ({ accessToken, userID, proxySetti const handleCreateSCIMToken = async (values: any) => { if (!accessToken || !userID) { - message.error("You need to be logged in to create a SCIM token"); + NotificationManager.fromBackend("You need to be logged in to create a SCIM token"); return; } @@ -70,7 +71,7 @@ const SCIMConfig: React.FC = ({ accessToken, userID, proxySetti message.success("SCIM token created successfully"); } catch (error: any) { console.error("Error creating SCIM token:", error); - message.error("Failed to create SCIM token: " + parseErrorMessage(error)); + NotificationManager.fromBackend("Failed to create SCIM token: " + parseErrorMessage(error)); } finally { setIsCreatingToken(false); } diff --git a/ui/litellm-dashboard/src/components/SSOModals.tsx b/ui/litellm-dashboard/src/components/SSOModals.tsx index 763242aeb6..f650badf9f 100644 --- a/ui/litellm-dashboard/src/components/SSOModals.tsx +++ b/ui/litellm-dashboard/src/components/SSOModals.tsx @@ -161,7 +161,7 @@ const SSOModals: React.FC = ({ // Enhanced form submission handler const handleFormSubmit = async (formValues: Record) => { if (!accessToken) { - message.error("No access token available"); + NotificationManager.fromBackend("No access token available"); return; } @@ -173,14 +173,14 @@ const SSOModals: React.FC = ({ handleShowInstructions(formValues); } catch (error) { console.error("Failed to save SSO settings:", error); - message.error("Failed to save SSO settings"); + NotificationManager.fromBackend("Failed to save SSO settings"); } }; // Handle clearing SSO settings const handleClearSSO = async () => { if (!accessToken) { - message.error("No access token available"); + NotificationManager.fromBackend("No access token available"); return; } @@ -216,7 +216,7 @@ const SSOModals: React.FC = ({ message.success("SSO settings cleared successfully"); } catch (error) { console.error("Failed to clear SSO settings:", error); - message.error("Failed to clear SSO settings"); + NotificationManager.fromBackend("Failed to clear SSO settings"); } }; diff --git a/ui/litellm-dashboard/src/components/SSOSettings.tsx b/ui/litellm-dashboard/src/components/SSOSettings.tsx index e21d7d1e00..68085b046b 100644 --- a/ui/litellm-dashboard/src/components/SSOSettings.tsx +++ b/ui/litellm-dashboard/src/components/SSOSettings.tsx @@ -56,7 +56,7 @@ const SSOSettings: React.FC = ({ accessToken, possibleUIRoles, } } catch (error) { console.error("Error fetching SSO settings:", error); - message.error("Failed to fetch SSO settings"); + NotificationManager.fromBackend("Failed to fetch SSO settings"); } finally { setLoading(false); } @@ -81,7 +81,7 @@ const SSOSettings: React.FC = ({ accessToken, possibleUIRoles, setIsEditing(false); } catch (error) { console.error("Error updating SSO settings:", error); - message.error("Failed to update settings: " + error); + NotificationManager.fromBackend("Failed to update settings: " + error); } finally { setSaving(false); } diff --git a/ui/litellm-dashboard/src/components/TeamSSOSettings.tsx b/ui/litellm-dashboard/src/components/TeamSSOSettings.tsx index 93e1e98f5c..3c62f0b67e 100644 --- a/ui/litellm-dashboard/src/components/TeamSSOSettings.tsx +++ b/ui/litellm-dashboard/src/components/TeamSSOSettings.tsx @@ -4,6 +4,7 @@ import { Typography, Spin, message, Switch, Select, Form } from "antd"; import { getDefaultTeamSettings, updateDefaultTeamSettings, modelAvailableCall } from "./networking"; import BudgetDurationDropdown, { getBudgetDurationLabel } from "./common_components/budget_duration_dropdown"; import { getModelDisplayName } from "./key_team_helpers/fetch_available_models_team_key"; +import NotificationManager from "./molecules/notifications_manager"; interface TeamSSOSettingsProps { accessToken: string | null; @@ -47,7 +48,7 @@ const TeamSSOSettings: React.FC = ({ accessToken, userID, } } catch (error) { console.error("Error fetching team SSO settings:", error); - message.error("Failed to fetch team settings"); + NotificationManager.fromBackend("Failed to fetch team settings"); } finally { setLoading(false); } @@ -67,7 +68,7 @@ const TeamSSOSettings: React.FC = ({ accessToken, userID, message.success("Default team settings updated successfully"); } catch (error) { console.error("Error updating team settings:", error); - message.error("Failed to update team settings"); + NotificationManager.fromBackend("Failed to update team settings"); } finally { setSaving(false); } diff --git a/ui/litellm-dashboard/src/components/UIAccessControlForm.tsx b/ui/litellm-dashboard/src/components/UIAccessControlForm.tsx index def9bf6bb9..542fc9d9ab 100644 --- a/ui/litellm-dashboard/src/components/UIAccessControlForm.tsx +++ b/ui/litellm-dashboard/src/components/UIAccessControlForm.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react"; import { Form, Button as Button2, Select, message } from "antd"; import { Text, TextInput } from "@tremor/react"; import { getSSOSettings, updateSSOSettings } from "./networking"; +import NotificationManager from "./molecules/notifications_manager"; interface UIAccessControlFormProps { accessToken: string | null; @@ -52,7 +53,7 @@ const UIAccessControlForm: React.FC = ({ accessToken, const handleUIAccessSubmit = async (formValues: Record) => { if (!accessToken) { - message.error("No access token available"); + NotificationManager.fromBackend("No access token available"); return; } @@ -71,7 +72,7 @@ const UIAccessControlForm: React.FC = ({ accessToken, onSuccess(); } catch (error) { console.error("Failed to save UI access settings:", error); - message.error("Failed to save UI access settings"); + NotificationManager.fromBackend("Failed to save UI access settings"); } finally { setLoading(false); } diff --git a/ui/litellm-dashboard/src/components/add_fallbacks.tsx b/ui/litellm-dashboard/src/components/add_fallbacks.tsx index 3ab7bc7e8e..ad27c7df1e 100644 --- a/ui/litellm-dashboard/src/components/add_fallbacks.tsx +++ b/ui/litellm-dashboard/src/components/add_fallbacks.tsx @@ -14,6 +14,7 @@ import { message, } from "antd"; import { fetchAvailableModels, ModelGroup } from "./chat_ui/llm_calls/fetch_models"; +import NotificationManager from "./molecules/notifications_manager"; interface AddFallbacksProps { models?: string[]; @@ -91,10 +92,10 @@ const AddFallbacks: React.FC = ({ // Update routerSettings state setRouterSettings(updatedRouterSettings); } catch (error) { - message.error("Failed to update router settings: " + error, 20); + NotificationManager.fromBackend("Failed to update router settings: " + error); } - message.success("router settings updated successfully"); + NotificationManager.success("router settings updated successfully"); setIsModalVisible(false); form.resetFields(); diff --git a/ui/litellm-dashboard/src/components/add_model/add_auto_router_tab.tsx b/ui/litellm-dashboard/src/components/add_model/add_auto_router_tab.tsx index 863fb3b62b..d8fffc5ba3 100644 --- a/ui/litellm-dashboard/src/components/add_model/add_auto_router_tab.tsx +++ b/ui/litellm-dashboard/src/components/add_model/add_auto_router_tab.tsx @@ -11,6 +11,7 @@ import { all_admin_roles } from "@/utils/roles"; import { handleAddAutoRouterSubmit } from "./handle_add_auto_router_submit"; import { fetchAvailableModels, ModelGroup } from "../chat_ui/llm_calls/fetch_models"; import RouterConfigBuilder from "./router_config_builder"; +import NotificationManager from "../molecules/notifications_manager"; interface AddAutoRouterTabProps { form: FormInstance; @@ -79,12 +80,12 @@ const AddAutoRouterTab: React.FC = ({ // Check basic required fields first if (!currentFormValues.auto_router_name) { - message.error("Please enter an Auto Router Name"); + NotificationManager.fromBackend("Please enter an Auto Router Name"); return; } if (!currentFormValues.auto_router_default_model) { - message.error("Please select a Default Model"); + NotificationManager.fromBackend("Please select a Default Model"); return; } @@ -98,7 +99,7 @@ const AddAutoRouterTab: React.FC = ({ // Custom validation for router config if (!routerConfig || !routerConfig.routes || routerConfig.routes.length === 0) { - message.error("Please configure at least one route for the auto router"); + NotificationManager.fromBackend("Please configure at least one route for the auto router"); return; } @@ -108,7 +109,7 @@ const AddAutoRouterTab: React.FC = ({ ); if (invalidRoutes.length > 0) { - message.error("Please ensure all routes have a target model, description, and at least one utterance"); + NotificationManager.fromBackend("Please ensure all routes have a target model, description, and at least one utterance"); return; } @@ -139,9 +140,9 @@ const AddAutoRouterTab: React.FC = ({ }; return friendlyNames[fieldName] || fieldName; }); - message.error(`Please fill in the following required fields: ${missingFields.join(', ')}`); + NotificationManager.fromBackend(`Please fill in the following required fields: ${missingFields.join(', ')}`); } else { - message.error("Please fill in all required fields"); + NotificationManager.fromBackend("Please fill in all required fields"); } }); }; diff --git a/ui/litellm-dashboard/src/components/add_model/handle_add_auto_router_submit.tsx b/ui/litellm-dashboard/src/components/add_model/handle_add_auto_router_submit.tsx index 718e4062df..4272dc68b0 100644 --- a/ui/litellm-dashboard/src/components/add_model/handle_add_auto_router_submit.tsx +++ b/ui/litellm-dashboard/src/components/add_model/handle_add_auto_router_submit.tsx @@ -1,5 +1,6 @@ import { message } from "antd"; import { modelCreateCall, Model } from "../networking"; +import NotificationManager from "../molecules/notifications_manager"; export const handleAddAutoRouterSubmit = async ( values: any, @@ -55,6 +56,6 @@ export const handleAddAutoRouterSubmit = async ( } catch (error) { console.error("Failed to add auto router:", error); - message.error("Failed to add auto router: " + error, 10); + NotificationManager.fromBackend("Failed to add auto router: " + error); } }; \ No newline at end of file diff --git a/ui/litellm-dashboard/src/components/add_model/handle_add_model_submit.tsx b/ui/litellm-dashboard/src/components/add_model/handle_add_model_submit.tsx index ff942c10a9..8aafd3f04e 100644 --- a/ui/litellm-dashboard/src/components/add_model/handle_add_model_submit.tsx +++ b/ui/litellm-dashboard/src/components/add_model/handle_add_model_submit.tsx @@ -3,6 +3,7 @@ import { provider_map, Providers } from "../provider_info_helpers"; import { modelCreateCall, Model, testConnectionRequest } from "../networking"; import React, { useState } from 'react'; import ConnectionErrorDisplay from './model_connection_test'; +import NotificationManager from "../molecules/notifications_manager"; export const prepareModelAddRequest = async ( formValues: Record, @@ -100,9 +101,8 @@ export const prepareModelAddRequest = async ( try { litellmExtraParams = JSON.parse(value); } catch (error) { - message.error( - "Failed to parse LiteLLM Extra Params: " + error, - 10 + NotificationManager.fromBackend( + "Failed to parse LiteLLM Extra Params: " + error ); throw new Error("Failed to parse litellm_extra_params: " + error); } @@ -117,9 +117,8 @@ export const prepareModelAddRequest = async ( try { modelInfoParams = JSON.parse(value); } catch (error) { - message.error( - "Failed to parse LiteLLM Extra Params: " + error, - 10 + NotificationManager.fromBackend( + "Failed to parse LiteLLM Extra Params: " + error ); throw new Error("Failed to parse litellm_extra_params: " + error); } @@ -151,7 +150,7 @@ export const prepareModelAddRequest = async ( return deployments; } catch (error) { - message.error("Failed to create model: " + error, 10); + NotificationManager.fromBackend("Failed to create model: " + error); } }; @@ -185,7 +184,7 @@ export const handleAddModelSubmit = async ( callback && callback(); form.resetFields(); } catch (error) { - message.error("Failed to add model: " + error, 10); + NotificationManager.fromBackend("Failed to add model: " + error); } }; diff --git a/ui/litellm-dashboard/src/components/add_pass_through.tsx b/ui/litellm-dashboard/src/components/add_pass_through.tsx index ac19d0b6a3..21f828e26d 100644 --- a/ui/litellm-dashboard/src/components/add_pass_through.tsx +++ b/ui/litellm-dashboard/src/components/add_pass_through.tsx @@ -28,6 +28,7 @@ import { list } from "postcss"; import KeyValueInput from "./key_value_input"; import { passThroughItem } from "./pass_through_settings"; import RoutePreview from "./route_preview"; +import NotificationManager from "./molecules/notifications_manager"; const { Option } = Select2; interface AddFallbacksProps { @@ -87,7 +88,7 @@ const AddPassThroughEndpoint: React.FC = ({ setIncludeSubpath(true); setIsModalVisible(false); } catch (error) { - message.error("Error creating pass-through endpoint: " + error, 20); + NotificationManager.fromBackend("Error creating pass-through endpoint: " + error); } finally { setIsLoading(false); } diff --git a/ui/litellm-dashboard/src/components/admins.tsx b/ui/litellm-dashboard/src/components/admins.tsx index b743dd6f17..ef6f49900a 100644 --- a/ui/litellm-dashboard/src/components/admins.tsx +++ b/ui/litellm-dashboard/src/components/admins.tsx @@ -46,6 +46,7 @@ import { ssoProviderConfigs } from './SSOModals'; import SCIMConfig from "./SCIM"; import UIAccessControlForm from "./UIAccessControlForm"; import UsefulLinksManagement from "./useful_links_management"; +import NotificationManager from "./molecules/notifications_manager"; interface AdminPanelProps { searchParams: any; @@ -150,7 +151,7 @@ const AdminPanel: React.FC = ({ const handleShowAllowedIPs = async () => { try { if (premiumUser !== true) { - message.error( + NotificationManager.fromBackend( "This feature is only available for premium users. Please upgrade your account." ) return @@ -163,7 +164,7 @@ const AdminPanel: React.FC = ({ } } catch (error) { console.error("Error fetching allowed IPs:", error); - message.error(`Failed to fetch allowed IPs ${error}`); + NotificationManager.fromBackend(`Failed to fetch allowed IPs ${error}`); setAllowedIPs([all_ip_address_allowed]); } finally { if (premiumUser === true) { @@ -183,7 +184,7 @@ const AdminPanel: React.FC = ({ } } catch (error) { console.error("Error adding IP:", error); - message.error(`Failed to add IP address ${error}`); + NotificationManager.fromBackend(`Failed to add IP address ${error}`); } finally { setIsAddIPModalVisible(false); } @@ -204,7 +205,7 @@ const AdminPanel: React.FC = ({ message.success('IP address deleted successfully'); } catch (error) { console.error("Error deleting IP:", error); - message.error(`Failed to delete IP address ${error}`); + NotificationManager.fromBackend(`Failed to delete IP address ${error}`); } finally { setIsDeleteIPModalVisible(false); setIPToDelete(null); @@ -564,7 +565,7 @@ const AdminPanel: React.FC = ({
@@ -580,7 +581,7 @@ const AdminPanel: React.FC = ({
diff --git a/ui/litellm-dashboard/src/components/budgets/budget_modal.tsx b/ui/litellm-dashboard/src/components/budgets/budget_modal.tsx index cca0876821..31eb650420 100644 --- a/ui/litellm-dashboard/src/components/budgets/budget_modal.tsx +++ b/ui/litellm-dashboard/src/components/budgets/budget_modal.tsx @@ -18,6 +18,7 @@ import { message, } from "antd"; import { budgetCreateCall } from "../networking"; +import NotificationManager from "../molecules/notifications_manager"; interface BudgetModalProps { isModalVisible: boolean; @@ -58,7 +59,7 @@ const BudgetModal: React.FC = ({ form.resetFields(); } catch (error) { console.error("Error creating the key:", error); - message.error(`Error creating the key: ${error}`, 20); + NotificationManager.fromBackend(`Error creating the key: ${error}`); } }; diff --git a/ui/litellm-dashboard/src/components/budgets/edit_budget_modal.tsx b/ui/litellm-dashboard/src/components/budgets/edit_budget_modal.tsx index cfd225dd6d..37df33e8a4 100644 --- a/ui/litellm-dashboard/src/components/budgets/edit_budget_modal.tsx +++ b/ui/litellm-dashboard/src/components/budgets/edit_budget_modal.tsx @@ -19,6 +19,7 @@ import { } from "antd"; import { budgetUpdateCall } from "../networking"; import { budgetItem } from "./budget_panel"; +import NotificationManager from "../molecules/notifications_manager"; interface BudgetModalProps { isModalVisible: boolean; @@ -69,7 +70,7 @@ const EditBudgetModal: React.FC = ({ handleUpdateCall(); } catch (error) { console.error("Error creating the key:", error); - message.error(`Error creating the key: ${error}`, 20); + NotificationManager.fromBackend(`Error creating the key: ${error}`); } }; diff --git a/ui/litellm-dashboard/src/components/bulk_create_users_button.tsx b/ui/litellm-dashboard/src/components/bulk_create_users_button.tsx index f7a892d646..f98b175bec 100644 --- a/ui/litellm-dashboard/src/components/bulk_create_users_button.tsx +++ b/ui/litellm-dashboard/src/components/bulk_create_users_button.tsx @@ -14,6 +14,7 @@ import Papa from "papaparse" import { CheckCircleIcon, XCircleIcon, ExclamationIcon } from "@heroicons/react/outline" import { CopyToClipboard } from "react-copy-to-clipboard" import { InvitationLink } from "./onboarding_link" +import NotificationManager from "./molecules/notifications_manager" interface BulkCreateUsersProps { accessToken: string @@ -110,7 +111,7 @@ const BulkCreateUsersButton: React.FC = ({ // Check file type if (file.type !== "text/csv" && !file.name.endsWith(".csv")) { setFileError(`Invalid file type: ${file.name}. Please upload a CSV file (.csv extension).`) - message.error("Invalid file type. Please upload a CSV file.") + NotificationManager.fromBackend("Invalid file type. Please upload a CSV file.") return false } diff --git a/ui/litellm-dashboard/src/components/bulk_edit_user.tsx b/ui/litellm-dashboard/src/components/bulk_edit_user.tsx index 4c0be6eb71..c4ae4a97d3 100644 --- a/ui/litellm-dashboard/src/components/bulk_edit_user.tsx +++ b/ui/litellm-dashboard/src/components/bulk_edit_user.tsx @@ -16,6 +16,7 @@ import { import { Button } from '@tremor/react'; import { userBulkUpdateUserCall, teamBulkMemberAddCall, Member } from "./networking"; import { UserEditView } from "./user_edit_view"; +import NotificationManager from "./molecules/notifications_manager"; const { Text, Title } = Typography; @@ -80,7 +81,7 @@ const BulkEditUserModal: React.FC = ({ const handleSubmit = async (formValues: any) => { console.log("formValues", formValues); if (!accessToken) { - message.error("Access token not found"); + NotificationManager.fromBackend("Access token not found"); return; } @@ -112,7 +113,7 @@ const BulkEditUserModal: React.FC = ({ const hasTeamAdditions = addToTeams && selectedTeams.length > 0; if (!hasUserUpdates && !hasTeamAdditions) { - message.error("Please modify at least one field or select teams to add users to"); + NotificationManager.fromBackend("Please modify at least one field or select teams to add users to"); return; } @@ -201,7 +202,7 @@ const BulkEditUserModal: React.FC = ({ onCancel(); } catch (error) { console.error("Bulk operation failed:", error); - message.error("Failed to perform bulk operations"); + NotificationManager.fromBackend("Failed to perform bulk operations"); } finally { setLoading(false); } diff --git a/ui/litellm-dashboard/src/components/chat_ui.tsx b/ui/litellm-dashboard/src/components/chat_ui.tsx index c7aae0d896..22e9f0149d 100644 --- a/ui/litellm-dashboard/src/components/chat_ui.tsx +++ b/ui/litellm-dashboard/src/components/chat_ui.tsx @@ -72,6 +72,7 @@ import { FilePdfOutlined, ArrowUpOutlined } from "@ant-design/icons"; +import NotificationManager from "./molecules/notifications_manager"; const { TextArea } = Input; const { Dragger } = Upload; @@ -516,7 +517,7 @@ const ChatUI: React.FC = ({ // For image edits, require both image and prompt if (endpointType === EndpointType.IMAGE_EDITS && !uploadedImage) { - message.error("Please upload an image for editing"); + NotificationManager.fromBackend("Please upload an image for editing"); return; } @@ -527,7 +528,7 @@ const ChatUI: React.FC = ({ const effectiveApiKey = apiKeySource === 'session' ? accessToken : apiKey; if (!effectiveApiKey) { - message.error("Please provide an API key or select Current UI Session"); + NotificationManager.fromBackend("Please provide an API key or select Current UI Session"); return; } @@ -543,7 +544,7 @@ const ChatUI: React.FC = ({ try { newUserMessage = await createMultimodalMessage(inputMessage, responsesUploadedImage); } catch (error) { - message.error("Failed to process image. Please try again."); + NotificationManager.fromBackend("Failed to process image. Please try again."); return; } } @@ -552,7 +553,7 @@ const ChatUI: React.FC = ({ try { newUserMessage = await createChatMultimodalMessage(inputMessage, chatUploadedImage); } catch (error) { - message.error("Failed to process image. Please try again."); + NotificationManager.fromBackend("Failed to process image. Please try again."); return; } } else { diff --git a/ui/litellm-dashboard/src/components/chat_ui/llm_calls/anthropic_messages.tsx b/ui/litellm-dashboard/src/components/chat_ui/llm_calls/anthropic_messages.tsx index 862d89973f..573c1cc291 100644 --- a/ui/litellm-dashboard/src/components/chat_ui/llm_calls/anthropic_messages.tsx +++ b/ui/litellm-dashboard/src/components/chat_ui/llm_calls/anthropic_messages.tsx @@ -3,6 +3,7 @@ import Anthropic from "@anthropic-ai/sdk"; import { MessageType } from "../types"; import { TokenUsage } from "../ResponseMetrics"; import { getProxyBaseUrl } from "@/components/networking"; +import NotificationManager from "@/components/molecules/notifications_manager"; export async function makeAnthropicMessagesRequest( messages: MessageType[], @@ -122,9 +123,8 @@ export async function makeAnthropicMessagesRequest( if (signal?.aborted) { console.log("Anthropic messages request was cancelled"); } else { - message.error( - `Error occurred while generating model response. Please try again. Error: ${error}`, - 20, + NotificationManager.fromBackend( + `Error occurred while generating model response. Please try again. Error: ${error}` ); } throw error; diff --git a/ui/litellm-dashboard/src/components/chat_ui/llm_calls/fetch_mcp_tools.tsx b/ui/litellm-dashboard/src/components/chat_ui/llm_calls/fetch_mcp_tools.tsx index 99596f1dbd..cd9368460e 100644 --- a/ui/litellm-dashboard/src/components/chat_ui/llm_calls/fetch_mcp_tools.tsx +++ b/ui/litellm-dashboard/src/components/chat_ui/llm_calls/fetch_mcp_tools.tsx @@ -1,3 +1,4 @@ +import NotificationManager from "@/components/molecules/notifications_manager"; import { mcpToolsCall } from "../../networking"; import { message } from "antd"; @@ -27,7 +28,7 @@ export async function fetchAvailableMCPTools( return data.tools || []; } catch (error) { console.error("Error fetching MCP tools:", error); - message.error("Failed to fetch MCP tools"); + NotificationManager.fromBackend("Failed to fetch MCP tools"); return []; } } \ No newline at end of file diff --git a/ui/litellm-dashboard/src/components/chat_ui/llm_calls/image_edits.tsx b/ui/litellm-dashboard/src/components/chat_ui/llm_calls/image_edits.tsx index 62f4d6bbbd..dd3cf96c3e 100644 --- a/ui/litellm-dashboard/src/components/chat_ui/llm_calls/image_edits.tsx +++ b/ui/litellm-dashboard/src/components/chat_ui/llm_calls/image_edits.tsx @@ -1,6 +1,7 @@ import openai from "openai"; import { message } from "antd"; import { getProxyBaseUrl } from "@/components/networking"; +import NotificationManager from "@/components/molecules/notifications_manager"; export async function makeOpenAIImageEditsRequest( imageFile: File, @@ -54,7 +55,7 @@ export async function makeOpenAIImageEditsRequest( if (signal?.aborted) { console.log("Image edits request was cancelled"); } else { - message.error(`Error occurred while editing image. Please try again. Error: ${error}`, 20); + NotificationManager.fromBackend(`Error occurred while editing image. Please try again. Error: ${error}`); } throw error; // Re-throw to allow the caller to handle the error } diff --git a/ui/litellm-dashboard/src/components/chat_ui/llm_calls/image_generation.tsx b/ui/litellm-dashboard/src/components/chat_ui/llm_calls/image_generation.tsx index 1d03f82c16..dbd9e7b383 100644 --- a/ui/litellm-dashboard/src/components/chat_ui/llm_calls/image_generation.tsx +++ b/ui/litellm-dashboard/src/components/chat_ui/llm_calls/image_generation.tsx @@ -1,6 +1,7 @@ import openai from "openai"; import { message } from "antd"; import { getProxyBaseUrl } from "@/components/networking"; +import NotificationManager from "@/components/molecules/notifications_manager"; export async function makeOpenAIImageGenerationRequest( prompt: string, @@ -51,7 +52,7 @@ export async function makeOpenAIImageGenerationRequest( if (signal?.aborted) { console.log("Image generation request was cancelled"); } else { - message.error(`Error occurred while generating image. Please try again. Error: ${error}`, 20); + NotificationManager.fromBackend(`Error occurred while generating image. Please try again. Error: ${error}`); } throw error; // Re-throw to allow the caller to handle the error } diff --git a/ui/litellm-dashboard/src/components/chat_ui/llm_calls/responses_api.tsx b/ui/litellm-dashboard/src/components/chat_ui/llm_calls/responses_api.tsx index 71033e5d9d..b6d656bc70 100644 --- a/ui/litellm-dashboard/src/components/chat_ui/llm_calls/responses_api.tsx +++ b/ui/litellm-dashboard/src/components/chat_ui/llm_calls/responses_api.tsx @@ -4,6 +4,7 @@ import { MessageType } from "../types"; import { TokenUsage } from "../ResponseMetrics"; import { getProxyBaseUrl } from "@/components/networking"; import { MCPTool } from "@/components/chat_ui/llm_calls/fetch_mcp_tools"; +import NotificationManager from "@/components/molecules/notifications_manager"; export async function makeOpenAIResponsesRequest( messages: MessageType[], @@ -181,7 +182,7 @@ export async function makeOpenAIResponsesRequest( if (signal?.aborted) { console.log("Responses API request was cancelled"); } else { - message.error(`Error occurred while generating model response. Please try again. Error: ${error}`, 20); + NotificationManager.fromBackend(`Error occurred while generating model response. Please try again. Error: ${error}`); } throw error; // Re-throw to allow the caller to handle the error } diff --git a/ui/litellm-dashboard/src/components/cloudzero_export_modal.tsx b/ui/litellm-dashboard/src/components/cloudzero_export_modal.tsx index a7b585e89e..47f9b8561a 100644 --- a/ui/litellm-dashboard/src/components/cloudzero_export_modal.tsx +++ b/ui/litellm-dashboard/src/components/cloudzero_export_modal.tsx @@ -8,6 +8,7 @@ import { TextInput, } from "@tremor/react"; import { Modal, Form, Input, message, Spin, Select } from "antd"; +import NotificationManager from "./molecules/notifications_manager"; interface CloudZeroExportModalProps { isOpen: boolean; @@ -68,11 +69,11 @@ const CloudZeroExportModal: React.FC = ({ } else if (response.status !== 404) { // 404 means no settings configured yet, which is fine const errorData = await response.json(); - message.error(`Failed to load existing settings: ${errorData.error || 'Unknown error'}`); + NotificationManager.fromBackend(`Failed to load existing settings: ${errorData.error || 'Unknown error'}`); } } catch (error) { console.error("Error loading CloudZero settings:", error); - message.error("Failed to load existing settings"); + NotificationManager.fromBackend("Failed to load existing settings"); } finally { setSettingsLoading(false); } @@ -80,7 +81,7 @@ const CloudZeroExportModal: React.FC = ({ const handleSaveCloudZeroSettings = async (values: CloudZeroSettings) => { if (!accessToken) { - message.error("No access token available"); + NotificationManager.fromBackend("No access token available"); return; } @@ -115,12 +116,12 @@ const CloudZeroExportModal: React.FC = ({ }); return true; } else { - message.error(data.error || "Failed to save CloudZero settings"); + NotificationManager.fromBackend(data.error || "Failed to save CloudZero settings"); return false; } } catch (error) { console.error("Error saving CloudZero settings:", error); - message.error("Failed to save CloudZero settings"); + NotificationManager.fromBackend("Failed to save CloudZero settings"); return false; } finally { setLoading(false); @@ -129,7 +130,7 @@ const CloudZeroExportModal: React.FC = ({ const handleExportCloudZero = async () => { if (!accessToken) { - message.error("No access token available"); + NotificationManager.fromBackend("No access token available"); return; } @@ -153,11 +154,11 @@ const CloudZeroExportModal: React.FC = ({ message.success(data.message || "Export to CloudZero completed successfully"); onClose(); } else { - message.error(data.error || "Failed to export to CloudZero"); + NotificationManager.fromBackend(data.error || "Failed to export to CloudZero"); } } catch (error) { console.error("Error exporting to CloudZero:", error); - message.error("Failed to export to CloudZero"); + NotificationManager.fromBackend("Failed to export to CloudZero"); } finally { setExportLoading(false); } @@ -171,7 +172,7 @@ const CloudZeroExportModal: React.FC = ({ onClose(); } catch (error) { console.error("Error exporting CSV:", error); - message.error("Failed to export CSV"); + NotificationManager.fromBackend("Failed to export CSV"); } finally { setExportLoading(false); } diff --git a/ui/litellm-dashboard/src/components/common_components/ModelAliasManager.tsx b/ui/litellm-dashboard/src/components/common_components/ModelAliasManager.tsx index db49e1d999..eb9372403c 100644 --- a/ui/litellm-dashboard/src/components/common_components/ModelAliasManager.tsx +++ b/ui/litellm-dashboard/src/components/common_components/ModelAliasManager.tsx @@ -13,6 +13,7 @@ import { TableCell } from "@tremor/react"; import ModelSelector from "./ModelSelector"; +import NotificationManager from "../molecules/notifications_manager"; interface ModelAliasManagerProps { accessToken: string; @@ -49,13 +50,13 @@ const ModelAliasManager: React.FC = ({ const handleAddAlias = () => { if (!newAlias.aliasName || !newAlias.targetModel) { - message.error("Please provide both alias name and target model"); + NotificationManager.fromBackend("Please provide both alias name and target model"); return; } // Check for duplicate alias names if (aliases.some(alias => alias.aliasName === newAlias.aliasName)) { - message.error("An alias with this name already exists"); + NotificationManager.fromBackend("An alias with this name already exists"); return; } @@ -90,13 +91,13 @@ const ModelAliasManager: React.FC = ({ if (!editingAlias) return; if (!editingAlias.aliasName || !editingAlias.targetModel) { - message.error("Please provide both alias name and target model"); + NotificationManager.fromBackend("Please provide both alias name and target model"); return; } // Check for duplicate alias names (excluding current alias) if (aliases.some(alias => alias.id !== editingAlias.id && alias.aliasName === editingAlias.aliasName)) { - message.error("An alias with this name already exists"); + NotificationManager.fromBackend("An alias with this name already exists"); return; } diff --git a/ui/litellm-dashboard/src/components/create_user_button.tsx b/ui/litellm-dashboard/src/components/create_user_button.tsx index fe706abab7..c1aad1811a 100644 --- a/ui/litellm-dashboard/src/components/create_user_button.tsx +++ b/ui/litellm-dashboard/src/components/create_user_button.tsx @@ -26,6 +26,7 @@ import { Tooltip } from "antd" import { InfoCircleOutlined } from "@ant-design/icons" import { getModelDisplayName } from "./key_team_helpers/fetch_available_models_team_key" import { useQueryClient } from "@tanstack/react-query" +import NotificationManager from "./molecules/notifications_manager" // Helper function to generate UUID compatible across all environments const generateUUID = (): string => { @@ -174,7 +175,7 @@ const Createuser: React.FC = ({ localStorage.removeItem("userData" + userID) } catch (error: any) { const errorMessage = error.response?.data?.detail || error?.message || "Error creating the user" - message.error(errorMessage) + NotificationManager.fromBackend(errorMessage) console.error("Error creating the user:", error) } } diff --git a/ui/litellm-dashboard/src/components/edit_auto_router/edit_auto_router_modal.tsx b/ui/litellm-dashboard/src/components/edit_auto_router/edit_auto_router_modal.tsx index 580f6761fe..1f5bc1d320 100644 --- a/ui/litellm-dashboard/src/components/edit_auto_router/edit_auto_router_modal.tsx +++ b/ui/litellm-dashboard/src/components/edit_auto_router/edit_auto_router_modal.tsx @@ -4,6 +4,7 @@ import { Text, TextInput } from "@tremor/react"; import { modelAvailableCall, modelPatchUpdateCall } from "../networking"; import { fetchAvailableModels, ModelGroup } from "../chat_ui/llm_calls/fetch_models"; import RouterConfigBuilder from "../add_model/router_config_builder"; +import NotificationManager from "../molecules/notifications_manager"; interface EditAutoRouterModalProps { isVisible: boolean; @@ -92,7 +93,7 @@ const EditAutoRouterModal: React.FC = ({ } catch (error) { console.error("Error parsing auto router config:", error); - message.error("Error loading auto router configuration"); + NotificationManager.fromBackend("Error loading auto router configuration"); } }; @@ -135,7 +136,7 @@ const EditAutoRouterModal: React.FC = ({ onCancel(); } catch (error) { console.error("Error updating auto router:", error); - message.error("Failed to update auto router configuration"); + NotificationManager.fromBackend("Failed to update auto router configuration"); } finally { setLoading(false); } diff --git a/ui/litellm-dashboard/src/components/email_settings.tsx b/ui/litellm-dashboard/src/components/email_settings.tsx index 56219c5a39..b6fe06a5e1 100644 --- a/ui/litellm-dashboard/src/components/email_settings.tsx +++ b/ui/litellm-dashboard/src/components/email_settings.tsx @@ -8,7 +8,7 @@ import { TableCell, } from "@tremor/react"; import { Typography } from "antd"; -import NotificationsManager from "./molecules/notifications_manager"; +import NotificationManager from "./molecules/notifications_manager"; import { serviceHealthCheck, setCallbacksCall } from "./networking"; import { EmailEventSettings } from "./email_events"; @@ -54,9 +54,9 @@ const EmailSettings: React.FC = ({ }; try { await setCallbacksCall(accessToken, payload); - NotificationsManager.success("Email settings updated successfully"); + NotificationManager.success("Email settings updated successfully"); } catch (error) { - NotificationsManager.fromBackend(error); + NotificationManager.fromBackend(error); } } @@ -195,9 +195,9 @@ const EmailSettings: React.FC = ({ if (!accessToken) return; try { await serviceHealthCheck(accessToken, "email"); - NotificationsManager.success("Email test triggered. Check your configured email inbox/logs."); + NotificationManager.success("Email test triggered. Check your configured email inbox/logs."); } catch (error) { - NotificationsManager.fromBackend(error); + NotificationManager.fromBackend(error); } }} className="mx-2" diff --git a/ui/litellm-dashboard/src/components/general_settings.tsx b/ui/litellm-dashboard/src/components/general_settings.tsx index d54092d1bf..2ed238f03d 100644 --- a/ui/litellm-dashboard/src/components/general_settings.tsx +++ b/ui/litellm-dashboard/src/components/general_settings.tsx @@ -63,6 +63,7 @@ import { import AddFallbacks from "./add_fallbacks"; import openai from "openai"; import Paragraph from "antd/es/skeleton/Paragraph"; +import NotificationManager from "./molecules/notifications_manager"; interface GeneralSettingsPageProps { accessToken: string | null; userRole: string | null; @@ -121,9 +122,8 @@ async function testFallbackModelResponse( ); } catch (error) { - message.error( + NotificationManager.fromBackend( `Error occurred while generating model response. Please try again. Error: ${error}`, - 20 ); } } @@ -311,7 +311,7 @@ const GeneralSettings: React.FC = ({ setRouterSettings(updatedSettings); message.success("Router settings updated successfully"); } catch (error) { - message.error("Failed to update router settings: " + error, 20); + NotificationManager.fromBackend("Failed to update router settings: " + error); } }; @@ -432,7 +432,7 @@ const GeneralSettings: React.FC = ({ try { setCallbacksCall(accessToken, payload); } catch (error) { - message.error("Failed to update router settings: " + error, 20); + NotificationManager.fromBackend("Failed to update router settings: " + error); } message.success("router settings updated successfully"); diff --git a/ui/litellm-dashboard/src/components/generic_key_value_manager.tsx b/ui/litellm-dashboard/src/components/generic_key_value_manager.tsx index 520893d14c..4525be6dd5 100644 --- a/ui/litellm-dashboard/src/components/generic_key_value_manager.tsx +++ b/ui/litellm-dashboard/src/components/generic_key_value_manager.tsx @@ -13,6 +13,7 @@ import { import { message, Input } from "antd"; import { EditOutlined, DeleteOutlined, SaveOutlined, CloseOutlined } from "@ant-design/icons"; import { ChevronDownIcon, ChevronRightIcon, PlusCircleIcon } from "@heroicons/react/outline"; +import NotificationManager from "./molecules/notifications_manager"; interface KeyValueItem { id?: string; @@ -73,7 +74,7 @@ const GenericKeyValueManager: React.FC = ({ setNewKey(""); setNewValue(""); } else { - message.error(`Please provide both ${keyLabel.toLowerCase()} and ${valueLabel.toLowerCase()}`); + NotificationManager.fromBackend(`Please provide both ${keyLabel.toLowerCase()} and ${valueLabel.toLowerCase()}`); } }, [newKey, newValue, items, onItemsChange, keyLabel, valueLabel]); @@ -93,7 +94,7 @@ const GenericKeyValueManager: React.FC = ({ setEditingKey(""); setEditingValue(""); } else { - message.error(`Please provide both ${keyLabel.toLowerCase()} and ${valueLabel.toLowerCase()}`); + NotificationManager.fromBackend(`Please provide both ${keyLabel.toLowerCase()} and ${valueLabel.toLowerCase()}`); } }, [editingKey, editingValue, items, editingItem, onItemsChange, keyLabel, valueLabel]); diff --git a/ui/litellm-dashboard/src/components/guardrails.tsx b/ui/litellm-dashboard/src/components/guardrails.tsx index 8f7d8fb3a1..4e09ecda63 100644 --- a/ui/litellm-dashboard/src/components/guardrails.tsx +++ b/ui/litellm-dashboard/src/components/guardrails.tsx @@ -7,6 +7,7 @@ import AddGuardrailForm from "./guardrails/add_guardrail_form" import GuardrailTable from "./guardrails/guardrail_table" import { isAdminRole } from "@/utils/roles" import GuardrailInfoView from "./guardrails/guardrail_info" +import NotificationManager from "./molecules/notifications_manager"; interface GuardrailsPanelProps { accessToken: string | null @@ -91,7 +92,7 @@ const GuardrailsPanel: React.FC = ({ accessToken, userRole fetchGuardrails() // Refresh the list } catch (error) { console.error("Error deleting guardrail:", error) - message.error("Failed to delete guardrail") + NotificationManager.fromBackend("Failed to delete guardrail") } finally { setIsDeleting(false) setGuardrailToDelete(null) diff --git a/ui/litellm-dashboard/src/components/guardrails/add_guardrail_form.tsx b/ui/litellm-dashboard/src/components/guardrails/add_guardrail_form.tsx index bce9db2e45..41a07099df 100644 --- a/ui/litellm-dashboard/src/components/guardrails/add_guardrail_form.tsx +++ b/ui/litellm-dashboard/src/components/guardrails/add_guardrail_form.tsx @@ -7,6 +7,7 @@ import { createGuardrailCall, getGuardrailUISettings, getGuardrailProviderSpecif import PiiConfiguration from './pii_configuration'; import GuardrailProviderFields from './guardrail_provider_fields'; import GuardrailOptionalParams from './guardrail_optional_params'; +import NotificationManager from '../molecules/notifications_manager'; const { Title, Text, Link } = Typography; const { Option } = Select; @@ -103,7 +104,7 @@ const AddGuardrailForm: React.FC = ({ populateGuardrailProviderMap(providerParamsResp); } catch (error) { console.error('Error fetching guardrail data:', error); - message.error('Failed to load guardrail configuration'); + NotificationManager.fromBackend('Failed to load guardrail configuration'); } }; @@ -186,7 +187,7 @@ const AddGuardrailForm: React.FC = ({ // Validate configuration steps if (currentStep === 1) { if (shouldRenderPIIConfigSettings(selectedProvider) && selectedEntities.length === 0) { - message.error('Please select at least one PII entity to continue'); + NotificationManager.fromBackend('Please select at least one PII entity to continue'); return; } } @@ -274,7 +275,7 @@ const AddGuardrailForm: React.FC = ({ // For some guardrails, the config values need to be in litellm_params guardrailData.guardrail_info = configObj; } catch (error) { - message.error('Invalid JSON in configuration'); + NotificationManager.fromBackend('Invalid JSON in configuration'); setLoading(false); return; } @@ -345,7 +346,7 @@ const AddGuardrailForm: React.FC = ({ onClose(); } catch (error) { console.error("Failed to create guardrail:", error); - message.error('Failed to create guardrail: ' + (error instanceof Error ? error.message : String(error))); + NotificationManager.fromBackend('Failed to create guardrail: ' + (error instanceof Error ? error.message : String(error))); } finally { setLoading(false); } diff --git a/ui/litellm-dashboard/src/components/guardrails/edit_guardrail_form.tsx b/ui/litellm-dashboard/src/components/guardrails/edit_guardrail_form.tsx index c64a7eac54..9a5a30b45a 100644 --- a/ui/litellm-dashboard/src/components/guardrails/edit_guardrail_form.tsx +++ b/ui/litellm-dashboard/src/components/guardrails/edit_guardrail_form.tsx @@ -4,6 +4,7 @@ import { Button, TextInput } from '@tremor/react'; import { GuardrailProviders, guardrail_provider_map, guardrailLogoMap, getGuardrailProviders } from './guardrail_info_helpers'; import { getGuardrailUISettings } from '../networking'; import PiiConfiguration from './pii_configuration'; +import NotificationManager from '../molecules/notifications_manager'; const { Title, Text } = Typography; const { Option } = Select; @@ -59,7 +60,7 @@ const EditGuardrailForm: React.FC = ({ setGuardrailSettings(data); } catch (error) { console.error('Error fetching guardrail settings:', error); - message.error('Failed to load guardrail settings'); + NotificationManager.fromBackend('Failed to load guardrail settings'); } }; @@ -165,7 +166,7 @@ const EditGuardrailForm: React.FC = ({ guardrailData.guardrail.guardrail_info = configObj; } } catch (error) { - message.error('Invalid JSON in configuration'); + NotificationManager.fromBackend('Invalid JSON in configuration'); setLoading(false); return; } @@ -200,7 +201,7 @@ const EditGuardrailForm: React.FC = ({ onClose(); } catch (error) { console.error("Failed to update guardrail:", error); - message.error('Failed to update guardrail: ' + (error instanceof Error ? error.message : String(error))); + NotificationManager.fromBackend('Failed to update guardrail: ' + (error instanceof Error ? error.message : String(error))); } finally { setLoading(false); } diff --git a/ui/litellm-dashboard/src/components/guardrails/guardrail_info.tsx b/ui/litellm-dashboard/src/components/guardrails/guardrail_info.tsx index ec02c412dc..8c78bb045c 100644 --- a/ui/litellm-dashboard/src/components/guardrails/guardrail_info.tsx +++ b/ui/litellm-dashboard/src/components/guardrails/guardrail_info.tsx @@ -28,6 +28,7 @@ import GuardrailOptionalParams from "./guardrail_optional_params" import { ArrowLeftIcon } from "@heroicons/react/outline" import { copyToClipboard as utilCopyToClipboard } from "@/utils/dataUtils" import { CheckIcon, CopyIcon } from "lucide-react" +import NotificationManager from "../molecules/notifications_manager" export interface GuardrailInfoProps { guardrailId: string @@ -104,7 +105,7 @@ const GuardrailInfoView: React.FC = ({ guardrailId, onClose, setSelectedPiiActions({}) } } catch (error) { - message.error("Failed to load guardrail information") + NotificationManager.fromBackend("Failed to load guardrail information") console.error("Error fetching guardrail info:", error) } finally { setLoading(false) @@ -296,7 +297,7 @@ const GuardrailInfoView: React.FC = ({ guardrailId, onClose, setIsEditing(false) } catch (error) { console.error("Error updating guardrail:", error) - message.error("Failed to update guardrail") + NotificationManager.fromBackend("Failed to update guardrail") } } diff --git a/ui/litellm-dashboard/src/components/make_model_public_form.tsx b/ui/litellm-dashboard/src/components/make_model_public_form.tsx index b8a0735a1f..8a67116846 100644 --- a/ui/litellm-dashboard/src/components/make_model_public_form.tsx +++ b/ui/litellm-dashboard/src/components/make_model_public_form.tsx @@ -3,6 +3,7 @@ import { Modal, Form, Steps, Button, message, Checkbox } from "antd"; import { Text, Title, Badge } from "@tremor/react"; import { makeModelGroupPublic } from "./networking"; import ModelFilters from "./model_filters"; +import NotificationManager from "./molecules/notifications_manager"; const { Step } = Steps; @@ -56,7 +57,7 @@ const MakeModelPublicForm: React.FC = ({ const handleNext = () => { if (currentStep === 0) { if (selectedModels.size === 0) { - message.error("Please select at least one model to make public"); + NotificationManager.fromBackend("Please select at least one model to make public"); return; } setCurrentStep(1); @@ -109,7 +110,7 @@ const MakeModelPublicForm: React.FC = ({ const handleSubmit = async () => { if (selectedModels.size === 0) { - message.error("Please select at least one model to make public"); + NotificationManager.fromBackend("Please select at least one model to make public"); return; } @@ -123,7 +124,7 @@ const MakeModelPublicForm: React.FC = ({ onSuccess(); } catch (error) { console.error("Error making model groups public:", error); - message.error("Failed to make model groups public. Please try again."); + NotificationManager.fromBackend("Failed to make model groups public. Please try again."); } finally { setLoading(false); } diff --git a/ui/litellm-dashboard/src/components/mcp_tools/ToolTestPanel.tsx b/ui/litellm-dashboard/src/components/mcp_tools/ToolTestPanel.tsx index 4727d3713b..54bd2f8e54 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/ToolTestPanel.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/ToolTestPanel.tsx @@ -3,7 +3,7 @@ import { Button, Callout, TextInput } from "@tremor/react"; import { MCPTool, InputSchema } from "./types"; import { Form, Tooltip, message } from "antd"; import { InfoCircleOutlined, ClockCircleOutlined } from "@ant-design/icons"; - +import NotificationManager from "../molecules/notifications_manager"; export function ToolTestPanel({ tool, @@ -145,7 +145,7 @@ export function ToolTestPanel({ if (success) { message.success('Result copied to clipboard'); } else { - message.error('Failed to copy result'); + NotificationManager.fromBackend('Failed to copy result'); } }; @@ -154,7 +154,7 @@ export function ToolTestPanel({ if (success) { message.success('Tool name copied to clipboard'); } else { - message.error('Failed to copy tool name'); + NotificationManager.fromBackend('Failed to copy tool name'); } }; diff --git a/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx index 7d0d36347f..12d8b67ff9 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx @@ -9,6 +9,7 @@ import MCPConnectionStatus from "./mcp_connection_status" import StdioConfiguration from "./StdioConfiguration" import { isAdminRole } from "@/utils/roles" import { validateMCPServerUrl, validateMCPServerName } from "./utils" +import NotificationManager from "../molecules/notifications_manager" const asset_logos_folder = "../ui/assets/logos/" export const mcpLogoImg = `${asset_logos_folder}mcp_logo.png` @@ -80,7 +81,7 @@ const CreateMCPServer: React.FC = ({ console.log("Parsed stdio config:", stdioFields) } catch (error) { - message.error("Invalid JSON in stdio configuration") + NotificationManager.fromBackend("Invalid JSON in stdio configuration") return } } @@ -113,7 +114,7 @@ const CreateMCPServer: React.FC = ({ onCreateSuccess(response) } } catch (error) { - message.error("Error creating MCP Server: " + error, 20) + NotificationManager.fromBackend("Error creating MCP Server: " + error) } finally { setIsLoading(false) } diff --git a/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_edit.tsx b/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_edit.tsx index 37a766c2cf..52cb09a9d8 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_edit.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/mcp_server_edit.tsx @@ -6,6 +6,7 @@ import { updateMCPServer, testMCPToolsListRequest } from "../networking"; import MCPServerCostConfig from "./mcp_server_cost_config"; import { MinusCircleOutlined, PlusOutlined, InfoCircleOutlined } from "@ant-design/icons"; import { validateMCPServerUrl, validateMCPServerName } from "./utils"; +import NotificationManager from "../molecules/notifications_manager"; interface MCPServerEditProps { mcpServer: MCPServer; @@ -131,7 +132,7 @@ const MCPServerEdit: React.FC = ({ mcpServer, accessToken, o message.success("MCP Server updated successfully"); onSuccess(updated); } catch (error: any) { - message.error("Failed to update MCP Server" + (error?.message ? `: ${error.message}` : "")); + NotificationManager.fromBackend("Failed to update MCP Server" + (error?.message ? `: ${error.message}` : "")); } }; diff --git a/ui/litellm-dashboard/src/components/mcp_tools/mcp_tools.tsx b/ui/litellm-dashboard/src/components/mcp_tools/mcp_tools.tsx index b2ba26875f..a8682467a4 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/mcp_tools.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/mcp_tools.tsx @@ -20,6 +20,7 @@ import { Button, Card, Title, Text } from "@tremor/react"; import { RobotOutlined, ApiOutlined, KeyOutlined, SafetyOutlined, ToolOutlined } from "@ant-design/icons"; import { AUTH_TYPE } from "./types"; +import NotificationManager from "../molecules/notifications_manager"; type AuthModalProps = { visible: boolean; diff --git a/ui/litellm-dashboard/src/components/model_dashboard.tsx b/ui/litellm-dashboard/src/components/model_dashboard.tsx index cd4fd66e58..c9143d1fbf 100644 --- a/ui/litellm-dashboard/src/components/model_dashboard.tsx +++ b/ui/litellm-dashboard/src/components/model_dashboard.tsx @@ -77,6 +77,7 @@ import PassThroughSettings from "./pass_through_settings"; import ModelGroupAliasSettings from "./model_group_alias_settings"; import { all_admin_roles } from "@/utils/roles"; import { Table as TableInstance } from "@tanstack/react-table"; +import NotificationManager from "./molecules/notifications_manager"; interface ModelDashboardProps { accessToken: string | null; @@ -439,7 +440,7 @@ const ModelDashboard: React.FC = ({ if (info.file.status === "done") { message.success(`${info.file.name} file uploaded successfully`); } else if (info.file.status === "error") { - message.error(`${info.file.name} file upload failed.`); + NotificationManager.fromBackend(`${info.file.name} file upload failed.`); } }, }; @@ -480,7 +481,7 @@ const ModelDashboard: React.FC = ({ await setCallbacksCall(accessToken, payload); } catch (error) { console.error("Failed to save retry settings:", error); - message.error("Failed to save retry settings"); + NotificationManager.fromBackend("Failed to save retry settings"); } }; @@ -1003,7 +1004,7 @@ const ModelDashboard: React.FC = ({ const errorMessages = error.errorFields?.map((field: any) => { return `${field.name.join('.')}: ${field.errors.join(', ')}`; }).join(' | ') || 'Unknown validation error'; - message.error(`Please fill in the following required fields: ${errorMessages}`); + NotificationManager.fromBackend(`Please fill in the following required fields: ${errorMessages}`); }); }; diff --git a/ui/litellm-dashboard/src/components/model_group_alias_settings.tsx b/ui/litellm-dashboard/src/components/model_group_alias_settings.tsx index d9a83e0a52..d035d45a06 100644 --- a/ui/litellm-dashboard/src/components/model_group_alias_settings.tsx +++ b/ui/litellm-dashboard/src/components/model_group_alias_settings.tsx @@ -13,6 +13,7 @@ import { TableRow, TableCell } from "@tremor/react"; +import NotificationManager from "./molecules/notifications_manager"; interface ModelGroupAliasSettingsProps { accessToken: string; @@ -75,20 +76,20 @@ const ModelGroupAliasSettings: React.FC = ({ return true; } catch (error) { console.error("Failed to save model group alias settings:", error); - message.error("Failed to save model group alias settings"); + NotificationManager.fromBackend("Failed to save model group alias settings"); return false; } }; const handleAddAlias = async () => { if (!newAlias.aliasName || !newAlias.targetModelGroup) { - message.error("Please provide both alias name and target model group"); + NotificationManager.fromBackend("Please provide both alias name and target model group"); return; } // Check for duplicate alias names if (aliases.some(alias => alias.aliasName === newAlias.aliasName)) { - message.error("An alias with this name already exists"); + NotificationManager.fromBackend("An alias with this name already exists"); return; } @@ -115,13 +116,13 @@ const ModelGroupAliasSettings: React.FC = ({ if (!editingAlias) return; if (!editingAlias.aliasName || !editingAlias.targetModelGroup) { - message.error("Please provide both alias name and target model group"); + NotificationManager.fromBackend("Please provide both alias name and target model group"); return; } // Check for duplicate alias names (excluding current alias) if (aliases.some(alias => alias.id !== editingAlias.id && alias.aliasName === editingAlias.aliasName)) { - message.error("An alias with this name already exists"); + NotificationManager.fromBackend("An alias with this name already exists"); return; } diff --git a/ui/litellm-dashboard/src/components/model_info_view.tsx b/ui/litellm-dashboard/src/components/model_info_view.tsx index 60d6968710..115be00779 100644 --- a/ui/litellm-dashboard/src/components/model_info_view.tsx +++ b/ui/litellm-dashboard/src/components/model_info_view.tsx @@ -38,6 +38,7 @@ import CacheControlSettings from "./add_model/cache_control_settings"; import { CheckIcon, CopyIcon } from "lucide-react"; import { copyToClipboard as utilCopyToClipboard } from "../utils/dataUtils"; import EditAutoRouterModal from "./edit_auto_router/edit_auto_router_modal"; +import NotificationManager from "./molecules/notifications_manager"; interface ModelInfoViewProps { modelId: string; @@ -211,7 +212,7 @@ export default function ModelInfoView({ }; } } catch (e) { - message.error("Invalid JSON in Model Info"); + NotificationManager.fromBackend("Invalid JSON in Model Info"); return; } @@ -242,7 +243,7 @@ export default function ModelInfoView({ setIsEditing(false); } catch (error) { console.error("Error updating model:", error); - message.error("Failed to update model settings"); + NotificationManager.fromBackend("Failed to update model settings"); } finally { setIsSaving(false); } @@ -280,7 +281,7 @@ export default function ModelInfoView({ onClose(); } catch (error) { console.error("Error deleting the model:", error); - message.error("Failed to delete model"); + NotificationManager.fromBackend("Failed to delete model"); } }; diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx index 81829eef7c..96d879295a 100644 --- a/ui/litellm-dashboard/src/components/networking.tsx +++ b/ui/litellm-dashboard/src/components/networking.tsx @@ -25,6 +25,7 @@ import { EmailEventSettingsUpdateRequest, } from "./email_events/types"; import { jsonFields } from "./common_components/check_openapi_schema" +import NotificationManager from "./molecules/notifications_manager"; const isLocal = process.env.NODE_ENV === "development"; export const defaultProxyBaseUrl = isLocal ? "http://localhost:4000" : null; @@ -3198,7 +3199,7 @@ export const keyInfoV1Call = async (accessToken: string, key: string) => { if (!response.ok) { const errorData = await response.text(); handleError(errorData); - message.error("Failed to fetch key info - " + errorData); + NotificationManager.fromBackend("Failed to fetch key info - " + errorData); } const data = await response.json(); @@ -3853,7 +3854,7 @@ export const teamUpdateCall = async ( const errorData = await response.text(); handleError(errorData); console.error("Error response from the server:", errorData); - message.error("Failed to update team settings: " + errorData); + NotificationManager.fromBackend("Failed to update team settings: " + errorData); throw new Error(errorData); } const data = (await response.json()) as { data: Team; team_id: string }; diff --git a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx index 7209e96f6a..3a220014dd 100644 --- a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx +++ b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx @@ -33,6 +33,7 @@ import { formatNumberWithCommas } from "@/utils/dataUtils" import { callback_map, mapDisplayToInternalNames } from "../callback_info_helpers" import MCPServerSelector from "../mcp_server_management/MCPServerSelector" import ModelAliasManager from "../common_components/ModelAliasManager" +import NotificationManager from "../molecules/notifications_manager" const { Option } = Select; @@ -384,7 +385,7 @@ const CreateKey: React.FC = ({ } catch (error) { console.log("error in create key:", error); - message.error(`Error creating the key: ${error}`); + NotificationManager.fromBackend(`Error creating the key: ${error}`); } }; @@ -434,7 +435,7 @@ const CreateKey: React.FC = ({ setUserOptions(options); } catch (error) { console.error('Error fetching users:', error); - message.error('Failed to search for users'); + NotificationManager.fromBackend('Failed to search for users'); } finally { setUserSearchLoading(false); } diff --git a/ui/litellm-dashboard/src/components/organization/organization_view.tsx b/ui/litellm-dashboard/src/components/organization/organization_view.tsx index c0eb59ff31..55e8b5308b 100644 --- a/ui/litellm-dashboard/src/components/organization/organization_view.tsx +++ b/ui/litellm-dashboard/src/components/organization/organization_view.tsx @@ -41,6 +41,7 @@ import VectorStoreSelector from "../vector_store_management/VectorStoreSelector" import MCPServerSelector from "../mcp_server_management/MCPServerSelector" import { copyToClipboard as utilCopyToClipboard, formatNumberWithCommas } from "@/utils/dataUtils" import { CheckIcon, CopyIcon } from "lucide-react" +import NotificationManager from "../molecules/notifications_manager" interface OrganizationInfoProps { organizationId: string @@ -78,7 +79,7 @@ const OrganizationInfoView: React.FC = ({ const response = await organizationInfoCall(accessToken, organizationId) setOrgData(response) } catch (error) { - message.error("Failed to load organization information") + NotificationManager.fromBackend("Failed to load organization information") console.error("Error fetching organization info:", error) } finally { setLoading(false) @@ -107,7 +108,7 @@ const OrganizationInfoView: React.FC = ({ form.resetFields() fetchOrgInfo() } catch (error) { - message.error("Failed to add organization member") + NotificationManager.fromBackend("Failed to add organization member") console.error("Error adding organization member:", error) } } @@ -128,7 +129,7 @@ const OrganizationInfoView: React.FC = ({ form.resetFields() fetchOrgInfo() } catch (error) { - message.error("Failed to update organization member") + NotificationManager.fromBackend("Failed to update organization member") console.error("Error updating organization member:", error) } } @@ -143,7 +144,7 @@ const OrganizationInfoView: React.FC = ({ form.resetFields() fetchOrgInfo() } catch (error) { - message.error("Failed to delete organization member") + NotificationManager.fromBackend("Failed to delete organization member") console.error("Error deleting organization member:", error) } } @@ -192,7 +193,7 @@ const OrganizationInfoView: React.FC = ({ setIsEditing(false) fetchOrgInfo() } catch (error) { - message.error("Failed to update organization settings") + NotificationManager.fromBackend("Failed to update organization settings") console.error("Error updating organization:", error) } } diff --git a/ui/litellm-dashboard/src/components/pass_through_info.tsx b/ui/litellm-dashboard/src/components/pass_through_info.tsx index 527fba2dbf..c3902ad8cc 100644 --- a/ui/litellm-dashboard/src/components/pass_through_info.tsx +++ b/ui/litellm-dashboard/src/components/pass_through_info.tsx @@ -20,6 +20,7 @@ import { } from "./networking"; import { Eye, EyeOff } from "lucide-react"; import RoutePreview from "./route_preview"; +import NotificationManager from "./molecules/notifications_manager"; export interface PassThroughInfoProps { endpointData: PassThroughEndpoint; @@ -87,7 +88,7 @@ const PassThroughInfoView: React.FC = ({ ? JSON.parse(values.headers) : values.headers; } catch (e) { - message.error("Invalid JSON format for headers"); + NotificationManager.fromBackend("Invalid JSON format for headers"); return; } } @@ -114,7 +115,7 @@ const PassThroughInfoView: React.FC = ({ } } catch (error) { console.error("Error updating endpoint:", error); - message.error("Failed to update pass through endpoint"); + NotificationManager.fromBackend("Failed to update pass through endpoint"); } }; @@ -130,7 +131,7 @@ const PassThroughInfoView: React.FC = ({ } } catch (error) { console.error("Error deleting endpoint:", error); - message.error("Failed to delete pass through endpoint"); + NotificationManager.fromBackend("Failed to delete pass through endpoint"); } }; diff --git a/ui/litellm-dashboard/src/components/pass_through_settings.tsx b/ui/litellm-dashboard/src/components/pass_through_settings.tsx index 6faea63551..4059c6ac52 100644 --- a/ui/litellm-dashboard/src/components/pass_through_settings.tsx +++ b/ui/litellm-dashboard/src/components/pass_through_settings.tsx @@ -45,6 +45,7 @@ import PassThroughInfoView from "./pass_through_info"; import { DataTable } from "./view_logs/table"; import { ColumnDef } from "@tanstack/react-table"; import { Eye, EyeOff } from "lucide-react"; +import NotificationManager from "./molecules/notifications_manager"; interface GeneralSettingsPageProps { accessToken: string | null; @@ -153,7 +154,7 @@ const PassThroughSettings: React.FC = ({ message.success("Endpoint deleted successfully."); } catch (error) { console.error("Error deleting the endpoint:", error); - message.error("Error deleting the endpoint: " + error); + NotificationManager.fromBackend("Error deleting the endpoint: " + error); } // Close the confirmation modal and reset the endpointToDelete diff --git a/ui/litellm-dashboard/src/components/price_data_reload.tsx b/ui/litellm-dashboard/src/components/price_data_reload.tsx index 05d3a2e102..4961d10db4 100644 --- a/ui/litellm-dashboard/src/components/price_data_reload.tsx +++ b/ui/litellm-dashboard/src/components/price_data_reload.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react"; import { Button, Popconfirm, message, Modal, InputNumber, Space, Typography, Tag, Card } from "antd"; import { ReloadOutlined, ClockCircleOutlined, StopOutlined } from "@ant-design/icons"; import { reloadModelCostMap, scheduleModelCostMapReload, cancelModelCostMapReload, getModelCostMapReloadStatus } from "./networking"; +import NotificationManager from "./molecules/notifications_manager"; const { Text } = Typography; @@ -77,7 +78,7 @@ const PriceDataReload: React.FC = ({ const handleHardRefresh = async () => { if (!accessToken) { - message.error("No access token available"); + NotificationManager.fromBackend("No access token available"); return; } @@ -93,23 +94,23 @@ const PriceDataReload: React.FC = ({ // Refresh status after successful reload await fetchReloadStatus(); } else { - message.error("Failed to reload price data"); + NotificationManager.fromBackend("Failed to reload price data"); } } catch (error) { console.error("Error reloading price data:", error); - message.error("Failed to reload price data. Please try again."); + NotificationManager.fromBackend("Failed to reload price data. Please try again."); } finally { setIsLoading(false); } }; const handleScheduleReload = async () => { if (!accessToken) { - message.error("No access token available"); + NotificationManager.fromBackend("No access token available"); return; } if (hours <= 0) { - message.error("Hours must be greater than 0"); + NotificationManager.fromBackend("Hours must be greater than 0"); return; } @@ -122,11 +123,11 @@ const PriceDataReload: React.FC = ({ setShowScheduleModal(false); await fetchReloadStatus(); } else { - message.error("Failed to schedule periodic reload"); + NotificationManager.fromBackend("Failed to schedule periodic reload"); } } catch (error) { console.error("Error scheduling reload:", error); - message.error("Failed to schedule periodic reload. Please try again."); + NotificationManager.fromBackend("Failed to schedule periodic reload. Please try again."); } finally { setIsScheduling(false); } @@ -134,7 +135,7 @@ const PriceDataReload: React.FC = ({ const handleCancelReload = async () => { if (!accessToken) { - message.error("No access token available"); + NotificationManager.fromBackend("No access token available"); return; } @@ -146,11 +147,11 @@ const PriceDataReload: React.FC = ({ message.success("Periodic reload cancelled successfully"); await fetchReloadStatus(); } else { - message.error("Failed to cancel periodic reload"); + NotificationManager.fromBackend("Failed to cancel periodic reload"); } } catch (error) { console.error("Error cancelling reload:", error); - message.error("Failed to cancel periodic reload. Please try again."); + NotificationManager.fromBackend("Failed to cancel periodic reload. Please try again."); } finally { setIsCancelling(false); } diff --git a/ui/litellm-dashboard/src/components/prompts.tsx b/ui/litellm-dashboard/src/components/prompts.tsx index 477a7c93e6..b272a4f14c 100644 --- a/ui/litellm-dashboard/src/components/prompts.tsx +++ b/ui/litellm-dashboard/src/components/prompts.tsx @@ -6,7 +6,7 @@ import { getPromptsList, PromptSpec, ListPromptsResponse, deletePromptCall } fro import PromptTable from "./prompts/prompt_table" import PromptInfoView from "./prompts/prompt_info" import AddPromptForm from "./prompts/add_prompt_form" - +import NotificationManager from "./molecules/notifications_manager" import { isAdminRole } from "@/utils/roles" interface PromptsProps { @@ -78,7 +78,7 @@ const PromptsPanel: React.FC = ({ accessToken, userRole }) => { fetchPrompts() // Refresh the list } catch (error) { console.error("Error deleting prompt:", error) - message.error("Failed to delete prompt") + NotificationManager.fromBackend("Failed to delete prompt") } finally { setIsDeleting(false) setPromptToDelete(null) diff --git a/ui/litellm-dashboard/src/components/prompts/add_prompt_form.tsx b/ui/litellm-dashboard/src/components/prompts/add_prompt_form.tsx index a9dd143fee..4c18fcaa0b 100644 --- a/ui/litellm-dashboard/src/components/prompts/add_prompt_form.tsx +++ b/ui/litellm-dashboard/src/components/prompts/add_prompt_form.tsx @@ -4,6 +4,7 @@ import { TextInput } from "@tremor/react" import { UploadOutlined } from "@ant-design/icons" import type { UploadFile, UploadProps } from "antd" import { convertPromptFileToJson, createPromptCall } from "../networking" +import NotificationManager from "../molecules/notifications_manager" const { Option } = Select @@ -44,12 +45,12 @@ const AddPromptForm: React.FC = ({ console.log("values: ", values) if (!accessToken) { - message.error("Access token is required") + NotificationManager.fromBackend("Access token is required") return } if (promptIntegration === "dotprompt" && fileList.length === 0) { - message.error("Please upload a .prompt file") + NotificationManager.fromBackend("Please upload a .prompt file") return } @@ -79,7 +80,7 @@ const AddPromptForm: React.FC = ({ } } catch (conversionError) { console.error("Error converting prompt file:", conversionError) - message.error("Failed to convert prompt file to JSON") + NotificationManager.fromBackend("Failed to convert prompt file to JSON") setLoading(false) return } @@ -93,7 +94,7 @@ const AddPromptForm: React.FC = ({ onSuccess() } catch (createError) { console.error("Error creating prompt:", createError) - message.error("Failed to create prompt") + NotificationManager.fromBackend("Failed to create prompt") } } catch (error) { @@ -106,7 +107,7 @@ const AddPromptForm: React.FC = ({ const uploadProps: UploadProps = { beforeUpload: (file) => { if (!file.name.endsWith('.prompt')) { - message.error('Please upload a .prompt file') + NotificationManager.fromBackend('Please upload a .prompt file') return false } return false // Prevent automatic upload diff --git a/ui/litellm-dashboard/src/components/prompts/prompt_info.tsx b/ui/litellm-dashboard/src/components/prompts/prompt_info.tsx index 0758789161..98cca56375 100644 --- a/ui/litellm-dashboard/src/components/prompts/prompt_info.tsx +++ b/ui/litellm-dashboard/src/components/prompts/prompt_info.tsx @@ -17,6 +17,7 @@ import { ArrowLeftIcon, TrashIcon } from "@heroicons/react/outline" import { getPromptInfo, PromptInfoResponse, PromptSpec, PromptTemplateBase, deletePromptCall } from "@/components/networking" import { copyToClipboard as utilCopyToClipboard } from "@/utils/dataUtils" import { CheckIcon, CopyIcon } from "lucide-react" +import NotificationManager from "../molecules/notifications_manager" export interface PromptInfoProps { promptId: string @@ -44,7 +45,7 @@ const PromptInfoView: React.FC = ({ promptId, onClose, accessTo setPromptTemplate(response.raw_prompt_template) setRawApiResponse(response) // Store the raw response for the Raw JSON tab } catch (error) { - message.error("Failed to load prompt information") + NotificationManager.fromBackend("Failed to load prompt information") console.error("Error fetching prompt info:", error) } finally { setLoading(false) @@ -95,7 +96,7 @@ const PromptInfoView: React.FC = ({ promptId, onClose, accessTo onClose() // Close the info view } catch (error) { console.error("Error deleting prompt:", error) - message.error("Failed to delete prompt") + NotificationManager.fromBackend("Failed to delete prompt") } finally { setIsDeleting(false) setShowDeleteConfirm(false) diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx index 1d42ac0974..82366428f4 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx @@ -1,5 +1,6 @@ import OpenAI from "openai"; import React from "react"; +import NotificationManager from "./molecules/notifications_manager"; export enum Providers { Bedrock = "Amazon Bedrock", diff --git a/ui/litellm-dashboard/src/components/tag_management/index.tsx b/ui/litellm-dashboard/src/components/tag_management/index.tsx index 22e87b2085..2799937ecd 100644 --- a/ui/litellm-dashboard/src/components/tag_management/index.tsx +++ b/ui/litellm-dashboard/src/components/tag_management/index.tsx @@ -27,6 +27,7 @@ import { modelInfoCall } from "../networking"; import { tagCreateCall, tagListCall, tagDeleteCall } from "../networking"; import { Tag } from "./types"; import TagTable from "./TagTable"; +import NotificationManager from "../molecules/notifications_manager"; interface ModelInfo { model_name: string; @@ -67,7 +68,7 @@ const TagManagement: React.FC = ({ setTags(Object.values(response)); } catch (error) { console.error("Error fetching tags:", error); - message.error("Error fetching tags: " + error); + NotificationManager.fromBackend("Error fetching tags: " + error); } }; @@ -91,7 +92,7 @@ const TagManagement: React.FC = ({ fetchTags(); } catch (error) { console.error("Error creating tag:", error); - message.error("Error creating tag: " + error); + NotificationManager.fromBackend("Error creating tag: " + error); } }; @@ -108,7 +109,7 @@ const TagManagement: React.FC = ({ fetchTags(); } catch (error) { console.error("Error deleting tag:", error); - message.error("Error deleting tag: " + error); + NotificationManager.fromBackend("Error deleting tag: " + error); } setIsDeleteModalOpen(false); setTagToDelete(null); @@ -124,7 +125,7 @@ const TagManagement: React.FC = ({ } } catch (error) { console.error("Error fetching models:", error); - message.error("Error fetching models: " + error); + NotificationManager.fromBackend("Error fetching models: " + error); } }; fetchModels(); diff --git a/ui/litellm-dashboard/src/components/tag_management/tag_info.tsx b/ui/litellm-dashboard/src/components/tag_management/tag_info.tsx index a727ff7269..17bba32350 100644 --- a/ui/litellm-dashboard/src/components/tag_management/tag_info.tsx +++ b/ui/litellm-dashboard/src/components/tag_management/tag_info.tsx @@ -6,6 +6,7 @@ import { fetchUserModels } from "../organisms/create_key_button" import { getModelDisplayName } from "../key_team_helpers/fetch_available_models_team_key" import { tagInfoCall, tagUpdateCall } from "../networking" import { Tag, TagInfoResponse } from "./types" +import NotificationManager from "../molecules/notifications_manager"; interface TagInfoViewProps { tagId: string @@ -38,7 +39,7 @@ const TagInfoView: React.FC = ({ tagId, onClose, accessToken, } } catch (error) { console.error("Error fetching tag details:", error) - message.error("Error fetching tag details: " + error) + NotificationManager.fromBackend("Error fetching tag details: " + error) } } @@ -67,7 +68,7 @@ const TagInfoView: React.FC = ({ tagId, onClose, accessToken, fetchTagDetails() } catch (error) { console.error("Error updating tag:", error) - message.error("Error updating tag: " + error) + NotificationManager.fromBackend("Error updating tag: " + error) } } diff --git a/ui/litellm-dashboard/src/components/team/available_teams.tsx b/ui/litellm-dashboard/src/components/team/available_teams.tsx index 2959925f42..cda2a4f458 100644 --- a/ui/litellm-dashboard/src/components/team/available_teams.tsx +++ b/ui/litellm-dashboard/src/components/team/available_teams.tsx @@ -13,6 +13,7 @@ import { } from "@tremor/react"; import { message } from 'antd'; import { availableTeamListCall, teamMemberAddCall } from "../networking"; +import NotificationManager from "../molecules/notifications_manager"; interface AvailableTeam { team_id: string; @@ -64,7 +65,7 @@ const AvailableTeamsPanel: React.FC = ({ setAvailableTeams(teams => teams.filter(team => team.team_id !== teamId)); } catch (error) { console.error('Error joining team:', error); - message.error('Failed to join team'); + NotificationManager.fromBackend('Failed to join team'); } }; diff --git a/ui/litellm-dashboard/src/components/team/edit_membership.tsx b/ui/litellm-dashboard/src/components/team/edit_membership.tsx index 5ffc1dd594..4a60877247 100644 --- a/ui/litellm-dashboard/src/components/team/edit_membership.tsx +++ b/ui/litellm-dashboard/src/components/team/edit_membership.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { Modal, Form, Input, Select as AntSelect, Button as AntButton, message } from 'antd'; import { Select, SelectItem } from "@tremor/react"; import { Card, Text } from "@tremor/react"; +import NotificationManager from "../molecules/notifications_manager"; interface BaseMember { user_email?: string; @@ -80,7 +81,7 @@ const MemberModal = ({ form.resetFields(); // message.success(`Successfully ${mode === 'add' ? 'added' : 'updated'} member`); } catch (error) { - // message.error('Failed to submit form'); + // NotificationManager.fromBackend('Failed to submit form'); console.error('Form submission error:', error); } }; diff --git a/ui/litellm-dashboard/src/components/team/member_permissions.tsx b/ui/litellm-dashboard/src/components/team/member_permissions.tsx index 30dc317675..c7edf66a59 100644 --- a/ui/litellm-dashboard/src/components/team/member_permissions.tsx +++ b/ui/litellm-dashboard/src/components/team/member_permissions.tsx @@ -15,6 +15,7 @@ import { Button, message, Checkbox, Empty } from "antd" import { ReloadOutlined, SaveOutlined } from "@ant-design/icons" import { getTeamPermissionsCall, teamPermissionsUpdateCall } from "@/components/networking" import { getPermissionInfo } from "./permission_definitions" +import NotificationManager from "../molecules/notifications_manager"; interface MemberPermissionsProps { teamId: string @@ -40,7 +41,7 @@ const MemberPermissions: React.FC = ({ teamId, accessTok setSelectedPermissions(teamPermissions) setHasChanges(false) } catch (error) { - message.error("Failed to load permissions") + NotificationManager.fromBackend("Failed to load permissions") console.error("Error fetching permissions:", error) } finally { setLoading(false) @@ -67,7 +68,7 @@ const MemberPermissions: React.FC = ({ teamId, accessTok message.success("Permissions updated successfully") setHasChanges(false) } catch (error) { - message.error("Failed to update permissions") + NotificationManager.fromBackend("Failed to update permissions") console.error("Error updating permissions:", error) } finally { setSaving(false) diff --git a/ui/litellm-dashboard/src/components/team/team_info.tsx b/ui/litellm-dashboard/src/components/team/team_info.tsx index c21294c882..664a2a0fed 100644 --- a/ui/litellm-dashboard/src/components/team/team_info.tsx +++ b/ui/litellm-dashboard/src/components/team/team_info.tsx @@ -54,6 +54,7 @@ import LoggingSettingsView from "../logging_settings_view"; import { fetchMCPAccessGroups } from "../networking"; import { CheckIcon, CopyIcon } from "lucide-react"; import { copyToClipboard as utilCopyToClipboard } from "../../utils/dataUtils" +import NotificationManager from "../molecules/notifications_manager"; export interface TeamMembership { user_id: string; @@ -160,7 +161,7 @@ const TeamInfoView: React.FC = ({ const response = await teamInfoCall(accessToken, teamId); setTeamData(response); } catch (error) { - message.error("Failed to load team information"); + NotificationManager.fromBackend("Failed to load team information"); console.error("Error fetching team info:", error); } finally { setLoading(false); @@ -236,7 +237,7 @@ const TeamInfoView: React.FC = ({ errMsg = error.message; } - message.error(errMsg); + NotificationManager.fromBackend(errMsg); console.error("Error adding team member:", error); } }; @@ -281,7 +282,7 @@ const TeamInfoView: React.FC = ({ message.destroy(); // Remove all existing toasts - message.error(errMsg); + NotificationManager.fromBackend(errMsg); console.error("Error updating team member:", error); } }; @@ -303,7 +304,7 @@ const TeamInfoView: React.FC = ({ // Notify parent component of the update onUpdate(updatedTeamData); } catch (error) { - message.error("Failed to remove team member"); + NotificationManager.fromBackend("Failed to remove team member"); console.error("Error removing team member:", error); } }; @@ -316,7 +317,7 @@ const TeamInfoView: React.FC = ({ try { parsedMetadata = values.metadata ? JSON.parse(values.metadata) : {}; } catch (e) { - message.error("Invalid JSON in metadata field"); + NotificationManager.fromBackend("Invalid JSON in metadata field"); return; } diff --git a/ui/litellm-dashboard/src/components/teams.tsx b/ui/litellm-dashboard/src/components/teams.tsx index c9d74696a3..cc76334193 100644 --- a/ui/litellm-dashboard/src/components/teams.tsx +++ b/ui/litellm-dashboard/src/components/teams.tsx @@ -464,7 +464,7 @@ const Teams: React.FC = ({ } } catch (error) { console.error("Error creating the team:", error); - message.error("Error creating the team: " + error, 20); + NotificationManager.fromBackend("Error creating the team: " + error, 20); } }; diff --git a/ui/litellm-dashboard/src/components/transform_request.tsx b/ui/litellm-dashboard/src/components/transform_request.tsx index b55e562dff..4507f27286 100644 --- a/ui/litellm-dashboard/src/components/transform_request.tsx +++ b/ui/litellm-dashboard/src/components/transform_request.tsx @@ -3,6 +3,7 @@ import { Button, Select, Tabs, message } from 'antd'; import { CopyOutlined } from '@ant-design/icons'; import { Title } from '@tremor/react'; import { transformRequestCall } from './networking'; +import NotificationManager from "./molecules/notifications_manager"; interface TransformRequestPanelProps { accessToken: string | null; } @@ -67,7 +68,7 @@ ${formattedBody} try { requestBody = JSON.parse(originalRequestJSON); } catch (e) { - message.error('Invalid JSON in request body'); + NotificationManager.fromBackend('Invalid JSON in request body'); setIsLoading(false); return; } @@ -80,7 +81,7 @@ ${formattedBody} // Make the API call using fetch if (!accessToken) { - message.error('No access token found'); + NotificationManager.fromBackend('No access token found'); setIsLoading(false); return; } @@ -108,7 +109,7 @@ ${formattedBody} } } catch (err) { console.error('Error transforming request:', err); - message.error('Failed to transform request'); + NotificationManager.fromBackend('Failed to transform request'); } finally { setIsLoading(false); } diff --git a/ui/litellm-dashboard/src/components/ui_theme_settings.tsx b/ui/litellm-dashboard/src/components/ui_theme_settings.tsx index 8bdafe0148..bcc09a36ba 100644 --- a/ui/litellm-dashboard/src/components/ui_theme_settings.tsx +++ b/ui/litellm-dashboard/src/components/ui_theme_settings.tsx @@ -9,6 +9,7 @@ import { import { message } from "antd" import { useTheme } from "@/contexts/ThemeContext" import { getProxyBaseUrl } from "@/components/networking" +import NotificationManager from "./molecules/notifications_manager"; interface UIThemeSettingsProps { userID: string | null; @@ -79,7 +80,7 @@ const UIThemeSettings: React.FC = ({ } } catch (error) { console.error("Error updating logo settings:", error); - message.error("Failed to update logo settings"); + NotificationManager.fromBackend("Failed to update logo settings"); } finally { setLoading(false); } @@ -112,7 +113,7 @@ const UIThemeSettings: React.FC = ({ } } catch (error) { console.error("Error resetting logo:", error); - message.error("Failed to reset logo"); + NotificationManager.fromBackend("Failed to reset logo"); } finally { setLoading(false); } diff --git a/ui/litellm-dashboard/src/components/useful_links_management.tsx b/ui/litellm-dashboard/src/components/useful_links_management.tsx index ec2fb61665..5e7e4d6fac 100644 --- a/ui/litellm-dashboard/src/components/useful_links_management.tsx +++ b/ui/litellm-dashboard/src/components/useful_links_management.tsx @@ -14,6 +14,7 @@ import { TableRow, TableCell } from "@tremor/react"; +import NotificationManager from "./molecules/notifications_manager"; interface UsefulLinksManagementProps { accessToken: string | null; @@ -117,7 +118,7 @@ const UsefulLinksManagement: React.FC = ({ return true; } catch (error) { console.error("Error saving links:", error); - message.error(`Failed to save links - ${error}`); + NotificationManager.fromBackend(`Failed to save links - ${error}`); return false; } }; @@ -129,13 +130,13 @@ const UsefulLinksManagement: React.FC = ({ try { new URL(newLink.url); } catch { - message.error("Please enter a valid URL"); + NotificationManager.fromBackend("Please enter a valid URL"); return; } // Check for duplicate display names if (links.some(link => link.displayName === newLink.displayName)) { - message.error("A link with this display name already exists"); + NotificationManager.fromBackend("A link with this display name already exists"); return; } @@ -165,13 +166,13 @@ const UsefulLinksManagement: React.FC = ({ try { new URL(editingLink.url); } catch { - message.error("Please enter a valid URL"); + NotificationManager.fromBackend("Please enter a valid URL"); return; } // Check for duplicate display names (excluding current link) if (links.some(link => link.id !== editingLink.id && link.displayName === editingLink.displayName)) { - message.error("A link with this display name already exists"); + NotificationManager.fromBackend("A link with this display name already exists"); return; } diff --git a/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreForm.tsx b/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreForm.tsx index 99acccf3d3..bf0687c9e5 100644 --- a/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreForm.tsx +++ b/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreForm.tsx @@ -17,6 +17,7 @@ import { import { InfoCircleOutlined } from '@ant-design/icons'; import { CredentialItem, vectorStoreCreateCall } from "../networking"; import { VectorStoreProviders, vectorStoreProviderLogoMap, vectorStoreProviderMap, getProviderSpecificFields, VectorStoreFieldConfig } from "../vector_store_providers"; +import NotificationManager from "../molecules/notifications_manager"; interface VectorStoreFormProps { isVisible: boolean; @@ -45,7 +46,7 @@ const VectorStoreForm: React.FC = ({ try { metadata = metadataJson.trim() ? JSON.parse(metadataJson) : {}; } catch (e) { - message.error("Invalid JSON in metadata field"); + NotificationManager.fromBackend("Invalid JSON in metadata field"); return; } @@ -75,7 +76,7 @@ const VectorStoreForm: React.FC = ({ onSuccess(); } catch (error) { console.error("Error creating vector store:", error); - message.error("Error creating vector store: " + error); + NotificationManager.fromBackend("Error creating vector store: " + error); } }; diff --git a/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreTester.tsx b/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreTester.tsx index a70c0d6400..b066cfc4eb 100644 --- a/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreTester.tsx +++ b/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreTester.tsx @@ -2,6 +2,7 @@ import React, { useState } from "react"; import { Button, Input, Card, Typography, Spin, message, Divider } from "antd"; import { SendOutlined, DatabaseOutlined, LoadingOutlined, DownOutlined, RightOutlined } from "@ant-design/icons"; import { vectorStoreSearchCall } from "../networking"; +import NotificationManager from "../molecules/notifications_manager"; const { TextArea } = Input; const { Text, Title } = Typography; @@ -66,7 +67,7 @@ export const VectorStoreTester: React.FC = ({ setQuery(""); } catch (error) { console.error("Error searching vector store:", error); - message.error("Failed to search vector store"); + NotificationManager.fromBackend("Failed to search vector store"); } finally { setIsLoading(false); } diff --git a/ui/litellm-dashboard/src/components/vector_store_management/index.tsx b/ui/litellm-dashboard/src/components/vector_store_management/index.tsx index f31f75758f..18fa8c24bd 100644 --- a/ui/litellm-dashboard/src/components/vector_store_management/index.tsx +++ b/ui/litellm-dashboard/src/components/vector_store_management/index.tsx @@ -19,6 +19,7 @@ import VectorStoreForm from "./VectorStoreForm"; import DeleteModal from "./DeleteModal"; import VectorStoreInfoView from "./vector_store_info"; import { isAdminRole } from "@/utils/roles"; +import NotificationManager from "../molecules/notifications_manager"; interface VectorStoreProps { accessToken: string | null; @@ -48,7 +49,7 @@ const VectorStoreManagement: React.FC = ({ setVectorStores(response.data || []); } catch (error) { console.error("Error fetching vector stores:", error); - message.error("Error fetching vector stores: " + error); + NotificationManager.fromBackend("Error fetching vector stores: " + error); } }; @@ -60,7 +61,7 @@ const VectorStoreManagement: React.FC = ({ setCredentials(response.credentials || []); } catch (error) { console.error("Error fetching credentials:", error); - message.error("Error fetching credentials: " + error); + NotificationManager.fromBackend("Error fetching credentials: " + error); } }; @@ -100,7 +101,7 @@ const VectorStoreManagement: React.FC = ({ fetchVectorStores(); } catch (error) { console.error("Error deleting vector store:", error); - message.error("Error deleting vector store: " + error); + NotificationManager.fromBackend("Error deleting vector store: " + error); } setIsDeleteModalOpen(false); setVectorStoreToDelete(null); diff --git a/ui/litellm-dashboard/src/components/vector_store_management/vector_store_info.tsx b/ui/litellm-dashboard/src/components/vector_store_management/vector_store_info.tsx index d557207820..f7c34679b7 100644 --- a/ui/litellm-dashboard/src/components/vector_store_management/vector_store_info.tsx +++ b/ui/litellm-dashboard/src/components/vector_store_management/vector_store_info.tsx @@ -25,6 +25,7 @@ import { vectorStoreInfoCall, vectorStoreUpdateCall, credentialListCall, Credent import { VectorStore } from "./types"; import { Providers, providerLogoMap, provider_map } from "../provider_info_helpers"; import VectorStoreTester from "./VectorStoreTester"; +import NotificationManager from "../molecules/notifications_manager"; interface VectorStoreInfoViewProps { vectorStoreId: string; @@ -74,7 +75,7 @@ const VectorStoreInfoView: React.FC = ({ } } catch (error) { console.error("Error fetching vector store details:", error); - message.error("Error fetching vector store details: " + error); + NotificationManager.fromBackend("Error fetching vector store details: " + error); } }; @@ -102,7 +103,7 @@ const VectorStoreInfoView: React.FC = ({ try { metadata = metadataString ? JSON.parse(metadataString) : {}; } catch (e) { - message.error("Invalid JSON in metadata field"); + NotificationManager.fromBackend("Invalid JSON in metadata field"); return; } @@ -120,7 +121,7 @@ const VectorStoreInfoView: React.FC = ({ fetchVectorStoreDetails(); } catch (error) { console.error("Error updating vector store:", error); - message.error("Error updating vector store: " + error); + NotificationManager.fromBackend("Error updating vector store: " + error); } }; diff --git a/ui/litellm-dashboard/src/components/view_logs/RequestResponsePanel.tsx b/ui/litellm-dashboard/src/components/view_logs/RequestResponsePanel.tsx index 63d27555b4..939c0ce62f 100644 --- a/ui/litellm-dashboard/src/components/view_logs/RequestResponsePanel.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/RequestResponsePanel.tsx @@ -1,5 +1,6 @@ import { LogEntry } from "./columns"; import { message } from "antd"; +import NotificationManager from "../molecules/notifications_manager"; interface RequestResponsePanelProps { row: { @@ -57,7 +58,7 @@ export function RequestResponsePanel({ if (success) { message.success('Request copied to clipboard'); } else { - message.error('Failed to copy request'); + NotificationManager.fromBackend('Failed to copy request'); } }; @@ -66,7 +67,7 @@ export function RequestResponsePanel({ if (success) { message.success('Response copied to clipboard'); } else { - message.error('Failed to copy response'); + NotificationManager.fromBackend('Failed to copy response'); } }; diff --git a/ui/litellm-dashboard/src/components/view_users.tsx b/ui/litellm-dashboard/src/components/view_users.tsx index 0275454abd..55d0fd4e01 100644 --- a/ui/litellm-dashboard/src/components/view_users.tsx +++ b/ui/litellm-dashboard/src/components/view_users.tsx @@ -29,6 +29,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query" import { updateExistingKeys } from "@/utils/dataUtils" import { useDebouncedState } from "@tanstack/react-pacer/debouncer" import { isAdminRole } from "@/utils/roles" +import NotificationManager from "./molecules/notifications_manager" interface ViewUserDashboardProps { accessToken: string | null @@ -138,7 +139,7 @@ const ViewUserDashboard: React.FC = ({ accessToken, toke const handleResetPassword = async (userId: string) => { if (!accessToken) { - message.error("Access token not found") + NotificationManager.fromBackend("Access token not found") return } try { @@ -147,7 +148,7 @@ const ViewUserDashboard: React.FC = ({ accessToken, toke setInvitationLinkData(data) setIsInvitationLinkModalVisible(true) } catch (error) { - message.error("Failed to generate password reset link") + NotificationManager.fromBackend("Failed to generate password reset link") } } @@ -166,7 +167,7 @@ const ViewUserDashboard: React.FC = ({ accessToken, toke message.success("User deleted successfully") } catch (error) { console.error("Error deleting user:", error) - message.error("Failed to delete user") + NotificationManager.fromBackend("Failed to delete user") } } setIsDeleteModalOpen(false) @@ -228,7 +229,7 @@ const ViewUserDashboard: React.FC = ({ accessToken, toke const handleBulkEdit = () => { if (selectedUsers.length === 0) { - message.error("Please select users to edit") + NotificationManager.fromBackend("Please select users to edit") return } diff --git a/ui/litellm-dashboard/src/components/view_users/user_info_view.tsx b/ui/litellm-dashboard/src/components/view_users/user_info_view.tsx index 8686d6c633..6bfdc62a89 100644 --- a/ui/litellm-dashboard/src/components/view_users/user_info_view.tsx +++ b/ui/litellm-dashboard/src/components/view_users/user_info_view.tsx @@ -15,6 +15,7 @@ import { UserEditView } from "../user_edit_view" import OnboardingModal, { InvitationLink } from "../onboarding_link" import { formatNumberWithCommas, copyToClipboard as utilCopyToClipboard } from "@/utils/dataUtils" import { CopyIcon, CheckIcon } from "lucide-react"; +import NotificationManager from "../molecules/notifications_manager"; interface UserInfoViewProps { userId: string @@ -83,7 +84,7 @@ export default function UserInfoView({ setUserModels(availableModels) } catch (error) { console.error("Error fetching user data:", error) - message.error("Failed to fetch user data") + NotificationManager.fromBackend("Failed to fetch user data") } finally { setIsLoading(false) } @@ -94,7 +95,7 @@ export default function UserInfoView({ const handleResetPassword = async () => { if (!accessToken) { - message.error("Access token not found") + NotificationManager.fromBackend("Access token not found") return } try { @@ -103,7 +104,7 @@ export default function UserInfoView({ setInvitationLinkData(data) setIsInvitationLinkModalVisible(true) } catch (error) { - message.error("Failed to generate password reset link") + NotificationManager.fromBackend("Failed to generate password reset link") } } @@ -118,7 +119,7 @@ export default function UserInfoView({ onClose() } catch (error) { console.error("Error deleting user:", error) - message.error("Failed to delete user") + NotificationManager.fromBackend("Failed to delete user") } } @@ -144,7 +145,7 @@ export default function UserInfoView({ setIsEditing(false) } catch (error) { console.error("Error updating user:", error) - message.error("Failed to update user") + NotificationManager.fromBackend("Failed to update user") } } diff --git a/ui/litellm-dashboard/src/utils/dataUtils.ts b/ui/litellm-dashboard/src/utils/dataUtils.ts index 0aeefbadc0..b908c0b2c8 100644 --- a/ui/litellm-dashboard/src/utils/dataUtils.ts +++ b/ui/litellm-dashboard/src/utils/dataUtils.ts @@ -1,3 +1,4 @@ +import NotificationManager from "@/components/molecules/notifications_manager"; import { message } from "antd"; export function updateExistingKeys( @@ -35,7 +36,7 @@ export const copyToClipboard = async ( message.success(messageText); return true; } catch (err) { - message.error("Failed to copy to clipboard"); + NotificationManager.fromBackend("Failed to copy to clipboard"); console.error("Failed to copy: ", err); return false; }