@@ -4512,6 +4512,95 @@ const rmFolder = (id) => {
45124512 } ) ;
45134513} ;
45144514
4515+ const getLockedDockerBranchFolderIds = ( id ) => {
4516+ const branchIds = [ id , ...getFolderDescendants ( id ) ] ;
4517+ return branchIds . filter ( ( folderId ) => isDockerFolderLocked ( folderId ) ) ;
4518+ } ;
4519+
4520+ const ensureDockerBranchUnlocked = ( id , actionLabel = 'This action' ) => {
4521+ const lockedIds = getLockedDockerBranchFolderIds ( id ) ;
4522+ if ( ! lockedIds . length ) {
4523+ return true ;
4524+ }
4525+ const previewNames = lockedIds
4526+ . slice ( 0 , 4 )
4527+ . map ( ( folderId ) => escapeHtml ( String ( globalFolders ?. [ folderId ] ?. name || folderId ) ) )
4528+ . join ( ', ' ) ;
4529+ const hiddenCount = Math . max ( 0 , lockedIds . length - Math . min ( 4 , lockedIds . length ) ) ;
4530+ const lockedLabel = lockedIds . length === 1 ? 'A folder in this branch is locked.' : `${ lockedIds . length } folders in this branch are locked.` ;
4531+ const hiddenSuffix = hiddenCount > 0 ? ` (+${ hiddenCount } more)` : '' ;
4532+ const detailsLine = previewNames ? `<br><strong>Locked:</strong> ${ previewNames } ${ hiddenSuffix } ` : '' ;
4533+ swal ( {
4534+ title : 'Folder branch locked' ,
4535+ text : `${ escapeHtml ( actionLabel ) } is blocked while ${ lockedLabel } ${ detailsLine } <br>Unlock the locked folder rows first and try again.` ,
4536+ type : 'info' ,
4537+ html : true ,
4538+ confirmButtonText : 'OK'
4539+ } ) ;
4540+ return false ;
4541+ } ;
4542+
4543+ const deleteDockerFolderBranch = async ( id ) => {
4544+ const deleteIds = [ ...getFolderDescendants ( id ) ] . reverse ( ) ;
4545+ deleteIds . push ( id ) ;
4546+ for ( const deleteId of deleteIds ) {
4547+ await $ . post ( '/plugins/folderview.plus/server/delete.php' , { type : 'docker' , id : deleteId } ) . promise ( ) ;
4548+ }
4549+ } ;
4550+
4551+ const rmFolderBranch = ( id ) => {
4552+ if ( FOLDER_VIEW_DEBUG_MODE ) console . log ( `[FV3_DEBUG] rmFolderBranch (id: ${ id } ): Entry.` ) ;
4553+ if ( ! ensureDockerBranchUnlocked ( id , 'Delete branch folders' ) ) {
4554+ return ;
4555+ }
4556+ const folder = globalFolders [ id ] || { } ;
4557+ const folderName = escapeHtml ( String ( folder . name || id ) ) ;
4558+ const descendantIds = getFolderDescendants ( id ) ;
4559+ const branchIds = [ id , ...descendantIds ] ;
4560+ const previewNames = branchIds
4561+ . slice ( 0 , 5 )
4562+ . map ( ( folderId ) => escapeHtml ( String ( globalFolders ?. [ folderId ] ?. name || folderId ) ) )
4563+ . join ( ', ' ) ;
4564+ const hiddenCount = Math . max ( 0 , branchIds . length - Math . min ( 5 , branchIds . length ) ) ;
4565+ const impactLines = [
4566+ `Delete branch folders: ${ folderName } ` ,
4567+ `This will permanently delete <strong>${ branchIds . length } </strong> folder${ branchIds . length === 1 ? '' : 's' } in this branch.` ,
4568+ `Nested child folders will be deleted with the root folder and will <strong>not</strong> be re-parented.`
4569+ ] ;
4570+ if ( previewNames ) {
4571+ impactLines . push ( `<strong>Branch:</strong> ${ previewNames } ${ hiddenCount > 0 ? ` (+${ hiddenCount } more)` : '' } ` ) ;
4572+ }
4573+ swal ( {
4574+ title : $ . i18n ( 'are-you-sure' ) ,
4575+ text : impactLines . join ( '<br>' ) ,
4576+ type : 'warning' ,
4577+ html : true ,
4578+ showCancelButton : true ,
4579+ confirmButtonText : $ . i18n ( 'yes-delete' ) ,
4580+ cancelButtonText : $ . i18n ( 'cancel' ) ,
4581+ showLoaderOnConfirm : true
4582+ } ,
4583+ async ( confirmed ) => {
4584+ if ( FOLDER_VIEW_DEBUG_MODE ) console . log ( `[FV3_DEBUG] rmFolderBranch (id: ${ id } ): Swal callback. Confirmed: ${ confirmed } ` ) ;
4585+ if ( ! confirmed ) { setTimeout ( loadlist , 0 ) ; return ; }
4586+ $ ( 'div.spinner.fixed' ) . show ( 'slow' ) ;
4587+ try {
4588+ const result = await runDockerGuardedAction ( 'delete-folder-branch' , async ( ) => {
4589+ await deleteDockerFolderBranch ( id ) ;
4590+ setTimeout ( loadlist , 500 ) ;
4591+ } , {
4592+ userMessage : getDockerMenuLabel ( 'delete-branch-folders-failed' , 'Failed to delete branch folders.' ) ,
4593+ userVisible : true
4594+ } ) ;
4595+ if ( ! result . ok ) {
4596+ setTimeout ( loadlist , 0 ) ;
4597+ }
4598+ } finally {
4599+ $ ( 'div.spinner.fixed' ) . hide ( 'slow' ) ;
4600+ }
4601+ } ) ;
4602+ } ;
4603+
45154604/**
45164605 * Redirect to the page to edit the folder
45174606 * @param {string } id the id of the folder
@@ -5483,6 +5572,14 @@ const addDockerFolderContext = (id) => {
54835572 }
54845573 } ) ;
54855574 }
5575+ branchSubMenu . push ( {
5576+ text : 'Delete branch folders' ,
5577+ icon : 'fa-trash' ,
5578+ action : ( evt ) => {
5579+ evt . preventDefault ( ) ;
5580+ rmFolderBranch ( id ) ;
5581+ }
5582+ } ) ;
54865583 if ( branchSubMenu . length > 0 ) {
54875584 opts . push ( {
54885585 text : 'Branch actions' ,
0 commit comments