From 0722c4369b27493394e2d830697fc8f34d8fd75d Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Sun, 14 Jan 2024 16:59:27 +0100 Subject: [PATCH] WIP new WebAdmin: folders page Signed-off-by: Nicola Murino --- internal/httpd/server.go | 6 +- internal/httpd/webadmin.go | 39 +- static/locales/en/translation.json | 7 +- static/locales/it/translation.json | 7 +- templates/webadmin/folders.html | 684 +++++++++++++++-------------- templates/webadmin/groups.html | 9 +- templates/webadmin/users.html | 20 +- templates/webclient/files.html | 135 +++++- templates/webclient/shares.html | 9 +- 9 files changed, 551 insertions(+), 365 deletions(-) diff --git a/internal/httpd/server.go b/internal/httpd/server.go index de78dd7c..42b30ecd 100644 --- a/internal/httpd/server.go +++ b/internal/httpd/server.go @@ -1682,7 +1682,7 @@ func (s *httpdServer) setupWebAdminRoutes() { router.With(s.checkPerm(dataprovider.PermAdminViewUsers), s.refreshCookie). Get(webUsersPath, s.handleGetWebUsers) - router.With(s.checkPerm(dataprovider.PermAdminViewUsers), s.refreshCookie). + router.With(s.checkPerm(dataprovider.PermAdminViewUsers), compressor.Handler, s.refreshCookie). Get(webUsersPath+"/json", getAllUsers) router.With(s.checkPerm(dataprovider.PermAdminAddUsers), s.refreshCookie). Get(webUserPath, s.handleWebAddUserGet) @@ -1693,7 +1693,7 @@ func (s *httpdServer) setupWebAdminRoutes() { s.handleWebUpdateUserPost) router.With(s.checkPerm(dataprovider.PermAdminManageGroups), s.refreshCookie). Get(webGroupsPath, s.handleWebGetGroups) - router.With(s.checkPerm(dataprovider.PermAdminManageGroups), s.refreshCookie). + router.With(s.checkPerm(dataprovider.PermAdminManageGroups), compressor.Handler, s.refreshCookie). Get(webGroupsPath+"/json", getAllGroups) router.With(s.checkPerm(dataprovider.PermAdminManageGroups), s.refreshCookie). Get(webGroupPath, s.handleWebAddGroupGet) @@ -1708,6 +1708,8 @@ func (s *httpdServer) setupWebAdminRoutes() { Get(webConnectionsPath, s.handleWebGetConnections) router.With(s.checkPerm(dataprovider.PermAdminManageFolders), s.refreshCookie). Get(webFoldersPath, s.handleWebGetFolders) + router.With(s.checkPerm(dataprovider.PermAdminManageFolders), compressor.Handler, s.refreshCookie). + Get(webFoldersPath+"/json", getAllFolders) router.With(s.checkPerm(dataprovider.PermAdminManageFolders), s.refreshCookie). Get(webFolderPath, s.handleWebAddFolderGet) router.With(s.checkPerm(dataprovider.PermAdminManageFolders)).Post(webFolderPath, s.handleWebAddFolderPost) diff --git a/internal/httpd/webadmin.go b/internal/httpd/webadmin.go index 99a34a15..aee5cb10 100644 --- a/internal/httpd/webadmin.go +++ b/internal/httpd/webadmin.go @@ -172,11 +172,6 @@ type adminsPage struct { Admins []dataprovider.Admin } -type foldersPage struct { - basePage - Folders []vfs.BaseVirtualFolder -} - type rolesPage struct { basePage Roles []dataprovider.Role @@ -428,7 +423,7 @@ func loadAdminTemplates(templatesPath string) { filepath.Join(templatesPath, templateAdminDir, templateMessage), } foldersPaths := []string{ - filepath.Join(templatesPath, templateCommonDir, templateCommonCSS), + filepath.Join(templatesPath, templateCommonDir, templateCommonBase), filepath.Join(templatesPath, templateAdminDir, templateBase), filepath.Join(templatesPath, templateAdminDir, templateFolders), } @@ -3444,7 +3439,7 @@ func (s *httpdServer) handleWebUpdateFolderPost(w http.ResponseWriter, r *http.R } func (s *httpdServer) getWebVirtualFolders(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]vfs.BaseVirtualFolder, error) { - folders := make([]vfs.BaseVirtualFolder, 0, limit) + folders := make([]vfs.BaseVirtualFolder, 0, 50) for { f, err := dataprovider.GetFolders(limit, len(folders), dataprovider.OrderASC, minimal) if err != nil { @@ -3459,25 +3454,27 @@ func (s *httpdServer) getWebVirtualFolders(w http.ResponseWriter, r *http.Reques return folders, nil } -func (s *httpdServer) handleWebGetFolders(w http.ResponseWriter, r *http.Request) { +func getAllFolders(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize) - limit := defaultQueryLimit - if _, ok := r.URL.Query()["qlimit"]; ok { - var err error - limit, err = strconv.Atoi(r.URL.Query().Get("qlimit")) + folders := make([]vfs.BaseVirtualFolder, 0, 50) + for { + f, err := dataprovider.GetFolders(defaultQueryLimit, len(folders), dataprovider.OrderASC, false) if err != nil { - limit = defaultQueryLimit + sendAPIResponse(w, r, err, getI18NErrorString(err, util.I18nError500Message), http.StatusInternalServerError) + return + } + folders = append(folders, f...) + if len(f) < defaultQueryLimit { + break } } - folders, err := s.getWebVirtualFolders(w, r, limit, false) - if err != nil { - return - } + render.JSON(w, r, folders) +} - data := foldersPage{ - basePage: s.getBasePageData(util.I18nFoldersTitle, webFoldersPath, r), - Folders: folders, - } +func (s *httpdServer) handleWebGetFolders(w http.ResponseWriter, r *http.Request) { + r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize) + + data := s.getBasePageData(util.I18nFoldersTitle, webFoldersPath, r) renderAdminTemplate(w, templateFolders, data) } diff --git a/static/locales/en/translation.json b/static/locales/en/translation.json index 828ff53b..17eceebb 100644 --- a/static/locales/en/translation.json +++ b/static/locales/en/translation.json @@ -206,7 +206,8 @@ "zero_no_limit_help": "0 means no limit", "global_settings": "Global settings", "mandatory_encryption": "Mandatory encryption", - "name_invalid": "The specified username is not valid, the following characters are allowed: a-zA-Z0-9-_.~" + "name_invalid": "The specified username is not valid, the following characters are allowed: a-zA-Z0-9-_.~", + "associations": "Associations" }, "fs": { "view_file": "View file \"{{- path}}\"", @@ -474,10 +475,12 @@ "members_summary": "Users: {{users}}. Admins: {{admins}}" }, "virtual_folders": { + "view_manage": "View and manage virtual folders", "mount_path": "mount path, i.e. /vfolder", "quota_size": "Quota size", "quota_size_help": "0 means no limit. You can use MB/GB/TB suffix", - "quota_files": "Quota files" + "quota_files": "Quota files", + "associations_summary": "Users: {{users}}. Groups: {{groups}}" }, "storage": { "title": "File system", diff --git a/static/locales/it/translation.json b/static/locales/it/translation.json index 5dd97326..4df3dd15 100644 --- a/static/locales/it/translation.json +++ b/static/locales/it/translation.json @@ -206,7 +206,8 @@ "zero_no_limit_help": "0 significa nessun limite", "global_settings": "Impostazioni globali", "mandatory_encryption": "Crittografia obbligatoria", - "name_invalid": "Il nome specificato non è valido, sono consentiti i seguenti caratteri: a-zA-Z0-9-_.~" + "name_invalid": "Il nome specificato non è valido, sono consentiti i seguenti caratteri: a-zA-Z0-9-_.~", + "associations": "Associazioni" }, "fs": { "view_file": "Visualizza file \"{{- path}}\"", @@ -474,10 +475,12 @@ "members_summary": "Utenti: {{users}}. Amministratori: {{admins}}" }, "virtual_folders": { + "view_manage": "Visualizza e gestisci cartelle virtuali", "mount_path": "percorso, es. /vfolder", "quota_size": "Quota (dimensione)", "quota_size_help": "0 significa nessun limite. E' possibile utilizzare il suffisso MB/GB/TB", - "quota_files": "Quota (numero file)" + "quota_files": "Quota (numero file)", + "associations_summary": "Utenti: {{users}}. Gruppi: {{groups}}" }, "storage": { "title": "File system", diff --git a/templates/webadmin/folders.html b/templates/webadmin/folders.html index 8b94cf0c..cf747517 100644 --- a/templates/webadmin/folders.html +++ b/templates/webadmin/folders.html @@ -1,361 +1,409 @@ {{template "base" .}} -{{define "title"}}{{.Title}}{{end}} +{{- define "extra_css"}} + +{{- end}} -{{define "extra_css"}} - - - - - - -{{end}} - -{{define "page_body"}} - - - - - -
-
-
View and manage folders
+{{- define "page_body"}} +{{- template "errmsg" ""}} +
+
+

View and manage folders

-
-
- +
+
+ + Loading... +
+
+
+
+ + +
+ +
+ + + {{- if .LoggedUser.HasPermission "manage_folders"}} + + + Add + + {{- end}} +
+
+
+ +
- - - - - - - - + + + + + + + - - {{range .Folders}} - - - - - - - - - - {{end}} - - +
NameStorageDescriptionAssociated usersAssociated groupsQuota
NameStorageDisk quotaAssociationsDescription
{{.GetLastQuotaUpdateAsString}}{{.Name}}{{.GetStorageDescrition}}{{.Description}}{{.GetUsersAsString}}{{.GetGroupsAsString}}{{.GetQuotaSummary}}
-{{end}} +{{- end}} +{{- define "extra_js"}} + + - - - - - - - - - - - -{{end}} \ No newline at end of file +{{- end}} \ No newline at end of file diff --git a/templates/webadmin/groups.html b/templates/webadmin/groups.html index 543a2cca..e39dc5d5 100644 --- a/templates/webadmin/groups.html +++ b/templates/webadmin/groups.html @@ -126,7 +126,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). if (!errorMessage){ errorMessage = "general.delete_error_generic"; } - showToast(2, errorMessage); + ModalAlert.fire({ + text: $.t(errorMessage), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); }); } }); diff --git a/templates/webadmin/users.html b/templates/webadmin/users.html index 44655f9f..771225eb 100644 --- a/templates/webadmin/users.html +++ b/templates/webadmin/users.html @@ -175,7 +175,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). if (!errorMessage){ errorMessage = "general.delete_error_generic"; } - showToast(2, errorMessage); + ModalAlert.fire({ + text: $.t(errorMessage), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); }); } }); @@ -209,7 +216,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). if (!errorMessage) { errorMessage = "general.quota_scan_error"; } - showToast(2, errorMessage); + ModalAlert.fire({ + text: $.t(errorMessage), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); }); } @@ -364,7 +378,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). if (!used){ used = 0; } - let usage = fileSizeIEC(used)+"/"+fileSizeIEC(row.quota_size) + let usage = fileSizeIEC(used)+"/"+fileSizeIEC(row.quota_size); val += $.t('fs.quota_usage.size', {val: usage})+". "; } else if (row.used_quota_size && row.used_quota_size > 0) { val += $.t('fs.quota_usage.size', {val: fileSizeIEC(row.used_quota_size)})+". "; diff --git a/templates/webclient/files.html b/templates/webclient/files.html index 0449fab8..21582359 100644 --- a/templates/webclient/files.html +++ b/templates/webclient/files.html @@ -1224,7 +1224,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). } items = checkMoveCopyItems(items) if (items.length == 0){ - showToast(2, "fs.invalid_name"); + ModalAlert.fire({ + text: $.t('fs.invalid_name'), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); return; } keepAlive(); @@ -1296,7 +1303,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). if (!errorMessage){ errorMessage = "fs.copy.err_generic"; } - showToast(2, errorMessage); + ModalAlert.fire({ + text: $.t(errorMessage), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); copyItem(); }); } @@ -1315,10 +1329,24 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). }).then((result)=>{ if (result.error) { hasError = true; - showToast(2, "fs.copy.err_generic"); + ModalAlert.fire({ + text: $.t("fs.copy.err_generic"), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); } else if (result.data.length > 0){ hasError = true; - showToast(2, "fs.copy.err_exists"); + ModalAlert.fire({ + text: $.t("fs.copy.err_exists"), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); } copyItem(); }); @@ -1332,7 +1360,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). } items = checkMoveCopyItems(items) if (items.length == 0){ - showToast(2, "fs.invalid_name"); + ModalAlert.fire({ + text: $.t("fs.invalid_name"), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); return; } keepAlive(); @@ -1404,7 +1439,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). if (!errorMessage){ errorMessage = "fs.move.err_generic"; } - showToast(2, errorMessage); + ModalAlert.fire({ + text: $.t(errorMessage), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); moveItem(); }); } @@ -1423,10 +1465,24 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). }).then((result)=>{ if (result.error) { hasError = true; - showToast(2, "fs.move.err_generic"); + ModalAlert.fire({ + text: $.t("fs.move.err_generic"), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); } else if (result.data.length > 0){ hasError = true; - showToast(2, "fs.move.err_exists"); + ModalAlert.fire({ + text: $.t("fs.move.err_exists"), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); } moveItem(); }); @@ -1493,7 +1549,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). if (!errorMessage){ errorMessage = "fs.delete.err_generic"; } - showToast(2, errorMessage, {name: itemName}); + ModalAlert.fire({ + text: $.t(errorMessage, {name: itemName}), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); }); } }); @@ -1523,15 +1586,36 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). let oldName = getNameFromMeta(meta); let newName = $('#rename_new_name').val(); if (!newName){ - showToast(2, "general.name_required"); + ModalAlert.fire({ + text: $.t('general.name_required'), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); return; } if (newName == oldName){ - showToast(2, "general.name_different"); + ModalAlert.fire({ + text: $.t('general.name_different'), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); return; } if (newName.includes("/")){ - showToast(2, "fs.invalid_name"); + ModalAlert.fire({ + text: $.t('fs.invalid_name'), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); return; } @@ -1567,7 +1651,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). if (!errorMessage) { errorMessage = "fs.rename.err_generic"; } - showToast(2, errorMessage, { name: oldName }); + ModalAlert.fire({ + text: $.t(errorMessage, {name: oldName}), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); }); } @@ -1578,12 +1669,26 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). }).then((result)=>{ if (result.error) { KTApp.hidePageLoading(); - showToast(2, "fs.rename.err_generic", { name: oldName }); + ModalAlert.fire({ + text: $.t('fs.rename.err_generic', { name: oldName }), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); return; } if (result.data.length > 0){ KTApp.hidePageLoading(); - showToast(2, "fs.rename.err_exists", { name: oldName }); + ModalAlert.fire({ + text: $.t('fs.rename.err_exists', { name: oldName }), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); return; } executeRename(); diff --git a/templates/webclient/shares.html b/templates/webclient/shares.html index cd43d348..c2e8d708 100644 --- a/templates/webclient/shares.html +++ b/templates/webclient/shares.html @@ -205,7 +205,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com). if (!errorMessage){ errorMessage = "general.delete_error_generic"; } - showToast(2, errorMessage); + ModalAlert.fire({ + text: $.t(errorMessage), + icon: "warning", + confirmButtonText: $.t('general.ok'), + customClass: { + confirmButton: "btn btn-primary" + } + }); }); } });