mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-29 12:16:39 +00:00
commit
4e6d00cf5c
12
package.json
12
package.json
@ -17,9 +17,9 @@
|
|||||||
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material/mwc-button": "^0.3.6",
|
"@material/mwc-button": "^0.5.0",
|
||||||
"@material/mwc-ripple": "^0.3.6",
|
"@material/mwc-ripple": "^0.5.0",
|
||||||
"@mdi/svg": "^3.0.39",
|
"@mdi/svg": "3.5.95",
|
||||||
"@polymer/app-layout": "^3.0.1",
|
"@polymer/app-layout": "^3.0.1",
|
||||||
"@polymer/app-localize-behavior": "^3.0.1",
|
"@polymer/app-localize-behavior": "^3.0.1",
|
||||||
"@polymer/app-route": "^3.0.2",
|
"@polymer/app-route": "^3.0.2",
|
||||||
@ -34,6 +34,7 @@
|
|||||||
"@polymer/iron-input": "^3.0.1",
|
"@polymer/iron-input": "^3.0.1",
|
||||||
"@polymer/iron-label": "^3.0.1",
|
"@polymer/iron-label": "^3.0.1",
|
||||||
"@polymer/iron-media-query": "^3.0.1",
|
"@polymer/iron-media-query": "^3.0.1",
|
||||||
|
"@polymer/iron-overlay-behavior": "^3.0.2",
|
||||||
"@polymer/iron-pages": "^3.0.1",
|
"@polymer/iron-pages": "^3.0.1",
|
||||||
"@polymer/iron-resizable-behavior": "^3.0.1",
|
"@polymer/iron-resizable-behavior": "^3.0.1",
|
||||||
"@polymer/neon-animation": "^3.0.1",
|
"@polymer/neon-animation": "^3.0.1",
|
||||||
@ -79,7 +80,7 @@
|
|||||||
"jquery": "^3.3.1",
|
"jquery": "^3.3.1",
|
||||||
"js-yaml": "^3.12.0",
|
"js-yaml": "^3.12.0",
|
||||||
"leaflet": "^1.3.4",
|
"leaflet": "^1.3.4",
|
||||||
"lit-element": "^2.0.0",
|
"lit-element": "^2.1.0",
|
||||||
"lit-html": "^1.0.0",
|
"lit-html": "^1.0.0",
|
||||||
"marked": "^0.6.0",
|
"marked": "^0.6.0",
|
||||||
"mdn-polyfills": "^5.12.0",
|
"mdn-polyfills": "^5.12.0",
|
||||||
@ -167,7 +168,8 @@
|
|||||||
"@webcomponents/webcomponentsjs": "^2.2.6",
|
"@webcomponents/webcomponentsjs": "^2.2.6",
|
||||||
"@webcomponents/shadycss": "^1.9.0",
|
"@webcomponents/shadycss": "^1.9.0",
|
||||||
"@vaadin/vaadin-overlay": "3.2.2",
|
"@vaadin/vaadin-overlay": "3.2.2",
|
||||||
"@vaadin/vaadin-lumo-styles": "1.3.0"
|
"@vaadin/vaadin-lumo-styles": "1.3.0",
|
||||||
|
"@polymer/iron-overlay-behavior": "^3.0.2"
|
||||||
},
|
},
|
||||||
"main": "src/home-assistant.js",
|
"main": "src/home-assistant.js",
|
||||||
"husky": {
|
"husky": {
|
||||||
|
2
setup.py
2
setup.py
@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="home-assistant-frontend",
|
name="home-assistant-frontend",
|
||||||
version="20190321.0",
|
version="20190327.0",
|
||||||
description="The Home Assistant frontend",
|
description="The Home Assistant frontend",
|
||||||
url="https://github.com/home-assistant/home-assistant-polymer",
|
url="https://github.com/home-assistant/home-assistant-polymer",
|
||||||
author="The Home Assistant Authors",
|
author="The Home Assistant Authors",
|
||||||
|
@ -2,6 +2,7 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import "../components/ha-form";
|
import "../components/ha-form";
|
||||||
|
import "../components/ha-markdown";
|
||||||
import { localizeLiteMixin } from "../mixins/localize-lite-mixin";
|
import { localizeLiteMixin } from "../mixins/localize-lite-mixin";
|
||||||
|
|
||||||
class HaAuthFlow extends localizeLiteMixin(PolymerElement) {
|
class HaAuthFlow extends localizeLiteMixin(PolymerElement) {
|
||||||
@ -121,6 +122,12 @@ class HaAuthFlow extends localizeLiteMixin(PolymerElement) {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
// allow auth provider bypass the login form
|
||||||
|
if (data.type === "create_entry") {
|
||||||
|
this._redirect(data.result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this._updateStep(data);
|
this._updateStep(data);
|
||||||
} else {
|
} else {
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
@ -138,6 +145,24 @@ class HaAuthFlow extends localizeLiteMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_redirect(authCode) {
|
||||||
|
// OAuth 2: 3.1.2 we need to retain query component of a redirect URI
|
||||||
|
let url = this.redirectUri;
|
||||||
|
if (!url.includes("?")) {
|
||||||
|
url += "?";
|
||||||
|
} else if (!url.endsWith("&")) {
|
||||||
|
url += "&";
|
||||||
|
}
|
||||||
|
|
||||||
|
url += `code=${encodeURIComponent(authCode)}`;
|
||||||
|
|
||||||
|
if (this.oauth2State) {
|
||||||
|
url += `&state=${encodeURIComponent(this.oauth2State)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.location = url;
|
||||||
|
}
|
||||||
|
|
||||||
_updateStep(step) {
|
_updateStep(step) {
|
||||||
const props = {
|
const props = {
|
||||||
_step: step,
|
_step: step,
|
||||||
@ -229,21 +254,7 @@ class HaAuthFlow extends localizeLiteMixin(PolymerElement) {
|
|||||||
const newStep = await response.json();
|
const newStep = await response.json();
|
||||||
|
|
||||||
if (newStep.type === "create_entry") {
|
if (newStep.type === "create_entry") {
|
||||||
// OAuth 2: 3.1.2 we need to retain query component of a redirect URI
|
this._redirect(newStep.result);
|
||||||
let url = this.redirectUri;
|
|
||||||
if (!url.includes("?")) {
|
|
||||||
url += "?";
|
|
||||||
} else if (!url.endsWith("&")) {
|
|
||||||
url += "&";
|
|
||||||
}
|
|
||||||
|
|
||||||
url += `code=${encodeURIComponent(newStep.result)}`;
|
|
||||||
|
|
||||||
if (this.oauth2State) {
|
|
||||||
url += `&state=${encodeURIComponent(this.oauth2State)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.location = url;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._updateStep(newStep);
|
this._updateStep(newStep);
|
||||||
|
@ -132,6 +132,10 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
height: 44px;
|
height: 44px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.playback-controls {
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
paper-icon-button {
|
paper-icon-button {
|
||||||
opacity: var(--dark-primary-opacity);
|
opacity: var(--dark-primary-opacity);
|
||||||
}
|
}
|
||||||
@ -186,7 +190,7 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
class="self-center secondary"
|
class="self-center secondary"
|
||||||
></paper-icon-button>
|
></paper-icon-button>
|
||||||
|
|
||||||
<div>
|
<div class="playback-controls">
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon="hass:skip-previous"
|
icon="hass:skip-previous"
|
||||||
invisible$="[[!playerObj.supportsPreviousTrack]]"
|
invisible$="[[!playerObj.supportsPreviousTrack]]"
|
||||||
|
@ -2,11 +2,17 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
html,
|
html,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
PropertyDeclarations,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
customElement,
|
||||||
|
property,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
|
||||||
import computeStateDomain from "../../common/entity/compute_state_domain";
|
import computeStateDomain from "../../common/entity/compute_state_domain";
|
||||||
import computeStateName from "../../common/entity/compute_state_name";
|
import computeStateName from "../../common/entity/compute_state_name";
|
||||||
@ -14,21 +20,20 @@ import domainIcon from "../../common/entity/domain_icon";
|
|||||||
import stateIcon from "../../common/entity/state_icon";
|
import stateIcon from "../../common/entity/state_icon";
|
||||||
import timerTimeRemaining from "../../common/entity/timer_time_remaining";
|
import timerTimeRemaining from "../../common/entity/timer_time_remaining";
|
||||||
import secondsToDuration from "../../common/datetime/seconds_to_duration";
|
import secondsToDuration from "../../common/datetime/seconds_to_duration";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
|
||||||
import { HomeAssistant } from "../../types";
|
|
||||||
|
|
||||||
import "../ha-label-badge";
|
import "../ha-label-badge";
|
||||||
|
|
||||||
/*
|
@customElement("ha-state-label-badge")
|
||||||
* @appliesMixin LocalizeMixin
|
|
||||||
* @appliesMixin EventsMixin
|
|
||||||
*/
|
|
||||||
export class HaStateLabelBadge extends LitElement {
|
export class HaStateLabelBadge extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
public state?: HassEntity;
|
|
||||||
|
@property() public state?: HassEntity;
|
||||||
|
|
||||||
|
@property() private _timerTimeRemaining?: number;
|
||||||
|
|
||||||
private _connected?: boolean;
|
private _connected?: boolean;
|
||||||
|
|
||||||
private _updateRemaining?: number;
|
private _updateRemaining?: number;
|
||||||
private _timerTimeRemaining?: number;
|
|
||||||
|
|
||||||
public connectedCallback(): void {
|
public connectedCallback(): void {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
@ -47,15 +52,20 @@ export class HaStateLabelBadge extends LitElement {
|
|||||||
|
|
||||||
if (!state) {
|
if (!state) {
|
||||||
return html`
|
return html`
|
||||||
${this.renderStyle()}
|
<ha-label-badge
|
||||||
<ha-label-badge label="not found"></ha-label-badge>
|
class="warning"
|
||||||
|
label="${this.hass!.localize("state_badge.default.error")}"
|
||||||
|
icon="hass:alert"
|
||||||
|
description="${this.hass!.localize(
|
||||||
|
"state_badge.default.entity_not_found"
|
||||||
|
)}"
|
||||||
|
></ha-label-badge>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const domain = computeStateDomain(state);
|
const domain = computeStateDomain(state);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${this.renderStyle()}
|
|
||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
class="${classMap({
|
class="${classMap({
|
||||||
[domain]: true,
|
[domain]: true,
|
||||||
@ -70,14 +80,6 @@ export class HaStateLabelBadge extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get properties(): PropertyDeclarations {
|
|
||||||
return {
|
|
||||||
hass: {},
|
|
||||||
state: {},
|
|
||||||
_timerTimeRemaining: {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||||
super.firstUpdated(changedProperties);
|
super.firstUpdated(changedProperties);
|
||||||
this.addEventListener("click", (ev) => {
|
this.addEventListener("click", (ev) => {
|
||||||
@ -201,48 +203,47 @@ export class HaStateLabelBadge extends LitElement {
|
|||||||
this._timerTimeRemaining = timerTimeRemaining(stateObj);
|
this._timerTimeRemaining = timerTimeRemaining(stateObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderStyle(): TemplateResult {
|
static get styles(): CSSResult {
|
||||||
return html`
|
return css`
|
||||||
<style>
|
:host {
|
||||||
:host {
|
cursor: pointer;
|
||||||
cursor: pointer;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ha-label-badge {
|
ha-label-badge {
|
||||||
--ha-label-badge-color: var(--label-badge-red, #df4c1e);
|
--ha-label-badge-color: var(--label-badge-red, #df4c1e);
|
||||||
}
|
}
|
||||||
ha-label-badge.has-unit_of_measurement {
|
ha-label-badge.has-unit_of_measurement {
|
||||||
--ha-label-badge-label-text-transform: none;
|
--ha-label-badge-label-text-transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-label-badge.binary_sensor,
|
ha-label-badge.binary_sensor,
|
||||||
ha-label-badge.updater {
|
ha-label-badge.updater {
|
||||||
--ha-label-badge-color: var(--label-badge-blue, #039be5);
|
--ha-label-badge-color: var(--label-badge-blue, #039be5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.red {
|
.red {
|
||||||
--ha-label-badge-color: var(--label-badge-red, #df4c1e);
|
--ha-label-badge-color: var(--label-badge-red, #df4c1e);
|
||||||
}
|
}
|
||||||
|
|
||||||
.blue {
|
.blue {
|
||||||
--ha-label-badge-color: var(--label-badge-blue, #039be5);
|
--ha-label-badge-color: var(--label-badge-blue, #039be5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.green {
|
.green {
|
||||||
--ha-label-badge-color: var(--label-badge-green, #0da035);
|
--ha-label-badge-color: var(--label-badge-green, #0da035);
|
||||||
}
|
}
|
||||||
|
|
||||||
.yellow {
|
.yellow {
|
||||||
--ha-label-badge-color: var(--label-badge-yellow, #f4b400);
|
--ha-label-badge-color: var(--label-badge-yellow, #f4b400);
|
||||||
}
|
}
|
||||||
|
|
||||||
.grey {
|
.grey {
|
||||||
--ha-label-badge-color: var(
|
--ha-label-badge-color: var(--label-badge-grey, var(--paper-grey-500));
|
||||||
--label-badge-grey,
|
}
|
||||||
var(--paper-grey-500)
|
|
||||||
);
|
.warning {
|
||||||
}
|
--ha-label-badge-color: var(--label-badge-yellow, #fce588);
|
||||||
</style>
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,5 +253,3 @@ declare global {
|
|||||||
"ha-state-label-badge": HaStateLabelBadge;
|
"ha-state-label-badge": HaStateLabelBadge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("ha-state-label-badge", HaStateLabelBadge);
|
|
||||||
|
@ -25,6 +25,7 @@ class HaClimateControl extends EventsMixin(PolymerElement) {
|
|||||||
#target_temperature {
|
#target_temperature {
|
||||||
@apply --layout-self-center;
|
@apply --layout-self-center;
|
||||||
font-size: 200%;
|
font-size: 200%;
|
||||||
|
direction: ltr;
|
||||||
}
|
}
|
||||||
.control-buttons {
|
.control-buttons {
|
||||||
font-size: 200%;
|
font-size: 200%;
|
||||||
|
@ -29,18 +29,24 @@ class HaClimateState extends LocalizeMixin(PolymerElement) {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unit {
|
||||||
|
display: inline-block;
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="target">
|
<div class="target">
|
||||||
<template is="dom-if" if="[[_hasKnownState(stateObj.state)]]">
|
<template is="dom-if" if="[[_hasKnownState(stateObj.state)]]">
|
||||||
<span class="state-label"> [[_localizeState(stateObj.state)]] </span>
|
<span class="state-label"> [[_localizeState(stateObj.state)]] </span>
|
||||||
</template>
|
</template>
|
||||||
[[computeTarget(hass, stateObj)]]
|
<div class="unit">[[computeTarget(hass, stateObj)]]</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template is="dom-if" if="[[currentStatus]]">
|
<template is="dom-if" if="[[currentStatus]]">
|
||||||
<div class="current">
|
<div class="current">
|
||||||
[[localize('ui.card.climate.currently')]]: [[currentStatus]]
|
[[localize('ui.card.climate.currently')]]:
|
||||||
|
<div class="unit">[[currentStatus]]</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
`;
|
`;
|
||||||
|
@ -58,6 +58,11 @@ class HaPaperSlider extends PaperSliderClass {
|
|||||||
-webkit-transform: scale(1) translate(0, -10px);
|
-webkit-transform: scale(1) translate(0, -10px);
|
||||||
transform: scale(1) translate(0, -10px);
|
transform: scale(1) translate(0, -10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:host([dir="rtl"]) .pin.expand > .slider-knob > .slider-knob-inner::after {
|
||||||
|
-webkit-transform: scale(1) translate(0, -17px) scaleX(-1) !important;
|
||||||
|
transform: scale(1) translate(0, -17px) scaleX(-1) !important;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
tpl.content.appendChild(styleEl);
|
tpl.content.appendChild(styleEl);
|
||||||
return tpl;
|
return tpl;
|
||||||
|
@ -26,19 +26,13 @@ const computePanels = (hass: HomeAssistant) => {
|
|||||||
if (!panels) {
|
if (!panels) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const isAdmin = hass.user.is_admin;
|
|
||||||
const sortValue = {
|
const sortValue = {
|
||||||
map: 1,
|
map: 1,
|
||||||
logbook: 2,
|
logbook: 2,
|
||||||
history: 3,
|
history: 3,
|
||||||
};
|
};
|
||||||
const result: Panel[] = [];
|
const result: Panel[] = Object.values(panels).filter((panel) => panel.title);
|
||||||
|
|
||||||
Object.values(panels).forEach((panel) => {
|
|
||||||
if (panel.title && (panel.component_name !== "config" || isAdmin)) {
|
|
||||||
result.push(panel);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
result.sort((a, b) => {
|
result.sort((a, b) => {
|
||||||
const aBuiltIn = a.component_name in sortValue;
|
const aBuiltIn = a.component_name in sortValue;
|
||||||
@ -133,9 +127,8 @@ class HaSidebar extends LitElement {
|
|||||||
: html``}
|
: html``}
|
||||||
</paper-listbox>
|
</paper-listbox>
|
||||||
|
|
||||||
${!hass.user.is_admin
|
${hass.user && hass.user.is_admin
|
||||||
? ""
|
? html`
|
||||||
: html`
|
|
||||||
<div>
|
<div>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
|
|
||||||
@ -192,7 +185,8 @@ class HaSidebar extends LitElement {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`}
|
`
|
||||||
|
: ""}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
src/data/panel_custom.ts
Normal file
8
src/data/panel_custom.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export interface CustomPanelConfig {
|
||||||
|
name: string;
|
||||||
|
embed_iframe: boolean;
|
||||||
|
trust_external: boolean;
|
||||||
|
js_url?: string;
|
||||||
|
module_url?: string;
|
||||||
|
html_url?: string;
|
||||||
|
}
|
@ -16,6 +16,7 @@ export interface ZHADevice {
|
|||||||
manufacturer_code: number;
|
manufacturer_code: number;
|
||||||
device_reg_id: string;
|
device_reg_id: string;
|
||||||
user_given_name: string;
|
user_given_name: string;
|
||||||
|
area_id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Attribute {
|
export interface Attribute {
|
||||||
@ -42,7 +43,7 @@ export interface ReadAttributeServiceData {
|
|||||||
cluster_id: number;
|
cluster_id: number;
|
||||||
cluster_type: string;
|
cluster_type: string;
|
||||||
attribute: number;
|
attribute: number;
|
||||||
manufacturer: number;
|
manufacturer?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const reconfigureNode = (
|
export const reconfigureNode = (
|
||||||
|
@ -17,6 +17,7 @@ import { supportsFeature } from "../../../common/entity/supports-feature";
|
|||||||
|
|
||||||
import EventsMixin from "../../../mixins/events-mixin";
|
import EventsMixin from "../../../mixins/events-mixin";
|
||||||
import LocalizeMixin from "../../../mixins/localize-mixin";
|
import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||||
|
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @appliesMixin EventsMixin
|
* @appliesMixin EventsMixin
|
||||||
@ -84,6 +85,7 @@ class MoreInfoClimate extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
width: 90px;
|
width: 90px;
|
||||||
font-size: 200%;
|
font-size: 200%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
direction: ltr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-climate-control.range-control-left,
|
ha-climate-control.range-control-left,
|
||||||
@ -181,6 +183,7 @@ class MoreInfoClimate extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
value="[[stateObj.attributes.humidity]]"
|
value="[[stateObj.attributes.humidity]]"
|
||||||
on-change="targetHumiditySliderChanged"
|
on-change="targetHumiditySliderChanged"
|
||||||
ignore-bar-touch=""
|
ignore-bar-touch=""
|
||||||
|
dir="[[rtl]]"
|
||||||
>
|
>
|
||||||
</ha-paper-slider>
|
</ha-paper-slider>
|
||||||
</div>
|
</div>
|
||||||
@ -314,6 +317,12 @@ class MoreInfoClimate extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
awayToggleChecked: Boolean,
|
awayToggleChecked: Boolean,
|
||||||
auxToggleChecked: Boolean,
|
auxToggleChecked: Boolean,
|
||||||
onToggleChecked: Boolean,
|
onToggleChecked: Boolean,
|
||||||
|
|
||||||
|
rtl: {
|
||||||
|
type: String,
|
||||||
|
value: "ltr",
|
||||||
|
computed: "_computeRTLDirection(hass)",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,6 +566,10 @@ class MoreInfoClimate extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
_localizeFanMode(localize, mode) {
|
_localizeFanMode(localize, mode) {
|
||||||
return localize(`state_attributes.climate.fan_mode.${mode}`) || mode;
|
return localize(`state_attributes.climate.fan_mode.${mode}`) || mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_computeRTLDirection(hass) {
|
||||||
|
return computeRTLDirection(hass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("more-info-climate", MoreInfoClimate);
|
customElements.define("more-info-climate", MoreInfoClimate);
|
||||||
|
@ -14,6 +14,7 @@ import attributeClassNames from "../../../common/entity/attribute_class_names";
|
|||||||
import isComponentLoaded from "../../../common/config/is_component_loaded";
|
import isComponentLoaded from "../../../common/config/is_component_loaded";
|
||||||
import EventsMixin from "../../../mixins/events-mixin";
|
import EventsMixin from "../../../mixins/events-mixin";
|
||||||
import LocalizeMixin from "../../../mixins/localize-mixin";
|
import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||||
|
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @appliesMixin LocalizeMixin
|
* @appliesMixin LocalizeMixin
|
||||||
@ -137,6 +138,7 @@ class MoreInfoMediaPlayer extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
on-change="volumeSliderChanged"
|
on-change="volumeSliderChanged"
|
||||||
class="flex"
|
class="flex"
|
||||||
ignore-bar-touch=""
|
ignore-bar-touch=""
|
||||||
|
dir="{{rtl}}"
|
||||||
>
|
>
|
||||||
</ha-paper-slider>
|
</ha-paper-slider>
|
||||||
</div>
|
</div>
|
||||||
@ -233,6 +235,11 @@ class MoreInfoMediaPlayer extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
type: String,
|
type: String,
|
||||||
value: "",
|
value: "",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
rtl: {
|
||||||
|
type: String,
|
||||||
|
computed: "_computeRTLDirection(hass)",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,6 +432,10 @@ class MoreInfoMediaPlayer extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
this.ttsMessage = "";
|
this.ttsMessage = "";
|
||||||
this.$.ttsInput.focus();
|
this.$.ttsInput.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_computeRTLDirection(hass) {
|
||||||
|
return computeRTLDirection(hass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("more-info-media_player", MoreInfoMediaPlayer);
|
customElements.define("more-info-media_player", MoreInfoMediaPlayer);
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
import { loadJS } from "../common/dom/load_resource";
|
|
||||||
import loadCustomPanel from "../util/custom-panel/load-custom-panel";
|
|
||||||
import createCustomPanelElement from "../util/custom-panel/create-custom-panel-element";
|
|
||||||
import setCustomPanelProperties from "../util/custom-panel/set-custom-panel-properties";
|
|
||||||
|
|
||||||
const webComponentsSupported =
|
|
||||||
"customElements" in window &&
|
|
||||||
"import" in document.createElement("link") &&
|
|
||||||
"content" in document.createElement("template");
|
|
||||||
|
|
||||||
let es5Loaded = null;
|
|
||||||
|
|
||||||
window.loadES5Adapter = () => {
|
|
||||||
if (!es5Loaded) {
|
|
||||||
es5Loaded = Promise.all([
|
|
||||||
loadJS(`${__STATIC_PATH__}custom-elements-es5-adapter.js`).catch(),
|
|
||||||
import(/* webpackChunkName: "compat" */ "./compatibility"),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
return es5Loaded;
|
|
||||||
};
|
|
||||||
|
|
||||||
let root = null;
|
|
||||||
|
|
||||||
function setProperties(properties) {
|
|
||||||
if (root === null) return;
|
|
||||||
setCustomPanelProperties(root, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
function initialize(panel, properties) {
|
|
||||||
const style = document.createElement("style");
|
|
||||||
style.innerHTML = "body{margin:0}";
|
|
||||||
document.head.appendChild(style);
|
|
||||||
|
|
||||||
const config = panel.config._panel_custom;
|
|
||||||
let start = Promise.resolve();
|
|
||||||
|
|
||||||
if (!webComponentsSupported) {
|
|
||||||
start = start.then(() => loadJS("/static/webcomponents-bundle.js"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__BUILD__ === "es5") {
|
|
||||||
// Load ES5 adapter. Swallow errors as it raises errors on old browsers.
|
|
||||||
start = start.then(() => window.loadES5Adapter());
|
|
||||||
}
|
|
||||||
|
|
||||||
start
|
|
||||||
.then(() => loadCustomPanel(config))
|
|
||||||
// If our element is using es5, let it finish loading that and define element
|
|
||||||
// This avoids elements getting upgraded after being added to the DOM
|
|
||||||
.then(() => es5Loaded || Promise.resolve())
|
|
||||||
.then(
|
|
||||||
() => {
|
|
||||||
root = createCustomPanelElement(config);
|
|
||||||
|
|
||||||
const forwardEvent = (ev) =>
|
|
||||||
window.parent.customPanel.fire(ev.type, ev.detail);
|
|
||||||
root.addEventListener("hass-toggle-menu", forwardEvent);
|
|
||||||
window.addEventListener("location-changed", (ev) =>
|
|
||||||
window.parent.customPanel.navigate(
|
|
||||||
window.location.pathname,
|
|
||||||
ev.detail ? ev.detail.replace : false
|
|
||||||
)
|
|
||||||
);
|
|
||||||
setProperties(Object.assign({ panel }, properties));
|
|
||||||
document.body.appendChild(root);
|
|
||||||
},
|
|
||||||
(err) => {
|
|
||||||
// eslint-disable-next-line
|
|
||||||
console.error(err, panel);
|
|
||||||
alert(`Unable to load the panel source: ${err}.`);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener(
|
|
||||||
"DOMContentLoaded",
|
|
||||||
() => window.parent.customPanel.registerIframe(initialize, setProperties),
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
97
src/entrypoints/custom-panel.ts
Normal file
97
src/entrypoints/custom-panel.ts
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import { loadJS } from "../common/dom/load_resource";
|
||||||
|
import { loadCustomPanel } from "../util/custom-panel/load-custom-panel";
|
||||||
|
import { createCustomPanelElement } from "../util/custom-panel/create-custom-panel-element";
|
||||||
|
import { setCustomPanelProperties } from "../util/custom-panel/set-custom-panel-properties";
|
||||||
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
import { navigate } from "../common/navigate";
|
||||||
|
import { PolymerElement } from "@polymer/polymer";
|
||||||
|
import { Panel } from "../types";
|
||||||
|
import { CustomPanelConfig } from "../data/panel_custom";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
loadES5Adapter: () => Promise<unknown>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const webComponentsSupported =
|
||||||
|
"customElements" in window &&
|
||||||
|
"import" in document.createElement("link") &&
|
||||||
|
"content" in document.createElement("template");
|
||||||
|
|
||||||
|
let es5Loaded: Promise<unknown> | undefined;
|
||||||
|
|
||||||
|
window.loadES5Adapter = () => {
|
||||||
|
if (!es5Loaded) {
|
||||||
|
es5Loaded = Promise.all([
|
||||||
|
loadJS(`${__STATIC_PATH__}custom-elements-es5-adapter.js`).catch(),
|
||||||
|
import(/* webpackChunkName: "compat" */ "./compatibility"),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return es5Loaded;
|
||||||
|
};
|
||||||
|
|
||||||
|
let panelEl: HTMLElement | PolymerElement | undefined;
|
||||||
|
|
||||||
|
function setProperties(properties) {
|
||||||
|
if (!panelEl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setCustomPanelProperties(panelEl, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize(panel: Panel, properties: {}) {
|
||||||
|
const style = document.createElement("style");
|
||||||
|
style.innerHTML = "body{margin:0}";
|
||||||
|
document.head.appendChild(style);
|
||||||
|
|
||||||
|
const config = panel.config!._panel_custom as CustomPanelConfig;
|
||||||
|
let start: Promise<unknown> = Promise.resolve();
|
||||||
|
|
||||||
|
if (!webComponentsSupported) {
|
||||||
|
start = start.then(() => loadJS("/static/webcomponents-bundle.js"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__BUILD__ === "es5") {
|
||||||
|
// Load ES5 adapter. Swallow errors as it raises errors on old browsers.
|
||||||
|
start = start.then(() => window.loadES5Adapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
.then(() => loadCustomPanel(config))
|
||||||
|
// If our element is using es5, let it finish loading that and define element
|
||||||
|
// This avoids elements getting upgraded after being added to the DOM
|
||||||
|
.then(() => es5Loaded || Promise.resolve())
|
||||||
|
.then(
|
||||||
|
() => {
|
||||||
|
panelEl = createCustomPanelElement(config);
|
||||||
|
|
||||||
|
const forwardEvent = (ev) => {
|
||||||
|
if (window.parent.customPanel) {
|
||||||
|
fireEvent(window.parent.customPanel, ev.type, ev.detail);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
panelEl!.addEventListener("hass-toggle-menu", forwardEvent);
|
||||||
|
window.addEventListener("location-changed", (ev: any) =>
|
||||||
|
navigate(
|
||||||
|
window.parent.customPanel,
|
||||||
|
window.location.pathname,
|
||||||
|
ev.detail ? ev.detail.replace : false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
setProperties({ panel, ...properties });
|
||||||
|
document.body.appendChild(panelEl!);
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
// tslint:disable-next-line
|
||||||
|
console.error(err, panel);
|
||||||
|
alert(`Unable to load the panel source: ${err}.`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener(
|
||||||
|
"DOMContentLoaded",
|
||||||
|
() => window.parent.customPanel!.registerIframe(initialize, setProperties),
|
||||||
|
{ once: true }
|
||||||
|
);
|
@ -73,9 +73,9 @@ class HaPanelConfig extends HassRouterPage {
|
|||||||
import(/* webpackChunkName: "panel-config-users" */ "./users/ha-config-users"),
|
import(/* webpackChunkName: "panel-config-users" */ "./users/ha-config-users"),
|
||||||
},
|
},
|
||||||
zha: {
|
zha: {
|
||||||
tag: "ha-config-zha",
|
tag: "zha-config-panel",
|
||||||
load: () =>
|
load: () =>
|
||||||
import(/* webpackChunkName: "panel-config-zha" */ "./zha/ha-config-zha"),
|
import(/* webpackChunkName: "panel-config-zha" */ "./zha/zha-config-panel"),
|
||||||
},
|
},
|
||||||
zwave: {
|
zwave: {
|
||||||
tag: "ha-config-zwave",
|
tag: "ha-config-zwave",
|
||||||
|
@ -180,9 +180,9 @@ class HaConfigPerson extends LitElement {
|
|||||||
},
|
},
|
||||||
removeEntry: async () => {
|
removeEntry: async () => {
|
||||||
if (
|
if (
|
||||||
!confirm(`Are you sure you want to delete this area?
|
!confirm(`Are you sure you want to delete this person?
|
||||||
|
|
||||||
All devices in this area will become unassigned.`)
|
All devices belonging to this person will become unassigned.`)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
import "@polymer/app-layout/app-header/app-header";
|
import "../../../components/ha-paper-icon-button-arrow-prev";
|
||||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
import "../../../layouts/hass-subpage";
|
||||||
|
import "./zha-binding";
|
||||||
|
import "./zha-cluster-attributes";
|
||||||
|
import "./zha-cluster-commands";
|
||||||
|
import "./zha-network";
|
||||||
|
import "./zha-node";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
CSSResult,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
|
||||||
import { HASSDomEvent } from "../../../common/dom/fire_event";
|
import { HASSDomEvent } from "../../../common/dom/fire_event";
|
||||||
import { Cluster, ZHADevice, fetchBindableDevices } from "../../../data/zha";
|
import { Cluster, fetchBindableDevices, ZHADevice } from "../../../data/zha";
|
||||||
import "../../../layouts/ha-app-layout";
|
|
||||||
import "../../../components/ha-paper-icon-button-arrow-prev";
|
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { ZHAClusterSelectedParams, ZHADeviceSelectedParams } from "./types";
|
import { ZHAClusterSelectedParams, ZHADeviceSelectedParams } from "./types";
|
||||||
import "./zha-cluster-attributes";
|
|
||||||
import "./zha-cluster-commands";
|
|
||||||
import "./zha-network";
|
|
||||||
import "./zha-node";
|
|
||||||
import "./zha-binding";
|
|
||||||
|
|
||||||
export class HaConfigZha extends LitElement {
|
export class HaConfigZha extends LitElement {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
@ -38,16 +38,7 @@ export class HaConfigZha extends LitElement {
|
|||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
<ha-app-layout>
|
<hass-subpage header="Zigbee Home Automation">
|
||||||
<app-header slot="header">
|
|
||||||
<app-toolbar>
|
|
||||||
<ha-paper-icon-button-arrow-prev
|
|
||||||
@click="${this._onBackTapped}"
|
|
||||||
></ha-paper-icon-button-arrow-prev>
|
|
||||||
<div main-title>Zigbee Home Automation</div>
|
|
||||||
</app-toolbar>
|
|
||||||
</app-header>
|
|
||||||
|
|
||||||
<zha-network
|
<zha-network
|
||||||
.isWide="${this.isWide}"
|
.isWide="${this.isWide}"
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
@ -86,7 +77,7 @@ export class HaConfigZha extends LitElement {
|
|||||||
></zha-binding-control>
|
></zha-binding-control>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
</ha-app-layout>
|
</hass-subpage>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,10 +108,6 @@ export class HaConfigZha extends LitElement {
|
|||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [haStyle];
|
return [haStyle];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onBackTapped(): void {
|
|
||||||
history.back();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -8,6 +8,12 @@ export interface ItemSelectedEvent {
|
|||||||
target?: PickerTarget;
|
target?: PickerTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ZHADeviceRemovedEvent {
|
||||||
|
detail?: {
|
||||||
|
device?: ZHADevice;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export interface ChangeEvent {
|
export interface ChangeEvent {
|
||||||
detail?: {
|
detail?: {
|
||||||
value?: any;
|
value?: any;
|
||||||
@ -22,7 +28,7 @@ export interface SetAttributeServiceData {
|
|||||||
cluster_type: string;
|
cluster_type: string;
|
||||||
attribute: number;
|
attribute: number;
|
||||||
value: any;
|
value: any;
|
||||||
manufacturer: number;
|
manufacturer?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IssueCommandServiceData {
|
export interface IssueCommandServiceData {
|
||||||
|
246
src/panels/config/zha/zha-add-devices-page.ts
Normal file
246
src/panels/config/zha/zha-add-devices-page.ts
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
import "../../../components/ha-service-description";
|
||||||
|
import "../../../components/ha-textarea";
|
||||||
|
import "../../../layouts/hass-subpage";
|
||||||
|
import "./zha-device-card";
|
||||||
|
import "@material/mwc-button";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
|
|
||||||
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
|
import { ZHADevice } from "../../../data/zha";
|
||||||
|
import { haStyle } from "../../../resources/styles";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
|
@customElement("zha-add-devices-page")
|
||||||
|
class ZHAAddDevicesPage extends LitElement {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
@property() public isWide?: boolean;
|
||||||
|
@property() private _error?: string;
|
||||||
|
@property() private _discoveredDevices: ZHADevice[] = [];
|
||||||
|
@property() private _formattedEvents: string = "";
|
||||||
|
@property() private _active: boolean = false;
|
||||||
|
@property() private _showHelp: boolean = false;
|
||||||
|
private _addDevicesTimeoutHandle: any = undefined;
|
||||||
|
private _subscribed?: Promise<() => Promise<void>>;
|
||||||
|
|
||||||
|
public connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
this._subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public disconnectedCallback(): void {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
this._unsubscribe();
|
||||||
|
this._error = undefined;
|
||||||
|
this._discoveredDevices = [];
|
||||||
|
this._formattedEvents = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
return html`
|
||||||
|
<hass-subpage
|
||||||
|
header="${this.hass!.localize(
|
||||||
|
"ui.panel.config.zha.add_device_page.header"
|
||||||
|
)}"
|
||||||
|
>
|
||||||
|
${this._active
|
||||||
|
? html`
|
||||||
|
<h2>
|
||||||
|
<paper-spinner
|
||||||
|
?active="${this._active}"
|
||||||
|
alt="Searching"
|
||||||
|
></paper-spinner>
|
||||||
|
${this.hass!.localize(
|
||||||
|
"ui.panel.config.zha.add_device_page.spinner"
|
||||||
|
)}
|
||||||
|
</h2>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
<div class="card-actions">
|
||||||
|
<mwc-button @click=${this._subscribe} class="search-button">
|
||||||
|
Search again
|
||||||
|
</mwc-button>
|
||||||
|
<paper-icon-button
|
||||||
|
class="toggle-help-icon"
|
||||||
|
@click="${this._onHelpTap}"
|
||||||
|
icon="hass:help-circle"
|
||||||
|
></paper-icon-button>
|
||||||
|
${this._showHelp
|
||||||
|
? html`
|
||||||
|
<ha-service-description
|
||||||
|
.hass="${this.hass}"
|
||||||
|
domain="zha"
|
||||||
|
service="permit"
|
||||||
|
class="help-text"
|
||||||
|
/>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
</div>
|
||||||
|
`}
|
||||||
|
${this._error
|
||||||
|
? html`
|
||||||
|
<div class="error">${this._error}</div>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
<div class="content-header"></div>
|
||||||
|
<div class="content">
|
||||||
|
${this._discoveredDevices.length < 1
|
||||||
|
? html`
|
||||||
|
<div class="discovery-text">
|
||||||
|
<h4>
|
||||||
|
${this.hass!.localize(
|
||||||
|
"ui.panel.config.zha.add_device_page.discovery_text"
|
||||||
|
)}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
${this._discoveredDevices.map(
|
||||||
|
(device) => html`
|
||||||
|
<zha-device-card
|
||||||
|
class="card"
|
||||||
|
.hass="${this.hass}"
|
||||||
|
.device="${device}"
|
||||||
|
.narrow="${!this.isWide}"
|
||||||
|
.showHelp="${this._showHelp}"
|
||||||
|
.showActions="${!this._active}"
|
||||||
|
.isJoinPage="${true}"
|
||||||
|
></zha-device-card>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
`}
|
||||||
|
</div>
|
||||||
|
<ha-textarea class="events" value="${this._formattedEvents}">
|
||||||
|
</ha-textarea>
|
||||||
|
</hass-subpage>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleMessage(message: any): void {
|
||||||
|
if (message.type === "log_output") {
|
||||||
|
this._formattedEvents += message.log_entry.message + "\n";
|
||||||
|
if (this.shadowRoot) {
|
||||||
|
const textArea = this.shadowRoot.querySelector("ha-textarea");
|
||||||
|
if (textArea) {
|
||||||
|
textArea.scrollTop = textArea.scrollHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (message.type && message.type === "device_fully_initialized") {
|
||||||
|
this._discoveredDevices.push(message.device_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _unsubscribe(): void {
|
||||||
|
this._active = false;
|
||||||
|
if (this._addDevicesTimeoutHandle) {
|
||||||
|
clearTimeout(this._addDevicesTimeoutHandle);
|
||||||
|
}
|
||||||
|
if (this._subscribed) {
|
||||||
|
this._subscribed.then((unsub) => unsub());
|
||||||
|
this._subscribed = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _subscribe(): void {
|
||||||
|
this._subscribed = this.hass!.connection.subscribeMessage(
|
||||||
|
(message) => this._handleMessage(message),
|
||||||
|
{ type: "zha/devices/permit" }
|
||||||
|
);
|
||||||
|
this._active = true;
|
||||||
|
this._addDevicesTimeoutHandle = setTimeout(
|
||||||
|
() => this._unsubscribe(),
|
||||||
|
60000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onHelpTap(): void {
|
||||||
|
this._showHelp = !this._showHelp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult[] {
|
||||||
|
return [
|
||||||
|
haStyle,
|
||||||
|
css`
|
||||||
|
.discovery-text,
|
||||||
|
.content-header {
|
||||||
|
margin: 16px;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
border-top: 1px solid var(--light-primary-color);
|
||||||
|
min-height: 500px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 4px;
|
||||||
|
justify-content: left;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
.error {
|
||||||
|
color: var(--google-red-500);
|
||||||
|
}
|
||||||
|
paper-spinner {
|
||||||
|
display: none;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
paper-spinner[active] {
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
margin-left: 16px;
|
||||||
|
margin-right: 16px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.events {
|
||||||
|
margin: 16px;
|
||||||
|
border-top: 1px solid var(--light-primary-color);
|
||||||
|
padding-top: 16px;
|
||||||
|
min-height: 200px;
|
||||||
|
max-height: 200px;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
.toggle-help-icon {
|
||||||
|
position: absolute;
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-right: 16px;
|
||||||
|
top: -6px;
|
||||||
|
right: 0;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
ha-service-description {
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-left: 16px;
|
||||||
|
display: block;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
.search-button {
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
.help-text {
|
||||||
|
color: grey;
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"zha-add-devices-page": ZHAAddDevicesPage;
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,26 @@
|
|||||||
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../components/ha-service-description";
|
||||||
|
import "../ha-config-section";
|
||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
customElement,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
CSSResult,
|
|
||||||
css,
|
|
||||||
customElement,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-card/paper-card";
|
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
import { bindDevices, unbindDevices, ZHADevice } from "../../../data/zha";
|
||||||
import "../../../components/ha-service-description";
|
|
||||||
import { ZHADevice, bindDevices, unbindDevices } from "../../../data/zha";
|
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
|
||||||
import { ItemSelectedEvent } from "./types";
|
import { ItemSelectedEvent } from "./types";
|
||||||
|
|
||||||
@customElement("zha-binding-control")
|
@customElement("zha-binding-control")
|
||||||
|
@ -1,17 +1,24 @@
|
|||||||
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../components/ha-service-description";
|
||||||
|
import "../ha-config-section";
|
||||||
|
import "@material/mwc-button";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@polymer/paper-item/paper-item";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
CSSResult,
|
|
||||||
css,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@material/mwc-button";
|
|
||||||
import "@polymer/paper-card/paper-card";
|
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
|
||||||
import "../../../components/ha-service-description";
|
|
||||||
import {
|
import {
|
||||||
Attribute,
|
Attribute,
|
||||||
Cluster,
|
Cluster,
|
||||||
@ -22,13 +29,12 @@ import {
|
|||||||
} from "../../../data/zha";
|
} from "../../../data/zha";
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
import { formatAsPaddedHex } from "./functions";
|
||||||
import {
|
import {
|
||||||
ChangeEvent,
|
ChangeEvent,
|
||||||
ItemSelectedEvent,
|
ItemSelectedEvent,
|
||||||
SetAttributeServiceData,
|
SetAttributeServiceData,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import { formatAsPaddedHex } from "./functions";
|
|
||||||
|
|
||||||
export class ZHAClusterAttributes extends LitElement {
|
export class ZHAClusterAttributes extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
@ -115,7 +121,7 @@ export class ZHAClusterAttributes extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
${this.showHelp
|
${this.showHelp
|
||||||
? html`
|
? html`
|
||||||
<div style="color: grey; padding: 16px">
|
<div class="help-text">
|
||||||
Select an attribute to view or set its value
|
Select an attribute to view or set its value
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
@ -152,6 +158,13 @@ export class ZHAClusterAttributes extends LitElement {
|
|||||||
<mwc-button @click="${this._onGetZigbeeAttributeClick}"
|
<mwc-button @click="${this._onGetZigbeeAttributeClick}"
|
||||||
>Get Zigbee Attribute</mwc-button
|
>Get Zigbee Attribute</mwc-button
|
||||||
>
|
>
|
||||||
|
${this.showHelp
|
||||||
|
? html`
|
||||||
|
<div class="help-text2">
|
||||||
|
Get the value for the selected attribute
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
<ha-call-service-button
|
<ha-call-service-button
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
domain="zha"
|
domain="zha"
|
||||||
@ -165,6 +178,7 @@ export class ZHAClusterAttributes extends LitElement {
|
|||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
domain="zha"
|
domain="zha"
|
||||||
service="set_zigbee_cluster_attribute"
|
service="set_zigbee_cluster_attribute"
|
||||||
|
class="help-text2"
|
||||||
></ha-service-description>
|
></ha-service-description>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@ -201,7 +215,7 @@ export class ZHAClusterAttributes extends LitElement {
|
|||||||
attribute: this._attributes[this._selectedAttributeIndex].id,
|
attribute: this._attributes[this._selectedAttributeIndex].id,
|
||||||
manufacturer: this._manufacturerCodeOverride
|
manufacturer: this._manufacturerCodeOverride
|
||||||
? parseInt(this._manufacturerCodeOverride as string, 10)
|
? parseInt(this._manufacturerCodeOverride as string, 10)
|
||||||
: this.selectedNode!.manufacturer_code,
|
: undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +234,7 @@ export class ZHAClusterAttributes extends LitElement {
|
|||||||
value: this._attributeValue,
|
value: this._attributeValue,
|
||||||
manufacturer: this._manufacturerCodeOverride
|
manufacturer: this._manufacturerCodeOverride
|
||||||
? parseInt(this._manufacturerCodeOverride as string, 10)
|
? parseInt(this._manufacturerCodeOverride as string, 10)
|
||||||
: this.selectedNode!.manufacturer_code,
|
: undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,6 +326,16 @@ export class ZHAClusterAttributes extends LitElement {
|
|||||||
[hidden] {
|
[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
.help-text {
|
||||||
|
color: grey;
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
.help-text2 {
|
||||||
|
color: grey;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,23 @@
|
|||||||
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../components/ha-service-description";
|
||||||
|
import "../ha-config-section";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@polymer/paper-item/paper-item";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
CSSResult,
|
|
||||||
css,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-card/paper-card";
|
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
|
||||||
import "../../../components/ha-service-description";
|
|
||||||
import {
|
import {
|
||||||
Cluster,
|
Cluster,
|
||||||
Command,
|
Command,
|
||||||
@ -18,13 +26,12 @@ import {
|
|||||||
} from "../../../data/zha";
|
} from "../../../data/zha";
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
import { formatAsPaddedHex } from "./functions";
|
||||||
import {
|
import {
|
||||||
ChangeEvent,
|
ChangeEvent,
|
||||||
IssueCommandServiceData,
|
IssueCommandServiceData,
|
||||||
ItemSelectedEvent,
|
ItemSelectedEvent,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import { formatAsPaddedHex } from "./functions";
|
|
||||||
|
|
||||||
export class ZHAClusterCommands extends LitElement {
|
export class ZHAClusterCommands extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
@ -107,7 +114,7 @@ export class ZHAClusterCommands extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
${this._showHelp
|
${this._showHelp
|
||||||
? html`
|
? html`
|
||||||
<div class="helpText">Select a command to interact with</div>
|
<div class="help-text">Select a command to interact with</div>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
${this._selectedCommandIndex !== -1
|
${this._selectedCommandIndex !== -1
|
||||||
@ -135,6 +142,7 @@ export class ZHAClusterCommands extends LitElement {
|
|||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
domain="zha"
|
domain="zha"
|
||||||
service="issue_zigbee_cluster_command"
|
service="issue_zigbee_cluster_command"
|
||||||
|
class="help-text2"
|
||||||
></ha-service-description>
|
></ha-service-description>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@ -242,7 +250,14 @@ export class ZHAClusterCommands extends LitElement {
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.helpText {
|
.help-text {
|
||||||
|
color: grey;
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-text2 {
|
||||||
color: grey;
|
color: grey;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,27 @@
|
|||||||
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../components/ha-service-description";
|
||||||
|
import "../ha-config-section";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||||
|
import "@polymer/paper-item/paper-item";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
CSSResult,
|
|
||||||
css,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-card/paper-card";
|
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
|
||||||
import "../../../components/ha-service-description";
|
|
||||||
import { Cluster, fetchClustersForZhaNode, ZHADevice } from "../../../data/zha";
|
import { Cluster, fetchClustersForZhaNode, ZHADevice } from "../../../data/zha";
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
|
||||||
import { ItemSelectedEvent } from "./types";
|
|
||||||
import { formatAsPaddedHex } from "./functions";
|
import { formatAsPaddedHex } from "./functions";
|
||||||
|
import { ItemSelectedEvent } from "./types";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// for fire event
|
// for fire event
|
||||||
@ -90,7 +95,7 @@ export class ZHAClusters extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
${this.showHelp
|
${this.showHelp
|
||||||
? html`
|
? html`
|
||||||
<div class="helpText">
|
<div class="help-text">
|
||||||
Select cluster to view attributes and commands
|
Select cluster to view attributes and commands
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
@ -143,9 +148,11 @@ export class ZHAClusters extends LitElement {
|
|||||||
padding-right: 28px;
|
padding-right: 28px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
.helpText {
|
.help-text {
|
||||||
color: grey;
|
color: grey;
|
||||||
padding: 16px;
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 16px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
70
src/panels/config/zha/zha-config-panel.ts
Normal file
70
src/panels/config/zha/zha-config-panel.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import "../../../layouts/hass-loading-screen";
|
||||||
|
|
||||||
|
import { customElement, property } from "lit-element";
|
||||||
|
|
||||||
|
import { listenMediaQuery } from "../../../common/dom/media_query";
|
||||||
|
import {
|
||||||
|
HassRouterPage,
|
||||||
|
RouterOptions,
|
||||||
|
} from "../../../layouts/hass-router-page";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
|
@customElement("zha-config-panel")
|
||||||
|
class ZHAConfigPanel extends HassRouterPage {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
@property() public _wideSidebar: boolean = false;
|
||||||
|
@property() public _wide: boolean = false;
|
||||||
|
|
||||||
|
protected routerOptions: RouterOptions = {
|
||||||
|
defaultPage: "configuration",
|
||||||
|
cacheAll: true,
|
||||||
|
preloadAll: true,
|
||||||
|
routes: {
|
||||||
|
configuration: {
|
||||||
|
tag: "ha-config-zha",
|
||||||
|
load: () =>
|
||||||
|
import(/* webpackChunkName: "zha-configuration-page" */ "./ha-config-zha"),
|
||||||
|
},
|
||||||
|
add: {
|
||||||
|
tag: "zha-add-devices-page",
|
||||||
|
load: () =>
|
||||||
|
import(/* webpackChunkName: "zha-add-devices-page" */ "./zha-add-devices-page"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
private _listeners: Array<() => void> = [];
|
||||||
|
|
||||||
|
public connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
this._listeners.push(
|
||||||
|
listenMediaQuery("(min-width: 1040px)", (matches) => {
|
||||||
|
this._wide = matches;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this._listeners.push(
|
||||||
|
listenMediaQuery("(min-width: 1296px)", (matches) => {
|
||||||
|
this._wideSidebar = matches;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public disconnectedCallback(): void {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
while (this._listeners.length) {
|
||||||
|
this._listeners.pop()!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updatePageEl(el): void {
|
||||||
|
el.route = this.routeTail;
|
||||||
|
el.hass = this.hass;
|
||||||
|
el.isWide = this.hass.dockedSidebar ? this._wideSidebar : this._wide;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"zha-config-panel": ZHAConfigPanel;
|
||||||
|
}
|
||||||
|
}
|
@ -1,40 +1,123 @@
|
|||||||
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../components/entity/state-badge";
|
||||||
|
import "@material/mwc-button";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@polymer/paper-item/paper-icon-item";
|
||||||
|
import "@polymer/paper-item/paper-item";
|
||||||
|
import "@polymer/paper-item/paper-item-body";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
customElement,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
CSSResult,
|
|
||||||
css,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-item/paper-icon-item";
|
|
||||||
import "@polymer/paper-item/paper-item-body";
|
|
||||||
import "@polymer/paper-card/paper-card";
|
|
||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
|
||||||
import "@polymer/paper-item/paper-item";
|
|
||||||
import "@polymer/paper-listbox/paper-listbox";
|
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import compare from "../../../common/string/compare";
|
||||||
|
import {
|
||||||
|
AreaRegistryEntry,
|
||||||
|
fetchAreaRegistry,
|
||||||
|
} from "../../../data/area_registry";
|
||||||
|
import {
|
||||||
|
DeviceRegistryEntryMutableParams,
|
||||||
|
updateDeviceRegistryEntry,
|
||||||
|
} from "../../../data/device_registry";
|
||||||
|
import { reconfigureNode, ZHADevice } from "../../../data/zha";
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { ItemSelectedEvent, NodeServiceData } from "./types";
|
||||||
|
|
||||||
import "../../../components/entity/state-badge";
|
declare global {
|
||||||
import { ZHADevice } from "../../../data/zha";
|
// for fire event
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"zha-device-removed": {
|
||||||
|
device?: ZHADevice;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement("zha-device-card")
|
||||||
class ZHADeviceCard extends LitElement {
|
class ZHADeviceCard extends LitElement {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
@property() public narrow?: boolean;
|
@property() public narrow?: boolean;
|
||||||
@property() public device?: ZHADevice;
|
@property() public device?: ZHADevice;
|
||||||
|
@property() public showHelp: boolean = false;
|
||||||
|
@property() public showActions?: boolean;
|
||||||
|
@property() public isJoinPage?: boolean;
|
||||||
|
@property() private _serviceData?: NodeServiceData;
|
||||||
|
@property() private _areas: AreaRegistryEntry[] = [];
|
||||||
|
@property() private _selectedAreaIndex: number = -1;
|
||||||
|
|
||||||
|
public firstUpdated(changedProperties: PropertyValues): void {
|
||||||
|
super.firstUpdated(changedProperties);
|
||||||
|
this.addEventListener("hass-service-called", (ev) =>
|
||||||
|
this.serviceCalled(ev)
|
||||||
|
);
|
||||||
|
this._serviceData = {
|
||||||
|
ieee_address: this.device!.ieee,
|
||||||
|
};
|
||||||
|
fetchAreaRegistry(this.hass!).then((areas) => {
|
||||||
|
this._areas = areas.sort((a, b) => compare(a.name, b.name));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updated(changedProperties: PropertyValues): void {
|
||||||
|
if (changedProperties.has("device")) {
|
||||||
|
this._selectedAreaIndex =
|
||||||
|
this._areas.findIndex((area) => area.area_id === this.device!.area_id) +
|
||||||
|
1;
|
||||||
|
}
|
||||||
|
super.update(changedProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected serviceCalled(ev): void {
|
||||||
|
// Check if this is for us
|
||||||
|
if (ev.detail.success && ev.detail.service === "remove") {
|
||||||
|
fireEvent(this, "zha-device-removed", {
|
||||||
|
device: this.device,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
<paper-card>
|
<paper-card heading="${this.isJoinPage ? this.device!.name : ""}">
|
||||||
|
${
|
||||||
|
this.isJoinPage
|
||||||
|
? html`
|
||||||
|
<div class="info">
|
||||||
|
<div class="model">${this.device!.model}</div>
|
||||||
|
<div class="manuf">
|
||||||
|
${this.hass!.localize(
|
||||||
|
"ui.panel.config.integrations.config_entry.manuf",
|
||||||
|
"manufacturer",
|
||||||
|
this.device!.manufacturer
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<dl>
|
<dl>
|
||||||
<dt class="label">IEEE:</dt>
|
<dt>IEEE:</dt>
|
||||||
<dd class="info">${this.device!.ieee}</dd>
|
<dd class="zha-info">${this.device!.ieee}</dd>
|
||||||
<dt class="label">Quirk applied:</dt>
|
${
|
||||||
<dd class="info">${this.device!.quirk_applied}</dd>
|
this.device!.quirk_applied
|
||||||
<dt class="label">Quirk:</dt>
|
? html`
|
||||||
<dd class="info">${this.device!.quirk_class}</dd>
|
<dt>Quirk:</dt>
|
||||||
|
<dd class="zha-info">${this.device!.quirk_class}</dd>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -49,24 +132,145 @@ class ZHADeviceCard extends LitElement {
|
|||||||
.stateObj="${this.hass!.states[entity.entity_id]}"
|
.stateObj="${this.hass!.states[entity.entity_id]}"
|
||||||
slot="item-icon"
|
slot="item-icon"
|
||||||
></state-badge>
|
></state-badge>
|
||||||
<paper-item-body>
|
${!this.isJoinPage
|
||||||
<div class="name">${entity.name}</div>
|
? html`
|
||||||
<div class="secondary entity-id">${entity.entity_id}</div>
|
<paper-item-body>
|
||||||
</paper-item-body>
|
<div class="name">${entity.name}</div>
|
||||||
|
<div class="secondary entity-id">
|
||||||
|
${entity.entity_id}
|
||||||
|
</div>
|
||||||
|
</paper-item-body>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="editable">
|
||||||
|
<paper-input
|
||||||
|
type="string"
|
||||||
|
@change="${this._saveCustomName}"
|
||||||
|
placeholder="${this.hass!.localize(
|
||||||
|
"ui.panel.config.zha.device_card.device_name_placeholder"
|
||||||
|
)}"
|
||||||
|
></paper-input>
|
||||||
|
</div>
|
||||||
|
<div class="node-picker">
|
||||||
|
<paper-dropdown-menu
|
||||||
|
label="${this.hass!.localize(
|
||||||
|
"ui.panel.config.zha.device_card.area_picker_label"
|
||||||
|
)}"
|
||||||
|
class="flex"
|
||||||
|
>
|
||||||
|
<paper-listbox
|
||||||
|
slot="dropdown-content"
|
||||||
|
.selected="${this._selectedAreaIndex}"
|
||||||
|
@iron-select="${this._selectedAreaChanged}"
|
||||||
|
>
|
||||||
|
<paper-item>
|
||||||
|
${this.hass!.localize(
|
||||||
|
"ui.panel.config.integrations.config_entry.no_area"
|
||||||
|
)}
|
||||||
|
</paper-item>
|
||||||
|
|
||||||
|
${this._areas.map(
|
||||||
|
(entry) => html`
|
||||||
|
<paper-item area="${entry}">${entry.name}</paper-item>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
${
|
||||||
|
this.showActions
|
||||||
|
? html`
|
||||||
|
<div class="card-actions">
|
||||||
|
<mwc-button @click="${this._onReconfigureNodeClick}"
|
||||||
|
>Reconfigure Device</mwc-button
|
||||||
|
>
|
||||||
|
${this.showHelp
|
||||||
|
? html`
|
||||||
|
<div class="help-text">
|
||||||
|
${this.hass!.localize(
|
||||||
|
"ui.panel.config.zha.services.reconfigure"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
|
||||||
|
<ha-call-service-button
|
||||||
|
.hass="${this.hass}"
|
||||||
|
domain="zha"
|
||||||
|
service="remove"
|
||||||
|
.serviceData="${this._serviceData}"
|
||||||
|
>Remove Device</ha-call-service-button
|
||||||
|
>
|
||||||
|
${this.showHelp
|
||||||
|
? html`
|
||||||
|
<div class="help-text">
|
||||||
|
${this.hass!.localize(
|
||||||
|
"ui.panel.config.zha.services.remove"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</paper-card>
|
</paper-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _onReconfigureNodeClick(): Promise<void> {
|
||||||
|
if (this.hass) {
|
||||||
|
await reconfigureNode(this.hass, this.device!.ieee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _saveCustomName(event): Promise<void> {
|
||||||
|
if (this.hass) {
|
||||||
|
const values: DeviceRegistryEntryMutableParams = {
|
||||||
|
name_by_user: event.target.value,
|
||||||
|
area_id: this.device!.area_id ? this.device!.area_id : undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
await updateDeviceRegistryEntry(
|
||||||
|
this.hass,
|
||||||
|
this.device!.device_reg_id,
|
||||||
|
values
|
||||||
|
);
|
||||||
|
|
||||||
|
this.device!.user_given_name = event.target.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _openMoreInfo(ev: MouseEvent): void {
|
private _openMoreInfo(ev: MouseEvent): void {
|
||||||
fireEvent(this, "hass-more-info", {
|
fireEvent(this, "hass-more-info", {
|
||||||
entityId: (ev.currentTarget as any).entity.entity_id,
|
entityId: (ev.currentTarget as any).entity.entity_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _selectedAreaChanged(event: ItemSelectedEvent) {
|
||||||
|
if (!this.device || !this._areas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._selectedAreaIndex = event!.target!.selected;
|
||||||
|
const area = this._areas[this._selectedAreaIndex - 1]; // account for No Area
|
||||||
|
if (
|
||||||
|
(!area && !this.device.area_id) ||
|
||||||
|
(area && area.area_id === this.device.area_id)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateDeviceRegistryEntry(this.hass!, this.device.device_reg_id, {
|
||||||
|
area_id: area ? area.area_id : undefined,
|
||||||
|
name_by_user: this.device!.user_given_name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
@ -74,29 +278,43 @@ class ZHADeviceCard extends LitElement {
|
|||||||
:host(:not([narrow])) .device-entities {
|
:host(:not([narrow])) .device-entities {
|
||||||
max-height: 225px;
|
max-height: 225px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 4px;
|
||||||
|
justify-content: left;
|
||||||
}
|
}
|
||||||
paper-card {
|
paper-card {
|
||||||
flex: 1 0 100%;
|
flex: 1 0 100%;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
min-width: 0;
|
min-width: 425px;
|
||||||
}
|
}
|
||||||
.device {
|
.device {
|
||||||
width: 30%;
|
width: 30%;
|
||||||
}
|
}
|
||||||
.label {
|
.device .name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
.device .manuf {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
.extra-info {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
.manuf,
|
||||||
|
.zha-info,
|
||||||
|
.entity-id {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
.info {
|
.info {
|
||||||
color: var(--secondary-text-color);
|
margin-left: 16px;
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
dl dt {
|
dl dt {
|
||||||
|
padding-left: 12px;
|
||||||
float: left;
|
float: left;
|
||||||
width: 100px;
|
width: 50px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
dt dd {
|
dt dd {
|
||||||
margin-left: 10px;
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
paper-icon-item {
|
paper-icon-item {
|
||||||
@ -104,6 +322,36 @@ class ZHADeviceCard extends LitElement {
|
|||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
.editable {
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
.help-text {
|
||||||
|
color: grey;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
.flex {
|
||||||
|
-ms-flex: 1 1 0.000000001px;
|
||||||
|
-webkit-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
-webkit-flex-basis: 0.000000001px;
|
||||||
|
flex-basis: 0.000000001px;
|
||||||
|
}
|
||||||
|
.node-picker {
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: -webkit-flex;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex-direction: row;
|
||||||
|
-webkit-flex-direction: row;
|
||||||
|
flex-direction: row;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
-webkit-align-items: center;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -114,5 +362,3 @@ declare global {
|
|||||||
"zha-device-card": ZHADeviceCard;
|
"zha-device-card": ZHADeviceCard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("zha-device-card", ZHADeviceCard);
|
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../components/ha-service-description";
|
||||||
|
import "../ha-config-section";
|
||||||
|
import "@material/mwc-button";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
CSSResult,
|
|
||||||
css,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@material/mwc-button";
|
|
||||||
import "@polymer/paper-card/paper-card";
|
import { navigate } from "../../../common/navigate";
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
|
||||||
import "../../../components/ha-service-description";
|
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
|
||||||
|
|
||||||
export class ZHANetwork extends LitElement {
|
export class ZHANetwork extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
@ -30,6 +33,7 @@ export class ZHANetwork extends LitElement {
|
|||||||
hass: {},
|
hass: {},
|
||||||
isWide: {},
|
isWide: {},
|
||||||
_showHelp: {},
|
_showHelp: {},
|
||||||
|
_joinParams: {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,29 +41,31 @@ export class ZHANetwork extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-config-section .isWide="${this.isWide}">
|
<ha-config-section .isWide="${this.isWide}">
|
||||||
<div style="position: relative" slot="header">
|
<div style="position: relative" slot="header">
|
||||||
<span>Network Management</span>
|
<span>Network Management</span>
|
||||||
<paper-icon-button class="toggle-help-icon" @click="${
|
<paper-icon-button
|
||||||
this._onHelpTap
|
class="toggle-help-icon"
|
||||||
}" icon="hass:help-circle"></paper-icon-button>
|
@click="${this._onHelpTap}"
|
||||||
|
icon="hass:help-circle"
|
||||||
|
></paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
<span slot="introduction">Commands that affect entire network</span>
|
<span slot="introduction">Commands that affect entire network</span>
|
||||||
|
|
||||||
<paper-card class="content">
|
<paper-card class="content">
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<ha-call-service-button .hass="${
|
<mwc-button @click=${this._onAddDevicesClick}>
|
||||||
this.hass
|
Add Devices
|
||||||
}" domain="zha" service="permit">Permit</ha-call-service-button>
|
</mwc-button>
|
||||||
${
|
${this._showHelp
|
||||||
this._showHelp
|
? html`
|
||||||
? html`
|
<ha-service-description
|
||||||
<ha-service-description
|
.hass="${this.hass}"
|
||||||
.hass="${this.hass}"
|
domain="zha"
|
||||||
domain="zha"
|
service="permit"
|
||||||
service="permit"
|
class="help-text2"
|
||||||
/>
|
/>
|
||||||
`
|
`
|
||||||
: ""
|
: ""}
|
||||||
}
|
</div>
|
||||||
</paper-card>
|
</paper-card>
|
||||||
</ha-config-section>
|
</ha-config-section>
|
||||||
`;
|
`;
|
||||||
@ -69,6 +75,10 @@ export class ZHANetwork extends LitElement {
|
|||||||
this._showHelp = !this._showHelp;
|
this._showHelp = !this._showHelp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _onAddDevicesClick() {
|
||||||
|
navigate(this, "add");
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
@ -102,6 +112,11 @@ export class ZHANetwork extends LitElement {
|
|||||||
[hidden] {
|
[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.help-text2 {
|
||||||
|
color: grey;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,30 @@
|
|||||||
import {
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
html,
|
import "../../../components/ha-service-description";
|
||||||
LitElement,
|
import "../ha-config-section";
|
||||||
PropertyDeclarations,
|
import "./zha-clusters";
|
||||||
TemplateResult,
|
import "./zha-device-card";
|
||||||
CSSResult,
|
|
||||||
PropertyValues,
|
|
||||||
css,
|
|
||||||
} from "lit-element";
|
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import "@polymer/paper-card/paper-card";
|
import "@polymer/paper-card/paper-card";
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
import "@polymer/paper-listbox/paper-listbox";
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
|
||||||
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
import { fetchDevices, ZHADevice } from "../../../data/zha";
|
||||||
import "../../../components/ha-service-description";
|
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
import { ItemSelectedEvent, ZHADeviceRemovedEvent } from "./types";
|
||||||
import { ItemSelectedEvent, NodeServiceData, ChangeEvent } from "./types";
|
|
||||||
import "./zha-clusters";
|
|
||||||
import "./zha-device-card";
|
|
||||||
import {
|
|
||||||
updateDeviceRegistryEntry,
|
|
||||||
DeviceRegistryEntryMutableParams,
|
|
||||||
} from "../../../data/device_registry";
|
|
||||||
import { reconfigureNode, fetchDevices, ZHADevice } from "../../../data/zha";
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// for fire event
|
// for fire event
|
||||||
@ -37,60 +35,25 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@customElement("zha-node")
|
||||||
export class ZHANode extends LitElement {
|
export class ZHANode extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
public isWide?: boolean;
|
@property() public isWide?: boolean;
|
||||||
private _showHelp: boolean;
|
@property() private _showHelp: boolean = false;
|
||||||
private _selectedNodeIndex: number;
|
@property() private _selectedDeviceIndex: number = -1;
|
||||||
private _selectedNode?: ZHADevice;
|
@property() private _selectedDevice?: ZHADevice;
|
||||||
private _serviceData?: {};
|
@property() private _nodes: ZHADevice[] = [];
|
||||||
private _nodes: ZHADevice[];
|
|
||||||
private _userSelectedName?: string;
|
|
||||||
|
|
||||||
constructor() {
|
public connectedCallback(): void {
|
||||||
super();
|
super.connectedCallback();
|
||||||
this._showHelp = false;
|
this._fetchDevices();
|
||||||
this._selectedNodeIndex = -1;
|
|
||||||
this._nodes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties(): PropertyDeclarations {
|
|
||||||
return {
|
|
||||||
hass: {},
|
|
||||||
isWide: {},
|
|
||||||
_showHelp: {},
|
|
||||||
_selectedNodeIndex: {},
|
|
||||||
_selectedNode: {},
|
|
||||||
_entities: {},
|
|
||||||
_serviceData: {},
|
|
||||||
_nodes: {},
|
|
||||||
_userSelectedName: {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public firstUpdated(changedProperties: PropertyValues): void {
|
|
||||||
super.firstUpdated(changedProperties);
|
|
||||||
if (this._nodes.length === 0) {
|
|
||||||
this._fetchDevices();
|
|
||||||
}
|
|
||||||
this.addEventListener("hass-service-called", (ev) =>
|
|
||||||
this.serviceCalled(ev)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected serviceCalled(ev): void {
|
|
||||||
// Check if this is for us
|
|
||||||
if (ev.detail.success && ev.detail.service === "remove") {
|
|
||||||
this._selectedNodeIndex = -1;
|
|
||||||
this._fetchDevices();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
<ha-config-section .isWide="${this.isWide}">
|
<ha-config-section .isWide="${this.isWide}">
|
||||||
<div class="sectionHeader" slot="header">
|
<div class="sectionHeader" slot="header">
|
||||||
<span>Node Management</span>
|
<span>Device Management</span>
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
class="toggle-help-icon"
|
class="toggle-help-icon"
|
||||||
@click="${this._onHelpTap}"
|
@click="${this._onHelpTap}"
|
||||||
@ -98,8 +61,8 @@ export class ZHANode extends LitElement {
|
|||||||
></paper-icon-button>
|
></paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
<span slot="introduction">
|
<span slot="introduction">
|
||||||
Run ZHA commands that affect a single node. Pick a node to see a list
|
Run ZHA commands that affect a single device. Pick a device to see a
|
||||||
of available commands. <br /><br />Note: Sleepy (battery powered)
|
list of available commands. <br /><br />Note: Sleepy (battery powered)
|
||||||
devices need to be awake when executing commands against them. You can
|
devices need to be awake when executing commands against them. You can
|
||||||
generally wake a sleepy device by triggering it. <br /><br />Some
|
generally wake a sleepy device by triggering it. <br /><br />Some
|
||||||
devices such as Xiaomi sensors have a wake up button that you can
|
devices such as Xiaomi sensors have a wake up button that you can
|
||||||
@ -108,11 +71,15 @@ export class ZHANode extends LitElement {
|
|||||||
</span>
|
</span>
|
||||||
<paper-card class="content">
|
<paper-card class="content">
|
||||||
<div class="node-picker">
|
<div class="node-picker">
|
||||||
<paper-dropdown-menu label="Nodes" class="flex">
|
<paper-dropdown-menu
|
||||||
|
label="Devices"
|
||||||
|
class="flex"
|
||||||
|
id="zha-device-selector"
|
||||||
|
>
|
||||||
<paper-listbox
|
<paper-listbox
|
||||||
slot="dropdown-content"
|
slot="dropdown-content"
|
||||||
@iron-select="${this._selectedNodeChanged}"
|
@iron-select="${this._selectedDeviceChanged}"
|
||||||
.selected="${this._selectedNodeIndex}"
|
.selected="${this._selectedDeviceIndex}"
|
||||||
>
|
>
|
||||||
${this._nodes.map(
|
${this._nodes.map(
|
||||||
(entry) => html`
|
(entry) => html`
|
||||||
@ -128,95 +95,36 @@ export class ZHANode extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
${this._showHelp
|
${this._showHelp
|
||||||
? html`
|
? html`
|
||||||
<div class="helpText">
|
<div class="help-text">
|
||||||
Select node to view per-node options
|
Select device to view per-device options
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
${this._selectedNodeIndex !== -1
|
${this._selectedDeviceIndex !== -1
|
||||||
? html`
|
? html`
|
||||||
<zha-device-card
|
<zha-device-card
|
||||||
class="card"
|
class="card"
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
.device="${this._selectedNode}"
|
.device="${this._selectedDevice}"
|
||||||
.narrow="${!this.isWide}"
|
.narrow="${!this.isWide}"
|
||||||
|
.showHelp="${this._showHelp}"
|
||||||
|
.showActions="${true}"
|
||||||
|
@zha-device-removed="${this._onDeviceRemoved}"
|
||||||
|
.isJoinPage="${false}"
|
||||||
></zha-device-card>
|
></zha-device-card>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
${this._selectedNodeIndex !== -1
|
${this._selectedDevice ? this._renderClusters() : ""}
|
||||||
? html`
|
|
||||||
<div class="input-text">
|
|
||||||
<paper-input
|
|
||||||
type="string"
|
|
||||||
.value="${this._userSelectedName}"
|
|
||||||
@value-changed="${this._onUserSelectedNameChanged}"
|
|
||||||
placeholder="User given name"
|
|
||||||
></paper-input>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
${this._selectedNodeIndex !== -1 ? this._renderNodeActions() : ""}
|
|
||||||
${this._selectedNode ? this._renderClusters() : ""}
|
|
||||||
</paper-card>
|
</paper-card>
|
||||||
</ha-config-section>
|
</ha-config-section>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderNodeActions(): TemplateResult {
|
|
||||||
return html`
|
|
||||||
<div class="card-actions">
|
|
||||||
<mwc-button @click="${this._onReconfigureNodeClick}"
|
|
||||||
>Reconfigure Node</mwc-button
|
|
||||||
>
|
|
||||||
${this._showHelp
|
|
||||||
? html`
|
|
||||||
<div class="helpText">
|
|
||||||
${this.hass!.localize(
|
|
||||||
"ui.panel.config.zha.services.reconfigure"
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
<ha-call-service-button
|
|
||||||
.hass="${this.hass}"
|
|
||||||
domain="zha"
|
|
||||||
service="remove"
|
|
||||||
.serviceData="${this._serviceData}"
|
|
||||||
>Remove Node</ha-call-service-button
|
|
||||||
>
|
|
||||||
${this._showHelp
|
|
||||||
? html`
|
|
||||||
<ha-service-description
|
|
||||||
.hass="${this.hass}"
|
|
||||||
domain="zha"
|
|
||||||
service="remove"
|
|
||||||
/>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
<mwc-button
|
|
||||||
@click="${this._onUpdateDeviceNameClick}"
|
|
||||||
.disabled="${!this._userSelectedName ||
|
|
||||||
this._userSelectedName === ""}"
|
|
||||||
>Update Name</mwc-button
|
|
||||||
>
|
|
||||||
${this._showHelp
|
|
||||||
? html`
|
|
||||||
<div class="helpText">
|
|
||||||
${this.hass!.localize(
|
|
||||||
"ui.panel.config.zha.services.updateDeviceName"
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderClusters(): TemplateResult {
|
private _renderClusters(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<zha-clusters
|
<zha-clusters
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
.selectedDevice="${this._selectedNode}"
|
.selectedDevice="${this._selectedDevice}"
|
||||||
.showHelp="${this._showHelp}"
|
.showHelp="${this._showHelp}"
|
||||||
></zha-clusters>
|
></zha-clusters>
|
||||||
`;
|
`;
|
||||||
@ -226,45 +134,10 @@ export class ZHANode extends LitElement {
|
|||||||
this._showHelp = !this._showHelp;
|
this._showHelp = !this._showHelp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _selectedNodeChanged(event: ItemSelectedEvent): void {
|
private _selectedDeviceChanged(event: ItemSelectedEvent): void {
|
||||||
this._selectedNodeIndex = event!.target!.selected;
|
this._selectedDeviceIndex = event!.target!.selected;
|
||||||
this._selectedNode = this._nodes[this._selectedNodeIndex];
|
this._selectedDevice = this._nodes[this._selectedDeviceIndex];
|
||||||
this._userSelectedName = "";
|
fireEvent(this, "zha-node-selected", { node: this._selectedDevice });
|
||||||
fireEvent(this, "zha-node-selected", { node: this._selectedNode });
|
|
||||||
this._serviceData = this._computeNodeServiceData();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _onReconfigureNodeClick(): Promise<void> {
|
|
||||||
if (this.hass) {
|
|
||||||
await reconfigureNode(this.hass, this._selectedNode!.ieee);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _onUserSelectedNameChanged(value: ChangeEvent): void {
|
|
||||||
this._userSelectedName = value.detail!.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _onUpdateDeviceNameClick(): Promise<void> {
|
|
||||||
if (this.hass) {
|
|
||||||
const values: DeviceRegistryEntryMutableParams = {
|
|
||||||
name_by_user: this._userSelectedName,
|
|
||||||
};
|
|
||||||
|
|
||||||
await updateDeviceRegistryEntry(
|
|
||||||
this.hass,
|
|
||||||
this._selectedNode!.device_reg_id,
|
|
||||||
values
|
|
||||||
);
|
|
||||||
|
|
||||||
this._selectedNode!.user_given_name = this._userSelectedName!;
|
|
||||||
this._userSelectedName = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _computeNodeServiceData(): NodeServiceData {
|
|
||||||
return {
|
|
||||||
ieee_address: this._selectedNode!.ieee,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _fetchDevices() {
|
private async _fetchDevices() {
|
||||||
@ -273,6 +146,13 @@ export class ZHANode extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _onDeviceRemoved(event: ZHADeviceRemovedEvent): void {
|
||||||
|
this._selectedDeviceIndex = -1;
|
||||||
|
this._nodes.splice(this._nodes.indexOf(event.detail!.device!), 1);
|
||||||
|
this._selectedDevice = undefined;
|
||||||
|
fireEvent(this, "zha-node-selected", { node: this._selectedDevice });
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
@ -298,13 +178,10 @@ export class ZHANode extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.help-text {
|
.help-text {
|
||||||
|
color: grey;
|
||||||
padding-left: 28px;
|
padding-left: 28px;
|
||||||
padding-right: 28px;
|
padding-right: 28px;
|
||||||
}
|
padding-bottom: 16px;
|
||||||
|
|
||||||
.helpText {
|
|
||||||
color: grey;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
paper-card {
|
paper-card {
|
||||||
@ -355,12 +232,6 @@ export class ZHANode extends LitElement {
|
|||||||
right: 0;
|
right: 0;
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-text {
|
|
||||||
padding-left: 28px;
|
|
||||||
padding-right: 28px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -371,5 +242,3 @@ declare global {
|
|||||||
"zha-node": ZHANode;
|
"zha-node": ZHANode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("zha-node", ZHANode);
|
|
||||||
|
@ -1,50 +1,69 @@
|
|||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { property, PropertyValues, UpdatingElement } from "lit-element";
|
||||||
|
import { loadCustomPanel } from "../../util/custom-panel/load-custom-panel";
|
||||||
|
import { createCustomPanelElement } from "../../util/custom-panel/create-custom-panel-element";
|
||||||
|
import { setCustomPanelProperties } from "../../util/custom-panel/set-custom-panel-properties";
|
||||||
|
import { HomeAssistant, Route, Panel } from "../../types";
|
||||||
|
import { CustomPanelConfig } from "../../data/panel_custom";
|
||||||
|
|
||||||
import EventsMixin from "../../mixins/events-mixin";
|
declare global {
|
||||||
import NavigateMixin from "../../mixins/navigate-mixin";
|
interface Window {
|
||||||
import loadCustomPanel from "../../util/custom-panel/load-custom-panel";
|
customPanel: HaPanelCustom | undefined;
|
||||||
import createCustomPanelElement from "../../util/custom-panel/create-custom-panel-element";
|
}
|
||||||
import setCustomPanelProperties from "../../util/custom-panel/set-custom-panel-properties";
|
}
|
||||||
|
|
||||||
/*
|
export class HaPanelCustom extends UpdatingElement {
|
||||||
* Mixins are used by ifram to communicate with main frontend.
|
@property() public hass!: HomeAssistant;
|
||||||
* @appliesMixin EventsMixin
|
@property() public narrow!: boolean;
|
||||||
* @appliesMixin NavigateMixin
|
@property() public route!: Route;
|
||||||
*/
|
@property() public panel!: Panel;
|
||||||
class HaPanelCustom extends NavigateMixin(EventsMixin(PolymerElement)) {
|
private _setProperties?: (props: {}) => void | undefined;
|
||||||
static get properties() {
|
|
||||||
return {
|
public registerIframe(initialize, setProperties) {
|
||||||
hass: Object,
|
initialize(this.panel, {
|
||||||
narrow: Boolean,
|
hass: this.hass,
|
||||||
route: Object,
|
narrow: this.narrow,
|
||||||
panel: {
|
route: this.route,
|
||||||
type: Object,
|
});
|
||||||
observer: "_panelChanged",
|
this._setProperties = setProperties;
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static get observers() {
|
public disconnectedCallback() {
|
||||||
return ["_dataChanged(hass, narrow, route)"];
|
super.disconnectedCallback();
|
||||||
|
this._cleanupPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
protected updated(changedProps: PropertyValues) {
|
||||||
super();
|
if (changedProps.has("panel")) {
|
||||||
this._setProperties = null;
|
// Clean up old things if we had a panel
|
||||||
|
if (changedProps.get("panel")) {
|
||||||
|
this._cleanupPanel();
|
||||||
|
}
|
||||||
|
this._createPanel(this.panel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this._setProperties) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const props = {};
|
||||||
|
for (const key of changedProps.keys()) {
|
||||||
|
props[key] = this[key];
|
||||||
|
}
|
||||||
|
this._setProperties(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
_panelChanged(panel) {
|
private _cleanupPanel() {
|
||||||
// Clean up
|
|
||||||
delete window.customPanel;
|
delete window.customPanel;
|
||||||
this._setProperties = null;
|
this._setProperties = undefined;
|
||||||
while (this.lastChild) {
|
while (this.lastChild) {
|
||||||
this.removeChild(this.lastChild);
|
this.removeChild(this.lastChild);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const config = panel.config._panel_custom;
|
private _createPanel(panel: Panel) {
|
||||||
|
const config = panel.config!._panel_custom as CustomPanelConfig;
|
||||||
|
|
||||||
const tempA = document.createElement("a");
|
const tempA = document.createElement("a");
|
||||||
tempA.href = config.html_url || config.js_url || config.module_url;
|
tempA.href = config.html_url || config.js_url || config.module_url || "";
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!config.trust_external &&
|
!config.trust_external &&
|
||||||
@ -96,32 +115,13 @@ It will have access to all data in Home Assistant.
|
|||||||
</style>
|
</style>
|
||||||
<iframe></iframe>
|
<iframe></iframe>
|
||||||
`.trim();
|
`.trim();
|
||||||
const iframeDoc = this.querySelector("iframe").contentWindow.document;
|
const iframeDoc = this.querySelector("iframe")!.contentWindow!.document;
|
||||||
iframeDoc.open();
|
iframeDoc.open();
|
||||||
iframeDoc.write(
|
iframeDoc.write(
|
||||||
`<!doctype html><script src='${window.customPanelJS}'></script>`
|
`<!doctype html><script src='${window.customPanelJS}'></script>`
|
||||||
);
|
);
|
||||||
iframeDoc.close();
|
iframeDoc.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback() {
|
|
||||||
super.disconnectedCallback();
|
|
||||||
delete window.customPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dataChanged(hass, narrow, route) {
|
|
||||||
if (!this._setProperties) return;
|
|
||||||
this._setProperties({ hass, narrow, route });
|
|
||||||
}
|
|
||||||
|
|
||||||
registerIframe(initialize, setProperties) {
|
|
||||||
initialize(this.panel, {
|
|
||||||
hass: this.hass,
|
|
||||||
narrow: this.narrow,
|
|
||||||
route: this.route,
|
|
||||||
});
|
|
||||||
this._setProperties = setProperties;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("ha-panel-custom", HaPanelCustom);
|
customElements.define("ha-panel-custom", HaPanelCustom);
|
@ -10,17 +10,17 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
|
import "../../../components/ha-card";
|
||||||
|
import "../../../components/ha-label-badge";
|
||||||
|
import "../components/hui-warning";
|
||||||
|
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import {
|
import {
|
||||||
callAlarmAction,
|
callAlarmAction,
|
||||||
FORMAT_NUMBER,
|
FORMAT_NUMBER,
|
||||||
} from "../../../data/alarm_control_panel";
|
} from "../../../data/alarm_control_panel";
|
||||||
|
import { AlarmPanelCardConfig } from "./types";
|
||||||
import "../../../components/ha-card";
|
|
||||||
import "../../../components/ha-label-badge";
|
|
||||||
import "../components/hui-warning";
|
|
||||||
|
|
||||||
const ICONS = {
|
const ICONS = {
|
||||||
armed_away: "hass:shield-lock",
|
armed_away: "hass:shield-lock",
|
||||||
@ -34,12 +34,6 @@ const ICONS = {
|
|||||||
|
|
||||||
const BUTTONS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "clear"];
|
const BUTTONS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "clear"];
|
||||||
|
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
entity: string;
|
|
||||||
name?: string;
|
|
||||||
states?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-alarm-panel-card")
|
@customElement("hui-alarm-panel-card")
|
||||||
class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
||||||
public static async getConfigElement() {
|
public static async getConfigElement() {
|
||||||
@ -53,7 +47,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: AlarmPanelCardConfig;
|
||||||
|
|
||||||
@property() private _code?: string;
|
@property() private _code?: string;
|
||||||
|
|
||||||
@ -69,7 +63,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
: 8;
|
: 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: AlarmPanelCardConfig): void {
|
||||||
if (
|
if (
|
||||||
!config ||
|
!config ||
|
||||||
!config.entity ||
|
!config.entity ||
|
||||||
@ -305,7 +299,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
.actions mwc-button {
|
.actions mwc-button {
|
||||||
min-width: calc(var(--base-unit) * 9);
|
min-width: calc(var(--base-unit) * 9);
|
||||||
margin: 0 4px;
|
margin: 0 4px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
mwc-button#disarm {
|
mwc-button#disarm {
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
import { createCardElement } from "../common/create-card-element";
|
import { createCardElement } from "../common/create-card-element";
|
||||||
import { computeCardSize } from "../common/compute-card-size";
|
import { computeCardSize } from "../common/compute-card-size";
|
||||||
import {
|
import {
|
||||||
Condition,
|
|
||||||
checkConditionsMet,
|
checkConditionsMet,
|
||||||
validateConditionalConfig,
|
validateConditionalConfig,
|
||||||
} from "../../lovelace/common/validate-condition";
|
} from "../../lovelace/common/validate-condition";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { ConditionalCardConfig } from "./types";
|
||||||
|
|
||||||
interface Config extends LovelaceCardConfig {
|
|
||||||
card: LovelaceCardConfig;
|
|
||||||
conditions: Condition[];
|
|
||||||
}
|
|
||||||
|
|
||||||
class HuiConditionalCard extends HTMLElement implements LovelaceCard {
|
class HuiConditionalCard extends HTMLElement implements LovelaceCard {
|
||||||
private _hass?: HomeAssistant;
|
private _hass?: HomeAssistant;
|
||||||
private _config?: Config;
|
private _config?: ConditionalCardConfig;
|
||||||
private _card?: LovelaceCard;
|
private _card?: LovelaceCard;
|
||||||
|
|
||||||
public setConfig(config) {
|
public setConfig(config) {
|
||||||
|
@ -11,13 +11,8 @@ import {
|
|||||||
import "@polymer/paper-card/paper-card";
|
import "@polymer/paper-card/paper-card";
|
||||||
|
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { EmptyStateCardConfig } from "./types";
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
content: string;
|
|
||||||
title?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-empty-state-card")
|
@customElement("hui-empty-state-card")
|
||||||
export class HuiEmptyStateCard extends LitElement implements LovelaceCard {
|
export class HuiEmptyStateCard extends LitElement implements LovelaceCard {
|
||||||
@ -27,7 +22,7 @@ export class HuiEmptyStateCard extends LitElement implements LovelaceCard {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(_config: Config): void {
|
public setConfig(_config: EmptyStateCardConfig): void {
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,30 +15,15 @@ import "../components/hui-entities-toggle";
|
|||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
|
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { EntityConfig, EntityRow } from "../entity-rows/types";
|
import { EntityRow } from "../entity-rows/types";
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import { processConfigEntities } from "../common/process-config-entities";
|
import { processConfigEntities } from "../common/process-config-entities";
|
||||||
import { createRowElement } from "../common/create-row-element";
|
import { createRowElement } from "../common/create-row-element";
|
||||||
|
import { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types";
|
||||||
|
|
||||||
import computeDomain from "../../../common/entity/compute_domain";
|
import computeDomain from "../../../common/entity/compute_domain";
|
||||||
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
||||||
|
|
||||||
export interface EntitiesCardEntityConfig extends EntityConfig {
|
|
||||||
type?: string;
|
|
||||||
secondary_info?: "entity-id" | "last-changed";
|
|
||||||
action_name?: string;
|
|
||||||
service?: string;
|
|
||||||
service_data?: object;
|
|
||||||
url?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EntitiesCardConfig extends LovelaceCardConfig {
|
|
||||||
show_header_toggle?: boolean;
|
|
||||||
title?: string;
|
|
||||||
entities: EntitiesCardEntityConfig[];
|
|
||||||
theme?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-entities-card")
|
@customElement("hui-entities-card")
|
||||||
class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
||||||
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
||||||
|
@ -21,21 +21,13 @@ import computeStateDomain from "../../../common/entity/compute_state_domain";
|
|||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
||||||
import computeDomain from "../../../common/entity/compute_domain";
|
import computeDomain from "../../../common/entity/compute_domain";
|
||||||
|
|
||||||
import { HomeAssistant, LightEntity } from "../../../types";
|
import { HomeAssistant, LightEntity } from "../../../types";
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace";
|
|
||||||
import { longPress } from "../common/directives/long-press-directive";
|
import { longPress } from "../common/directives/long-press-directive";
|
||||||
import { handleClick } from "../common/handle-click";
|
import { handleClick } from "../common/handle-click";
|
||||||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||||
|
import { EntityButtonCardConfig } from "./types";
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
entity: string;
|
|
||||||
name?: string;
|
|
||||||
icon?: string;
|
|
||||||
theme?: string;
|
|
||||||
tap_action?: ActionConfig;
|
|
||||||
hold_action?: ActionConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-entity-button-card")
|
@customElement("hui-entity-button-card")
|
||||||
class HuiEntityButtonCard extends LitElement implements LovelaceCard {
|
class HuiEntityButtonCard extends LitElement implements LovelaceCard {
|
||||||
@ -48,18 +40,20 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard {
|
|||||||
return {
|
return {
|
||||||
tap_action: { action: "toggle" },
|
tap_action: { action: "toggle" },
|
||||||
hold_action: { action: "more-info" },
|
hold_action: { action: "more-info" },
|
||||||
|
show_icon: true,
|
||||||
|
show_name: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: EntityButtonCardConfig;
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: EntityButtonCardConfig): void {
|
||||||
if (!isValidEntityId(config.entity)) {
|
if (!isValidEntityId(config.entity)) {
|
||||||
throw new Error("Invalid Entity");
|
throw new Error("Invalid Entity");
|
||||||
}
|
}
|
||||||
@ -67,6 +61,8 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard {
|
|||||||
this._config = {
|
this._config = {
|
||||||
theme: "default",
|
theme: "default",
|
||||||
hold_action: { action: "more-info" },
|
hold_action: { action: "more-info" },
|
||||||
|
show_icon: true,
|
||||||
|
show_name: true,
|
||||||
...config,
|
...config,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -126,18 +122,26 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard {
|
|||||||
@ha-hold="${this._handleHold}"
|
@ha-hold="${this._handleHold}"
|
||||||
.longPress="${longPress()}"
|
.longPress="${longPress()}"
|
||||||
>
|
>
|
||||||
<ha-icon
|
${this._config.show_icon
|
||||||
data-domain="${computeStateDomain(stateObj)}"
|
? html`
|
||||||
data-state="${stateObj.state}"
|
<ha-icon
|
||||||
.icon="${this._config.icon || stateIcon(stateObj)}"
|
data-domain="${computeStateDomain(stateObj)}"
|
||||||
style="${styleMap({
|
data-state="${stateObj.state}"
|
||||||
filter: this._computeBrightness(stateObj),
|
.icon="${this._config.icon || stateIcon(stateObj)}"
|
||||||
color: this._computeColor(stateObj),
|
style="${styleMap({
|
||||||
})}"
|
filter: this._computeBrightness(stateObj),
|
||||||
></ha-icon>
|
color: this._computeColor(stateObj),
|
||||||
<span>
|
})}"
|
||||||
${this._config.name || computeStateName(stateObj)}
|
></ha-icon>
|
||||||
</span>
|
`
|
||||||
|
: ""}
|
||||||
|
${this._config.show_name
|
||||||
|
? html`
|
||||||
|
<span>
|
||||||
|
${this._config.name || computeStateName(stateObj)}
|
||||||
|
</span>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
<mwc-ripple></mwc-ripple>
|
<mwc-ripple></mwc-ripple>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
|
@ -4,14 +4,7 @@ import { LovelaceCard } from "../types";
|
|||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||||
import { EntityConfig } from "../entity-rows/types";
|
import { EntityConfig } from "../entity-rows/types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { EntityFilterCardConfig } from "./types";
|
||||||
export interface EntityFilterCardConfig extends LovelaceCardConfig {
|
|
||||||
type: "entity-filter";
|
|
||||||
entities: Array<EntityConfig | string>;
|
|
||||||
state_filter: string[];
|
|
||||||
card: Partial<LovelaceCardConfig>;
|
|
||||||
show_empty?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class EntityFilterCard extends HTMLElement implements LovelaceCard {
|
class EntityFilterCard extends HTMLElement implements LovelaceCard {
|
||||||
public isPanel?: boolean;
|
public isPanel?: boolean;
|
||||||
|
@ -11,11 +11,7 @@ import {
|
|||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { ErrorCardConfig } from "./types";
|
||||||
interface Config extends LovelaceCardConfig {
|
|
||||||
error: string;
|
|
||||||
origConfig: LovelaceCardConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createErrorCardElement = (config) => {
|
export const createErrorCardElement = (config) => {
|
||||||
const el = document.createElement("hui-error-card");
|
const el = document.createElement("hui-error-card");
|
||||||
@ -33,13 +29,13 @@ export const createErrorCardConfig = (error, origConfig) => ({
|
|||||||
export class HuiErrorCard extends LitElement implements LovelaceCard {
|
export class HuiErrorCard extends LitElement implements LovelaceCard {
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: ErrorCardConfig;
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: ErrorCardConfig): void {
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,31 +13,15 @@ import { styleMap } from "lit-html/directives/style-map";
|
|||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../components/hui-warning";
|
import "../components/hui-warning";
|
||||||
|
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
|
||||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
|
||||||
|
|
||||||
import isValidEntityId from "../../../common/entity/valid_entity_id";
|
import isValidEntityId from "../../../common/entity/valid_entity_id";
|
||||||
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
|
|
||||||
export interface SeverityConfig {
|
import { HomeAssistant } from "../../../types";
|
||||||
green?: number;
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
yellow?: number;
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
red?: number;
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
}
|
import { GaugeCardConfig } from "./types";
|
||||||
|
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
entity: string;
|
|
||||||
name?: string;
|
|
||||||
unit?: string;
|
|
||||||
min?: number;
|
|
||||||
max?: number;
|
|
||||||
severity?: SeverityConfig;
|
|
||||||
theme?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const severityMap = {
|
export const severityMap = {
|
||||||
red: "var(--label-badge-red)",
|
red: "var(--label-badge-red)",
|
||||||
@ -58,7 +42,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: GaugeCardConfig;
|
||||||
|
|
||||||
private _updated?: boolean;
|
private _updated?: boolean;
|
||||||
|
|
||||||
@ -66,7 +50,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: GaugeCardConfig): void {
|
||||||
if (!config || !config.entity) {
|
if (!config || !config.entity) {
|
||||||
throw new Error("Invalid card configuration");
|
throw new Error("Invalid card configuration");
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,6 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
|
||||||
import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace";
|
|
||||||
import { longPress } from "../common/directives/long-press-directive";
|
|
||||||
import { EntityConfig } from "../entity-rows/types";
|
|
||||||
import { processConfigEntities } from "../common/process-config-entities";
|
|
||||||
import { handleClick } from "../common/handle-click";
|
|
||||||
|
|
||||||
import computeStateDisplay from "../../../common/entity/compute_state_display";
|
import computeStateDisplay from "../../../common/entity/compute_state_display";
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
||||||
@ -25,22 +17,14 @@ import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
|||||||
import "../../../components/entity/state-badge";
|
import "../../../components/entity/state-badge";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../../../components/ha-icon";
|
import "../../../components/ha-icon";
|
||||||
import "../components/hui-warning";
|
import "../components/hui-warning-element";
|
||||||
|
|
||||||
export interface ConfigEntity extends EntityConfig {
|
import { HomeAssistant } from "../../../types";
|
||||||
tap_action?: ActionConfig;
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
hold_action?: ActionConfig;
|
import { longPress } from "../common/directives/long-press-directive";
|
||||||
}
|
import { processConfigEntities } from "../common/process-config-entities";
|
||||||
|
import { handleClick } from "../common/handle-click";
|
||||||
export interface GlanceCardConfig extends LovelaceCardConfig {
|
import { GlanceCardConfig, ConfigEntity } from "./types";
|
||||||
show_name?: boolean;
|
|
||||||
show_state?: boolean;
|
|
||||||
show_icon?: boolean;
|
|
||||||
title?: string;
|
|
||||||
theme?: string;
|
|
||||||
entities: ConfigEntity[];
|
|
||||||
columns?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-glance-card")
|
@customElement("hui-glance-card")
|
||||||
export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||||
@ -184,13 +168,13 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
if (!stateObj) {
|
if (!stateObj) {
|
||||||
return html`
|
return html`
|
||||||
<hui-warning
|
<hui-warning-element
|
||||||
>${this.hass!.localize(
|
label=${this.hass!.localize(
|
||||||
"ui.panel.lovelace.warning.entity_not_found",
|
"ui.panel.lovelace.warning.entity_not_found",
|
||||||
"entity",
|
"entity",
|
||||||
entityConf.entity
|
entityConf.entity
|
||||||
)}</hui-warning
|
)}
|
||||||
>
|
></hui-warning-element>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,14 +11,8 @@ import {
|
|||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import { styleMap } from "lit-html/directives/style-map";
|
import { styleMap } from "lit-html/directives/style-map";
|
||||||
|
import { IframeCardConfig } from "./types";
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
aspect_ratio?: string;
|
|
||||||
title?: string;
|
|
||||||
url: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-iframe-card")
|
@customElement("hui-iframe-card")
|
||||||
export class HuiIframeCard extends LitElement implements LovelaceCard {
|
export class HuiIframeCard extends LitElement implements LovelaceCard {
|
||||||
@ -30,7 +24,7 @@ export class HuiIframeCard extends LitElement implements LovelaceCard {
|
|||||||
return { url: "https://www.home-assistant.io", aspect_ratio: "50%" };
|
return { url: "https://www.home-assistant.io", aspect_ratio: "50%" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() protected _config?: Config;
|
@property() protected _config?: IframeCardConfig;
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
@ -42,7 +36,7 @@ export class HuiIframeCard extends LitElement implements LovelaceCard {
|
|||||||
return 1 + aspectRatio / 25;
|
return 1 + aspectRatio / 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: IframeCardConfig): void {
|
||||||
if (!config.url) {
|
if (!config.url) {
|
||||||
throw new Error("URL required");
|
throw new Error("URL required");
|
||||||
}
|
}
|
||||||
|
@ -8,15 +8,6 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
|
||||||
import { styleMap } from "lit-html/directives/style-map";
|
|
||||||
import { HomeAssistant, LightEntity } from "../../../types";
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
|
||||||
import { loadRoundslider } from "../../../resources/jquery.roundslider.ondemand";
|
|
||||||
import { toggleEntity } from "../common/entity/toggle-entity";
|
|
||||||
|
|
||||||
import stateIcon from "../../../common/entity/state_icon";
|
import stateIcon from "../../../common/entity/state_icon";
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
||||||
@ -25,6 +16,15 @@ import "../../../components/ha-card";
|
|||||||
import "../../../components/ha-icon";
|
import "../../../components/ha-icon";
|
||||||
import "../components/hui-warning";
|
import "../components/hui-warning";
|
||||||
|
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { styleMap } from "lit-html/directives/style-map";
|
||||||
|
import { HomeAssistant, LightEntity } from "../../../types";
|
||||||
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
import { loadRoundslider } from "../../../resources/jquery.roundslider.ondemand";
|
||||||
|
import { toggleEntity } from "../common/entity/toggle-entity";
|
||||||
|
import { LightCardConfig } from "./types";
|
||||||
|
|
||||||
const lightConfig = {
|
const lightConfig = {
|
||||||
radius: 80,
|
radius: 80,
|
||||||
step: 1,
|
step: 1,
|
||||||
@ -40,12 +40,6 @@ const lightConfig = {
|
|||||||
animation: false,
|
animation: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
entity: string;
|
|
||||||
name?: string;
|
|
||||||
theme?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-light-card")
|
@customElement("hui-light-card")
|
||||||
export class HuiLightCard extends LitElement implements LovelaceCard {
|
export class HuiLightCard extends LitElement implements LovelaceCard {
|
||||||
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
||||||
@ -58,7 +52,7 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: LightCardConfig;
|
||||||
|
|
||||||
@property() private _roundSliderStyle?: TemplateResult;
|
@property() private _roundSliderStyle?: TemplateResult;
|
||||||
|
|
||||||
@ -70,7 +64,7 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: LightCardConfig): void {
|
||||||
if (!config.entity || config.entity.split(".")[0] !== "light") {
|
if (!config.entity || config.entity.split(".")[0] !== "light") {
|
||||||
throw new Error("Specify an entity from within the light domain.");
|
throw new Error("Specify an entity from within the light domain.");
|
||||||
}
|
}
|
||||||
|
@ -21,20 +21,13 @@ import computeStateDomain from "../../../common/entity/compute_state_domain";
|
|||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
import debounce from "../../../common/util/debounce";
|
import debounce from "../../../common/util/debounce";
|
||||||
import parseAspectRatio from "../../../common/util/parse-aspect-ratio";
|
import parseAspectRatio from "../../../common/util/parse-aspect-ratio";
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import computeDomain from "../../../common/entity/compute_domain";
|
import computeDomain from "../../../common/entity/compute_domain";
|
||||||
|
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import { EntityConfig } from "../entity-rows/types";
|
import { EntityConfig } from "../entity-rows/types";
|
||||||
import { processConfigEntities } from "../common/process-config-entities";
|
import { processConfigEntities } from "../common/process-config-entities";
|
||||||
|
import { MapCardConfig } from "./types";
|
||||||
export interface MapCardConfig extends LovelaceCardConfig {
|
|
||||||
title: string;
|
|
||||||
aspect_ratio: string;
|
|
||||||
default_zoom?: number;
|
|
||||||
entities?: Array<EntityConfig | string>;
|
|
||||||
geo_location_sources?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-map-card")
|
@customElement("hui-map-card")
|
||||||
class HuiMapCard extends LitElement implements LovelaceCard {
|
class HuiMapCard extends LitElement implements LovelaceCard {
|
||||||
|
@ -13,12 +13,7 @@ import "../../../components/ha-card";
|
|||||||
import "../../../components/ha-markdown";
|
import "../../../components/ha-markdown";
|
||||||
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { MarkdownCardConfig } from "./types";
|
||||||
|
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
content: string;
|
|
||||||
title?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-markdown-card")
|
@customElement("hui-markdown-card")
|
||||||
export class HuiMarkdownCard extends LitElement implements LovelaceCard {
|
export class HuiMarkdownCard extends LitElement implements LovelaceCard {
|
||||||
@ -31,13 +26,13 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard {
|
|||||||
return { content: " " };
|
return { content: " " };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: MarkdownCardConfig;
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
return this._config!.content.split("\n").length;
|
return this._config!.content.split("\n").length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: MarkdownCardConfig): void {
|
||||||
if (!config.content) {
|
if (!config.content) {
|
||||||
throw new Error("Invalid Configuration: Content Required");
|
throw new Error("Invalid Configuration: Content Required");
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,6 @@ import "../../../cards/ha-media_player-card";
|
|||||||
|
|
||||||
import LegacyWrapperCard from "./hui-legacy-wrapper-card";
|
import LegacyWrapperCard from "./hui-legacy-wrapper-card";
|
||||||
|
|
||||||
// should be interface when converted to TS
|
|
||||||
export const Config = {
|
|
||||||
entity: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
class HuiMediaControlCard extends LegacyWrapperCard {
|
class HuiMediaControlCard extends LegacyWrapperCard {
|
||||||
static async getConfigElement() {
|
static async getConfigElement() {
|
||||||
await import(/* webpackChunkName: "hui-media-control-card-editor" */ "../editor/config-elements/hui-media-control-card-editor");
|
await import(/* webpackChunkName: "hui-media-control-card-editor" */ "../editor/config-elements/hui-media-control-card-editor");
|
||||||
|
@ -11,17 +11,11 @@ import {
|
|||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
import { handleClick } from "../common/handle-click";
|
import { handleClick } from "../common/handle-click";
|
||||||
import { longPress } from "../common/directives/long-press-directive";
|
import { longPress } from "../common/directives/long-press-directive";
|
||||||
|
import { PictureCardConfig } from "./types";
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
image?: string;
|
|
||||||
tap_action?: ActionConfig;
|
|
||||||
hold_action?: ActionConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-picture-card")
|
@customElement("hui-picture-card")
|
||||||
export class HuiPictureCard extends LitElement implements LovelaceCard {
|
export class HuiPictureCard extends LitElement implements LovelaceCard {
|
||||||
@ -40,13 +34,13 @@ export class HuiPictureCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() protected _config?: Config;
|
@property() protected _config?: PictureCardConfig;
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: PictureCardConfig): void {
|
||||||
if (!config || !config.image) {
|
if (!config || !config.image) {
|
||||||
throw new Error("Invalid Configuration: 'image' required");
|
throw new Error("Invalid Configuration: 'image' required");
|
||||||
}
|
}
|
||||||
|
@ -9,25 +9,14 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import { createStyledHuiElement } from "./picture-elements/create-styled-hui-element";
|
import { createStyledHuiElement } from "./picture-elements/create-styled-hui-element";
|
||||||
|
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
|
import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
|
||||||
|
import { PictureElementsCardConfig } from "./types";
|
||||||
interface Config extends LovelaceCardConfig {
|
|
||||||
title?: string;
|
|
||||||
image?: string;
|
|
||||||
camera_image?: string;
|
|
||||||
state_image?: {};
|
|
||||||
aspect_ratio?: string;
|
|
||||||
entity?: string;
|
|
||||||
elements: LovelaceElementConfig[];
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-picture-elements-card")
|
@customElement("hui-picture-elements-card")
|
||||||
class HuiPictureElementsCard extends LitElement implements LovelaceCard {
|
class HuiPictureElementsCard extends LitElement implements LovelaceCard {
|
||||||
@property() private _config?: Config;
|
@property() private _config?: PictureElementsCardConfig;
|
||||||
|
|
||||||
private _hass?: HomeAssistant;
|
private _hass?: HomeAssistant;
|
||||||
|
|
||||||
@ -43,7 +32,7 @@ class HuiPictureElementsCard extends LitElement implements LovelaceCard {
|
|||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: PictureElementsCardConfig): void {
|
||||||
if (!config) {
|
if (!config) {
|
||||||
throw new Error("Invalid Configuration");
|
throw new Error("Invalid Configuration");
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
property,
|
property,
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
@ -19,35 +20,23 @@ import computeStateName from "../../../common/entity/compute_state_name";
|
|||||||
|
|
||||||
import { longPress } from "../common/directives/long-press-directive";
|
import { longPress } from "../common/directives/long-press-directive";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace";
|
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { handleClick } from "../common/handle-click";
|
import { handleClick } from "../common/handle-click";
|
||||||
import { UNAVAILABLE } from "../../../data/entity";
|
import { UNAVAILABLE } from "../../../data/entity";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
interface Config extends LovelaceCardConfig {
|
import { PictureEntityCardConfig } from "./types";
|
||||||
entity: string;
|
|
||||||
name?: string;
|
|
||||||
image?: string;
|
|
||||||
camera_image?: string;
|
|
||||||
state_image?: {};
|
|
||||||
aspect_ratio?: string;
|
|
||||||
tap_action?: ActionConfig;
|
|
||||||
hold_action?: ActionConfig;
|
|
||||||
show_name?: boolean;
|
|
||||||
show_state?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-picture-entity-card")
|
@customElement("hui-picture-entity-card")
|
||||||
class HuiPictureEntityCard extends LitElement implements LovelaceCard {
|
class HuiPictureEntityCard extends LitElement implements LovelaceCard {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: PictureEntityCardConfig;
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: PictureEntityCardConfig): void {
|
||||||
if (!config || !config.entity) {
|
if (!config || !config.entity) {
|
||||||
throw new Error("Invalid Configuration: 'entity' required");
|
throw new Error("Invalid Configuration: 'entity' required");
|
||||||
}
|
}
|
||||||
@ -62,6 +51,10 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
|
|||||||
this._config = { show_name: true, show_state: true, ...config };
|
this._config = { show_name: true, show_state: true, ...config };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
|
@ -6,16 +6,10 @@ import {
|
|||||||
property,
|
property,
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
|
||||||
import { LovelaceCard } from "../types";
|
|
||||||
import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace";
|
|
||||||
import { EntityConfig } from "../entity-rows/types";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import { longPress } from "../common/directives/long-press-directive";
|
|
||||||
import { processConfigEntities } from "../common/process-config-entities";
|
|
||||||
import computeStateDisplay from "../../../common/entity/compute_state_display";
|
import computeStateDisplay from "../../../common/entity/compute_state_display";
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
import computeDomain from "../../../common/entity/compute_domain";
|
import computeDomain from "../../../common/entity/compute_domain";
|
||||||
@ -24,29 +18,26 @@ import stateIcon from "../../../common/entity/state_icon";
|
|||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../../../components/ha-icon";
|
import "../../../components/ha-icon";
|
||||||
import "../components/hui-image";
|
import "../components/hui-image";
|
||||||
|
import "../components/hui-warning-element";
|
||||||
|
|
||||||
|
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||||
|
import { LovelaceCard } from "../types";
|
||||||
|
import { EntityConfig } from "../entity-rows/types";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { longPress } from "../common/directives/long-press-directive";
|
||||||
|
import { processConfigEntities } from "../common/process-config-entities";
|
||||||
import { handleClick } from "../common/handle-click";
|
import { handleClick } from "../common/handle-click";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { toggleEntity } from "../common/entity/toggle-entity";
|
import { toggleEntity } from "../common/entity/toggle-entity";
|
||||||
|
import { PictureGlanceCardConfig } from "./types";
|
||||||
|
|
||||||
const STATES_OFF = new Set(["closed", "locked", "not_home", "off"]);
|
const STATES_OFF = new Set(["closed", "locked", "not_home", "off"]);
|
||||||
|
|
||||||
interface Config extends LovelaceCardConfig {
|
|
||||||
entities: EntityConfig[];
|
|
||||||
title?: string;
|
|
||||||
image?: string;
|
|
||||||
camera_image?: string;
|
|
||||||
state_image?: {};
|
|
||||||
aspect_ratio?: string;
|
|
||||||
entity?: string;
|
|
||||||
tap_action?: ActionConfig;
|
|
||||||
hold_action?: ActionConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-picture-glance-card")
|
@customElement("hui-picture-glance-card")
|
||||||
class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
|
class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: PictureGlanceCardConfig;
|
||||||
|
|
||||||
private _entitiesDialog?: EntityConfig[];
|
private _entitiesDialog?: EntityConfig[];
|
||||||
|
|
||||||
@ -56,7 +47,7 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: PictureGlanceCardConfig): void {
|
||||||
if (
|
if (
|
||||||
!config ||
|
!config ||
|
||||||
!config.entities ||
|
!config.entities ||
|
||||||
@ -85,6 +76,39 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
if (changedProps.has("_config")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||||
|
if (!oldHass) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._entitiesDialog) {
|
||||||
|
for (const entity of this._entitiesDialog) {
|
||||||
|
if (
|
||||||
|
oldHass.states[entity.entity] !== this.hass!.states[entity.entity]
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._entitiesToggle) {
|
||||||
|
for (const entity of this._entitiesToggle) {
|
||||||
|
if (
|
||||||
|
oldHass.states[entity.entity] !== this.hass!.states[entity.entity]
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
@ -138,7 +162,15 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
|
|||||||
const stateObj = this.hass!.states[entityConf.entity];
|
const stateObj = this.hass!.states[entityConf.entity];
|
||||||
|
|
||||||
if (!stateObj) {
|
if (!stateObj) {
|
||||||
return html``;
|
return html`
|
||||||
|
<hui-warning-element
|
||||||
|
label=${this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.warning.entity_not_found",
|
||||||
|
"entity",
|
||||||
|
entityConf.entity
|
||||||
|
)}
|
||||||
|
></hui-warning-element>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
|
@ -6,18 +6,20 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
property,
|
property,
|
||||||
customElement,
|
customElement,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../../../components/ha-icon";
|
import "../../../components/ha-icon";
|
||||||
|
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
|
|
||||||
import { LovelaceCardEditor, LovelaceCard } from "../types";
|
import { LovelaceCardEditor, LovelaceCard } from "../types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
import { PlantStatusCardConfig, PlantAttributeTarget } from "./types";
|
||||||
|
|
||||||
const SENSORS = {
|
const SENSORS = {
|
||||||
moisture: "hass:water",
|
moisture: "hass:water",
|
||||||
@ -27,15 +29,6 @@ const SENSORS = {
|
|||||||
battery: "hass:battery",
|
battery: "hass:battery",
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface PlantAttributeTarget extends EventTarget {
|
|
||||||
value?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PlantStatusConfig extends LovelaceCardConfig {
|
|
||||||
name?: string;
|
|
||||||
entity: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-plant-status-card")
|
@customElement("hui-plant-status-card")
|
||||||
class HuiPlantStatusCard extends LitElement implements LovelaceCard {
|
class HuiPlantStatusCard extends LitElement implements LovelaceCard {
|
||||||
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
||||||
@ -49,13 +42,13 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: PlantStatusConfig;
|
@property() private _config?: PlantStatusCardConfig;
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: PlantStatusConfig): void {
|
public setConfig(config: PlantStatusCardConfig): void {
|
||||||
if (!config.entity || config.entity.split(".")[0] !== "plant") {
|
if (!config.entity || config.entity.split(".")[0] !== "plant") {
|
||||||
throw new Error("Specify an entity from within the plant domain.");
|
throw new Error("Specify an entity from within the plant domain.");
|
||||||
}
|
}
|
||||||
@ -63,6 +56,10 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass || !this._config) {
|
if (!this.hass || !this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
@ -91,7 +88,7 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard {
|
|||||||
style="background-image:url(${stateObj.attributes.entity_picture})"
|
style="background-image:url(${stateObj.attributes.entity_picture})"
|
||||||
>
|
>
|
||||||
<div class="header">
|
<div class="header">
|
||||||
${this._config.title || computeStateName(stateObj)}
|
${this._config.name || computeStateName(stateObj)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
@ -11,12 +11,6 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
|
||||||
import { fetchRecent } from "../../../data/history";
|
|
||||||
|
|
||||||
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
import stateIcon from "../../../common/entity/state_icon";
|
import stateIcon from "../../../common/entity/state_icon";
|
||||||
@ -25,6 +19,13 @@ import "../../../components/ha-card";
|
|||||||
import "../../../components/ha-icon";
|
import "../../../components/ha-icon";
|
||||||
import "../components/hui-warning";
|
import "../components/hui-warning";
|
||||||
|
|
||||||
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { fetchRecent } from "../../../data/history";
|
||||||
|
import { SensorCardConfig } from "./types";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
const midPoint = (
|
const midPoint = (
|
||||||
_Ax: number,
|
_Ax: number,
|
||||||
_Ay: number,
|
_Ay: number,
|
||||||
@ -137,17 +138,6 @@ const coordinates = (
|
|||||||
return calcPoints(history, hours, width, detail, min, max);
|
return calcPoints(history, hours, width, detail, min, max);
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
entity: string;
|
|
||||||
name?: string;
|
|
||||||
icon?: string;
|
|
||||||
graph?: string;
|
|
||||||
unit?: string;
|
|
||||||
detail?: number;
|
|
||||||
theme?: string;
|
|
||||||
hours_to_show?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-sensor-card")
|
@customElement("hui-sensor-card")
|
||||||
class HuiSensorCard extends LitElement implements LovelaceCard {
|
class HuiSensorCard extends LitElement implements LovelaceCard {
|
||||||
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
||||||
@ -161,13 +151,13 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: SensorCardConfig;
|
||||||
|
|
||||||
@property() private _history?: any;
|
@property() private _history?: any;
|
||||||
|
|
||||||
private _date?: Date;
|
private _date?: Date;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: SensorCardConfig): void {
|
||||||
if (!config.entity || config.entity.split(".")[0] !== "sensor") {
|
if (!config.entity || config.entity.split(".")[0] !== "sensor") {
|
||||||
throw new Error("Specify an entity from within the sensor domain.");
|
throw new Error("Specify an entity from within the sensor domain.");
|
||||||
}
|
}
|
||||||
@ -272,6 +262,14 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
this._date = new Date();
|
this._date = new Date();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
if (changedProps.has("_history")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues) {
|
protected updated(changedProps: PropertyValues) {
|
||||||
super.updated(changedProps);
|
super.updated(changedProps);
|
||||||
if (!this._config || this._config.graph !== "line" || !this.hass) {
|
if (!this._config || this._config.graph !== "line" || !this.hass) {
|
||||||
|
@ -16,7 +16,6 @@ import "../../../components/ha-icon";
|
|||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import {
|
import {
|
||||||
fetchItems,
|
fetchItems,
|
||||||
updateItem,
|
updateItem,
|
||||||
@ -24,10 +23,7 @@ import {
|
|||||||
clearItems,
|
clearItems,
|
||||||
addItem,
|
addItem,
|
||||||
} from "../../../data/shopping-list";
|
} from "../../../data/shopping-list";
|
||||||
|
import { ShoppingListCardConfig } from "./types";
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
title?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-shopping-list-card")
|
@customElement("hui-shopping-list-card")
|
||||||
class HuiShoppingListCard extends LitElement implements LovelaceCard {
|
class HuiShoppingListCard extends LitElement implements LovelaceCard {
|
||||||
@ -42,7 +38,7 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: ShoppingListCardConfig;
|
||||||
|
|
||||||
@property() private _uncheckedItems?: ShoppingListItem[];
|
@property() private _uncheckedItems?: ShoppingListItem[];
|
||||||
|
|
||||||
@ -54,7 +50,7 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard {
|
|||||||
return (this._config ? (this._config.title ? 1 : 0) : 0) + 3;
|
return (this._config ? (this._config.title ? 1 : 0) : 0) + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: ShoppingListCardConfig): void {
|
||||||
this._config = config;
|
this._config = config;
|
||||||
this._uncheckedItems = [];
|
this._uncheckedItems = [];
|
||||||
this._checkedItems = [];
|
this._checkedItems = [];
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
import { html, LitElement, TemplateResult } from "lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
|
|
||||||
import { createCardElement } from "../common/create-card-element";
|
import { createCardElement } from "../common/create-card-element";
|
||||||
|
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { StackCardConfig } from "./types";
|
||||||
interface Config extends LovelaceCardConfig {
|
|
||||||
cards: LovelaceCardConfig[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class HuiStackCard extends LitElement implements LovelaceCard {
|
export abstract class HuiStackCard extends LitElement implements LovelaceCard {
|
||||||
static get properties() {
|
static get properties() {
|
||||||
@ -29,12 +25,12 @@ export abstract class HuiStackCard extends LitElement implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected _cards?: LovelaceCard[];
|
protected _cards?: LovelaceCard[];
|
||||||
private _config?: Config;
|
private _config?: StackCardConfig;
|
||||||
private _hass?: HomeAssistant;
|
private _hass?: HomeAssistant;
|
||||||
|
|
||||||
public abstract getCardSize(): number;
|
public abstract getCardSize(): number;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: StackCardConfig): void {
|
||||||
if (!config || !config.cards || !Array.isArray(config.cards)) {
|
if (!config || !config.cards || !Array.isArray(config.cards)) {
|
||||||
throw new Error("Card config incorrect");
|
throw new Error("Card config incorrect");
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,10 @@ import computeStateName from "../../../common/entity/compute_state_name";
|
|||||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
import { HomeAssistant, ClimateEntity } from "../../../types";
|
import { HomeAssistant, ClimateEntity } from "../../../types";
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
|
||||||
import { loadRoundslider } from "../../../resources/jquery.roundslider.ondemand";
|
import { loadRoundslider } from "../../../resources/jquery.roundslider.ondemand";
|
||||||
import { UNIT_F } from "../../../common/const";
|
import { UNIT_F } from "../../../common/const";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { ThermostatCardConfig } from "./types";
|
||||||
|
|
||||||
const thermostatConfig = {
|
const thermostatConfig = {
|
||||||
radius: 150,
|
radius: 150,
|
||||||
@ -47,12 +47,6 @@ const modeIcons = {
|
|||||||
idle: "hass:power-sleep",
|
idle: "hass:power-sleep",
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Config extends LovelaceCardConfig {
|
|
||||||
entity: string;
|
|
||||||
theme?: string;
|
|
||||||
name?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-thermostat-card")
|
@customElement("hui-thermostat-card")
|
||||||
export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||||
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
||||||
@ -66,7 +60,7 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: ThermostatCardConfig;
|
||||||
|
|
||||||
@property() private _roundSliderStyle?: TemplateResult;
|
@property() private _roundSliderStyle?: TemplateResult;
|
||||||
|
|
||||||
@ -82,7 +76,7 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
|||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: ThermostatCardConfig): void {
|
||||||
if (!config.entity || config.entity.split(".")[0] !== "climate") {
|
if (!config.entity || config.entity.split(".")[0] !== "climate") {
|
||||||
throw new Error("Specify an entity from within the climate domain.");
|
throw new Error("Specify an entity from within the climate domain.");
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,6 @@ import "../../../cards/ha-weather-card";
|
|||||||
|
|
||||||
import LegacyWrapperCard from "./hui-legacy-wrapper-card";
|
import LegacyWrapperCard from "./hui-legacy-wrapper-card";
|
||||||
|
|
||||||
// should be interface when converted to TS
|
|
||||||
export const Config = {
|
|
||||||
entity: "",
|
|
||||||
name: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
class HuiWeatherForecastCard extends LegacyWrapperCard {
|
class HuiWeatherForecastCard extends LegacyWrapperCard {
|
||||||
static async getConfigElement() {
|
static async getConfigElement() {
|
||||||
await import(/* webpackChunkName: "hui-weather-forecast-card-editor" */ "../editor/config-elements/hui-weather-forecast-card-editor");
|
await import(/* webpackChunkName: "hui-weather-forecast-card-editor" */ "../editor/config-elements/hui-weather-forecast-card-editor");
|
||||||
|
200
src/panels/lovelace/cards/types.ts
Normal file
200
src/panels/lovelace/cards/types.ts
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace";
|
||||||
|
import { Condition } from "../common/validate-condition";
|
||||||
|
import { EntityConfig } from "../entity-rows/types";
|
||||||
|
import { LovelaceElementConfig } from "../elements/types";
|
||||||
|
|
||||||
|
export interface AlarmPanelCardConfig extends LovelaceCardConfig {
|
||||||
|
entity: string;
|
||||||
|
name?: string;
|
||||||
|
states?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConditionalCardConfig extends LovelaceCardConfig {
|
||||||
|
card: LovelaceCardConfig;
|
||||||
|
conditions: Condition[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EmptyStateCardConfig extends LovelaceCardConfig {
|
||||||
|
content: string;
|
||||||
|
title?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EntitiesCardEntityConfig extends EntityConfig {
|
||||||
|
type?: string;
|
||||||
|
secondary_info?: "entity-id" | "last-changed";
|
||||||
|
action_name?: string;
|
||||||
|
service?: string;
|
||||||
|
service_data?: object;
|
||||||
|
url?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EntitiesCardConfig extends LovelaceCardConfig {
|
||||||
|
show_header_toggle?: boolean;
|
||||||
|
title?: string;
|
||||||
|
entities: EntitiesCardEntityConfig[];
|
||||||
|
theme?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EntityButtonCardConfig extends LovelaceCardConfig {
|
||||||
|
entity: string;
|
||||||
|
name?: string;
|
||||||
|
show_name?: boolean;
|
||||||
|
icon?: string;
|
||||||
|
show_icon?: boolean;
|
||||||
|
theme?: string;
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
hold_action?: ActionConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EntityFilterCardConfig extends LovelaceCardConfig {
|
||||||
|
type: "entity-filter";
|
||||||
|
entities: Array<EntityConfig | string>;
|
||||||
|
state_filter: string[];
|
||||||
|
card: Partial<LovelaceCardConfig>;
|
||||||
|
show_empty?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ErrorCardConfig extends LovelaceCardConfig {
|
||||||
|
error: string;
|
||||||
|
origConfig: LovelaceCardConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SeverityConfig {
|
||||||
|
green?: number;
|
||||||
|
yellow?: number;
|
||||||
|
red?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GaugeCardConfig extends LovelaceCardConfig {
|
||||||
|
entity: string;
|
||||||
|
name?: string;
|
||||||
|
unit?: string;
|
||||||
|
min?: number;
|
||||||
|
max?: number;
|
||||||
|
severity?: SeverityConfig;
|
||||||
|
theme?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConfigEntity extends EntityConfig {
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
hold_action?: ActionConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GlanceCardConfig extends LovelaceCardConfig {
|
||||||
|
show_name?: boolean;
|
||||||
|
show_state?: boolean;
|
||||||
|
show_icon?: boolean;
|
||||||
|
title?: string;
|
||||||
|
theme?: string;
|
||||||
|
entities: ConfigEntity[];
|
||||||
|
columns?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IframeCardConfig extends LovelaceCardConfig {
|
||||||
|
aspect_ratio?: string;
|
||||||
|
title?: string;
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LightCardConfig extends LovelaceCardConfig {
|
||||||
|
entity: string;
|
||||||
|
name?: string;
|
||||||
|
theme?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MapCardConfig extends LovelaceCardConfig {
|
||||||
|
title: string;
|
||||||
|
aspect_ratio: string;
|
||||||
|
default_zoom?: number;
|
||||||
|
entities?: Array<EntityConfig | string>;
|
||||||
|
geo_location_sources?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarkdownCardConfig extends LovelaceCardConfig {
|
||||||
|
content: string;
|
||||||
|
title?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MediaControlCardConfig extends LovelaceCardConfig {
|
||||||
|
entity: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PictureCardConfig extends LovelaceCardConfig {
|
||||||
|
image?: string;
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
hold_action?: ActionConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PictureElementsCardConfig extends LovelaceCardConfig {
|
||||||
|
title?: string;
|
||||||
|
image?: string;
|
||||||
|
camera_image?: string;
|
||||||
|
state_image?: {};
|
||||||
|
aspect_ratio?: string;
|
||||||
|
entity?: string;
|
||||||
|
elements: LovelaceElementConfig[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PictureEntityCardConfig extends LovelaceCardConfig {
|
||||||
|
entity: string;
|
||||||
|
name?: string;
|
||||||
|
image?: string;
|
||||||
|
camera_image?: string;
|
||||||
|
state_image?: {};
|
||||||
|
aspect_ratio?: string;
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
hold_action?: ActionConfig;
|
||||||
|
show_name?: boolean;
|
||||||
|
show_state?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PictureGlanceCardConfig extends LovelaceCardConfig {
|
||||||
|
entities: EntityConfig[];
|
||||||
|
title?: string;
|
||||||
|
image?: string;
|
||||||
|
camera_image?: string;
|
||||||
|
state_image?: {};
|
||||||
|
aspect_ratio?: string;
|
||||||
|
entity?: string;
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
hold_action?: ActionConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PlantAttributeTarget extends EventTarget {
|
||||||
|
value?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PlantStatusCardConfig extends LovelaceCardConfig {
|
||||||
|
name?: string;
|
||||||
|
entity: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SensorCardConfig extends LovelaceCardConfig {
|
||||||
|
entity: string;
|
||||||
|
name?: string;
|
||||||
|
icon?: string;
|
||||||
|
graph?: string;
|
||||||
|
unit?: string;
|
||||||
|
detail?: number;
|
||||||
|
theme?: string;
|
||||||
|
hours_to_show?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShoppingListCardConfig extends LovelaceCardConfig {
|
||||||
|
title?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StackCardConfig extends LovelaceCardConfig {
|
||||||
|
cards: LovelaceCardConfig[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ThermostatCardConfig extends LovelaceCardConfig {
|
||||||
|
entity: string;
|
||||||
|
theme?: string;
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WeatherForecastCardConfig extends LovelaceCardConfig {
|
||||||
|
entity: string;
|
||||||
|
name?: string;
|
||||||
|
}
|
@ -5,6 +5,7 @@ import {
|
|||||||
LovelaceViewConfig,
|
LovelaceViewConfig,
|
||||||
} from "../../../data/lovelace";
|
} from "../../../data/lovelace";
|
||||||
import { HassEntity, HassEntities } from "home-assistant-js-websocket";
|
import { HassEntity, HassEntities } from "home-assistant-js-websocket";
|
||||||
|
|
||||||
import extractViews from "../../../common/entity/extract_views";
|
import extractViews from "../../../common/entity/extract_views";
|
||||||
import getViewEntities from "../../../common/entity/get_view_entities";
|
import getViewEntities from "../../../common/entity/get_view_entities";
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
@ -12,9 +13,10 @@ import splitByGroups from "../../../common/entity/split_by_groups";
|
|||||||
import computeObjectId from "../../../common/entity/compute_object_id";
|
import computeObjectId from "../../../common/entity/compute_object_id";
|
||||||
import computeStateDomain from "../../../common/entity/compute_state_domain";
|
import computeStateDomain from "../../../common/entity/compute_state_domain";
|
||||||
import computeDomain from "../../../common/entity/compute_domain";
|
import computeDomain from "../../../common/entity/compute_domain";
|
||||||
|
|
||||||
import { EntityRowConfig, WeblinkConfig } from "../entity-rows/types";
|
import { EntityRowConfig, WeblinkConfig } from "../entity-rows/types";
|
||||||
import { EntitiesCardConfig } from "../cards/hui-entities-card";
|
|
||||||
import { LocalizeFunc } from "../../../common/translations/localize";
|
import { LocalizeFunc } from "../../../common/translations/localize";
|
||||||
|
import { EntitiesCardConfig } from "../cards/types";
|
||||||
|
|
||||||
const DEFAULT_VIEW_ENTITY_ID = "group.default_view";
|
const DEFAULT_VIEW_ENTITY_ID = "group.default_view";
|
||||||
const DOMAINS_BADGES = [
|
const DOMAINS_BADGES = [
|
||||||
|
@ -11,13 +11,11 @@ export function checkConditionsMet(
|
|||||||
hass: HomeAssistant
|
hass: HomeAssistant
|
||||||
): boolean {
|
): boolean {
|
||||||
return conditions.every((c) => {
|
return conditions.every((c) => {
|
||||||
if (!(c.entity in hass.states)) {
|
const state = hass.states[c.entity]
|
||||||
return false;
|
? hass!.states[c.entity].state
|
||||||
}
|
: "unavailable";
|
||||||
if (c.state) {
|
|
||||||
return hass.states[c.entity].state === c.state;
|
return c.state ? state === c.state : state !== c.state_not;
|
||||||
}
|
|
||||||
return hass!.states[c.entity].state !== c.state_not;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
src/panels/lovelace/components/dialog/ha-dialog.ts
Normal file
26
src/panels/lovelace/components/dialog/ha-dialog.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import "@polymer/paper-dialog/paper-dialog";
|
||||||
|
import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class";
|
||||||
|
import { HaIronFocusablesHelper } from "./ha-iron-focusables-helper.js";
|
||||||
|
|
||||||
|
const paperDialogClass = customElements.get("paper-dialog");
|
||||||
|
|
||||||
|
// behavior that will override existing iron-overlay-behavior and call the fixed implementation
|
||||||
|
const haTabFixBehaviorImpl = {
|
||||||
|
get _focusableNodes() {
|
||||||
|
return HaIronFocusablesHelper.getTabbableNodes(this);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// paper-dialog that uses the haTabFixBehaviorImpl behvaior
|
||||||
|
// export class HaPaperDialog extends paperDialogClass {}
|
||||||
|
export class HaPaperDialog extends mixinBehaviors(
|
||||||
|
[haTabFixBehaviorImpl],
|
||||||
|
paperDialogClass
|
||||||
|
) {}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-paper-dialog": HaPaperDialog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
customElements.define("ha-paper-dialog", HaPaperDialog);
|
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
@license
|
||||||
|
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
|
||||||
|
This code may only be used under the BSD style license found at
|
||||||
|
http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
|
||||||
|
http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
|
||||||
|
found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
|
||||||
|
part of the polymer project is also subject to an additional IP rights grant
|
||||||
|
found at http://polymer.github.io/PATENTS.txt
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Fixes issue with not using shadow dom properly in iron-overlay-behavior/icon-focusables-helper.js
|
||||||
|
*/
|
||||||
|
import { dom } from "@polymer/polymer/lib/legacy/polymer.dom.js";
|
||||||
|
|
||||||
|
import { IronFocusablesHelper } from "@polymer/iron-overlay-behavior/iron-focusables-helper.js";
|
||||||
|
|
||||||
|
export const HaIronFocusablesHelper = {
|
||||||
|
/**
|
||||||
|
* Returns a sorted array of tabbable nodes, including the root node.
|
||||||
|
* It searches the tabbable nodes in the light and shadow dom of the chidren,
|
||||||
|
* sorting the result by tabindex.
|
||||||
|
* @param {!Node} node
|
||||||
|
* @return {!Array<!HTMLElement>}
|
||||||
|
*/
|
||||||
|
getTabbableNodes: function(node) {
|
||||||
|
var result = [];
|
||||||
|
// If there is at least one element with tabindex > 0, we need to sort
|
||||||
|
// the final array by tabindex.
|
||||||
|
var needsSortByTabIndex = this._collectTabbableNodes(node, result);
|
||||||
|
if (needsSortByTabIndex) {
|
||||||
|
return IronFocusablesHelper._sortByTabIndex(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for nodes that are tabbable and adds them to the `result` array.
|
||||||
|
* Returns if the `result` array needs to be sorted by tabindex.
|
||||||
|
* @param {!Node} node The starting point for the search; added to `result`
|
||||||
|
* if tabbable.
|
||||||
|
* @param {!Array<!HTMLElement>} result
|
||||||
|
* @return {boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_collectTabbableNodes: function(node, result) {
|
||||||
|
// If not an element or not visible, no need to explore children.
|
||||||
|
if (
|
||||||
|
node.nodeType !== Node.ELEMENT_NODE ||
|
||||||
|
!IronFocusablesHelper._isVisible(node)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var element = /** @type {!HTMLElement} */ (node);
|
||||||
|
var tabIndex = IronFocusablesHelper._normalizedTabIndex(element);
|
||||||
|
var needsSort = tabIndex > 0;
|
||||||
|
if (tabIndex >= 0) {
|
||||||
|
result.push(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In ShadowDOM v1, tab order is affected by the order of distrubution.
|
||||||
|
// E.g. getTabbableNodes(#root) in ShadowDOM v1 should return [#A, #B];
|
||||||
|
// in ShadowDOM v0 tab order is not affected by the distrubution order,
|
||||||
|
// in fact getTabbableNodes(#root) returns [#B, #A].
|
||||||
|
// <div id="root">
|
||||||
|
// <!-- shadow -->
|
||||||
|
// <slot name="a">
|
||||||
|
// <slot name="b">
|
||||||
|
// <!-- /shadow -->
|
||||||
|
// <input id="A" slot="a">
|
||||||
|
// <input id="B" slot="b" tabindex="1">
|
||||||
|
// </div>
|
||||||
|
// TODO(valdrin) support ShadowDOM v1 when upgrading to Polymer v2.0.
|
||||||
|
var children;
|
||||||
|
if (element.localName === "content" || element.localName === "slot") {
|
||||||
|
children = dom(element).getDistributedNodes();
|
||||||
|
} else {
|
||||||
|
// /////////////////////////
|
||||||
|
// Use shadow root if possible, will check for distributed nodes.
|
||||||
|
// THIS IS THE CHANGED LINE
|
||||||
|
children = dom(element.shadowRoot || element.root || element).children;
|
||||||
|
// /////////////////////////
|
||||||
|
}
|
||||||
|
for (var i = 0; i < children.length; i++) {
|
||||||
|
// Ensure method is always invoked to collect tabbable children.
|
||||||
|
needsSort = this._collectTabbableNodes(children[i], result) || needsSort;
|
||||||
|
}
|
||||||
|
return needsSort;
|
||||||
|
},
|
||||||
|
};
|
@ -9,15 +9,15 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import { EntitiesCardEntityConfig } from "../cards/hui-entities-card";
|
|
||||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
|
||||||
|
|
||||||
import "../../../components/entity/state-badge";
|
import "../../../components/entity/state-badge";
|
||||||
import "../../../components/ha-relative-time";
|
import "../../../components/ha-relative-time";
|
||||||
import "../../../components/ha-icon";
|
import "../../../components/ha-icon";
|
||||||
import "../components/hui-warning";
|
import "../components/hui-warning";
|
||||||
|
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||||
|
import { EntitiesCardEntityConfig } from "../cards/types";
|
||||||
|
|
||||||
class HuiGenericEntityRow extends LitElement {
|
class HuiGenericEntityRow extends LitElement {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
|
36
src/panels/lovelace/components/hui-warning-element.ts
Normal file
36
src/panels/lovelace/components/hui-warning-element.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
TemplateResult,
|
||||||
|
CSSResult,
|
||||||
|
css,
|
||||||
|
customElement,
|
||||||
|
property,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
|
import "../../../components/ha-icon";
|
||||||
|
|
||||||
|
@customElement("hui-warning-element")
|
||||||
|
export class HuiWarningElement extends LitElement {
|
||||||
|
@property() public label?: string;
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
return html`
|
||||||
|
<ha-icon icon="hass:alert" .title="${this.label}"></ha-icon>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return css`
|
||||||
|
ha-icon {
|
||||||
|
color: #fce588;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-warning-element": HuiWarningElement;
|
||||||
|
}
|
||||||
|
}
|
@ -96,6 +96,10 @@ export class HuiYamlEditor extends HTMLElement {
|
|||||||
tabSize: 2,
|
tabSize: 2,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
viewportMargin: Infinity,
|
viewportMargin: Infinity,
|
||||||
|
extraKeys: {
|
||||||
|
Tab: "indentMore",
|
||||||
|
"Shift-Tab": "indentLess",
|
||||||
|
},
|
||||||
gutters:
|
gutters:
|
||||||
this._hass && computeRTL(this._hass!)
|
this._hass && computeRTL(this._hass!)
|
||||||
? ["rtl-gutter", "CodeMirror-linenumbers"]
|
? ["rtl-gutter", "CodeMirror-linenumbers"]
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
import "@material/mwc-button";
|
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
|
||||||
|
|
||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|
||||||
|
|
||||||
import "./hui-notification-item-template";
|
|
||||||
|
|
||||||
import EventsMixin from "../../../../mixins/events-mixin";
|
|
||||||
import LocalizeMixin from "../../../../mixins/localize-mixin";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @appliesMixin EventsMixin
|
|
||||||
* @appliesMixin LocalizeMixin
|
|
||||||
*/
|
|
||||||
export class HuiConfiguratorNotificationItem extends EventsMixin(
|
|
||||||
LocalizeMixin(PolymerElement)
|
|
||||||
) {
|
|
||||||
static get template() {
|
|
||||||
return html`
|
|
||||||
<hui-notification-item-template>
|
|
||||||
<span slot="header">[[localize('domain.configurator')]]</span>
|
|
||||||
|
|
||||||
<div>[[_getMessage(notification)]]</div>
|
|
||||||
|
|
||||||
<mwc-button slot="actions" on-click="_handleClick"
|
|
||||||
>[[_localizeState(notification.state)]]</mwc-button
|
|
||||||
>
|
|
||||||
</hui-notification-item-template>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
notification: Object,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleClick() {
|
|
||||||
this.fire("hass-more-info", { entityId: this.notification.entity_id });
|
|
||||||
}
|
|
||||||
|
|
||||||
_localizeState(state) {
|
|
||||||
return this.localize(`state.configurator.${state}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getMessage(notification) {
|
|
||||||
const friendlyName = notification.attributes.friendly_name;
|
|
||||||
return this.localize(
|
|
||||||
"ui.notification_drawer.click_to_configure",
|
|
||||||
"entity",
|
|
||||||
friendlyName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
customElements.define(
|
|
||||||
"hui-configurator-notification-item",
|
|
||||||
HuiConfiguratorNotificationItem
|
|
||||||
);
|
|
@ -0,0 +1,59 @@
|
|||||||
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
TemplateResult,
|
||||||
|
property,
|
||||||
|
customElement,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@material/mwc-button";
|
||||||
|
|
||||||
|
import "./hui-notification-item-template";
|
||||||
|
|
||||||
|
import { HomeAssistant } from "../../../../types";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
|
||||||
|
@customElement("hui-configurator-notification-item")
|
||||||
|
export class HuiConfiguratorNotificationItem extends LitElement {
|
||||||
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public notification?: HassEntity;
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
if (!this.hass || !this.notification) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<hui-notification-item-template>
|
||||||
|
<span slot="header">${this.hass.localize("domain.configurator")}</span>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.notification_drawer.click_to_configure",
|
||||||
|
"entity",
|
||||||
|
this.notification.attributes.friendly_name
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<mwc-button slot="actions" @click="${this._handleClick}"
|
||||||
|
>${this.hass.localize(
|
||||||
|
`state.configurator.${this.notification.state}`
|
||||||
|
)}</mwc-button
|
||||||
|
>
|
||||||
|
</hui-notification-item-template>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleClick(): void {
|
||||||
|
fireEvent(this, "hass-more-info", {
|
||||||
|
entityId: this.notification!.entity_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-configurator-notification-item": HuiConfiguratorNotificationItem;
|
||||||
|
}
|
||||||
|
}
|
@ -1,35 +0,0 @@
|
|||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|
||||||
import computeDomain from "../../../../common/entity/compute_domain";
|
|
||||||
|
|
||||||
import "./hui-configurator-notification-item";
|
|
||||||
import "./hui-persistent-notification-item";
|
|
||||||
|
|
||||||
export class HuiNotificationItem extends PolymerElement {
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
notification: {
|
|
||||||
type: Object,
|
|
||||||
observer: "_stateChanged",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_stateChanged(notification) {
|
|
||||||
if (this.lastChild) {
|
|
||||||
this.removeChild(this.lastChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!notification) return;
|
|
||||||
|
|
||||||
const domain = notification.entity_id
|
|
||||||
? computeDomain(notification.entity_id)
|
|
||||||
: "persistent_notification";
|
|
||||||
const tag = `hui-${domain}-notification-item`;
|
|
||||||
const el = document.createElement(tag);
|
|
||||||
el.hass = this.hass;
|
|
||||||
el.notification = notification;
|
|
||||||
this.appendChild(el);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
customElements.define("hui-notification-item", HuiNotificationItem);
|
|
@ -0,0 +1,55 @@
|
|||||||
|
import {
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
customElement,
|
||||||
|
PropertyValues,
|
||||||
|
TemplateResult,
|
||||||
|
html,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
|
import "./hui-configurator-notification-item";
|
||||||
|
import "./hui-persistent-notification-item";
|
||||||
|
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { HomeAssistant } from "../../../../types";
|
||||||
|
|
||||||
|
@customElement("hui-notification-item")
|
||||||
|
export class HuiNotificationItem extends LitElement {
|
||||||
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public notification?: HassEntity;
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
if (!this.hass || !this.notification || changedProps.has("notification")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
if (!this.hass || !this.notification) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.notification.entity_id
|
||||||
|
? html`
|
||||||
|
<hui-configurator-notification-item
|
||||||
|
.hass="${this.hass}"
|
||||||
|
.notification="${this.notification}"
|
||||||
|
></hui-configurator-notification-item>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
<hui-persistent-notification-item
|
||||||
|
.hass="${this.hass}"
|
||||||
|
.notification="${this.notification}"
|
||||||
|
></hui-persistent-notification-item>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-notification-item": HuiNotificationItem;
|
||||||
|
}
|
||||||
|
}
|
@ -87,6 +87,6 @@ export class HuiPersistentNotificationItem extends LocalizeMixin(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
customElements.define(
|
customElements.define(
|
||||||
"hui-persistent_notification-notification-item",
|
"hui-persistent-notification-item",
|
||||||
HuiPersistentNotificationItem
|
HuiPersistentNotificationItem
|
||||||
);
|
);
|
||||||
|
@ -12,6 +12,7 @@ import { LovelaceCardConfig } from "../../../../data/lovelace";
|
|||||||
import "./hui-edit-card";
|
import "./hui-edit-card";
|
||||||
import "./hui-dialog-pick-card";
|
import "./hui-dialog-pick-card";
|
||||||
import { EditCardDialogParams } from "./show-edit-card-dialog";
|
import { EditCardDialogParams } from "./show-edit-card-dialog";
|
||||||
|
import { addCard, replaceCard } from "../config-util";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// for fire event
|
// for fire event
|
||||||
@ -32,19 +33,22 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
|
|
||||||
@property() private _cardConfig?: LovelaceCardConfig;
|
@property() private _cardConfig?: LovelaceCardConfig;
|
||||||
|
|
||||||
|
@property() private _newCard?: boolean;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this._cardPicked = this._cardPicked.bind(this);
|
this._cardPicked = this._cardPicked.bind(this);
|
||||||
this._cancel = this._cancel.bind(this);
|
this._cancel = this._cancel.bind(this);
|
||||||
|
this._save = this._save.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async showDialog(params: EditCardDialogParams): Promise<void> {
|
public async showDialog(params: EditCardDialogParams): Promise<void> {
|
||||||
this._params = params;
|
this._params = params;
|
||||||
|
const [view, card] = params.path;
|
||||||
|
this._newCard = card !== undefined ? false : true;
|
||||||
this._cardConfig =
|
this._cardConfig =
|
||||||
params.path.length === 2
|
card !== undefined
|
||||||
? (this._cardConfig = params.lovelace.config.views[
|
? params.lovelace.config.views[view].cards![card]
|
||||||
params.path[0]
|
|
||||||
].cards![params.path[1]])
|
|
||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,9 +70,10 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
<hui-edit-card
|
<hui-edit-card
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
.lovelace="${this._params.lovelace}"
|
.lovelace="${this._params.lovelace}"
|
||||||
.path="${this._params.path}"
|
|
||||||
.cardConfig="${this._cardConfig}"
|
.cardConfig="${this._cardConfig}"
|
||||||
.closeDialog="${this._cancel}"
|
.closeDialog="${this._cancel}"
|
||||||
|
.saveCard="${this._save}"
|
||||||
|
.newCard="${this._newCard}"
|
||||||
>
|
>
|
||||||
</hui-edit-card>
|
</hui-edit-card>
|
||||||
`;
|
`;
|
||||||
@ -82,6 +87,19 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
this._cardConfig = undefined;
|
this._cardConfig = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _save(cardConf: LovelaceCardConfig): Promise<void> {
|
||||||
|
const lovelace = this._params!.lovelace;
|
||||||
|
await lovelace.saveConfig(
|
||||||
|
this._params!.path.length === 1
|
||||||
|
? addCard(lovelace.config, this._params!.path as [number], cardConf)
|
||||||
|
: replaceCard(
|
||||||
|
lovelace.config,
|
||||||
|
this._params!.path as [number, number],
|
||||||
|
cardConf
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -15,9 +15,10 @@ import { haStyleDialog } from "../../../../resources/styles";
|
|||||||
|
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
import "@polymer/paper-dialog/paper-dialog";
|
import "@polymer/paper-dialog/paper-dialog";
|
||||||
|
import "../../components/dialog/ha-dialog";
|
||||||
// This is not a duplicate import, one is for types, one is for element.
|
// This is not a duplicate import, one is for types, one is for element.
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
|
import { HaPaperDialog } from "../../components/dialog/ha-dialog";
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
@ -33,10 +34,9 @@ import "./hui-card-preview";
|
|||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
import { HuiCardPreview } from "./hui-card-preview";
|
import { HuiCardPreview } from "./hui-card-preview";
|
||||||
import { LovelaceCardEditor, Lovelace } from "../../types";
|
import { LovelaceCardEditor, Lovelace } from "../../types";
|
||||||
import { ConfigValue, ConfigError } from "../types";
|
import { ConfigError } from "../types";
|
||||||
import { EntityConfig } from "../../entity-rows/types";
|
import { EntityConfig } from "../../entity-rows/types";
|
||||||
import { getCardElementTag } from "../../common/get-card-element-tag";
|
import { getCardElementTag } from "../../common/get-card-element-tag";
|
||||||
import { addCard, replaceCard } from "../config-util";
|
|
||||||
import { afterNextRender } from "../../../../common/util/render-status";
|
import { afterNextRender } from "../../../../common/util/render-status";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@ -58,15 +58,17 @@ export class HuiEditCard extends LitElement {
|
|||||||
|
|
||||||
public lovelace?: Lovelace;
|
public lovelace?: Lovelace;
|
||||||
|
|
||||||
public path?: [number] | [number, number];
|
|
||||||
|
|
||||||
public closeDialog?: () => void;
|
public closeDialog?: () => void;
|
||||||
|
|
||||||
|
public saveCard?: (cardConf: LovelaceCardConfig) => Promise<void>;
|
||||||
|
|
||||||
|
public newCard?: boolean;
|
||||||
|
|
||||||
@property() private _configElement?: LovelaceCardEditor | null;
|
@property() private _configElement?: LovelaceCardEditor | null;
|
||||||
|
|
||||||
@property() private _uiEditor?: boolean;
|
@property() private _uiEditor?: boolean;
|
||||||
|
|
||||||
@property() private _configValue?: ConfigValue;
|
@property() private _cardConfig?: LovelaceCardConfig;
|
||||||
|
|
||||||
@property() private _configState?: string;
|
@property() private _configState?: string;
|
||||||
|
|
||||||
@ -76,16 +78,28 @@ export class HuiEditCard extends LitElement {
|
|||||||
|
|
||||||
@property() private _errorMsg?: TemplateResult;
|
@property() private _errorMsg?: TemplateResult;
|
||||||
|
|
||||||
private _cardType?: string;
|
private get _dialog(): HaPaperDialog {
|
||||||
|
return this.shadowRoot!.querySelector("ha-paper-dialog")!;
|
||||||
private get _dialog(): PaperDialogElement {
|
|
||||||
return this.shadowRoot!.querySelector("paper-dialog")!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _previewEl(): HuiCardPreview {
|
private get _previewEl(): HuiCardPreview {
|
||||||
return this.shadowRoot!.querySelector("hui-card-preview")!;
|
return this.shadowRoot!.querySelector("hui-card-preview")!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line
|
||||||
|
private __cardYaml: string | undefined;
|
||||||
|
|
||||||
|
private get _cardYaml(): string | undefined {
|
||||||
|
if (!this.__cardYaml) {
|
||||||
|
this.__cardYaml = yaml.safeDump(this._cardConfig);
|
||||||
|
}
|
||||||
|
return this.__cardYaml;
|
||||||
|
}
|
||||||
|
|
||||||
|
private set _cardYaml(yml: string | undefined) {
|
||||||
|
this.__cardYaml = yml;
|
||||||
|
}
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super();
|
super();
|
||||||
this._saving = false;
|
this._saving = false;
|
||||||
@ -98,7 +112,8 @@ export class HuiEditCard extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._configValue = { format: "yaml", value: undefined };
|
this._cardConfig = undefined;
|
||||||
|
this._cardYaml = undefined;
|
||||||
this._configState = "OK";
|
this._configState = "OK";
|
||||||
this._uiEditor = true;
|
this._uiEditor = true;
|
||||||
this._errorMsg = undefined;
|
this._errorMsg = undefined;
|
||||||
@ -119,7 +134,7 @@ export class HuiEditCard extends LitElement {
|
|||||||
: html`
|
: html`
|
||||||
<hui-yaml-editor
|
<hui-yaml-editor
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
.value="${this._configValue!.value}"
|
.value="${this._cardYaml}"
|
||||||
@yaml-changed="${this._handleYamlChanged}"
|
@yaml-changed="${this._handleYamlChanged}"
|
||||||
@yaml-save="${this._save}"
|
@yaml-save="${this._save}"
|
||||||
></hui-yaml-editor>
|
></hui-yaml-editor>
|
||||||
@ -133,7 +148,7 @@ export class HuiEditCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<paper-dialog
|
<ha-paper-dialog
|
||||||
with-backdrop
|
with-backdrop
|
||||||
opened
|
opened
|
||||||
modal
|
modal
|
||||||
@ -162,7 +177,6 @@ export class HuiEditCard extends LitElement {
|
|||||||
<div class="paper-dialog-buttons">
|
<div class="paper-dialog-buttons">
|
||||||
<mwc-button
|
<mwc-button
|
||||||
class="toggle-button"
|
class="toggle-button"
|
||||||
?hidden="${!this._configValue || !this._configValue.value}"
|
|
||||||
?disabled="${this._configElement === null ||
|
?disabled="${this._configElement === null ||
|
||||||
this._configState !== "OK"}"
|
this._configState !== "OK"}"
|
||||||
@click="${this._toggleEditor}"
|
@click="${this._toggleEditor}"
|
||||||
@ -174,7 +188,6 @@ export class HuiEditCard extends LitElement {
|
|||||||
>${this.hass!.localize("ui.common.cancel")}</mwc-button
|
>${this.hass!.localize("ui.common.cancel")}</mwc-button
|
||||||
>
|
>
|
||||||
<mwc-button
|
<mwc-button
|
||||||
?hidden="${!this._configValue || !this._configValue.value}"
|
|
||||||
?disabled="${this._saving || this._configState !== "OK"}"
|
?disabled="${this._saving || this._configState !== "OK"}"
|
||||||
@click="${this._save}"
|
@click="${this._save}"
|
||||||
>
|
>
|
||||||
@ -187,7 +200,7 @@ export class HuiEditCard extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
</paper-dialog>
|
</ha-paper-dialog>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +219,7 @@ export class HuiEditCard extends LitElement {
|
|||||||
|
|
||||||
private async _resizeDialog(): Promise<void> {
|
private async _resizeDialog(): Promise<void> {
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
fireEvent(this._dialog, "iron-resize");
|
fireEvent(this._dialog as HTMLElement, "iron-resize");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _save(): Promise<void> {
|
private async _save(): Promise<void> {
|
||||||
@ -222,22 +235,9 @@ export class HuiEditCard extends LitElement {
|
|||||||
|
|
||||||
this._saving = true;
|
this._saving = true;
|
||||||
|
|
||||||
const cardConf: LovelaceCardConfig =
|
|
||||||
this._configValue!.format === "yaml"
|
|
||||||
? yaml.safeLoad(this._configValue!.value!)
|
|
||||||
: this._configValue!.value!;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const lovelace = this.lovelace!;
|
await this.saveCard!(this._cardConfig!);
|
||||||
await lovelace.saveConfig(
|
this._cardYaml = undefined;
|
||||||
this._creatingCard
|
|
||||||
? addCard(lovelace.config, this.path as [number], cardConf)
|
|
||||||
: replaceCard(
|
|
||||||
lovelace.config,
|
|
||||||
this.path as [number, number],
|
|
||||||
cardConf
|
|
||||||
)
|
|
||||||
);
|
|
||||||
this.closeDialog!();
|
this.closeDialog!();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(`Saving failed: ${err.message}`);
|
alert(`Saving failed: ${err.message}`);
|
||||||
@ -247,12 +247,9 @@ export class HuiEditCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _handleYamlChanged(ev: CustomEvent): void {
|
private _handleYamlChanged(ev: CustomEvent): void {
|
||||||
this._configValue = { format: "yaml", value: ev.detail.value };
|
this._cardConfig = yaml.safeLoad(ev.detail.value);
|
||||||
try {
|
try {
|
||||||
const config = yaml.safeLoad(
|
this._updatePreview(this._cardConfig!);
|
||||||
this._configValue.value
|
|
||||||
) as LovelaceCardConfig;
|
|
||||||
this._updatePreview(config);
|
|
||||||
this._configState = "OK";
|
this._configState = "OK";
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._configState = "YAML_ERROR";
|
this._configState = "YAML_ERROR";
|
||||||
@ -264,7 +261,7 @@ export class HuiEditCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _handleUIConfigChanged(value: LovelaceCardConfig): void {
|
private _handleUIConfigChanged(value: LovelaceCardConfig): void {
|
||||||
this._configValue = { format: "json", value };
|
this._cardConfig = value;
|
||||||
this._updatePreview(value);
|
this._updatePreview(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,35 +291,23 @@ export class HuiEditCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _toggleEditor(): Promise<void> {
|
private async _toggleEditor(): Promise<void> {
|
||||||
if (this._uiEditor && this._configValue!.format === "json") {
|
this._cardYaml = undefined;
|
||||||
this._configValue = {
|
if (this._uiEditor) {
|
||||||
format: "yaml",
|
this._uiEditor = false;
|
||||||
value: yaml.safeDump(this._configValue!.value),
|
} else if (this._configElement) {
|
||||||
};
|
const success = await this._loadConfigElement(this._cardConfig!);
|
||||||
this._uiEditor = !this._uiEditor;
|
if (!success) {
|
||||||
} else if (this._configElement && this._configValue!.format === "yaml") {
|
this._loadedDialog();
|
||||||
const yamlConfig = this._configValue!.value;
|
|
||||||
const cardConfig = yaml.safeLoad(yamlConfig) as LovelaceCardConfig;
|
|
||||||
this._uiEditor = !this._uiEditor;
|
|
||||||
if (cardConfig.type !== this._cardType) {
|
|
||||||
const succes = await this._loadConfigElement(cardConfig);
|
|
||||||
if (!succes) {
|
|
||||||
this._loadedDialog();
|
|
||||||
}
|
|
||||||
this._cardType = cardConfig.type;
|
|
||||||
} else {
|
} else {
|
||||||
this._configValue = {
|
this._uiEditor = true;
|
||||||
format: "json",
|
this._configElement.setConfig(this._cardConfig!);
|
||||||
value: cardConfig,
|
|
||||||
};
|
|
||||||
this._configElement.setConfig(cardConfig);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._resizeDialog();
|
this._resizeDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _isConfigValid(): boolean {
|
private _isConfigValid(): boolean {
|
||||||
if (!this._configValue || !this._configValue.value) {
|
if (!this._cardConfig) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this._configState === "OK") {
|
if (this._configState === "OK") {
|
||||||
@ -333,14 +318,10 @@ export class HuiEditCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _isConfigChanged(): boolean {
|
private _isConfigChanged(): boolean {
|
||||||
if (this._creatingCard) {
|
if (this.newCard) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const configValue =
|
return JSON.stringify(this._cardConfig) !== JSON.stringify(this.cardConfig);
|
||||||
this._configValue!.format === "yaml"
|
|
||||||
? yaml.safeLoad(this._configValue!.value)
|
|
||||||
: this._configValue!.value;
|
|
||||||
return JSON.stringify(configValue) !== JSON.stringify(this.cardConfig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _loadConfigElement(conf: LovelaceCardConfig): Promise<boolean> {
|
private async _loadConfigElement(conf: LovelaceCardConfig): Promise<boolean> {
|
||||||
@ -357,10 +338,11 @@ export class HuiEditCard extends LitElement {
|
|||||||
const elClass = customElements.get(tag);
|
const elClass = customElements.get(tag);
|
||||||
let configElement;
|
let configElement;
|
||||||
|
|
||||||
|
this._cardConfig = conf;
|
||||||
|
|
||||||
if (elClass && elClass.getConfigElement) {
|
if (elClass && elClass.getConfigElement) {
|
||||||
configElement = await elClass.getConfigElement();
|
configElement = await elClass.getConfigElement();
|
||||||
} else {
|
} else {
|
||||||
this._configValue = { format: "yaml", value: yaml.safeDump(conf) };
|
|
||||||
this._updatePreview(conf);
|
this._updatePreview(conf);
|
||||||
this._uiEditor = false;
|
this._uiEditor = false;
|
||||||
this._configElement = null;
|
this._configElement = null;
|
||||||
@ -374,10 +356,6 @@ export class HuiEditCard extends LitElement {
|
|||||||
Your config is not supported by the UI editor:<br /><b>${err.message}</b
|
Your config is not supported by the UI editor:<br /><b>${err.message}</b
|
||||||
><br />Falling back to YAML editor.
|
><br />Falling back to YAML editor.
|
||||||
`;
|
`;
|
||||||
this._configValue = {
|
|
||||||
format: "yaml",
|
|
||||||
value: yaml.safeDump(conf),
|
|
||||||
};
|
|
||||||
this._updatePreview(conf);
|
this._updatePreview(conf);
|
||||||
this._uiEditor = false;
|
this._uiEditor = false;
|
||||||
this._configElement = null;
|
this._configElement = null;
|
||||||
@ -388,17 +366,12 @@ export class HuiEditCard extends LitElement {
|
|||||||
configElement.addEventListener("config-changed", (ev) =>
|
configElement.addEventListener("config-changed", (ev) =>
|
||||||
this._handleUIConfigChanged(ev.detail.config)
|
this._handleUIConfigChanged(ev.detail.config)
|
||||||
);
|
);
|
||||||
this._configValue = { format: "json", value: conf };
|
|
||||||
this._configElement = configElement;
|
this._configElement = configElement;
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
this._updatePreview(conf);
|
this._updatePreview(conf);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _creatingCard(): boolean {
|
|
||||||
return this.path!.length === 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _openedChanged(ev): void {
|
private _openedChanged(ev): void {
|
||||||
if (!ev.detail.value) {
|
if (!ev.detail.value) {
|
||||||
this.closeDialog!();
|
this.closeDialog!();
|
||||||
|
@ -16,11 +16,11 @@ import { EntitiesEditorEvent, EditorTarget } from "../types";
|
|||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-alarm-panel-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
import "../../../../components/ha-icon";
|
import "../../../../components/ha-icon";
|
||||||
|
import { AlarmPanelCardConfig } from "../../cards/types";
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -34,9 +34,9 @@ export class HuiAlarmPanelCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: AlarmPanelCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: AlarmPanelCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -10,23 +10,23 @@ import "@polymer/paper-item/paper-item";
|
|||||||
import "@polymer/paper-listbox/paper-listbox";
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
import "@polymer/paper-toggle-button/paper-toggle-button";
|
import "@polymer/paper-toggle-button/paper-toggle-button";
|
||||||
|
|
||||||
|
import "../../../../components/entity/state-badge";
|
||||||
|
import "../../components/hui-theme-select-editor";
|
||||||
|
import "../../components/hui-entity-editor";
|
||||||
|
import "../../../../components/ha-card";
|
||||||
|
import "../../../../components/ha-icon";
|
||||||
|
|
||||||
import { processEditorEntities } from "../process-editor-entities";
|
import { processEditorEntities } from "../process-editor-entities";
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import {
|
import {
|
||||||
EntitiesCardConfig,
|
EntitiesCardConfig,
|
||||||
EntitiesCardEntityConfig,
|
EntitiesCardEntityConfig,
|
||||||
} from "../../cards/hui-entities-card";
|
} from "../../cards/types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
|
||||||
|
|
||||||
import "../../../../components/entity/state-badge";
|
|
||||||
import "../../components/hui-theme-select-editor";
|
|
||||||
import "../../components/hui-entity-editor";
|
|
||||||
import "../../../../components/ha-card";
|
|
||||||
import "../../../../components/ha-icon";
|
|
||||||
|
|
||||||
const entitiesConfigStruct = struct.union([
|
const entitiesConfigStruct = struct.union([
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,10 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
|
import "../../components/hui-action-editor";
|
||||||
|
import "../../components/hui-theme-select-editor";
|
||||||
|
import "../../components/hui-entity-editor";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import {
|
import {
|
||||||
EntitiesEditorEvent,
|
EntitiesEditorEvent,
|
||||||
@ -16,19 +20,17 @@ import {
|
|||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-entity-button-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { ActionConfig } from "../../../../data/lovelace";
|
import { ActionConfig } from "../../../../data/lovelace";
|
||||||
|
import { EntityButtonCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-action-editor";
|
|
||||||
import "../../components/hui-theme-select-editor";
|
|
||||||
import "../../components/hui-entity-editor";
|
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
entity: "string?",
|
entity: "string?",
|
||||||
name: "string?",
|
name: "string?",
|
||||||
|
show_name: "boolean?",
|
||||||
icon: "string?",
|
icon: "string?",
|
||||||
|
show_icon: "boolean?",
|
||||||
tap_action: struct.optional(actionConfigStruct),
|
tap_action: struct.optional(actionConfigStruct),
|
||||||
hold_action: struct.optional(actionConfigStruct),
|
hold_action: struct.optional(actionConfigStruct),
|
||||||
theme: "string?",
|
theme: "string?",
|
||||||
@ -39,9 +41,9 @@ export class HuiEntityButtonCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: EntityButtonCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: EntityButtonCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
@ -54,10 +56,18 @@ export class HuiEntityButtonCardEditor extends LitElement
|
|||||||
return this._config!.name || "";
|
return this._config!.name || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _show_name(): boolean {
|
||||||
|
return this._config!.show_name || true;
|
||||||
|
}
|
||||||
|
|
||||||
get _icon(): string {
|
get _icon(): string {
|
||||||
return this._config!.icon || "";
|
return this._config!.icon || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _show_icon(): boolean {
|
||||||
|
return this._config!.show_icon || true;
|
||||||
|
}
|
||||||
|
|
||||||
get _tap_action(): ActionConfig {
|
get _tap_action(): ActionConfig {
|
||||||
return this._config!.tap_action || { action: "more-info" };
|
return this._config!.tap_action || { action: "more-info" };
|
||||||
}
|
}
|
||||||
@ -101,6 +111,20 @@ export class HuiEntityButtonCardEditor extends LitElement
|
|||||||
@value-changed="${this._valueChanged}"
|
@value-changed="${this._valueChanged}"
|
||||||
></paper-input>
|
></paper-input>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="side-by-side">
|
||||||
|
<paper-toggle-button
|
||||||
|
?checked="${this._config!.show_name !== false}"
|
||||||
|
.configValue="${"show_name"}"
|
||||||
|
@change="${this._valueChanged}"
|
||||||
|
>Show Name?</paper-toggle-button
|
||||||
|
>
|
||||||
|
<paper-toggle-button
|
||||||
|
?checked="${this._config!.show_icon !== false}"
|
||||||
|
.configValue="${"show_icon"}"
|
||||||
|
@change="${this._valueChanged}"
|
||||||
|
>Show Icon?</paper-toggle-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
<hui-theme-select-editor
|
<hui-theme-select-editor
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
.value="${this._theme}"
|
.value="${this._theme}"
|
||||||
@ -147,7 +171,12 @@ export class HuiEntityButtonCardEditor extends LitElement
|
|||||||
} else {
|
} else {
|
||||||
this._config = {
|
this._config = {
|
||||||
...this._config,
|
...this._config,
|
||||||
[target.configValue!]: target.value ? target.value : target.config,
|
[target.configValue!]:
|
||||||
|
target.checked !== undefined
|
||||||
|
? target.checked
|
||||||
|
: target.value
|
||||||
|
? target.value
|
||||||
|
: target.config,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,16 @@ import {
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import "@polymer/paper-toggle-button/paper-toggle-button";
|
import "@polymer/paper-toggle-button/paper-toggle-button";
|
||||||
|
|
||||||
|
import "../../components/hui-theme-select-editor";
|
||||||
|
import "../../components/hui-entity-editor";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config, SeverityConfig } from "../../cards/hui-gauge-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
import { GaugeCardConfig, SeverityConfig } from "../../cards/types";
|
||||||
import "../../components/hui-theme-select-editor";
|
|
||||||
import "../../components/hui-entity-editor";
|
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -37,11 +37,11 @@ export class HuiGaugeCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: GaugeCardConfig;
|
||||||
|
|
||||||
private _useSeverity?: boolean;
|
private _useSeverity?: boolean;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: GaugeCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._useSeverity = !!config.severity;
|
this._useSeverity = !!config.severity;
|
||||||
this._config = config;
|
this._config = config;
|
||||||
|
@ -10,20 +10,20 @@ import "@polymer/paper-item/paper-item";
|
|||||||
import "@polymer/paper-listbox/paper-listbox";
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
import "@polymer/paper-toggle-button/paper-toggle-button";
|
import "@polymer/paper-toggle-button/paper-toggle-button";
|
||||||
|
|
||||||
|
import "../../../../components/entity/state-badge";
|
||||||
|
import "../../components/hui-theme-select-editor";
|
||||||
|
import "../../components/hui-entity-editor";
|
||||||
|
import "../../../../components/ha-card";
|
||||||
|
import "../../../../components/ha-icon";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { processEditorEntities } from "../process-editor-entities";
|
import { processEditorEntities } from "../process-editor-entities";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { GlanceCardConfig, ConfigEntity } from "../../cards/hui-glance-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
import { GlanceCardConfig, ConfigEntity } from "../../cards/types";
|
||||||
import "../../../../components/entity/state-badge";
|
|
||||||
import "../../components/hui-theme-select-editor";
|
|
||||||
import "../../components/hui-entity-editor";
|
|
||||||
import "../../../../components/ha-card";
|
|
||||||
import "../../../../components/ha-icon";
|
|
||||||
|
|
||||||
const entitiesConfigStruct = struct.union([
|
const entitiesConfigStruct = struct.union([
|
||||||
{
|
{
|
||||||
|
@ -12,8 +12,8 @@ import { EntitiesEditorEvent, EditorTarget } from "../types";
|
|||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-iframe-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
import { IframeCardConfig } from "../../cards/types";
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -27,9 +27,9 @@ export class HuiIframeCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: IframeCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: IframeCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -7,16 +7,16 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
|
import "../../components/hui-theme-select-editor";
|
||||||
|
import "../../components/hui-entity-editor";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-light-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
import { LightCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-theme-select-editor";
|
|
||||||
import "../../components/hui-entity-editor";
|
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -30,9 +30,9 @@ export class HuiLightCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: LightCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: LightCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -9,19 +9,19 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
|
import "../../components/hui-entity-editor";
|
||||||
|
import "../../components/hui-input-list-editor";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { MapCardConfig } from "../../cards/hui-map-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { processEditorEntities } from "../process-editor-entities";
|
import { processEditorEntities } from "../process-editor-entities";
|
||||||
import { EntityConfig } from "../../entity-rows/types";
|
import { EntityConfig } from "../../entity-rows/types";
|
||||||
import { PolymerChangedEvent } from "../../../../polymer-types";
|
import { PolymerChangedEvent } from "../../../../polymer-types";
|
||||||
|
import { MapCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-entity-editor";
|
|
||||||
import "../../components/hui-input-list-editor";
|
|
||||||
|
|
||||||
const entitiesConfigStruct = struct.union([
|
const entitiesConfigStruct = struct.union([
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,8 @@ import { EntitiesEditorEvent, EditorTarget } from "../types";
|
|||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-markdown-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
import { MarkdownCardConfig } from "../../cards/types";
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -27,9 +27,9 @@ export class HuiMarkdownCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: MarkdownCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: MarkdownCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import { EntitiesEditorEvent, EditorTarget } from "../types";
|
|||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-media-control-card";
|
import { MediaControlCardConfig } from "../../cards/hui-media-control-card";
|
||||||
|
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
|
|
||||||
@ -25,9 +25,9 @@ export class HuiMediaControlCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: MediaControlCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: MediaControlCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
|
import "../../components/hui-action-editor";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import {
|
import {
|
||||||
EntitiesEditorEvent,
|
EntitiesEditorEvent,
|
||||||
@ -16,11 +18,9 @@ import {
|
|||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-picture-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { ActionConfig } from "../../../../data/lovelace";
|
import { ActionConfig } from "../../../../data/lovelace";
|
||||||
|
import { PictureCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-action-editor";
|
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -34,9 +34,9 @@ export class HuiPictureCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: PictureCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: PictureCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -7,16 +7,16 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
|
import "../../../../components/ha-icon";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-alarm-panel-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
import { PlantStatusCardConfig } from "../../cards/types";
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
|
||||||
import "../../../../components/ha-icon";
|
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -29,9 +29,9 @@ export class HuiPlantStatusCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: PlantStatusCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: PlantStatusCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,16 @@ import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
|||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
import "@polymer/paper-listbox/paper-listbox";
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
|
||||||
|
import "../../components/hui-theme-select-editor";
|
||||||
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-sensor-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
import { SensorCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-theme-select-editor";
|
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -38,9 +38,9 @@ export class HuiSensorCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: SensorCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: SensorCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import { EntitiesEditorEvent, EditorTarget } from "../types";
|
|||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-shopping-list-card";
|
import { ShoppingListCardConfig } from "../../cards/types";
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -24,9 +24,9 @@ export class HuiShoppingListEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: ShoppingListCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: ShoppingListCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -7,16 +7,16 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
|
import "../../components/hui-theme-select-editor";
|
||||||
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-thermostat-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
import { ThermostatCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-theme-select-editor";
|
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -30,9 +30,9 @@ export class HuiThermostatCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: ThermostatCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: ThermostatCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,15 @@ import {
|
|||||||
property,
|
property,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { Config } from "../../cards/hui-weather-forecast-card";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
import { WeatherForecastCardConfig } from "../../cards/types";
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -27,9 +27,9 @@ export class HuiWeatherForecastCardEditor extends LitElement
|
|||||||
implements LovelaceCardEditor {
|
implements LovelaceCardEditor {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() private _config?: Config;
|
@property() private _config?: WeatherForecastCardConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: WeatherForecastCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,21 @@
|
|||||||
import {
|
import {
|
||||||
Condition,
|
|
||||||
checkConditionsMet,
|
checkConditionsMet,
|
||||||
validateConditionalConfig,
|
validateConditionalConfig,
|
||||||
} from "../../lovelace/common/validate-condition";
|
} from "../../lovelace/common/validate-condition";
|
||||||
import { createStyledHuiElement } from "../cards/picture-elements/create-styled-hui-element";
|
import { createStyledHuiElement } from "../cards/picture-elements/create-styled-hui-element";
|
||||||
|
import {
|
||||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
LovelaceElement,
|
||||||
|
LovelaceElementConfig,
|
||||||
|
ConditionalElementConfig,
|
||||||
|
} from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
interface Config extends LovelaceElementConfig {
|
|
||||||
conditions: Condition[];
|
|
||||||
elements: LovelaceElementConfig[];
|
|
||||||
}
|
|
||||||
|
|
||||||
class HuiConditionalElement extends HTMLElement implements LovelaceElement {
|
class HuiConditionalElement extends HTMLElement implements LovelaceElement {
|
||||||
public _hass?: HomeAssistant;
|
public _hass?: HomeAssistant;
|
||||||
private _config?: Config;
|
private _config?: ConditionalElementConfig;
|
||||||
private _elements: LovelaceElement[] = [];
|
private _elements: LovelaceElement[] = [];
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: ConditionalElementConfig): void {
|
||||||
if (
|
if (
|
||||||
!config.conditions ||
|
!config.conditions ||
|
||||||
!Array.isArray(config.conditions) ||
|
!Array.isArray(config.conditions) ||
|
||||||
|
@ -13,24 +13,15 @@ import "../../../components/ha-icon";
|
|||||||
import { computeTooltip } from "../common/compute-tooltip";
|
import { computeTooltip } from "../common/compute-tooltip";
|
||||||
import { handleClick } from "../common/handle-click";
|
import { handleClick } from "../common/handle-click";
|
||||||
import { longPress } from "../common/directives/long-press-directive";
|
import { longPress } from "../common/directives/long-press-directive";
|
||||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
import { LovelaceElement, IconElementConfig } from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { ActionConfig } from "../../../data/lovelace";
|
|
||||||
|
|
||||||
export interface Config extends LovelaceElementConfig {
|
|
||||||
entity?: string;
|
|
||||||
name?: string;
|
|
||||||
tap_action?: ActionConfig;
|
|
||||||
hold_action?: ActionConfig;
|
|
||||||
icon: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-icon-element")
|
@customElement("hui-icon-element")
|
||||||
export class HuiIconElement extends LitElement implements LovelaceElement {
|
export class HuiIconElement extends LitElement implements LovelaceElement {
|
||||||
@property() public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
@property() private _config?: Config;
|
@property() private _config?: IconElementConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: IconElementConfig): void {
|
||||||
if (!config.icon) {
|
if (!config.icon) {
|
||||||
throw Error("Invalid Configuration: 'icon' required");
|
throw Error("Invalid Configuration: 'icon' required");
|
||||||
}
|
}
|
||||||
|
@ -13,28 +13,15 @@ import "../components/hui-image";
|
|||||||
import { computeTooltip } from "../common/compute-tooltip";
|
import { computeTooltip } from "../common/compute-tooltip";
|
||||||
import { handleClick } from "../common/handle-click";
|
import { handleClick } from "../common/handle-click";
|
||||||
import { longPress } from "../common/directives/long-press-directive";
|
import { longPress } from "../common/directives/long-press-directive";
|
||||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
import { LovelaceElement, ImageElementConfig } from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { ActionConfig } from "../../../data/lovelace";
|
|
||||||
|
|
||||||
export interface Config extends LovelaceElementConfig {
|
|
||||||
entity?: string;
|
|
||||||
tap_action?: ActionConfig;
|
|
||||||
hold_action?: ActionConfig;
|
|
||||||
image?: string;
|
|
||||||
state_image?: string;
|
|
||||||
camera_image?: string;
|
|
||||||
filter?: string;
|
|
||||||
state_filter?: string;
|
|
||||||
aspect_ratio?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-image-element")
|
@customElement("hui-image-element")
|
||||||
export class HuiImageElement extends LitElement implements LovelaceElement {
|
export class HuiImageElement extends LitElement implements LovelaceElement {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
@property() private _config?: Config;
|
@property() private _config?: ImageElementConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: ImageElementConfig): void {
|
||||||
if (!config) {
|
if (!config) {
|
||||||
throw Error("Error in element configuration");
|
throw Error("Error in element configuration");
|
||||||
}
|
}
|
||||||
|
@ -10,20 +10,14 @@ import {
|
|||||||
|
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
|
||||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
import { LovelaceElement, ServiceButtonElementConfig } from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
export interface Config extends LovelaceElementConfig {
|
|
||||||
title?: string;
|
|
||||||
service?: string;
|
|
||||||
service_data?: object;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-service-button-element")
|
@customElement("hui-service-button-element")
|
||||||
export class HuiServiceButtonElement extends LitElement
|
export class HuiServiceButtonElement extends LitElement
|
||||||
implements LovelaceElement {
|
implements LovelaceElement {
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
@property() private _config?: Config;
|
@property() private _config?: ServiceButtonElementConfig;
|
||||||
private _domain?: string;
|
private _domain?: string;
|
||||||
private _service?: string;
|
private _service?: string;
|
||||||
|
|
||||||
@ -31,7 +25,7 @@ export class HuiServiceButtonElement extends LitElement
|
|||||||
return { _config: {} };
|
return { _config: {} };
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: ServiceButtonElementConfig): void {
|
||||||
if (!config || !config.service) {
|
if (!config || !config.service) {
|
||||||
throw Error("Invalid Configuration: 'service' required");
|
throw Error("Invalid Configuration: 'service' required");
|
||||||
}
|
}
|
||||||
|
@ -4,26 +4,24 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
customElement,
|
customElement,
|
||||||
property,
|
property,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import "../../../components/entity/ha-state-label-badge";
|
import "../../../components/entity/ha-state-label-badge";
|
||||||
import "../components/hui-warning";
|
import "../components/hui-warning-element";
|
||||||
|
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
import { LovelaceElement, StateBadgeElementConfig } from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
export interface Config extends LovelaceElementConfig {
|
|
||||||
entity: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-state-badge-element")
|
@customElement("hui-state-badge-element")
|
||||||
export class HuiStateBadgeElement extends LitElement
|
export class HuiStateBadgeElement extends LitElement
|
||||||
implements LovelaceElement {
|
implements LovelaceElement {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
@property() private _config?: Config;
|
@property() private _config?: StateBadgeElementConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: StateBadgeElementConfig): void {
|
||||||
if (!config.entity) {
|
if (!config.entity) {
|
||||||
throw Error("Invalid Configuration: 'entity' required");
|
throw Error("Invalid Configuration: 'entity' required");
|
||||||
}
|
}
|
||||||
@ -31,6 +29,10 @@ export class HuiStateBadgeElement extends LitElement
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
@ -40,13 +42,13 @@ export class HuiStateBadgeElement extends LitElement
|
|||||||
|
|
||||||
if (!stateObj) {
|
if (!stateObj) {
|
||||||
return html`
|
return html`
|
||||||
<hui-warning
|
<hui-warning-element
|
||||||
>${this.hass.localize(
|
label="${this.hass.localize(
|
||||||
"ui.panel.lovelace.warning.entity_not_found",
|
"ui.panel.lovelace.warning.entity_not_found",
|
||||||
"entity",
|
"entity",
|
||||||
this._config.entity
|
this._config.entity
|
||||||
)}</hui-warning
|
)}"
|
||||||
>
|
></hui-warning-element>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,30 +6,25 @@ import {
|
|||||||
property,
|
property,
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import "../../../components/entity/state-badge";
|
import "../../../components/entity/state-badge";
|
||||||
import "../components/hui-warning";
|
import "../components/hui-warning-element";
|
||||||
|
|
||||||
import { computeTooltip } from "../common/compute-tooltip";
|
import { computeTooltip } from "../common/compute-tooltip";
|
||||||
import { handleClick } from "../common/handle-click";
|
import { handleClick } from "../common/handle-click";
|
||||||
import { longPress } from "../common/directives/long-press-directive";
|
import { longPress } from "../common/directives/long-press-directive";
|
||||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
import { LovelaceElement, StateIconElementConfig } from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { ActionConfig } from "../../../data/lovelace";
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
export interface Config extends LovelaceElementConfig {
|
|
||||||
entity: string;
|
|
||||||
tap_action?: ActionConfig;
|
|
||||||
hold_action?: ActionConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-state-icon-element")
|
@customElement("hui-state-icon-element")
|
||||||
export class HuiStateIconElement extends LitElement implements LovelaceElement {
|
export class HuiStateIconElement extends LitElement implements LovelaceElement {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
@property() private _config?: Config;
|
@property() private _config?: StateIconElementConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: StateIconElementConfig): void {
|
||||||
if (!config.entity) {
|
if (!config.entity) {
|
||||||
throw Error("Invalid Configuration: 'entity' required");
|
throw Error("Invalid Configuration: 'entity' required");
|
||||||
}
|
}
|
||||||
@ -37,6 +32,10 @@ export class HuiStateIconElement extends LitElement implements LovelaceElement {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
@ -46,13 +45,13 @@ export class HuiStateIconElement extends LitElement implements LovelaceElement {
|
|||||||
|
|
||||||
if (!stateObj) {
|
if (!stateObj) {
|
||||||
return html`
|
return html`
|
||||||
<hui-warning
|
<hui-warning-element
|
||||||
>${this.hass.localize(
|
label=${this.hass.localize(
|
||||||
"ui.panel.lovelace.warning.entity_not_found",
|
"ui.panel.lovelace.warning.entity_not_found",
|
||||||
"entity",
|
"entity",
|
||||||
this._config.entity
|
this._config.entity
|
||||||
)}</hui-warning
|
)}
|
||||||
>
|
></hui-warning-element>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,33 +6,26 @@ import {
|
|||||||
property,
|
property,
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import "../../../components/entity/ha-state-label-badge";
|
import "../../../components/entity/ha-state-label-badge";
|
||||||
import "../components/hui-warning";
|
import "../components/hui-warning-element";
|
||||||
|
|
||||||
import computeStateDisplay from "../../../common/entity/compute_state_display";
|
import computeStateDisplay from "../../../common/entity/compute_state_display";
|
||||||
import { computeTooltip } from "../common/compute-tooltip";
|
import { computeTooltip } from "../common/compute-tooltip";
|
||||||
import { handleClick } from "../common/handle-click";
|
import { handleClick } from "../common/handle-click";
|
||||||
import { longPress } from "../common/directives/long-press-directive";
|
import { longPress } from "../common/directives/long-press-directive";
|
||||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
import { LovelaceElement, StateLabelElementConfig } from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { ActionConfig } from "../../../data/lovelace";
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
interface Config extends LovelaceElementConfig {
|
|
||||||
entity: string;
|
|
||||||
prefix?: string;
|
|
||||||
suffix?: string;
|
|
||||||
tap_action?: ActionConfig;
|
|
||||||
hold_action?: ActionConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("hui-state-label-element")
|
@customElement("hui-state-label-element")
|
||||||
class HuiStateLabelElement extends LitElement implements LovelaceElement {
|
class HuiStateLabelElement extends LitElement implements LovelaceElement {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
@property() private _config?: Config;
|
@property() private _config?: StateLabelElementConfig;
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: StateLabelElementConfig): void {
|
||||||
if (!config.entity) {
|
if (!config.entity) {
|
||||||
throw Error("Invalid Configuration: 'entity' required");
|
throw Error("Invalid Configuration: 'entity' required");
|
||||||
}
|
}
|
||||||
@ -40,6 +33,10 @@ class HuiStateLabelElement extends LitElement implements LovelaceElement {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
@ -49,13 +46,13 @@ class HuiStateLabelElement extends LitElement implements LovelaceElement {
|
|||||||
|
|
||||||
if (!stateObj) {
|
if (!stateObj) {
|
||||||
return html`
|
return html`
|
||||||
<hui-warning
|
<hui-warning-element
|
||||||
>${this.hass.localize(
|
label=${this.hass.localize(
|
||||||
"ui.panel.lovelace.warning.entity_not_found",
|
"ui.panel.lovelace.warning.entity_not_found",
|
||||||
"entity",
|
"entity",
|
||||||
this._config.entity
|
this._config.entity
|
||||||
)}</hui-warning
|
)}
|
||||||
>
|
></hui-warning-element>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { Condition } from "../common/validate-condition";
|
||||||
|
import { ActionConfig } from "../../../data/lovelace";
|
||||||
|
|
||||||
export interface LovelaceElementConfig {
|
export interface LovelaceElementConfig {
|
||||||
type: string;
|
type: string;
|
||||||
@ -9,3 +11,52 @@ export interface LovelaceElement extends HTMLElement {
|
|||||||
hass?: HomeAssistant;
|
hass?: HomeAssistant;
|
||||||
setConfig(config: LovelaceElementConfig): void;
|
setConfig(config: LovelaceElementConfig): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ConditionalElementConfig extends LovelaceElementConfig {
|
||||||
|
conditions: Condition[];
|
||||||
|
elements: LovelaceElementConfig[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IconElementConfig extends LovelaceElementConfig {
|
||||||
|
entity?: string;
|
||||||
|
name?: string;
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
hold_action?: ActionConfig;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImageElementConfig extends LovelaceElementConfig {
|
||||||
|
entity?: string;
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
hold_action?: ActionConfig;
|
||||||
|
image?: string;
|
||||||
|
state_image?: string;
|
||||||
|
camera_image?: string;
|
||||||
|
filter?: string;
|
||||||
|
state_filter?: string;
|
||||||
|
aspect_ratio?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServiceButtonElementConfig extends LovelaceElementConfig {
|
||||||
|
title?: string;
|
||||||
|
service?: string;
|
||||||
|
service_data?: object;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StateBadgeElementConfig extends LovelaceElementConfig {
|
||||||
|
entity: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StateIconElementConfig extends LovelaceElementConfig {
|
||||||
|
entity: string;
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
hold_action?: ActionConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StateLabelElementConfig extends LovelaceElementConfig {
|
||||||
|
entity: string;
|
||||||
|
prefix?: string;
|
||||||
|
suffix?: string;
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
hold_action?: ActionConfig;
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import "../../../components/ha-climate-state";
|
import "../../../components/ha-climate-state";
|
||||||
@ -14,6 +15,7 @@ import "../components/hui-warning";
|
|||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { EntityRow, EntityConfig } from "./types";
|
import { EntityRow, EntityConfig } from "./types";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
@customElement("hui-climate-entity-row")
|
@customElement("hui-climate-entity-row")
|
||||||
class HuiClimateEntityRow extends LitElement implements EntityRow {
|
class HuiClimateEntityRow extends LitElement implements EntityRow {
|
||||||
@ -29,6 +31,10 @@ class HuiClimateEntityRow extends LitElement implements EntityRow {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass || !this._config) {
|
if (!this.hass || !this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import "../components/hui-generic-entity-row";
|
import "../components/hui-generic-entity-row";
|
||||||
@ -16,6 +17,7 @@ import "../components/hui-warning";
|
|||||||
import { isTiltOnly } from "../../../util/cover-model";
|
import { isTiltOnly } from "../../../util/cover-model";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { EntityRow, EntityConfig } from "./types";
|
import { EntityRow, EntityConfig } from "./types";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
@customElement("hui-cover-entity-row")
|
@customElement("hui-cover-entity-row")
|
||||||
class HuiCoverEntityRow extends LitElement implements EntityRow {
|
class HuiCoverEntityRow extends LitElement implements EntityRow {
|
||||||
@ -30,6 +32,10 @@ class HuiCoverEntityRow extends LitElement implements EntityRow {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
property,
|
property,
|
||||||
customElement,
|
customElement,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import "../components/hui-generic-entity-row";
|
import "../components/hui-generic-entity-row";
|
||||||
@ -11,9 +12,11 @@ import "../../../components/entity/ha-entity-toggle";
|
|||||||
import "../components/hui-warning";
|
import "../components/hui-warning";
|
||||||
|
|
||||||
import computeStateDisplay from "../../../common/entity/compute_state_display";
|
import computeStateDisplay from "../../../common/entity/compute_state_display";
|
||||||
|
|
||||||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { EntityRow, EntityConfig } from "./types";
|
import { EntityRow, EntityConfig } from "./types";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
@customElement("hui-group-entity-row")
|
@customElement("hui-group-entity-row")
|
||||||
class HuiGroupEntityRow extends LitElement implements EntityRow {
|
class HuiGroupEntityRow extends LitElement implements EntityRow {
|
||||||
@ -28,6 +31,10 @@ class HuiGroupEntityRow extends LitElement implements EntityRow {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
customElement,
|
customElement,
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import "../components/hui-generic-entity-row";
|
import "../components/hui-generic-entity-row";
|
||||||
@ -16,6 +17,7 @@ import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
|||||||
import { EntityRow, EntityConfig } from "./types";
|
import { EntityRow, EntityConfig } from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { setValue } from "../../../data/input_text";
|
import { setValue } from "../../../data/input_text";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
@customElement("hui-input-number-entity-row")
|
@customElement("hui-input-number-entity-row")
|
||||||
class HuiInputNumberEntityRow extends LitElement implements EntityRow {
|
class HuiInputNumberEntityRow extends LitElement implements EntityRow {
|
||||||
@ -48,6 +50,10 @@ class HuiInputNumberEntityRow extends LitElement implements EntityRow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { repeat } from "lit-html/directives/repeat";
|
import { repeat } from "lit-html/directives/repeat";
|
||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||||
@ -16,9 +17,11 @@ import "../../../components/entity/state-badge";
|
|||||||
import "../components/hui-warning";
|
import "../components/hui-warning";
|
||||||
|
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { EntityRow, EntityConfig } from "./types";
|
import { EntityRow, EntityConfig } from "./types";
|
||||||
import { setOption } from "../../../data/input-select";
|
import { setOption } from "../../../data/input-select";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
@customElement("hui-input-select-entity-row")
|
@customElement("hui-input-select-entity-row")
|
||||||
class HuiInputSelectEntityRow extends LitElement implements EntityRow {
|
class HuiInputSelectEntityRow extends LitElement implements EntityRow {
|
||||||
@ -34,6 +37,10 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass || !this._config) {
|
if (!this.hass || !this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
property,
|
property,
|
||||||
customElement,
|
customElement,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ import "../components/hui-warning";
|
|||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { EntityRow, EntityConfig } from "./types";
|
import { EntityRow, EntityConfig } from "./types";
|
||||||
import { setValue } from "../../../data/input_text";
|
import { setValue } from "../../../data/input_text";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
@customElement("hui-input-text-entity-row")
|
@customElement("hui-input-text-entity-row")
|
||||||
class HuiInputTextEntityRow extends LitElement implements EntityRow {
|
class HuiInputTextEntityRow extends LitElement implements EntityRow {
|
||||||
@ -27,6 +29,10 @@ class HuiInputTextEntityRow extends LitElement implements EntityRow {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
|
||||||
import "../components/hui-generic-entity-row";
|
import "../components/hui-generic-entity-row";
|
||||||
@ -13,6 +14,7 @@ import "../components/hui-warning";
|
|||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { EntityRow, EntityConfig } from "./types";
|
import { EntityRow, EntityConfig } from "./types";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
@customElement("hui-lock-entity-row")
|
@customElement("hui-lock-entity-row")
|
||||||
class HuiLockEntityRow extends LitElement implements EntityRow {
|
class HuiLockEntityRow extends LitElement implements EntityRow {
|
||||||
@ -27,6 +29,10 @@ class HuiLockEntityRow extends LitElement implements EntityRow {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
property,
|
property,
|
||||||
customElement,
|
customElement,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ import {
|
|||||||
OFF_STATES,
|
OFF_STATES,
|
||||||
SUPPORT_PAUSE,
|
SUPPORT_PAUSE,
|
||||||
} from "../../../data/media-player";
|
} from "../../../data/media-player";
|
||||||
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
|
|
||||||
@customElement("hui-media-player-entity-row")
|
@customElement("hui-media-player-entity-row")
|
||||||
class HuiMediaPlayerEntityRow extends LitElement implements EntityRow {
|
class HuiMediaPlayerEntityRow extends LitElement implements EntityRow {
|
||||||
@ -37,6 +39,10 @@ class HuiMediaPlayerEntityRow extends LitElement implements EntityRow {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
return hasConfigOrEntityChanged(this, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass || !this._config) {
|
if (!this.hass || !this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user