From 8f376a60fafc8f7dad15e447a8696c1c64e26c20 Mon Sep 17 00:00:00 2001 From: Cole McIntosh Date: Thu, 26 Jun 2025 13:59:40 -0600 Subject: [PATCH] fix(ui): fix Today filter not showing usage data in dashboard - Fix date formatting in API calls from ISO format to YYYY-MM-DD - Update userDailyActivityCall, teamDailyActivityCall, and tagDailyActivityCall - Prevent date mutation by creating new Date objects before API calls - Set proper time boundaries (00:00:00 to 23:59:59) for same-day selections The API expects dates in YYYY-MM-DD format but the UI was sending full ISO timestamps, causing the Today filter to return empty results. --- .../src/components/entity_usage.tsx | 5 +-- .../src/components/networking.tsx | 35 +++++++++++++++---- .../src/components/new_usage.tsx | 5 +-- .../components/shared/usage_date_picker.tsx | 17 ++++++--- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/ui/litellm-dashboard/src/components/entity_usage.tsx b/ui/litellm-dashboard/src/components/entity_usage.tsx index 10af11b009c..a17bc66f7e6 100644 --- a/ui/litellm-dashboard/src/components/entity_usage.tsx +++ b/ui/litellm-dashboard/src/components/entity_usage.tsx @@ -95,8 +95,9 @@ const EntityUsage: React.FC = ({ const fetchSpendData = async () => { if (!accessToken || !dateValue.from || !dateValue.to) return; - const startTime = dateValue.from; - const endTime = dateValue.to; + // Create new Date objects to avoid mutating the original dates + const startTime = new Date(dateValue.from); + const endTime = new Date(dateValue.to); if (entityType === 'tag') { const data = await tagDailyActivityCall( diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx index 2ec8642458d..085fe5cfe9b 100644 --- a/ui/litellm-dashboard/src/components/networking.tsx +++ b/ui/litellm-dashboard/src/components/networking.tsx @@ -19,7 +19,7 @@ import { } from "./email_events/types"; const isLocal = process.env.NODE_ENV === "development"; -export const defaultProxyBaseUrl = isLocal ? "http://localhost:4000" : null; +export const defaultProxyBaseUrl = isLocal ? "http://localhost:43845" : null; const defaultServerRootPath = "/"; export let serverRootPath = defaultServerRootPath; export let proxyBaseUrl = defaultProxyBaseUrl; @@ -1333,8 +1333,15 @@ export const userDailyActivityCall = async ( ? `${proxyBaseUrl}/user/daily/activity` : `/user/daily/activity`; const queryParams = new URLSearchParams(); - queryParams.append("start_date", startTime.toISOString()); - queryParams.append("end_date", endTime.toISOString()); + // Format dates as YYYY-MM-DD for the API + const formatDate = (date: Date) => { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; + }; + queryParams.append("start_date", formatDate(startTime)); + queryParams.append("end_date", formatDate(endTime)); queryParams.append("page_size", "1000"); queryParams.append("page", page.toString()); const queryString = queryParams.toString(); @@ -1379,8 +1386,15 @@ export const tagDailyActivityCall = async ( ? `${proxyBaseUrl}/tag/daily/activity` : `/tag/daily/activity`; const queryParams = new URLSearchParams(); - queryParams.append("start_date", startTime.toISOString()); - queryParams.append("end_date", endTime.toISOString()); + // Format dates as YYYY-MM-DD for the API + const formatDate = (date: Date) => { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; + }; + queryParams.append("start_date", formatDate(startTime)); + queryParams.append("end_date", formatDate(endTime)); queryParams.append("page_size", "1000"); queryParams.append("page", page.toString()); if (tags) { @@ -1428,8 +1442,15 @@ export const teamDailyActivityCall = async ( ? `${proxyBaseUrl}/team/daily/activity` : `/team/daily/activity`; const queryParams = new URLSearchParams(); - queryParams.append("start_date", startTime.toISOString()); - queryParams.append("end_date", endTime.toISOString()); + // Format dates as YYYY-MM-DD for the API + const formatDate = (date: Date) => { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; + }; + queryParams.append("start_date", formatDate(startTime)); + queryParams.append("end_date", formatDate(endTime)); queryParams.append("page_size", "1000"); queryParams.append("page", page.toString()); if (teamIds) { diff --git a/ui/litellm-dashboard/src/components/new_usage.tsx b/ui/litellm-dashboard/src/components/new_usage.tsx index 294e041a631..3434f08c45a 100644 --- a/ui/litellm-dashboard/src/components/new_usage.tsx +++ b/ui/litellm-dashboard/src/components/new_usage.tsx @@ -212,8 +212,9 @@ const NewUsagePage: React.FC = ({ const fetchUserSpendData = async () => { if (!accessToken || !dateValue.from || !dateValue.to) return; - const startTime = dateValue.from; - const endTime = dateValue.to; + // Create new Date objects to avoid mutating the original dates + const startTime = new Date(dateValue.from); + const endTime = new Date(dateValue.to); try { // Get first page diff --git a/ui/litellm-dashboard/src/components/shared/usage_date_picker.tsx b/ui/litellm-dashboard/src/components/shared/usage_date_picker.tsx index 82f8aa24411..2d9bba75d56 100644 --- a/ui/litellm-dashboard/src/components/shared/usage_date_picker.tsx +++ b/ui/litellm-dashboard/src/components/shared/usage_date_picker.tsx @@ -23,19 +23,26 @@ const UsageDatePicker: React.FC = ({ }) => { const handleDateChange = (newValue: DateRangePickerValue) => { // Handle the case where "Today" or same-day selection is made - if (newValue.from && newValue.to) { + if (newValue.from) { const adjustedValue = { ...newValue }; // Create new Date objects to avoid mutating the original dates const adjustedStartTime = new Date(newValue.from); - const adjustedEndTime = new Date(newValue.to); + let adjustedEndTime: Date; - // Check if it's the same day (Today selection) + if (newValue.to) { + adjustedEndTime = new Date(newValue.to); + } else { + // If no end date is provided (like "Today" from dropdown), use the same date + adjustedEndTime = new Date(newValue.from); + } + + // Check if it's the same day (Today selection or single day selection) const isSameDay = adjustedStartTime.toDateString() === adjustedEndTime.toDateString(); if (isSameDay) { - // For same-day selections (like "Today"), set proper time boundaries + // For same-day selections, set proper time boundaries // Use local timezone boundaries that will be converted to UTC properly adjustedStartTime.setHours(0, 0, 0, 0); // Start of day in local time adjustedEndTime.setHours(23, 59, 59, 999); // End of day in local time @@ -50,7 +57,7 @@ const UsageDatePicker: React.FC = ({ onValueChange(adjustedValue); } else { - // If either date is missing, pass through as-is + // If no from date, pass through as-is onValueChange(newValue); } };