Skip to content

Commit f9c3757

Browse files
committed
feat: implement sequential loading
Signed-off-by: Olivier Vernin <olivier@vernin.me>
1 parent 253d05a commit f9c3757

File tree

1 file changed

+55
-29
lines changed

1 file changed

+55
-29
lines changed

src/components/scm/_summary.vue

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
</div>
8080

8181
<!-- Mini Doughnut Chart -->
82-
<div class="chart-container">
82+
<div class="chart-container" v-if="hasDoughnutData(url, branch)">
8383
<SCMDoughnut
8484
:chartData="getDoughnutData(url, branch)"
8585
:chartOptions="miniDoughnutOptions"
@@ -126,7 +126,7 @@
126126
</div>
127127

128128
<!-- Mini Doughnut Chart -->
129-
<div class="chart-container">
129+
<div class="chart-container" v-if="hasDoughnutData(url, branch)">
130130
<SCMDoughnut
131131
:chartData="getDoughnutData(url, branch)"
132132
:chartOptions="miniDoughnutOptions"
@@ -238,7 +238,7 @@ export default {
238238
}
239239
}
240240
},
241-
currentPage: 1,
241+
currentPage: 0,
242242
itemsPerPage: 1,
243243
totalCount: 0,
244244
isLoading: false,
@@ -247,17 +247,18 @@ export default {
247247
}),
248248
249249
watch: {
250-
scmid: function(newScmId, oldScmId) {
251-
if (newScmId !== oldScmId) {
252-
this.resetPagination();
253-
this.getSummaryData(1, true);
254-
}
250+
scmid: async function(newScmId, oldScmId) {
251+
if (newScmId !== oldScmId) {
252+
this.stopSequentialLoad(); // cancel any in-flight sequential loads
253+
this.resetPagination();
254+
await this.loadSequentialPages(9); // or desired number
255255
}
256+
}
256257
},
257258
258259
methods: {
259260
resetPagination() {
260-
this.currentPage = 1;
261+
this.currentPage = 0;
261262
this.totalCount = 0;
262263
this.hasMoreData = true;
263264
this.loadedPages.clear();
@@ -277,6 +278,36 @@ export default {
277278
return this.isFullWidth() ? 12 : 6;
278279
},
279280
281+
async loadSequentialPages(pagesToLoad = 1) {
282+
// create a unique id for this run so we can cancel/stale-check
283+
const runId = (this._sequentialRunId = (this._sequentialRunId || 0) + 1);
284+
try {
285+
for (let i = 0; i < pagesToLoad; i++) {
286+
// if a newer run started, stop this one
287+
if (this._sequentialRunId !== runId) return;
288+
if (!this.hasMoreData) return;
289+
290+
// increment page and fetch (getSummaryData will ignore duplicates via loadedPages)
291+
const next = this.currentPage + 1;
292+
await this.getSummaryData(next, false);
293+
this.currentPage = next;
294+
295+
if (this.currentPage == this.totalCount) {
296+
this.hasMoreData = false;
297+
}
298+
299+
if (!this.hasMoreData) return;
300+
}
301+
} catch (err) {
302+
console.error('Sequential load error', err);
303+
}
304+
},
305+
306+
// Stop any ongoing sequential load
307+
stopSequentialLoad() {
308+
this._sequentialRunId = (this._sequentialRunId || 0) + 1;
309+
},
310+
280311
async getSummaryData(page= 1 , reset = false) {
281312
// Avoid duplicate requests for the same page
282313
if (this.loadedPages.has(page) && !reset) {
@@ -294,7 +325,7 @@ export default {
294325
const params = new URLSearchParams();
295326
params.append('summary', 'true');
296327
params.append('limit', this.itemsPerPage);
297-
params.append('page', this.currentPage);
328+
params.append('page', page);
298329
299330
// Add SCM ID filter if provided
300331
if (restrictedSCM) {
@@ -357,10 +388,10 @@ export default {
357388
},
358389
359390
async loadMoreData() {
360-
if (this.hasMoreData && !this.isLoading) {
361-
this.currentPage++;
362-
await this.getSummaryData(this.currentPage, false);
363-
}
391+
if (this.hasMoreData && !this.isLoading) {
392+
this.stopSequentialLoad(); // ensure previous run is stopped
393+
await this.loadSequentialPages(3); // start new sequential load
394+
}
364395
},
365396
366397
// Infinite scroll handler
@@ -411,20 +442,14 @@ export default {
411442
},
412443
413444
getDoughnutData(url, branch) {
445+
if (!url || !branch) return { labels: [], datasets: [] };
446+
const d = (this.doughnutData && this.doughnutData[url] && this.doughnutData[url][branch]) || { labels: [], datasets: [] };
447+
return { labels: Array.isArray(d.labels) ? d.labels : [], datasets: Array.isArray(d.datasets) ? d.datasets : [] };
448+
},
414449
415-
if (url === undefined || branch === undefined) {
416-
return {};
417-
}
418-
419-
if (this.doughnutData[url] === undefined) {
420-
return {};
421-
}
422-
423-
if (this.doughnutData[url][branch] === undefined) {
424-
return {};
425-
}
426-
427-
return this.doughnutData[url][branch];
450+
hasDoughnutData(url, branch) {
451+
const d = this.getDoughnutData(url, branch);
452+
return Array.isArray(d.datasets) && d.datasets.length > 0;
428453
},
429454
430455
updateDoughnutData: function(){
@@ -502,11 +527,11 @@ export default {
502527
case '-': return 'grey';
503528
default: return 'purple';
504529
}
505-
}
530+
},
506531
},
507532
async created() {
508533
try {
509-
this.getSummaryData(1, true);
534+
await this.loadSequentialPages(9);
510535
} catch(error) {
511536
console.log(error);
512537
}
@@ -517,6 +542,7 @@ export default {
517542
},
518543
519544
beforeUnmount() {
545+
this.stopSequentialLoad();
520546
// Clean up scroll listener if using infinite scroll
521547
window.removeEventListener('scroll', this.handleScroll);
522548
}

0 commit comments

Comments
 (0)