@@ -47,7 +47,7 @@ export function showEmptyBuildsLast() {
4747 } ;
4848}
4949
50- export function IndexController ( $scope , $rootScope , $location , $http , $filter , $timeout , anchors , apiLoader , filters , multisort , modalSvc ) {
50+ export function IndexController ( $scope , $rootScope , $location , $http , $filter , $timeout , $q , anchors , apiLoader , filters , multisort , modalSvc ) {
5151 // Show spinner while page is loading.
5252 $scope . loading = true ;
5353
@@ -201,6 +201,17 @@ export function IndexController($scope, $rootScope, $location, $http, $filter, $
201201 $scope . cdash . buildgroups [ i ] . builds = $filter ( 'orderBy' ) ( $scope . cdash . buildgroups [ i ] . builds , $scope . cdash . buildgroups [ i ] . orderByFields ) ;
202202 $scope . cdash . buildgroups [ i ] . builds = $filter ( 'showEmptyBuildsLast' ) ( $scope . cdash . buildgroups [ i ] . builds , $scope . cdash . buildgroups [ i ] . orderByFields ) ;
203203
204+ // Initialize expectedInGroup property for each build to avoid checkbox binding conflicts
205+ for ( var j = 0 ; j < $scope . cdash . buildgroups [ i ] . builds . length ; j ++ ) {
206+ $scope . cdash . buildgroups [ i ] . builds [ j ] . expectedInGroup = { } ;
207+ }
208+
209+ // Initialize bulk selection properties
210+ $scope . cdash . buildgroups [ i ] . selectedBuilds = [ ] ;
211+ $scope . cdash . buildgroups [ i ] . selectAll = false ;
212+ $scope . cdash . buildgroups [ i ] . bulkTargetGroup = '' ;
213+ $scope . cdash . buildgroups [ i ] . selectionMode = false ;
214+
204215 // Mark this group has having "normal" builds if it only contains missing & expected builds.
205216 if ( ! $scope . cdash . buildgroups [ i ] . hasnormalbuilds && ! $scope . cdash . buildgroups [ i ] . hasparentbuilds && $scope . cdash . buildgroups [ i ] . builds . length > 0 ) {
206217 $scope . cdash . buildgroups [ i ] . hasnormalbuilds = true ;
@@ -389,7 +400,7 @@ export function IndexController($scope, $rootScope, $location, $http, $filter, $
389400 } ;
390401
391402 $scope . showModal = function ( buildid ) {
392- modalSvc . showModal ( buildid , $scope . removeBuild , 'modal-template' ) ;
403+ modalSvc . showModal ( buildid , $scope . removeBuild , 'modal-template' , null , 'sm' , null , null , false ) ;
393404 }
394405
395406 $scope . removeBuild = function ( build ) {
@@ -498,20 +509,133 @@ export function IndexController($scope, $rootScope, $location, $http, $filter, $
498509 $http . post ( 'api/v1/expectedbuild.php' , parameters )
499510 . then ( function success ( ) {
500511 window . location . reload ( ) ;
512+ } ) . catch ( function ( error ) {
513+ console . error ( 'Error moving expected build:' , error ) ;
514+ alert ( 'An error occurred while moving the build. Please try again.' ) ;
501515 } ) ;
502516 } else {
517+ // Use the checkbox value for this specific group, default to current expected value
518+ var expectedInNewGroup = build . expectedInGroup && build . expectedInGroup [ groupid ] !== undefined
519+ ? ( build . expectedInGroup [ groupid ] ? 1 : 0 )
520+ : build . expected ;
521+
522+ // Use the build API with the correct parameters
503523 var parameters = {
504524 buildid : build . id ,
505525 newgroupid : groupid ,
506- expected : build . expected
526+ expected : expectedInNewGroup
507527 } ;
508528 $http . post ( 'api/v1/build.php' , parameters )
509529 . then ( function success ( ) {
510530 window . location . reload ( ) ;
531+ } ) . catch ( function ( error ) {
532+ console . error ( 'Error moving build:' , error ) ;
533+ alert ( 'Error moving build: ' + ( error . data && error . data . error ? error . data . error : 'Unknown error' ) ) ;
511534 } ) ;
512535 }
513536 } ;
514537
538+ // Bulk selection functions
539+ $scope . toggleBuildSelection = function ( build , buildgroup ) {
540+ if ( build . selected ) {
541+ buildgroup . selectedBuilds . push ( build ) ;
542+ } else {
543+ var index = buildgroup . selectedBuilds . indexOf ( build ) ;
544+ if ( index > - 1 ) {
545+ buildgroup . selectedBuilds . splice ( index , 1 ) ;
546+ }
547+ buildgroup . selectAll = false ;
548+ }
549+ } ;
550+
551+ $scope . toggleSelectAll = function ( buildgroup ) {
552+ buildgroup . selectedBuilds = [ ] ;
553+ for ( var i = 0 ; i < buildgroup . pagination . filteredBuilds . length ; i ++ ) {
554+ var build = buildgroup . pagination . filteredBuilds [ i ] ;
555+ if ( build . id ) { // Only select builds that have IDs (not expected missing builds)
556+ build . selected = buildgroup . selectAll ;
557+ if ( buildgroup . selectAll ) {
558+ buildgroup . selectedBuilds . push ( build ) ;
559+ }
560+ }
561+ }
562+ } ;
563+
564+ $scope . clearBuildSelection = function ( buildgroup ) {
565+ buildgroup . selectAll = false ;
566+ buildgroup . selectedBuilds = [ ] ;
567+ for ( var i = 0 ; i < buildgroup . builds . length ; i ++ ) {
568+ buildgroup . builds [ i ] . selected = false ;
569+ }
570+ } ;
571+
572+ $scope . toggleSelectionMode = function ( buildgroup ) {
573+ buildgroup . selectionMode = ! buildgroup . selectionMode ;
574+ // Clear selection when exiting selection mode
575+ if ( ! buildgroup . selectionMode ) {
576+ $scope . clearBuildSelection ( buildgroup ) ;
577+ }
578+ } ;
579+
580+ $scope . bulkMoveToGroup = function ( buildgroup ) {
581+ if ( ! buildgroup . bulkTargetGroup || buildgroup . selectedBuilds . length === 0 ) {
582+ return ;
583+ }
584+
585+ var targetGroupId = parseInt ( buildgroup . bulkTargetGroup , 10 ) ;
586+ var movePromises = [ ] ;
587+
588+ // Move each selected build using the build API
589+ for ( var i = 0 ; i < buildgroup . selectedBuilds . length ; i ++ ) {
590+ var build = buildgroup . selectedBuilds [ i ] ;
591+ var expectedInNewGroup = build . expectedInGroup && build . expectedInGroup [ targetGroupId ] !== undefined
592+ ? ( build . expectedInGroup [ targetGroupId ] ? 1 : 0 )
593+ : ( build . expected || 0 ) ;
594+
595+ var parameters = {
596+ buildid : build . id ,
597+ newgroupid : targetGroupId ,
598+ expected : expectedInNewGroup
599+ } ;
600+ movePromises . push ( $http . post ( 'api/v1/build.php' , parameters ) ) ;
601+ }
602+
603+ // Wait for all moves to complete, then reload
604+ $q . all ( movePromises ) . then ( function ( ) {
605+ window . location . reload ( ) ;
606+ } ) . catch ( function ( error ) {
607+ console . error ( 'Error moving builds:' , error ) ;
608+ alert ( 'An error occurred while moving builds. Please try again.' ) ;
609+ } ) ;
610+ } ;
611+
612+ $scope . bulkMarkAsExpected = function ( buildgroup , expectedValue ) {
613+ if ( buildgroup . selectedBuilds . length === 0 ) {
614+ return ;
615+ }
616+
617+ var updatePromises = [ ] ;
618+
619+ // Update expected status for each selected build using the build API
620+ for ( var i = 0 ; i < buildgroup . selectedBuilds . length ; i ++ ) {
621+ var build = buildgroup . selectedBuilds [ i ] ;
622+ var parameters = {
623+ buildid : build . id ,
624+ groupid : parseInt ( buildgroup . id , 10 ) ,
625+ expected : expectedValue
626+ } ;
627+ updatePromises . push ( $http . post ( 'api/v1/build.php' , parameters ) ) ;
628+ }
629+
630+ // Wait for all updates to complete, then reload
631+ $q . all ( updatePromises ) . then ( function ( ) {
632+ window . location . reload ( ) ;
633+ } ) . catch ( function ( error ) {
634+ console . error ( 'Error updating builds:' , error ) ;
635+ alert ( 'An error occurred while updating builds. Please try again.' ) ;
636+ } ) ;
637+ } ;
638+
515639 $scope . colorblind_toggle = function ( ) {
516640 if ( $scope . cdash . filterdata . colorblind ) {
517641 $rootScope . cssfile = "colorblind" ;
0 commit comments