diff --git a/src/cards/AbstractCard.ts b/src/cards/AbstractCard.ts index c5524ad..f2adcbd 100644 --- a/src/cards/AbstractCard.ts +++ b/src/cards/AbstractCard.ts @@ -1,59 +1,59 @@ -import {Helper} from "../Helper"; -import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config"; -import {cards} from "../types/strategy/cards"; -import {generic} from "../types/strategy/generic"; +import { Registry } from '../Registry'; +import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config'; +import { AbstractCardConfig } from '../types/strategy/strategy-cards'; +import { RegistryEntry } from '../types/strategy/strategy-generics'; +import { logMessage, lvlFatal } from '../utilities/debug'; /** * Abstract Card Class * - * To create a new card, extend the new class with this one. + * To create a card configuration, this class should be extended by a child class. + * Child classes should override the default configuration so the card correctly reflects the entity. * - * @class - * @abstract + * @remarks + * Before using this class, the Registry module must be initialized by calling {@link Registry.initialize}. */ abstract class AbstractCard { - /** - * Entity to create the card for. - * - * @type {generic.RegistryEntry} - */ - entity: generic.RegistryEntry; + /** The registry entry this card represents. */ + readonly entity: RegistryEntry; /** - * Configuration of the card. + * The card configuration for this entity. * - * @type {EntityCardConfig} + * Child classes should override this property to reflect their own card type and options. */ - config: EntityCardConfig = { - type: "custom:mushroom-entity-card", - icon: "mdi:help-circle", + configuration: EntityCardConfig = { + type: 'custom:mushroom-entity-card', + icon: 'mdi:help-circle', }; /** * Class constructor. * - * @param {generic.RegistryEntry} entity The hass entity to create a card for. - * @throws {Error} If the Helper module isn't initialized. + * @param {RegistryEntry} entity The registry entry to create a card configuration for. + * + * @remarks + * Before this class can be used, the Registry module must be initialized by calling {@link Registry.initialize}. */ - protected constructor(entity: generic.RegistryEntry) { - if (!Helper.isInitialized()) { - throw new Error("The Helper module must be initialized before using this one."); + protected constructor(entity: RegistryEntry) { + if (!Registry.initialized) { + logMessage(lvlFatal, 'Registry not initialized!'); } this.entity = entity; } /** - * Get a card. + * Get a card configuration. * - * @returns {cards.AbstractCardConfig} A card object. + * The configuration should be set by any of the child classes so the card correctly reflects an entity. */ - getCard(): cards.AbstractCardConfig { + getCard(): AbstractCardConfig { return { - ...this.config, - entity: "entity_id" in this.entity ? this.entity.entity_id : undefined, + ...this.configuration, + entity: 'entity_id' in this.entity ? this.entity.entity_id : undefined, }; } } -export {AbstractCard}; +export default AbstractCard; diff --git a/src/cards/CameraCard.ts b/src/cards/CameraCard.ts index 812ec81..161ca45 100644 --- a/src/cards/CameraCard.ts +++ b/src/cards/CameraCard.ts @@ -1,44 +1,37 @@ -import {AbstractCard} from "./AbstractCard"; -import {cards} from "../types/strategy/cards"; -import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry"; -import {PictureEntityCardConfig} from "../types/homeassistant/panels/lovelace/cards/types"; - // noinspection JSUnusedGlobalSymbols Class is dynamically imported. + +import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; +import { PictureEntityCardConfig } from '../types/homeassistant/panels/lovelace/cards/types'; +import AbstractCard from './AbstractCard'; + /** * Camera Card Class * - * Used to create a card for controlling an entity of the camera domain. - * - * @class - * @extends AbstractCard + * Used to create a card configuration to control an entity of the camera domain. */ class CameraCard extends AbstractCard { - /** - * Default configuration of the card. - * - * @type {PictureEntityCardConfig} - * @private - */ - #defaultConfig: PictureEntityCardConfig = { - entity: "", - type: "picture-entity", - show_name: false, - show_state: false, - camera_view: "live", - }; + /** Returns the default configuration object for the card. */ + static getDefaultConfig(): PictureEntityCardConfig { + return { + entity: '', + type: 'picture-entity', + show_name: false, + show_state: false, + camera_view: 'live', + }; + } /** * Class constructor. * - * @param {EntityRegistryEntry} entity The hass entity to create a card for. - * @param {cards.PictureEntityCardOptions} [options={}] Options for the card. - * @throws {Error} If the Helper module isn't initialized. + * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. + * @param {PictureEntityCardConfig} [customConfiguration] Custom card configuration. */ - constructor(entity: EntityRegistryEntry, options: cards.PictureEntityCardOptions = {}) { + constructor(entity: EntityRegistryEntry, customConfiguration?: PictureEntityCardConfig) { super(entity); - this.config = Object.assign(this.config, this.#defaultConfig, options); + this.configuration = { ...this.configuration, ...CameraCard.getDefaultConfig(), ...customConfiguration }; } } -export {CameraCard}; +export default CameraCard; diff --git a/src/cards/HaAreaCard.ts b/src/cards/HaAreaCard.ts index ce31b34..4bdca38 100644 --- a/src/cards/HaAreaCard.ts +++ b/src/cards/HaAreaCard.ts @@ -1,49 +1,45 @@ -import {AbstractCard} from "./AbstractCard"; -import {cards} from "../types/strategy/cards"; -import {AreaRegistryEntry} from "../types/homeassistant/data/area_registry"; -import {AreaCardConfig} from "../types/homeassistant/panels/lovelace/cards/types"; - // noinspection JSUnusedGlobalSymbols Class is dynamically imported. + +import { AreaRegistryEntry } from '../types/homeassistant/data/area_registry'; +import { AreaCardConfig } from '../types/homeassistant/panels/lovelace/cards/types'; +import AbstractCard from './AbstractCard'; + /** * HA Area Card Class * - * Used to create a card for an entity of the area domain using the built-in type 'area'. - * - * @class - * @extends AbstractCard + * Used to create card configuration for an entry of the HASS area registry. */ class AreaCard extends AbstractCard { - /** - * Default configuration of the card. - * - * @type {AreaCardConfig} - * @private - */ - #defaultConfig: AreaCardConfig = { - type: "area", - area: "", - }; + /** Returns the default configuration object for the card. */ + static getDefaultConfig(): AreaCardConfig { + return { + type: 'area', + area: '', + }; + } /** * Class constructor. * - * @param {AreaRegistryEntry} area The area entity to create a card for. - * @param {cards.AreaCardOptions} [options={}] Options for the card. - * @throws {Error} If the Helper module isn't initialized. + * @param {AreaRegistryEntry} area The HASS entity to create a card configuration for. + * @param {AreaCardConfig} [customConfiguration] Custom card configuration. */ - - constructor(area: AreaRegistryEntry, options: cards.AreaCardOptions = {}) { + constructor(area: AreaRegistryEntry, customConfiguration?: AreaCardConfig) { super(area); // Initialize the default configuration. - this.#defaultConfig.area = area.area_id; - this.#defaultConfig.navigation_path = this.#defaultConfig.area; + const configuration = AreaCard.getDefaultConfig(); - // Enforce the card type. - delete options.type; + configuration.area = area.area_id; + configuration.navigation_path = configuration.area; - this.config = Object.assign(this.config, this.#defaultConfig, options); + this.configuration = { + ...this.configuration, + ...configuration, + ...customConfiguration, + type: configuration.type, // Enforce the card type. + }; } } -export {AreaCard}; +export default AreaCard; diff --git a/src/cards/LightCard.ts b/src/cards/LightCard.ts index c6e4415..1da21f8 100644 --- a/src/cards/LightCard.ts +++ b/src/cards/LightCard.ts @@ -2,7 +2,7 @@ import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; import { LightCardConfig } from '../types/lovelace-mushroom/cards/light-card-config'; -import { isCallServiceActionConfig } from '../types/strategy/strategy-generics'; +import { isCallServiceActionConfig, isCallServiceActionTarget } from '../types/strategy/strategy-generics'; import AbstractCard from './AbstractCard'; /** @@ -44,8 +44,11 @@ class LightCard extends AbstractCard { const configuration = LightCard.getDefaultConfig(); - if (isCallServiceActionConfig(configuration.double_tap_action)) { - configuration.double_tap_action.target = { entity_id: entity.entity_id }; + if ( + isCallServiceActionConfig(configuration.double_tap_action) && + isCallServiceActionTarget(configuration.double_tap_action.target) + ) { + configuration.double_tap_action.target.entity_id = entity.entity_id; } this.configuration = { ...this.configuration, ...configuration, ...customConfiguration }; diff --git a/src/cards/SceneCard.ts b/src/cards/SceneCard.ts index 5bd9729..4a4706f 100644 --- a/src/cards/SceneCard.ts +++ b/src/cards/SceneCard.ts @@ -3,27 +3,27 @@ import { Registry } from '../Registry'; import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config'; +import { isCallServiceActionConfig, isCallServiceActionTarget } from '../types/strategy/strategy-generics'; import AbstractCard from './AbstractCard'; -import SwitchCard from './SwitchCard'; -import { isCallServiceActionConfig } from '../types/strategy/strategy-generics'; /** * Scene Card Class * * Used to create a card configuration to control an entity of the scene domain. - * - * Supports Stateful scenes from https://github.com/hugobloem/stateful_scenes. - * If the stateful scene entity is available, it will be used instead of the original scene entity. */ class SceneCard extends AbstractCard { /** Returns the default configuration object for the card. */ static getDefaultConfig(): EntityCardConfig { return { type: 'custom:mushroom-entity-card', + icon: 'mdi:palette', + icon_color: 'blue', tap_action: { - action: 'perform-action', + action: 'call-service', perform_action: 'scene.turn_on', - target: {}, + target: { + entity_id: undefined, + }, }, }; } @@ -35,25 +35,16 @@ class SceneCard extends AbstractCard { * @param {EntityCardConfig} [customConfiguration] Custom card configuration. */ constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) { - const sceneName = entity.entity_id.split('.').pop(); - const statefulScene = Registry.entities.find((entity) => entity.entity_id === `switch.${sceneName}_stateful_scene`); + super(entity); - super(statefulScene ?? entity); - - // Stateful scene support. - if (statefulScene) { - this.configuration = new SwitchCard(statefulScene).getCard(); - - return; - } - - // Initialize the default configuration. const configuration = SceneCard.getDefaultConfig(); - if (isCallServiceActionConfig(configuration.tap_action)) { - configuration.tap_action.target = { entity_id: entity.entity_id }; + if ( + isCallServiceActionConfig(configuration.tap_action) && + isCallServiceActionTarget(configuration.tap_action.target) + ) { + configuration.tap_action.target.entity_id = entity.entity_id; } - configuration.icon = Registry.hassStates[entity.entity_id]?.attributes.icon ?? configuration.icon; this.configuration = { ...this.configuration, ...configuration, ...customConfiguration };