diff --git a/src/panels/lovelace/cards/hui-column-card.js b/src/panels/lovelace/cards/hui-column-card.js new file mode 100644 index 0000000000..6bda7f8f8d --- /dev/null +++ b/src/panels/lovelace/cards/hui-column-card.js @@ -0,0 +1,84 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + +import computeCardSize from '../common/compute-card-size.js'; +import createCardElement from '../common/create-card-element.js'; +import createErrorConfig from '../common/create-error-card-config.js'; + +class HuiColumnCard extends PolymerElement { + static get template() { + return html` + +
+ `; + } + + static get properties() { + return { + hass: { + type: Object, + observer: '_hassChanged' + }, + config: { + type: Object, + observer: '_configChanged' + } + }; + } + + constructor() { + super(); + this._elements = []; + } + + getCardSize() { + let totalSize = 0; + this._elements.forEach((element) => { + totalSize += computeCardSize(element); + }); + return totalSize; + } + + _configChanged(config) { + this._elements = []; + const root = this.$.root; + + while (root.lastChild) { + root.removeChild(root.lastChild); + } + + if (!config || !config.cards || !Array.isArray(config.cards)) { + const error = 'Card config incorrect.'; + const element = createCardElement(createErrorConfig(error, config)); + root.appendChild(element); + return; + } + + const elements = []; + config.cards.forEach((card) => { + const element = createCardElement(card); + element.hass = this.hass; + elements.push(element); + root.appendChild(element); + }); + this._elements = elements; + } + + _hassChanged(hass) { + this._elements.forEach((element) => { + element.hass = hass; + }); + } +} + +customElements.define('hui-column-card', HuiColumnCard); diff --git a/src/panels/lovelace/cards/hui-error-card.js b/src/panels/lovelace/cards/hui-error-card.js index 6a0f8b934e..122c22197f 100644 --- a/src/panels/lovelace/cards/hui-error-card.js +++ b/src/panels/lovelace/cards/hui-error-card.js @@ -24,7 +24,7 @@ class HuiErrorCard extends PolymerElement { } getCardSize() { - return 1; + return 4; } _toStr(obj) { diff --git a/src/panels/lovelace/cards/hui-row-card.js b/src/panels/lovelace/cards/hui-row-card.js new file mode 100644 index 0000000000..a5d06256af --- /dev/null +++ b/src/panels/lovelace/cards/hui-row-card.js @@ -0,0 +1,85 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + +import computeCardSize from '../common/compute-card-size.js'; +import createCardElement from '../common/create-card-element.js'; +import createErrorConfig from '../common/create-error-card-config.js'; + +class HuiRowCard extends PolymerElement { + static get template() { + return html` + +
+ `; + } + + static get properties() { + return { + hass: { + type: Object, + observer: '_hassChanged' + }, + config: { + type: Object, + observer: '_configChanged' + } + }; + } + + constructor() { + super(); + this._elements = []; + } + + getCardSize() { + let size = 1; + this._elements.forEach((element) => { + const elSize = computeCardSize(element); + if (elSize > size) size = elSize; + }); + return size; + } + + _configChanged(config) { + this._elements = []; + const root = this.$.root; + + while (root.lastChild) { + root.removeChild(root.lastChild); + } + + if (!config || !config.cards || !Array.isArray(config.cards)) { + const error = 'Card config incorrect.'; + const element = createCardElement(createErrorConfig(error, config)); + root.appendChild(element); + return; + } + + const elements = []; + config.cards.forEach((card) => { + const element = createCardElement(card); + element.hass = this.hass; + elements.push(element); + root.appendChild(element); + }); + this._elements = elements; + } + + _hassChanged(hass) { + this._elements.forEach((element) => { + element.hass = hass; + }); + } +} + +customElements.define('hui-row-card', HuiRowCard); diff --git a/src/panels/lovelace/common/compute-card-size.js b/src/panels/lovelace/common/compute-card-size.js new file mode 100644 index 0000000000..ae491e9eda --- /dev/null +++ b/src/panels/lovelace/common/compute-card-size.js @@ -0,0 +1,3 @@ +export default function computeCardSize(element) { + return typeof element.getCardSize === 'function' ? element.getCardSize() : 1; +} diff --git a/src/panels/lovelace/common/create-card-element.js b/src/panels/lovelace/common/create-card-element.js index e5501046a6..d307416d39 100644 --- a/src/panels/lovelace/common/create-card-element.js +++ b/src/panels/lovelace/common/create-card-element.js @@ -1,8 +1,10 @@ import fireEvent from '../../../common/dom/fire_event.js'; import '../cards/hui-camera-preview-card.js'; +import '../cards/hui-column-card.js'; import '../cards/hui-entities-card.js'; import '../cards/hui-entity-filter-card.js'; +import '../cards/hui-error-card.js'; import '../cards/hui-glance-card'; import '../cards/hui-history-graph-card.js'; import '../cards/hui-iframe-card.js'; @@ -12,13 +14,14 @@ import '../cards/hui-entity-picture-card.js'; import '../cards/hui-picture-elements-card'; import '../cards/hui-picture-glance-card'; import '../cards/hui-plant-status-card.js'; +import '../cards/hui-row-card.js'; import '../cards/hui-weather-forecast-card'; -import '../cards/hui-error-card.js'; import createErrorCardConfig from './create-error-card-config.js'; const CARD_TYPES = [ 'camera-preview', + 'column', 'entities', 'entity-filter', 'entity-picture', @@ -31,6 +34,7 @@ const CARD_TYPES = [ 'picture-elements', 'picture-glance', 'plant-status', + 'row', 'weather-forecast' ];