`);
if (filter.currently_active == true) {
// set active filter title and key
if (self.$dropdown.title.parent().find(`i.fas`).length == 0) {
self.$dropdown.title.parent().prepend(``);
}
const newContent = $entry.html();
self.$dropdown.title.html(newContent);
// remove the active class from the li elements
self.$dropdown.container.find('li').removeClass(`active`);
// add active class to current entry
if (filter.key !== 'all') {
$entry.addClass(`active`);
}
}
} else if (filter.regex !== undefined && (filter.countable === undefined || filter.countable)) {
const data = this.tableAPI.columns(this.columnIndex).data()[0];
const count = this._countEntries(filter.regex, data);
const $counter = $(`(${count})`);
// if the count is 0 then hide the menu entry
if (count == 0) $entry.hide();
//append the $counter object inside the $entry
$entry.append($counter);
}
$entry.on('click', function (e) {
// set active filter title and key
if (self.$dropdown.title.parent().find(`i.fas`).length == 0) {
self.$dropdown.title.parent().prepend(``);
}
const newContent = $entry.html();
self.$dropdown.title.html(newContent);
// remove the active class from the li elements
self.$dropdown.container.find('li').removeClass(`active`);
// add active class to current entry
if (filter.key !== 'all') {
$entry.addClass(`active`);
}
if (self.callbackFunction) {
self.callbackFunction(self.tableAPI, filter);
if (filter.callback) filter.callback();
return;
}
if (!self.url) {
self.preventUpdate = true;
// if the filter have a callback then call it
if (filter.callback) filter.callback();
// perform the table filtering
self.tableAPI.column(self.columnIndex).search(filter.regex, true, false).draw();
// set current filter
self.currentFilterSelected = filter;
} else {
self.urlParams = window.location.search
const newUrlParams = new URLSearchParams(self.urlParams)
newUrlParams.set(self.filterMenuKey, (typeof (filter.id) != "undefined") ? filter.id : '')
window.history.pushState('', '', window.location.pathname + '?' + newUrlParams.toString())
location.reload()
}
});
return $entry;
}
_createFilters(filters) {
const filtersCreated = {};
// for each filter defined in this.filters
for (const filter of filters) {
const $filter = this._createMenuEntry(filter);
// save the filter inside the $filters object
filtersCreated[filter.key] = { filter: filter, $node: $filter };
}
return filtersCreated;
}
_render(filters) {
if (typeof this.columnIndex == 'undefined') {
$(`${this.icon || this.filterTitle}`).insertBefore(this.$datatableWrapper.find('.dataTables_filter').parent());
} else {
const $dropdownContainer = $(``);
const $dropdownButton = $(``);
const $dropdownTitle = $(`${this.filterTitle}`);
$dropdownButton.append($dropdownTitle);
this.$dropdown = {
container: $dropdownContainer,
title: $dropdownTitle,
button: $dropdownButton
};
this.filters = this._createFilters(filters);
const $menuContainer = $(`
`);
for (const [_, filter] of Object.entries(this.filters)) {
$menuContainer.append(filter.$node);
}
// the All entry is created by the object
if (!this.removeAllEntry) {
const allFilter = this._generateAllFilter();
$menuContainer.prepend(this._createMenuEntry(allFilter));
}
// append the created dropdown inside
$dropdownContainer.append($dropdownButton);
$dropdownContainer.append($menuContainer);
// append the dropdown menu inside the filter wrapper
$dropdownContainer.insertBefore(this.$datatableWrapper.find('.dataTables_filter').parent());
this._selectFilterFromState(this.filterMenuKey);
}
}
_selectFilterFromState(filterKey) {
if (!this.tableAPI.state) return;
if (!this.tableAPI.state.loaded()) return;
if (!this.tableAPI.state.loaded().filters) return;
// save the current table state
tableAPI.state.save();
}
_generateAllFilter() {
return {
key: 'all',
label: i18n_ext.all,
regex: '',
countable: false,
callback: () => {
this.$dropdown.title.parent().find('i.fas.fa-filter').remove();
this.$dropdown.title.html(`${this.filterTitle}`);
}
};
}
_update() {
// if the filters have not been initialized by _render then return
if (this.filters === undefined) return;
if (this.preventUpdate) {
this.preventUpdate = false;
return;
}
for (const [_, filter] of Object.entries(this.filters)) {
if (filter.countable == false || filter.filter.countable == false) continue;
const data = this.tableAPI.columns(this.columnIndex).data()[0];
const count = this._countEntries(filter.filter.regex, data);
// hide the filter if the count is zero
(count == 0) ? filter.$node.hide() : filter.$node.show();
// update the counter label
filter.$node.find('.counter').text(`(${count})`);
// update the selected button counter
this.$dropdown.button.find('.counter').text(`(${count})`);
}
}
}
export class DataTableUtils {
/**
* Return a standard config for the Sprymedia (c) DataTables
*/
static getStdDatatableConfig(dtButtons = [], dom = "<'row'<'col-sm-2 d-inline-block'l><'col-sm-10 text-end d-inline-block'<'dt-search'f>B>rtip>") {
// hide the buttons section if there aren't buttons inside the array
if (dtButtons.length == 0) {
dom = "fBrtip";
}
return {
dom: dom,
pagingType: 'full_numbers',
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
language: {
search: i18n.script_search,
paginate: {
previous: '<',
next: '>',
first: '«',
last: '»'
}
},
saveState: true,
responsive: true,
buttons: {
buttons: dtButtons,
dom: {
button: {
className: 'btn btn-link'
},
container: {
className: 'd-inline-block'
}
}
}
}
}
static createLinkCallback(action) {
let handler = "";
let fOnClick = DataTableHandlers.addHandler(action.handler);
handler = `onclick="${fOnClick}"`;
return `
${action.text || ''}
`;
}
/**
* Example of action:
* {
* class: string,
* data: object,
* icon: string,
* modal: string,
* href: string,
* hidden: bool,
* }
* @param {*} actions
*/
static createActionButtons(actions = []) {
const buttons = [];
const dropdownButton = ''
actions.forEach((action, i) => {
let handler = "";
if (action.handler) {
let fOnClick = DataTableHandlers.addHandler(action.handler);
handler = `onclick="${fOnClick}"`;
}
let button = (`
`);
}
static deleteButtonHandlers(handlerId) {
DataTableHandlers.deleteHandlersById(handlerId);
}
static setAjaxConfig(config, url, dataSrc = '', method = "get", params = {}) {
config.ajax = {
url: url,
type: method,
dataSrc: dataSrc,
data: function (d) {
return $.extend({}, d, params);
}
}
return config;
}
static extendConfig(config, extension) {
// if there are custom filters then manage state in this way
if (extension.hasFilters) {
extension.stateSaveCallback = function (settings, data) {
localStorage.setItem('DataTables_' + settings.sInstance, JSON.stringify(data))
};
extension.stateLoadCallback = function (settings) {
return JSON.parse(localStorage.getItem('DataTables_' + settings.sInstance));
};
// on saving the table state store the selected filters
extension.stateSaveParams = function (settings, data) {
// save the filters selected from the user inside the state
$('[data-filter]').each(function () {
const activeFilter = $(this).find(`li.active`).data('filter-key');
if (!activeFilter) return;
// if the filters object is not allocated then initizializes it
if (!data.filters) data.filters = {};
data.filters[$(this).data('filter')] = activeFilter;
});
};
}
// const userInitComplete = extension.initComplete;
// const initComplete = (settings, json) => {
// if (userInitComplete !== undefined) userInitComplete(settings, json);
// // turn on tooltips
// $(`.actions-group [title]`).tooltip('enable');
// };
// // override initComplete function
// extension.initComplete = initComplete;
return $.extend({}, config, extension);
}
/**
* Format the passed seconds into the "HH:MM:SS" string.
* @param {number} seconds
*/
static secondsToHHMMSS(seconds) {
const padZeroes = n => `${n}`.padStart(2, '0');
const sec = seconds % 60;
const mins = Math.floor(seconds / 60) % 60;
const hours = Math.floor(seconds / 3600);
return `${padZeroes(hours)}:${padZeroes(mins)}:${padZeroes(sec)}`;
}
/**
* Open the pool edit modal of a chosen pool if the query params contains the pool paramater
* @param tableAPI
*/
static openEditModalByQuery(params) {
const urlParams = new URLSearchParams(window.location.search);
if (!urlParams.has(params.paramName)) return;
const dataID = urlParams.get(params.paramName);
const data = params.datatableInstance.data().toArray().find((data => data[params.paramName] == dataID));
// if the cancelIf param has been passed
// then test the cancelIf function, if the return value
// is true then cancel the modal opening
if (typeof (params.cancelIf) === 'function') {
if (params.cancelIf(data)) return;
}
const $modal = $(`#${params.modalHandler.getModalID()}`);
// if the pool id is valid then open the edit modal
if (data !== undefined) {
params.modalHandler.invokeModalInit(data);
$modal.modal('show');
}
if (!urlParams.has('referer')) {
$modal.on('hidden.bs.modal', function (e) {
const url = new URL(window.location.href);
url.searchParams.delete(params.paramName);
history.replaceState({}, '', url.toString());
});
return;
}
const referer = urlParams.get('referer');
$modal.on('hidden.bs.modal', function (e) {
window.location = referer;
});
}
static addToggleColumnsDropdown(tableAPI, toggleCallback = (col, visible) => { }) {
if (tableAPI === undefined) {
throw 'The $table is undefined!';
}
const tableID = tableAPI.table().node().id;
DataTableUtils._loadColumnsVisibility(tableAPI).then(function (fetchedData) {
let savedColumns = [-1];
if (fetchedData.success) {
savedColumns = fetchedData.columns.map(i => parseInt(i));
}
else {
console.warn(fetchedData.message);
}
const columns = [];
const ignoredColumns = [];
const $datatableWrapper = $(tableAPI.context[0].nTableWrapper);
// get the table headers
tableAPI.columns().every(function (i) {
// avoid already hidden columns
if (!tableAPI.column(i).visible()) {
ignoredColumns.push(i);
return;
}
columns.push({ index: i, name: this.header().textContent, label: this.i18n.name /* Human-readable column name */ });
});
const $btnGroup = $(`
`);
const $dropdownMenu = $(`
Show Columns
`);
const $checkboxes = $(``);
for (let i = 0; i < columns.length; i++) {
const column = columns[i];
// Prevents columns with no names to be selectively hidden (e.g., the entity under the all alerts page)
if (column.name == "")
continue;
// create a checkbox and delegate a change event
const id = `toggle-${column.name.split().join('_')}`;
// check if the column id it's inside the savedColumns array
// if toggled is true then the column is not hidden
const toggled = savedColumns.indexOf(column.index) === -1;
if (!toggled) {
const col = tableAPI.column(column.index);
col.visible(false);
}
const $checkbox = $(``);
const $wrapper = $(`