Skip to content

Commit 5966740

Browse files
CopilotkarpikplCopilotdependabot[bot]
authored
Redesign Teams tab with dropdown team selection, multi-line comparison charts, and bar chart visualizations (#236)
* Initial plan * Implement Teams tab functionality with comparison features Co-authored-by: karpikpl <[email protected]> * Redesign Teams component with dropdown selection and multi-line charts Co-authored-by: karpikpl <[email protected]> * Fix Teams tab styling and implement bar charts for language/editor comparison - Fixed v-chip styling issues in team selection dropdown (added color="primary" and variant="outlined") - Fixed selected teams chips styling (changed to variant="tonal" for better visibility) - Replaced language/editor comparison tables with interactive bar charts - Added Bar chart component import from vue-chartjs with BarElement registration - Implemented generateBarChartData() function for chart data transformation - Updated chart clearing logic to include bar chart data - All 85 tests passing, styling issues resolved Co-authored-by: karpikpl <[email protected]> * Implement Agent Mode Statistics display with models used by users (#226) * Initial plan * Initial exploration and setup complete Co-authored-by: karpikpl <[email protected]> * Implement Agent Mode Statistics display with models used by users Co-authored-by: karpikpl <[email protected]> * Rename agent mode to GitHub.com and update terminology Co-authored-by: karpikpl <[email protected]> * Merge with main and move GitHub.com calculations to backend Co-authored-by: karpikpl <[email protected]> * model info * Update e2e-tests/pages/GitHubTab.ts Co-authored-by: Copilot <[email protected]> * Update app/components/AgentModeViewer.vue Co-authored-by: Copilot <[email protected]> * Update server/api/github-stats.ts Co-authored-by: Copilot <[email protected]> * Update e2e-tests/pages/GitHubTab.ts Co-authored-by: Copilot <[email protected]> * code cleanup after copilot made a mess --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: karpikpl <[email protected]> Co-authored-by: Piotr Karpala <[email protected]> Co-authored-by: Piotr Karpala <[email protected]> Co-authored-by: Copilot <[email protected]> * Update package.json (#237) Update for version 2.0.7 * Bump @eslint/plugin-kit in the npm_and_yarn group across 1 directory (#238) Bumps the npm_and_yarn group with 1 update in the / directory: [@eslint/plugin-kit](https://github.com/eslint/rewrite/tree/HEAD/packages/plugin-kit). Updates `@eslint/plugin-kit` from 0.2.4 to 0.2.8 - [Release notes](https://github.com/eslint/rewrite/releases) - [Changelog](https://github.com/eslint/rewrite/blob/main/packages/plugin-kit/CHANGELOG.md) - [Commits](https://github.com/eslint/rewrite/commits/plugin-kit-v0.2.8/packages/plugin-kit) --- updated-dependencies: - dependency-name: "@eslint/plugin-kit" dependency-version: 0.2.8 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump the npm_and_yarn group across 1 directory with 3 updates (#242) Bumps the npm_and_yarn group with 3 updates in the / directory: [esbuild](https://github.com/evanw/esbuild), [@eslint/plugin-kit](https://github.com/eslint/rewrite/tree/HEAD/packages/plugin-kit) and [eslint](https://github.com/eslint/eslint). Updates `esbuild` from 0.25.6 to 0.25.7 - [Release notes](https://github.com/evanw/esbuild/releases) - [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md) - [Commits](evanw/esbuild@v0.25.6...v0.25.7) Updates `@eslint/plugin-kit` from 0.2.8 to 0.3.4 - [Release notes](https://github.com/eslint/rewrite/releases) - [Changelog](https://github.com/eslint/rewrite/blob/main/packages/plugin-kit/CHANGELOG.md) - [Commits](https://github.com/eslint/rewrite/commits/plugin-kit-v0.3.4/packages/plugin-kit) Updates `eslint` from 9.17.0 to 9.32.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](eslint/eslint@v9.17.0...v9.32.0) --- updated-dependencies: - dependency-name: esbuild dependency-version: 0.25.7 dependency-type: direct:development dependency-group: npm_and_yarn - dependency-name: "@eslint/plugin-kit" dependency-version: 0.3.4 dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: eslint dependency-version: 9.32.0 dependency-type: direct:production dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix Teams component rendering by adding missing template directive in MainComponent.vue Co-authored-by: karpikpl <[email protected]> * fixes to styles * working API * in progress * fix for routes * fixing seats * seats * seats * Update app/components/TeamsComponent.vue Co-authored-by: Copilot <[email protected]> * ident * fix pr comment * 2.1.0 --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: karpikpl <[email protected]> Co-authored-by: Piotr Karpala <[email protected]> Co-authored-by: Piotr Karpala <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1 parent a0dc776 commit 5966740

File tree

13 files changed

+1245
-30
lines changed

13 files changed

+1245
-30
lines changed

.vscode/settings.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"files.watcherExclude": {
3+
"**/node_modules/**": true,
4+
"**/.git/**": true,
5+
"**/dist/**": true
6+
}
7+
}

app/assets/global.css

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
/* App theme variables */
2+
:root {
3+
/* Use Vuetify primary as the single source of truth for accent */
4+
--app-accent: var(--v-theme-primary, #1976D2);
5+
/* Fallback translucent variants (based on #1976D2) */
6+
--app-accent-weak: rgba(25, 118, 210, 0.10); /* subtle bg */
7+
--app-accent-overlay: rgba(25, 118, 210, 0.12); /* tab overlay */
8+
}
9+
10+
/* Prefer dynamic derivation when supported */
11+
@supports (color: color-mix(in srgb, red, transparent)) {
12+
:root {
13+
--app-accent-weak: color-mix(in srgb, var(--app-accent), transparent 90%);
14+
--app-accent-overlay: color-mix(in srgb, var(--app-accent), transparent 88%);
15+
}
16+
}
17+
118
.tiles-container {
219
display: flex;
320
justify-content: flex-start;
@@ -34,7 +51,7 @@
3451
left: 0 !important;
3552
width: 100% !important;
3653
height: 100% !important;
37-
background-color: rgba(44, 32, 157, 0.557) !important;
54+
background-color: var(--app-accent-overlay) !important;
3855
pointer-events: none !important;
3956
z-index: 1 !important;
4057
}
@@ -60,7 +77,7 @@
6077

6178
/* Fix button hover styles - light gray background */
6279
.v-btn:hover {
63-
background-color: rgba(63, 81, 181, 0.1) !important;
80+
background-color: var(--app-accent-weak) !important;
6481
}
6582

6683
.v-btn:hover .v-btn__overlay {
@@ -75,4 +92,109 @@
7592
/* Override Vuetify's default overlay behavior for variant-text buttons in tabs */
7693
.v-tab .v-btn--variant-text .v-btn__overlay {
7794
background: transparent !important;
95+
}
96+
97+
/* Teams dropdown menu: global surface fallback and panel styling */
98+
.v-overlay__content.teams-select-menu {
99+
background-color: var(--v-theme-surface, #fff) !important;
100+
border: 1px solid var(--app-accent-weak);
101+
box-shadow: 0 6px 24px rgba(56, 79, 184, 0.15);
102+
border-radius: 8px;
103+
max-height: 360px;
104+
overflow-y: auto;
105+
min-width: 320px;
106+
z-index: 2000;
107+
}
108+
109+
/* Hover highlight inside teams dropdown aligns with tab/button accent */
110+
.v-overlay__content.teams-select-menu .v-list-item:hover {
111+
background-color: var(--app-accent-weak) !important;
112+
}
113+
114+
/* Ensure readable black text and remove dark overlay on items */
115+
.v-overlay__content.teams-select-menu .v-list-item,
116+
.v-overlay__content.teams-select-menu .v-list-item .v-list-item-title,
117+
.v-overlay__content.teams-select-menu .v-list-item .v-list-item-subtitle,
118+
.v-overlay__content.teams-select-menu .v-list-item .v-icon,
119+
.v-overlay__content.teams-select-menu .v-list-item .v-selection-control .v-icon {
120+
color: #000 !important;
121+
}
122+
.v-overlay__content.teams-select-menu .v-list-item .v-list-item__overlay,
123+
.v-overlay__content.teams-select-menu .v-list-item--active .v-list-item__overlay {
124+
background: transparent !important;
125+
}
126+
/* Keep selected item highlighted with same light blue as hover */
127+
.v-overlay__content.teams-select-menu .v-list-item--active {
128+
background-color: var(--app-accent-weak) !important;
129+
}
130+
131+
.v-overlay__content.teams-select-menu .v-list {
132+
padding: 8px 0;
133+
}
134+
135+
.v-overlay__content.teams-select-menu .v-list-item {
136+
min-height: 40px;
137+
}
138+
139+
/* Chips palette: light primary tint background + black text/icons */
140+
.v-chip.select-chip,
141+
.v-chip.selected-team-chip {
142+
background-color: var(--app-accent-weak) !important;
143+
color: #000 !important;
144+
border-color: var(--app-accent-weak) !important;
145+
background-image: none !important;
146+
}
147+
.v-chip.select-chip .v-chip__overlay,
148+
.v-chip.selected-team-chip .v-chip__overlay {
149+
background: transparent !important;
150+
}
151+
.v-chip.select-chip .v-chip__underlay,
152+
.v-chip.selected-team-chip .v-chip__underlay {
153+
background-color: var(--app-accent-weak) !important;
154+
}
155+
.v-chip.select-chip:hover .v-chip__overlay,
156+
.v-chip.selected-team-chip:hover .v-chip__overlay {
157+
background: transparent !important;
158+
}
159+
.v-chip.select-chip .v-icon,
160+
.v-chip.selected-team-chip .v-icon,
161+
.v-chip.select-chip .v-chip__content,
162+
.v-chip.selected-team-chip .v-chip__content {
163+
color: #000 !important;
164+
}
165+
166+
/* Data table pagination & items-per-page menu styling */
167+
/* Ensure pagination toolbar inherits surface background and consistent spacing */
168+
.v-data-table .v-data-table-footer {
169+
background-color: var(--v-theme-surface, #fff) !important;
170+
}
171+
172+
/* Items-per-page activator button */
173+
.v-data-table .v-data-table-footer .v-field {
174+
min-width: 90px;
175+
}
176+
177+
/* Dropdown menu for items-per-page (was showing black background entries) */
178+
.v-overlay__content .v-list-item[role="option"] {
179+
background: #fff !important;
180+
color: #000 !important;
181+
}
182+
.v-overlay__content .v-list-item[role="option"] .v-list-item-title {
183+
color: #000 !important;
184+
}
185+
.v-overlay__content .v-list-item[role="option"]:hover {
186+
background: var(--app-accent-weak) !important;
187+
}
188+
.v-overlay__content .v-list-item[role="option"].v-list-item--active {
189+
background: var(--app-accent-weak) !important;
190+
}
191+
192+
/* Remove dark overlay layer inside those list items */
193+
.v-overlay__content .v-list-item[role="option"] .v-list-item__overlay {
194+
background: transparent !important;
195+
}
196+
197+
/* Pagination buttons hover state unify with buttons */
198+
.v-data-table .v-data-table-footer .v-btn:hover {
199+
background-color: var(--app-accent-weak) !important;
78200
}

app/components/MainComponent.vue

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@
7070
<v-window v-show="(metricsReady && metrics.length) || (seatsReady && tab === 'seat analysis')" v-model="tab">
7171
<v-window-item v-for="item in tabItems" :key="item" :value="item">
7272
<v-card flat>
73-
<MetricsViewer v-if="item === itemName" :metrics="metrics" :date-range-description="dateRangeDescription" />
73+
<MetricsViewer v-if="item === getDisplayTabName(itemName)" :metrics="metrics" :date-range-description="dateRangeDescription" />
74+
<TeamsComponent v-if="item === 'teams'" :date-range-description="dateRangeDescription" :date-range="dateRange" />
7475
<BreakdownComponent
7576
v-if="item === 'languages'" :metrics="metrics" :breakdown-key="'language'"
7677
:date-range-description="dateRangeDescription" />
@@ -108,6 +109,7 @@ import MetricsViewer from './MetricsViewer.vue'
108109
import BreakdownComponent from './BreakdownComponent.vue'
109110
import CopilotChatViewer from './CopilotChatViewer.vue'
110111
import SeatsAnalysisViewer from './SeatsAnalysisViewer.vue'
112+
import TeamsComponent from './TeamsComponent.vue'
111113
import ApiResponse from './ApiResponse.vue'
112114
import AgentModeViewer from './AgentModeViewer.vue'
113115
import DateRangeSelector from './DateRangeSelector.vue'
@@ -121,6 +123,7 @@ export default defineNuxtComponent({
121123
BreakdownComponent,
122124
CopilotChatViewer,
123125
SeatsAnalysisViewer,
126+
TeamsComponent,
124127
ApiResponse,
125128
AgentModeViewer,
126129
DateRangeSelector
@@ -132,6 +135,19 @@ export default defineNuxtComponent({
132135
this.seats = [];
133136
clear();
134137
},
138+
getDisplayTabName(itemName: string): string {
139+
// Transform scope names to display names for tabs
140+
switch (itemName) {
141+
case 'team-organization':
142+
case 'team-enterprise':
143+
return 'team';
144+
case 'organization':
145+
case 'enterprise':
146+
return itemName;
147+
default:
148+
return itemName;
149+
}
150+
},
135151
async handleDateRangeChange(newDateRange: {
136152
since?: string;
137153
until?: string;
@@ -232,7 +248,13 @@ export default defineNuxtComponent({
232248
}
233249
},
234250
created() {
235-
this.tabItems.unshift(this.itemName);
251+
this.tabItems.unshift(this.getDisplayTabName(this.itemName));
252+
253+
// Add teams tab for organization and enterprise scopes to allow team comparison
254+
if (this.itemName === 'organization' || this.itemName === 'enterprise') {
255+
this.tabItems.splice(1, 0, 'teams'); // Insert after the first tab
256+
}
257+
236258
this.config = useRuntimeConfig();
237259
},
238260
async mounted() {

app/components/SeatsAnalysisViewer.vue

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ elevation="4" color="white" variant="elevated" class="mx-auto my-4"
1111
<div v-bind="props" class="text-h6 mb-1">Total Assigned </div>
1212
</template>
1313
<v-card class="pa-2" style="background-color: #f0f0f0; max-width: 350px;">
14-
<span class="text-caption" style="font-size: 10px !important;">This metric represents the total number of Copilot seats assigned within the current organization/enterprise.</span>
14+
<span class="text-caption" style="font-size: 10px !important;">This metric represents the total number of Copilot seats assigned {{ isTeamView ? `to team "${currentTeam}"` : 'within the current organization/enterprise' }}.</span>
1515
</v-card>
1616
</v-tooltip>
1717
<div class="text-caption">
18-
Currently assigned seats
18+
{{ isTeamView ? `Seats assigned to team "${currentTeam}"` : 'Currently assigned seats' }}
1919
</div>
2020
<p class="text-h4">{{ totalSeats.length }}</p>
2121
</div>
@@ -33,7 +33,7 @@ elevation="4" color="white" variant="elevated" class="mx-auto my-3"
3333
<div v-bind="props" class="text-h6 mb-1">Assigned But Never Used</div>
3434
</template>
3535
<v-card class="pa-2" style="background-color: #f0f0f0; max-width: 350px;">
36-
<span class="text-caption" style="font-size: 10px !important;">This metric shows seats that were assigned but never used within the current organization/enterprise. The assigned timestamp is also displayed in the chart.</span>
36+
<span class="text-caption" style="font-size: 10px !important;">This metric shows seats that were assigned but never used {{ isTeamView ? `within team "${currentTeam}"` : 'within the current organization/enterprise' }}. The assigned timestamp is also displayed in the chart.</span>
3737
</v-card>
3838
</v-tooltip>
3939
<div class="text-caption">
@@ -96,7 +96,7 @@ elevation="4" color="white" variant="elevated" class="mx-auto my-3"
9696
<td>{{ item.login }}</td>
9797
<td>{{ item.id }}</td>
9898
<td>{{ item.team }}</td>
99-
<td>{{ item.created_at }}</td>
99+
<td>{{ item.created_at }} {{ item.plan_type }}</td>
100100
<td>{{ item.last_activity_at }}</td>
101101
<td>{{ item.last_activity_editor }}</td>
102102
</tr>
@@ -108,7 +108,7 @@ elevation="4" color="white" variant="elevated" class="mx-auto my-3"
108108
</template>
109109

110110
<script lang="ts">
111-
import { defineComponent, ref, watchEffect } from 'vue';
111+
import { defineComponent, ref, watchEffect, computed } from 'vue';
112112
import type { Seat } from '@/model/Seat';
113113
import {
114114
Chart as ChartJS,
@@ -197,11 +197,18 @@ setup(props) {
197197
unusedSeatsInSevenDays.value = unusedIn7Count;
198198
unusedSeatsInThirtyDays.value = unusedIn30Count;
199199
200+
// Add computed properties for team filtering info
201+
const config = useRuntimeConfig();
202+
const isTeamView = computed(() => config.public.scope?.includes('team') && config.public.githubTeam);
203+
const currentTeam = computed(() => config.public.githubTeam || '');
204+
200205
return {
201206
totalSeats,
202207
noshowSeats: noshowSeats,
203208
unusedSeatsInSevenDays: unusedSeatsInSevenDays,
204-
unusedSeatsInThirtyDays: unusedSeatsInThirtyDays
209+
unusedSeatsInThirtyDays: unusedSeatsInThirtyDays,
210+
isTeamView,
211+
currentTeam
205212
}
206213
},
207214
data() {

0 commit comments

Comments
 (0)