Add lovelace template extension points (#1653)

This commit is contained in:
cdce8p 2018-09-10 23:15:29 +02:00 committed by Paulus Schoutsen
parent 8505750958
commit 76161329b6
15 changed files with 323 additions and 179 deletions

View File

@ -9,6 +9,24 @@ import computeStateName from '../../../common/entity/compute_state_name.js';
class HuiGenericEntityRow extends PolymerElement { class HuiGenericEntityRow extends PolymerElement {
static get template() { static get template() {
return html`
${this.styleTemplate}
<template is="dom-if" if="[[_stateObj]]">
${this.stateBadgeTemplate}
<div class="flex">
${this.infoTemplate}
<slot></slot>
</div>
</template>
<template is="dom-if" if="[[!_stateObj]]">
<div class="not-found">
Entity not available: [[config.entity]]
</div>
</template>
`;
}
static get styleTemplate() {
return html` return html`
<style> <style>
:host { :host {
@ -50,36 +68,36 @@ class HuiGenericEntityRow extends PolymerElement {
flex: 0 0 40px; flex: 0 0 40px;
} }
</style> </style>
<template is="dom-if" if="[[_stateObj]]"> `;
<state-badge }
state-obj="[[_stateObj]]"
override-icon="[[config.icon]]" static get stateBadgeTemplate() {
></state-badge> return html`
<div class="flex"> <state-badge
<div class="info"> state-obj="[[_stateObj]]"
[[_computeName(config.name, _stateObj)]] override-icon="[[config.icon]]"
<template is="dom-if" if="[[config.secondary_info]]"> ></state-badge>
<template is="dom-if" if="[[_equals(config.secondary_info, 'entity-id')]]"> `;
<div class="secondary"> }
[[_stateObj.entity_id]]
</div> static get infoTemplate() {
</template> return html`
<template is="dom-if" if="[[_equals(config.secondary_info, 'last-changed')]]"> <div class="info">
<ha-relative-time [[_computeName(config.name, _stateObj)]]
hass="[[hass]]" <template is="dom-if" if="[[config.secondary_info]]">
datetime="[[_stateObj.last_changed]]" <template is="dom-if" if="[[_equals(config.secondary_info, 'entity-id')]]">
></ha-relative-time> <div class="secondary">
</template> [[_stateObj.entity_id]]
</template> </div>
</div> </template>
<slot></slot> <template is="dom-if" if="[[_equals(config.secondary_info, 'last-changed')]]">
</div> <ha-relative-time
</template> hass="[[hass]]"
<template is="dom-if" if="[[!_stateObj]]"> datetime="[[_stateObj.last_changed]]"
<div class="not-found"> ></ha-relative-time>
Entity not available: [[config.entity]] </template>
</div> </template>
</template> </div>
`; `;
} }

View File

@ -6,21 +6,33 @@ import '../components/hui-generic-entity-row.js';
class HuiClimateEntityRow extends PolymerElement { class HuiClimateEntityRow extends PolymerElement {
static get template() { static get template() {
return html`
${this.styleTemplate}
<hui-generic-entity-row
hass="[[hass]]"
config="[[_config]]"
>
${this.climateControlTemplate}
</hui-generic-entity-row>
`;
}
static get styleTemplate() {
return html` return html`
<style> <style>
ha-climate-state { ha-climate-state {
text-align: right; text-align: right;
} }
</style> </style>
<hui-generic-entity-row `;
}
static get climateControlTemplate() {
return html`
<ha-climate-state
hass="[[hass]]" hass="[[hass]]"
config="[[_config]]" state-obj="[[_stateObj]]"
> ></ha-climate-state>
<ha-climate-state
hass="[[hass]]"
state-obj="[[_stateObj]]"
></ha-climate-state>
</hui-generic-entity-row>
`; `;
} }

View File

@ -8,6 +8,18 @@ import CoverEntity from '../../../util/cover-model.js';
class HuiCoverEntityRow extends PolymerElement { class HuiCoverEntityRow extends PolymerElement {
static get template() { static get template() {
return html`
${this.styleTemplate}
<hui-generic-entity-row
hass="[[hass]]"
config="[[_config]]"
>
${this.coverControlTemplate}
</hui-generic-entity-row>
`;
}
static get styleTemplate() {
return html` return html`
<style> <style>
ha-cover-controls, ha-cover-controls,
@ -15,17 +27,17 @@ class HuiCoverEntityRow extends PolymerElement {
margin-right: -.57em; margin-right: -.57em;
} }
</style> </style>
<hui-generic-entity-row `;
hass="[[hass]]" }
config="[[_config]]"
> static get coverControlTemplate() {
<template is="dom-if" if="[[!_entityObj.isTiltOnly]]"> return html`
<ha-cover-controls hass="[[hass]]" state-obj="[[_stateObj]]"></ha-cover-controls> <template is="dom-if" if="[[!_entityObj.isTiltOnly]]">
</template> <ha-cover-controls hass="[[hass]]" state-obj="[[_stateObj]]"></ha-cover-controls>
<template is="dom-if" if="[[_entityObj.isTiltOnly]]"> </template>
<ha-cover-tilt-controls hass="[[hass]]" state-obj="[[_stateObj]]"></ha-cover-tilt-controls> <template is="dom-if" if="[[_entityObj.isTiltOnly]]">
</template> <ha-cover-tilt-controls hass="[[hass]]" state-obj="[[_stateObj]]"></ha-cover-tilt-controls>
</hui-generic-entity-row> </template>
`; `;
} }

View File

@ -18,21 +18,27 @@ class HuiGroupEntityRow extends LocalizeMixin(PolymerElement) {
hass="[[hass]]" hass="[[hass]]"
config="[[_config]]" config="[[_config]]"
> >
<template is="dom-if" if="[[_canToggle]]"> ${this.groupControlTemplate}
<ha-entity-toggle
hass="[[hass]]"
state-obj="[[_stateObj]]"
></ha-entity-toggle>
</template>
<template is="dom-if" if="[[!_canToggle]]">
<div>
[[_computeState(_stateObj)]]
</div>
</template>
</hui-generic-entity-row> </hui-generic-entity-row>
`; `;
} }
static get groupControlTemplate() {
return html`
<template is="dom-if" if="[[_canToggle]]">
<ha-entity-toggle
hass="[[hass]]"
state-obj="[[_stateObj]]"
></ha-entity-toggle>
</template>
<template is="dom-if" if="[[!_canToggle]]">
<div>
[[_computeState(_stateObj)]]
</div>
</template>
`;
}
static get properties() { static get properties() {
return { return {
hass: Object, hass: Object,

View File

@ -9,6 +9,19 @@ import '../components/hui-generic-entity-row.js';
class HuiInputNumberEntityRow extends mixinBehaviors([IronResizableBehavior], PolymerElement) { class HuiInputNumberEntityRow extends mixinBehaviors([IronResizableBehavior], PolymerElement) {
static get template() { static get template() {
return html`
${this.styleTemplate}
<hui-generic-entity-row
hass="[[hass]]"
config="[[_config]]"
id="input_number_card"
>
${this.inputNumberControlTemplate}
</hui-generic-entity-row>
`;
}
static get styleTemplate() {
return html` return html`
<style> <style>
.flex { .flex {
@ -23,41 +36,40 @@ class HuiInputNumberEntityRow extends mixinBehaviors([IronResizableBehavior], Po
text-align: right; text-align: right;
} }
</style> </style>
<hui-generic-entity-row `;
hass="[[hass]]" }
config="[[_config]]"
id="input_number_card" static get inputNumberControlTemplate() {
> return html`
<div> <div>
<template is="dom-if" if="[[_equals(_stateObj.attributes.mode, 'slider')]]"> <template is="dom-if" if="[[_equals(_stateObj.attributes.mode, 'slider')]]">
<div class="flex"> <div class="flex">
<paper-slider <paper-slider
min="[[_min]]"
max="[[_max]]"
value="{{_value}}"
step="[[_step]]"
pin
on-change="_selectedValueChanged"
ignore-bar-touch
></paper-slider>
<span class="state">[[_value]] [[_stateObj.attributes.unit_of_measurement]]</span>
</div>
</template>
<template is="dom-if" if="[[_equals(_stateObj.attributes.mode, 'box')]]">
<paper-input
no-label-float
auto-validate
pattern="[0-9]+([\\.][0-9]+)?"
step="[[_step]]"
min="[[_min]]" min="[[_min]]"
max="[[_max]]" max="[[_max]]"
value="{{_value}}" value="{{_value}}"
type="number" step="[[_step]]"
pin
on-change="_selectedValueChanged" on-change="_selectedValueChanged"
></paper-input> ignore-bar-touch
</template> ></paper-slider>
</div> <span class="state">[[_value]] [[_stateObj.attributes.unit_of_measurement]]</span>
</hui-generic-entity-row> </div>
</template>
<template is="dom-if" if="[[_equals(_stateObj.attributes.mode, 'box')]]">
<paper-input
no-label-float
auto-validate
pattern="[0-9]+([\\.][0-9]+)?"
step="[[_step]]"
min="[[_min]]"
max="[[_max]]"
value="{{_value}}"
type="number"
on-change="_selectedValueChanged"
></paper-input>
</template>
</div>
`; `;
} }

View File

@ -16,21 +16,7 @@ import EventsMixin from '../../../mixins/events-mixin.js';
class HuiInputSelectEntityRow extends EventsMixin(PolymerElement) { class HuiInputSelectEntityRow extends EventsMixin(PolymerElement) {
static get template() { static get template() {
return html` return html`
<style> ${this.styleTemplate}
:host {
display: flex;
align-items: center;
}
paper-dropdown-menu {
margin-left: 16px;
flex: 1;
}
.not-found {
flex: 1;
background-color: yellow;
padding: 8px;
}
</style>
<template is="dom-if" if="[[_stateObj]]"> <template is="dom-if" if="[[_stateObj]]">
<state-badge state-obj="[[_stateObj]]"></state-badge> <state-badge state-obj="[[_stateObj]]"></state-badge>
<paper-dropdown-menu on-click="_stopPropagation" selected-item-label="{{_selected}}" label="[[_computeName(_config.name, _stateObj)]]"> <paper-dropdown-menu on-click="_stopPropagation" selected-item-label="{{_selected}}" label="[[_computeName(_config.name, _stateObj)]]">
@ -49,6 +35,26 @@ class HuiInputSelectEntityRow extends EventsMixin(PolymerElement) {
`; `;
} }
static get styleTemplate() {
return html`
<style>
:host {
display: flex;
align-items: center;
}
paper-dropdown-menu {
margin-left: 16px;
flex: 1;
}
.not-found {
flex: 1;
background-color: yellow;
padding: 8px;
}
</style>
`;
}
static get properties() { static get properties() {
return { return {
hass: Object, hass: Object,

View File

@ -11,21 +11,27 @@ class HuiInputTextEntityRow extends PolymerElement {
hass="[[hass]]" hass="[[hass]]"
config="[[_config]]" config="[[_config]]"
> >
<paper-input ${this.inputTextControlTemplate}
no-label-float
minlength="[[_stateObj.attributes.min]]"
maxlength="[[_stateObj.attributes.max]]"
value="{{_value}}"
auto-validate="[[_stateObj.attributes.pattern]]"
pattern="[[_stateObj.attributes.pattern]]"
type="[[_stateObj.attributes.mode]]"
on-change="_selectedValueChanged"
placeholder="(empty value)"
></paper-input>
</hui-generic-entity-row> </hui-generic-entity-row>
`; `;
} }
static get inputTextControlTemplate() {
return html`
<paper-input
no-label-float
minlength="[[_stateObj.attributes.min]]"
maxlength="[[_stateObj.attributes.max]]"
value="{{_value}}"
auto-validate="[[_stateObj.attributes.pattern]]"
pattern="[[_stateObj.attributes.pattern]]"
type="[[_stateObj.attributes.mode]]"
on-change="_selectedValueChanged"
placeholder="(empty value)"
></paper-input>
`;
}
static get properties() { static get properties() {
return { return {
hass: Object, hass: Object,

View File

@ -11,6 +11,18 @@ import LocalizeMixin from '../../../mixins/localize-mixin.js';
*/ */
class HuiLockEntityRow extends LocalizeMixin(PolymerElement) { class HuiLockEntityRow extends LocalizeMixin(PolymerElement) {
static get template() { static get template() {
return html`
${this.styleTemplate}
<hui-generic-entity-row
hass="[[hass]]"
config="[[_config]]"
>
${this.lockControlTemplate}
</hui-generic-entity-row>
`;
}
static get styleTemplate() {
return html` return html`
<style> <style>
paper-button { paper-button {
@ -19,14 +31,14 @@ class HuiLockEntityRow extends LocalizeMixin(PolymerElement) {
margin-right: -.57em; margin-right: -.57em;
} }
</style> </style>
<hui-generic-entity-row `;
hass="[[hass]]" }
config="[[_config]]"
> static get lockControlTemplate() {
<paper-button on-click="_callService"> return html`
[[_computeButtonTitle(_stateObj.state)]] <paper-button on-click="_callService">
</paper-button> [[_computeButtonTitle(_stateObj.state)]]
</hui-generic-entity-row> </paper-button>
`; `;
} }

View File

@ -11,6 +11,18 @@ import LocalizeMixin from '../../../mixins/localize-mixin.js';
*/ */
class HuiSceneEntityRow extends LocalizeMixin(PolymerElement) { class HuiSceneEntityRow extends LocalizeMixin(PolymerElement) {
static get template() { static get template() {
return html`
${this.styleTemplate}
<hui-generic-entity-row
hass="[[hass]]"
config="[[_config]]"
>
${this.sceneControlTemplate}
</hui-generic-entity-row>
`;
}
static get styleTemplate() {
return html` return html`
<style> <style>
paper-button { paper-button {
@ -19,14 +31,14 @@ class HuiSceneEntityRow extends LocalizeMixin(PolymerElement) {
margin-right: -.57em; margin-right: -.57em;
} }
</style> </style>
<hui-generic-entity-row `;
hass="[[hass]]" }
config="[[_config]]"
> static get sceneControlTemplate() {
<paper-button on-click="_callService"> return html`
[[localize('ui.card.scene.activate')]] <paper-button on-click="_callService">
</paper-button> [[localize('ui.card.scene.activate')]]
</hui-generic-entity-row> </paper-button>
`; `;
} }

View File

@ -12,6 +12,18 @@ import LocalizeMixin from '../../../mixins/localize-mixin.js';
*/ */
class HuiScriptEntityRow extends LocalizeMixin(PolymerElement) { class HuiScriptEntityRow extends LocalizeMixin(PolymerElement) {
static get template() { static get template() {
return html`
${this.styleTemplate}
<hui-generic-entity-row
hass="[[hass]]"
config="[[_config]]"
>
${this.scriptControlTemplate}
</hui-generic-entity-row>
`;
}
static get styleTemplate() {
return html` return html`
<style> <style>
paper-button { paper-button {
@ -20,17 +32,17 @@ class HuiScriptEntityRow extends LocalizeMixin(PolymerElement) {
margin-right: -.57em; margin-right: -.57em;
} }
</style> </style>
<hui-generic-entity-row `;
hass="[[hass]]" }
config="[[_config]]"
> static get scriptControlTemplate() {
<template is="dom-if" if="[[_stateObj.attributes.can_cancel]]"> return html`
<ha-entity-toggle state-obj="[[_stateObj]]" hass="[[hass]]"></ha-entity-toggle> <template is="dom-if" if="[[_stateObj.attributes.can_cancel]]">
</template> <ha-entity-toggle state-obj="[[_stateObj]]" hass="[[hass]]"></ha-entity-toggle>
<template is="dom-if" if="[[!_stateObj.attributes.can_cancel]]"> </template>
<paper-button on-click="_callService">[[localize('ui.card.script.execute')]]</paper-button> <template is="dom-if" if="[[!_stateObj.attributes.can_cancel]]">
</template> <paper-button on-click="_callService">[[localize('ui.card.script.execute')]]</paper-button>
</hui-generic-entity-row> </template>
`; `;
} }

View File

@ -12,20 +12,32 @@ import LocalizeMixin from '../../../mixins/localize-mixin.js';
*/ */
class HuiTextEntityRow extends LocalizeMixin(PolymerElement) { class HuiTextEntityRow extends LocalizeMixin(PolymerElement) {
static get template() { static get template() {
return html`
${this.styleTemplate}
<hui-generic-entity-row
hass="[[hass]]"
config="[[_config]]"
>
${this.textControlTemplate}
</hui-generic-entity-row>
`;
}
static get styleTemplate() {
return html` return html`
<style> <style>
div { div {
text-align: right; text-align: right;
} }
</style> </style>
<hui-generic-entity-row `;
hass="[[hass]]" }
config="[[_config]]"
> static get textControlTemplate() {
<div> return html`
[[_computeState(_stateObj)]] <div>
</div> [[_computeState(_stateObj)]]
</hui-generic-entity-row> </div>
`; `;
} }

View File

@ -13,13 +13,19 @@ class HuiTimerEntityRow extends PolymerElement {
hass="[[hass]]" hass="[[hass]]"
config="[[_config]]" config="[[_config]]"
> >
<div> ${this.timerControlTemplate}
[[_computeDisplay(_stateObj, _timeRemaining)]]
</div>
</hui-generic-entity-row> </hui-generic-entity-row>
`; `;
} }
static get timerControlTemplate() {
return html`
<div>
[[_computeDisplay(_stateObj, _timeRemaining)]]
</div>
`;
}
static get properties() { static get properties() {
return { return {
hass: Object, hass: Object,

View File

@ -18,21 +18,27 @@ class HuiToggleEntityRow extends LocalizeMixin(PolymerElement) {
hass="[[hass]]" hass="[[hass]]"
config="[[_config]]" config="[[_config]]"
> >
<template is="dom-if" if="[[_canToggle]]"> ${this.toggleControlTemplate}
<ha-entity-toggle
hass="[[hass]]"
state-obj="[[_stateObj]]"
></ha-entity-toggle>
</template>
<template is="dom-if" if="[[!_canToggle]]">
<div>
[[_computeState(_stateObj)]]
</div>
</template>
</hui-generic-entity-row> </hui-generic-entity-row>
`; `;
} }
static get toggleControlTemplate() {
return html`
<template is="dom-if" if="[[_canToggle]]">
<ha-entity-toggle
hass="[[hass]]"
state-obj="[[_stateObj]]"
></ha-entity-toggle>
</template>
<template is="dom-if" if="[[!_canToggle]]">
<div>
[[_computeState(_stateObj)]]
</div>
</template>
`;
}
static get properties() { static get properties() {
return { return {
hass: Object, hass: Object,

View File

@ -7,6 +7,19 @@ import callService from '../common/call-service.js';
class HuiCallServiceRow extends PolymerElement { class HuiCallServiceRow extends PolymerElement {
static get template() { static get template() {
return html`
${this.styleTemplate}
<ha-icon icon="[[_config.icon]]"></ha-icon>
<div class="flex">
<div>
[[_config.name]]
</div>
<paper-button on-click="_callService">[[_config.action_name]]</paper-button>
</div>
`;
}
static get styleTemplate() {
return html` return html`
<style> <style>
:host { :host {
@ -36,13 +49,6 @@ class HuiCallServiceRow extends PolymerElement {
margin-right: -.57em; margin-right: -.57em;
} }
</style> </style>
<ha-icon icon="[[_config.icon]]"></ha-icon>
<div class="flex">
<div>
[[_config.name]]
</div>
<paper-button on-click="_callService">[[_config.action_name]]</paper-button>
</div>
`; `;
} }

View File

@ -5,6 +5,18 @@ import '../../../components/ha-icon.js';
class HuiWeblinkRow extends PolymerElement { class HuiWeblinkRow extends PolymerElement {
static get template() { static get template() {
return html`
${this.styleTemplate}
<a href="[[_config.url]]">
<ha-icon icon="[[_config.icon]]"></ha-icon>
<div>
[[_config.name]]
</div>
</a>
`;
}
static get styleTemplate() {
return html` return html`
<style> <style>
a { a {
@ -24,12 +36,6 @@ class HuiWeblinkRow extends PolymerElement {
margin-left: 16px; margin-left: 16px;
} }
</style> </style>
<a href="[[_config.url]]">
<ha-icon icon="[[_config.icon]]"></ha-icon>
<div>
[[_config.name]]
</div>
</a>
`; `;
} }