From fc023748c10eab307b0c17d36e57e21dc1a3c332 Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Sun, 31 Mar 2024 20:42:28 +0200 Subject: [PATCH] WebClient: improve file uploads Signed-off-by: Nicola Murino --- internal/httpd/api_shares.go | 7 +++ static/locales/en/translation.json | 2 +- static/locales/it/translation.json | 2 +- templates/common/base.html | 7 +++ templates/webadmin/admins.html | 1 + templates/webadmin/connections.html | 1 + templates/webadmin/defender.html | 1 + templates/webadmin/eventactions.html | 1 + templates/webadmin/eventrules.html | 1 + templates/webadmin/folders.html | 1 + templates/webadmin/groups.html | 1 + templates/webadmin/iplists.html | 1 + templates/webadmin/roles.html | 1 + templates/webadmin/users.html | 1 + templates/webclient/files.html | 88 ++++++++++++++++++++++------ templates/webclient/shares.html | 1 + templates/webclient/shareupload.html | 36 ++++++++++-- 17 files changed, 127 insertions(+), 26 deletions(-) diff --git a/internal/httpd/api_shares.go b/internal/httpd/api_shares.go index d742cf67..531c5930 100644 --- a/internal/httpd/api_shares.go +++ b/internal/httpd/api_shares.go @@ -357,6 +357,13 @@ func (s *httpdServer) uploadFileToShare(w http.ResponseWriter, r *http.Request) return } defer common.Connections.Remove(connection.GetID()) + + if getBoolQueryParam(r, "mkdir_parents") { + if err = connection.CheckParentDirs(path.Dir(filePath)); err != nil { + sendAPIResponse(w, r, err, "Error checking parent directories", getMappedStatusCode(err)) + return + } + } if err := doUploadFile(w, r, connection, filePath); err != nil { dataprovider.UpdateShareLastUse(&share, -1) //nolint:errcheck } diff --git a/static/locales/en/translation.json b/static/locales/en/translation.json index 1ae2008b..8fd39e89 100644 --- a/static/locales/en/translation.json +++ b/static/locales/en/translation.json @@ -360,7 +360,7 @@ "err_403": "$t(fs.upload.err_generic). $t(fs.err_403)", "err_429": "$t(fs.upload.err_generic). $t(fs.err_429)", "err_dir_overwrite": "$t(fs.upload.err_generic). There are directories with the same name as the files: {{- val}}", - "overwrite_text": "File conflict detected. Do you want to overwrite the following files?" + "overwrite_text": "Conflict detected. Do you want to overwrite the following files/directories?" }, "quota_usage": { "title": "Quota usage", diff --git a/static/locales/it/translation.json b/static/locales/it/translation.json index c6dc0bc6..447994ee 100644 --- a/static/locales/it/translation.json +++ b/static/locales/it/translation.json @@ -360,7 +360,7 @@ "err_403": "$t(fs.upload.err_generic). $t(fs.err_403)", "err_429": "$t(fs.upload.err_generic). $t(fs.err_429)", "err_dir_overwrite": "$t(fs.upload.err_generic). Ci sono cartelle con lo stesso nome dei file: {{- val}}", - "overwrite_text": "Rilevato conflitto di file. Vuoi sovrascrivere i seguenti file?" + "overwrite_text": "Rilevato conflitto. Vuoi sovrascrivere i seguenti file/cartelle?" }, "quota_usage": { "title": "Utilizzo quota", diff --git a/templates/common/base.html b/templates/common/base.html index e2c1a6fc..df281ecc 100644 --- a/templates/common/base.html +++ b/templates/common/base.html @@ -341,6 +341,13 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). .shortcut { font-family: monospace; color: #666; } + + .overflow-auto { + overflow: auto; + } + .visibility-auto { + content-visibility: auto; + } {{- end}} diff --git a/templates/webadmin/admins.html b/templates/webadmin/admins.html index 0e9e02c0..e650fa4d 100644 --- a/templates/webadmin/admins.html +++ b/templates/webadmin/admins.html @@ -227,6 +227,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: "", error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; diff --git a/templates/webadmin/connections.html b/templates/webadmin/connections.html index ff9ac14e..10406a44 100644 --- a/templates/webadmin/connections.html +++ b/templates/webadmin/connections.html @@ -127,6 +127,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: "", error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; diff --git a/templates/webadmin/defender.html b/templates/webadmin/defender.html index cfdf4c29..2a553d99 100644 --- a/templates/webadmin/defender.html +++ b/templates/webadmin/defender.html @@ -132,6 +132,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: "", error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; diff --git a/templates/webadmin/eventactions.html b/templates/webadmin/eventactions.html index e78dba57..1475eff1 100644 --- a/templates/webadmin/eventactions.html +++ b/templates/webadmin/eventactions.html @@ -132,6 +132,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: "", error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; diff --git a/templates/webadmin/eventrules.html b/templates/webadmin/eventrules.html index 4dcaf544..7b1a22b7 100644 --- a/templates/webadmin/eventrules.html +++ b/templates/webadmin/eventrules.html @@ -183,6 +183,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: "", error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; diff --git a/templates/webadmin/folders.html b/templates/webadmin/folders.html index 3a10d975..eed87bdc 100644 --- a/templates/webadmin/folders.html +++ b/templates/webadmin/folders.html @@ -164,6 +164,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: "", error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; diff --git a/templates/webadmin/groups.html b/templates/webadmin/groups.html index 049eec8e..4c1271d1 100644 --- a/templates/webadmin/groups.html +++ b/templates/webadmin/groups.html @@ -150,6 +150,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: "", error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; diff --git a/templates/webadmin/iplists.html b/templates/webadmin/iplists.html index 5facdc7b..78e08665 100644 --- a/templates/webadmin/iplists.html +++ b/templates/webadmin/iplists.html @@ -263,6 +263,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: handleResponseData, error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; diff --git a/templates/webadmin/roles.html b/templates/webadmin/roles.html index 6a726796..20c487cd 100644 --- a/templates/webadmin/roles.html +++ b/templates/webadmin/roles.html @@ -151,6 +151,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: "", error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; diff --git a/templates/webadmin/users.html b/templates/webadmin/users.html index 8800369b..a0b1b773 100644 --- a/templates/webadmin/users.html +++ b/templates/webadmin/users.html @@ -279,6 +279,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: "", error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; diff --git a/templates/webclient/files.html b/templates/webclient/files.html index 6fa538aa..512e8bf9 100644 --- a/templates/webclient/files.html +++ b/templates/webclient/files.html @@ -159,7 +159,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
-
+
@@ -235,6 +235,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). //{{- end}} //{{- end}} + const dzPreviewTemplate = `
+ +
 ()
+
+
+
+ `; + //{{- if not .ShareUploadBaseURL}} const supportedEditExtensions = ["csv", "bat", "dyalog", "apl", "asc", "pgp", "sig", "asn", "asn1", "b", "bf", "c", "h", "ino", "cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx", "cob", "cpy", "cbl", "cs", "clj", @@ -556,6 +564,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). dataSrc: "", error: function ($xhr, textStatus, errorThrown) { $(".dataTables_processing").hide(); + $('#loader').addClass("d-none"); let txt = ""; if ($xhr) { let json = $xhr.responseJSON; @@ -1979,6 +1988,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). let has_errors = false; let index = 0; let success = 0; + let checkedDirs = []; $('#errorMsg').addClass("d-none"); $('#loading_message').text(""); KTApp.showPageLoading(); @@ -1996,10 +2006,20 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). let f = files[index]; let uploadPath; + let name = f.name; + let mkdirParents = "false"; + if (f.fullPath){ + name = f.fullPath; + let dirName = name.substr(0, name.lastIndexOf("/")); + if (!checkedDirs.includes(dirName)){ + mkdirParents = "true"; + checkedDirs.push(dirName); + } + } //{{- if .ShareUploadBaseURL}} - uploadPath = '{{.ShareUploadBaseURL}}' + encodeURIComponent("/" + f.name); + uploadPath = '{{.ShareUploadBaseURL}}' + encodeURIComponent("/" + name)+"?mkdir_parents="+mkdirParents; //{{- else}} - uploadPath = '{{.FileURL}}?path={{.CurrentDir}}' + encodeURIComponent("/" + f.name); + uploadPath = '{{.FileURL}}?path={{.CurrentDir}}' + encodeURIComponent("/" + name)+"&mkdir_parents="+mkdirParents; //{{- end}} let lastModified; try { @@ -2064,9 +2084,27 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). }); } + let filesArray = []; + let dirsArray = []; + if (files.length > 0){ + for (let i = 0; i < files.length; i++){ + if (files[i].fullPath){ + let dirName = files[i].fullPath.split('/')[0]; + if (!dirsArray.includes(dirName)){ + dirsArray.push(dirName); + } + if (!filesArray.includes(dirName)){ + filesArray.push(dirName); + } + } else { + filesArray.push(files[i].name); + } + } + } + CheckExist.fire({ operation: "upload", - files: files, + files: filesArray, path: "{{.CurrentDir}}" }).then((result)=> { if (result.error) { @@ -2079,7 +2117,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). let existingFiles = []; let existingDirs = []; $.each(result.data, function (key, item) { - if (item.type === "1") { + if (item.type === "1" && !dirsArray.includes(item.name)) { existingDirs.push(item.name); } else { existingFiles.push(item.name); @@ -2122,15 +2160,9 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). var promiseResolve; function doCheck(operation, files, target) { - let filesArray = []; - if (files && files.length > 0){ - for (let i = 0; i < files.length; i++){ - filesArray.push(files[i].name); - } - } let path = '{{.CheckExistURL}}?op='+encodeURIComponent(operation)+"&path="+target; axios.post(path, { - files: filesArray + files: files }, { headers: { timeout: 15000, @@ -2176,12 +2208,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). var dropzone = new Dropzone("#upload_files", { url: "{{.FilesURL}}?path={{.CurrentDir}}", paramName: "filenames", - maxFiles: 250, + createImageThumbnails: false, + maxFiles: null, maxFilesize: null, autoQueue: false, - addRemoveLinks: true, + addRemoveLinks: false, autoProcessQueue: false, filesizeBase: 1000, + previewTemplate: dzPreviewTemplate, init: function() { var dropzone = this; $("#upload_files_button").click(function(){ @@ -2191,18 +2225,27 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). }); dropzone.on("addedfile", file => { - file.previewElement.querySelector(".dz-progress").style.display = 'none'; + for (node of file.previewElement.querySelectorAll("[data-custom-size]")) { + node.textContent = fileSizeIEC(file.size); + } + if (file.fullPath){ + for (var node of file.previewElement.querySelectorAll("[data-dz-name]")) { + node.textContent = file.fullPath; + } + } }); var dropzoneEmpty = new Dropzone("#upload_files_empty", { url: "{{.FilesURL}}?path={{.CurrentDir}}", paramName: "filenames", - maxFiles: 250, + createImageThumbnails: false, + maxFiles: null, maxFilesize: null, autoQueue: false, - addRemoveLinks: true, + addRemoveLinks: false, autoProcessQueue: false, filesizeBase: 1000, + previewTemplate: dzPreviewTemplate, init: function() { var dropzoneEmpty = this; $("#upload_files_empty_button").click(function(){ @@ -2212,7 +2255,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). }); dropzoneEmpty.on("addedfile", file => { - file.previewElement.querySelector(".dz-progress").style.display = 'none'; + for (node of file.previewElement.querySelectorAll("[data-custom-size]")) { + node.textContent = fileSizeIEC(file.size); + } + if (file.fullPath){ + for (var node of file.previewElement.querySelectorAll("[data-dz-name]")) { + node.textContent = file.fullPath; + } + } }); $('#modal_video_player').on('hide.bs.modal', function () { @@ -2406,7 +2456,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).