mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-11 22:51:28 +00:00
fix(ui): block usage export while the first activity page is loading
Also drop the explanatory comments the repo guidelines disallow. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
fe131b807a
commit
45ad441c48
4 changed files with 19 additions and 12 deletions
|
|
@ -74,14 +74,6 @@ const mergeDay = (a: DailyData, b: DailyData): DailyData => ({
|
|||
breakdown: mergeBreakdown(a.breakdown, b.breakdown),
|
||||
});
|
||||
|
||||
/**
|
||||
* Combine daily activity pages into one series with a single entry per date.
|
||||
*
|
||||
* The backend paginates over raw spend rows, so a date whose rows straddle a
|
||||
* page boundary comes back once per page, each entry holding only that page's
|
||||
* share of the day. Concatenating those entries leaves duplicate dates that
|
||||
* under-report every per-day figure in the charts and the CSV export.
|
||||
*/
|
||||
export const mergeDailyResults = (existing: readonly DailyData[], incoming: readonly DailyData[]): DailyData[] =>
|
||||
incoming.reduce<DailyData[]>(
|
||||
(acc, day) => {
|
||||
|
|
|
|||
|
|
@ -119,6 +119,24 @@ describe("usePaginatedDailyActivity", () => {
|
|||
expect(result.current.incomplete).toBe(false);
|
||||
});
|
||||
|
||||
it("stays incomplete while the first page is still in flight", async () => {
|
||||
let resolveFirstPage: (value: ReturnType<typeof page>) => void = () => {};
|
||||
const fetchFn = vi.fn().mockReturnValueOnce(
|
||||
new Promise<ReturnType<typeof page>>((resolve) => {
|
||||
resolveFirstPage = resolve;
|
||||
}),
|
||||
);
|
||||
|
||||
const { result } = renderHook(() => usePaginatedDailyActivity({ fetchFn, args, enabled: true }));
|
||||
|
||||
await waitFor(() => expect(result.current.loading).toBe(true), { timeout: 3000 });
|
||||
expect(result.current.incomplete).toBe(true);
|
||||
|
||||
resolveFirstPage(page("2026-06-25", 22.38, 1, 1));
|
||||
|
||||
await waitFor(() => expect(result.current.incomplete).toBe(false), { timeout: 3000 });
|
||||
});
|
||||
|
||||
it("flags the range as incomplete when a page fetch fails instead of looking complete", async () => {
|
||||
const fetchFn = vi
|
||||
.fn()
|
||||
|
|
|
|||
|
|
@ -49,9 +49,7 @@ interface UsePaginatedDailyActivityReturn {
|
|||
isFetchingMore: boolean;
|
||||
progress: PaginationProgress;
|
||||
cancelled: boolean;
|
||||
/** True when a page fetch failed, so the data on screen covers only part of the range. */
|
||||
failed: boolean;
|
||||
/** True whenever the data on screen is known not to cover the whole requested range. */
|
||||
incomplete: boolean;
|
||||
cancel: () => void;
|
||||
}
|
||||
|
|
@ -250,7 +248,7 @@ export function usePaginatedDailyActivity({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [enabled, fetchFn, argsKey]);
|
||||
|
||||
const incomplete = isFetchingMore || cancelled || failed;
|
||||
const incomplete = loading || isFetchingMore || cancelled || failed;
|
||||
|
||||
return { data, loading, isFetchingMore, progress, cancelled, failed, incomplete, cancel };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ interface UsageExportHeaderProps {
|
|||
customTitle?: string;
|
||||
compactLayout?: boolean;
|
||||
teams?: Team[];
|
||||
/** Blocks the export while the data on screen does not cover the whole requested range. */
|
||||
exportDisabled?: boolean;
|
||||
exportDisabledReason?: string;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue