Skip to content

fix(ui): add paginated team search to usage page filter#25107

Merged
ryan-crabbe-berri merged 2 commits intolitellm_ryan-march-31from
litellm_fix-team-id-search-filter
Apr 3, 2026
Merged

fix(ui): add paginated team search to usage page filter#25107
ryan-crabbe-berri merged 2 commits intolitellm_ryan-march-31from
litellm_fix-team-id-search-filter

Conversation

@ryan-crabbe-berri
Copy link
Copy Markdown
Collaborator

@ryan-crabbe-berri ryan-crabbe-berri commented Apr 3, 2026

Summary

  • Bug: Team ID wasn't showing up when typing in the usage page team filter — users were forced to scroll through all teams
  • Root cause: The old filter used a static <Select> with no showSearch, loading all teams upfront via the unpaginated v1 /team/list endpoint
  • Fix: Created a new TeamMultiSelect component that mirrors the existing TeamDropdown pattern — paginated v2/team/list endpoint, debounced server-side search, infinite scroll. Options display both team alias and team ID so users can search by either

Screenshot

Screenshot 2026-04-03 at 2 09 23 PM Screenshot 2026-04-03 at 2 19 37 PM

greptile comment not real bug

Screenshot 2026-04-03 at 2 36 41 PM

Test plan

  • Go to Usage page → Team Usage tab
  • Verify the team filter dropdown is full-width and shows "Search teams by name or ID..."
  • Type a team alias — verify results filter as you type
  • Select multiple teams — verify usage data filters correctly
  • Scroll to bottom of dropdown — verify more teams load (infinite scroll)
  • Verify other entity type filters (org, customer, tag) are unaffected

Replace the static team dropdown on the usage page with a new
TeamMultiSelect component that uses the paginated v2/team/list
endpoint with debounced server-side search and infinite scroll.
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Apr 3, 2026 9:38pm

Request Review

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 3, 2026

Greptile Summary

This PR replaces the static, unpaginated team filter on the Usage page's Team Usage tab with a new TeamMultiSelect component that uses the paginated v2/team/list endpoint, debounced server-side search, and infinite scroll — addressing a real UX regression where large team lists made the filter unusable. The approach correctly mirrors the existing TeamDropdown pattern, and the selected team IDs wire correctly into both the backend data-fetch argument (entityFilterArg) and the client-side filterDataByTags function.

Key changes:

  • New TeamMultiSelect component with useInfiniteTeams, debounced search via @tanstack/react-pacer, infinite scroll, and duplicate-safe page accumulation
  • showFilters guard updated so the old UsageExportHeader filter is suppressed for the \"team\" entity type and replaced by TeamMultiSelect
  • Two issues were flagged in prior review rounds and remain open: selected chips lose their display label when search results evict the option (label-in-value pattern needed), and the search only matches team_alias despite the placeholder suggesting ID search is supported
  • Minor new finding: options for teams without a team_alias render an invisible label; a ?? \"(unnamed)\" fallback is recommended

Confidence Score: 4/5

Safe to merge for the core paginated-search improvement; two prior-thread issues (chip label loss, ID-search mismatch) are still open and affect correctness of the UX promise made in the PR description.

The new component is architecturally clean and follows established patterns. The two unresolved issues from prior rounds (selected chip labels dropping after search, alias-only search despite ID-search promise) are real UX defects the author should address before declaring the feature complete, hence 4 rather than 5.

ui/litellm-dashboard/src/components/common_components/team_multi_select.tsx — chip label persistence and search-by-ID claims still need resolution.

Important Files Changed

Filename Overview
ui/litellm-dashboard/src/components/common_components/team_multi_select.tsx New paginated multi-select component for teams — mirrors TeamDropdown pattern correctly with debounced search, infinite scroll deduplication, and server-side filtering; two pre-existing issues flagged in prior threads (label loss on search, alias-only search); minor null alias rendering concern flagged here.
ui/litellm-dashboard/src/components/UsagePage/components/EntityUsage/EntityUsage.tsx Integrates TeamMultiSelect for the team entity type; correctly hides the old UsageExportHeader filter for teams via showFilters guard; selected team IDs flow correctly to both the backend API arg and client-side filterDataByTags.

Sequence Diagram

sequenceDiagram
    participant U as User
    participant TMS as TeamMultiSelect
    participant Hook as useInfiniteTeams
    participant API as v2/team/list
    participant EU as EntityUsage
    participant DA as teamDailyActivityCall

    U->>TMS: types search term
    TMS->>TMS: setSearchInput (immediate, controls searchValue)
    TMS->>Hook: setDebouncedSearch after 300ms
    Hook->>API: GET /v2/team/list?team_alias=&page=1
    API-->>Hook: TeamsResponse {teams, total_pages}
    Hook-->>TMS: data.pages[]
    TMS-->>U: renders deduplicated team options

    U->>TMS: scrolls to 80% of dropdown
    TMS->>Hook: fetchNextPage()
    Hook->>API: GET /v2/team/list?team_alias=&page=2
    API-->>Hook: next TeamsResponse
    Hook-->>TMS: appended to data.pages

    U->>TMS: selects team IDs
    TMS->>EU: onChange(selectedTags)
    EU->>EU: entityFilterArg = selectedTags
    EU->>DA: fetch(accessToken, start, end, entityFilterArg)
    DA-->>EU: filtered SpendData
    EU->>EU: filterDataByTags (client-side)
    EU-->>U: renders filtered usage charts
Loading

Reviews (2): Last reviewed commit: "fix(ui): fix imports and update placehol..." | Re-trigger Greptile

Comment on lines +102 to +107
{teams.map((team) => (
<Select.Option key={team.team_id} value={team.team_id}>
<span className="font-medium">{team.team_alias}</span>{" "}
<Text type="secondary">({team.team_id})</Text>
</Select.Option>
))}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Selected chips lose their display label after a search

Ant Design's <Select mode="multiple" /> uses the option's children/label to render the selected-value chips. When a user selects a team (e.g. "My Team (team_abc123)") and then types a new search term that evicts those options from the list, the chip falls back to rendering the raw value string — losing the human-readable alias.

A common fix is to always keep previously-selected teams in the options list regardless of the current search results, or pass labelInValue to Ant Design Select so the label is stored alongside the selected value and doesn't depend on the current options list.

@ryan-crabbe-berri ryan-crabbe-berri temporarily deployed to integration-redis-postgres April 3, 2026 21:36 — with GitHub Actions Inactive
@ryan-crabbe-berri ryan-crabbe-berri temporarily deployed to integration-postgres April 3, 2026 21:36 — with GitHub Actions Inactive
@ryan-crabbe-berri ryan-crabbe-berri temporarily deployed to integration-postgres April 3, 2026 21:36 — with GitHub Actions Inactive
@ryan-crabbe-berri ryan-crabbe-berri temporarily deployed to integration-postgres April 3, 2026 21:36 — with GitHub Actions Inactive
@ryan-crabbe-berri ryan-crabbe-berri temporarily deployed to integration-postgres April 3, 2026 21:36 — with GitHub Actions Inactive
@ryan-crabbe-berri ryan-crabbe-berri merged commit 0575c3f into litellm_ryan-march-31 Apr 3, 2026
50 of 58 checks passed
@ryan-crabbe-berri ryan-crabbe-berri deleted the litellm_fix-team-id-search-filter branch April 3, 2026 23:06
fede-kamel pushed a commit to fede-kamel/litellm that referenced this pull request Apr 5, 2026
…rch-filter

fix(ui): add paginated team search to usage page filter
xykong pushed a commit to xykong/litellm that referenced this pull request Apr 15, 2026
User Usage filter only allowed selecting from a static preloaded list,
unlike Global Usage which supports debounced text search via useInfiniteUsers.

Add UserSingleSelect component (single-select with useInfiniteUsers +
300ms debounce + infinite scroll) and wire it into EntityUsage for
entityType === 'user', mirroring the TeamMultiSelect fix in PR BerriAI#25107.

- Add src/components/common_components/user_single_select.tsx
- Add src/components/common_components/user_single_select.test.tsx (10 tests)
- Update EntityUsage.tsx to render UserSingleSelect for user entity type
- Update EntityUsage.test.tsx to mock user_single_select
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant