forked from DigiLive/mushroom-strategy
Merge branch 'main' into camera-fix
This commit is contained in:
7
.github/ISSUE_TEMPLATE/bug_report.md
vendored
7
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -10,6 +10,12 @@ assignees: ''
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Versions**
|
||||
* Mushroom-Strategy:
|
||||
* HACS:
|
||||
* Mushroom:
|
||||
* Home Assistant:
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
@@ -23,6 +29,5 @@ A clear and concise description of what you expected to happen.
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
36
README.md
36
README.md
@@ -109,16 +109,16 @@ 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). |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `domains` | object (optional) | All supported domains | See [Supported domains](#supported-domains). |
|
||||
| Name | Type | Default | Description |
|
||||
|:---------------------|:--------------------------|:--------------------------------------------------------|:---------------------------------------------------------------|
|
||||
| `areas` | object (optional) | unset | One or more areas in a list, see [areas object](#area-object). |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `domains` | object (optional) | All supported domains | See [Supported domains](#supported-domains). |
|
||||
|
||||
#### 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.
|
||||
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
|
||||
|
@@ -26,7 +26,7 @@ class AreaCard extends AbstractCard {
|
||||
},
|
||||
hold_action: {
|
||||
action: "none",
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -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",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@@ -57,7 +57,6 @@ class MushroomStrategy {
|
||||
type: "custom:mushroom-strategy",
|
||||
options: {
|
||||
area,
|
||||
"entity_config": Helper.strategyOptions.entity_config,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -84,12 +83,9 @@ class MushroomStrategy {
|
||||
* @return {Promise<{cards: Object[]}>}
|
||||
*/
|
||||
static async generateView(info) {
|
||||
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,
|
||||
};
|
||||
const exposedDomainIds = Helper.getExposedDomainIds();
|
||||
const area = info.view.strategy.options.area;
|
||||
const viewCards = [...(area.extra_cards ?? [])];
|
||||
|
||||
// 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 (sensorState?.attributes.unit_of_measurement) {
|
||||
cardOptions = {
|
||||
type: "custom:mini-graph-card",
|
||||
entities: [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());
|
||||
}
|
||||
|
||||
sensorCards.push(new SensorCard(sensor, cardOptions).getCard());
|
||||
}
|
||||
|
||||
domainCards.push({
|
||||
type: "vertical-stack",
|
||||
cards: sensorCards,
|
||||
});
|
||||
if (sensorCards.length) {
|
||||
domainCards.push({
|
||||
type: "vertical-stack",
|
||||
cards: sensorCards,
|
||||
});
|
||||
|
||||
domainCards.unshift(titleCard);
|
||||
}
|
||||
|
||||
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,7 +169,9 @@ class MushroomStrategy {
|
||||
domainCards = horizontalCards;
|
||||
}
|
||||
|
||||
domainCards.unshift(titleCard);
|
||||
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;
|
||||
|
@@ -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
|
||||
*/
|
||||
|
||||
|
@@ -63,43 +63,52 @@ class AbstractView {
|
||||
*
|
||||
* @return {Object[] | Promise} An array of card objects.
|
||||
*/
|
||||
createViewCards() {
|
||||
async 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");
|
||||
const areaCards = [];
|
||||
const entities = Helper.getDeviceEntities(area, this["domain"]);
|
||||
const className = Helper.sanitizeClassName(this["domain"] + "Card");
|
||||
const cardModule = await import(`../cards/${className}`);
|
||||
|
||||
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) {
|
||||
let cardOptions = Helper.strategyOptions.card_options?.[entity.entity_id] ?? {};
|
||||
|
||||
// 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);
|
||||
}
|
||||
if (cardOptions.hidden) {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
|
||||
viewCards.push({
|
||||
type: "vertical-stack",
|
||||
cards: areaCards,
|
||||
});
|
||||
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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user