Skip to content

Commit 6ed4e9e

Browse files
committed
feat: allow to filter dashboard summary based on label
Signed-off-by: Olivier Vernin <olivier@vernin.me>
1 parent 77365ac commit 6ed4e9e

1 file changed

Lines changed: 91 additions & 30 deletions

File tree

src/components/scm/_summary.vue

Lines changed: 91 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,10 @@
8383
:key="status"
8484
:color="getStatusColor(status)"
8585
size="x-small"
86-
class="mr-1 mb-1"
86+
class="status-chip"
8787
>
88-
{{ status }} {{ count }}
88+
<span class="status-chip-status">{{ status }}</span>
89+
<span class="status-chip-value">{{ getStatusPercentage(count, branchData.total_result) }}</span>
8990
</v-chip>
9091
</div>
9192
</v-col>
@@ -133,9 +134,10 @@
133134
:key="status"
134135
:color="getStatusColor(status)"
135136
size="x-small"
136-
class="mr-1 mb-1"
137+
class="status-chip"
137138
>
138-
{{ status }} {{ count }}
139+
<span class="status-chip-status">{{ status }}</span>
140+
<span class="status-chip-value">{{ getStatusPercentage(count, branchData.total_result) }}</span>
139141
</v-chip>
140142
</div>
141143
</div>
@@ -266,17 +268,16 @@ export default {
266268
loadedPages: new Set(),
267269
}),
268270
269-
watch: {
270-
filter: async function(newFilter, oldFilter) {
271-
const newScmId = newFilter.scmid || "";
272-
const oldScmId = oldFilter.scmid || "";
273-
if (newScmId !== oldScmId) {
274-
this.stopSequentialLoad(); // cancel any in-flight sequential loads
275-
this.resetPagination();
276-
await this.loadSequentialPages(9); // or desired number
277-
}
278-
}
279-
},
271+
watch: {
272+
filter: {
273+
deep: true,
274+
async handler() {
275+
this.stopSequentialLoad();
276+
this.resetPagination();
277+
await this.loadSequentialPages(9);
278+
},
279+
},
280+
},
280281
281282
methods: {
282283
isNoData() {
@@ -343,41 +344,63 @@ export default {
343344
this.isLoading= true;
344345
this.$emit('loaded', false)
345346
346-
try {
347+
try {
347348
const auth_enabled = process.env.VUE_APP_AUTH_ENABLED === 'true';
348349
const restrictedSCM = router.currentRoute.value.query.filter?.scmid;
349350
350-
// Build query with pagination parameters
351-
const params = new URLSearchParams();
352-
params.append('summary', 'true');
353-
params.append('limit', this.itemsPerPage);
354-
params.append('page', page);
351+
const requestBody = {
352+
summary: true,
353+
limit: this.itemsPerPage,
354+
page,
355+
};
355356
356357
// Add SCM ID filter if provided
357358
if (restrictedSCM) {
358-
params.append('scmid', restrictedSCM);
359+
requestBody.scmid = restrictedSCM;
359360
} else if (this.filter?.scmid && this.filter?.scmid !== '') {
360-
params.append('scmid', this.filter.scmid);
361+
requestBody.scmid = this.filter.scmid;
361362
}
362363
363364
// Add starttime and endtime filters if provided
364365
if (this.filter?.startTime && this.filter.endTime ) {
365-
params.append('start_time', this.filter.startTime);
366-
params.append('end_time', this.filter.endTime);
366+
requestBody.start_time = this.filter.startTime;
367+
requestBody.end_time = this.filter.endTime;
368+
}
369+
370+
if (this.filter?.labels && typeof this.filter.labels === 'object' && !Array.isArray(this.filter.labels)) {
371+
const labels = {};
372+
Object.entries(this.filter.labels).forEach(([key, value]) => {
373+
if (typeof key === 'string' && value !== undefined && value !== null) {
374+
labels[key] = String(value);
375+
}
376+
});
377+
378+
if (Object.keys(labels).length > 0) {
379+
requestBody.labels = labels;
380+
}
367381
}
368382
369-
let query = `${getApiBaseURL()}/pipeline/scms?${params.toString()}`;
383+
const query = `${getApiBaseURL()}/pipeline/scms/search`;
370384
371385
let response;
372386
if (auth_enabled) {
373387
const token = await this.$auth0.getAccessTokenSilently();
374388
response = await fetch(query, {
389+
method: 'POST',
375390
headers: {
376-
Authorization: `Bearer ${token}`
377-
}
391+
Authorization: `Bearer ${token}`,
392+
'Content-Type': 'application/json',
393+
},
394+
body: JSON.stringify(requestBody),
378395
});
379396
} else {
380-
response = await fetch(query);
397+
response = await fetch(query, {
398+
method: 'POST',
399+
headers: {
400+
'Content-Type': 'application/json',
401+
},
402+
body: JSON.stringify(requestBody),
403+
});
381404
}
382405
383406
if (!response.ok) {
@@ -560,6 +583,17 @@ export default {
560583
default: return 'purple';
561584
}
562585
},
586+
587+
getStatusPercentage(count, total) {
588+
const safeCount = Number(count) || 0;
589+
const safeTotal = Number(total) || 0;
590+
591+
if (safeTotal <= 0) {
592+
return '0%';
593+
}
594+
595+
return `${Math.round((safeCount / safeTotal) * 100)}%`;
596+
},
563597
},
564598
async created() {
565599
try {
@@ -613,7 +647,34 @@ export default {
613647
}
614648
615649
.status-summary {
616-
max-width: 200px;
650+
max-width: 220px;
651+
display: flex;
652+
flex-direction: column;
653+
align-items: flex-start;
654+
gap: 6px;
655+
}
656+
657+
.status-chip {
658+
margin: 0;
659+
width: 100%;
660+
justify-content: stretch;
661+
}
662+
663+
.status-chip :deep(.v-chip__content) {
664+
width: 100%;
665+
display: flex;
666+
align-items: center;
667+
}
668+
669+
.status-chip-status {
670+
font-weight: 600;
671+
}
672+
673+
.status-chip-value {
674+
margin-left: auto;
675+
min-width: 48px;
676+
text-align: right;
677+
font-variant-numeric: tabular-nums;
617678
}
618679
619680
.branch-info {

0 commit comments

Comments
 (0)