forked from DigiLive/mushroom-strategy
Add options for all areas (#52)
Area identifier `_` sets the options for all areas. Options for a specific area can still be overridden like before. Also the HA area-card is added to use as a strategy area-card. --------- Co-authored-by: DigiLive <info@digilive.nl>
This commit is contained in:
1 parent
8311fa240c
commit
98ef9fed05
8 files changed
+152
-42
No files matched your search
@@ -75,7 +75,7 @@ All the rounded cards can be configured using the Dashboard UI editor.
|
||||
```yaml
|
||||
strategy:
|
||||
type: custom:mushroom-strategy
|
||||
views: [ ]
|
||||
views: []
|
||||
```
|
||||
|
||||
### Hidding specific entities
|
||||
@@ -133,7 +133,7 @@ strategy:
|
||||
name: Family Room
|
||||
icon: mdi:sofa
|
||||
icon_color: green
|
||||
views: [ ]
|
||||
views: []
|
||||
```
|
||||
|
||||
### Area Object
|
||||
@@ -161,6 +161,7 @@ at the top of the area subview.
|
||||
| `hidden` | boolean | false | Set to `true` to exclude the area from the dashboard and views. |
|
||||
| `order` | number | Infinity | Ordering position of the area in the list of available areas. |
|
||||
| `extra_cards` | array of cards | unset or empty | A list of cards to show on the top of the area subview. |
|
||||
| `type` | string | `default` | Set to a type of area card. (Currently supported: `default` & `HaAreaCard` |
|
||||
|
||||
*) `more-info` `toggle` `call-service` `navigate` `url` `none`
|
||||
|
||||
@@ -191,7 +192,9 @@ strategy:
|
||||
order: 2
|
||||
garage_id:
|
||||
hidden: true
|
||||
views: [ ]
|
||||
hallway_id:
|
||||
type: HaAreaCard
|
||||
views: []
|
||||
```
|
||||
|
||||
#### Undisclosed Area
|
||||
@@ -202,6 +205,22 @@ 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`.
|
||||
|
||||
#### Setting options for all areas
|
||||
|
||||
Use `_` as an identifier to set the options for all areas.
|
||||
|
||||
The following example sets the type of all area-cards to Home Assistant's area card:
|
||||
|
||||
```yaml
|
||||
strategy:
|
||||
type: custom:mushroom-strategy
|
||||
options:
|
||||
areas:
|
||||
_:
|
||||
type: HaAreaCard
|
||||
views: []
|
||||
```
|
||||
|
||||
### Card Options
|
||||
|
||||
The `card_options` entry enables you to specify a card type for an entity or to hide the card from the dashboard.
|
||||
@@ -222,7 +241,7 @@ strategy:
|
||||
077ba0492c9bb3b31ffac34f1f3a626a:
|
||||
hidden: true
|
||||
|
||||
views: [ ]
|
||||
views: []
|
||||
```
|
||||
|
||||
### Pre-built views
|
||||
@@ -230,7 +249,7 @@ views: [ ]
|
||||

|
||||
|
||||
Mushroom strategy includes pre-built views to control/view specific domains.
|
||||
All devices that are in an area where `hidden` is set to false/undefined are shown.
|
||||
All devices that are in an area where `hidden` is set to false/undefined are shown.
|
||||
|
||||
By default, all pre-built views below are shown:
|
||||
|
||||
@@ -270,7 +289,7 @@ strategy:
|
||||
order: 1
|
||||
hidden: true
|
||||
icon: mdi:toggle-switch
|
||||
views: [ ]
|
||||
views: []
|
||||
```
|
||||
|
||||
### Supported domains
|
||||
@@ -312,7 +331,7 @@ strategy:
|
||||
showControls: false
|
||||
default:
|
||||
hidden: true
|
||||
views: [ ]
|
||||
views: []
|
||||
```
|
||||
|
||||
### Chips
|
||||
@@ -475,7 +494,7 @@ strategy:
|
||||
title: cool view
|
||||
path: cool-view
|
||||
icon: mdi:emoticon-cool
|
||||
badges: [ ]
|
||||
badges: []
|
||||
cards:
|
||||
- type: markdown
|
||||
content: I am cool
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
(()=>{var t,e,i={84:(t,e,i)=>{"use strict";i.d(e,{W:()=>a});const s={home:{order:1,hidden:!1},light:{order:2,hidden:!1},fan:{order:3,hidden:!1},cover:{order:4,hidden:!1},switch:{order:5,hidden:!1},climate:{order:6,hidden:!1},camera:{order:7,hidden:!1}},r={aliases:[],area_id:null,name:"Undisclosed",picture:null,hidden:!1},o={default:{title:"Miscellaneous",showControls:!1,hidden:!1},light:{title:"Lights",showControls:!0,iconOn:"mdi:lightbulb",iconOff:"mdi:lightbulb-off",onService:"light.turn_on",offService:"light.turn_off",hidden:!1},fan:{title:"Fans",showControls:!0,iconOn:"mdi:fan",iconOff:"mdi:fan-off",onService:"fan.turn_on",offService:"fan.turn_off",hidden:!1},cover:{title:"Covers",showControls:!0,iconOn:"mdi:arrow-up",iconOff:"mdi:arrow-down",onService:"cover.open_cover",offService:"cover.close_cover",hidden:!1},switch:{title:"Switches",showControls:!0,iconOn:"mdi:power-plug",iconOff:"mdi:power-plug-off",onService:"switch.turn_on",offService:"switch.turn_off",hidden:!1},camera:{title:"Cameras",showControls:!1,hidden:!1},lock:{title:"Locks",showControls:!1,hidden:!1},climate:{title:"Climates",showControls:!1,hidden:!1},media_player:{title:"Media Players",showControls:!1,hidden:!1},sensor:{title:"Sensors",showControls:!1,hidden:!1},binary_sensor:{title:"Binary Sensors",showControls:!1,hidden:!1}};class a{static#t;static#e;static#i=[];static#s;static#r=!1;static#o={};static debug=false;constructor(){throw new Error("This class should be invoked with method initialize() instead of using the keyword new!")}static get strategyOptions(){return this.#o}static get areas(){return this.#i}static get devices(){return this.#e}static get entities(){return this.#t}static get debug(){return this.debug}static async initialize(t){this.#s=t.hass.states;try{[this.#t,this.#e,this.#i]=await Promise.all([t.hass.callWS({type:"config/entity_registry/list"}),t.hass.callWS({type:"config/device_registry/list"}),t.hass.callWS({type:"config/area_registry/list"})])}catch(t){console.error(a.debug?t:"An error occurred while querying Home assistant's registries!")}this.#o=structuredClone(t.config.strategy.options||{}),this.debug=this.#o.debug,this.#o.areas=this.#o.areas??{},this.#o.views=this.#o.views??{},this.#o.domains=this.#o.domains??{},this.#o.areas.undisclosed?.hidden||(this.#o.areas.undisclosed={...r,...this.#o.areas.undisclosed},this.#o.areas.undisclosed.area_id=null,this.#i.push(this.#o.areas.undisclosed)),this.#i=a.areas.map((t=>({...t,...this.#o.areas[t.area_id??"undisclosed"]}))),this.#i.sort(((t,e)=>(t.order??1/0)-(e.order??1/0)||t.name.localeCompare(e.name)));for(const t of Object.keys(s))this.#o.views[t]={...s[t],...this.#o.views[t]};this.#o.views=Object.fromEntries(Object.entries(this.#o.views).sort((([,t],[,e])=>(t.order??1/0)-(e.order??1/0)||t.title?.localeCompare(e.title))));for(const t of Object.keys(o))this.#o.domains[t]={...o[t],...this.#o.domains[t]};this.#o.domains=Object.fromEntries(Object.entries(this.#o.domains).sort((([,t],[,e])=>(t.order??1/0)-(e.order??1/0)||t.title?.localeCompare(e.title)))),this.#r=!0}static isInitialized(){return this.#r}static getCountTemplate(t,e,i){const s=[];this.isInitialized()||console.warn("Helper class should be initialized before calling this method!");for(const e of this.#i){const i=this.#e.filter((t=>t.area_id===e.area_id)).map((t=>t.id)),r=this.#t.filter(this.#a,{area:e,domain:t,areaDeviceIds:i}).map((t=>`states['${t.entity_id}']`));s.push(...r)}return`{% set entities = [${s}] %} {{ entities | selectattr('state','${e}','${i}') | list | count }}`}static#a(t){return(this.area.area_id?this.areaDeviceIds.includes(t.device_id)||t.area_id===this.area.area_id:(this.areaDeviceIds.includes(t.device_id)||!t.device_id)&&!t.area_id)&&t.entity_id.startsWith(`${this.domain}.`)&&null==t.hidden_by&&null==t.disabled_by}static getDeviceEntities(t,e){this.isInitialized()||console.warn("Helper class should be initialized before calling this method!");const i=this.#e.filter((e=>e.area_id===t.area_id)).map((t=>t.id));return this.#t.filter(this.#a,{area:t,domain:e,areaDeviceIds:i}).sort(((t,e)=>t.original_name?.localeCompare(e.original_name)))}static getStateEntities(t,e){this.isInitialized()||console.warn("Helper class should be initialized before calling this method!");const i=[],s=Object.fromEntries(this.#t.map((t=>[t.entity_id,t]))),r=Object.fromEntries(this.#e.map((t=>[t.id,t]))),o=Object.values(this.#s).filter((t=>t.entity_id.startsWith(`${e}.`)));for(const e of o){const o=s[e.entity_id],a=r[o?.device_id];(o?.area_id===t.area_id||a&&a.area_id===t.area_id)&&i.push(e)}return i}static sanitizeClassName(t){return(t=t.charAt(0).toUpperCase()+t.slice(1)).replace(/([-_][a-z])/g,(t=>t.toUpperCase().replace("-","").replace("_","")))}static#n(t,e,i){const s=[];for(const r of Object.keys(t))t[r][e]===i&&s.push(r);return s}static getExposedViewIds(){return this.isInitialized()||console.warn("Helper class should be initialized before calling this method!"),this.#n(this.#o.views,"hidden",!1)}static getExpLine truncated
|
||||
(()=>{var t,e,i={84:(t,e,i)=>{"use strict";i.d(e,{W:()=>o});const s={home:{order:1,hidden:!1},light:{order:2,hidden:!1},fan:{order:3,hidden:!1},cover:{order:4,hidden:!1},switch:{order:5,hidden:!1},climate:{order:6,hidden:!1},camera:{order:7,hidden:!1}},r={aliases:[],area_id:null,name:"Undisclosed",picture:null,hidden:!1},a={default:{title:"Miscellaneous",showControls:!1,hidden:!1},light:{title:"Lights",showControls:!0,iconOn:"mdi:lightbulb",iconOff:"mdi:lightbulb-off",onService:"light.turn_on",offService:"light.turn_off",hidden:!1},fan:{title:"Fans",showControls:!0,iconOn:"mdi:fan",iconOff:"mdi:fan-off",onService:"fan.turn_on",offService:"fan.turn_off",hidden:!1},cover:{title:"Covers",showControls:!0,iconOn:"mdi:arrow-up",iconOff:"mdi:arrow-down",onService:"cover.open_cover",offService:"cover.close_cover",hidden:!1},switch:{title:"Switches",showControls:!0,iconOn:"mdi:power-plug",iconOff:"mdi:power-plug-off",onService:"switch.turn_on",offService:"switch.turn_off",hidden:!1},camera:{title:"Cameras",showControls:!1,hidden:!1},lock:{title:"Locks",showControls:!1,hidden:!1},climate:{title:"Climates",showControls:!1,hidden:!1},media_player:{title:"Media Players",showControls:!1,hidden:!1},sensor:{title:"Sensors",showControls:!1,hidden:!1},binary_sensor:{title:"Binary Sensors",showControls:!1,hidden:!1}};class o{static#t;static#e;static#i=[];static#s;static#r=!1;static#a={};static debug=false;constructor(){throw new Error("This class should be invoked with method initialize() instead of using the keyword new!")}static get strategyOptions(){return this.#a}static get areas(){return this.#i}static get devices(){return this.#e}static get entities(){return this.#t}static get debug(){return this.debug}static async initialize(t){this.#s=t.hass.states;try{[this.#t,this.#e,this.#i]=await Promise.all([t.hass.callWS({type:"config/entity_registry/list"}),t.hass.callWS({type:"config/device_registry/list"}),t.hass.callWS({type:"config/area_registry/list"})])}catch(t){console.error(o.debug?t:"An error occurred while querying Home assistant's registries!")}this.#a=structuredClone(t.config.strategy.options||{}),this.debug=this.#a.debug,this.#a.areas=this.#a.areas??{},this.#a.views=this.#a.views??{},this.#a.domains=this.#a.domains??{},this.#a.areas.undisclosed?.hidden||(this.#a.areas.undisclosed={...r,...this.#a.areas.undisclosed},this.#a.areas.undisclosed.area_id=null,this.#i.push(this.#a.areas.undisclosed)),this.#i=o.areas.map((t=>({...t,...this.#a.areas[t.area_id??"undisclosed"]}))),this.#i.sort(((t,e)=>(t.order??1/0)-(e.order??1/0)||t.name.localeCompare(e.name)));for(const t of Object.keys(s))this.#a.views[t]={...s[t],...this.#a.views[t]};this.#a.views=Object.fromEntries(Object.entries(this.#a.views).sort((([,t],[,e])=>(t.order??1/0)-(e.order??1/0)||t.title?.localeCompare(e.title))));for(const t of Object.keys(a))this.#a.domains[t]={...a[t],...this.#a.domains[t]};this.#a.domains=Object.fromEntries(Object.entries(this.#a.domains).sort((([,t],[,e])=>(t.order??1/0)-(e.order??1/0)||t.title?.localeCompare(e.title)))),this.#r=!0}static isInitialized(){return this.#r}static getCountTemplate(t,e,i){const s=[];this.isInitialized()||console.warn("Helper class should be initialized before calling this method!");for(const e of this.#i){const i=this.#e.filter((t=>t.area_id===e.area_id)).map((t=>t.id)),r=this.#t.filter(this.#o,{area:e,domain:t,areaDeviceIds:i}).map((t=>`states['${t.entity_id}']`));s.push(...r)}return`{% set entities = [${s}] %} {{ entities | selectattr('state','${e}','${i}') | list | count }}`}static#o(t){return(this.area.area_id?this.areaDeviceIds.includes(t.device_id)||t.area_id===this.area.area_id:(this.areaDeviceIds.includes(t.device_id)||!t.device_id)&&!t.area_id)&&t.entity_id.startsWith(`${this.domain}.`)&&null==t.hidden_by&&null==t.disabled_by}static getDeviceEntities(t,e){this.isInitialized()||console.warn("Helper class should be initialized before calling this method!");const i=this.#e.filter((e=>e.area_id===t.area_id)).map((t=>t.id));return this.#t.filter(this.#o,{area:t,domain:e,areaDeviceIds:i}).sort(((t,e)=>t.original_name?.localeCompare(e.original_name)))}static getStateEntities(t,e){this.isInitialized()||console.warn("Helper class should be initialized before calling this method!");const i=[],s=Object.fromEntries(this.#t.map((t=>[t.entity_id,t]))),r=Object.fromEntries(this.#e.map((t=>[t.id,t]))),a=Object.values(this.#s).filter((t=>t.entity_id.startsWith(`${e}.`)));for(const e of a){const a=s[e.entity_id],o=r[a?.device_id];(a?.area_id===t.area_id||o&&o.area_id===t.area_id)&&i.push(e)}return i}static sanitizeClassName(t){return(t=t.charAt(0).toUpperCase()+t.slice(1)).replace(/([-_][a-z])/g,(t=>t.toUpperCase().replace("-","").replace("_","")))}static#n(t,e,i){const s=[];for(const r of Object.keys(t))t[r][e]===i&&s.push(r);return s}static getExposedViewIds(){return this.isInitialized()||console.warn("Helper class should be initialized before calling this method!"),this.#n(this.#a.views,"hidden",!1)}static getExpLine truncated
|
||||
@@ -38,9 +38,15 @@ class AreaCard extends AbstractCard {
|
||||
*/
|
||||
constructor(area, options = {}) {
|
||||
super(area);
|
||||
|
||||
this.#defaultOptions.primary = area.name;
|
||||
this.#defaultOptions.tap_action.navigation_path = area.area_id ?? area.name;
|
||||
|
||||
// Set card type to default if a type "default" is given in strategy options.
|
||||
if (options.type === "default") {
|
||||
options.type = this.#defaultOptions.type;
|
||||
}
|
||||
|
||||
this.mergeOptions(
|
||||
this.#defaultOptions,
|
||||
options,
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
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
|
||||
*/
|
||||
class AreaCard extends AbstractCard {
|
||||
/**
|
||||
* Default options of the card.
|
||||
*
|
||||
* @type {HaAreaCardOptions}
|
||||
* @private
|
||||
*/
|
||||
#defaultOptions = {
|
||||
type: "area",
|
||||
area: undefined,
|
||||
navigation_path: undefined,
|
||||
};
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {areaEntity} area The area entity to create a card for.
|
||||
* @param {HaAreaCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
*/
|
||||
|
||||
constructor(area, options = {}) {
|
||||
super(area);
|
||||
this.#defaultOptions.area = area.area_id ?? area.name;
|
||||
this.#defaultOptions.navigation_path = area.area_id ?? area.name;
|
||||
|
||||
// Enforce the card type.
|
||||
options.type = this.#defaultOptions.type;
|
||||
|
||||
this.mergeOptions(
|
||||
this.#defaultOptions,
|
||||
options,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export {AreaCard};
|
||||
@@ -112,6 +112,13 @@
|
||||
* @memberOf typedefs.cards
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {abstractOptions & Object} HaAreaCardOptions HA Area Card options.
|
||||
* @property {string} area The id of the area.
|
||||
* @property {string} navigation_path The id of the area to navigate to.
|
||||
* @memberOf typedefs.cards
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {abstractOptions & Object} mediaPlayerCardOptions Media Player Card options.
|
||||
* @property {boolean} [use_media_info=true] Use media info instead of name, state, and icon when a media is playing
|
||||
|
||||
@@ -191,12 +191,11 @@ class MushroomStrategy {
|
||||
}
|
||||
|
||||
if (!Helper.strategyOptions.domains.default.hidden) {
|
||||
// TODO: Check if default is hidden
|
||||
// Create cards for any other domain.
|
||||
// Collect device entities of the current area.
|
||||
const areaDevices = Helper.devices.filter(device => device.area_id === area.area_id)
|
||||
.map(device => device.id);
|
||||
|
||||
|
||||
// Collect the remaining entities of which all conditions below are met:
|
||||
// 1. The entity is linked to a device which is linked to the current area,
|
||||
// or the entity itself is linked to the current area.
|
||||
@@ -207,33 +206,33 @@ class MushroomStrategy {
|
||||
&& entity.disabled_by == null
|
||||
&& !exposedDomainIds.includes(entity.entity_id.split(".", 1)[0]);
|
||||
});
|
||||
|
||||
|
||||
// Create a column of miscellaneous entity cards.
|
||||
if (miscellaneousEntities.length) {
|
||||
let miscellaneousCards = [];
|
||||
|
||||
|
||||
try {
|
||||
miscellaneousCards = await import("./cards/MiscellaneousCard").then(cardModule => {
|
||||
/** @type Object[] */
|
||||
const miscellaneousCards = [
|
||||
new TitleCard([area], Helper.strategyOptions.domains.default).createCard(),
|
||||
];
|
||||
|
||||
|
||||
for (const entity of miscellaneousEntities) {
|
||||
let cardOptions = Helper.strategyOptions.card_options?.[entity.entity_id] ?? {};
|
||||
let deviceOptions = Helper.strategyOptions.card_options?.[entity.device_id] ?? {};
|
||||
|
||||
|
||||
if (!cardOptions.hidden && !deviceOptions.hidden) {
|
||||
miscellaneousCards.push(new cardModule.MiscellaneousCard(entity, cardOptions).getCard());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return miscellaneousCards;
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(Helper.debug ? e : "An error occurred while creating the domain cards!");
|
||||
}
|
||||
|
||||
|
||||
viewCards.push({
|
||||
type: "vertical-stack",
|
||||
cards: miscellaneousCards,
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
* @property {Object[]} [extra_cards] An array of card configurations.
|
||||
* The configured cards are added to the dashboard.
|
||||
* This property is added by the custom strategy.
|
||||
* @property {boolean} [use_ha_area_card] Set to true to use ha area card instead of mushroom.
|
||||
* @memberOf typedefs.generic
|
||||
*/
|
||||
|
||||
|
||||
+56
-25
@@ -82,9 +82,9 @@ class HomeView extends AbstractView {
|
||||
|
||||
// Add area cards.
|
||||
homeViewCards.push({
|
||||
type: "vertical-stack",
|
||||
cards: areaCards,
|
||||
});
|
||||
type: "vertical-stack",
|
||||
cards: areaCards,
|
||||
});
|
||||
|
||||
// Add custom cards.
|
||||
if (options.extra_cards) {
|
||||
@@ -158,10 +158,10 @@ class HomeView extends AbstractView {
|
||||
|
||||
import("../cards/PersonCard").then(personModule => {
|
||||
for (const person of Helper.entities.filter(entity => {
|
||||
return entity.entity_id.startsWith("person.")
|
||||
&& entity.hidden_by == null
|
||||
&& entity.disabled_by == null
|
||||
})) {
|
||||
return entity.entity_id.startsWith("person.")
|
||||
&& entity.hidden_by == null
|
||||
&& entity.disabled_by == null;
|
||||
})) {
|
||||
cards.push(new personModule.PersonCard(person).getCard());
|
||||
}
|
||||
});
|
||||
@@ -176,30 +176,61 @@ class HomeView extends AbstractView {
|
||||
*
|
||||
* @return {Object[]} A card object array.
|
||||
*/
|
||||
#createAreaCards() {
|
||||
const groupedCards = [{
|
||||
type: "custom:mushroom-title-card",
|
||||
title: "Areas",
|
||||
}];
|
||||
async #createAreaCards() {
|
||||
/**
|
||||
* Cards to be stacked vertically.
|
||||
*
|
||||
* Contains a Title card and horizontal stacks of Area cards.
|
||||
*
|
||||
* @type {[{}]}
|
||||
*/
|
||||
const groupedCards = [
|
||||
{
|
||||
type: "custom:mushroom-title-card",
|
||||
title: "Areas",
|
||||
},
|
||||
];
|
||||
let areaCards = [];
|
||||
|
||||
import("../cards/AreaCard").then(areaModule => {
|
||||
const areaCards = [];
|
||||
for (const [i, area] of Helper.areas.entries()) {
|
||||
let module;
|
||||
let moduleName =
|
||||
Helper.strategyOptions.areas[area.area_id ?? "undisclosed"]?.type ??
|
||||
Helper.strategyOptions.areas["_"]?.type ??
|
||||
"default";
|
||||
|
||||
for (const area of Helper.areas) {
|
||||
if (!Helper.strategyOptions.areas[area.area_id]?.hidden) {
|
||||
areaCards.push(
|
||||
new areaModule.AreaCard(area, Helper.strategyOptions.areas[area.area_id ?? "undisclosed"]).getCard());
|
||||
// Load module by type in strategy options.
|
||||
try {
|
||||
module = await import((`../cards/${moduleName}`));
|
||||
} catch (e) {
|
||||
// Fallback to the default strategy card.
|
||||
module = await import("../cards/AreaCard");
|
||||
|
||||
if (Helper.strategyOptions.debug && moduleName !== "default") {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Horizontally group every two area cards.
|
||||
for (let i = 0; i < areaCards.length; i += 2) {
|
||||
groupedCards.push({
|
||||
type: "horizontal-stack",
|
||||
cards: areaCards.slice(i, i + 2),
|
||||
});
|
||||
// Get a card for the area.
|
||||
if (!Helper.strategyOptions.areas[area.area_id]?.hidden) {
|
||||
let options = {
|
||||
...Helper.strategyOptions.areas["_"],
|
||||
...Helper.strategyOptions.areas[area.area_id ?? "undisclosed"],
|
||||
};
|
||||
|
||||
areaCards.push(new module.AreaCard(area, options).getCard());
|
||||
}
|
||||
});
|
||||
|
||||
// Horizontally group every two area cards if all cards are created.
|
||||
if (i === Helper.areas.length - 1) {
|
||||
for (let i = 0; i < areaCards.length; i += 2) {
|
||||
groupedCards.push({
|
||||
type: "horizontal-stack",
|
||||
cards: areaCards.slice(i, i + 2),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return groupedCards;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user