mirror of
https://github.com/ntop/ntopng.git
synced 2026-05-05 10:41:34 +00:00
248 lines
9.7 KiB
Vue
248 lines
9.7 KiB
Vue
<!-- (C) 2022 - ntop.org -->
|
|
<template>
|
|
<div class="mb-2" style="overflow-x: auto; white-space: nowrap;"> <!-- legend-wrapper -->
|
|
<div class="d-flex align-items-center"> <!-- legend-div -->
|
|
<div v-if="!$props.hide_stacked" class="form-check form-switch form-control-sm ms-1" data-bs-toggle="tooltip"
|
|
:title="block_stacked ? i18n('stacked_blocked_title') : i18n('stacked_unblocked_title')">
|
|
<input type="checkbox" class="form-check-input" @click="changeStacked" :checked="stacked"
|
|
:disabled="block_stacked">
|
|
<label class="form-check-label">
|
|
{{ i18n('stacked') }}
|
|
</label>
|
|
</div>
|
|
<div class="ms-auto">
|
|
<label class="form-check-label form-control-sm" v-for="(item, i) in timeseries_list">
|
|
<input type="checkbox" class="form-check-input align-middle mt-0"
|
|
@click="change_visibility(!item.checked, i)" :checked="item.checked"
|
|
style="border-color: #0d6efd;" :style="{ backgroundColor: item.color }">
|
|
{{ item.name }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-if="disable_fixed_height == true" class="mb-3" style="width:100%;" ref="chart"></div>
|
|
<div v-else class="mb-3" style="width:100%;min-height:320px;" ref="chart"></div>
|
|
</template>
|
|
|
|
<script>
|
|
import { Dygraph } from '../utilities/graph/dygraph';
|
|
export default {
|
|
components: {
|
|
},
|
|
props: {
|
|
id: String,
|
|
chart_type: String,
|
|
register_on_status_change: Boolean,
|
|
base_url_request: String,
|
|
get_params_url_request: Function,
|
|
get_custom_chart_options: Function,
|
|
disable_fixed_height: Boolean,
|
|
hide_stacked: Boolean,
|
|
},
|
|
emits: ["apply", "hidden", "showed", "chart_reloaded", "zoom"],
|
|
/** This method is the first method of the component called, it's called before html template creation. */
|
|
created() { },
|
|
beforeUnmount() { },
|
|
data() {
|
|
return {
|
|
chart: null,
|
|
stacked: null,
|
|
block_stacked: false,
|
|
chart_options: null,
|
|
from_zoom: false,
|
|
reload: false,
|
|
timeseries_visibility: null,
|
|
timeseries_list: [],
|
|
last_url_request: '',
|
|
i18n: (t) => i18n(t),
|
|
};
|
|
},
|
|
/** This method is the first method called after html template creation. */
|
|
async mounted() {
|
|
await this.init();
|
|
ntopng_sync.ready(this.$props["id"]);
|
|
},
|
|
methods: {
|
|
init: async function () {
|
|
let status = ntopng_status_manager.get_status();
|
|
let url_request = this.get_url_request(status);
|
|
if (this.register_on_status_change) {
|
|
this.register_status(status);
|
|
}
|
|
await this.draw_chart(url_request);
|
|
},
|
|
get_image: function (image) {
|
|
return Dygraph.Export.asPNG(this.chart, image, this.$refs["chart"]);
|
|
},
|
|
changeStacked: function () {
|
|
this.stacked = !this.stacked;
|
|
localStorage.setItem('ntopng.timeseries.chartStackedOption.' + this.$props["id"], this.stacked)
|
|
this.updateIntoStackedChart(this.stacked);
|
|
},
|
|
change_visibility: function (visible, id) {
|
|
if (this.timeseries_list[id] != null) {
|
|
this.timeseries_list[id]["checked"] = visible
|
|
this.chart.setVisibility(id, visible);
|
|
}
|
|
},
|
|
register_status: function (status) {
|
|
let url_request = this.get_url_request(status);
|
|
ntopng_status_manager.on_status_change(this.id, (new_status) => {
|
|
if (this.from_zoom == true) {
|
|
this.from_zoom = false;
|
|
//return;
|
|
}
|
|
let new_url_request = this.get_url_request(new_status);
|
|
if (new_url_request == url_request) {
|
|
url_request = new_url_request;
|
|
return;
|
|
}
|
|
url_request = new_url_request;
|
|
this.update_chart(new_url_request);
|
|
}, false);
|
|
},
|
|
get_url_request: function (status) {
|
|
let url_params;
|
|
if (this.$props.get_params_url_request != null) {
|
|
if (status == null) {
|
|
status = ntopng_status_manager.get_status();
|
|
}
|
|
url_params = this.$props.get_params_url_request(status);
|
|
} else {
|
|
url_params = ntopng_url_manager.get_url_params();
|
|
}
|
|
|
|
return `${this.$props.base_url_request || ''}?${url_params}`;
|
|
},
|
|
ensure_path: function (obj, path) {
|
|
return path.reduce((acc, key) => (acc[key] ??= {}), obj);
|
|
},
|
|
get_chart_options: async function (url_request) {
|
|
let chart_options = {};
|
|
const date_format = await ntopng_utility.get_date_format(false, this.$props.csrf, http_prefix);
|
|
|
|
/* Retrieve the chart options */
|
|
if (this.$props.get_custom_chart_options == null) {
|
|
chart_options = await ntopng_utility.http_request(url_request);
|
|
} else {
|
|
chart_options = await this.$props.get_custom_chart_options(url_request);
|
|
}
|
|
if (!chart_options) {
|
|
chart_options = {}
|
|
}
|
|
const xAxis = this.ensure_path(chart_options, ["axes", "x"]);
|
|
/* Set the date depending on the server date */
|
|
xAxis.axisLabelFormatter ??= function (date) {
|
|
return ntopng_utility.from_utc_to_server_date_format(date, date_format);
|
|
};
|
|
xAxis.valueFormatter ??= function (date) {
|
|
return ntopng_utility.from_utc_to_server_date_format(date, date_format);
|
|
};
|
|
/* Emit the chart_reloaded event */
|
|
this.$emit('chart_reloaded', chart_options);
|
|
if (this.stacked === null && !chart_options.blockStacked) {
|
|
// First loading of the chart
|
|
const is_stacked_option_found = localStorage.getItem('ntopng.timeseries.chartStackedOption.' + this.$props["id"])
|
|
if (is_stacked_option_found !== null) {
|
|
this.stacked = (is_stacked_option_found == 'true');
|
|
chart_options.stackedGraph = this.stacked;
|
|
} else {
|
|
this.stacked = chart_options.stackedGraph;
|
|
}
|
|
} else {
|
|
if (chart_options.blockStacked)
|
|
this.stacked = false;
|
|
chart_options.stackedGraph = this.stacked;
|
|
}
|
|
return chart_options;
|
|
},
|
|
draw_chart: async function (url_request) {
|
|
let chart_options = await this.get_chart_options(url_request);
|
|
const data = chart_options.data || [];
|
|
chart_options.data = null;
|
|
chart_options.zoomCallback = this.on_zoomed;
|
|
if (chart_options.blockStacked) {
|
|
this.block_stacked = true
|
|
}
|
|
this.timeseries_list = [];
|
|
let visibility = [];
|
|
let id = 0;
|
|
if (!chart_options.disableTsList) {
|
|
for (const key in chart_options.series) {
|
|
this.timeseries_list.push({ name: key, checked: true, id: id, color: chart_options.colors[id] + "!important" });
|
|
id = id + 1;
|
|
visibility.push(true);
|
|
}
|
|
}
|
|
this.chart = new Dygraph(this.$refs["chart"], data, chart_options);
|
|
},
|
|
update_chart: async function (url_request) {
|
|
if (this.chart) {
|
|
let chart_options = await this.get_chart_options(url_request);
|
|
this.chart.updateChart(chart_options);
|
|
}
|
|
},
|
|
update_chart_options: function (chart_options) {
|
|
if (this.chart) {
|
|
this.chart.updateChart(chart_options);
|
|
}
|
|
},
|
|
updateIntoStackedChart: function (stacked) {
|
|
if (this.chart) {
|
|
this.chart.updateOptions({ 'stackedGraph': stacked });
|
|
}
|
|
},
|
|
update_chart_series: function (options) {
|
|
if (options == null) { return; }
|
|
if (this.chart) {
|
|
this.chart.updateOptions({ 'file': options.data, 'colors': options.colors, 'label': options.labels });
|
|
}
|
|
},
|
|
on_zoomed: function (minDate, maxDate) {
|
|
this.from_zoom = true;
|
|
const begin = moment(minDate);
|
|
const end = moment(maxDate);
|
|
// the timestamps are in milliseconds, convert them into seconds
|
|
let new_epoch_status = { epoch_begin: Number.parseInt(begin.unix()), epoch_end: Number.parseInt(end.unix()) };
|
|
ntopng_events_manager.emit_event(ntopng_events.EPOCH_CHANGE, new_epoch_status, this.id);
|
|
this.$emit('zoom', new_epoch_status);
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
.dygraph-legend {
|
|
color: var(--ntop-text-color);
|
|
background-color: var(--timeseries-legend-bg-color) !important;
|
|
border-color: var(--timeseries-legend-border-color);
|
|
border-style: solid;
|
|
border-width: thin;
|
|
z-index: 80 !important;
|
|
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, .15);
|
|
border-radius: 0.375rem;
|
|
position: fixed;
|
|
width: auto;
|
|
word-wrap: break-word;
|
|
padding: 8px !important;
|
|
}
|
|
|
|
.dygraph-legend>span {
|
|
color: #111111;
|
|
padding-left: 5px;
|
|
padding-right: 2px;
|
|
margin-left: -5px;
|
|
background-color: #FFFFFF !important;
|
|
}
|
|
|
|
.dygraph-legend>span:first-child {
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.dygraph-axis-label {
|
|
z-index: 10;
|
|
line-height: normal;
|
|
overflow: hidden;
|
|
color: var(--ntop-text-color);
|
|
}
|
|
</style>
|