sftpgo/templates/webadmin/events.html
Nicola Murino 456517af87
notifier plugin: add support for login succeeded events
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2024-04-10 18:39:08 +02:00

1023 lines
41 KiB
HTML

<!--
Copyright (C) 2024 Nicola Murino
This WebUI uses the KeenThemes Mega Bundle, a proprietary theme:
https://keenthemes.com/products/templates-mega-bundle
KeenThemes HTML/CSS/JS components are allowed for use only within the
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" .}}
{{- define "extra_css"}}
<link href="{{.StaticURL}}/assets/plugins/custom/datatables/datatables.bundle.css" rel="stylesheet" type="text/css"/>
{{- end}}
{{- define "page_body"}}
{{- template "errmsg" ""}}
<div class="card shadow-sm">
<div class="card-header bg-light">
<h3 data-i18n="events.search" class="card-title section-title">Search logs</h3>
</div>
<div id="card_body" class="card-body">
<div class="form-group row">
<div class="col-md-3 mt-5">
<select class="form-select" id="idEventType" name="events_type" data-control="i18n-select2" data-hide-search="true">
<option value="1" data-i18n="events.fs_events">Fs events</option>
<option value="2" data-i18n="events.provider_events">Provider events</option>
<option value="3" data-i18n="events.other_events">Other events</option>
</select>
</div>
<div class="col-md-4 mt-5">
<select class="form-select" id="idActions" name="actions" data-control="i18n-select2" data-hide-search="true"
data-close-on-select="false" data-i18n="[data-placeholder]general.actions" multiple>
</select>
</div>
<div class="col-md-3 mt-5">
<input type="text" class="form-control" id="idUsername" name="username" data-i18n="[placeholder]login.username" spellcheck="false">
</div>
<div class="col-md-2 mt-5">
<input type="text" class="form-control" id="idIp" name="ip" data-i18n="[placeholder]defender.ip">
</div>
</div>
<div class="form-group row">
<div class="col-md-3 mt-5">
<select class="form-select fs-events" id="idStatuses" name="statuses" data-control="i18n-select2" data-hide-search="true"
data-close-on-select="false" data-i18n="[data-placeholder]general.status" multiple>
<option value="1" data-i18n="general.ok">OK</option>
<option value="2" data-i18n="general.failed">KO</option>
<option value="3" data-i18n="events.quota_exceeded">Quota exceeded</option>
</select>
</div>
<div class="col-md-4 mt-5">
<select class="form-select fs-events log-events" id="idProtocols" name="protocols" data-control="i18n-select2" data-hide-search="true"
data-close-on-select="false" data-i18n="[data-placeholder]ip_list.protocols" multiple>
<option value="SFTP">SFTP</option>
<option value="SCP">SCP</option>
<option value="SSH">SSH</option>
<option value="FTP">FTP</option>
<option value="DAV">DAV</option>
<option value="HTTP">HTTP</option>
<option value="OIDC">OIDC</option>
<option value="HTTPShare">HTTPShare</option>
<option value="DataRetention">DataRetention</option>
<option value="EventAction">EventAction</option>
</select>
</div>
<div class="col-md-5 mt-5">
<input id="dateTimeRange" class="form-control" data-i18n="[placeholder]events.date_range" />
</div>
</div>
<div class="d-flex justify-content-end mt-10 mb-10">
<button id="export_button" class="btn btn-secondary px-10 me-10">
<span data-i18n="general.export" class="indicator-label">
Export
</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>
<button id="search_button" class="btn btn-primary px-10">
<span data-i18n="general.search" class="indicator-label">
Search
</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>
<table id="dataTableFs" class="table align-middle table-row-dashed fs-6 gy-5 fs-events">
<thead>
<tr class="text-start text-muted fw-bold fs-6 gs-0">
<th data-i18n="events.datetime">Date and time</th>
<th data-i18n="events.action">Action</th>
<th data-i18n="events.path">Path</th>
<th data-i18n="login.username">Username</th>
<th data-i18n="general.protocol">Protocol</th>
<th data-i18n="defender.ip">IP</th>
<th data-i18n="general.info">Info</th>
</tr>
</thead>
<tbody id="table_body" class="text-gray-800 fw-semibold"></tbody>
</table>
<table id="dataTableProvider" class="table align-middle table-row-dashed fs-6 gy-5 provider-events">
<thead>
<tr class="text-start text-muted fw-bold fs-6 gs-0">
<th data-i18n="events.datetime">Date and time</th>
<th data-i18n="events.action">Action</th>
<th data-i18n="events.object">Object</th>
<th data-i18n="login.username">Username</th>
<th data-i18n="defender.ip">IP</th>
</tr>
</thead>
<tbody id="table_body" class="text-gray-800 fw-semibold"></tbody>
</table>
<table id="dataTableLog" class="table align-middle table-row-dashed fs-6 gy-5 log-events">
<thead>
<tr class="text-start text-muted fw-bold fs-6 gs-0">
<th data-i18n="events.datetime">Date and time</th>
<th data-i18n="events.event">Event</th>
<th data-i18n="login.username">Username</th>
<th data-i18n="general.protocol">Protocol</th>
<th data-i18n="defender.ip">IP</th>
<th data-i18n="general.info">Info</th>
</tr>
</thead>
<tbody id="table_body" class="text-gray-800 fw-semibold"></tbody>
</table>
<div id="paginationContainer" class="d-flex mt-4 mb-4 justify-content-end d-none">
<div class="btn-group" role="group" aria-label="Pagination">
<button id="pagePrevious" data-i18n="general.previous" type="button" class="btn btn-outline btn-active-primary disabled">Previous</button>
<button id="pageNext" data-i18n="general.next" type="button" class="btn btn-outline btn-active-primary disabled">Next</button>
</div>
</div>
</div>
</div>
{{- end}}
{{- define "extra_js"}}
<script {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}} src="{{.StaticURL}}/assets/plugins/custom/datatables/datatables.bundle.js"></script>
<script {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}} src="{{.StaticURL}}/assets/plugins/custom/flatpickr/l10n/it.js"></script>
<script {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}} src="{{.StaticURL}}/vendor/humanize-duration/humanize-duration.min.js"></script>
<script type="text/javascript" {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}}>
const pageSize = 20;
const paginationData = new Map();
function resetPagination() {
$('#pagePrevious').addClass("disabled");
$('#pageNext').addClass("disabled");
$('#paginationContainer').addClass("d-none");
paginationData.delete("firstId");
paginationData.delete("firstTs");
paginationData.delete("lastId");
paginationData.delete("lastTs");
paginationData.set("prevClicked",false);
paginationData.set("nextClicked",false);
}
function prevClicked(){
paginationData.set("prevClicked",true);
paginationData.set("nextClicked",false);
doSearch();
}
function nextClicked(){
paginationData.set("prevClicked",false);
paginationData.set("nextClicked",true);
doSearch();
}
function handleResponseData(data) {
let length = data.length;
let isNext = paginationData.get("nextClicked");
let isPrev = paginationData.get("prevClicked");
if (length > pageSize) {
data.pop();
length--;
if (isPrev || isNext){
$('#pagePrevious').removeClass("disabled");
}
$('#pageNext').removeClass("disabled");
} else {
if (isPrev){
$('#pagePrevious').addClass("disabled");
$('#pageNext').removeClass("disabled");
} else if (isNext){
$('#pagePrevious').removeClass("disabled");
$('#pageNext').addClass("disabled");
} else {
$('#pageNext').addClass("disabled");
}
}
if (isPrev){
data = data.reverse();
}
if (length > 0){
paginationData.set("lastId",data[0].id);
paginationData.set("lastTs",data[0].timestamp);
paginationData.set("firstId",data[length-1].id);
paginationData.set("firstTs",data[length-1].timestamp);
$('#paginationContainer').removeClass("d-none");
} else {
resetPagination();
}
return data;
}
function humanizeMilliseconds(val) {
let units = ["d", "h", "m", "s", "ms"];
let decimalPoints = 1;
if (val > 1000){
units = ["d", "h", "m", "s"]
}
if (val > 60000){
decimalPoints = 0;
}
return humanizeDuration(val, {
language: i18next.resolvedLanguage,
fallbacks: ["en"],
maxDecimalPoints: decimalPoints,
units: units
})
}
function getSearchURL(csvExport) {
let url = "";
let eventType = $('#idEventType').val();
let order = "DESC";
let limit = pageSize + 1;
if (csvExport){
order = "ASC";
}
if (eventType == 1){
url = "{{.FsEventsSearchURL}}?limit="+limit;
let protocols = [];
$('#idProtocols').find('option:selected').each(function(){
protocols.push($(this).val());
});
if (protocols.length > 0){
url+="&protocols="+encodeURIComponent(String(protocols));
}
let statuses = [];
$('#idStatuses').find('option:selected').each(function(){
statuses.push($(this).val());
});
if (statuses.length > 0){
url+="&statuses="+encodeURIComponent(String(statuses));
}
} else if (eventType == 2) {
url = "{{.ProviderEventsSearchURL}}?omit_object_data=true&limit="+limit;
} else {
url = "{{.LogEventsSearchURL}}?limit="+limit;
let protocols = [];
$('#idProtocols').find('option:selected').each(function(){
protocols.push($(this).val());
});
if (protocols.length > 0){
url+="&protocols="+encodeURIComponent(String(protocols));
}
}
let actions = [];
$('#idActions').find('option:selected').each(function(){
actions.push($(this).val());
});
if (actions.length > 0){
if (eventType == 3){
url+="&events="+encodeURIComponent(String(actions));
} else {
url+="&actions="+encodeURIComponent(String(actions));
}
}
let username = $('#idUsername').val();
if (username){
url+="&username="+encodeURIComponent(username);
}
let ip = $('#idIp').val();
if (ip){
url+="&ip="+encodeURIComponent(ip);
}
const dateRangePicker = document.querySelector("#dateTimeRange")._flatpickr;
let drp = dateRangePicker.selectedDates;
let fromID = "";
let start_ts = 0;
if (!csvExport && paginationData.get("prevClicked") && paginationData.has("lastId") && paginationData.has("lastTs")){
order = "ASC";
start_ts = paginationData.get("lastTs");
fromID = paginationData.get("lastId");
} else {
if (drp.length > 0){
let d = drp[0];
if (d) {
start_ts = d.getTime()*1000000;
}
}
}
let end_ts = 0;
if (!csvExport && paginationData.get("nextClicked") && paginationData.has("firstId") && paginationData.has("firstTs")){
end_ts = paginationData.get("firstTs");
fromID = paginationData.get("firstId");
} else {
if (drp.length > 1){
let d = drp[1];
if (d) {
end_ts = d.getTime()*1000000;
}
}
}
url+="&start_timestamp="+encodeURIComponent(start_ts);
url+="&end_timestamp="+encodeURIComponent(end_ts);
if (fromID){
url+="&from_id="+encodeURIComponent(fromID);
}
url+="&order="+order;
if (csvExport){
url+="&csv_export=true";
}
return url;
}
function onExportClicked() {
paginationData.set("prevClicked",false);
paginationData.set("nextClicked",false);
let exportURL = getSearchURL(true);
let ts = new Date().getTime().toString();
window.open(`${exportURL}&_=${ts}`);
}
function onSearchClicked() {
resetPagination();
doSearch();
}
function doSearch() {
let eventType = $('#idEventType').val();
switch (eventType){
case "1":
datatableFsEvents.init();
return;
case "2":
datatableProviderEvents.init();
return;
case "3":
datatableLogEvents.init();
return;
default:
console.log(`unsupported event type "${eventType}"`);
}
}
function selectFsEvents(){
let idActions = $('#idActions');
idActions.empty();
idActions.append(new Option($.t('events.upload'),"upload",false,false));
idActions.append(new Option($.t('events.download'),"download",false,false));
idActions.append(new Option($.t('events.mkdir'),"mkdir",false,false));
idActions.append(new Option($.t('events.rmdir'),"rmdir",false,false));
idActions.append(new Option($.t('events.rename'),"rename",false,false));
idActions.append(new Option($.t('events.delete'),"delete",false,false));
idActions.append(new Option($.t('events.first_upload'),"first-upload",false,false));
idActions.append(new Option($.t('events.first_download'),"first-download",false,false));
idActions.append(new Option($.t('events.ssh_cmd'),"ssh_cmd",false,false));
idActions.trigger('change');
$('#idUsername').val("");
$('#idIp').val("");
$('.provider-events').hide();
$('.log-events').hide();
$('.fs-events').show();
onSearchClicked();
}
function selectLogEvents(){
let idActions = $('#idActions');
idActions.empty();
idActions.append(new Option($.t('events.login_ok'),"5",false,false));
idActions.append(new Option($.t('events.login_failed'),"1",false,false));
idActions.append(new Option($.t('events.login_missing_user'),"2",false,false));
idActions.append(new Option($.t('events.no_login_tried'),"3",false,false));
idActions.append(new Option($.t('events.algo_negotiation_failed'),"4",false,false));
idActions.trigger('change');
$('#idUsername').val("");
$('#idIp').val("");
$('.provider-events').hide();
$('.fs-events').hide();
$('.log-events').show();
onSearchClicked();
}
function selectProviderEvents(){
let idActions = $('#idActions');
idActions.empty();
idActions.append(new Option($.t('events.add'),"add",false,false));
idActions.append(new Option($.t('events.update'),"update",false,false));
idActions.append(new Option($.t('events.delete'),"delete",false,false));
idActions.trigger('change');
$('#idUsername').val("");
$('#idIp').val("");
$('.fs-events').hide();
$('.log-events').hide();
$('.provider-events').show();
onSearchClicked();
}
function onEventChanged(val){
switch (val){
case '1':
selectFsEvents();
break;
case '2':
selectProviderEvents();
break;
case '3':
selectLogEvents();
break;
default:
console.log(`unsupported event type: ${val}`);
}
}
var datatableFsEvents = function(){
var dt;
var initDatatable = function () {
if (dt){
dt.clear().draw();
dt.ajax.url(getSearchURL(false)).load();
return;
}
$('#errorMsg').addClass("d-none");
dt = $('#dataTableFs').DataTable({
ajax: {
url: getSearchURL(false),
dataSrc: handleResponseData,
error: function ($xhr, textStatus, errorThrown) {
$(".dataTables_processing").hide();
let txt = "";
if ($xhr) {
let json = $xhr.responseJSON;
if (json) {
if (json.message){
txt = json.message;
}
}
}
if (!txt){
txt = "general.error500";
}
setI18NData($('#errorTxt'), txt);
$('#errorMsg').removeClass("d-none");
}
},
columns: [
{
data: "timestamp",
render: function(data, type, row) {
if (type === 'display') {
if (data){
let ts = data/1000000;
if (ts){
return $.t('general.datetime', {
val: new Date(ts),
formatParams: {
val: { year: '2-digit', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric' },
}
});
}
}
return "";
}
return data;
}
},
{
data: "action",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
switch (data){
case "upload":
return $.t('events.upload');
case "download":
return $.t('events.download');
case "mkdir":
return $.t('events.mkdir');
case "rmdir":
return $.t('events.rmdir');
case "rename":
return $.t('events.rename');
case "delete":
return $.t('events.delete');
case "first-upload":
return $.t('events.first_upload');
case "first-download":
return $.t('events.first_download');
case "ssh_cmd":
return $.t('events.ssh_cmd');
default:
console.log(`unknown fs action "${data}"`);
return "";
}
}
return data;
}
},
{
data: "virtual_path",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
if (!data){
return "";
}
if (row.virtual_target_path){
return escapeHTML(`${data} => ${row.virtual_target_path}`);
}
return escapeHTML(data);
}
return data;
}
},
{
data: "username",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
return escapeHTML(data);
}
return data;
}
},
{
data: "protocol",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
return escapeHTML(data);
}
return data;
}
},
{
data: "ip",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
return escapeHTML(data);
}
return data;
}
},
{
data: "status",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
let info = "";
switch (data){
case 1:
info = $.t('general.ok');
break;
case 2:
info = $.t('general.failed');
break;
case 3:
info = $.t('events.quota_exceeded');
break;
default:
console.log(`unknow status ${data}`);
}
if (row.file_size || row.file_size == 0){
let humanSize = fileSizeIEC(row["file_size"]);
info+=`. ${humanSize}`;
}
if (row.elapsed){
let elapsed = humanizeMilliseconds(row.elapsed);
info+=`. ${elapsed}`;
}
if (row.ssh_cmd){
info+=". "+$.t('events.ssh_cmd')+` "${row.ssh_cmd}"`;
}
return info;
}
return data;
}
},
],
deferRender: true,
processing: true,
lengthChange: false,
searching: false,
paging: false,
info: false,
ordering: false,
language: {
info: $.t('datatable.info'),
infoEmpty: $.t('datatable.info_empty'),
infoFiltered: $.t('datatable.info_filtered'),
loadingRecords: "",
processing: $.t('datatable.processing'),
zeroRecords: "",
emptyTable: $.t('datatable.no_records')
},
});
dt.on('draw', drawAction);
}
function drawAction() {
$('#table_body').localize();
}
return {
init: function () {
initDatatable();
}
}
}();
var datatableProviderEvents = function(){
var dt;
var initDatatable = function () {
if (dt){
dt.clear().draw();
dt.ajax.url(getSearchURL(false)).load();
return;
}
$('#errorMsg').addClass("d-none");
dt = $('#dataTableProvider').DataTable({
ajax: {
url: getSearchURL(false),
dataSrc: handleResponseData,
error: function ($xhr, textStatus, errorThrown) {
$(".dataTables_processing").hide();
let txt = "";
if ($xhr) {
let json = $xhr.responseJSON;
if (json) {
if (json.message){
txt = json.message;
}
}
}
if (!txt){
txt = "general.error500";
}
setI18NData($('#errorTxt'), txt);
$('#errorMsg').removeClass("d-none");
}
},
columns: [
{
data: "timestamp",
render: function(data, type, row) {
if (type === 'display') {
if (data){
let ts = data/1000000;
if (ts){
return $.t('general.datetime', {
val: new Date(ts),
formatParams: {
val: { year: '2-digit', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric' },
}
});
}
}
return "";
}
return data;
}
},
{
data: "action",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
switch (data){
case "add":
return $.t('events.add');
case "update":
return $.t('events.update');
case "delete":
return $.t('events.delete');
console.log(`unknown provider action "${data}"`);
return "";
}
}
return data;
}
},
{
data: "object_type",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
if (!data){
return "";
}
let message;
switch (data){
case "user":
message = $.t('provider_objects.user');
break;
case "folder":
message = $.t('provider_objects.folder');
break;
case "group":
message = $.t('provider_objects.group');
break;
case "admin":
message = $.t('provider_objects.admin');
break;
case "api_key":
message = $.t('provider_objects.api_key');
break;
case "share":
message = $.t('provider_objects.share');
break;
case "event_action":
message = $.t('provider_objects.event_action');
break;
case "event_rule":
message = $.t('provider_objects.event_rule');
break;
case "role":
message = $.t('provider_objects.role');
break;
case "ip_list_entry":
message = $.t('provider_objects.ip_list_entry');
break;
case "configs":
message = $.t('provider_objects.configs');
break;
default:
console.log("uknown object type: "+data);
return ""
}
if (row.object_name && data != "configs"){
return message+= escapeHTML(` "${row.object_name}"`);
}
return message;
}
return data;
}
},
{
data: "username",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
return escapeHTML(data);
}
return data;
}
},
{
data: "ip",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
return escapeHTML(data);
}
return data;
}
},
],
deferRender: true,
processing: true,
lengthChange: false,
searching: false,
paging: false,
info: false,
ordering: false,
language: {
info: $.t('datatable.info'),
infoEmpty: $.t('datatable.info_empty'),
infoFiltered: $.t('datatable.info_filtered'),
loadingRecords: "",
processing: $.t('datatable.processing'),
zeroRecords: "",
emptyTable: $.t('datatable.no_records')
},
});
dt.on('draw', drawAction);
}
function drawAction() {
$('#table_body').localize();
}
return {
init: function () {
initDatatable();
}
}
}();
var datatableLogEvents = function(){
var dt;
var initDatatable = function () {
if (dt){
dt.clear().draw();
dt.ajax.url(getSearchURL(false)).load();
return;
}
$('#errorMsg').addClass("d-none");
dt = $('#dataTableLog').DataTable({
ajax: {
url: getSearchURL(false),
dataSrc: handleResponseData,
error: function ($xhr, textStatus, errorThrown) {
$(".dataTables_processing").hide();
let txt = "";
if ($xhr) {
let json = $xhr.responseJSON;
if (json) {
if (json.message){
txt = json.message;
}
}
}
if (!txt){
txt = "general.error500";
}
setI18NData($('#errorTxt'), txt);
$('#errorMsg').removeClass("d-none");
}
},
columns: [
{
data: "timestamp",
render: function(data, type, row) {
if (type === 'display') {
if (data){
let ts = data/1000000;
if (ts){
return $.t('general.datetime', {
val: new Date(ts),
formatParams: {
val: { year: '2-digit', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric' },
}
});
}
}
return "";
}
return data;
}
},
{
data: "event",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
switch (data){
case 1:
return $.t('events.login_failed');
case 2:
return $.t('events.login_missing_user');
case 3:
return $.t('events.no_login_tried');
case 4:
return $.t('events.algo_negotiation_failed');
case 5:
return $.t('events.login_ok');
default:
console.log(`unknown log action "${data}"`);
return "";
}
}
return data;
}
},
{
data: "username",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
if (!data){
return "";
}
return escapeHTML(data);
}
return data;
}
},
{
data: "protocol",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
if (!data){
return "";
}
return escapeHTML(data);
}
return data;
}
},
{
data: "ip",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
if (data){
return escapeHTML(data);
}
}
return data;
}
},
{
data: "message",
defaultContent: "",
render: function(data, type, row) {
if (type === 'display') {
if (data){
return escapeHTML(data);
}
}
return "";
}
},
],
deferRender: true,
processing: true,
lengthChange: false,
searching: false,
paging: false,
info: false,
ordering: false,
language: {
info: $.t('datatable.info'),
infoEmpty: $.t('datatable.info_empty'),
infoFiltered: $.t('datatable.info_filtered'),
loadingRecords: "",
processing: $.t('datatable.processing'),
zeroRecords: "",
emptyTable: $.t('datatable.no_records')
},
});
dt.on('draw', drawAction);
}
function drawAction() {
$('#table_body').localize();
}
return {
init: function () {
initDatatable();
}
}
}();
$(document).on("i18nload", function(){
$('#dateTimeRange').flatpickr({
enableTime: true,
time_24hr: true,
formatDate: (date, format, locale) => {
return $.t('general.datetime', {
val: new Date(date),
formatParams: {
val: { year: '2-digit', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric' },
}
});
},
mode: "range",
defaultDate: [moment().add(-1,'hour').format('YYYY-MM-DD HH:mm')],
minuteIncrement: 1,
locale: i18next.resolvedLanguage
});
onEventChanged('1');
});
$(document).on("i18nshow", function(){
$('#idEventType').on("change", function(){
onEventChanged(this.value);
});
$('#search_button').on("click", function(e){
e.preventDefault();
this.blur();
onSearchClicked();
});
$('#export_button').on("click", function(e){
e.preventDefault();
this.blur();
onExportClicked();
});
$('#pagePrevious').on("click", function(e){
e.preventDefault();
this.blur();
prevClicked();
});
$('#pageNext').on("click", function(e){
e.preventDefault();
this.blur();
nextClicked();
});
});
</script>
{{- end}}