Files
mushroom-strategy/src/views/AbstractView.js

122 lines
2.9 KiB
JavaScript
Raw Normal View History

Code Cleanup (#7) Refactor the code base from Procedural to Object-Oriented Programming. The new code base requires webpack (https://webpack.js.org/) to bundle the code into a single javascript file. Webpack can be installed with npm, using file `package-lock.json` or `package.json`. File `package.json` contains two script entries: * `build` for a *release* build (uses file`webpack.config.js`). * `build-dev` for a *debug* build (uses file `webpack.dev.config.js`). Both of the scripts will bundle the separate package files into a single javascript file in the `dist` directory. Includes fixes and changes: * The release badge in readme now displays the latest release version. * Optimize function `getStateEntities()`. * Implement #11. * Merge Home Assistant and User-defined areas. * Add contributors to readme. * Fix getCountTemplate method. The method only counted states which aren't equal to value `off`. States are now counted by specifying a comparison operator and value. * Document default HACS installation. * Fix overriding sensor card configuration. Having an `entity_config` property in the strategy options resulted in overriding each sensor card. Only the cards listed under this property should be overridden. * Cut redundant properties and constants Method `generateDashboard()` passes redundant values to generateView(). Writing those values into properties and reading them into constants is removed. * Fix undefined sensorState. Not all entities (like a RESTful sensor) are bound to a device. SensorStates did contain states which meet all following conditions: 1. The linked entity is linked to the given area or isn't linked to any area. 2. The linked device is linked to the given area. SensorStates now contains states which meet any* of the following conditions: 1. The linked entity is linked to the given area or isn't linked to any area. 2. The entity is linked to a device, and the linked device is linked to the given area. *) Whichever comes first. * Add undisclosed area. * Add ordering of area-cards. Area cards are now ordered by a custom set position first and then by the area name. * Add global sorting of entities by original_name. * Add global sorting of areas by order and name. * Add global sorting of domains by order and title. * Make production build. Known Issue: Title cards or chips won't switch entities assigned to the undisclosed area.
2023-06-14 07:29:18 +02:00
import {Helper} from "../Helper";
import {TitleCard} from "../cards/TitleCard";
/**
* Abstract View Class.
*
* To create a new view, extend the new class with this one.
*
* @class
* @abstract
*/
class AbstractView {
/**
* Options for creating a view.
*
* @type {abstractOptions}
*/
options = {
title: null,
path: null,
icon: "mdi:view-dashboard",
subview: false,
};
/**
* A card to switch all entities in the view.
*
* @type {Object}
*/
viewTitleCard;
/**
* Class constructor.
*
* @throws {Error} If trying to instantiate this class.
* @throws {Error} If the Helper module isn't initialized.
*/
constructor() {
if (this.constructor === AbstractView) {
throw new Error("Abstract classes can't be instantiated.");
}
if (!Helper.isInitialized()) {
throw new Error("The Helper module must be initialized before using this one.");
}
}
/**
* Merge the default options of this class and the custom options into the options of the parent class.
*
* @param {Object} [defaultOptions={}] Default options for the card.
* @param {Object} [customOptions={}] Custom Options for the card.
*/
mergeOptions(defaultOptions, customOptions) {
this.options = {
...defaultOptions,
...customOptions,
};
}
/**
* Create the cards to include in the view.
*
* @return {Object[] | Promise} An array of card objects.
*/
createViewCards() {
/** @type Object[] */
const viewCards = [this.viewTitleCard];
// Create cards for each area.
for (const area of Helper.areas) {
const areaCards = [];
const entities = Helper.getDeviceEntities(area, this["domain"]);
const className = Helper.sanitizeClassName(this["domain"] + "Card");
import((`../cards/${className}`)).then(cardModule => {
if (entities.length) {
// Create a Title card for the current area.
areaCards.push(
new TitleCard([area], {
title: area.name,
...this.options["titleCard"],
}).createCard(),
);
// Create a card for each domain-entity of the current area.
for (const entity of entities) {
const card = (Helper.strategyOptions.entity_config ?? []).find(
config => config.entity === entity.entity_id,
) ?? new cardModule[className](entity).getCard();
areaCards.push(card);
}
}
});
viewCards.push({
type: "vertical-stack",
cards: areaCards,
});
}
return viewCards;
}
/**
* Get a view object.
*
* The view includes the cards which are created by method createViewCards().
*
* @returns {viewOptions & {cards: Object[]}} The view object.
*/
async getView() {
return {
...this.options,
cards: await this.createViewCards(),
};
}
}
export {AbstractView};