iobroker.lovelace
Version:
With this adapter you can build visualization for ioBroker with Home Assistant Lovelace UI
182 lines (169 loc) • 6.01 kB
JavaScript
/**
* Class to handle dashboards.
*
* It keeps an array of dashboards and delivers it to the frontend, if asked for.
*/
class DashboardModule {
_dashboards = [];
//store config with url_path as key.
_dashboardConfigs = {};
/**
* Constructor
*
* @param options {object} options including adapter.
*/
constructor(options) {
this.adapter = options.adapter;
this.sendResponse = options.sendResponse;
this.sendUpdate = options.sendUpdate;
}
/**
* Load the entity registry from the ioBroker object database
*
* @returns {Promise<void>}
*/
async loadDashboards() {
const storage = await this.adapter.getObjectAsync('dashboardStorage');
this._dashboards = storage?.native?.dashboards || [];
this._dashboardConfigs = storage?.native?.dashboardConfigs || {};
}
/**
* Store the entity registry from the ioBroker object database
*
* @returns {Promise<void>}
*/
async saveDashboards() {
const storage = await this.adapter.getObjectAsync('dashboardStorage');
if (!storage.native) {
storage.native = {};
}
storage.native.dashboards = this._dashboards;
storage.native.dashboardConfigs = this._dashboardConfigs;
await this.adapter.setObject('dashboardStorage', storage);
}
/**
* Add a dashboard config to the storage.
*
* @param urlPath {string} the url path of the dashboard
* @returns object with the dashboard config
*/
getConfig(urlPath) {
if (this._dashboardConfigs[urlPath]) {
return this._dashboardConfigs[urlPath];
}
return { views: [] };
}
/**
* Store a dashboard config to the storage.
*
* @param urlPath {string} the url path of the dashboard
* @param config {object} the dashboard config
* @returns {Promise<void>}
*/
async storeConfig(urlPath, config) {
this._dashboardConfigs[urlPath] = config;
await this.saveDashboards();
}
/**
* Search a unique id for the dashboard.
*
* @param dashboard {object} the dashboard to search an id for.
* @returns {string} the unique id for the dashboard
*/
findDashboardId(dashboard) {
if (dashboard.id) {
// if the dashboard has an id, use it
return dashboard.id;
}
let id = `dashboard_${dashboard.title.toLowerCase().replace(/[^a-z0-9]/g, '_')}`;
id = id.replace(/_+/g, '_');
let dashboards = this._dashboards.filter(d => d.id === id);
let num = 1;
while (dashboards.length > 0) {
id = `${id}_${num}`;
dashboards = this._dashboards.filter(d => d.id === id);
num += 1;
}
return id;
}
/**
* Add dashboards to the panels array.
*
* @param panels {Array} the panels array to add the dashboards to
*/
addDashboardsToPanels(panels) {
for (const dashboard of this._dashboards) {
panels[dashboard.url_path] = {
component_name: 'lovelace',
icon: dashboard.show_in_sidebar ? dashboard.icon : null,
title: dashboard.show_in_sidebar ? dashboard.title : null,
id: dashboard.id,
config: {
mode: dashboard.mode,
},
url_path: dashboard.url_path,
require_admin: dashboard.require_admin,
config_panel_domain: null, //hm?
};
}
}
/**
* Process incoming messages from the frontend
*
* @param ws {WebSocket} the websocket connection
* @param message {object} the message from the frontend
* @returns {Promise<boolean>} true if the message was processed, false if not
*/
async processMessage(ws, message) {
if (message.type === 'lovelace/dashboards/list') {
this.sendResponse(ws, message.id, this._dashboards);
return true;
} else if (message.type === 'lovelace/dashboards/create' || message.type === 'lovelace/dashboards/update') {
const dashboard = this._dashboards.find(d => d.id === message.dashboard_id) || {};
console.log('dashboard', message);
for (const key of Object.keys(message)) {
if (key !== 'type' && key !== 'id' && key !== 'dashboard_id') {
dashboard[key] = message[key] || dashboard[key];
}
}
if (!message.dashboard_id) {
// new dashboard
dashboard.id = this.findDashboardId(dashboard);
}
this._dashboards = this._dashboards.filter(d => d.id !== dashboard.id);
this._dashboards.push(dashboard);
await this.saveDashboards();
//notify the frontend about the new dashboard that has to be shown in sidebar.
this.sendUpdate('panels_updated');
this.sendResponse(ws, message.id, dashboard);
return true;
} else if (message.type === 'lovelace/dashboards/delete') {
const dashboardId = message.dashboard_id;
this._dashboards = this._dashboards.filter(d => d.id !== dashboardId);
await this.saveDashboards();
//notify the frontend about the new dashboard that has to be shown in sidebar.
this.sendUpdate('panels_updated');
this.sendResponse(ws, message.id, { success: true });
return true;
}
return false;
}
/**
* Clean up, save the entity registry
*
* @returns {Promise<void>}
*/
async cleanup() {
this.adapter.log.debug('cleaning up dashboards');
await this.saveDashboards();
}
/**
* Init module.
*
* @returns {Promise<void>}
*/
async init() {
await this.loadDashboards();
}
}
module.exports = DashboardModule;