WIP new WebAdmin: folder page

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino
2024-01-16 19:51:37 +01:00
parent d939a82225
commit 5ac99ee556
7 changed files with 212 additions and 136 deletions

View File

@@ -428,7 +428,7 @@ func loadAdminTemplates(templatesPath string) {
filepath.Join(templatesPath, templateAdminDir, templateFolders), filepath.Join(templatesPath, templateAdminDir, templateFolders),
} }
folderPaths := []string{ folderPaths := []string{
filepath.Join(templatesPath, templateCommonDir, templateCommonCSS), filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
filepath.Join(templatesPath, templateAdminDir, templateBase), filepath.Join(templatesPath, templateAdminDir, templateBase),
filepath.Join(templatesPath, templateAdminDir, templateFsConfig), filepath.Join(templatesPath, templateAdminDir, templateFsConfig),
filepath.Join(templatesPath, templateAdminDir, templateFolder), filepath.Join(templatesPath, templateAdminDir, templateFolder),
@@ -1171,13 +1171,13 @@ func (s *httpdServer) renderFolderPage(w http.ResponseWriter, r *http.Request, f
var title, currentURL string var title, currentURL string
switch mode { switch mode {
case folderPageModeAdd: case folderPageModeAdd:
title = "Add a new folder" title = util.I18nAddFolderTitle
currentURL = webFolderPath currentURL = webFolderPath
case folderPageModeUpdate: case folderPageModeUpdate:
title = "Update folder" title = util.I18nUpdateFolderTitle
currentURL = fmt.Sprintf("%v/%v", webFolderPath, url.PathEscape(folder.Name)) currentURL = fmt.Sprintf("%v/%v", webFolderPath, url.PathEscape(folder.Name))
case folderPageModeTemplate: case folderPageModeTemplate:
title = "Folder template" title = util.I18nTemplateFolderTitle
currentURL = webTemplateFolder currentURL = webTemplateFolder
} }
folder.FsConfig.RedactedSecret = redactedSecret folder.FsConfig.RedactedSecret = redactedSecret
@@ -1201,6 +1201,11 @@ func (s *httpdServer) renderFolderPage(w http.ResponseWriter, r *http.Request, f
func getFoldersForTemplate(r *http.Request) []string { func getFoldersForTemplate(r *http.Request) []string {
var res []string var res []string
for k := range r.Form {
if hasPrefixAndSuffix(k, "template_folders[", "][tpl_foldername]") {
r.Form.Add("tpl_foldername", r.Form.Get(k))
}
}
folderNames := r.Form["tpl_foldername"] folderNames := r.Form["tpl_foldername"]
folders := make(map[string]bool) folders := make(map[string]bool)
for _, name := range folderNames { for _, name := range folderNames {
@@ -1958,11 +1963,17 @@ func getQuotaLimits(r *http.Request) (int64, int, error) {
func updateRepeaterFormFields(r *http.Request) { func updateRepeaterFormFields(r *http.Request) {
for k := range r.Form { for k := range r.Form {
if hasPrefixAndSuffix(k, "public_keys[", "][public_key]") { if hasPrefixAndSuffix(k, "public_keys[", "][public_key]") {
r.Form.Add("public_keys", r.Form.Get(k)) key := r.Form.Get(k)
if strings.TrimSpace(key) != "" {
r.Form.Add("public_keys", key)
}
continue continue
} }
if hasPrefixAndSuffix(k, "tls_certs[", "][tls_cert]") { if hasPrefixAndSuffix(k, "tls_certs[", "][tls_cert]") {
r.Form.Add("tls_certs", strings.TrimSpace(r.Form.Get(k))) cert := strings.TrimSpace(r.Form.Get(k))
if cert != "" {
r.Form.Add("tls_certs", cert)
}
continue continue
} }
if hasPrefixAndSuffix(k, "virtual_folders[", "][vfolder_path]") { if hasPrefixAndSuffix(k, "virtual_folders[", "][vfolder_path]") {

View File

@@ -186,6 +186,9 @@ const (
I18nAddGroupTitle = "title.add_group" I18nAddGroupTitle = "title.add_group"
I18nUpdateGroupTitle = "title.update_group" I18nUpdateGroupTitle = "title.update_group"
I18nErrorInvalidTLSCert = "user.tls_cert_invalid" I18nErrorInvalidTLSCert = "user.tls_cert_invalid"
I18nAddFolderTitle = "title.add_folder"
I18nUpdateFolderTitle = "title.update_folder"
I18nTemplateFolderTitle = "title.template_folder"
) )
// NewI18nError returns a I18nError wrappring the provided error // NewI18nError returns a I18nError wrappring the provided error

View File

@@ -49,7 +49,10 @@
"update_user": "Update user", "update_user": "Update user",
"template_user": "User template", "template_user": "User template",
"add_group": "Add group", "add_group": "Add group",
"update_group": "Update group" "update_group": "Update group",
"add_folder": "Add virtual folder",
"update_folder": "Update virtual folder",
"template_folder": "Virtual folder template"
}, },
"setup": { "setup": {
"desc": "To start using SFTPGo you need to create an administrator user", "desc": "To start using SFTPGo you need to create an administrator user",
@@ -207,7 +210,8 @@
"global_settings": "Global settings", "global_settings": "Global settings",
"mandatory_encryption": "Mandatory encryption", "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" "associations": "Associations",
"template_placeholders": "The following placeholders are supported"
}, },
"fs": { "fs": {
"view_file": "View file \"{{- path}}\"", "view_file": "View file \"{{- path}}\"",
@@ -470,7 +474,12 @@
"expires_in_help": "Account expiration as number of days from the creation. 0 means no expiration", "expires_in_help": "Account expiration as number of days from the creation. 0 means no expiration",
"tls_certs": "TLS certificates", "tls_certs": "TLS certificates",
"tls_cert_help": "Paste your PEM encoded TLS certificate here", "tls_cert_help": "Paste your PEM encoded TLS certificate here",
"tls_cert_invalid": "Invalid TLS certificate" "tls_cert_invalid": "Invalid TLS certificate",
"template_title": "Create one or more new users from this template",
"template_username_placeholder": "replaced with the specified username",
"template_password_placeholder": "replaced with the specified password",
"template_help1": "Placeholders will be replaced in paths and credentials of the configured storage backend.",
"template_help2": "The generated users can be saved or exported. Exported users can be imported from the \"Maintenance\" section of this SFTPGo instance or another."
}, },
"group": { "group": {
"view_manage": "View and manage groups", "view_manage": "View and manage groups",
@@ -483,7 +492,13 @@
"quota_size": "Quota size", "quota_size": "Quota size",
"quota_size_help": "0 means no limit. You can use MB/GB/TB suffix", "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}}" "associations_summary": "Users: {{users}}. Groups: {{groups}}",
"template_title": "Create one or more new virtual folders from this template",
"template_name_placeholder": "replaced with the name of the specified virtual folder",
"template_help": "The generated virtual folders can be saved or exported. Exported folders can be imported from the \"Maintenance\" section of this SFTPGo instance or another.",
"name": "Virtual folder name",
"submit_generate": "Generate and save folders",
"submit_export": "Generate and export folder"
}, },
"storage": { "storage": {
"title": "File system", "title": "File system",

View File

@@ -49,7 +49,10 @@
"update_user": "Aggiorna utente", "update_user": "Aggiorna utente",
"template_user": "Modello utente", "template_user": "Modello utente",
"add_group": "Aggiungi gruppo", "add_group": "Aggiungi gruppo",
"update_group": "Aggiorna gruppo" "update_group": "Aggiorna gruppo",
"add_folder": "Aggiungi cartella virtuale",
"update_folder": "Aggiorna cartella virtuale",
"template_folder": "Modello cartella virtuale"
}, },
"setup": { "setup": {
"desc": "Per iniziare a utilizzare SFTPGo devi creare un utente amministratore", "desc": "Per iniziare a utilizzare SFTPGo devi creare un utente amministratore",
@@ -207,7 +210,8 @@
"global_settings": "Impostazioni globali", "global_settings": "Impostazioni globali",
"mandatory_encryption": "Crittografia obbligatoria", "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" "associations": "Associazioni",
"template_placeholders": "Sono supportati i seguenti segnaposto"
}, },
"fs": { "fs": {
"view_file": "Visualizza file \"{{- path}}\"", "view_file": "Visualizza file \"{{- path}}\"",
@@ -470,7 +474,12 @@
"expires_in_help": "Scadenza dell'account espressa in numero di giorni dalla creazione. 0 significa nessuna scadenza", "expires_in_help": "Scadenza dell'account espressa in numero di giorni dalla creazione. 0 significa nessuna scadenza",
"tls_certs": "Certificati TLS", "tls_certs": "Certificati TLS",
"tls_cert_help": "Incolla qui il tuo certificato TLS codificato PEM", "tls_cert_help": "Incolla qui il tuo certificato TLS codificato PEM",
"tls_cert_invalid": "Certificato TLS non valido" "tls_cert_invalid": "Certificato TLS non valido",
"template_title": "Crea uno o più nuovi utenti da questo modello",
"template_username_placeholder": "sostituito con il nome utente specificato",
"template_password_placeholder": "sostituito con la password specificata",
"template_help1": "I segnaposto verranno sostituiti nei percorsi e nelle credenziali del backend di archiviazione configurato.",
"template_help2": "Gli utenti generati possono essere salvati o esportati. Gli utenti esportati possono essere importati dalla sezione \"Manutenzione\" di questa istanza SFTPGo o di un'altra."
}, },
"group": { "group": {
"view_manage": "Visualizza e gestisci gruppi", "view_manage": "Visualizza e gestisci gruppi",
@@ -483,7 +492,13 @@
"quota_size": "Quota (dimensione)", "quota_size": "Quota (dimensione)",
"quota_size_help": "0 significa nessun limite. E' possibile utilizzare il suffisso MB/GB/TB", "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}}" "associations_summary": "Utenti: {{users}}. Gruppi: {{groups}}",
"template_title": "Crea una o più nuove cartelle virtuali da questo modello",
"template_name_placeholder": "sostituito con il nome della cartella virtuale specificata",
"template_help": "Le cartelle virtuali generate possono essere salvate o esportate. Le cartelle esportate possono essere importate dalla sezione \"Manutenzione\" di questa istanza SFTPGo o di un'altra.",
"name": "Nome cartella virtuale",
"submit_generate": "Genera e salva cartelle",
"submit_export": "Genera e esporta cartelle"
}, },
"storage": { "storage": {
"title": "File system", "title": "File system",

View File

@@ -1,149 +1,168 @@
<!-- <!--
Copyright (C) 2019 Nicola Murino Copyright (C) 2024 Nicola Murino
This program is free software: you can redistribute it and/or modify This WebUI uses the KeenThemes Mega Bundle, a proprietary theme:
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, version 3.
This program is distributed in the hope that it will be useful, https://keenthemes.com/products/templates-mega-bundle
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License KeenThemes HTML/CSS/JS components are allowed for use only within the
along with this program. If not, see <https://www.gnu.org/licenses/>. SFTPGo product and restricted to be used in a resealable HTML template
that can compete with KeenThemes products anyhow.
This WebUI is allowed for use only within the SFTPGo product and
therefore cannot be used in derivative works/products without an
explicit grant from the SFTPGo Team (support@sftpgo.com).
--> -->
{{template "base" .}} {{template "base" .}}
{{define "title"}}{{.Title}}{{end}} {{- define "page_body"}}
<div class="card shadow-sm">
{{define "extra_css"}} <div class="card-header bg-light">
<link href="{{.StaticURL}}/vendor/bootstrap-select/css/bootstrap-select.min.css" rel="stylesheet"> <h3 data-i18n="{{.Title}}" class="card-title section-title"></h3>
{{end}}
{{define "page_body"}}
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">{{.Title}}</h6>
</div> </div>
<div class="card-body"> <div class="card-body">
{{if .Error}} {{- if eq .Mode 3}}
<div class="alert alert-warning alert-dismissible fade show" role="alert"> <div class="notice d-flex bg-light-primary rounded border-primary border border-dashed p-6 mb-5">
{{.Error}} <i class="ki-duotone ki-shield-tick fs-2tx text-primary me-4">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span class="path1"></span>
<span aria-hidden="true">&times;</span> <span class="path2"></span>
</button> </i>
</div> <div class="d-flex flex-stack flex-grow-1 flex-wrap flex-md-nowrap">
{{end}} <div class="mb-3 mb-md-0 fw-semibold">
{{if eq .Mode 3}} <h4 class="text-gray-900 fw-bold">
<div class="card mb-4 border-left-info"> <span data-i18n="virtual_folders.template_title">Create one or more new folders from this template</span>
<div class="card-body"> </h4>
Create and save one or more new folders or generate a data provider independent JSON file to import. <div class="fs-6 text-gray-800 pe-7">
<br> <p data-i18n="general.template_placeholders" class="mt-5">The following placeholders are supported</p>
The following placeholder is supported:
<br><br>
<ul> <ul>
<li><span class="text-success">%name%</span> will be replaced with the specified folder name</li> <li><span class="text-info">%name%</span>, <span data-i18n="virtual_folders.template_name_placeholder">replaced with the specified folder name</span></li>
</ul> </ul>
The generated folders can be saved or exported. Exported folders can be imported from the "Maintenance" section of this SFTPGo instance or another. <p data-i18n="virtual_folders.template_help">The generated folders can be saved or exported. Exported folders can be imported from the "Maintenance" section of this SFTPGo instance or another.</p>
</div> </div>
</div> </div>
{{end}} </div>
</div>
{{- end}}
{{- template "errmsg" .Error}}
<form id="folder_form" enctype="multipart/form-data" action="{{.CurrentURL}}" method="POST" autocomplete="off" {{if eq .Mode 3}}target="_blank"{{end}}> <form id="folder_form" enctype="multipart/form-data" action="{{.CurrentURL}}" method="POST" autocomplete="off" {{if eq .Mode 3}}target="_blank"{{end}}>
{{if eq .Mode 3}} {{- if eq .Mode 3}}
<div class="card bg-light mb-3"> <div class="card mt-10">
<div class="card-header"> <div class="card-header bg-light">
<b>Folders</b> <h3 data-i18n="title.folders" class="card-title section-title-inner">Folders</h3>
</div> </div>
<div class="card-body"> <div class="card-body">
<div id="template_folders">
<div class="form-group">
<div data-repeater-list="template_folders">
<div data-repeater-item>
<div class="form-group row"> <div class="form-group row">
<div class="col-md-12 form_field_tpl_folders_outer"> <div class="col-md-9 mt-3 mt-md-8">
<div class="row form_field_tpl_folder_outer_row"> <input data-i18n="[placeholder]virtual_folders.name" type="text" class="form-control" name="tpl_foldername" autocomplete="nope" spellcheck="false" value="" />
<div class="form-group col-md-10"> </div>
<input type="text" class="form-control" id="idTplFolder0" name="tpl_foldername" placeholder="Folder name" maxlength="255"> <div class="col-md-3 mt-3 mt-md-8">
<a href="#" data-repeater-delete
class="btn btn-light-danger">
<i class="ki-duotone ki-trash fs-5">
<span class="path1"></span>
<span class="path2"></span>
<span class="path3"></span>
<span class="path4"></span>
<span class="path5"></span>
</i>
<span data-i18n="general.delete">Delete</span>
</a>
</div> </div>
<div class="form-group col-md-2">
<button class="btn btn-circle btn-danger remove_tpl_folder_btn_frm_field">
<i class="fas fa-trash"></i>
</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="row mx-1"> <div class="form-group mt-5">
<button type="button" class="btn btn-secondary add_new_tpl_folder_field_btn"> <a href="#" data-repeater-create class="btn btn-light-primary">
<i class="fas fa-plus"></i> Add new folder name <i class="ki-duotone ki-plus fs-3"></i>
</button> <span data-i18n="general.add">Add</span>
</a>
</div>
</div> </div>
</div> </div>
</div> </div>
<input type="hidden" name="name" id="idFolderName" value="{{.Folder.Name}}"> <input type="hidden" name="name" id="idFolderName" value="{{.Folder.Name}}">
{{else}} {{- else}}
<div class="form-group row"> <div class="form-group row">
<label for="idFolderName" class="col-sm-2 col-form-label">Name</label> <label for="idFolderName" data-i18n="general.name" class="col-md-3 col-form-label">Name</label>
<div class="col-sm-10"> <div class="col-md-9">
<input type="text" class="form-control" id="idFolderName" name="name" placeholder="" <input id="idFolderName" type="text" class="form-control" placeholder="" name="name" value="{{.Folder.Name}}"
value="{{.Folder.Name}}" maxlength="255" autocomplete="nope" required {{if ge .Mode 2}}readonly{{end}}> maxlength="255" autocomplete="nope" spellcheck="false" required {{if ge .Mode 2}}readonly{{end}} />
</div> </div>
</div> </div>
{{end}} {{- end}}
<div class="form-group row">
<label for="idDescription" class="col-sm-2 col-form-label">Description</label> <div class="form-group row mt-10">
<div class="col-sm-10"> <label for="idDescription" data-i18n="general.description" class="col-md-3 col-form-label">Description</label>
<input type="text" class="form-control" id="idDescription" name="description" placeholder="" <div class="col-md-9">
value="{{.Folder.Description}}" maxlength="255" aria-describedby="descriptionHelpBlock"> <input id="idDescription" type="text" class="form-control" name="description" value="{{.Folder.Description}}" maxlength="255">
<small id="descriptionHelpBlock" class="form-text text-muted">
Optional description
</small>
</div> </div>
</div> </div>
{{template "fshtml" .FsWrapper}} {{- template "fshtml" .FsWrapper}}
<div class="d-flex justify-content-end mt-12">
<input type="hidden" name="_form_token" value="{{.CSRFToken}}"> <input type="hidden" name="_form_token" value="{{.CSRFToken}}">
<div class="col-sm-12 text-right px-0"> {{- if eq .Mode 3}}
{{if eq .Mode 3}} <button type="submit" id="form_generate_submit" class="btn btn-secondary px-10 me-10" name="form_action" value="export_from_template">
<button type="submit" class="btn btn-secondary mt-3 px-5" name="form_action" value="export_from_template">Generate and export folders</button> <span data-i18n="virtual_folders.submit_export" class="indicator-label">
{{end}} Generate and export folders
<button type="submit" class="btn btn-primary mt-3 ml-3 px-5" name="form_action" value="submit">{{if eq .Mode 3}}Generate and save new folders{{else}}Submit{{end}}</button> </span>
<span data-i18n="general.wait" class="indicator-progress">
Please wait...
<span class="spinner-border spinner-border-sm align-middle ms-2"></span>
</span>
</button>
{{- end}}
<button type="submit" id="form_submit" class="btn btn-primary px-10" name="form_action" value="submit">
<span {{if eq .Mode 3}}data-i18n="virtual_folders.submit_generate"{{else}}data-i18n="general.submit"{{end}} class="indicator-label">
Submit
</span>
<span data-i18n="general.wait" class="indicator-progress">
Please wait...
<span class="spinner-border spinner-border-sm align-middle ms-2"></span>
</span>
</button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
{{end}} {{- end}}
{{define "extra_js"}} {{- define "extra_js"}}
<script src="{{.StaticURL}}/vendor/bootstrap-select/js/bootstrap-select.min.js"></script> <script {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}} src="{{.StaticURL}}/assets/plugins/custom/formrepeater/formrepeater.bundle.js"></script>
<script type="text/javascript"> <script type="text/javascript" {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}}>
$(document).ready(function () { function onFilesystemChanged(val){
$('.form-group.fsconfig').hide();
$('.form-group.fsconfig-'+val).show();
}
$(document).on("i18nload", function(){
onFilesystemChanged('{{.Folder.FsConfig.Provider.Name}}'); onFilesystemChanged('{{.Folder.FsConfig.Provider.Name}}');
$("body").on("click", ".add_new_tpl_folder_field_btn", function () { $('#idFilesystem').on("change", function(){
let index = $(".form_field_tpl_folders_outer").find(".form_field_tpl_folder_outer_row").length; onFilesystemChanged(this.value);
while (document.getElementById("idTplFolder"+index) != null){ });
index++;
}
$(".form_field_tpl_folders_outer").append(`
<div class="row form_field_tpl_folder_outer_row">
<div class="form-group col-md-10">
<input type="text" class="form-control" id="idTplFolder${index}" name="tpl_foldername" placeholder="Folder name" maxlength="255">
</div>
<div class="form-group col-md-2">
<button class="btn btn-circle btn-danger remove_tpl_folder_btn_frm_field">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
`);
}); });
$("body").on("click", ".remove_tpl_folder_btn_frm_field", function () { $(document).on("i18nshow", function(){
$(this).closest(".form_field_tpl_folder_outer_row").remove(); //{{- if eq .Mode 3}}
}); initRepeater('#template_folders');
initRepeaterItems();
//{{- end}}
$("#folder_form").submit(function (event) {
//{{- if ne .Mode 3}}
let submitButton = document.querySelector('#form_submit');
submitButton.setAttribute('data-kt-indicator', 'on');
submitButton.disabled = true;
//{{- end}}
});
}); });
</script> </script>
{{- end}}
{{template "fsjs"}}
{{end}}

View File

@@ -290,6 +290,14 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
actions+=`<div class="menu-item px-3"> actions+=`<div class="menu-item px-3">
<a data-i18n="general.edit" href="#" class="menu-link px-3" data-share-table-action="edit_row">Edit</a> <a data-i18n="general.edit" href="#" class="menu-link px-3" data-share-table-action="edit_row">Edit</a>
</div>` </div>`
//{{- end}}
//{{- if .LoggedUser.HasPermission "manage_system"}}
numActions++;
actions+=`<div class="menu-item px-3">
<a data-i18n="general.template" href="#" class="menu-link px-3" data-share-table-action="template_row">Template</a>
</div>`
//{{- end}}
//{{- if .LoggedUser.HasPermission "manage_folders"}}
numActions++; numActions++;
actions+=`<div class="menu-item px-3"> actions+=`<div class="menu-item px-3">
<a data-i18n="general.delete" href="#" class="menu-link text-danger px-3" data-share-table-action="delete_row">Delete</a> <a data-i18n="general.delete" href="#" class="menu-link text-danger px-3" data-share-table-action="delete_row">Delete</a>
@@ -382,6 +390,17 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
}); });
}); });
const templateButtons = document.querySelectorAll('[data-share-table-action="template_row"]');
templateButtons.forEach(d => {
let el = $(d);
el.off("click");
el.on("click", function(e){
e.preventDefault();
let rowData = dt.row(e.target.closest('tr')).data();
window.location.replace('{{.FolderTemplateURL}}' + "?from=" + encodeURIComponent(rowData['name']));
});
});
const deleteButtons = document.querySelectorAll('[data-share-table-action="delete_row"]'); const deleteButtons = document.querySelectorAll('[data-share-table-action="delete_row"]');
deleteButtons.forEach(d => { deleteButtons.forEach(d => {
let el = $(d); let el = $(d);

View File

@@ -30,19 +30,16 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
<div class="d-flex flex-stack flex-grow-1 flex-wrap flex-md-nowrap"> <div class="d-flex flex-stack flex-grow-1 flex-wrap flex-md-nowrap">
<div class="mb-3 mb-md-0 fw-semibold"> <div class="mb-3 mb-md-0 fw-semibold">
<h4 class="text-gray-900 fw-bold"> <h4 class="text-gray-900 fw-bold">
<span data-i18n="">Create one or more new users from this template</span> <span data-i18n="user.template_title">Create one or more new users from this template</span>
</h4> </h4>
<div class="fs-6 text-gray-800 pe-7"> <div class="fs-6 text-gray-800 pe-7">
<p class="mt-5">The following placeholders are supported:</p> <p data-i18n="general.template_placeholders" class="mt-5">The following placeholders are supported</p>
<ul> <ul>
<li><span class="text-info">%username%</span> will be replaced with the specified username</li> <li><span class="text-info">%username%</span>, <span data-i18n="user.template_username_placeholder">replaced with the specified username</span></li>
<li><span class="text-info">%password%</span> will be replaced with the specified password</li> <li><span class="text-info">%password%</span>, <span data-i18n="user.template_password_placeholder">replaced with the specified password</span></li>
</ul> </ul>
<p>They will be replaced, with the specified username and password, in the paths and credentials of the configured storage backend.</p> <p data-i18n="user.template_help1">Placeholders will be replaced in paths and credentials of the configured storage backend.</p>
<p>The generated users can be saved or exported. Exported users can be imported from the "Maintenance" section of this SFTPGo instance or another.</p> <p data-i18n="user.template_help2">The generated users can be saved or exported. Exported users can be imported from the "Maintenance" section of this SFTPGo instance or another.</p>
{{if .User.Username}}
<p>Please note that no credentials were copied from user "{{.User.Username}}", you have to set them explicitly.</p>
{{end}}
</div> </div>
</div> </div>
</div> </div>
@@ -739,7 +736,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
<input type="hidden" name="expiration_date" id="hidden_start_datetime" value=""> <input type="hidden" name="expiration_date" id="hidden_start_datetime" value="">
<input type="hidden" name="_form_token" value="{{.CSRFToken}}"> <input type="hidden" name="_form_token" value="{{.CSRFToken}}">
{{- if eq .Mode 3}} {{- if eq .Mode 3}}
<button type="submit" id="form_generate_submit" class="btn btn-primary px-10 me-10" name="form_action" value="export_from_template"> <button type="submit" id="form_generate_submit" class="btn btn-secondary px-10 me-10" name="form_action" value="export_from_template">
<span data-i18n="user.submit_export" class="indicator-label"> <span data-i18n="user.submit_export" class="indicator-label">
Generate and export users Generate and export users
</span> </span>
@@ -841,13 +838,10 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
$('#hidden_start_datetime').val(dateString); $('#hidden_start_datetime').val(dateString);
} }
} }
//{{- if ne .Mode 3}}
let submitButton = document.querySelector('#form_submit'); let submitButton = document.querySelector('#form_submit');
submitButton.setAttribute('data-kt-indicator', 'on'); submitButton.setAttribute('data-kt-indicator', 'on');
submitButton.disabled = true; submitButton.disabled = true;
//{{- if eq .Mode 3}}
let generateButton = document.querySelector('#form_generate_submit');
generateButton.setAttribute('data-kt-indicator', 'on');
generateButton.disabled = true;
//{{- end}} //{{- end}}
}); });