Add multiple file/directory deletion in the filemanager (#544)

* Add deletion of multiple selected files
* Adjust success/failure text to properly represent multiple files
* Actually update the minimized versions with the new code
* Use let instead of var and seperate items into seperate code tags
* Deleting the selected items now supports the new endpoint
* Replaced the select buttons with checkboxes
* Selections is now handled by find all the selected checkboxes
* Add a warning if no files/folders are selected when pressing delete
* Add a select all files/folders checkbox
* Move mass delete button into a mass actions dropdown
* Move style to css file
* Actually update the minimized files (again)
* Mass actions button is now disabled by default
* Clicking on a row selects the checkbox and enables the actions button
* Fix clicking anything else but the row or checkbox triggering selection
This commit is contained in:
OrangeJuiced 2017-07-21 02:10:01 +03:00 committed by Dane Everitt
parent 0def41740a
commit e64eb4901e
7 changed files with 203 additions and 13 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -292,12 +292,17 @@ class ActionsClass {
showLoaderOnConfirm: true
}, () => {
$.ajax({
type: 'DELETE',
url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/server/file/f/${delPath}${delName}`,
type: 'POST',
headers: {
'X-Access-Token': Pterodactyl.server.daemonSecret,
'X-Access-Server': Pterodactyl.server.uuid,
}
},
contentType: 'application/json; charset=utf-8',
url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/server/file/delete`,
timeout: 10000,
data: JSON.stringify({
items: [`${delPath}${delName}`]
}),
}).done(data => {
nameBlock.parent().addClass('warning').delay(200).fadeOut();
swal({
@ -316,6 +321,125 @@ class ActionsClass {
});
}
toggleMassActions() {
if ($('#file_listing input[type="checkbox"]:checked').length) {
$('#mass_actions').removeClass('disabled');
} else {
$('#mass_actions').addClass('disabled');
}
}
toggleHighlight(event) {
const parent = $(event.currentTarget);
const item = $(event.currentTarget).find('input');
if($(item).is(':checked')) {
$(item).prop('checked', false);
parent.removeClass('warning').delay(200);
} else {
$(item).prop('checked', true);
parent.addClass('warning').delay(200);
}
}
highlightAll(event) {
let parent;
const item = $(event.currentTarget).find('input');
if($(item).is(':checked')) {
$('#file_listing input[type=checkbox]').prop('checked', false);
$('#file_listing input[data-action="addSelection"]').each(function() {
parent = $(this).closest('tr');
parent.removeClass('warning').delay(200);
});
} else {
$('#file_listing input[type=checkbox]').prop('checked', true);
$('#file_listing input[data-action="addSelection"]').each(function() {
parent = $(this).closest('tr');
parent.addClass('warning').delay(200);
});
}
}
deleteSelected() {
let selectedItems = [];
let selectedItemsElements = [];
let parent;
let nameBlock;
let delLocation;
$('#file_listing input[data-action="addSelection"]:checked').each(function() {
parent = $(this).closest('tr');
nameBlock = $(parent).find('td[data-identifier="name"]');
delLocation = decodeURIComponent(nameBlock.data('path')) + decodeURIComponent(nameBlock.data('name'));
selectedItems.push(delLocation);
selectedItemsElements.push(parent);
});
if (selectedItems.length != 0)
{
let formattedItems = "";
$.each(selectedItems, function(key, value) {
formattedItems += ("<code>" + value + "</code>, ");
})
formattedItems = formattedItems.slice(0, -2);
swal({
type: 'warning',
title: '',
text: 'Are you sure you want to delete:' + formattedItems + '? There is <strong>no</strong> reversing this action.',
html: true,
showCancelButton: true,
showConfirmButton: true,
closeOnConfirm: false,
showLoaderOnConfirm: true
}, () => {
$.ajax({
type: 'POST',
headers: {
'X-Access-Token': Pterodactyl.server.daemonSecret,
'X-Access-Server': Pterodactyl.server.uuid,
},
contentType: 'application/json; charset=utf-8',
url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/server/file/delete`,
timeout: 10000,
data: JSON.stringify({
items: selectedItems
}),
}).done(data => {
$('#file_listing input:checked').each(function() {
$(this).prop('checked', false);
});
$.each(selectedItemsElements, function() {
$(this).addClass('warning').delay(200).fadeOut();
})
swal({
type: 'success',
title: 'Files Deleted'
});
}).fail(jqXHR => {
console.error(jqXHR);
swal({
type: 'error',
title: 'Whoops!',
html: true,
text: 'An error occured while attempting to delete these files. Please try again.',
});
});
});
} else {
swal({
type: 'warning',
title: '',
text: 'Please select files/folders to delete.',
});
}
}
decompress() {
const nameBlock = $(this.element).find('td[data-identifier="name"]');
const compPath = decodeURIComponent(nameBlock.data('path'));

View file

@ -45,6 +45,10 @@ class FileManager {
ContextMenu.run();
this.reloadFilesButton();
this.addFolderButton();
this.selectItem();
this.selectAll();
this.selectiveDeletion();
this.selectRow();
if (_.isFunction(next)) {
return next();
}
@ -83,12 +87,42 @@ class FileManager {
});
}
selectItem() {
$('[data-action="addSelection"]').on('click', event => {
event.preventDefault();
});
}
selectAll() {
$('[data-action="selectAll"]').on('click', event => {
event.preventDefault();
});
}
selectiveDeletion() {
$('[data-action="selective-deletion"]').on('mousedown', event => {
new ActionsClass().deleteSelected();
});
}
addFolderButton() {
$('[data-action="add-folder"]').unbind().on('click', () => {
new ActionsClass().folder($('#file_listing').data('current-dir') || '/');
})
}
selectRow() {
$('#file_listing tr').on('mousedown', event => {
if($(event.target).is('th') || $(event.target).is('input[data-action="selectAll"]')) {
new ActionsClass().highlightAll(event);
} else if($(event.target).is('td') || $(event.target).is('input[data-action="addSelection"]')) {
new ActionsClass().toggleHighlight(event);
}
new ActionsClass().toggleMassActions();
});
}
decodeHash() {
return decodeURIComponent(window.location.hash.substring(1));
}