mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-07 23:00:55 +03:00
web client: allow to upload/delete multiple files
This commit is contained in:
@@ -85,7 +85,7 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="uploadFilesModalLabel">
|
||||
Upload a file
|
||||
Upload one or more files
|
||||
</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
@@ -93,9 +93,10 @@
|
||||
</div>
|
||||
<form id="upload_files_form" action="{{.FilesURL}}?path={{.CurrentDir}}" method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-body">
|
||||
<input type="file" class="form-control-file" id="files_name" name="filenames" required>
|
||||
<input type="file" class="form-control-file" id="files_name" name="filenames" required multiple>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<input type="hidden" name="_form_token" value="{{.CSRFToken}}">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
@@ -148,7 +149,7 @@
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">Do you want to delete the selected item?</div>
|
||||
<div class="modal-body">Do you want to delete the selected item/s?</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">
|
||||
Cancel
|
||||
@@ -183,6 +184,7 @@
|
||||
<script src="{{.StaticURL}}/vendor/codemirror/codemirror.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/codemirror/meta.js"></script>
|
||||
<script type="text/javascript">
|
||||
var spinnerDone = false;
|
||||
|
||||
function getIconForFile(filename) {
|
||||
var extension = filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
|
||||
@@ -295,46 +297,76 @@
|
||||
function deleteAction() {
|
||||
var table = $('#dataTable').DataTable();
|
||||
table.button('delete:name').enable(false);
|
||||
var selected = table.column(0).checkboxes.selected()[0];
|
||||
var itemType = getTypeFromMeta(selected);
|
||||
var itemName = getNameFromMeta(selected);
|
||||
var path;
|
||||
if (itemType == "1"){
|
||||
path = '{{.DirsURL}}';
|
||||
} else {
|
||||
path = '{{.FilesURL}}';
|
||||
}
|
||||
path+='?path={{.CurrentDir}}'+fixedEncodeURIComponent("/"+itemName);
|
||||
|
||||
var selectedItems = table.column(0).checkboxes.selected()
|
||||
var has_errors = false;
|
||||
var index = 0;
|
||||
var success = 0;
|
||||
spinnerDone = false;
|
||||
|
||||
$('#deleteModal').modal('hide');
|
||||
$.ajax({
|
||||
url: path,
|
||||
type: 'DELETE',
|
||||
dataType: 'json',
|
||||
headers: { 'X-CSRF-TOKEN': '{{.CSRFToken}}' },
|
||||
timeout: 15000,
|
||||
success: function (result) {
|
||||
location.reload();
|
||||
},
|
||||
error: function ($xhr, textStatus, errorThrown) {
|
||||
var txt = "Unable to delete the selected item";
|
||||
if ($xhr) {
|
||||
var json = $xhr.responseJSON;
|
||||
if (json) {
|
||||
if (json.message) {
|
||||
txt = json.message;
|
||||
}
|
||||
if (json.error) {
|
||||
txt += ": " + json.error;
|
||||
$('#spinnerModal').modal('show');
|
||||
|
||||
function deleteItem() {
|
||||
if (index >= selectedItems.length || has_errors){
|
||||
$('#spinnerModal').modal('hide');
|
||||
spinnerDone = true;
|
||||
if (!has_errors){
|
||||
location.reload();
|
||||
}
|
||||
return;
|
||||
}
|
||||
var selected = selectedItems[index];
|
||||
var itemType = getTypeFromMeta(selected);
|
||||
var itemName = getNameFromMeta(selected);
|
||||
var path;
|
||||
if (itemType == "1"){
|
||||
path = '{{.DirsURL}}';
|
||||
} else {
|
||||
path = '{{.FilesURL}}';
|
||||
}
|
||||
path+='?path={{.CurrentDir}}'+fixedEncodeURIComponent("/"+itemName);
|
||||
|
||||
$.ajax({
|
||||
url: path,
|
||||
type: 'DELETE',
|
||||
dataType: 'json',
|
||||
headers: { 'X-CSRF-TOKEN': '{{.CSRFToken}}' },
|
||||
timeout: 60000,
|
||||
success: function (result) {
|
||||
index++;
|
||||
success++;
|
||||
deleteItem();
|
||||
},
|
||||
error: function ($xhr, textStatus, errorThrown) {
|
||||
index++;
|
||||
has_errors = true;
|
||||
var txt = "Unable to delete the selected item/s";
|
||||
if (success > 0){
|
||||
txt = "Not all the selected items have been deleted, please reload the page";
|
||||
}
|
||||
if ($xhr) {
|
||||
var json = $xhr.responseJSON;
|
||||
if (json) {
|
||||
if (json.message) {
|
||||
txt = json.message;
|
||||
}
|
||||
if (json.error) {
|
||||
txt += ": " + json.error;
|
||||
}
|
||||
}
|
||||
}
|
||||
$('#errorTxt').text(txt);
|
||||
$('#errorMsg').show();
|
||||
setTimeout(function () {
|
||||
$('#errorMsg').hide();
|
||||
}, 10000);
|
||||
deleteItem();
|
||||
}
|
||||
$('#errorTxt').text(txt);
|
||||
$('#errorMsg').show();
|
||||
setTimeout(function () {
|
||||
$('#errorMsg').hide();
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
deleteItem();
|
||||
}
|
||||
|
||||
function keepAlive() {
|
||||
@@ -345,6 +377,11 @@
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#spinnerModal').on('shown.bs.modal', function () {
|
||||
if (spinnerDone){
|
||||
$('#spinnerModal').modal('hide');
|
||||
}
|
||||
});
|
||||
$("#create_dir_form").submit(function (event) {
|
||||
event.preventDefault();
|
||||
$('#createDirModal').modal('hide');
|
||||
@@ -385,44 +422,73 @@
|
||||
event.preventDefault();
|
||||
var keepAliveTimer = setInterval(keepAlive, 90000);
|
||||
var path = '{{.FilesURL}}?path={{.CurrentDir}}';
|
||||
$.ajax({
|
||||
url: path,
|
||||
type: 'POST',
|
||||
data: new FormData(this),
|
||||
processData: false,
|
||||
contentType: false,
|
||||
headers: { 'X-CSRF-TOKEN': '{{.CSRFToken}}' },
|
||||
timeout: 0,
|
||||
beforeSend: function () {
|
||||
$('#uploadFilesModal').modal('hide');
|
||||
$('#spinnerModal').modal('show');
|
||||
},
|
||||
success: function (result) {
|
||||
clearInterval(keepAliveTimer);
|
||||
location.reload();
|
||||
},
|
||||
error: function ($xhr, textStatus, errorThrown) {
|
||||
|
||||
var files = $("#files_name")[0].files;
|
||||
var has_errors = false;
|
||||
var index = 0;
|
||||
var success = 0;
|
||||
spinnerDone = false;
|
||||
|
||||
$('#uploadFilesModal').modal('hide');
|
||||
$('#spinnerModal').modal('show');
|
||||
|
||||
function uploadFile() {
|
||||
if (index >= files.length || has_errors){
|
||||
//console.log("upload done, index: "+index+" has errors: "+has_errors+" ok: "+success);
|
||||
clearInterval(keepAliveTimer);
|
||||
$('#spinnerModal').modal('hide');
|
||||
var txt = "Error uploading files";
|
||||
if ($xhr) {
|
||||
var json = $xhr.responseJSON;
|
||||
if (json) {
|
||||
if (json.message) {
|
||||
txt = json.message;
|
||||
}
|
||||
if (json.error) {
|
||||
txt += ": " + json.error;
|
||||
spinnerDone = true;
|
||||
if (!has_errors){
|
||||
location.reload();
|
||||
}
|
||||
return;
|
||||
}
|
||||
//console.log("upload file, index: "+index);
|
||||
var data = new FormData();
|
||||
data.append('filenames', files[index]);
|
||||
|
||||
$.ajax({
|
||||
url: path,
|
||||
type: 'POST',
|
||||
data: data,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
headers: { 'X-CSRF-TOKEN': '{{.CSRFToken}}' },
|
||||
timeout: 0,
|
||||
success: function (result) {
|
||||
index++;
|
||||
success++;
|
||||
uploadFile();
|
||||
},
|
||||
error: function ($xhr, textStatus, errorThrown) {
|
||||
index++;
|
||||
has_errors = true;
|
||||
var txt = "Error uploading files";
|
||||
if (success > 0){
|
||||
txt = "Not all files have been uploaded, please reload the page";
|
||||
}
|
||||
if ($xhr) {
|
||||
var json = $xhr.responseJSON;
|
||||
if (json) {
|
||||
if (json.message) {
|
||||
txt = json.message;
|
||||
}
|
||||
if (json.error) {
|
||||
txt += ": " + json.error;
|
||||
}
|
||||
}
|
||||
}
|
||||
$('#errorTxt').text(txt);
|
||||
$('#errorMsg').show();
|
||||
setTimeout(function () {
|
||||
$('#errorMsg').hide();
|
||||
}, 10000);
|
||||
uploadFile();
|
||||
}
|
||||
$('#errorTxt').text(txt);
|
||||
$('#errorMsg').show();
|
||||
setTimeout(function () {
|
||||
$('#errorMsg').hide();
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
uploadFile();
|
||||
});
|
||||
|
||||
$("#rename_form").submit(function (event){
|
||||
@@ -505,6 +571,7 @@
|
||||
name: 'addFiles',
|
||||
titleAttr: "Upload files",
|
||||
action: function (e, dt, node, config) {
|
||||
document.getElementById("files_name").value = null;
|
||||
$('#uploadFilesModal').modal('show');
|
||||
},
|
||||
enabled: true
|
||||
@@ -671,7 +738,7 @@
|
||||
table.button('rename:name').enable(selectedItems == 1);
|
||||
{{end}}
|
||||
{{if .CanDelete}}
|
||||
table.button('delete:name').enable(selectedItems == 1);
|
||||
table.button('delete:name').enable(selectedItems > 0);
|
||||
{{end}}
|
||||
{{if .CanShare}}
|
||||
table.button('share:name').enable(selectedItems > 0);
|
||||
|
||||
Reference in New Issue
Block a user