Revert "Added Vite to frontend builds"

This reverts commit 2b5d2d7949.
This commit is contained in:
Matteo Biscosi 2025-05-22 15:30:23 +02:00
parent c40f854283
commit 4e31f600f6
118 changed files with 34006 additions and 10177 deletions

View file

@ -7,81 +7,79 @@
const DEFINED_WIDGETS = {};
/* Used to implement the on click events onto the graph */
const DEFINED_EVENTS = {
/* On click event used by the flow analyze section, redirect to the current url + a single filter */
'db_analyze': function(event, chartContext, config) {
const {dataPointIndex} = config;
const {filter} = config.w.config;
let value;
/* On click event used by the flow analyze section, redirect to the current url + a single filter */
"db_analyze" : function (event, chartContext, config) {
const { dataPointIndex } = config;
const { filter } = config.w.config;
let value;
if (config.w.config.filtering_labels) {
value = config.w.config.filtering_labels[dataPointIndex];
}
if(config.w.config.filtering_labels)
value = config.w.config.filtering_labels[dataPointIndex];
if (filter.length == 0 || value === undefined) {
return;
}
if(filter.length == 0 || value === undefined)
return;
const status = ntopng_status_manager.get_status();
const filters = status.filters;
filters.push({id: filter[0], operator: 'eq', value: value});
// notify that filters status is updated
ntopng_events_manager.emit_event(ntopng_events.FILTERS_CHANGE, {filters});
},
let status = ntopng_status_manager.get_status();
let filters = status.filters;
filters.push({id: filter[0], operator: "eq", value: value});
// notify that filters status is updated
ntopng_events_manager.emit_event(ntopng_events.FILTERS_CHANGE, {filters});
},
'none': function(event, chartContext, config) {
return;
},
"none" : function (event, chartContext, config) {
return;
},
/* Standard on click event, redirect to the url */
"standard" : function (event, chartContext, config) {
const { seriesIndex, dataPointIndex } = config;
const { series } = config.w.config;
if (seriesIndex === -1) return;
if (series === undefined) return;
/* Standard on click event, redirect to the url */
'standard': function(event, chartContext, config) {
const {seriesIndex, dataPointIndex} = config;
const {series} = config.w.config;
if (seriesIndex === -1) return;
if (series === undefined) return;
const serie = series[seriesIndex];
if (serie.base_url !== undefined) {
const default_url = (serie.start_url || '');
const search = serie.data[dataPointIndex].meta.url_query;
location.href = `${serie.base_url}?${default_url}${search}`;
}
},
};
const serie = series[seriesIndex];
if (serie.base_url !== undefined) {
const default_url = (serie.start_url || '')
const search = serie.data[dataPointIndex].meta.url_query;
location.href = `${serie.base_url}?${default_url}${search}`;
}
},
}
export const DEFINED_TOOLTIP = {
/* On click event used by the flow analyze section, redirect to the current url + a single filter */
'format_bytes': function(value, {config, seriesIndex, dataPointIndex}) {
return NtopUtils.bytesToSize(value);
},
/* On click event used by the flow analyze section, redirect to the current url + a single filter */
"format_bytes" : function(value, { config, seriesIndex, dataPointIndex }) {
return NtopUtils.bytesToSize(value);
},
'format_pkts': function(value, {config, seriesIndex, dataPointIndex}) {
return NtopUtils.formatPackets(value);
},
"format_pkts" : function(value, { config, seriesIndex, dataPointIndex }) {
return NtopUtils.formatPackets(value);
},
/* On click event used by the flow analyze section, redirect to the current url + a single filter */
'format_value': function(value, {config, seriesIndex, dataPointIndex}) {
return NtopUtils.formatValue(value);
},
/* On click event used by the flow analyze section, redirect to the current url + a single filter */
"format_value" : function(value, { config, seriesIndex, dataPointIndex }) {
return NtopUtils.formatValue(value);
},
'format_multiple_date': function(value, {config, seriesIndex, dataPointIndex}) {
return new Date(value[0]) + ' - ' + new Date(value[1]);
},
"format_multiple_date" : function(value, { config, seriesIndex, dataPointIndex }) {
return new Date(value[0]) + " - " + new Date(value[1])
},
/*
/*
* This formatter is used by the bubble host map, from the y axis,
* used to show the Hosts, with their respective values
* used to show the Hosts, with their respective values
*/
'format_label_from_xy': function({series, seriesIndex, dataPointIndex, w}) {
const serie = w.config.series[seriesIndex]['data'][dataPointIndex];
"format_label_from_xy" : function({series, seriesIndex, dataPointIndex, w}) {
const serie = w.config.series[seriesIndex]["data"][dataPointIndex];
const x_value = serie["x"];
const y_value = serie["y"];
const host_name = serie["meta"]["label"];
const x_value = serie['x'];
const y_value = serie['y'];
const host_name = serie['meta']['label'];
const x_axis_title = w.config.xaxis.title.text;
const y_axis_title = w.config.yaxis[0].title.text;
const x_axis_title = w.config.xaxis.title.text;
const y_axis_title = w.config.yaxis[0].title.text;
return (`
return (`
<div class='apexcharts-theme-light apexcharts-active' id='test'>
<div class='apexcharts-tooltip-title' style='font-family: Helvetica, Arial, sans-serif; font-size: 12px;'>
${host_name}
@ -94,18 +92,18 @@ export const DEFINED_TOOLTIP = {
<b>${y_axis_title}</b>: ${y_value}
</div>
</div>
</div>`);
},
'format_label_from_xname': function({series, seriesIndex, dataPointIndex, w}) {
const serie = w.config.series[seriesIndex]['data'][dataPointIndex];
const name = serie['name'];
const y_value = serie['y'];
const host_name = serie['meta']['label'];
</div>`)
},
"format_label_from_xname" : function({series, seriesIndex, dataPointIndex, w}) {
const serie = w.config.series[seriesIndex]["data"][dataPointIndex];
const name = serie["name"]
const y_value = serie["y"];
const host_name = serie["meta"]["label"];
const x_axis_title = w.config.xaxis.title.text;
const y_axis_title = w.config.yaxis[0].title.text;
const x_axis_title = w.config.xaxis.title.text;
const y_axis_title = w.config.yaxis[0].title.text;
return (`
return (`
<div class='apexcharts-theme-light apexcharts-active' id='test'>
<div class='apexcharts-tooltip-title' style='font-family: Helvetica, Arial, sans-serif; font-size: 12px;'>
${host_name}
@ -118,394 +116,400 @@ export const DEFINED_TOOLTIP = {
<b>${y_axis_title}</b>: ${y_value}
</div>
</div>
</div>`);
},
};
</div>`)
},
}
/* Standard Formatter */
const DEFAULT_FORMATTER = DEFINED_TOOLTIP['format_value'];
const DEFAULT_FORMATTER = DEFINED_TOOLTIP["format_value"];
export class WidgetUtils {
static registerWidget(widget) {
if (widget === null) throw new Error(`The passed widget reference is null!`);
if (widget.name in DEFINED_WIDGETS) throw new Error(`The widget ${widget.name} is already defined!`);
DEFINED_WIDGETS[widget.name] = widget;
}
static getWidgetByName(widgetName) {
if (widgetName in DEFINED_WIDGETS) {
return DEFINED_WIDGETS[widgetName];
static registerWidget(widget) {
if (widget === null) throw new Error(`The passed widget reference is null!`);
if (widget.name in DEFINED_WIDGETS) throw new Error(`The widget ${widget.name} is already defined!`);
DEFINED_WIDGETS[widget.name] = widget;
}
static getWidgetByName(widgetName) {
if (widgetName in DEFINED_WIDGETS) {
return DEFINED_WIDGETS[widgetName];
}
throw new Error(`Widget ${widgetName} not found!`)
}
throw new Error(`Widget ${widgetName} not found!`);
}
}
/**
* Define a simple wrapper class for the widgets.
*/
class Widget {
constructor(name, datasource = {}, updateTime = 0, additionalParams = {}) {
// field containing the data fetched from the datasources provided
this._fetchedData = [];
this.name = name;
constructor(name, datasource = {}, updateTime = 0, additionalParams = {}) {
// if 0 then don't update the chart automatically, the time
// is expressed in milliseconds
this._updateTime = updateTime;
// field containing the data fetched from the datasources provided
this._fetchedData = [];
this._datasource = datasource;
this._additionalParams = additionalParams;
}
this.name = name;
/**
// if 0 then don't update the chart automatically, the time
// is expressed in milliseconds
this._updateTime = updateTime;
this._datasource = datasource;
this._additionalParams = additionalParams;
}
/**
* Init the widget.
*/
async init() {
// register the widget to the DEFINED_WIDGETS object
WidgetUtils.registerWidget(this);
this._fetchedData = await this._fetchData();
async init() {
if (this._updateTime > 0) {
setInterval(async () => {
await this.update(this._datasource.params);
}, this._updateTime);
// register the widget to the DEFINED_WIDGETS object
WidgetUtils.registerWidget(this);
this._fetchedData = await this._fetchData();
if (this._updateTime > 0) {
setInterval(async () => { await this.update(this._datasource.params); }, this._updateTime);
}
}
}
/**
/**
* Destroy the widget freeing the resources used.
*/
async destroy() { }
async destroy() { }
/**
/**
* Force the widget to reload it's data.
*/
async destroyAndUpdate(datasourceParams = {}) {
await this.destroy();
await this.update(datasourceParams);
}
async updateByUrl(url) {
const u = new URL(`${location.origin}${this._datasource.name}`);
const entries = ntopng_url_manager.get_url_entries(url);
for (const [key, value] of entries) {
u.searchParams.set(key, value);
}
this._datasource.endpoint = u.pathname + u.search;
this._fetchedData = await this._fetchData();
}
async update(datasourceParams = {}) {
// build the new endpoint
const u = new URL(`${location.origin}${this._datasource.name}`);
for (const [key, value] of Object.entries(datasourceParams)) {
u.searchParams.set(key, value);
async destroyAndUpdate(datasourceParams = {}) {
await this.destroy();
await this.update(datasourceParams);
}
this._datasource.endpoint = u.pathname + u.search;
this._fetchedData = await this._fetchData();
}
async updateByUrl(url) {
const u = new URL(`${location.origin}${this._datasource.name}`);
let entries = ntopng_url_manager.get_url_entries(url);
for (const [key, value] of entries) {
u.searchParams.set(key, value);
}
this._datasource.endpoint = u.pathname + u.search;
this._fetchedData = await this._fetchData();
}
async update(datasourceParams = {}) {
// build the new endpoint
const u = new URL(`${location.origin}${this._datasource.name}`);
/**
for (const [key, value] of Object.entries(datasourceParams)) {
u.searchParams.set(key, value);
}
this._datasource.endpoint = u.pathname + u.search;
this._fetchedData = await this._fetchData();
}
/**
* For each datasources provided to the constructor,
* do a GET request to a REST endpoint.
*/
async _fetchData() {
const req = await fetch(`${http_prefix}${this._datasource.endpoint}`);
return await req.json();
}
async _fetchData() {
const req = await fetch(`${http_prefix}${this._datasource.endpoint}`);
return await req.json();
}
}
export class ChartWidget extends Widget {
constructor(name, type = 'line', datasource = {}, updateTime = 0, additionalParams = {}) {
super(name, datasource, updateTime, additionalParams);
this._chartType = type;
this._chart = {};
this._$htmlChart = document.querySelector(`#canvas-widget-${name}`);
}
constructor(name, type = 'line', datasource = {}, updateTime = 0, additionalParams = {}) {
super(name, datasource, updateTime, additionalParams);
static registerEventCallback(widgetName, eventName, callback) {
setTimeout(async () => {
try {
const widget = WidgetUtils.getWidgetByName(widgetName);
const updatedOptions = {
chart: {
events: {
[eventName]: callback,
this._chartType = type;
this._chart = {};
this._$htmlChart = document.querySelector(`#canvas-widget-${name}`);
}
static registerEventCallback(widgetName, eventName, callback) {
setTimeout(async () => {
try {
const widget = WidgetUtils.getWidgetByName(widgetName);
const updatedOptions = {
chart: {
events: {
[eventName]: callback
}
}
};
await widget._chart.updateOptions(updatedOptions);
}
catch (e) {
}
}, 1000);
}
_generateConfig() {
const config = {
series: [],
tooltip: {
enabledOnSeries: [0],
x: {
show: true,
format: 'dd/MM/yyyy HH:mm:ss',
},
y: {
formatter: function(value, { series, seriesIndex, dataPointIndex, w }) {
return value;
},
},
z: {
show: false,
}
},
chart: {
type: this._chartType,
events: {},
height: '100%',
toolbar: {
show: false,
}
},
xaxis: {
labels: {
style: {
fontSize: '14px',
}
},
tooltip: {
enabled: true,
formatter: function(value) {
return value;
}
}
},
yaxis: {
labels: {
style: {
fontSize: '14px',
}
},
tooltip: {
enabled: true,
formatter: function(value) {
return value;
}
}
},
zaxis: {
labels: {
style: {
fontSize: '14px',
}
},
tooltip: {
enabled: true
}
},
dataLabels: {
enabled: true,
style: {
fontSize: '14px',
}
},
},
};
await widget._chart.updateOptions(updatedOptions);
} catch (e) {
}
}, 1000);
}
_generateConfig() {
const config = {
series: [],
tooltip: {
enabledOnSeries: [0],
x: {
show: true,
format: 'dd/MM/yyyy HH:mm:ss',
},
y: {
formatter: function(value, {series, seriesIndex, dataPointIndex, w}) {
return value;
},
},
z: {
show: false,
},
},
chart: {
type: this._chartType,
events: {},
height: '100%',
toolbar: {
show: false,
},
},
xaxis: {
labels: {
style: {
fontSize: '14px',
},
},
tooltip: {
enabled: true,
formatter: function(value) {
return value;
},
},
},
yaxis: {
labels: {
style: {
fontSize: '14px',
},
},
tooltip: {
enabled: true,
formatter: function(value) {
return value;
},
},
},
zaxis: {
labels: {
style: {
fontSize: '14px',
},
},
tooltip: {
enabled: true,
},
},
dataLabels: {
enabled: true,
style: {
fontSize: '14px',
},
},
labels: [],
legend: {
show: true,
fontSize: '14px',
position: 'bottom',
onItemClick: {
toggleDataSeries: true,
},
},
plotOptions: {
bar: {
borderRadius: 4,
horizontal: true,
},
},
noData: {
text: 'No Data',
align: 'center',
verticalAlign: 'middle',
style: {
fontSize: '24px',
},
},
};
legend: {
show: true,
fontSize: '14px',
position: 'bottom',
onItemClick: {
toggleDataSeries: true,
},
},
plotOptions: {
bar: {
borderRadius: 4,
horizontal: true,
}
},
noData: {
text: 'No Data',
align: 'center',
verticalAlign: 'middle',
style: {
fontSize: '24px'
}
}
};
// check if the additionalParams field contains an apex property,
// then merge the two configurations giving priority to the custom one
if (this._additionalParams && this._additionalParams.apex) {
const mergedConfig = Object.assign(config, this._additionalParams.apex);
return mergedConfig;
}
return config;
}
_buildTooltip(config, rsp) {
debugger;
/* By default the areaChart tooltip[y] is overwritten */
config['tooltip']['y'] = {
formatter: function(value, {series, seriesIndex, dataPointIndex, w}) {
return value;
},
};
/* Changing events if given */
if (rsp['tooltip']) {
for (const axis in rsp['tooltip']) {
if (axis === 'x' || axis === 'y' || axis === 'z') {
const formatter = rsp['tooltip'][axis]['formatter'];
if (!config['tooltip'][axis]) {
config['tooltip'][axis] = {};
}
config['tooltip'][axis]['formatter'] = DEFINED_TOOLTIP[formatter] || NtopUtils[formatter];
}
}
/* Customizable tooltip requested */
if (rsp['tooltip']['custom']) {
config['tooltip']['custom'] = DEFINED_TOOLTIP[rsp['tooltip']['custom']] || NtopUtils[rsp['tooltip']['custom']];
}
}
}
_buildAxisFormatter(config, axisName) {
const axis = config[axisName];
if (axis === undefined || axis.labels === undefined) return;
// enable formatters
if (axis.labels.ntop_utils_formatter !== undefined && axis.labels.ntop_utils_formatter !== 'none') {
const selectedFormatter = axis.labels.ntop_utils_formatter;
if (NtopUtils[selectedFormatter] === undefined) {
console.error(`xaxis: Formatting function '${selectedFormatter}' didn't found inside NtopUtils.`);
} else {
axis.labels.formatter = NtopUtils[selectedFormatter];
}
} // enable formatters
}
_buildDataLabels(config, rsp) {
if (rsp['dataLabels']) {
for (const [dataLabelsOpts, data] of Object.entries(rsp['dataLabels'])) {
config['dataLabels'][dataLabelsOpts] = data;
}
}
const formatter = config['dataLabels']['formatter'];
if (formatter && DEFINED_TOOLTIP[formatter]) {
config['dataLabels']['formatter'] = DEFINED_TOOLTIP[formatter];
}
}
_buildConfig() {
const config = this._generateConfig();
const rsp = this._fetchedData.rsp;
// add additional params fetched from the datasource
const additionals = ['series', 'xaxis', 'yaxis', 'colors', 'labels', 'fill', 'filter', 'filtering_labels'];
for (const additional of additionals) {
if (rsp[additional] === undefined) continue;
if (config[additional] !== undefined) {
config[additional] = Object.assign(config[additional], rsp[additional]);
} else {
config[additional] = rsp[additional];
}
}
/* Changing events if given */
if (rsp['events']) {
/* Just pass a table of events. e.g. { events = { click = "db_analyze", updated = "standard" } }*/
for (const event in rsp['events']) {
config['chart']['events'][event] = DEFINED_EVENTS[rsp['events'][event]];
}
}
if (rsp['horizontal_chart'] !== undefined) {
config['plotOptions']['bar']['horizontal'] = rsp['horizontal_chart'];
}
this._buildTooltip(config, rsp);
this._buildAxisFormatter(config, 'xaxis');
this._buildAxisFormatter(config, 'yaxis');
this._buildDataLabels(config, rsp);
return config;
}
_initializeChart() {
const config = this._buildConfig();
this._chartConfig = config;
this._chart = new ApexCharts(this._$htmlChart, this._chartConfig);
this._chart.render();
}
async init() {
await super.init();
this._initializeChart();
}
async destroy() {
await super.destroy();
this._chart.destroy();
this._chart = null;
}
async update(datasourceParams = {}) {
if (this._chartConfig !== undefined) {
if (datasourceParams) {
await super.update(datasourceParams);
} else {
await super.updateByUrl();
}
if (this._chart != null) {
// expecting that rsp contains an object called series
const {colors, series, dataLabels, labels, xaxis, filtering_labels} = this._fetchedData.rsp;
// update the colors list
this._chartConfig.colors = colors;
this._chartConfig.series = series;
if (xaxis && xaxis.categories) {
this._chartConfig.xaxis.categories = xaxis.categories;
// check if the additionalParams field contains an apex property,
// then merge the two configurations giving priority to the custom one
if (this._additionalParams && this._additionalParams.apex) {
const mergedConfig = Object.assign(config, this._additionalParams.apex);
return mergedConfig;
}
if (filtering_labels) {
this._chartConfig.filtering_labels = filtering_labels;
return config;
}
_buildTooltip(config, rsp) {
debugger;
/* By default the areaChart tooltip[y] is overwritten */
config["tooltip"]["y"] = {
formatter: function(value, { series, seriesIndex, dataPointIndex, w }) {
return value;
}
};
/* Changing events if given */
if (rsp['tooltip']) {
for (const axis in rsp['tooltip']) {
if (axis === "x" || axis === "y" || axis === "z") {
const formatter = rsp['tooltip'][axis]['formatter'];
if(!config['tooltip'][axis])
config['tooltip'][axis] = {}
config['tooltip'][axis]['formatter'] = DEFINED_TOOLTIP[formatter] || NtopUtils[formatter]
}
}
/* Customizable tooltip requested */
if(rsp['tooltip']['custom'])
config['tooltip']['custom'] = DEFINED_TOOLTIP[rsp['tooltip']['custom']] || NtopUtils[rsp['tooltip']['custom']]
}
}
_buildAxisFormatter(config, axisName) {
const axis = config[axisName];
if (axis === undefined || axis.labels === undefined) return;
// enable formatters
if (axis.labels.ntop_utils_formatter !== undefined && axis.labels.ntop_utils_formatter !== 'none') {
const selectedFormatter = axis.labels.ntop_utils_formatter;
if (NtopUtils[selectedFormatter] === undefined) {
console.error(`xaxis: Formatting function '${selectedFormatter}' didn't found inside NtopUtils.`);
}
else {
axis.labels.formatter = NtopUtils[selectedFormatter];
}
} // enable formatters
}
_buildDataLabels(config, rsp) {
if (rsp["dataLabels"]) {
for (const [dataLabelsOpts, data] of Object.entries(rsp["dataLabels"])) {
config["dataLabels"][dataLabelsOpts] = data;
}
}
let formatter = config["dataLabels"]["formatter"];
if(formatter && DEFINED_TOOLTIP[formatter]) {
config["dataLabels"]["formatter"] = DEFINED_TOOLTIP[formatter];
}
}
_buildConfig() {
const config = this._generateConfig();
const rsp = this._fetchedData.rsp;
// add additional params fetched from the datasource
const additionals = ['series', 'xaxis', 'yaxis', 'colors', 'labels', 'fill', 'filter', 'filtering_labels'];
for (const additional of additionals) {
if (rsp[additional] === undefined) continue;
if (config[additional] !== undefined) {
config[additional] = Object.assign(config[additional], rsp[additional]);
}
else {
config[additional] = rsp[additional];
}
}
/* Changing events if given */
if (rsp['events']) {
/* Just pass a table of events. e.g. { events = { click = "db_analyze", updated = "standard" } }*/
for (const event in rsp['events']) {
config['chart']['events'][event] = DEFINED_EVENTS[rsp['events'][event]]
}
}
if (dataLabels) {
const formatter = this._chartConfig.dataLabels.formatter;
if (formatter && DEFINED_TOOLTIP[formatter]) {
this._chartConfig.dataLabels.formatter = DEFINED_TOOLTIP[formatter];
if (rsp['horizontal_chart'] !== undefined) {
config['plotOptions']['bar']['horizontal'] = rsp['horizontal_chart'];
}
this._buildTooltip(config, rsp)
this._buildAxisFormatter(config, 'xaxis');
this._buildAxisFormatter(config, 'yaxis');
this._buildDataLabels(config, rsp);
return config;
}
_initializeChart() {
const config = this._buildConfig();
this._chartConfig = config;
this._chart = new ApexCharts(this._$htmlChart, this._chartConfig);
this._chart.render();
}
async init() {
await super.init();
this._initializeChart();
}
async destroy() {
await super.destroy();
this._chart.destroy();
this._chart = null;
}
async update(datasourceParams = {}) {
if(this._chartConfig !== undefined) {
if (datasourceParams) {
await super.update(datasourceParams);
} else {
this._chartConfig.dataLabels.formatter = DEFAULT_FORMATTER;
await super.updateByUrl();
}
}
if (this._chart != null) {
// expecting that rsp contains an object called series
const { colors, series, dataLabels, labels, xaxis, filtering_labels } = this._fetchedData.rsp;
// update the colors list
this._chartConfig.colors = colors;
this._chartConfig.series = series;
if(xaxis && xaxis.categories)
this._chartConfig.xaxis.categories = xaxis.categories;
if(filtering_labels)
this._chartConfig.filtering_labels = filtering_labels;
if (labels) {
this._chartConfig.labels = labels;
}
if(dataLabels) {
let formatter = this._chartConfig.dataLabels.formatter;
if(formatter && DEFINED_TOOLTIP[formatter])
this._chartConfig.dataLabels.formatter = DEFINED_TOOLTIP[formatter];
else
this._chartConfig.dataLabels.formatter = DEFAULT_FORMATTER;
}
if(labels)
this._chartConfig.labels = labels;
this._chart.updateOptions(this._chartConfig, true);
}
this._chart.updateOptions(this._chartConfig, true);
}
}
}
async destroyAndUpdate(datasource = {}) {
await super.destroyAndUpdate(datasource);
this._initializeChart();
}
}
async destroyAndUpdate(datasource = {}) {
await super.destroyAndUpdate(datasource);
this._initializeChart();
}
}