dashboard: add mechanism for widget-specific data storage and restructure BaseWidget

This commit is contained in:
Stephan de Wit 2024-06-26 14:57:59 +02:00
parent 902487aecc
commit 2aeb8074d1
5 changed files with 43 additions and 17 deletions

View File

@ -290,6 +290,11 @@ class WidgetManager {
let items = this.grid.save(false);
items.forEach((item) => {
// Store widget-specific configuration
let widgetConfig = this.widgetClasses[item.id].getWidgetConfig();
if (widgetConfig) {
item['widget'] = widgetConfig;
}
// XXX the gridstack save() behavior is inconsistent with the responsive columnWidth option,
// as the calculation will return impossible values for the x, y, w and h attributes.
// For now, the gs-{x,y,w,h} attributes are a better representation of the grid for layout persistence

View File

@ -27,8 +27,8 @@
import BaseWidget from "./BaseWidget.js";
export default class BaseTableWidget extends BaseWidget {
constructor() {
super();
constructor(config) {
super(config);
this.tables = {};
this.curSize = null;

View File

@ -36,10 +36,20 @@ export default class BaseWidget {
this.eventSourceOnData = null;
}
/* Public functions */
getResizeHandles() {
return this.resizeHandles;
}
getWidgetConfig() {
if (this.config !== undefined && 'widget' in this.config) {
return this.config['widget'];
}
return false;
}
setId(id) {
this.id = id;
}
@ -48,6 +58,8 @@ export default class BaseWidget {
this.translations = translations;
}
/* Public virtual functions */
getGridOptions() {
// per-widget gridstack options override
return {};
@ -73,6 +85,22 @@ export default class BaseWidget {
this.closeEventSource();
}
onVisibilityChanged(visible) {
if (this.eventSourceUrl !== null) {
if (visible) {
this.openEventSource(this.eventSourceUrl, this.eventSourceOnData);
} else if (this.eventSource !== null) {
this.closeEventSource();
}
}
}
/* Utility/protected functions */
setWidgetConfig(config) {
this.config['widget'] = config;
}
openEventSource(url, onMessage) {
this.closeEventSource();
@ -81,7 +109,12 @@ export default class BaseWidget {
this.eventSource = new EventSource(url);
this.eventSource.onmessage = onMessage;
this.eventSource.onerror = (e) => {
if (this.eventSource.readyState == EventSource.closed) {
if (this.eventSource.readyState == EventSource.CONNECTING) {
/* Backend closed connection due to timeout, reconnect issued by browser */
return;
}
if (this.eventSource.readyState == EventSource.CLOSED) {
this.closeEventSource();
} else {
console.error('Unknown error occurred during streaming operation', e);
@ -96,16 +129,6 @@ export default class BaseWidget {
}
}
onVisibilityChanged(visible) {
if (this.eventSourceUrl !== null) {
if (visible) {
this.openEventSource(this.eventSourceUrl, this.eventSourceOnData);
} else if (this.eventSource !== null) {
this.closeEventSource();
}
}
}
/* For testing purposes */
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));

View File

@ -31,8 +31,7 @@ import BaseTableWidget from "./BaseTableWidget.js";
export default class Firewall extends BaseTableWidget {
constructor(config) {
super();
this.config = config;
super(config);
this.ifMap = {};
this.counters = {};
this.chart = null;

View File

@ -30,8 +30,7 @@ import BaseTableWidget from "./BaseTableWidget.js";
export default class LiveLog extends BaseTableWidget {
constructor(config) {
super();
this.config = config;
super(config);
}
getMarkup() {