refactor(ui): consolidate invitation flow into the dashboard layout - #32576
Conversation
Greptile SummaryThis PR consolidates the invitation entry point into the
Confidence Score: 5/5Safe to merge — the refactor is behavior-preserving, the new redirect path is covered by a focused layout test, and the removed code paths are genuinely unreachable. The invitation redirect logic is centralized in one well-tested place. The layout suppresses child rendering when isInvitationFlow is true, so the page component's redirectToLogin can never race with the layout redirect. Removed branches in page.tsx and user_dashboard.tsx were dead code once the layout took ownership. The explicitPage vs page fix in the legacy redirect is a correctness improvement with no regressions. No auth paths, data mutations, or API calls are affected. No files require special attention.
|
| Filename | Overview |
|---|---|
| ui/litellm-dashboard/src/app/(dashboard)/layout.tsx | Adds legacy-invitation-link redirect in LayoutContent: when invitation_id is present, shows LoadingScreen and calls router.replace toward /onboarding, suppressing the dashboard shell for that flow. |
| ui/litellm-dashboard/src/app/(dashboard)/layout.test.tsx | Adds a new test asserting that invitation_id in search params causes router.replace to be called with /onboarding and suppresses dashboard shell rendering; wires up replaceMock and mutable searchParamsValue properly. |
| ui/litellm-dashboard/src/app/(dashboard)/page.tsx | Removes duplicate teams state, UserDashboard branch, and invitation_id check; fixes legacy-redirect to use explicitPage instead of the defaulted page variable; renders ApiKeysDashboard unconditionally. |
| ui/litellm-dashboard/src/components/user_dashboard.tsx | Removes now-dead invitation_id early-return branch and the Onboarding import/useSearchParams call that supported it; no functional change to the component's normal rendering path. |
| ui/litellm-dashboard/eslint-metrics.json | Snapshot resynced: no-explicit-any decremented by 2 (two any casts removed); no-large-inline-object-arg incremented by 7 reflecting pre-existing drift captured by the full regeneration. |
Reviews (2): Last reviewed commit: "refactor(ui): consolidate invitation flo..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
The App Router migration is complete: every page is a path route and the legacy `?page=` switch is gone from the index. This closes it out. The `/ui/` index (page.tsx) kept its own duplicate copy of teams state, a teams fetch, and keys/addKey plumbing solely to feed a second `UserDashboard` render for the `invitation_id` case. That was redundant: `ApiKeysDashboard` already renders `UserDashboard` sourcing its own data, so the index is thinned to just render `<ApiKeysDashboard />`. The login redirect, the legacy `?page=` deep-link redirect for old bookmarks, and the post-login return-URL handling stay on the index. The invitation entry point now resolves in one place. Modern invitation links already point at the dedicated `/onboarding` route; the dashboard layout now redirects legacy `/ui/?invitation_id=` links there too (via `migratedHref`, the same base-aware redirect the index uses for `?page=`), instead of re-rendering that route's page component inline. This removes an import of one route's `page.tsx` into another module, and lets the now-unreachable `if (invitation_id) return <Onboarding/>` branch in the shared `user_dashboard.tsx` be deleted along with its dead `Onboarding` import and `searchParams` read. A layout test asserts the redirect and fails if it regresses. `legacyPageHref` and the sidebar's migrated-vs-legacy href fallback are left in place; they are still live for the parent-category nav nodes (agentic, tools, experimental, settings) that are not page routes. eslint-metrics.json is resynced: -2 no-explicit-any from the removed `any` casts, plus pre-existing drift the gate requires the snapshot to match.
184ba4e to
6b9fc41
Compare
|
@greptileai re review |
…erriAI#32576) The App Router migration is complete: every page is a path route and the legacy `?page=` switch is gone from the index. This closes it out. The `/ui/` index (page.tsx) kept its own duplicate copy of teams state, a teams fetch, and keys/addKey plumbing solely to feed a second `UserDashboard` render for the `invitation_id` case. That was redundant: `ApiKeysDashboard` already renders `UserDashboard` sourcing its own data, so the index is thinned to just render `<ApiKeysDashboard />`. The login redirect, the legacy `?page=` deep-link redirect for old bookmarks, and the post-login return-URL handling stay on the index. The invitation entry point now resolves in one place. Modern invitation links already point at the dedicated `/onboarding` route; the dashboard layout now redirects legacy `/ui/?invitation_id=` links there too (via `migratedHref`, the same base-aware redirect the index uses for `?page=`), instead of re-rendering that route's page component inline. This removes an import of one route's `page.tsx` into another module, and lets the now-unreachable `if (invitation_id) return <Onboarding/>` branch in the shared `user_dashboard.tsx` be deleted along with its dead `Onboarding` import and `searchParams` read. A layout test asserts the redirect and fails if it regresses. `legacyPageHref` and the sidebar's migrated-vs-legacy href fallback are left in place; they are still live for the parent-category nav nodes (agentic, tools, experimental, settings) that are not page routes. eslint-metrics.json is resynced: -2 no-explicit-any from the removed `any` casts, plus pre-existing drift the gate requires the snapshot to match.
Relevant issues
Linear ticket
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaito re-request a review after pushing changes)Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
This is a behavior-preserving refactor of the dashboard shell, so the proof is that the three entry points the index touches still behave identically. Run the dev proxy (and the UI dev server if you want the fast path), log in, then walk these in order and screenshot each:
http://localhost:4000/ui/renders the API Keys landing (virtual keys table), same as beforehttp://localhost:4000/ui/?page=teamsimmediately redirects tohttp://localhost:4000/ui/teams(legacy bookmark back-compat still works)/ui/onboarding?invitation_id=; the legacy/ui/?invitation_id=shape now redirects to that same onboarding route with the params preserved/ui/and confirm it still bounces to the SSO login with aredirect_toback to where you wereLocal checks captured at commit 6b9fc41:
npx vitest runon the touched suites (layout, CreateKeyPage, migratedPages, ApiKeysDashboard, user_dashboard) all green,npm run buildcompiles every route, andmake pre-commitpasses.Type
🧹 Refactoring
Changes
The App Router migration is finished; every page is a real path route and the legacy
?page=switch is already gone from the index. This is the closeout.The
/ui/index page carried its own duplicate copy of teams state, a teams fetch, and keys/addKey plumbing, all so it could render a secondUserDashboardfor theinvitation_idcase. That was redundant becauseApiKeysDashboardalready rendersUserDashboardsourcing its own data. The index is thinned to just render<ApiKeysDashboard />; the login redirect, the legacy?page=deep-link redirect for old bookmarks, and the post-login return-URL handling all stay putThe invitation entry point now resolves in one place. Modern invitation links already point at the dedicated
/onboardingroute, so the dashboard layout redirects legacy/ui/?invitation_id=links there too, preserving the query params. It does this withmigratedHref, the same base-path-aware redirect the index already uses for?page=, soSERVER_ROOT_PATHdeployments resolve correctly. This replaces the previous approach of importing the/onboardingroute'spage.tsxinto another module and re-rendering it inline. With that gone, the now-unreachableif (invitation_id != null) return <Onboarding/>branch in the shareduser_dashboard.tsxis deleted here as well, along with its deadOnboardingimport andsearchParamsread. A layout test asserts the redirect and fails if it regressesWhile mapping this out I found that
legacyPageHrefand the sidebar's migrated-vs-legacy href fallback are not dead: the parent-category nav nodes (agentic, tools, experimental, settings) are not page routes and still flow through the legacy path builder, so removing it would break their hrefs. It is intentionally left in place, which narrows this PR from the original closeout sketcheslint-metrics.json is resynced. The change removes two
anycasts (no-explicit-any 1982 to 1980); the snapshot also picks up pre-existing drift on no-large-inline-object-arg (512 to 519) that the gate requires the file to match, sincelint:metricsregenerates the whole snapshot rather than a single rule