Skip to content

Commit b8a6f3f

Browse files
authored
Fixes for team enterprise (#232)
* Fixes for team enteprise * fixed PR comment * tests * version 2.0.6
1 parent 7cefc84 commit b8a6f3f

File tree

12 files changed

+1258
-141
lines changed

12 files changed

+1258
-141
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,12 @@ can be overriden by route parameters, e.g.
100100
- `http://localhost:3000/enterprises/octo-demo-ent`
101101
- `http://localhost:3000/orgs/octo-demo-org`
102102
- `http://localhost:3000/orgs/octo-demo-org/teams/the-a-team`
103+
- `http://localhost:3000/enterprises/octo-demo-ent/teams/the-a-team`
103104
- `http://localhost:3000/orgs/mocked-org?mock=true`
104105

105106
#### NUXT_PUBLIC_SCOPE
106107

107-
The `NUXT_PUBLIC_SCOPE` environment variable in the `.env` file determines the default scope of the API calls made by the application. It can be set to 'enterprise', 'organization' or 'team'.
108+
The `NUXT_PUBLIC_SCOPE` environment variable in the `.env` file determines the default scope of the API calls made by the application. It can be set to 'enterprise', 'organization', 'team-organization' or 'team-enterprise'.
108109

109110
- If set to 'enterprise', the application will target API calls to the GitHub Enterprise account defined in the `NUXT_PUBLIC_GITHUB_ENT` variable.
110111
- If set to 'organization', the application will target API calls to the GitHub Organization account defined in the `NUXT_PUBLIC_GITHUB_ORG` variable.

app/components/MainComponent.vue

Lines changed: 69 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,9 @@
3535
</v-toolbar>
3636

3737
<!-- 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+
4441
<!-- Organization info for seats tab -->
4542
<div v-if="tab === 'seat analysis'" class="organization-info">
4643
<v-card flat class="pa-3 mb-2">
@@ -72,18 +69,20 @@
7269
<v-window-item v-for="item in tabItems" :key="item" :value="item">
7370
<v-card flat>
7471
<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" />
7878
<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"
8180
:seats="seats" />
8281
</v-card>
8382
</v-window-item>
8483
<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" />
8786
</v-window>
8887

8988
</div>
@@ -104,6 +103,8 @@ import CopilotChatViewer from './CopilotChatViewer.vue'
104103
import SeatsAnalysisViewer from './SeatsAnalysisViewer.vue'
105104
import ApiResponse from './ApiResponse.vue'
106105
import DateRangeSelector from './DateRangeSelector.vue'
106+
import { Options } from '@/model/Options';
107+
import { useRoute } from 'vue-router';
107108
108109
export default defineNuxtComponent({
109110
name: 'MainComponent',
@@ -120,28 +121,42 @@ export default defineNuxtComponent({
120121
const { clear } = useUserSession()
121122
this.metrics = [];
122123
this.seats = [];
123-
// console.log('metrics are now', this.metrics);
124124
clear();
125125
},
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+
128141
this.isLoading = true;
129-
142+
130143
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();
137148
const apiUrl = queryString ? `/api/metrics?${queryString}` : '/api/metrics';
138-
149+
139150
const response = await $fetch(apiUrl) as MetricsApiResponse;
140-
151+
141152
this.metrics = response.metrics || [];
142153
this.originalMetrics = response.usage || [];
143154
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+
145160
} catch (error: any) {
146161
this.processError(error);
147162
} finally {
@@ -185,7 +200,7 @@ export default defineNuxtComponent({
185200
seatsReady: false,
186201
seats: [] as Seat[],
187202
apiError: undefined as string | undefined,
188-
config: null as any
203+
config: null as ReturnType<typeof useRuntimeConfig> | null
189204
}
190205
},
191206
created() {
@@ -195,27 +210,22 @@ export default defineNuxtComponent({
195210
async mounted() {
196211
// Load initial data
197212
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-
}
207213
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();
211215
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+
}
218227
}
228+
219229
} catch (error) {
220230
console.error('Error loading initial data:', error);
221231
}
@@ -228,19 +238,21 @@ export default defineNuxtComponent({
228238
const itemName = computed(() => config.public.scope);
229239
const githubInfo = getDisplayName(config.public)
230240
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());
231244
232245
const signInRequired = computed(() => {
233246
return config.public.usingGithubAuth && !loggedIn.value;
234247
});
235248
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+
})
244256
});
245257
246258
return {
@@ -250,8 +262,10 @@ export default defineNuxtComponent({
250262
displayName,
251263
signInRequired,
252264
user,
253-
metricsFetch,
254-
seatsFetch
265+
seatsFetch,
266+
dateRange,
267+
isLoading,
268+
route,
255269
};
256270
},
257271
})

0 commit comments

Comments
 (0)