@@ -723,4 +723,72 @@ public async Task<IActionResult> GetSyncProgress(string instanceId, Cancellation
723723 _ => Json ( new { status = "error" } )
724724 } ;
725725 }
726+
727+ [ HttpPost ]
728+ [ ValidateAntiForgeryToken ]
729+ public async Task < IActionResult > CancelOperation ( Guid operationId , Guid assignmentId , CancellationToken cancellationToken = default )
730+ {
731+ return await ExecuteWithErrorHandlingAsync ( async ( ) =>
732+ {
733+ var assignmentResponse = await repositoryApiClient . MapRotations . V1 . GetServerAssignment ( assignmentId , cancellationToken ) . ConfigureAwait ( false ) ;
734+
735+ if ( assignmentResponse . IsNotFound || assignmentResponse . Result ? . Data is null )
736+ return NotFound ( ) ;
737+
738+ var assignment = assignmentResponse . Result . Data ;
739+
740+ var rotationResponse = await repositoryApiClient . MapRotations . V1 . GetMapRotation ( assignment . MapRotationId , cancellationToken ) . ConfigureAwait ( false ) ;
741+
742+ if ( rotationResponse . IsNotFound || rotationResponse . Result ? . Data is null )
743+ return NotFound ( ) ;
744+
745+ var rotation = rotationResponse . Result . Data ;
746+
747+ var authResult = await CheckAuthorizationAsync (
748+ authorizationService ,
749+ rotation . GameType ,
750+ AuthPolicies . ManageMapRotations ,
751+ nameof ( CancelOperation ) ,
752+ "MapRotation" ) . ConfigureAwait ( false ) ;
753+
754+ if ( authResult != null )
755+ return authResult ;
756+
757+ var updateResult = await repositoryApiClient . MapRotations . V1 . UpdateAssignmentOperation (
758+ operationId , AssignmentOperationStatus . Cancelled , "Manually cancelled by user" ) . ConfigureAwait ( false ) ;
759+
760+ if ( updateResult . IsSuccess )
761+ {
762+ // Also reset the assignment state so the user can retry
763+ var deploymentReset = assignment . DeploymentState is DeploymentState . Syncing or DeploymentState . Removing
764+ ? DeploymentState . Failed
765+ : ( DeploymentState ? ) null ;
766+
767+ var activationReset = assignment . ActivationState is ActivationState . Activating or ActivationState . Deactivating
768+ ? ActivationState . Inactive
769+ : ( ActivationState ? ) null ;
770+
771+ if ( deploymentReset . HasValue || activationReset . HasValue )
772+ {
773+ var resetDto = new UpdateMapRotationServerAssignmentDto ( assignmentId )
774+ {
775+ DeploymentState = deploymentReset ,
776+ ActivationState = activationReset ,
777+ LastError = "Operation cancelled by user" ,
778+ LastErrorAt = DateTime . UtcNow
779+ } ;
780+
781+ await repositoryApiClient . MapRotations . V1 . UpdateServerAssignment ( resetDto , cancellationToken ) . ConfigureAwait ( false ) ;
782+ }
783+
784+ this . AddAlertSuccess ( "Operation cancelled successfully." ) ;
785+ }
786+ else
787+ {
788+ this . AddAlertDanger ( "Failed to cancel operation. Please try again." ) ;
789+ }
790+
791+ return RedirectToAction ( nameof ( AssignmentStatus ) , new { id = assignmentId } ) ;
792+ } , nameof ( CancelOperation ) ) . ConfigureAwait ( false ) ;
793+ }
726794}
0 commit comments