Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions app/components/MainComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@


<div v-show="!apiError">
<v-progress-linear v-show="!metricsReady && !signInRequired" indeterminate color="indigo" />
<v-progress-linear v-show="showActiveTabLoading" indeterminate color="indigo" />
<v-window v-show="(metricsReady && metrics.length) || (seatsReady && tab === 'seat analysis') || (userMetricsReady && tab === 'user metrics') || tab === 'my usage' || tab === 'billing' || (metricsReady && reportData.length > 0 && (tab === 'languages' || tab === 'editors'))" v-model="tab">
<v-window-item v-for="item in tabItems" :key="item" :value="item">
<v-card flat>
Expand Down Expand Up @@ -321,7 +321,7 @@ import AiChatPanel from './AiChatPanel.vue'
import AdminPanel from './AdminPanel.vue'
import { Options } from '@/model/Options';
import { useRoute } from 'vue-router';
import { applyHiddenTabs, applyHistoricalModeFilter } from '@/utils/tabUtils';
import { applyHiddenTabs, applyHistoricalModeFilter, shouldShowActiveTabLoading } from '@/utils/tabUtils';
import { routeParamStr } from '@/utils/routeUtils';
import { resolveDisplayName } from '#shared/utils/resolveDisplayName';

Expand Down Expand Up @@ -352,6 +352,15 @@ export default defineNuxtComponent({
showAnnouncementBanner(): boolean {
return !!this.announcementMessage && !this.announcementDismissed;
},
showActiveTabLoading(): boolean {
return shouldShowActiveTabLoading({
tab: this.tab,
signInRequired: this.signInRequired,
metricsReady: this.metricsReady,
seatsReady: this.seatsReady,
userMetricsReady: this.userMetricsReady,
});
},
},
methods: {
dismissAnnouncement() {
Expand Down
26 changes: 26 additions & 0 deletions app/utils/tabUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,29 @@ export function applyHiddenTabs(tabItems: string[], hiddenTabsConfig: string): s
export function applyHistoricalModeFilter(tabItems: string[], _enableHistoricalMode: boolean | string): string[] {
return tabItems;
}

export interface ActiveTabLoadingState {
tab: string | null;
signInRequired: boolean;
metricsReady: boolean;
seatsReady: boolean;
userMetricsReady: boolean;
}

/**
* Returns whether the shared loading indicator should be visible for the
* currently active tab.
*/
export function shouldShowActiveTabLoading(state: ActiveTabLoadingState): boolean {
if (state.signInRequired) return false;

if (state.tab === 'seat analysis') {
return !state.seatsReady;
}

if (state.tab === 'user metrics') {
return !state.userMetricsReady;
}

return !state.metricsReady;
}
44 changes: 44 additions & 0 deletions tests/tabUtils.loading.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { describe, expect, test } from 'vitest'
import { shouldShowActiveTabLoading } from '../app/utils/tabUtils'

describe('shouldShowActiveTabLoading', () => {
test('shows loading for seat analysis while seats data is not ready', () => {
expect(shouldShowActiveTabLoading({
tab: 'seat analysis',
signInRequired: false,
metricsReady: true,
seatsReady: false,
userMetricsReady: true,
})).toBe(true)
})

test('shows loading for user metrics while user metrics data is not ready', () => {
expect(shouldShowActiveTabLoading({
tab: 'user metrics',
signInRequired: false,
metricsReady: true,
seatsReady: true,
userMetricsReady: false,
})).toBe(true)
})

test('does not show loading on seat analysis when seats data is ready', () => {
expect(shouldShowActiveTabLoading({
tab: 'seat analysis',
signInRequired: false,
metricsReady: true,
seatsReady: true,
userMetricsReady: true,
})).toBe(false)
})

test('does not show loading when sign in is required', () => {
expect(shouldShowActiveTabLoading({
tab: 'seat analysis',
signInRequired: true,
metricsReady: false,
seatsReady: false,
userMetricsReady: false,
})).toBe(false)
})
})