Add options to configure entity-cards (#31)

* Add options to configure entity-cards

Closes #10.
- Option to set the type of entity card.
- Option to hide an entity card from the dashboard.

* Add hiding title cards

When all entity cards are hidden for an area or domain, the
corresponding title cards will be hidden also.

* Fix Climate Chip navigation

Closes #33

* Build production distribution
This commit is contained in:
Ferry Cools
2023-07-19 15:07:55 +02:00
committed by GitHub
parent 5bded12e70
commit 140aec854b
7 changed files with 103 additions and 86 deletions

View File

@@ -110,9 +110,9 @@ weather entity for the weather chip.
The options available are:
| Name | Type | Default | Description |
|:---------------------|:--------------------------|:--------------------------------------------------------|:--------------------------------------------------------------------|
|:---------------------|:--------------------------|:--------------------------------------------------------|:---------------------------------------------------------------|
| `areas` | object (optional) | unset | One or more areas in a list, see [areas object](#area-object). |
| `entity_config` | array of cards (optional) | unset | Card definition for an entity, see [entity config](#entity-config). |
| `card_options` | object (optional) | unset | Card options for an entity, see [Card Options](#card-options). |
| `views` | object (optional) | All default views | See available [Pre-built views](#pre-built-views). |
| `chips` | object | All count chips enabled with auto selected weather card | See [chips](#chips). |
| `quick_access_cards` | array of cards (optional) | unset | List of cards to show between welcome card and rooms cards. |
@@ -200,9 +200,9 @@ This area is enabled by default and includes the entities that aren't linked to
The area can be configured like any other area as described above.
To exclude this area from the dashboard and views, set its property `hidden` to `true`.
### Entity Config
### Card Options
The `entity_config` essentially enables you to give a specific entity any card you wish.
The `card_options` entry enables you to specify a card type for an entity or to hide the card from the dashboard.
#### Example
@@ -210,9 +210,11 @@ The `entity_config` essentially enables you to give a specific entity any card y
strategy:
type: custom:mushroom-strategy
options:
entity_config:
- entity: fan.master_bedroom_fan
card_options:
fan.master_bedroom_fan:
type: custom:mushroom-fan-card
remote.harmony_hub_wk:
hidden: true
views: [ ]
```
@@ -419,9 +421,11 @@ strategy:
front_door_id:
name: Front Door
icon: mdi:door-closed
entity_config:
- entity: fan.master_bedroom_fan
card_options:
fan.master_bedroom_fan:
type: custom:mushroom-fan-card
remote.harmony_hub_wk:
hidden: true
quick_access_cards:
- type: custom:mushroom-title-card
title: Security

File diff suppressed because one or more lines are too long

View File

@@ -26,7 +26,7 @@ class AreaCard extends AbstractCard {
},
hold_action: {
action: "none",
}
},
};
/**

View File

@@ -26,7 +26,11 @@ class ClimateChip {
content: Helper.getCountTemplate("climate", "ne", "off"),
tap_action: {
action: "navigate",
navigation_path: "thermostats",
navigation_path: "climates",
},
hold_action: {
action: "navigate",
navigation_path: "climates",
},
};
}

View File

@@ -57,7 +57,6 @@ class MushroomStrategy {
type: "custom:mushroom-strategy",
options: {
area,
"entity_config": Helper.strategyOptions.entity_config,
},
},
});
@@ -87,9 +86,6 @@ class MushroomStrategy {
const exposedDomainIds = Helper.getExposedDomainIds();
const area = info.view.strategy.options.area;
const viewCards = [...(area.extra_cards ?? [])];
const strategyOptions = {
entityConfig: info.view.strategy.options.entity_config,
};
// Create cards for each domain.
for (const domain of exposedDomainIds) {
@@ -110,7 +106,7 @@ class MushroomStrategy {
// Create a Title card for the current domain.
const titleCard = new TitleCard(
[area],
Helper.strategyOptions.domains[domain]
Helper.strategyOptions.domains[domain],
).createCard();
if (domain === "sensor") {
@@ -119,43 +115,44 @@ class MushroomStrategy {
const sensorCards = [];
for (const sensor of entities) {
let card = (strategyOptions.entityConfig?.find(config => config.entity_id === sensor.entity_id));
if (card) {
sensorCards.push(card);
continue;
}
// Find the state of the current sensor.
const sensorState = sensorStates.find(state => state.entity_id === sensor.entity_id);
let cardOptions = {};
let cardOptions = Helper.strategyOptions.card_options?.[sensor.entity_id] ?? {};
if (!cardOptions.hidden) {
if (sensorState?.attributes.unit_of_measurement) {
cardOptions = {
...{
type: "custom:mini-graph-card",
entities: [sensor.entity_id],
},
...cardOptions,
};
}
sensorCards.push(new SensorCard(sensor, cardOptions).getCard());
}
}
if (sensorCards.length) {
domainCards.push({
type: "vertical-stack",
cards: sensorCards,
});
domainCards.unshift(titleCard);
}
return domainCards;
}
// 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();
let cardOptions = Helper.strategyOptions.card_options?.[entity.entity_id] ?? {};
domainCards.push(card);
if (!cardOptions.hidden) {
domainCards.push(new cardModule[className](entity, cardOptions).getCard());
}
}
if (domain === "binary_sensor") {
@@ -172,8 +169,10 @@ class MushroomStrategy {
domainCards = horizontalCards;
}
if (domainCards.length) {
domainCards.unshift(titleCard);
}
}
return domainCards;
});
@@ -215,12 +214,13 @@ class MushroomStrategy {
const miscellaneousCards = [
new TitleCard([area], Helper.strategyOptions.domains.default).createCard(),
];
for (const entity of miscellaneousEntities) {
const card = (Helper.strategyOptions.entity_config ?? []).find(
config => config.entity === entity.entity_id,
) ?? new cardModule.MiscellaneousCard(entity).getCard();
miscellaneousCards.push(card);
for (const entity of miscellaneousEntities) {
let cardOptions = Helper.strategyOptions.card_options?.[entity.entity_id] ?? {};
if (!cardOptions.hidden) {
miscellaneousCards.push(new cardModule.MiscellaneousCard(entity, cardOptions).getCard());
}
}
return miscellaneousCards;

View File

@@ -111,7 +111,7 @@
* @typedef {Object} customStrategyOptions Custom strategy configuration.
* @property {boolean} [debug] Set to true for more verbose debugging info.
* @property {Object.<areaEntity>} [areas] List of areas.
* @property {Object[]} [entity_config] Card definition for entities.
* @property {Object.<cardOptions>} [card_options] Card options for entities.
* @property {Object.<viewEntity>} [views] List of views.
* @property {Object.<domainEntity>} [domains] List of domains.
* @property {chip[]} [chips] List of chips to show in the Home view.
@@ -134,9 +134,9 @@
*/
/**
* @typedef {Object} entityConfig Custom card-configuration for an entity on a view card.
* @property {string} entity The id of the entity to create a card for.
* @typedef {Object} cardOptions Custom card-configuration for an entity.
* @property {string} type Type of card for the entity
* @property {boolean} hidden True if the entity should be hidden from the dashboard.
* @memberOf typedefs.generic
*/

View File

@@ -63,7 +63,7 @@ class AbstractView {
*
* @return {Object[] | Promise} An array of card objects.
*/
createViewCards() {
async createViewCards() {
/** @type Object[] */
const viewCards = [this.viewTitleCard];
@@ -72,33 +72,42 @@ class AbstractView {
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(),
);
const cardModule = await import(`../cards/${className}`);
// 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();
let cardOptions = Helper.strategyOptions.card_options?.[entity.entity_id] ?? {};
areaCards.push(card);
if (cardOptions.hidden) {
continue;
}
areaCards.push(new cardModule[className](entity, cardOptions).getCard());
}
});
if (areaCards.length) {
// Create a Title card for the current area if it has entities.
areaCards.unshift(new TitleCard(
[area],
{
title: area.name,
...this.options["titleCard"],
},
this["domain"],
).createCard());
viewCards.push({
type: "vertical-stack",
cards: areaCards,
});
}
}
viewCards.unshift(viewCards.length ? this.viewTitleCard : {
type: "custom:mushroom-title-card",
title: "No Entities Available",
subtitle: "They're either hidden by the configuration or by Home Assistant.",
});
return viewCards;
}