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"
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