mirror of
https://github.com/DigiLive/mushroom-strategy.git
synced 2025-08-04 20:14:28 +02:00
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:
36
README.md
36
README.md
@@ -109,16 +109,16 @@ weather entity for the weather chip.
|
|||||||
|
|
||||||
The options available are:
|
The options available are:
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
|:---------------------|:--------------------------|:--------------------------------------------------------|:--------------------------------------------------------------------|
|
|:---------------------|:--------------------------|:--------------------------------------------------------|:---------------------------------------------------------------|
|
||||||
| `areas` | object (optional) | unset | One or more areas in a list, see [areas object](#area-object). |
|
| `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). |
|
| `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). |
|
| `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. |
|
| `quick_access_cards` | array of cards (optional) | unset | List of cards to show between welcome card and rooms cards. |
|
||||||
| `extra_cards` | array of cards (optional | unset | List of cards to show below room cards. |
|
| `extra_cards` | array of cards (optional | unset | List of cards to show below room cards. |
|
||||||
| `extra_views` | array of views (optional) | unset | List of views to add to the dashboard. |
|
| `extra_views` | array of views (optional) | unset | List of views to add to the dashboard. |
|
||||||
| `domains` | object (optional) | All supported domains | See [Supported domains](#supported-domains). |
|
| `domains` | object (optional) | All supported domains | See [Supported domains](#supported-domains). |
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
@@ -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.
|
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`.
|
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
|
#### Example
|
||||||
|
|
||||||
@@ -210,9 +210,11 @@ The `entity_config` essentially enables you to give a specific entity any card y
|
|||||||
strategy:
|
strategy:
|
||||||
type: custom:mushroom-strategy
|
type: custom:mushroom-strategy
|
||||||
options:
|
options:
|
||||||
entity_config:
|
card_options:
|
||||||
- entity: fan.master_bedroom_fan
|
fan.master_bedroom_fan:
|
||||||
type: custom:mushroom-fan-card
|
type: custom:mushroom-fan-card
|
||||||
|
remote.harmony_hub_wk:
|
||||||
|
hidden: true
|
||||||
views: [ ]
|
views: [ ]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -419,9 +421,11 @@ strategy:
|
|||||||
front_door_id:
|
front_door_id:
|
||||||
name: Front Door
|
name: Front Door
|
||||||
icon: mdi:door-closed
|
icon: mdi:door-closed
|
||||||
entity_config:
|
card_options:
|
||||||
- entity: fan.master_bedroom_fan
|
fan.master_bedroom_fan:
|
||||||
type: custom:mushroom-fan-card
|
type: custom:mushroom-fan-card
|
||||||
|
remote.harmony_hub_wk:
|
||||||
|
hidden: true
|
||||||
quick_access_cards:
|
quick_access_cards:
|
||||||
- type: custom:mushroom-title-card
|
- type: custom:mushroom-title-card
|
||||||
title: Security
|
title: Security
|
||||||
|
2
dist/mushroom-strategy.js
vendored
2
dist/mushroom-strategy.js
vendored
File diff suppressed because one or more lines are too long
@@ -26,7 +26,7 @@ class AreaCard extends AbstractCard {
|
|||||||
},
|
},
|
||||||
hold_action: {
|
hold_action: {
|
||||||
action: "none",
|
action: "none",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -26,7 +26,11 @@ class ClimateChip {
|
|||||||
content: Helper.getCountTemplate("climate", "ne", "off"),
|
content: Helper.getCountTemplate("climate", "ne", "off"),
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "navigate",
|
action: "navigate",
|
||||||
navigation_path: "thermostats",
|
navigation_path: "climates",
|
||||||
|
},
|
||||||
|
hold_action: {
|
||||||
|
action: "navigate",
|
||||||
|
navigation_path: "climates",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -57,7 +57,6 @@ class MushroomStrategy {
|
|||||||
type: "custom:mushroom-strategy",
|
type: "custom:mushroom-strategy",
|
||||||
options: {
|
options: {
|
||||||
area,
|
area,
|
||||||
"entity_config": Helper.strategyOptions.entity_config,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -84,12 +83,9 @@ class MushroomStrategy {
|
|||||||
* @return {Promise<{cards: Object[]}>}
|
* @return {Promise<{cards: Object[]}>}
|
||||||
*/
|
*/
|
||||||
static async generateView(info) {
|
static async generateView(info) {
|
||||||
const exposedDomainIds = Helper.getExposedDomainIds();
|
const exposedDomainIds = Helper.getExposedDomainIds();
|
||||||
const area = info.view.strategy.options.area;
|
const area = info.view.strategy.options.area;
|
||||||
const viewCards = [...(area.extra_cards ?? [])];
|
const viewCards = [...(area.extra_cards ?? [])];
|
||||||
const strategyOptions = {
|
|
||||||
entityConfig: info.view.strategy.options.entity_config,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create cards for each domain.
|
// Create cards for each domain.
|
||||||
for (const domain of exposedDomainIds) {
|
for (const domain of exposedDomainIds) {
|
||||||
@@ -110,7 +106,7 @@ class MushroomStrategy {
|
|||||||
// Create a Title card for the current domain.
|
// Create a Title card for the current domain.
|
||||||
const titleCard = new TitleCard(
|
const titleCard = new TitleCard(
|
||||||
[area],
|
[area],
|
||||||
Helper.strategyOptions.domains[domain]
|
Helper.strategyOptions.domains[domain],
|
||||||
).createCard();
|
).createCard();
|
||||||
|
|
||||||
if (domain === "sensor") {
|
if (domain === "sensor") {
|
||||||
@@ -119,43 +115,44 @@ class MushroomStrategy {
|
|||||||
const sensorCards = [];
|
const sensorCards = [];
|
||||||
|
|
||||||
for (const sensor of entities) {
|
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.
|
// Find the state of the current sensor.
|
||||||
const sensorState = sensorStates.find(state => state.entity_id === sensor.entity_id);
|
const sensorState = sensorStates.find(state => state.entity_id === sensor.entity_id);
|
||||||
let cardOptions = {};
|
let cardOptions = Helper.strategyOptions.card_options?.[sensor.entity_id] ?? {};
|
||||||
|
|
||||||
if (sensorState?.attributes.unit_of_measurement) {
|
if (!cardOptions.hidden) {
|
||||||
cardOptions = {
|
if (sensorState?.attributes.unit_of_measurement) {
|
||||||
type: "custom:mini-graph-card",
|
cardOptions = {
|
||||||
entities: [sensor.entity_id],
|
...{
|
||||||
};
|
type: "custom:mini-graph-card",
|
||||||
|
entities: [sensor.entity_id],
|
||||||
|
},
|
||||||
|
...cardOptions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sensorCards.push(new SensorCard(sensor, cardOptions).getCard());
|
||||||
}
|
}
|
||||||
|
|
||||||
sensorCards.push(new SensorCard(sensor, cardOptions).getCard());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
domainCards.push({
|
if (sensorCards.length) {
|
||||||
type: "vertical-stack",
|
domainCards.push({
|
||||||
cards: sensorCards,
|
type: "vertical-stack",
|
||||||
});
|
cards: sensorCards,
|
||||||
|
});
|
||||||
|
|
||||||
|
domainCards.unshift(titleCard);
|
||||||
|
}
|
||||||
|
|
||||||
domainCards.unshift(titleCard);
|
|
||||||
return domainCards;
|
return domainCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a card for each domain-entity of the current area.
|
// Create a card for each domain-entity of the current area.
|
||||||
for (const entity of entities) {
|
for (const entity of entities) {
|
||||||
const card = (Helper.strategyOptions.entity_config ?? []).find(
|
let cardOptions = Helper.strategyOptions.card_options?.[entity.entity_id] ?? {};
|
||||||
config => config.entity === entity.entity_id,
|
|
||||||
) ?? new cardModule[className](entity).getCard();
|
|
||||||
|
|
||||||
domainCards.push(card);
|
if (!cardOptions.hidden) {
|
||||||
|
domainCards.push(new cardModule[className](entity, cardOptions).getCard());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (domain === "binary_sensor") {
|
if (domain === "binary_sensor") {
|
||||||
@@ -172,7 +169,9 @@ class MushroomStrategy {
|
|||||||
domainCards = horizontalCards;
|
domainCards = horizontalCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
domainCards.unshift(titleCard);
|
if (domainCards.length) {
|
||||||
|
domainCards.unshift(titleCard);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return domainCards;
|
return domainCards;
|
||||||
@@ -215,12 +214,13 @@ class MushroomStrategy {
|
|||||||
const miscellaneousCards = [
|
const miscellaneousCards = [
|
||||||
new TitleCard([area], Helper.strategyOptions.domains.default).createCard(),
|
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;
|
return miscellaneousCards;
|
||||||
|
@@ -111,7 +111,7 @@
|
|||||||
* @typedef {Object} customStrategyOptions Custom strategy configuration.
|
* @typedef {Object} customStrategyOptions Custom strategy configuration.
|
||||||
* @property {boolean} [debug] Set to true for more verbose debugging info.
|
* @property {boolean} [debug] Set to true for more verbose debugging info.
|
||||||
* @property {Object.<areaEntity>} [areas] List of areas.
|
* @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.<viewEntity>} [views] List of views.
|
||||||
* @property {Object.<domainEntity>} [domains] List of domains.
|
* @property {Object.<domainEntity>} [domains] List of domains.
|
||||||
* @property {chip[]} [chips] List of chips to show in the Home view.
|
* @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.
|
* @typedef {Object} cardOptions Custom card-configuration for an entity.
|
||||||
* @property {string} entity The id of the entity to create a card for.
|
|
||||||
* @property {string} type Type of card for the 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
|
* @memberOf typedefs.generic
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -63,43 +63,52 @@ class AbstractView {
|
|||||||
*
|
*
|
||||||
* @return {Object[] | Promise} An array of card objects.
|
* @return {Object[] | Promise} An array of card objects.
|
||||||
*/
|
*/
|
||||||
createViewCards() {
|
async createViewCards() {
|
||||||
/** @type Object[] */
|
/** @type Object[] */
|
||||||
const viewCards = [this.viewTitleCard];
|
const viewCards = [this.viewTitleCard];
|
||||||
|
|
||||||
// Create cards for each area.
|
// Create cards for each area.
|
||||||
for (const area of Helper.areas) {
|
for (const area of Helper.areas) {
|
||||||
const areaCards = [];
|
const areaCards = [];
|
||||||
const entities = Helper.getDeviceEntities(area, this["domain"]);
|
const entities = Helper.getDeviceEntities(area, this["domain"]);
|
||||||
const className = Helper.sanitizeClassName(this["domain"] + "Card");
|
const className = Helper.sanitizeClassName(this["domain"] + "Card");
|
||||||
|
const cardModule = await import(`../cards/${className}`);
|
||||||
|
|
||||||
import((`../cards/${className}`)).then(cardModule => {
|
// Create a card for each domain-entity of the current area.
|
||||||
if (entities.length) {
|
for (const entity of entities) {
|
||||||
// Create a Title card for the current area.
|
let cardOptions = Helper.strategyOptions.card_options?.[entity.entity_id] ?? {};
|
||||||
areaCards.push(
|
|
||||||
new TitleCard([area], {
|
|
||||||
title: area.name,
|
|
||||||
...this.options["titleCard"],
|
|
||||||
}).createCard(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create a card for each domain-entity of the current area.
|
if (cardOptions.hidden) {
|
||||||
for (const entity of entities) {
|
continue;
|
||||||
const card = (Helper.strategyOptions.entity_config ?? []).find(
|
|
||||||
config => config.entity === entity.entity_id,
|
|
||||||
) ?? new cardModule[className](entity).getCard();
|
|
||||||
|
|
||||||
areaCards.push(card);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
viewCards.push({
|
areaCards.push(new cardModule[className](entity, cardOptions).getCard());
|
||||||
type: "vertical-stack",
|
}
|
||||||
cards: areaCards,
|
|
||||||
});
|
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;
|
return viewCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user