mirror of
https://github.com/ntop/ntopng.git
synced 2026-05-02 00:40:10 +00:00
782 lines
28 KiB
Text
782 lines
28 KiB
Text
{#
|
|
(C) 2020 - ntop.org
|
|
|
|
This is the template for the active monitoring stats page. I
|
|
#}
|
|
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
{% if not ntop.getPrefs().active_monitoring then %}
|
|
<div class="alert alert-warning alert-dismissable">
|
|
<span>{* i18n("enable_active_monitoring_warning", { base_prefix = ntop.getHttpPrefix() }) *} </span>
|
|
</div>
|
|
{% end %}
|
|
<div class="card card-shadow">
|
|
<div class="card-body">
|
|
<table class="table w-100 table-striped table-hover table-bordered" id="am-table">
|
|
<thead>
|
|
<tr>
|
|
<th>{{i18n("flow_details.url")}}</th>
|
|
<th>{{i18n("system_stats.last_ip")}}</th>
|
|
<th>{{i18n("active_monitoring_stats.measurement")}}</th>
|
|
<th>{{i18n("chart")}}</th>
|
|
<th>{{i18n("threshold")}}</th>
|
|
<th>{{i18n("active_monitoring_stats.last_24_hours")}}</th>
|
|
<th>{{i18n("active_monitoring_stats.last_measurement")}}</th>
|
|
<th>{{i18n("active_monitoring_stats.measurement")}}</th>
|
|
<th>{{i18n("active_monitoring_stats.alerted")}}</th>
|
|
<th>{{i18n("active_monitoring_stats.pool")}}</th>
|
|
<th>{{i18n("active_monitoring_stats.jitter")}}</th>
|
|
<th>{{i18n("actions")}}</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
<div class="card-footer">
|
|
{* ui_utils.render_configuration_footer('active_monitoring') *}
|
|
</div>
|
|
</div>
|
|
<div class="notes bg-light border">
|
|
<b>{{ i18n("notes") }}</b>:
|
|
<ul>
|
|
{% for _, note in pairs(am_stats.notes) do %}
|
|
<li>{{ note }}</li>
|
|
{% end %}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{*
|
|
template_utils.render("am_add_host_modal.html", {
|
|
dialog = {
|
|
add_record = i18n("active_monitoring_stats.add_record"),
|
|
measurement = i18n("active_monitoring_stats.measurement"),
|
|
add_measurement_select = generate_select("select-add-measurement", "measurement", true, false, {}, "measurement-select"),
|
|
am_host = i18n("about.host_checks_directory"),
|
|
periodicity = i18n("internals.periodicity"),
|
|
add_granularity_select = generate_select("select-add-granularity", "granularity", true, false, {}, "measurement-granularity"),
|
|
threshold = i18n("threshold"),
|
|
notes = i18n("notes"),
|
|
note_icmp = i18n("active_monitoring_stats.am_note_icmp"),
|
|
note_http = i18n("active_monitoring_stats.am_note_http"),
|
|
note_alert = i18n("active_monitoring_stats.note_alert"),
|
|
cancel = i18n("cancel"),
|
|
add = i18n("add"),
|
|
}
|
|
})
|
|
*}
|
|
|
|
{*
|
|
template_utils.render("am_edit_host_modal.html", {
|
|
dialog = {
|
|
measurement = i18n("active_monitoring_stats.measurement"),
|
|
edit_measurement_select = generate_select("select-edit-measurement", "measurement", true, false, {}, "measurement-select"),
|
|
am_host = i18n("about.host_checks_directory"),
|
|
periodicity = i18n("internals.periodicity"),
|
|
edit_granularity_select = generate_select("select-edit-granularity", "granularity", true, false, {}, "measurement-granularity"),
|
|
edit_record = i18n("active_monitoring_stats.edit_record"),
|
|
notes = i18n("notes"),
|
|
note_icmp = i18n("active_monitoring_stats.am_note_icmp"),
|
|
note_http = i18n("active_monitoring_stats.am_note_http"),
|
|
note_alert = i18n("active_monitoring_stats.note_alert"),
|
|
note_periodicity_change = i18n("active_monitoring_stats.note_periodicity_change"),
|
|
reset = i18n("reset"),
|
|
apply = i18n("apply"),
|
|
cancel = i18n("cancel"),
|
|
threshold = i18n("threshold"),
|
|
}
|
|
})
|
|
*}
|
|
|
|
{*
|
|
|
|
template_utils.render("am_delete_host_modal.html", {
|
|
dialog = {
|
|
confirm_delete = i18n("active_monitoring_stats.confirm_delete"),
|
|
delete = i18n("delete"),
|
|
cancel = i18n("cancel"),
|
|
}
|
|
})
|
|
|
|
*}
|
|
|
|
|
|
<script type="text/javascript">
|
|
let get_host = "{* am_stats.get_host *}";
|
|
let am_csrf = "{{ ntop.getRandomCSRFValue()}}";
|
|
let import_csrf = "{{ ntop.getRandomCSRFValue()}}";
|
|
const measurements_info = {*json.encode(am_stats.measurements_info)*};
|
|
const poolsFilter = {* json.encode(am_stats.pool_filters)*};
|
|
const SHOW_IFACE = {{ ntop.isPingIfaceAvailable() }};
|
|
|
|
const MAX_RECIPIENTS = 3;
|
|
const DEFAULT_MEASUREMENT = "cicmp";
|
|
const INFRASTRUCTURE_ENDPOINT = "/lua/rest/v2/get/system/data.lua";
|
|
|
|
const getMeasurementRegex = (measurement) => {
|
|
switch (measurement) {
|
|
default:
|
|
case "throughput":
|
|
return `${NtopUtils.REGEXES["url"]}|${NtopUtils.REGEXES["domainName"]}`;
|
|
case "http":
|
|
case "https":
|
|
return `${NtopUtils.REGEXES["url"]}`;
|
|
case "icmp":
|
|
case "cicmp":
|
|
return `${NtopUtils.REGEXES["ipv4"]}|${NtopUtils.REGEXES["ipv6"]}|${NtopUtils.REGEXES["domainName"]}`;
|
|
}
|
|
}
|
|
|
|
const getMeasurementPlaceholder = (measurement) => {
|
|
switch (measurement) {
|
|
default:
|
|
case "throughput":
|
|
return `Insert an URL (https://www.google.com)`;
|
|
case "http":
|
|
case "https":
|
|
return `Insert an URL (https://www.google.com)`;
|
|
case "icmp":
|
|
case "cicmp":
|
|
return `Insert an IP or a Domain Name`;
|
|
}
|
|
}
|
|
|
|
const addPoolFilter = (tableAPI) => {
|
|
|
|
const POOL_COLUMN_INDEX = 8;
|
|
|
|
return new DataTableFiltersMenu({
|
|
filterTitle: i18n('pools.pools'),
|
|
tableAPI: tableAPI,
|
|
filters: poolsFilter,
|
|
filterMenuKey: 'pools',
|
|
columnIndex: POOL_COLUMN_INDEX
|
|
}).init();
|
|
}
|
|
|
|
const addMeasurementFilter = (tableAPI) => {
|
|
|
|
const MEASUREMENT_COLUMN_INDEX = 1;
|
|
|
|
// build filters for datatable
|
|
const measurements = Object.keys(measurements_info);
|
|
const filters = [];
|
|
|
|
for (const measurement of measurements) {
|
|
filters.push({
|
|
key: measurement,
|
|
label: `${measurements_info[measurement].label}`,
|
|
regex: `^(${measurements_info[measurement].label})$`
|
|
});
|
|
}
|
|
|
|
// sort the created filters
|
|
filters.sort((a, b) => a.label.localeCompare(b.label));
|
|
|
|
return new DataTableFiltersMenu({
|
|
filterTitle: i18n('active_monitoring_stats.measurement'),
|
|
tableAPI: tableAPI,
|
|
filters: filters,
|
|
filterMenuKey: 'measurement',
|
|
columnIndex: MEASUREMENT_COLUMN_INDEX
|
|
});
|
|
}
|
|
|
|
const addAlertedFilter = (tableAPI) => {
|
|
|
|
const ALERTED_COLUMN_INDEX = 8;
|
|
const filters = [
|
|
{
|
|
key: 'alerted',
|
|
label: `${i18n('active_monitoring_stats.alerted')}`,
|
|
regex: `1`
|
|
},
|
|
{
|
|
key: 'not_alerted',
|
|
label: `${i18n('active_monitoring_stats.not_alerted')}`,
|
|
regex: `0`
|
|
}
|
|
];
|
|
|
|
return new DataTableFiltersMenu({
|
|
filterTitle: i18n('active_monitoring_stats.alert_status'),
|
|
tableAPI: tableAPI,
|
|
filters: filters,
|
|
filterMenuKey: 'alert-status',
|
|
columnIndex: ALERTED_COLUMN_INDEX
|
|
});
|
|
}
|
|
|
|
// Disable the already defined measurements for forced_hosts since
|
|
// they are unique
|
|
const dialogDisableUniqueMeasurements = ($dialog, cur_measurement) => {
|
|
const $m_sel = $dialog.find(".measurement-select");
|
|
const measurements_to_skip = {};
|
|
|
|
// find out wich unique measurements are already defined
|
|
$amTable.rows().data().each(function(row_data) {
|
|
var m_info = measurements_info[row_data.measurement];
|
|
|
|
if(m_info && m_info.force_host)
|
|
measurements_to_skip[row_data.measurement] = true;
|
|
});
|
|
|
|
// Populate the measurements dropdown
|
|
$m_sel.find('option').remove();
|
|
|
|
// Sort measurements according to their localized labels
|
|
var sorted_measurements = [];
|
|
for(var k in measurements_info)
|
|
sorted_measurements.push([k, measurements_info[k]]);
|
|
|
|
sorted_measurements.sort(function(a, b){
|
|
a = a[1]; b = b[1];
|
|
if(a.label < b.label) { return -1; }
|
|
if(a.label > b.label) { return 1; }
|
|
return 0;
|
|
});
|
|
|
|
for(var i=0; i<sorted_measurements.length; i++) {
|
|
var k = sorted_measurements[i][0];
|
|
var m_info = measurements_info[k];
|
|
|
|
if((k == cur_measurement) || !measurements_to_skip[k])
|
|
$m_sel.append(`<option value="${k}">${m_info.label}</option>`);
|
|
}
|
|
}
|
|
|
|
/* Called whenever the measurment of a dialog changes/is initialized. */
|
|
const dialogRefreshMeasurement = ($dialog, granularity, use_defaults) => {
|
|
const measurement = $dialog.find(".measurement-select").val();
|
|
|
|
if(!measurement || !measurements_info[measurement]) return;
|
|
|
|
const info = measurements_info[measurement];
|
|
|
|
$dialog.find(".measurement-operator").html("&" + (info.operator || "gt") + ";");
|
|
$dialog.find(".measurement-unit").html(info.unit || i18n("active_monitoring_stats.msec"));
|
|
|
|
// Check if host is forced
|
|
const host = $dialog.find(".measurement-host")
|
|
if(info.force_host) {
|
|
host.attr("disabled", "disabled");
|
|
host.val(info.force_host);
|
|
} else {
|
|
host.removeAttr("disabled");
|
|
}
|
|
|
|
// Populate the granularities dropdown
|
|
const $granularities = $dialog.find(".measurement-granularity");
|
|
const old_val = $granularities.val();
|
|
let old_val_ok = false;
|
|
$granularities.find('option').remove();
|
|
|
|
for(let i=0; i<info.granularities.length; i++) {
|
|
let g_info = info.granularities[i];
|
|
if(g_info.value == old_val)
|
|
old_val_ok = true;
|
|
|
|
$granularities.append(`<option value="${g_info.value}">${g_info.title}</option>`);
|
|
}
|
|
|
|
const $threshold = $dialog.find(".measurement-threshold");
|
|
|
|
if(info.max_threshold)
|
|
$threshold.attr("max", info.max_threshold);
|
|
else
|
|
$threshold.removeAttr("max");
|
|
|
|
if(use_defaults && info.default_threshold)
|
|
$threshold.val(info.default_threshold);
|
|
|
|
if(granularity)
|
|
$granularities.val(granularity);
|
|
else if(old_val_ok)
|
|
$granularities.val(old_val);
|
|
}
|
|
|
|
const dialogRefreshPeriodicity = ($modal) => {
|
|
|
|
const $periodicityGroup = $modal.find(`[name='granularity']`).parents('.form-group');
|
|
const selectedMeasurement = $modal.find(".measurement-select").val();
|
|
if (!selectedMeasurement || !measurements_info[selectedMeasurement]) return;
|
|
const measurement = measurements_info[selectedMeasurement];
|
|
|
|
if (measurement.granularities.length == 1) {
|
|
$periodicityGroup.hide();
|
|
}
|
|
else {
|
|
$periodicityGroup.show();
|
|
}
|
|
|
|
}
|
|
|
|
const getAmData = ($am_table, $button_caller) => {
|
|
|
|
const row_data = $am_table.row($button_caller.parent().parent()).data();
|
|
return row_data;
|
|
}
|
|
|
|
const createHoursHeatmap = (td, data) => {
|
|
const squareLength = 7, squareHeight = 20;
|
|
const colors = ['#d3d3d3', '#28a745', '#f00', '#ffc107'];
|
|
const $svg = $(td).find('svg');
|
|
const this_hour = new Date().getHours();
|
|
|
|
for (let x = 0; x < 24; x++) {
|
|
const $rect = $(document.createElementNS("http://www.w3.org/2000/svg", "rect"));
|
|
$rect.attr('x', x*(squareLength+2)).attr('y', 0).attr('width', squareLength).attr('height', squareHeight);
|
|
const colorIndex = (data.length > 0) ? data[x] : 0;
|
|
$rect.attr('fill', colors[colorIndex]);
|
|
if (this_hour == x) {
|
|
$rect.attr('stroke', '#000'); /* Add stroke for the current hour */
|
|
$rect.attr('stroke-width', '2');
|
|
$rect.attr('stroke-dasharray', '2'); /* Make line dashed */
|
|
$rect.attr('opacity', '0.6');
|
|
}
|
|
$svg.append($rect);
|
|
}
|
|
}
|
|
|
|
const $addHostModalHandler = $(`#am-add-form`).modalHandler({
|
|
method: 'post',
|
|
endpoint: `${http_prefix}/lua/edit_active_monitoring_host.lua`,
|
|
resetAfterSubmit: false,
|
|
csrf: am_csrf,
|
|
onModalInit: function () {
|
|
const $dialog = $('#am-add-modal');
|
|
dialogDisableUniqueMeasurements($dialog);
|
|
|
|
// select the first non-disabled option (after dialogDisableUniqueMeasurements)
|
|
$("#select-add-measurement").val($("#select-add-measurement").find("option:not([disabled]):first").val());
|
|
|
|
$('#input-add-host').val('');
|
|
$('#input-add-threshold').val(100);
|
|
$(`#am-add-modal span.invalid-feedback`).hide();
|
|
$('#am-add-modal').modal('show');
|
|
|
|
// set the edit pool link
|
|
const $editPoolLink = $('#am-add-form .edit-pool');
|
|
$editPoolLink.attr('href', NtopUtils.getEditPoolLink($editPoolLink.attr('href'), 0));
|
|
|
|
$(`#am-add-form select[name='pool']`).trigger('change');
|
|
|
|
dialogRefreshMeasurement($dialog, null, true /* use defaults */);
|
|
dialogRefreshPeriodicity($dialog);
|
|
},
|
|
beforeSumbit: function () {
|
|
const host = $("#input-add-host").val(), measurement = $("#select-add-measurement").val();
|
|
const granularity = $("#select-add-granularity").val();
|
|
const threshold = $("#input-add-threshold").val();
|
|
const pool = $(`#select-add-pool`).val();
|
|
let iface = $(`#am-add-form select[name='iface']`).val();
|
|
if (iface == 'Default Interface') {
|
|
iface = "{* default_ifname *}";
|
|
}
|
|
$(`#add-invalid-feedback`).hide();
|
|
|
|
return {
|
|
action: 'add',
|
|
am_host: host,
|
|
threshold: threshold,
|
|
measurement: measurement,
|
|
granularity: granularity,
|
|
pool: pool,
|
|
ifname: iface
|
|
}
|
|
},
|
|
onSubmitSuccess: function (response, dataSent) {
|
|
if (response.success) {
|
|
|
|
ToastUtils.showToast({
|
|
title: i18n("success"),
|
|
body: response.message,
|
|
level: 'success',
|
|
delay: 3000,
|
|
id: `am-add-${dataSent.am_host}`
|
|
});
|
|
|
|
$(`#am-add-modal`).modal('hide');
|
|
$amTable.ajax.reload();
|
|
return;
|
|
}
|
|
|
|
$(`#add-invalid-feedback`).show().text(response.error);
|
|
}
|
|
});
|
|
|
|
const $editModalHandler = $(`#am-edit-form`).modalHandler({
|
|
method: 'post',
|
|
endpoint: `${http_prefix}/lua/edit_active_monitoring_host.lua`,
|
|
resetAfterSubmit: false,
|
|
csrf: am_csrf,
|
|
onModalInit: function (amData) {
|
|
const DEFAULT_THRESHOLD = 500;
|
|
const DEFAULT_GRANULARITY = "min";
|
|
const DEFAULT_MEASUREMENT = "icmp";
|
|
const DEFAULT_HOST = "";
|
|
const DEFAULT_POOL = 0;
|
|
|
|
const cur_measurement = amData.measurement_key || DEFAULT_MEASUREMENT;
|
|
const $dialog = $('#am-edit-modal');
|
|
|
|
$(`#hostCheck`).hide();
|
|
|
|
dialogDisableUniqueMeasurements($dialog, cur_measurement);
|
|
$('#am-edit-modal').modal('show');
|
|
// fill input boxes
|
|
$('#input-edit-threshold').val(amData.threshold || DEFAULT_THRESHOLD);
|
|
$('#select-edit-measurement').val(cur_measurement).change();
|
|
$('#select-edit-granularity').val(amData.granularity || DEFAULT_GRANULARITY);
|
|
$('#input-edit-host').val(amData.host || DEFAULT_HOST);
|
|
$(`#select-edit-pool`).val(amData.pool || DEFAULT_POOL);
|
|
|
|
// set the edit pool link
|
|
const $editPoolLink = $('#am-add-form .edit-pool');
|
|
$editPoolLink.attr('href', NtopUtils.getEditPoolLink($editPoolLink.attr('href'), amData.pool || DEFAULT_POOL));
|
|
$(`#am-edit-form select[name='pool']`).trigger('change');
|
|
if (SHOW_IFACE && ['icmp', 'cicmp'].includes(cur_measurement)) {
|
|
const value = (amData.ifname === '') ? $(`#am-edit-form .interface-group [name='iface'] option:first`).val() : amData.ifname;
|
|
$(`#am-edit-form .interface-group`).show();
|
|
$(`#am-edit-form .interface-group [name='iface']`).val(value);
|
|
}
|
|
else {
|
|
$(`#am-edit-form .interface-group`).hide();
|
|
}
|
|
|
|
dialogRefreshMeasurement($dialog, amData.granularity);
|
|
dialogRefreshPeriodicity($dialog);
|
|
},
|
|
beforeSumbit: function (amData) {
|
|
const host = $("#input-edit-host").val();
|
|
const measurement_key = $("#select-edit-measurement").val();
|
|
const granularity = $("#select-edit-granularity").val();
|
|
const threshold = $("#input-edit-threshold").val();
|
|
const pool = $(`#select-edit-pool`).val();
|
|
console.log($(`#am-edit-form select[name='iface']`));
|
|
const iface = $(`#am-edit-form select[name='iface']`).val();
|
|
$(`#am-edit-modal .invalid-feedback`).hide();
|
|
|
|
$(`#hostCheck`).show();
|
|
|
|
return {
|
|
action: 'edit',
|
|
threshold: threshold,
|
|
am_host: host,
|
|
measurement: measurement_key,
|
|
old_am_host: amData.host,
|
|
old_measurement: amData.measurement_key,
|
|
granularity: granularity,
|
|
old_granularity: amData.granularity,
|
|
ifname: iface,
|
|
pool: pool
|
|
};
|
|
},
|
|
onSubmitSuccess: function (response, dataSent) {
|
|
$(`#hostCheck`).hide();
|
|
if (response.success) {
|
|
|
|
ToastUtils.showToast({
|
|
title: i18n('success'),
|
|
body: response.message,
|
|
level: 'success',
|
|
delay: 3000,
|
|
id: `am-edit-${dataSent.am_host}`
|
|
});
|
|
|
|
$(`#am-edit-modal`).modal('hide');
|
|
$amTable.ajax.reload();
|
|
|
|
return;
|
|
} else {
|
|
$(`#am-edit-modal .invalid-feedback`).html(response.error).show();
|
|
}
|
|
}
|
|
});
|
|
|
|
const $removeModalHandler = $(`#am-delete-modal form`).modalHandler({
|
|
method: 'post',
|
|
csrf: am_csrf,
|
|
endpoint: `${http_prefix}/lua/edit_active_monitoring_host.lua`,
|
|
dontDisableSubmit: true,
|
|
onModalInit: function(amData) {
|
|
$("#delete-host").html(`<b>${amData.measurement}://${amData.html_label}</b>`);
|
|
},
|
|
beforeSumbit: (amData) => {
|
|
return {
|
|
action: 'delete',
|
|
am_host: amData.host,
|
|
measurement: amData.measurement_key,
|
|
csrf: am_csrf
|
|
}
|
|
},
|
|
onSubmitSuccess: function (response, dataSent) {
|
|
if (response.success) {
|
|
$(`#am-delete-modal`).modal('hide');
|
|
ToastUtils.showToast({
|
|
title: i18n('success'),
|
|
body: response.message,
|
|
level: 'success',
|
|
delay: 3000,
|
|
id: `am-delete-${dataSent.am_host}`
|
|
});
|
|
$amTable.ajax.reload();
|
|
}
|
|
}
|
|
});
|
|
|
|
let dtConfig = DataTableUtils.getStdDatatableConfig( [
|
|
{
|
|
text: '<i class="fas fa-plus"></i>',
|
|
className: 'btn-link',
|
|
enabled: (get_host === ""),
|
|
action: function(e, dt, node, config) {
|
|
$addHostModalHandler.invokeModalInit();
|
|
$("#select-add-measurement").trigger('change');
|
|
}
|
|
},
|
|
{
|
|
text: '<i class="fas fa-sync-alt"></i>',
|
|
className: 'btn-link',
|
|
action: function(e, dt, node, config) {
|
|
$amTable.ajax.reload();
|
|
}
|
|
}
|
|
], );
|
|
dtConfig = DataTableUtils.setAjaxConfig(dtConfig, `${http_prefix}/lua/get_active_monitoring_hosts.lua`);
|
|
dtConfig = DataTableUtils.extendConfig(dtConfig, {
|
|
lengthChange: (get_host === ""),
|
|
paging: (get_host === ""),
|
|
order: [[ 1 /* Last IP */, "desc" ]],
|
|
initComplete: function(settings, data) {
|
|
|
|
if (get_host != "") {
|
|
$amTable.search(get_host).draw(true);
|
|
$amTable.state.clear();
|
|
}
|
|
|
|
const table = settings.oInstance.api();
|
|
setInterval(() => { $amTable.ajax.reload(); }, 15000);
|
|
},
|
|
columns: [
|
|
{
|
|
data: 'html_label',
|
|
width: '100%',
|
|
render: function(html_label, type, row) {
|
|
|
|
if (type === 'display') {
|
|
if (html_label == "" || html_label == undefined) return "";
|
|
|
|
if(row.alerted) {
|
|
return `${html_label} <i class="fas fa-exclamation-triangle" style="color: #f0ad4e;"></i>`
|
|
}
|
|
|
|
return html_label;
|
|
}
|
|
|
|
return (row.label);
|
|
}
|
|
},
|
|
{
|
|
data: 'last_ip',
|
|
className: 'dt-body-right dt-head-center text-nowrap'
|
|
},
|
|
{
|
|
data: 'measurement',
|
|
class: 'text-nowrap',
|
|
},
|
|
{
|
|
data: 'chart',
|
|
class: 'text-center',
|
|
sortable: false,
|
|
render: function(href, type, row) {
|
|
if(type === 'display') {
|
|
if (href == "" || href == undefined) return "";
|
|
return `<a href='${href}'><i class='fas fa-chart-area'></i></a>`
|
|
}
|
|
|
|
// The raw data must be returned here for sorting
|
|
return(href);
|
|
}
|
|
},
|
|
{
|
|
data: 'threshold',
|
|
className: 'text-center',
|
|
render: function(data, type, row) {
|
|
if(type === 'display' || type === 'filter') {
|
|
if(row.threshold)
|
|
return `${row.threshold} ${row.unit}`
|
|
else
|
|
return "";
|
|
}
|
|
|
|
// The raw data must be returned here for sorting
|
|
return(data);
|
|
}
|
|
},
|
|
{
|
|
data: 'hours',
|
|
className: 'text-center dt-head-center text-nowrap',
|
|
sortable: false,
|
|
render: function(data, type) {
|
|
if (type == 'display') {
|
|
return `<svg width='220' height='20' viewBox='0 0 220 20'></svg>`;
|
|
}
|
|
return data;
|
|
},
|
|
createdCell: function(td, data) {
|
|
createHoursHeatmap(td, data);
|
|
}
|
|
},
|
|
{
|
|
data: 'last_mesurement_time',
|
|
className: 'text-center text-nowrap',
|
|
render: $.fn.dataTableExt.absoluteFormatSecondsToHHMMSS,
|
|
},
|
|
{
|
|
data: 'last_measure',
|
|
className: 'text-center',
|
|
sortable: false,
|
|
render: function(data, type, row) {
|
|
if(type === 'display' || type === 'filter') {
|
|
if (row.last_measure) {
|
|
return (parseFloat(row.last_measure) != NaN ? `${parseFloat(row.last_measure)} ${row.unit}` : `${row.last_measure}`)
|
|
}
|
|
else
|
|
return "";
|
|
}
|
|
|
|
// The raw data must be returned here for sorting
|
|
return(data);
|
|
}
|
|
},
|
|
{
|
|
data: 'alerted',
|
|
visible: false,
|
|
sortable: false,
|
|
},
|
|
{
|
|
data: 'pool',
|
|
visible: false,
|
|
sortable: false
|
|
},
|
|
{
|
|
data: 'jitter',
|
|
className: 'dt-body-right dt-head-center no-wrap',
|
|
sortable: false,
|
|
},
|
|
{
|
|
targets: -1,
|
|
data: null,
|
|
sortable: false,
|
|
name: 'actions',
|
|
responsivePriority: 3,
|
|
class: 'text-center',
|
|
render: function(_, type, host) {
|
|
|
|
const disabled = (host.readonly) ? 'disabled' : '';
|
|
|
|
return DataTableUtils.createActionButtons([
|
|
{ class: `btn-info ${disabled}`, icon: 'fa-edit', modal: '#am-edit-modal', title: `${i18n("users.edit")}` },
|
|
{ class: `btn-danger ${disabled}`, icon: 'fa-trash', modal: '#am-delete-modal', title: `${i18n("delete")}` }
|
|
]);
|
|
}
|
|
},
|
|
{
|
|
data: 'measurement_key',
|
|
visible: false
|
|
}
|
|
]
|
|
});
|
|
|
|
const $amTable = $("#am-table").DataTable(dtConfig);
|
|
DataTableUtils.addToggleColumnsDropdown($amTable);
|
|
|
|
addMeasurementFilter($amTable).init();
|
|
addAlertedFilter($amTable).init();
|
|
|
|
$('#am-table').on('click', `a[href='#am-edit-modal']`, function(e) {
|
|
const amData = getAmData($amTable, $(this).parent().parent());
|
|
$editModalHandler.invokeModalInit(amData);
|
|
});
|
|
|
|
$('#am-table').on('click', `a[href='#am-delete-modal']`, function(e) {
|
|
const amData = getAmData($amTable, $(this).parent().parent());
|
|
$removeModalHandler.invokeModalInit(amData);
|
|
});
|
|
|
|
$("#select-edit-measurement").on('change', function(event) {
|
|
const selectedMeasurement = $(this).val();
|
|
// change the pattern depending on the selected measurement
|
|
$(`#input-edit-host`).attr('pattern', getMeasurementRegex(selectedMeasurement));
|
|
|
|
// trigger form validation
|
|
if ($(`#input-edit-host`).val().length > 0) $(`#am-edit-form`)[0].reportValidity();
|
|
if (['icmp', 'cicmp'].includes(selectedMeasurement)) {
|
|
if (SHOW_IFACE) {
|
|
$(`#am-edit-form .interface-group`).show();
|
|
}
|
|
}
|
|
else {
|
|
$(`#am-edit-form .interface-group`).hide();
|
|
}
|
|
|
|
dialogRefreshMeasurement($("#am-edit-modal"));
|
|
dialogRefreshPeriodicity($("#am-edit-modal"));
|
|
});
|
|
|
|
// select the first pattern based to the first selected measurement
|
|
// on the input-add-host
|
|
$(`#input-add-host`).attr('pattern', getMeasurementRegex($("#select-add-measurement").val()));
|
|
|
|
$("#select-add-measurement").on('change', function(event) {
|
|
|
|
const selectedMeasurement = $(this).val();
|
|
|
|
// change the pattern depending on the selected measurement
|
|
$(`#input-add-host`).attr('pattern', getMeasurementRegex(selectedMeasurement));
|
|
$(`#input-add-host`).attr('placeholder',getMeasurementPlaceholder(selectedMeasurement));
|
|
|
|
// trigger form validation
|
|
if ($(`#input-add-host`).val().length > 0) $(`#am-add-form`)[0].reportValidity();
|
|
|
|
if (['icmp', 'cicmp'].includes(selectedMeasurement)) {
|
|
if (SHOW_IFACE) {
|
|
$(`#am-add-form .interface-group`).show();
|
|
}
|
|
}
|
|
else {
|
|
$(`#am-add-form .interface-group`).hide();
|
|
}
|
|
|
|
dialogRefreshMeasurement($("#am-add-modal"));
|
|
dialogRefreshPeriodicity($("#am-add-modal"));
|
|
});
|
|
|
|
// on changing the associated pool updates the link to the edit pool
|
|
$(`select[name='pool']`).change(async function() {
|
|
|
|
const poolId = $(this).val();
|
|
const $editPoolLink = $(this).parents('.form-group').find('.edit-pool');
|
|
const $recipientsInfo = $(this).parents('.form-group').find('.recipients-info')
|
|
|
|
$editPoolLink.attr('href', NtopUtils.getEditPoolLink($editPoolLink.attr('href'), poolId));
|
|
|
|
const [success, pool] = await NtopUtils.getPool('active_monitoring', poolId);
|
|
if (!success) return;
|
|
|
|
let recipients = pool.recipients;
|
|
|
|
if (recipients.length == 0) {
|
|
$recipientsInfo.html(i18n('pools.no_recipients'));
|
|
return;
|
|
}
|
|
|
|
const recipientNames = NtopUtils.arrayToListString(recipients.map(recipient => recipient.recipient_name), MAX_RECIPIENTS);
|
|
$recipientsInfo.html(i18n('pools.some_recipients').replace('${recipients}', recipientNames));
|
|
|
|
});
|
|
</script>
|
|
|