Describe the bug
The app shows exactly one loading indicator (v-progress-linear) gated on !metricsReady, which only tracks the default "enterprise" tab's data. The "Seat analysis" and "User metrics" tabs have their own readiness flags (seatsReady, userMetricsReady) that are not wired to that indicator or to any indicator of their own. Since tabs are client-side v-window panels (not separate routes — there's no route navigation to hook a loading indicator into), switching to either tab before its data has loaded renders a completely blank content area with zero feedback that anything is happening.
Environment
- copilot-metrics-viewer v3.11.4
- Enterprise/organization scope, first load or a tab switch before that tab's data has arrived
Steps to reproduce
- Load the dashboard (or wait until the default "enterprise" tab has finished loading, so the shared progress bar disappears).
- Immediately click the "Seat analysis" or "User metrics" tab, before its own data fetch (
/api/seats or /api/user-metrics) has resolved.
- Observe a blank content area — no spinner, no progress bar, no skeleton — until the fetch completes.
Root cause (code references)
app/components/MainComponent.vue:219 — the only loading indicator: <v-progress-linear v-show="!metricsReady && !signInRequired" ... />, keyed solely to metricsReady.
app/components/MainComponent.vue:220 — the entire v-window (all tab panels) is hidden by one combined v-show: (metricsReady && metrics.length) || (seatsReady && tab === 'seat analysis') || (userMetricsReady && tab === 'user metrics') || tab === 'my usage' || tab === 'billing' || (...). When on the seat-analysis/user-metrics tab and its Ready flag is still false, this whole expression is false, so the window — and everything in it — is hidden, with the line-219 progress bar not showing because metricsReady may already be true.
app/components/SeatsAnalysisViewer.vue — no v-progress-linear/v-progress-circular at all, so even if the parent stopped hiding it, the component itself has no loading state of its own.
- Not fixable with Nuxt's built-in
NuxtLoadingIndicator: tabs are plain component state (v-model="tab"), not Nuxt route navigations, so that indicator would never fire on a tab switch.
Expected behavior
Some visible loading feedback (progress bar/spinner/skeleton) while seatsReady/userMetricsReady is false and that tab is active — consistent with what the enterprise tab already gets.
Suggested fix
- Extend the condition on the line-219 progress bar (or add a small per-branch one) to also cover
!seatsReady && tab === 'seat analysis' and !userMetricsReady && tab === 'user metrics', so the "loading" affordance follows whichever tab is actually active instead of only the enterprise tab.
- Alternatively, give each tab-gated branch its own local
v-progress-linear/skeleton inside the corresponding viewer component, so it doesn't depend on a shared flag in the parent.
Describe the bug
The app shows exactly one loading indicator (
v-progress-linear) gated on!metricsReady, which only tracks the default "enterprise" tab's data. The "Seat analysis" and "User metrics" tabs have their own readiness flags (seatsReady,userMetricsReady) that are not wired to that indicator or to any indicator of their own. Since tabs are client-sidev-windowpanels (not separate routes — there's no route navigation to hook a loading indicator into), switching to either tab before its data has loaded renders a completely blank content area with zero feedback that anything is happening.Environment
Steps to reproduce
/api/seatsor/api/user-metrics) has resolved.Root cause (code references)
app/components/MainComponent.vue:219— the only loading indicator:<v-progress-linear v-show="!metricsReady && !signInRequired" ... />, keyed solely tometricsReady.app/components/MainComponent.vue:220— the entirev-window(all tab panels) is hidden by one combinedv-show:(metricsReady && metrics.length) || (seatsReady && tab === 'seat analysis') || (userMetricsReady && tab === 'user metrics') || tab === 'my usage' || tab === 'billing' || (...). When on the seat-analysis/user-metrics tab and itsReadyflag is still false, this whole expression is false, so the window — and everything in it — is hidden, with the line-219 progress bar not showing becausemetricsReadymay already betrue.app/components/SeatsAnalysisViewer.vue— nov-progress-linear/v-progress-circularat all, so even if the parent stopped hiding it, the component itself has no loading state of its own.NuxtLoadingIndicator: tabs are plain component state (v-model="tab"), not Nuxt route navigations, so that indicator would never fire on a tab switch.Expected behavior
Some visible loading feedback (progress bar/spinner/skeleton) while
seatsReady/userMetricsReadyis false and that tab is active — consistent with what the enterprise tab already gets.Suggested fix
!seatsReady && tab === 'seat analysis'and!userMetricsReady && tab === 'user metrics', so the "loading" affordance follows whichever tab is actually active instead of only the enterprise tab.v-progress-linear/skeleton inside the corresponding viewer component, so it doesn't depend on a shared flag in the parent.