diff --git a/app/components/MainComponent.vue b/app/components/MainComponent.vue index 66b7c3dc..d7ea5eef 100644 --- a/app/components/MainComponent.vue +++ b/app/components/MainComponent.vue @@ -216,7 +216,7 @@
- + @@ -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'; @@ -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() { diff --git a/app/utils/tabUtils.ts b/app/utils/tabUtils.ts index e57e8fcf..49db7565 100644 --- a/app/utils/tabUtils.ts +++ b/app/utils/tabUtils.ts @@ -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; +} diff --git a/tests/tabUtils.loading.spec.ts b/tests/tabUtils.loading.spec.ts new file mode 100644 index 00000000..52d5cb30 --- /dev/null +++ b/tests/tabUtils.loading.spec.ts @@ -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) + }) +})