mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-09 08:15:13 +03:00
add event manager
auto backup removed from setting. You can now schedule backups with the event manager Fixes #762 Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
@@ -74,6 +74,22 @@
|
||||
</li>
|
||||
{{end}}
|
||||
|
||||
{{ if .LoggedAdmin.HasPermission "manage_event_rules"}}
|
||||
<li class="nav-item {{if .IsEventManagerPage}}active{{end}}">
|
||||
<a class="nav-link {{if not .IsEventManagerPage}}collapsed{{end}}" href="#" data-toggle="collapse" data-target="#collapseEventManager"
|
||||
aria-expanded="true" aria-controls="collapseEventManager">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<span>Event Manager</span>
|
||||
</a>
|
||||
<div id="collapseEventManager" class="collapse {{if .IsEventManagerPage}}show{{end}}" aria-labelledby="headingEventManager" data-parent="#accordionSidebar">
|
||||
<div class="bg-white py-2 collapse-inner rounded">
|
||||
<a class="collapse-item {{if eq .CurrentURL .EventRulesURL}}active{{end}}" href="{{.EventRulesURL}}">{{.EventRulesTitle}}</a>
|
||||
<a class="collapse-item {{if eq .CurrentURL .EventActionsURL}}active{{end}}" href="{{.EventActionsURL}}">{{.EventActionsTitle}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{end}}
|
||||
|
||||
{{ if .LoggedAdmin.HasPermission "view_conns"}}
|
||||
<li class="nav-item {{if eq .CurrentURL .ConnectionsURL}}active{{end}}">
|
||||
<a class="nav-link" href="{{.ConnectionsURL}}">
|
||||
@@ -142,6 +158,7 @@
|
||||
|
||||
<!-- Topbar Navbar -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
{{block "additionalnavitems" .}}{{end}}
|
||||
|
||||
<!-- Nav Item - User Information -->
|
||||
<li class="nav-item dropdown no-arrow">
|
||||
|
||||
511
templates/webadmin/eventaction.html
Normal file
511
templates/webadmin/eventaction.html
Normal file
@@ -0,0 +1,511 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "title"}}{{.Title}}{{end}}
|
||||
|
||||
{{define "extra_css"}}
|
||||
<link href="{{.StaticURL}}/vendor/bootstrap-select/css/bootstrap-select.min.css" rel="stylesheet">
|
||||
{{end}}
|
||||
|
||||
{{define "additionalnavitems"}}
|
||||
<li class="nav-item dropdown no-arrow mx-1">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="editorDropdown" role="button"
|
||||
data-toggle="modal" data-target="#infoModal">
|
||||
<i class="fas fa-info fa-fw"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<div class="topbar-divider d-none d-sm-block"></div>
|
||||
{{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 class="card-body">
|
||||
{{if .Error}}
|
||||
<div class="card mb-4 border-left-warning">
|
||||
<div class="card-body text-form-error">{{.Error}}</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<form id="eventaction_form" action="{{.CurrentURL}}" method="POST" autocomplete="off">
|
||||
<div class="form-group row">
|
||||
<label for="idName" class="col-sm-2 col-form-label">Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="idName" name="name" placeholder=""
|
||||
value="{{.Action.Name}}" maxlength="255" autocomplete="nope" required {{if eq .Mode 2}}readonly{{end}}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idDescription" class="col-sm-2 col-form-label">Description</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="idDescription" name="description" placeholder=""
|
||||
value="{{.Action.Description}}" maxlength="255" aria-describedby="descriptionHelpBlock">
|
||||
<small id="descriptionHelpBlock" class="form-text text-muted">
|
||||
Optional description
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idType" class="col-sm-2 col-form-label">Type</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idType" name="type" onchange="onTypeChanged(this.value)">
|
||||
{{- range .ActionTypes}}
|
||||
<option value="{{.Value}}" {{if eq $.Action.Type .Value }}selected{{end}}>{{.Name}}</option>
|
||||
{{- end}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row action-type action-http">
|
||||
<label for="idHTTPEndpoint" class="col-sm-2 col-form-label">Endpoint</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="idHTTPEndpoint" name="http_endpoint" placeholder=""
|
||||
aria-describedby="HTTPEndpointHelpBlock" value="{{.Action.Options.HTTPConfig.Endpoint}}">
|
||||
<small id="HTTPEndpointHelpBlock" class="form-text text-muted">
|
||||
Endpoint URL, i.e https://host:port/path
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row action-type action-http">
|
||||
<label for="idHTTPUsername" class="col-sm-2 col-form-label">Username</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="text" class="form-control" id="idHTTPUsername" name="http_username" placeholder=""
|
||||
aria-describedby="usernameHelpBlock" value="{{.Action.Options.HTTPConfig.Username}}" maxlength="255">
|
||||
<small id="httpBodyHelpBlock" class="form-text text-muted">
|
||||
Placeholders are supported
|
||||
</small>
|
||||
</div>
|
||||
<div class="col-sm-2"></div>
|
||||
<label for="idHTTPPassword" class="col-sm-2 col-form-label">Password</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="password" class="form-control" id="idHTTPPassword" name="http_password" placeholder=""
|
||||
value="{{if .Action.Options.HTTPConfig.Password.IsEncrypted}}{{.RedactedSecret}}{{else}}{{.Action.Options.HTTPConfig.Password.GetPayload}}{{end}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-light mb-3 action-type action-http">
|
||||
<div class="card-header">
|
||||
<b>HTTP headers</b>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="card-title mb-4">Placeholders are supported in header values.</h6>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 form_field_http_headers_outer">
|
||||
{{range $idx, $val := .Action.Options.HTTPConfig.Headers}}
|
||||
<div class="row form_field_http_headers_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPHeaderKey{{$idx}}" name="http_header_key{{$idx}}" placeholder="Enter key" value="{{$val.Key}}">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPHeaderVal{{$idx}}" name="http_header_val{{$idx}}" placeholder="Enter value" value="{{$val.Value}}">
|
||||
</div>
|
||||
<div class="form-group col-md-1"></div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_http_header_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="row form_field_http_headers_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPHeaderKey0" name="http_header_key0" placeholder="Enter key" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPHeaderVal0" name="http_header_val0" placeholder="Enter value" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-1"></div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_http_header_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mx-1">
|
||||
<button type="button" class="btn btn-secondary add_new_header_field_btn">
|
||||
<i class="fas fa-plus"></i> Add new header
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-light mb-3 action-type action-http">
|
||||
<div class="card-header">
|
||||
<b>Query parameters</b>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="card-title mb-4">Placeholders are supported in query values.</h6>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 form_field_http_query_outer">
|
||||
{{range $idx, $val := .Action.Options.HTTPConfig.QueryParameters}}
|
||||
<div class="row form_field_http_query_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPQueryKey{{$idx}}" name="http_query_key{{$idx}}" placeholder="Enter key" value="{{$val.Key}}">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPQueryVal{{$idx}}" name="http_query_val{{$idx}}" placeholder="Enter value" value="{{$val.Value}}">
|
||||
</div>
|
||||
<div class="form-group col-md-1"></div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_http_query_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="row form_field_http_query_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPQueryKey0" name="http_query_key0" placeholder="Enter key" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPQueryVal0" name="http_query_val0" placeholder="Enter value" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-1"></div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_http_query_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mx-1">
|
||||
<button type="button" class="btn btn-secondary add_new_query_field_btn">
|
||||
<i class="fas fa-plus"></i> Add new parameter
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row action-type action-http">
|
||||
<label for="idHTTPMethod" class="col-sm-2 col-form-label">Method</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idHTTPMethod" name="http_method">
|
||||
{{- range .HTTPMethods}}
|
||||
<option value="{{.}}" {{if eq $.Action.Options.HTTPConfig.Method . }}selected{{end}}>{{.}}</option>
|
||||
{{- end}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row action-type action-http">
|
||||
<label for="idHTTPBody" class="col-sm-2 col-form-label">Body</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" id="idHTTPBody" name="http_body" rows="4" placeholder=""
|
||||
aria-describedby="httpBodyHelpBlock">{{.Action.Options.HTTPConfig.Body}}</textarea>
|
||||
<small id="httpBodyHelpBlock" class="form-text text-muted">
|
||||
Placeholders are supported
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row action-type action-http">
|
||||
<label for="idHTTPTimeout" class="col-sm-2 col-form-label">Timeout</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" min="1" max="120" class="form-control" id="idHTTPTimeout" name="http_timeout" placeholder=""
|
||||
value="{{.Action.Options.HTTPConfig.Timeout}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group action-type action-http">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="idHTTPSkipTLSVerify" name="http_skip_tls_verify"
|
||||
{{if .Action.Options.HTTPConfig.SkipTLSVerify}}checked{{end}}>
|
||||
<label for="idHTTPSkipTLSVerify" class="form-check-label">Skip TLS verify</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row action-type action-cmd">
|
||||
<label for="idCmdPath" class="col-sm-2 col-form-label">Command</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="idCmdPath" name="cmd_path" placeholder=""
|
||||
aria-describedby="CmdPathHelpBlock" value="{{.Action.Options.CmdConfig.Cmd}}">
|
||||
<small id="CmdPathHelpBlock" class="form-text text-muted">
|
||||
Absolute path of the command to execute
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row action-type action-cmd">
|
||||
<label for="idCmdTimeout" class="col-sm-2 col-form-label">Timeout</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" min="1" max="120" class="form-control" id="idCmdTimeout" name="cmd_timeout" placeholder=""
|
||||
value="{{.Action.Options.CmdConfig.Timeout}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-light mb-3 action-type action-cmd">
|
||||
<div class="card-header">
|
||||
<b>Environment variables</b>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="card-title mb-4">Placeholders are supported in values.</h6>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 form_field_cmd_env_outer">
|
||||
{{range $idx, $val := .Action.Options.CmdConfig.EnvVars}}
|
||||
<div class="row form_field_cmd_env_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idCMDEnvKey{{$idx}}" name="cmd_env_key{{$idx}}" placeholder="Enter key" value="{{$val.Key}}">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idCMDEnvVal{{$idx}}" name="cmd_env_val{{$idx}}" placeholder="Enter value" value="{{$val.Value}}">
|
||||
</div>
|
||||
<div class="form-group col-md-1"></div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_cmd_env_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="row form_field_cmd_env_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idCMDEnvKey0" name="cmd_env_key0" placeholder="Enter key" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idCMDEnvVal0" name="cmd_env_val0" placeholder="Enter value" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-1"></div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_cmd_env_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mx-1">
|
||||
<button type="button" class="btn btn-secondary add_new_cmd_env_field_btn">
|
||||
<i class="fas fa-plus"></i> Add environment variable
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row action-type action-smtp">
|
||||
<label for="idEmailRecipients" class="col-sm-2 col-form-label">Email recipients</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" id="idEmailRecipients" name="email_recipients" rows="2" placeholder=""
|
||||
aria-describedby="smtpRecipientsHelpBlock">{{.Action.Options.EmailConfig.GetRecipientsAsString}}</textarea>
|
||||
<small id="smtpRecipientsHelpBlock" class="form-text text-muted">
|
||||
Comma separated email recipients
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row action-type action-smtp">
|
||||
<label for="idEmailSubject" class="col-sm-2 col-form-label">Email subject</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="idEmailSubject" name="email_subject" placeholder=""
|
||||
value="{{.Action.Options.EmailConfig.Subject}}" maxlength="255" aria-describedby="emailSubjectHelpBlock">
|
||||
<small id="emailSubjectHelpBlock" class="form-text text-muted">
|
||||
Placeholders are supported
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row action-type action-smtp">
|
||||
<label for="idEmailBody" class="col-sm-2 col-form-label">Email body</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" id="idEmailBody" name="email_body" rows="4" placeholder=""
|
||||
aria-describedby="smtpBodyHelpBlock">{{.Action.Options.EmailConfig.Body}}</textarea>
|
||||
<small id="smtpBodyHelpBlock" class="form-text text-muted">
|
||||
Placeholders are supported
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<input type="hidden" name="_form_token" value="{{.CSRFToken}}">
|
||||
<div class="col-sm-12 text-right px-0">
|
||||
<button type="submit" class="btn btn-primary mt-3 ml-3 px-5" name="form_action" value="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "dialog"}}
|
||||
<div class="modal fade" id="infoModal" tabindex="-1" role="dialog" aria-labelledby="infoModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="infoModalLabel">
|
||||
Supported placeholders
|
||||
</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{Name}}`}}</b></span> => Username, folder name, or admin username for provider actions.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{Event}}`}}</b></span> => Event name, for example "upload", "download" for filesystem events or "add", "update" for provider events.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{Status}}`}}</b></span> => Status for "upload", "download" and "ssh_cmd" events. 1 means no error, 2 means a generic error occurred, 3 means quota exceeded error.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{VirtualPath}}`}}</b></span> => Path seen by SFTPGo users, for example "/adir/afile.txt".
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{FsPath}}`}}</b></span> => Full filesystem path, for example "/user/homedir/adir/afile.txt" or "C:/data/user/homedir/adir/afile.txt" on Windows.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{ObjectName}}`}}</b></span> => File/directory name, for example "afile.txt" or provider object name.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{ObjectType}}`}}</b></span> => Object type for provider events: "user", "group", "admin", etc.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{VirtualTargetPath}}`}}</b></span> => Virtual target path for renames.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{FsTargetPath}}`}}</b></span> => Full filesystem target path for renames.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{FileSize}}`}}</b></span> => File size.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{Protocol}}`}}</b></span> => Protocol, for example "SFTP", "FTP".
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{IP}}`}}</b></span> => Client IP address.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{Timestamp}}`}}</b></span> => Event timestamp as nanoseconds since epoch.
|
||||
</p>
|
||||
<p>
|
||||
<span class="shortcut"><b>{{`{{ObjectData}}`}}</b></span> => Provider object data serialized as JSON with sensitive fields removed.
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" type="button" data-dismiss="modal">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "extra_js"}}
|
||||
<script src="{{.StaticURL}}/vendor/bootstrap-select/js/bootstrap-select.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$("body").on("click", ".add_new_header_field_btn", function () {
|
||||
var index = $(".form_field_http_headers_outer").find(".form_field_http_headers_outer_row").length;
|
||||
while (document.getElementById("idHTTPHeaderKey"+index) != null){
|
||||
index++;
|
||||
}
|
||||
$(".form_field_http_headers_outer").append(`
|
||||
<div class="row form_field_http_headers_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPHeaderKey${index}" name="http_header_key${index}" placeholder="Enter key" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPHeaderVal${index}" name="http_header_val${index}" placeholder="Enter value" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-1"></div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_http_header_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
$("body").on("click", ".remove_http_header_btn_frm_field", function () {
|
||||
$(this).closest(".form_field_http_headers_outer_row").remove();
|
||||
});
|
||||
|
||||
$("body").on("click", ".add_new_query_field_btn", function () {
|
||||
var index = $(".form_field_http_query_outer").find(".form_field_http_query_outer_row").length;
|
||||
while (document.getElementById("idHTTPQueryKey"+index) != null){
|
||||
index++;
|
||||
}
|
||||
$(".form_field_http_query_outer").append(`
|
||||
<div class="row form_field_http_query_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPQueryKey${index}" name="http_query_key${index}" placeholder="Enter key" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idHTTPQueryVal${index}" name="http_query_val${index}" placeholder="Enter value" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-1"></div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_http_query_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
$("body").on("click", ".remove_http_query_btn_frm_field", function () {
|
||||
$(this).closest(".form_field_http_query_outer_row").remove();
|
||||
});
|
||||
|
||||
$("body").on("click", ".add_new_cmd_env_field_btn", function () {
|
||||
var index = $(".form_field_cmd_env_outer").find(".form_field_cmd_env_outer_row").length;
|
||||
while (document.getElementById("idCMDEnvKey"+index) != null){
|
||||
index++;
|
||||
}
|
||||
$(".form_field_cmd_env_outer").append(`
|
||||
<div class="row form_field_cmd_env_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idCMDEnvKey${index}" name="cmd_env_key${index}" placeholder="Enter key" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<input type="text" class="form-control" id="idCMDEnvVal${index}" name="cmd_env_val${index}" placeholder="Enter value" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-1"></div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_cmd_env_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
$("body").on("click", ".remove_cmd_env_btn_frm_field", function () {
|
||||
$(this).closest(".form_field_cmd_env_outer_row").remove();
|
||||
});
|
||||
|
||||
function onTypeChanged(val){
|
||||
$('.action-type').hide();
|
||||
switch (val) {
|
||||
case '1':
|
||||
case 1:
|
||||
$('.action-http').show();
|
||||
break;
|
||||
case '2':
|
||||
case 2:
|
||||
$('.action-cmd').show();
|
||||
break;
|
||||
case '3':
|
||||
case 3:
|
||||
$('.action-smtp').show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
onTypeChanged('{{.Action.Type}}');
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
||||
206
templates/webadmin/eventactions.html
Normal file
206
templates/webadmin/eventactions.html
Normal file
@@ -0,0 +1,206 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "title"}}{{.Title}}{{end}}
|
||||
|
||||
{{define "extra_css"}}
|
||||
<link href="{{.StaticURL}}/vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
|
||||
<link href="{{.StaticURL}}/vendor/datatables/buttons.bootstrap4.min.css" rel="stylesheet">
|
||||
<link href="{{.StaticURL}}/vendor/datatables/fixedHeader.bootstrap4.min.css" rel="stylesheet">
|
||||
<link href="{{.StaticURL}}/vendor/datatables/responsive.bootstrap4.min.css" rel="stylesheet">
|
||||
<link href="{{.StaticURL}}/vendor/datatables/select.bootstrap4.min.css" rel="stylesheet">
|
||||
{{end}}
|
||||
|
||||
{{define "page_body"}}
|
||||
<div id="errorMsg" class="card mb-4 border-left-warning" style="display: none;">
|
||||
<div id="errorTxt" class="card-body text-form-error"></div>
|
||||
</div>
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3">
|
||||
<h6 class="m-0 font-weight-bold text-primary">View and manage event actions</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover nowrap" id="dataTable" width="100%" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Type</th>
|
||||
<th>Rules</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Actions}}
|
||||
<tr>
|
||||
<td>{{.Name}}</td>
|
||||
<td>{{.Description}}</td>
|
||||
<td>{{.GetTypeAsString}}</td>
|
||||
<td>{{.GetRulesAsString}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "dialog"}}
|
||||
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="deleteModalLabel">
|
||||
Confirmation required
|
||||
</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">Do you want to delete the selected event action? A referenced action cannot be removed</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
<a class="btn btn-warning" href="#" onclick="deleteAction()">
|
||||
Delete
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "extra_js"}}
|
||||
<script src="{{.StaticURL}}/vendor/datatables/jquery.dataTables.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/dataTables.bootstrap4.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/dataTables.buttons.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/buttons.bootstrap4.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/buttons.colVis.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/dataTables.fixedHeader.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/dataTables.responsive.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/responsive.bootstrap4.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/dataTables.select.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/ellipsis.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
function deleteAction() {
|
||||
var table = $('#dataTable').DataTable();
|
||||
table.button('delete:name').enable(false);
|
||||
var name = table.row({ selected: true }).data()[0];
|
||||
var path = '{{.EventActionURL}}' + "/" + fixedEncodeURIComponent(name);
|
||||
$('#deleteModal').modal('hide');
|
||||
$.ajax({
|
||||
url: path,
|
||||
type: 'DELETE',
|
||||
dataType: 'json',
|
||||
headers: {'X-CSRF-TOKEN' : '{{.CSRFToken}}'},
|
||||
timeout: 15000,
|
||||
success: function (result) {
|
||||
window.location.href = '{{.EventActionsURL}}';
|
||||
},
|
||||
error: function ($xhr, textStatus, errorThrown) {
|
||||
var txt = "Unable to delete the selected action";
|
||||
if ($xhr) {
|
||||
var json = $xhr.responseJSON;
|
||||
if (json) {
|
||||
if (json.message){
|
||||
txt += ": " + json.message;
|
||||
} else {
|
||||
txt += ": " + json.error;
|
||||
}
|
||||
}
|
||||
}
|
||||
$('#errorTxt').text(txt);
|
||||
$('#errorMsg').show();
|
||||
setTimeout(function () {
|
||||
$('#errorMsg').hide();
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$.fn.dataTable.ext.buttons.add = {
|
||||
text: '<i class="fas fa-plus"></i>',
|
||||
name: 'add',
|
||||
titleAttr: "Add",
|
||||
action: function (e, dt, node, config) {
|
||||
window.location.href = '{{.EventActionURL}}';
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.dataTable.ext.buttons.edit = {
|
||||
text: '<i class="fas fa-pen"></i>',
|
||||
name: 'edit',
|
||||
titleAttr: "Edit",
|
||||
action: function (e, dt, node, config) {
|
||||
var name = table.row({ selected: true }).data()[0];
|
||||
var path = '{{.EventActionURL}}' + "/" + fixedEncodeURIComponent(name);
|
||||
window.location.href = path;
|
||||
},
|
||||
enabled: false
|
||||
};
|
||||
|
||||
$.fn.dataTable.ext.buttons.delete = {
|
||||
text: '<i class="fas fa-trash"></i>',
|
||||
name: 'delete',
|
||||
titleAttr: "Delete",
|
||||
action: function (e, dt, node, config) {
|
||||
$('#deleteModal').modal('show');
|
||||
},
|
||||
enabled: false
|
||||
};
|
||||
|
||||
var table = $('#dataTable').DataTable({
|
||||
"select": {
|
||||
"style": "single",
|
||||
"blurable": true
|
||||
},
|
||||
"stateSave": true,
|
||||
"stateDuration": 0,
|
||||
"buttons": [
|
||||
{
|
||||
"text": "Column visibility",
|
||||
"extend": "colvis",
|
||||
"columns": ":not(.noVis)"
|
||||
}
|
||||
],
|
||||
"columnDefs": [
|
||||
{
|
||||
"targets": [0],
|
||||
"className": "noVis"
|
||||
},
|
||||
{
|
||||
"targets": [3],
|
||||
"render": $.fn.dataTable.render.ellipsis(100, true)
|
||||
},
|
||||
],
|
||||
"scrollX": false,
|
||||
"scrollY": false,
|
||||
"responsive": true,
|
||||
"language": {
|
||||
"emptyTable": "No event actions defined"
|
||||
},
|
||||
"order": [[0, 'asc']]
|
||||
});
|
||||
|
||||
new $.fn.dataTable.FixedHeader( table );
|
||||
|
||||
table.button().add(0,'delete');
|
||||
table.button().add(0,'edit');
|
||||
table.button().add(0,'add');
|
||||
|
||||
table.buttons().container().appendTo('.col-md-6:eq(0)', table.table().container());
|
||||
|
||||
table.on('select deselect', function () {
|
||||
var selectedRows = table.rows({ selected: true }).count();
|
||||
table.button('delete:name').enable(selectedRows == 1);
|
||||
table.button('edit:name').enable(selectedRows == 1);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
{{end}}
|
||||
541
templates/webadmin/eventrule.html
Normal file
541
templates/webadmin/eventrule.html
Normal file
@@ -0,0 +1,541 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "title"}}{{.Title}}{{end}}
|
||||
|
||||
{{define "extra_css"}}
|
||||
<link href="{{.StaticURL}}/vendor/bootstrap-select/css/bootstrap-select.min.css" rel="stylesheet">
|
||||
{{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 class="card-body">
|
||||
{{if .Error}}
|
||||
<div class="card mb-4 border-left-warning">
|
||||
<div class="card-body text-form-error">{{.Error}}</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<form id="eventrule_form" action="{{.CurrentURL}}" method="POST" autocomplete="off">
|
||||
<div class="form-group row">
|
||||
<label for="idName" class="col-sm-2 col-form-label">Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="idName" name="name" placeholder=""
|
||||
value="{{.Rule.Name}}" maxlength="255" autocomplete="nope" required {{if eq .Mode 2}}readonly{{end}}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idDescription" class="col-sm-2 col-form-label">Description</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="idDescription" name="description" placeholder=""
|
||||
value="{{.Rule.Description}}" maxlength="255" aria-describedby="descriptionHelpBlock">
|
||||
<small id="descriptionHelpBlock" class="form-text text-muted">
|
||||
Optional description
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idTrigger" class="col-sm-2 col-form-label">Trigger</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idTrigger" name="trigger" onchange="onTriggerChanged(this.value)">
|
||||
{{- range .TriggerTypes}}
|
||||
<option value="{{.Value}}" {{if eq $.Rule.Trigger .Value }}selected{{end}}>{{.Name}}</option>
|
||||
{{- end}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row trigger trigger-fs">
|
||||
<label for="idFsEvents" class="col-sm-2 col-form-label">Fs events</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idFsEvents" name="fs_events" multiple>
|
||||
{{- range $event := .FsEvents}}
|
||||
<option value="{{$event}}" {{- range $.Rule.Conditions.FsEvents }}{{- if eq . $event}}selected{{- end}}{{- end}}>{{$event}}</option>
|
||||
{{- end}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row trigger trigger-provider">
|
||||
<label for="idProviderEvents" class="col-sm-2 col-form-label">Provider events</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idProviderEvents" name="provider_events" multiple>
|
||||
{{- range $event := .ProviderEvents}}
|
||||
<option value="{{$event}}" {{- range $.Rule.Conditions.ProviderEvents }}{{- if eq . $event}}selected{{- end}}{{- end}}>{{$event}}</option>
|
||||
{{- end}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-light mb-3 trigger trigger-schedule">
|
||||
<div class="card-header">
|
||||
<b>Schedules</b>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="card-title mb-4">Hours: 0-23. Day of week: 0-6 (Sun-Sat). Day of month: 1-31. Month: 1-12. Asterisk (*) indicates a match for all the values of the field. e.g. every day of week, every day of month and so on. More <a href="https://pkg.go.dev/github.com/robfig/cron/v3#hdr-CRON_Expression_Format" target="_blank">info</a>.</h6>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 form_field_schedules_outer">
|
||||
{{range $idx, $val := .Rule.Conditions.Schedules}}
|
||||
<div class="row form_field_schedules_outer_row">
|
||||
<div class="form-group col-md-3">
|
||||
<input type="text" class="form-control" id="idScheduleHour{{$idx}}" name="schedule_hour{{$idx}}" placeholder="Hours" value="{{$val.Hours}}">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<input type="text" class="form-control" id="idScheduleDayOfWeek{{$idx}}" name="schedule_day_of_week{{$idx}}" placeholder="Day of week" value="{{$val.DayOfWeek}}">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<input type="text" class="form-control" id="idScheduleDayOfMonth{{$idx}}" name="schedule_day_of_month{{$idx}}" placeholder="Day of month" value="{{$val.DayOfMonth}}">
|
||||
</div>
|
||||
<div class="form-group col-md-2">
|
||||
<input type="text" class="form-control" id="idScheduleMonth{{$idx}}" name="schedule_month{{$idx}}" placeholder="Month" value="{{$val.Month}}">
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_schedule_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="row form_field_schedules_outer_row">
|
||||
<div class="form-group col-md-3">
|
||||
<input type="text" class="form-control" id="idScheduleHour0" name="schedule_hour0" placeholder="Hours" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<input type="text" class="form-control" id="idScheduleDayOfWeek0" name="schedule_day_of_week0" placeholder="Day of week" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<input type="text" class="form-control" id="idScheduleDayOfMonth0" name="schedule_day_of_month0" placeholder="Day of month" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-2">
|
||||
<input type="text" class="form-control" id="idScheduleMonth0" name="schedule_month0" placeholder="Month" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_schedule_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mx-1">
|
||||
<button type="button" class="btn btn-secondary add_new_schedule_field_btn">
|
||||
<i class="fas fa-plus"></i> Add new schedule
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .IsShared}}
|
||||
<div class="form-group trigger trigger-schedule">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="idConcurrentExecution" name="concurrent_execution"
|
||||
{{if .Rule.Conditions.Options.ConcurrentExecution}}checked{{end}}>
|
||||
<label for="idConcurrentExecution" class="form-check-label">Allow concurrent execution from multiple instances</label>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="form-group row trigger trigger-fs">
|
||||
<label for="idFsProtocols" class="col-sm-2 col-form-label">Protocol filters</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idFsProtocols" name="fs_protocols" aria-describedby="fsProtocolsHelpBlock" multiple>
|
||||
{{- range $p := .Protocols}}
|
||||
<option value="{{$p}}" {{- range $.Rule.Conditions.Options.Protocols }}{{- if eq . $p}}selected{{- end}}{{- end}}>{{$p}}</option>
|
||||
{{- end}}
|
||||
</select>
|
||||
<small id="fsProtocolsHelpBlock" class="form-text text-muted">
|
||||
No selection means any protocol will trigger events
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row trigger trigger-provider">
|
||||
<label for="idProviderObjects" class="col-sm-2 col-form-label">Object filters</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idProviderObjects" name="provider_objects" aria-describedby="providerObjectsHelpBlock" multiple>
|
||||
{{- range $p := .ProviderObjects}}
|
||||
<option value="{{$p}}" {{- range $.Rule.Conditions.Options.ProviderObjects }}{{- if eq . $p}}selected{{- end}}{{- end}}>{{$p}}</option>
|
||||
{{- end}}
|
||||
</select>
|
||||
<small id="providerObjectsHelpBlock" class="form-text text-muted">
|
||||
No selection means any provider object will trigger events
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-light mb-3">
|
||||
<div class="card-header">
|
||||
<b>Name filters</b>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="card-title mb-4">Shell-like pattern filters for usernames, folder names. For example "user*"" will match names starting with "user"</h6>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 form_field_names_outer">
|
||||
{{range $idx, $val := .Rule.Conditions.Options.Names}}
|
||||
<div class="row form_field_names_outer_row">
|
||||
<div class="form-group col-md-8">
|
||||
<input type="text" class="form-control" id="idNamePattern{{$idx}}" name="name_pattern{{$idx}}" placeholder="" value="{{$val.Pattern}}" maxlength="255">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<select class="form-control selectpicker" id="idNamePatternType{{$idx}}" name="type_name_pattern{{$idx}}">
|
||||
<option value=""></option>
|
||||
<option value="inverse" {{if $val.InverseMatch}}selected{{end}}>Inverse match</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_name_pattern_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="row form_field_names_outer_row">
|
||||
<div class="form-group col-md-8">
|
||||
<input type="text" class="form-control" id="idNamePattern0" name="name_pattern0" placeholder="" value="" maxlength="255">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<select class="form-control selectpicker" id="idNamePatternType0" name="type_name_pattern0">
|
||||
<option value=""></option>
|
||||
<option value="inverse">Inverse match</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_name_pattern_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mx-1">
|
||||
<button type="button" class="btn btn-secondary add_new_name_pattern_field_btn">
|
||||
<i class="fas fa-plus"></i> Add new filter
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-light mb-3 trigger trigger-fs">
|
||||
<div class="card-header">
|
||||
<b>Path filters</b>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="card-title mb-4">Shell-like pattern filters for filesystem events. For example "/adir/*.txt"" will match paths in the "/adir" directory ending with ".txt"</h6>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 form_field_fs_paths_outer">
|
||||
{{range $idx, $val := .Rule.Conditions.Options.FsPaths}}
|
||||
<div class="row form_field_fs_paths_outer_row">
|
||||
<div class="form-group col-md-8">
|
||||
<input type="text" class="form-control" id="idFsPathPattern{{$idx}}" name="fs_path_pattern{{$idx}}" placeholder="" value="{{$val.Pattern}}" maxlength="255">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<select class="form-control selectpicker" id="idFsPathPatternType{{$idx}}" name="type_fs_path_pattern{{$idx}}">
|
||||
<option value=""></option>
|
||||
<option value="inverse" {{if $val.InverseMatch}}selected{{end}}>Inverse match</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_fs_path_pattern_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="row form_field_fs_paths_outer_row">
|
||||
<div class="form-group col-md-8">
|
||||
<input type="text" class="form-control" id="idFsPathPattern0" name="fs_path_pattern0" placeholder="" value="" maxlength="255">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<select class="form-control selectpicker" id="idFsPathPatternType0" name="type_fs_path_pattern0">
|
||||
<option value=""></option>
|
||||
<option value="inverse">Inverse match</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_fs_path_pattern_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mx-1">
|
||||
<button type="button" class="btn btn-secondary add_new_fs_path_pattern_field_btn">
|
||||
<i class="fas fa-plus"></i> Add new filter
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-light mb-3 trigger trigger-fs">
|
||||
<div class="card-header">
|
||||
<b>File size limits. 0 means no limit</b>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group row">
|
||||
<label for="idFsMinSize" class="col-sm-2 col-form-label">Min size</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="number" class="form-control" id="idFsMinSize" name="fs_min_size" placeholder=""
|
||||
value="{{.Rule.Conditions.Options.MinFileSize}}" min="0">
|
||||
</div>
|
||||
<div class="col-sm-2"></div>
|
||||
<label for="idFsMaxSize" class="col-sm-2 col-form-label">Max size</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="number" class="form-control" id="idFsMaxSize" name="fs_max_size" placeholder=""
|
||||
value="{{.Rule.Conditions.Options.MaxFileSize}}" min="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-light mb-3">
|
||||
<div class="card-header">
|
||||
<b>Actions</b>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="card-title mb-4">One or more actions to execute. The "Execute sync" options is only supported for upload events</h6>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 form_field_action_outer">
|
||||
{{range $idx, $val := .Rule.Actions}}
|
||||
<div class="row form_field_action_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<select class="form-control selectpicker" data-live-search="true" id="idActionName{{$idx}}" name="action_name{{$idx}}">
|
||||
<option value=""></option>
|
||||
{{range $.Actions}}
|
||||
<option value="{{.Name}}" {{if eq $val.Name .Name}}selected{{end}}>{{.Name}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<select class="form-control selectpicker" id="idActionOptions{{$idx}}" name="action_options{{$idx}}" multiple>
|
||||
<option value="2" {{if $val.Options.StopOnFailure}}selected{{end}}>Stop on failure</option>
|
||||
<option value="3" {{if $val.Options.ExecuteSync}}selected{{end}}>Execute sync</option>
|
||||
<option value="1" {{if $val.Options.IsFailureAction}}selected{{end}}>Is failure action</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-1">
|
||||
<input type="hidden" name="action_order{{$idx}}" value="{{$idx}}">
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_action_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="row form_field_action_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<select class="form-control selectpicker" data-live-search="true" id="idActionName0" name="action_name0">
|
||||
<option value=""></option>
|
||||
{{range $.Actions}}
|
||||
<option value="{{.Name}}">{{.Name}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<select class="form-control selectpicker" id="idActionOptions0" name="action_options0" multiple>
|
||||
<option value="1">Is failure action</option>
|
||||
<option value="2">Stop on failure</option>
|
||||
<option value="3">Execute sync</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-1">
|
||||
<input type="hidden" name="action_order0" value="0">
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_action_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mx-1">
|
||||
<button type="button" class="btn btn-secondary add_new_action_field_btn">
|
||||
<i class="fas fa-plus"></i> Add new action
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="_form_token" value="{{.CSRFToken}}">
|
||||
<div class="col-sm-12 text-right px-0">
|
||||
<button type="submit" class="btn btn-primary mt-3 ml-3 px-5" name="form_action" value="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "extra_js"}}
|
||||
<script src="{{.StaticURL}}/vendor/bootstrap-select/js/bootstrap-select.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$("body").on("click", ".add_new_schedule_field_btn", function () {
|
||||
var index = $(".form_field_schedules_outer").find(".form_field_schedules_outer_row").length;
|
||||
while (document.getElementById("idScheduleHour"+index) != null){
|
||||
index++;
|
||||
}
|
||||
$(".form_field_schedules_outer").append(`
|
||||
<div class="row form_field_schedules_outer_row">
|
||||
<div class="form-group col-md-3">
|
||||
<input type="text" class="form-control" id="idScheduleHour${index}" name="schedule_hour${index}" placeholder="Hours" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<input type="text" class="form-control" id="idScheduleDayOfWeek${index}" name="schedule_day_of_week${index}" placeholder="Day of week" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<input type="text" class="form-control" id="idScheduleDayOfMonth${index}" name="schedule_day_of_month${index}" placeholder="Day of month" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-2">
|
||||
<input type="text" class="form-control" id="idScheduleMonth${index}" name="schedule_month${index}" placeholder="Month" value="">
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_schedule_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
$("body").on("click", ".remove_schedule_btn_frm_field", function () {
|
||||
$(this).closest(".form_field_schedules_outer_row").remove();
|
||||
});
|
||||
|
||||
$("body").on("click", ".add_new_name_pattern_field_btn", function () {
|
||||
var index = $(".form_field_names_outer").find(".form_field_names_outer_row").length;
|
||||
while (document.getElementById("idNamePattern"+index) != null){
|
||||
index++;
|
||||
}
|
||||
$(".form_field_names_outer").append(`
|
||||
<div class="row form_field_names_outer_row">
|
||||
<div class="form-group col-md-8">
|
||||
<input type="text" class="form-control" id="idNamePattern${index}" name="name_pattern${index}" placeholder="" value="" maxlength="255">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<select class="form-control" id="idNamePatternType${index}" name="type_name_pattern${index}">
|
||||
<option value=""></option>
|
||||
<option value="inverse">Inverse match</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_name_pattern_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
$("#idNamePatternType"+index).selectpicker();
|
||||
});
|
||||
|
||||
$("body").on("click", ".remove_name_pattern_btn_frm_field", function () {
|
||||
$(this).closest(".form_field_names_outer_row").remove();
|
||||
});
|
||||
|
||||
$("body").on("click", ".add_new_fs_path_pattern_field_btn", function () {
|
||||
var index = $(".form_field_fs_paths_outer").find("form_field_fs_paths_outer_row").length;
|
||||
while (document.getElementById("idFsPathPattern"+index) != null){
|
||||
index++;
|
||||
}
|
||||
$(".form_field_fs_paths_outer").append(`
|
||||
<div class="row form_field_fs_paths_outer_row">
|
||||
<div class="form-group col-md-8">
|
||||
<input type="text" class="form-control" id="idFsPathPattern${index}" name="fs_path_pattern${index}" placeholder="" value="" maxlength="255">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<select class="form-control" id="idFsPathPatternType${index}" name="type_fs_path_pattern${index}">
|
||||
<option value=""></option>
|
||||
<option value="inverse">Inverse match</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_fs_path_pattern_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
$("#idFsPathPatternType"+index).selectpicker();
|
||||
});
|
||||
|
||||
$("body").on("click", ".remove_fs_path_pattern_btn_frm_field", function () {
|
||||
$(this).closest(".form_field_fs_paths_outer_row").remove();
|
||||
});
|
||||
|
||||
$("body").on("click", ".add_new_action_field_btn", function () {
|
||||
var index = $(".form_field_action_outer").find("form_field_action_outer_row").length;
|
||||
while (document.getElementById("idActionName"+index) != null){
|
||||
index++;
|
||||
}
|
||||
$(".form_field_action_outer").append(`
|
||||
<div class="row form_field_action_outer_row">
|
||||
<div class="form-group col-md-5">
|
||||
<select class="form-control" id="idActionName${index}" name="action_name${index}">
|
||||
<option value=""></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<select class="form-control" id="idActionOptions${index}" name="action_options${index}" multiple>
|
||||
<option value="1">Is failure action</option>
|
||||
<option value="2">Stop on failure</option>
|
||||
<option value="3">Execute sync</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-1">
|
||||
<input type="hidden" name="action_order${index}" value="${index}">
|
||||
</div>
|
||||
<div class="form-group col-md-1">
|
||||
<button class="btn btn-circle btn-danger remove_action_btn_frm_field">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
{{- range .Actions}}
|
||||
$("#idActionName"+index).append($('<option>').val('{{.Name}}').text('{{.Name}}'));
|
||||
{{- end}}
|
||||
console.log("index "+index);
|
||||
$("#idActionName"+index).selectpicker({'liveSearch': true});
|
||||
$("#idActionOptions"+index).selectpicker();
|
||||
});
|
||||
|
||||
$("body").on("click", ".remove_action_btn_frm_field", function () {
|
||||
$(this).closest(".form_field_action_outer_row").remove();
|
||||
});
|
||||
|
||||
function onTriggerChanged(val){
|
||||
$('.trigger').hide();
|
||||
switch (val) {
|
||||
case '1':
|
||||
case 1:
|
||||
$('.trigger-fs').show();
|
||||
break;
|
||||
case '2':
|
||||
case 2:
|
||||
$('.trigger-provider').show();
|
||||
break;
|
||||
case '3':
|
||||
case 3:
|
||||
$('.trigger-schedule').show();
|
||||
break;
|
||||
default:
|
||||
console.log(`unsupported event trigger type: ${val}`);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
onTriggerChanged('{{.Rule.Trigger}}');
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
||||
206
templates/webadmin/eventrules.html
Normal file
206
templates/webadmin/eventrules.html
Normal file
@@ -0,0 +1,206 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "title"}}{{.Title}}{{end}}
|
||||
|
||||
{{define "extra_css"}}
|
||||
<link href="{{.StaticURL}}/vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
|
||||
<link href="{{.StaticURL}}/vendor/datatables/buttons.bootstrap4.min.css" rel="stylesheet">
|
||||
<link href="{{.StaticURL}}/vendor/datatables/fixedHeader.bootstrap4.min.css" rel="stylesheet">
|
||||
<link href="{{.StaticURL}}/vendor/datatables/responsive.bootstrap4.min.css" rel="stylesheet">
|
||||
<link href="{{.StaticURL}}/vendor/datatables/select.bootstrap4.min.css" rel="stylesheet">
|
||||
{{end}}
|
||||
|
||||
{{define "page_body"}}
|
||||
<div id="errorMsg" class="card mb-4 border-left-warning" style="display: none;">
|
||||
<div id="errorTxt" class="card-body text-form-error"></div>
|
||||
</div>
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3">
|
||||
<h6 class="m-0 font-weight-bold text-primary">View and manage event rules</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover nowrap" id="dataTable" width="100%" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Trigger</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Rules}}
|
||||
<tr>
|
||||
<td>{{.Name}}</td>
|
||||
<td>{{.Description}}</td>
|
||||
<td>{{.GetTriggerAsString}}</td>
|
||||
<td>{{.GetActionsAsString}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "dialog"}}
|
||||
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="deleteModalLabel">
|
||||
Confirmation required
|
||||
</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">Do you want to delete the selected rule?</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
<a class="btn btn-warning" href="#" onclick="deleteAction()">
|
||||
Delete
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "extra_js"}}
|
||||
<script src="{{.StaticURL}}/vendor/datatables/jquery.dataTables.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/dataTables.bootstrap4.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/dataTables.buttons.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/buttons.bootstrap4.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/buttons.colVis.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/dataTables.fixedHeader.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/dataTables.responsive.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/responsive.bootstrap4.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/dataTables.select.min.js"></script>
|
||||
<script src="{{.StaticURL}}/vendor/datatables/ellipsis.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
function deleteAction() {
|
||||
var table = $('#dataTable').DataTable();
|
||||
table.button('delete:name').enable(false);
|
||||
var name = table.row({ selected: true }).data()[0];
|
||||
var path = '{{.EventRuleURL}}' + "/" + fixedEncodeURIComponent(name);
|
||||
$('#deleteModal').modal('hide');
|
||||
$.ajax({
|
||||
url: path,
|
||||
type: 'DELETE',
|
||||
dataType: 'json',
|
||||
headers: {'X-CSRF-TOKEN' : '{{.CSRFToken}}'},
|
||||
timeout: 15000,
|
||||
success: function (result) {
|
||||
window.location.href = '{{.EventRulesURL}}';
|
||||
},
|
||||
error: function ($xhr, textStatus, errorThrown) {
|
||||
var txt = "Unable to delete the selected rule";
|
||||
if ($xhr) {
|
||||
var json = $xhr.responseJSON;
|
||||
if (json) {
|
||||
if (json.message){
|
||||
txt += ": " + json.message;
|
||||
} else {
|
||||
txt += ": " + json.error;
|
||||
}
|
||||
}
|
||||
}
|
||||
$('#errorTxt').text(txt);
|
||||
$('#errorMsg').show();
|
||||
setTimeout(function () {
|
||||
$('#errorMsg').hide();
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$.fn.dataTable.ext.buttons.add = {
|
||||
text: '<i class="fas fa-plus"></i>',
|
||||
name: 'add',
|
||||
titleAttr: "Add",
|
||||
action: function (e, dt, node, config) {
|
||||
window.location.href = '{{.EventRuleURL}}';
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.dataTable.ext.buttons.edit = {
|
||||
text: '<i class="fas fa-pen"></i>',
|
||||
name: 'edit',
|
||||
titleAttr: "Edit",
|
||||
action: function (e, dt, node, config) {
|
||||
var name = table.row({ selected: true }).data()[0];
|
||||
var path = '{{.EventRuleURL}}' + "/" + fixedEncodeURIComponent(name);
|
||||
window.location.href = path;
|
||||
},
|
||||
enabled: false
|
||||
};
|
||||
|
||||
$.fn.dataTable.ext.buttons.delete = {
|
||||
text: '<i class="fas fa-trash"></i>',
|
||||
name: 'delete',
|
||||
titleAttr: "Delete",
|
||||
action: function (e, dt, node, config) {
|
||||
$('#deleteModal').modal('show');
|
||||
},
|
||||
enabled: false
|
||||
};
|
||||
|
||||
var table = $('#dataTable').DataTable({
|
||||
"select": {
|
||||
"style": "single",
|
||||
"blurable": true
|
||||
},
|
||||
"stateSave": true,
|
||||
"stateDuration": 0,
|
||||
"buttons": [
|
||||
{
|
||||
"text": "Column visibility",
|
||||
"extend": "colvis",
|
||||
"columns": ":not(.noVis)"
|
||||
}
|
||||
],
|
||||
"columnDefs": [
|
||||
{
|
||||
"targets": [0],
|
||||
"className": "noVis"
|
||||
},
|
||||
{
|
||||
"targets": [3],
|
||||
"render": $.fn.dataTable.render.ellipsis(100, true)
|
||||
},
|
||||
],
|
||||
"scrollX": false,
|
||||
"scrollY": false,
|
||||
"responsive": true,
|
||||
"language": {
|
||||
"emptyTable": "No event rules defined"
|
||||
},
|
||||
"order": [[0, 'asc']]
|
||||
});
|
||||
|
||||
new $.fn.dataTable.FixedHeader( table );
|
||||
|
||||
table.button().add(0,'delete');
|
||||
table.button().add(0,'edit');
|
||||
table.button().add(0,'add');
|
||||
|
||||
table.buttons().container().appendTo('.col-md-6:eq(0)', table.table().container());
|
||||
|
||||
table.on('select deselect', function () {
|
||||
var selectedRows = table.rows({ selected: true }).count();
|
||||
table.button('delete:name').enable(selectedRows == 1);
|
||||
table.button('edit:name').enable(selectedRows == 1);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
{{end}}
|
||||
@@ -15,10 +15,6 @@
|
||||
<div id="errorTxt" class="card-body text-form-error"></div>
|
||||
</div>
|
||||
|
||||
<div id="successMsg" class="card mb-4 border-left-success" style="display: none;">
|
||||
<div id="successTxt" class="card-body"></div>
|
||||
</div>
|
||||
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3">
|
||||
<h6 class="m-0 font-weight-bold text-primary">View and manage groups</h6>
|
||||
@@ -88,7 +84,7 @@
|
||||
<script src="{{.StaticURL}}/vendor/datatables/ellipsis.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
function deleteAction() {
|
||||
function deleteAction() {
|
||||
var table = $('#dataTable').DataTable();
|
||||
table.button('delete:name').enable(false);
|
||||
var groupName = table.row({ selected: true }).data()[0];
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
$("#idSubDirPermissions"+index).selectpicker();
|
||||
});
|
||||
|
||||
$("body").on("click", ".remove_dirperms_btn_frm_field", function () {
|
||||
$(this).closest(".form_field_dirperms_outer_row").remove();
|
||||
});
|
||||
$("body").on("click", ".remove_dirperms_btn_frm_field", function () {
|
||||
$(this).closest(".form_field_dirperms_outer_row").remove();
|
||||
});
|
||||
|
||||
$("body").on("click", ".add_new_vfolder_field_btn", function () {
|
||||
var index = $(".form_field_vfolders_outer").find(".form_field_vfolder_outer_row").length;
|
||||
|
||||
Reference in New Issue
Block a user