35
35
</v-toolbar >
36
36
37
37
<!-- Date Range Selector - Hidden for seats tab -->
38
- <DateRangeSelector
39
- v-show =" tab !== 'seat analysis' && !signInRequired"
40
- :loading =" isLoading"
41
- @date-range-changed =" handleDateRangeChange"
42
- />
43
-
38
+ <DateRangeSelector v-show =" tab !== 'seat analysis' && !signInRequired" :loading =" isLoading"
39
+ @date-range-changed =" handleDateRangeChange" />
40
+
44
41
<!-- Organization info for seats tab -->
45
42
<div v-if =" tab === 'seat analysis'" class =" organization-info" >
46
43
<v-card flat class =" pa-3 mb-2" >
72
69
<v-window-item v-for =" item in tabItems" :key =" item" :value =" item" >
73
70
<v-card flat >
74
71
<MetricsViewer v-if =" item === itemName" :metrics =" metrics" :date-range-description =" dateRangeDescription" />
75
- <BreakdownComponent v-if =" item === 'languages'" :metrics =" metrics" :breakdown-key =" 'language'" :date-range-description =" dateRangeDescription" />
76
- <BreakdownComponent v-if =" item === 'editors'" :metrics =" metrics" :breakdown-key =" 'editor'" :date-range-description =" dateRangeDescription" />
77
- <CopilotChatViewer v-if =" item === 'copilot chat'" :metrics =" metrics" :date-range-description =" dateRangeDescription" />
72
+ <BreakdownComponent v-if =" item === 'languages'" :metrics =" metrics" :breakdown-key =" 'language'"
73
+ :date-range-description =" dateRangeDescription" />
74
+ <BreakdownComponent v-if =" item === 'editors'" :metrics =" metrics" :breakdown-key =" 'editor'"
75
+ :date-range-description =" dateRangeDescription" />
76
+ <CopilotChatViewer v-if =" item === 'copilot chat'" :metrics =" metrics"
77
+ :date-range-description =" dateRangeDescription" />
78
78
<SeatsAnalysisViewer v-if =" item === 'seat analysis'" :seats =" seats" />
79
- <ApiResponse
80
- v-if =" item === 'api response'" :metrics =" metrics" :original-metrics =" originalMetrics"
79
+ <ApiResponse v-if =" item === 'api response'" :metrics =" metrics" :original-metrics =" originalMetrics"
81
80
:seats =" seats" />
82
81
</v-card >
83
82
</v-window-item >
84
83
<v-alert
85
- v-show =" (metricsReady && metrics.length == 0 && tab !== 'seat analysis') || (seatsReady && seats.length == 0 && tab === 'seat analysis')" density = " compact " text = " No data available to display "
86
- title =" No data" type =" warning" />
84
+ v-show =" (metricsReady && metrics.length == 0 && tab !== 'seat analysis') || (seatsReady && seats.length == 0 && tab === 'seat analysis')"
85
+ density = " compact " text = " No data available to display " title =" No data" type =" warning" />
87
86
</v-window >
88
87
89
88
</div >
@@ -104,6 +103,8 @@ import CopilotChatViewer from './CopilotChatViewer.vue'
104
103
import SeatsAnalysisViewer from ' ./SeatsAnalysisViewer.vue'
105
104
import ApiResponse from ' ./ApiResponse.vue'
106
105
import DateRangeSelector from ' ./DateRangeSelector.vue'
106
+ import { Options } from ' @/model/Options' ;
107
+ import { useRoute } from ' vue-router' ;
107
108
108
109
export default defineNuxtComponent ({
109
110
name: ' MainComponent' ,
@@ -120,28 +121,42 @@ export default defineNuxtComponent({
120
121
const { clear } = useUserSession ()
121
122
this .metrics = [];
122
123
this .seats = [];
123
- // console.log('metrics are now', this.metrics);
124
124
clear ();
125
125
},
126
- async handleDateRangeChange(dateRange : { since? : string ; until? : string ; description: string }) {
127
- this .dateRangeDescription = dateRange .description ;
126
+ async handleDateRangeChange(newDateRange : { since? : string ; until? : string ; description: string }) {
127
+ this .dateRangeDescription = newDateRange .description ;
128
+ this .dateRange = {
129
+ since: newDateRange .since ,
130
+ until: newDateRange .until
131
+ };
132
+
133
+ await this .fetchMetrics ();
134
+ },
135
+ async fetchMetrics() {
136
+ if (this .signInRequired || ! this .dateRange .since || ! this .dateRange .until || this .isLoading ) {
137
+ return ;
138
+ }
139
+ const config = useRuntimeConfig ();
140
+
128
141
this .isLoading = true ;
129
-
142
+
130
143
try {
131
- // Build query parameters
132
- const params = new URLSearchParams ();
133
- if (dateRange .since ) params .append (' since' , dateRange .since );
134
- if (dateRange .until ) params .append (' until' , dateRange .until );
135
-
136
- const queryString = params .toString ();
144
+ const options = Options .fromRoute (this .route , this .dateRange .since , this .dateRange .until );
145
+ const params = options .toParams ();
146
+
147
+ const queryString = new URLSearchParams (params ).toString ();
137
148
const apiUrl = queryString ? ` /api/metrics?${queryString } ` : ' /api/metrics' ;
138
-
149
+
139
150
const response = await $fetch (apiUrl ) as MetricsApiResponse ;
140
-
151
+
141
152
this .metrics = response .metrics || [];
142
153
this .originalMetrics = response .usage || [];
143
154
this .metricsReady = true ;
144
- this .apiError = undefined ;
155
+
156
+ if (config .public .scope && config .public .scope .includes (' team' ) && this .metrics .length === 0 && ! this .apiError ) {
157
+ this .apiError = ' No data returned from API - check if the team exists and has any activity and at least 5 active members' ;
158
+ }
159
+
145
160
} catch (error : any ) {
146
161
this .processError (error );
147
162
} finally {
@@ -185,7 +200,7 @@ export default defineNuxtComponent({
185
200
seatsReady: false ,
186
201
seats: [] as Seat [],
187
202
apiError: undefined as string | undefined ,
188
- config: null as any
203
+ config: null as ReturnType < typeof useRuntimeConfig > | null
189
204
}
190
205
},
191
206
created() {
@@ -195,27 +210,22 @@ export default defineNuxtComponent({
195
210
async mounted() {
196
211
// Load initial data
197
212
try {
198
- const { data : metricsData, error : metricsError } = await this .metricsFetch ;
199
- if (metricsError .value || ! metricsData .value ) {
200
- this .processError (metricsError .value as H3Error );
201
- } else {
202
- const apiResponse = metricsData .value as MetricsApiResponse ;
203
- this .metrics = apiResponse .metrics || [];
204
- this .originalMetrics = apiResponse .usage || [];
205
- this .metricsReady = true ;
206
- }
207
213
208
- if (this .config .public .scope === ' team' && this .metrics .length === 0 && ! this .apiError ) {
209
- this .apiError = ' No data returned from API - check if the team exists and has any activity and at least 5 active members' ;
210
- }
214
+ await this .fetchMetrics ();
211
215
212
- const { data : seatsData, error : seatsError } = await this .seatsFetch ;
213
- if (seatsError .value ) {
214
- this .processError (seatsError .value as H3Error );
215
- } else {
216
- this .seats = seatsData .value || [];
217
- this .seatsReady = true ;
216
+ const { data : seatsData, error : seatsError, execute : executeSeats } = this .seatsFetch ;
217
+
218
+ if (! this .signInRequired ) {
219
+ await executeSeats ();
220
+
221
+ if (seatsError .value ) {
222
+ this .processError (seatsError .value as H3Error );
223
+ } else {
224
+ this .seats = (seatsData .value as Seat []) || [];
225
+ this .seatsReady = true ;
226
+ }
218
227
}
228
+
219
229
} catch (error ) {
220
230
console .error (' Error loading initial data:' , error );
221
231
}
@@ -228,19 +238,21 @@ export default defineNuxtComponent({
228
238
const itemName = computed (() => config .public .scope );
229
239
const githubInfo = getDisplayName (config .public )
230
240
const displayName = computed (() => githubInfo );
241
+ const dateRange = ref ({ since: undefined as string | undefined , until: undefined as string | undefined });
242
+ const isLoading = ref (false );
243
+ const route = ref (useRoute ());
231
244
232
245
const signInRequired = computed (() => {
233
246
return config .public .usingGithubAuth && ! loggedIn .value ;
234
247
});
235
248
236
- // Initial data load with default date range
237
- const metricsFetch = useFetch (' /api/metrics' , {
238
- key: ' initial-metrics' ,
239
- server: true
240
- });
241
- const seatsFetch = useFetch (' /api/seats' , {
242
- key: ' initial-seats' ,
243
- server: true
249
+ const seatsFetch = useFetch (' /api/seats' , {
250
+ server: true ,
251
+ immediate: ! signInRequired .value ,
252
+ query: computed (() => {
253
+ const options = Options .fromRoute (route .value );
254
+ return options .toParams ();
255
+ })
244
256
});
245
257
246
258
return {
@@ -250,8 +262,10 @@ export default defineNuxtComponent({
250
262
displayName ,
251
263
signInRequired ,
252
264
user ,
253
- metricsFetch ,
254
- seatsFetch
265
+ seatsFetch ,
266
+ dateRange ,
267
+ isLoading ,
268
+ route ,
255
269
};
256
270
},
257
271
})
0 commit comments