mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 17:56:46 +00:00
commit
00ad91af9a
@ -1,12 +1,11 @@
|
|||||||
import { html, LitElement } from "@polymer/lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
import "@polymer/paper-button/paper-button";
|
import "@polymer/paper-button/paper-button";
|
||||||
|
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import { longPress } from "../../../src/panels/lovelace/common/directives/long-press-directive";
|
import { longPress } from "../../../src/panels/lovelace/common/directives/long-press-directive";
|
||||||
|
|
||||||
export class DemoUtilLongPress extends LitElement {
|
export class DemoUtilLongPress extends LitElement {
|
||||||
public render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
${this.renderStyle()}
|
${this.renderStyle()}
|
||||||
${
|
${
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
"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-ripple": "^0.3.1",
|
|
||||||
"@mdi/svg": "^3.0.39",
|
"@mdi/svg": "^3.0.39",
|
||||||
"@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",
|
||||||
@ -35,7 +34,6 @@
|
|||||||
"@polymer/iron-media-query": "^3.0.1",
|
"@polymer/iron-media-query": "^3.0.1",
|
||||||
"@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/lit-element": "0.6.2",
|
|
||||||
"@polymer/neon-animation": "^3.0.1",
|
"@polymer/neon-animation": "^3.0.1",
|
||||||
"@polymer/paper-button": "^3.0.1",
|
"@polymer/paper-button": "^3.0.1",
|
||||||
"@polymer/paper-card": "^3.0.1",
|
"@polymer/paper-card": "^3.0.1",
|
||||||
@ -78,7 +76,8 @@
|
|||||||
"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-html": "0.12.0",
|
"lit-element": "2.0.0-rc.2",
|
||||||
|
"lit-html": "1.0.0-rc.2",
|
||||||
"marked": "^0.5.0",
|
"marked": "^0.5.0",
|
||||||
"mdn-polyfills": "^5.12.0",
|
"mdn-polyfills": "^5.12.0",
|
||||||
"moment": "^2.22.2",
|
"moment": "^2.22.2",
|
||||||
@ -158,9 +157,7 @@
|
|||||||
"@webcomponents/shadycss": "^1.6.0",
|
"@webcomponents/shadycss": "^1.6.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",
|
||||||
"fecha": "https://github.com/taylorhakes/fecha/archive/5e8fe08d982647fdb19fb403459838b02647813c.tar.gz",
|
"fecha": "https://github.com/taylorhakes/fecha/archive/5e8fe08d982647fdb19fb403459838b02647813c.tar.gz"
|
||||||
"lit-html": "0.12.0",
|
|
||||||
"@polymer/lit-element": "0.6.2"
|
|
||||||
},
|
},
|
||||||
"main": "src/home-assistant.js",
|
"main": "src/home-assistant.js",
|
||||||
"husky": {
|
"husky": {
|
||||||
|
@ -10,9 +10,10 @@ function patch(version) {
|
|||||||
|
|
||||||
function today() {
|
function today() {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
return `${now.getFullYear()}${now.getMonth() + 1}${String(
|
return `${now.getFullYear()}${String(now.getMonth() + 1).padStart(
|
||||||
now.getDate()
|
2,
|
||||||
).padStart(2, "0")}.0`;
|
"0"
|
||||||
|
)}${String(now.getDate()).padStart(2, "0")}.0`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const methods = {
|
const methods = {
|
||||||
@ -51,4 +52,4 @@ async function main(args) {
|
|||||||
console.log(stdout);
|
console.log(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
main(process.argv.slice(2));
|
main(process.argv.slice(2)).catch(console.error);
|
||||||
|
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="20190109.1",
|
version="20190116.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",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
||||||
import { LitElement, html, PropertyDeclarations } from "@polymer/lit-element";
|
import { LitElement, html, PropertyDeclarations } from "lit-element";
|
||||||
import "./ha-auth-flow";
|
import "./ha-auth-flow";
|
||||||
import { AuthProvider } from "../data/auth";
|
import { AuthProvider } from "../data/auth";
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
protected render() {
|
||||||
if (!this._authProviders) {
|
if (!this._authProviders) {
|
||||||
return html`
|
return html`
|
||||||
<p>[[localize('ui.panel.page-authorize.initializing')]]</p>
|
<p>[[localize('ui.panel.page-authorize.initializing')]]</p>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
export const DEFAULT_DOMAIN_ICON = "hass:bookmark";
|
export const DEFAULT_DOMAIN_ICON = "hass:bookmark";
|
||||||
|
|
||||||
/** Panel to show when no panel is picked. */
|
/** Panel to show when no panel is picked. */
|
||||||
export const DEFAULT_PANEL = "states";
|
export const DEFAULT_PANEL = "lovelace";
|
||||||
|
|
||||||
/** Domains that have a state card. */
|
/** Domains that have a state card. */
|
||||||
export const DOMAINS_WITH_CARD = [
|
export const DOMAINS_WITH_CARD = [
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { LitElement, html } from "@polymer/lit-element";
|
import { LitElement, html } from "lit-element";
|
||||||
|
|
||||||
import "./ha-progress-button";
|
import "./ha-progress-button";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
@ -3,10 +3,10 @@ import {
|
|||||||
html,
|
html,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult } from "lit-html";
|
} from "lit-element";
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { classMap } from "lit-html/directives/classMap";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
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";
|
||||||
@ -41,7 +41,7 @@ export class HaStateLabelBadge extends hassLocalizeLitMixin(LitElement) {
|
|||||||
this.clearInterval();
|
this.clearInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
const state = this.state;
|
const state = this.state;
|
||||||
|
|
||||||
if (!state) {
|
if (!state) {
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult, html } from "lit-html";
|
CSSResult,
|
||||||
import { classMap } from "lit-html/directives/classMap";
|
css,
|
||||||
|
} from "lit-element";
|
||||||
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
import "./ha-icon";
|
import "./ha-icon";
|
||||||
|
|
||||||
class HaLabelBadge extends LitElement {
|
class HaLabelBadge extends LitElement {
|
||||||
@ -24,9 +27,8 @@ class HaLabelBadge extends LitElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
${this.renderStyle()}
|
|
||||||
<div class="badge-container">
|
<div class="badge-container">
|
||||||
<div class="label-badge" id="badge">
|
<div class="label-badge" id="badge">
|
||||||
<div
|
<div
|
||||||
@ -77,9 +79,9 @@ class HaLabelBadge extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected renderStyle(): TemplateResult {
|
static get styles(): CSSResult[] {
|
||||||
return html`
|
return [
|
||||||
<style>
|
css`
|
||||||
.badge-container {
|
.badge-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -148,8 +150,8 @@ class HaLabelBadge extends LitElement {
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
</style>
|
`,
|
||||||
`;
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProperties: PropertyValues): void {
|
protected updated(changedProperties: PropertyValues): void {
|
||||||
|
@ -20,6 +20,7 @@ class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
|||||||
<paper-toggle-button
|
<paper-toggle-button
|
||||||
disabled="[[_compDisabled(disabled, loading)]]"
|
disabled="[[_compDisabled(disabled, loading)]]"
|
||||||
checked="{{pushChecked}}"
|
checked="{{pushChecked}}"
|
||||||
|
on-change="handlePushChange"
|
||||||
></paper-toggle-button>
|
></paper-toggle-button>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -35,7 +36,6 @@ class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
value:
|
value:
|
||||||
"Notification" in window && Notification.permission === "granted",
|
"Notification" in window && Notification.permission === "granted",
|
||||||
observer: "handlePushChange",
|
|
||||||
},
|
},
|
||||||
loading: {
|
loading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -63,12 +63,12 @@ class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePushChange(pushChecked) {
|
handlePushChange(event) {
|
||||||
// Somehow this is triggered on Safari on page load causing
|
// Somehow this is triggered on Safari on page load causing
|
||||||
// it to get into a loop and crash the page.
|
// it to get into a loop and crash the page.
|
||||||
if (!pushSupported) return;
|
if (!pushSupported) return;
|
||||||
|
|
||||||
if (pushChecked) {
|
if (event.target.checked) {
|
||||||
this.subscribePushNotifications();
|
this.subscribePushNotifications();
|
||||||
} else {
|
} else {
|
||||||
this.unsubscribePushNotifications();
|
this.unsubscribePushNotifications();
|
||||||
@ -77,10 +77,9 @@ class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
|||||||
|
|
||||||
async subscribePushNotifications() {
|
async subscribePushNotifications() {
|
||||||
const reg = await navigator.serviceWorker.ready;
|
const reg = await navigator.serviceWorker.ready;
|
||||||
|
let sub;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const sub = await reg.pushManager.subscribe({ userVisibleOnly: true });
|
|
||||||
|
|
||||||
let browserName;
|
let browserName;
|
||||||
if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1) {
|
if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1) {
|
||||||
browserName = "firefox";
|
browserName = "firefox";
|
||||||
@ -88,12 +87,24 @@ class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
|||||||
browserName = "chrome";
|
browserName = "chrome";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const name = prompt("What should this device be called ?");
|
||||||
|
if (name == null) {
|
||||||
|
this.pushChecked = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub = await reg.pushManager.subscribe({ userVisibleOnly: true });
|
||||||
|
|
||||||
await this.hass.callApi("POST", "notify.html5", {
|
await this.hass.callApi("POST", "notify.html5", {
|
||||||
subscription: sub,
|
subscription: sub,
|
||||||
browser: browserName,
|
browser: browserName,
|
||||||
|
name,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const message = err.message || "Notification registration failed.";
|
const message = err.message || "Notification registration failed.";
|
||||||
|
if (sub) {
|
||||||
|
await sub.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
@ -1,8 +1,28 @@
|
|||||||
import "@polymer/paper-slider";
|
import "@polymer/paper-slider";
|
||||||
|
|
||||||
const PaperSliderClass = customElements.get("paper-slider");
|
const PaperSliderClass = customElements.get("paper-slider");
|
||||||
|
let subTemplate;
|
||||||
|
|
||||||
class HaSlider extends PaperSliderClass {
|
class HaSlider extends PaperSliderClass {
|
||||||
|
static get template() {
|
||||||
|
if (!subTemplate) {
|
||||||
|
subTemplate = PaperSliderClass.template.cloneNode(true);
|
||||||
|
|
||||||
|
const superStyle = subTemplate.content.querySelector("style");
|
||||||
|
|
||||||
|
// append style to add mirroring of pin in RTL
|
||||||
|
superStyle.appendChild(
|
||||||
|
document.createTextNode(`
|
||||||
|
:host([dir="rtl"]) #sliderContainer.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;
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return subTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
_calcStep(value) {
|
_calcStep(value) {
|
||||||
if (!this.step) {
|
if (!this.step) {
|
||||||
return parseFloat(value);
|
return parseFloat(value);
|
||||||
|
@ -20,6 +20,10 @@ class StateHistoryChartTimeline extends LocalizeMixin(PolymerElement) {
|
|||||||
:host([rendered]) {
|
:host([rendered]) {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ha-chart-base {
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<ha-chart-base
|
<ha-chart-base
|
||||||
data="[[chartData]]"
|
data="[[chartData]]"
|
||||||
@ -185,6 +189,11 @@ class StateHistoryChartTimeline extends LocalizeMixin(PolymerElement) {
|
|||||||
afterSetDimensions: (yaxe) => {
|
afterSetDimensions: (yaxe) => {
|
||||||
yaxe.maxWidth = yaxe.chart.width * 0.18;
|
yaxe.maxWidth = yaxe.chart.width * 0.18;
|
||||||
},
|
},
|
||||||
|
position: this.hass.translationMetadata.translations[
|
||||||
|
this.hass.selectedLanguage || this.hass.language
|
||||||
|
].isRTL
|
||||||
|
? "right"
|
||||||
|
: "left",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
|
export const FORMAT_TEXT = "text";
|
||||||
|
export const FORMAT_NUMBER = "number";
|
||||||
|
|
||||||
export const callAlarmAction = (
|
export const callAlarmAction = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entity: string,
|
entity: string,
|
||||||
|
104
src/data/zha.ts
Normal file
104
src/data/zha.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
|
export interface ZHADeviceEntity extends HassEntity {
|
||||||
|
device_info?: {
|
||||||
|
identifiers: any[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ZHAEntities {
|
||||||
|
[key: string]: HassEntity[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Attribute {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Cluster {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Command {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReadAttributeServiceData {
|
||||||
|
entity_id: string;
|
||||||
|
cluster_id: number;
|
||||||
|
cluster_type: string;
|
||||||
|
attribute: number;
|
||||||
|
manufacturer: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const reconfigureNode = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
ieeeAddress: string
|
||||||
|
): Promise<void> =>
|
||||||
|
hass.callWS({
|
||||||
|
type: "zha/nodes/reconfigure",
|
||||||
|
ieee: ieeeAddress,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchAttributesForCluster = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entityId: string,
|
||||||
|
ieeeAddress: string,
|
||||||
|
clusterId: number,
|
||||||
|
clusterType: string
|
||||||
|
): Promise<Attribute[]> =>
|
||||||
|
hass.callWS({
|
||||||
|
type: "zha/entities/clusters/attributes",
|
||||||
|
entity_id: entityId,
|
||||||
|
ieee: ieeeAddress,
|
||||||
|
cluster_id: clusterId,
|
||||||
|
cluster_type: clusterType,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const readAttributeValue = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
data: ReadAttributeServiceData
|
||||||
|
): Promise<string> => {
|
||||||
|
return hass.callWS({
|
||||||
|
...data,
|
||||||
|
type: "zha/entities/clusters/attributes/value",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchCommandsForCluster = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entityId: string,
|
||||||
|
ieeeAddress: string,
|
||||||
|
clusterId: number,
|
||||||
|
clusterType: string
|
||||||
|
): Promise<Command[]> =>
|
||||||
|
hass.callWS({
|
||||||
|
type: "zha/entities/clusters/commands",
|
||||||
|
entity_id: entityId,
|
||||||
|
ieee: ieeeAddress,
|
||||||
|
cluster_id: clusterId,
|
||||||
|
cluster_type: clusterType,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchClustersForZhaNode = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entityId: string,
|
||||||
|
ieeeAddress: string
|
||||||
|
): Promise<Cluster[]> =>
|
||||||
|
hass.callWS({
|
||||||
|
type: "zha/entities/clusters",
|
||||||
|
entity_id: entityId,
|
||||||
|
ieee: ieeeAddress,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchEntitiesForZhaNode = (
|
||||||
|
hass: HomeAssistant
|
||||||
|
): Promise<ZHAEntities> =>
|
||||||
|
hass.callWS({
|
||||||
|
type: "zha/entities",
|
||||||
|
});
|
@ -72,6 +72,18 @@ function initPushNotifications() {
|
|||||||
var data;
|
var data;
|
||||||
if (event.data) {
|
if (event.data) {
|
||||||
data = event.data.json();
|
data = event.data.json();
|
||||||
|
if (data.dismiss) {
|
||||||
|
event.waitUntil(
|
||||||
|
self.registration
|
||||||
|
.getNotifications({ tag: data.tag })
|
||||||
|
.then(function(notifications) {
|
||||||
|
for (const n of notifications) {
|
||||||
|
n.close();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
event.waitUntil(
|
event.waitUntil(
|
||||||
self.registration
|
self.registration
|
||||||
.showNotification(data.title, data)
|
.showNotification(data.title, data)
|
||||||
@ -96,7 +108,11 @@ function initPushNotifications() {
|
|||||||
|
|
||||||
event.notification.close();
|
event.notification.close();
|
||||||
|
|
||||||
if (!event.notification.data || !event.notification.data.url) {
|
if (
|
||||||
|
event.action ||
|
||||||
|
!event.notification.data ||
|
||||||
|
!event.notification.data.url
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { PolymerElement } from "@polymer/polymer";
|
import { PolymerElement } from "@polymer/polymer";
|
||||||
import { Constructor } from "@polymer/lit-element";
|
import { Constructor } from "lit-element";
|
||||||
import { HASSDomEvent, ValidHassDomEvent } from "../../common/dom/fire_event";
|
import { HASSDomEvent, ValidHassDomEvent } from "../../common/dom/fire_event";
|
||||||
|
|
||||||
interface RegisterDialogParams {
|
interface RegisterDialogParams {
|
||||||
|
@ -4,7 +4,7 @@ import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
|||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
import { afterNextRender } from "@polymer/polymer/lib/utils/render-status";
|
import { afterNextRender } from "@polymer/polymer/lib/utils/render-status";
|
||||||
import { html as litHtml, LitElement } from "@polymer/lit-element";
|
import { html as litHtml, LitElement } from "lit-element";
|
||||||
|
|
||||||
import "../home-assistant-main";
|
import "../home-assistant-main";
|
||||||
import "../ha-init-page";
|
import "../ha-init-page";
|
||||||
@ -95,7 +95,11 @@ class HomeAssistant extends ext(PolymerElement, [
|
|||||||
}
|
}
|
||||||
|
|
||||||
computePanelUrl(routeData) {
|
computePanelUrl(routeData) {
|
||||||
return (routeData && routeData.panel) || DEFAULT_PANEL;
|
return (
|
||||||
|
(routeData && routeData.panel) ||
|
||||||
|
localStorage.defaultPage ||
|
||||||
|
DEFAULT_PANEL
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
panelUrlChanged(newPanelUrl) {
|
panelUrlChanged(newPanelUrl) {
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
} from "lit-element";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import { getActiveTranslation } from "../util/hass-translation";
|
import { getActiveTranslation } from "../util/hass-translation";
|
||||||
import { LocalizeFunc, LocalizeMixin } from "./localize-base-mixin";
|
import { LocalizeFunc, LocalizeMixin } from "./localize-base-mixin";
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
} from "lit-element";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import {
|
import {
|
||||||
localizeBaseMixin,
|
localizeBaseMixin,
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-button/paper-button";
|
import "@polymer/paper-button/paper-button";
|
||||||
import "@polymer/paper-card/paper-card";
|
import "@polymer/paper-card/paper-card";
|
||||||
import "@polymer/paper-toggle-button/paper-toggle-button";
|
import "@polymer/paper-toggle-button/paper-toggle-button";
|
||||||
@ -23,7 +27,7 @@ export class CloudAlexaPref extends LitElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.cloudStatus) {
|
if (!this.cloudStatus) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult } from "lit-html";
|
} from "lit-element";
|
||||||
import { repeat } from "lit-html/directives/repeat";
|
import { repeat } from "lit-html/directives/repeat";
|
||||||
import "@polymer/paper-tooltip/paper-tooltip";
|
import "@polymer/paper-tooltip/paper-tooltip";
|
||||||
import { HassEntityBase } from "home-assistant-js-websocket";
|
import { HassEntityBase } from "home-assistant-js-websocket";
|
||||||
@ -34,7 +34,7 @@ export class CloudExposedEntities extends LitElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._filterFunc) {
|
if (!this._filterFunc) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-button/paper-button";
|
import "@polymer/paper-button/paper-button";
|
||||||
import "@polymer/paper-card/paper-card";
|
import "@polymer/paper-card/paper-card";
|
||||||
import "@polymer/paper-toggle-button/paper-toggle-button";
|
import "@polymer/paper-toggle-button/paper-toggle-button";
|
||||||
@ -24,7 +28,7 @@ export class CloudGooglePref extends LitElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.cloudStatus) {
|
if (!this.cloudStatus) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
import "@polymer/paper-button/paper-button";
|
import "@polymer/paper-button/paper-button";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
@ -10,10 +16,9 @@ import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
|
|||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { buttonLink } from "../../../resources/ha-style";
|
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { WebhookDialogParams } from "./types";
|
import { WebhookDialogParams } from "./types";
|
||||||
|
import { haStyle } from "../../../resources/ha-style";
|
||||||
|
|
||||||
const inputLabel = "Public URL – Click to copy to clipboard";
|
const inputLabel = "Public URL – Click to copy to clipboard";
|
||||||
|
|
||||||
@ -44,7 +49,6 @@ export class CloudWebhookManageDialog extends LitElement {
|
|||||||
? "https://www.home-assistant.io/docs/automation/trigger/#webhook-trigger"
|
? "https://www.home-assistant.io/docs/automation/trigger/#webhook-trigger"
|
||||||
: `https://www.home-assistant.io/components/${webhook.domain}/`;
|
: `https://www.home-assistant.io/components/${webhook.domain}/`;
|
||||||
return html`
|
return html`
|
||||||
${this._renderStyle()}
|
|
||||||
<paper-dialog with-backdrop>
|
<paper-dialog with-backdrop>
|
||||||
<h2>Webhook for ${webhook.name}</h2>
|
<h2>Webhook for ${webhook.name}</h2>
|
||||||
<div>
|
<div>
|
||||||
@ -112,24 +116,25 @@ export class CloudWebhookManageDialog extends LitElement {
|
|||||||
this._paperInput.label = inputLabel;
|
this._paperInput.label = inputLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderStyle() {
|
static get styles(): CSSResult[] {
|
||||||
return html`
|
return [
|
||||||
<style>
|
haStyle,
|
||||||
|
css`
|
||||||
paper-dialog {
|
paper-dialog {
|
||||||
width: 650px;
|
width: 650px;
|
||||||
}
|
}
|
||||||
paper-input {
|
paper-input {
|
||||||
margin-top: -8px;
|
margin-top: -8px;
|
||||||
}
|
}
|
||||||
${buttonLink} button.link {
|
button.link {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
paper-button {
|
paper-button {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
</style>
|
`,
|
||||||
`;
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-toggle-button/paper-toggle-button";
|
import "@polymer/paper-toggle-button/paper-toggle-button";
|
||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
import "@polymer/paper-item/paper-item-body";
|
import "@polymer/paper-item/paper-item-body";
|
||||||
|
52
src/panels/config/js/trigger/time_pattern.js
Normal file
52
src/panels/config/js/trigger/time_pattern.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { h, Component } from "preact";
|
||||||
|
|
||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
|
import { onChangeEvent } from "../../../../common/preact/event";
|
||||||
|
|
||||||
|
export default class TimePatternTrigger extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.onChange = onChangeEvent.bind(this, "trigger");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
render({ trigger, localize }) {
|
||||||
|
const { hours, minutes, seconds } = trigger;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<paper-input
|
||||||
|
label={localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.type.time_pattern.hours"
|
||||||
|
)}
|
||||||
|
name="hours"
|
||||||
|
value={hours}
|
||||||
|
onvalue-changed={this.onChange}
|
||||||
|
/>
|
||||||
|
<paper-input
|
||||||
|
label={localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.type.time_pattern.minutes"
|
||||||
|
)}
|
||||||
|
name="minutes"
|
||||||
|
value={minutes}
|
||||||
|
onvalue-changed={this.onChange}
|
||||||
|
/>
|
||||||
|
<paper-input
|
||||||
|
label={localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.type.time_pattern.seconds"
|
||||||
|
)}
|
||||||
|
name="seconds"
|
||||||
|
value={seconds}
|
||||||
|
onvalue-changed={this.onChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TimePatternTrigger.defaultConfig = {
|
||||||
|
hours: "",
|
||||||
|
minutes: "",
|
||||||
|
seconds: "",
|
||||||
|
};
|
@ -8,6 +8,7 @@ import EventTrigger from "./event";
|
|||||||
import HassTrigger from "./homeassistant";
|
import HassTrigger from "./homeassistant";
|
||||||
import MQTTTrigger from "./mqtt";
|
import MQTTTrigger from "./mqtt";
|
||||||
import NumericStateTrigger from "./numeric_state";
|
import NumericStateTrigger from "./numeric_state";
|
||||||
|
import TimePatternTrigger from "./time_pattern";
|
||||||
import StateTrigger from "./state";
|
import StateTrigger from "./state";
|
||||||
import SunTrigger from "./sun";
|
import SunTrigger from "./sun";
|
||||||
import TemplateTrigger from "./template";
|
import TemplateTrigger from "./template";
|
||||||
@ -24,6 +25,7 @@ const TYPES = {
|
|||||||
sun: SunTrigger,
|
sun: SunTrigger,
|
||||||
template: TemplateTrigger,
|
template: TemplateTrigger,
|
||||||
time: TimeTrigger,
|
time: TimeTrigger,
|
||||||
|
time_pattern: TimePatternTrigger,
|
||||||
webhook: WebhookTrigger,
|
webhook: WebhookTrigger,
|
||||||
zone: ZoneTrigger,
|
zone: ZoneTrigger,
|
||||||
};
|
};
|
||||||
|
@ -1,51 +1,119 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
import "@polymer/app-layout/app-header/app-header";
|
import "@polymer/app-layout/app-header/app-header";
|
||||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
|
||||||
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||||
import { HomeAssistant } from "../../../types";
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { HASSDomEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { Cluster } from "../../../data/zha";
|
||||||
import "../../../layouts/ha-app-layout";
|
import "../../../layouts/ha-app-layout";
|
||||||
import "../../../resources/ha-style";
|
import "../../../resources/ha-style";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import {
|
||||||
|
ZHAClusterSelectedParams,
|
||||||
|
ZHAEntitySelectedParams,
|
||||||
|
ZHANodeSelectedParams,
|
||||||
|
} from "./types";
|
||||||
|
import "./zha-cluster-attributes";
|
||||||
|
import "./zha-cluster-commands";
|
||||||
import "./zha-network";
|
import "./zha-network";
|
||||||
|
import "./zha-node";
|
||||||
|
|
||||||
export class HaConfigZha extends LitElement {
|
export class HaConfigZha extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
public isWide?: boolean;
|
public isWide?: boolean;
|
||||||
private _haStyle?: DocumentFragment;
|
private _haStyle?: DocumentFragment;
|
||||||
private _ironFlex?: DocumentFragment;
|
private _ironFlex?: DocumentFragment;
|
||||||
|
private _selectedNode?: HassEntity;
|
||||||
|
private _selectedCluster?: Cluster;
|
||||||
|
private _selectedEntity?: HassEntity;
|
||||||
|
|
||||||
static get properties(): PropertyDeclarations {
|
static get properties(): PropertyDeclarations {
|
||||||
return {
|
return {
|
||||||
hass: {},
|
hass: {},
|
||||||
isWide: {},
|
isWide: {},
|
||||||
|
_selectedCluster: {},
|
||||||
|
_selectedEntity: {},
|
||||||
|
_selectedNode: {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
${this.renderStyle()}
|
${this.renderStyle()}
|
||||||
<ha-app-layout has-scrolling-region="">
|
<ha-app-layout>
|
||||||
<app-header slot="header" fixed="">
|
<app-header slot="header">
|
||||||
<app-toolbar>
|
<app-toolbar>
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon="hass:arrow-left"
|
icon="hass:arrow-left"
|
||||||
@click="${this._onBackTapped}"
|
@click="${this._onBackTapped}"
|
||||||
></paper-icon-button>
|
></paper-icon-button>
|
||||||
|
<div main-title>Zigbee Home Automation</div>
|
||||||
</app-toolbar>
|
</app-toolbar>
|
||||||
</app-header>
|
</app-header>
|
||||||
|
|
||||||
<zha-network
|
<zha-network
|
||||||
id="zha-network"
|
.isWide="${this.isWide}"
|
||||||
.is-wide="${this.isWide}"
|
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
></zha-network>
|
></zha-network>
|
||||||
|
|
||||||
|
<zha-node
|
||||||
|
.isWide="${this.isWide}"
|
||||||
|
.hass="${this.hass}"
|
||||||
|
@zha-cluster-selected="${this._onClusterSelected}"
|
||||||
|
@zha-node-selected="${this._onNodeSelected}"
|
||||||
|
@zha-entity-selected="${this._onEntitySelected}"
|
||||||
|
></zha-node>
|
||||||
|
${
|
||||||
|
this._selectedCluster
|
||||||
|
? html`
|
||||||
|
<zha-cluster-attributes
|
||||||
|
.isWide="${this.isWide}"
|
||||||
|
.hass="${this.hass}"
|
||||||
|
.selectedNode="${this._selectedNode}"
|
||||||
|
.selectedEntity="${this._selectedEntity}"
|
||||||
|
.selectedCluster="${this._selectedCluster}"
|
||||||
|
></zha-cluster-attributes>
|
||||||
|
|
||||||
|
<zha-cluster-commands
|
||||||
|
.isWide="${this.isWide}"
|
||||||
|
.hass="${this.hass}"
|
||||||
|
.selectedNode="${this._selectedNode}"
|
||||||
|
.selectedEntity="${this._selectedEntity}"
|
||||||
|
.selectedCluster="${this._selectedCluster}"
|
||||||
|
></zha-cluster-commands>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
</ha-app-layout>
|
</ha-app-layout>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _onClusterSelected(
|
||||||
|
selectedClusterEvent: HASSDomEvent<ZHAClusterSelectedParams>
|
||||||
|
): void {
|
||||||
|
this._selectedCluster = selectedClusterEvent.detail.cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onNodeSelected(
|
||||||
|
selectedNodeEvent: HASSDomEvent<ZHANodeSelectedParams>
|
||||||
|
): void {
|
||||||
|
this._selectedNode = selectedNodeEvent.detail.node;
|
||||||
|
this._selectedCluster = undefined;
|
||||||
|
this._selectedEntity = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onEntitySelected(
|
||||||
|
selectedEntityEvent: HASSDomEvent<ZHAEntitySelectedParams>
|
||||||
|
): void {
|
||||||
|
this._selectedEntity = selectedEntityEvent.detail.entity;
|
||||||
|
}
|
||||||
|
|
||||||
private renderStyle(): TemplateResult {
|
private renderStyle(): TemplateResult {
|
||||||
if (!this._haStyle) {
|
if (!this._haStyle) {
|
||||||
this._haStyle = document.importNode(
|
this._haStyle = document.importNode(
|
||||||
|
50
src/panels/config/zha/types.ts
Normal file
50
src/panels/config/zha/types.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { ZHADeviceEntity, Cluster } from "../../../data/zha";
|
||||||
|
|
||||||
|
export interface PickerTarget extends EventTarget {
|
||||||
|
selected: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ItemSelectedEvent {
|
||||||
|
target?: PickerTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChangeEvent {
|
||||||
|
detail?: {
|
||||||
|
value?: any;
|
||||||
|
};
|
||||||
|
target?: EventTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SetAttributeServiceData {
|
||||||
|
entity_id: string;
|
||||||
|
cluster_id: number;
|
||||||
|
cluster_type: string;
|
||||||
|
attribute: number;
|
||||||
|
value: any;
|
||||||
|
manufacturer: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IssueCommandServiceData {
|
||||||
|
entity_id: string;
|
||||||
|
cluster_id: number;
|
||||||
|
cluster_type: string;
|
||||||
|
command: number;
|
||||||
|
command_type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ZHAEntitySelectedParams {
|
||||||
|
entity: HassEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ZHANodeSelectedParams {
|
||||||
|
node: ZHADeviceEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ZHAClusterSelectedParams {
|
||||||
|
cluster: Cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NodeServiceData {
|
||||||
|
ieee_address: string;
|
||||||
|
}
|
329
src/panels/config/zha/zha-cluster-attributes.ts
Normal file
329
src/panels/config/zha/zha-cluster-attributes.ts
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||||
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
PropertyValues,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@polymer/paper-button/paper-button";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../components/ha-service-description";
|
||||||
|
import {
|
||||||
|
Attribute,
|
||||||
|
Cluster,
|
||||||
|
fetchAttributesForCluster,
|
||||||
|
ReadAttributeServiceData,
|
||||||
|
readAttributeValue,
|
||||||
|
ZHADeviceEntity,
|
||||||
|
} from "../../../data/zha";
|
||||||
|
import "../../../resources/ha-style";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import "../ha-config-section";
|
||||||
|
import {
|
||||||
|
ChangeEvent,
|
||||||
|
ItemSelectedEvent,
|
||||||
|
SetAttributeServiceData,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
|
export class ZHAClusterAttributes extends LitElement {
|
||||||
|
public hass?: HomeAssistant;
|
||||||
|
public isWide?: boolean;
|
||||||
|
public showHelp: boolean;
|
||||||
|
public selectedNode?: HassEntity;
|
||||||
|
public selectedEntity?: ZHADeviceEntity;
|
||||||
|
public selectedCluster?: Cluster;
|
||||||
|
private _haStyle?: DocumentFragment;
|
||||||
|
private _ironFlex?: DocumentFragment;
|
||||||
|
private _attributes: Attribute[];
|
||||||
|
private _selectedAttributeIndex: number;
|
||||||
|
private _attributeValue?: any;
|
||||||
|
private _manufacturerCodeOverride?: string | number;
|
||||||
|
private _setAttributeServiceData?: SetAttributeServiceData;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.showHelp = false;
|
||||||
|
this._selectedAttributeIndex = -1;
|
||||||
|
this._attributes = [];
|
||||||
|
this._attributeValue = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties(): PropertyDeclarations {
|
||||||
|
return {
|
||||||
|
hass: {},
|
||||||
|
isWide: {},
|
||||||
|
showHelp: {},
|
||||||
|
selectedNode: {},
|
||||||
|
selectedEntity: {},
|
||||||
|
selectedCluster: {},
|
||||||
|
_attributes: {},
|
||||||
|
_selectedAttributeIndex: {},
|
||||||
|
_attributeValue: {},
|
||||||
|
_manufacturerCodeOverride: {},
|
||||||
|
_setAttributeServiceData: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updated(changedProperties: PropertyValues): void {
|
||||||
|
if (changedProperties.has("selectedCluster")) {
|
||||||
|
this._attributes = [];
|
||||||
|
this._selectedAttributeIndex = -1;
|
||||||
|
this._attributeValue = "";
|
||||||
|
this._fetchAttributesForCluster();
|
||||||
|
}
|
||||||
|
super.update(changedProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
return html`
|
||||||
|
${this.renderStyle()}
|
||||||
|
<ha-config-section .isWide="${this.isWide}">
|
||||||
|
<div style="position: relative" slot="header">
|
||||||
|
<span>Cluster Attributes</span>
|
||||||
|
<paper-icon-button
|
||||||
|
class="toggle-help-icon"
|
||||||
|
@click="${this._onHelpTap}"
|
||||||
|
icon="hass:help-circle"
|
||||||
|
>
|
||||||
|
</paper-icon-button>
|
||||||
|
</div>
|
||||||
|
<span slot="introduction">View and edit cluster attributes.</span>
|
||||||
|
|
||||||
|
<paper-card class="content">
|
||||||
|
<div class="attribute-picker">
|
||||||
|
<paper-dropdown-menu
|
||||||
|
label="Attributes of the selected cluster"
|
||||||
|
class="flex"
|
||||||
|
>
|
||||||
|
<paper-listbox
|
||||||
|
slot="dropdown-content"
|
||||||
|
.selected="${this._selectedAttributeIndex}"
|
||||||
|
@iron-select="${this._selectedAttributeChanged}"
|
||||||
|
>
|
||||||
|
${
|
||||||
|
this._attributes.map(
|
||||||
|
(entry) => html`
|
||||||
|
<paper-item
|
||||||
|
>${entry.name + " (id: " + entry.id + ")"}</paper-item
|
||||||
|
>
|
||||||
|
`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
${
|
||||||
|
this.showHelp
|
||||||
|
? html`
|
||||||
|
<div style="color: grey; padding: 16px">
|
||||||
|
Select an attribute to view or set its value
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
${
|
||||||
|
this._selectedAttributeIndex !== -1
|
||||||
|
? this._renderAttributeInteractions()
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
</paper-card>
|
||||||
|
</ha-config-section>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderAttributeInteractions(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="input-text">
|
||||||
|
<paper-input
|
||||||
|
label="Value"
|
||||||
|
type="string"
|
||||||
|
.value="${this._attributeValue}"
|
||||||
|
@value-changed="${this._onAttributeValueChanged}"
|
||||||
|
placeholder="Value"
|
||||||
|
></paper-input>
|
||||||
|
</div>
|
||||||
|
<div class="input-text">
|
||||||
|
<paper-input
|
||||||
|
label="Manufacturer code override"
|
||||||
|
type="number"
|
||||||
|
.value="${this._manufacturerCodeOverride}"
|
||||||
|
@value-changed="${this._onManufacturerCodeOverrideChanged}"
|
||||||
|
placeholder="Value"
|
||||||
|
></paper-input>
|
||||||
|
</div>
|
||||||
|
<div class="card-actions">
|
||||||
|
<paper-button @click="${this._onGetZigbeeAttributeClick}"
|
||||||
|
>Get Zigbee Attribute</paper-button
|
||||||
|
>
|
||||||
|
<ha-call-service-button
|
||||||
|
.hass="${this.hass}"
|
||||||
|
domain="zha"
|
||||||
|
service="set_zigbee_cluster_attribute"
|
||||||
|
.serviceData="${this._setAttributeServiceData}"
|
||||||
|
>Set Zigbee Attribute</ha-call-service-button
|
||||||
|
>
|
||||||
|
${
|
||||||
|
this.showHelp
|
||||||
|
? html`
|
||||||
|
<ha-service-description
|
||||||
|
.hass="${this.hass}"
|
||||||
|
domain="zha"
|
||||||
|
service="set_zigbee_cluster_attribute"
|
||||||
|
></ha-service-description>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _fetchAttributesForCluster(): Promise<void> {
|
||||||
|
if (this.selectedEntity && this.selectedCluster && this.hass) {
|
||||||
|
this._attributes = await fetchAttributesForCluster(
|
||||||
|
this.hass,
|
||||||
|
this.selectedEntity!.entity_id,
|
||||||
|
this.selectedEntity!.device_info!.identifiers[0][1],
|
||||||
|
this.selectedCluster!.id,
|
||||||
|
this.selectedCluster!.type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeReadAttributeServiceData():
|
||||||
|
| ReadAttributeServiceData
|
||||||
|
| undefined {
|
||||||
|
if (!this.selectedEntity || !this.selectedCluster || !this.selectedNode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
entity_id: this.selectedEntity!.entity_id,
|
||||||
|
cluster_id: this.selectedCluster!.id,
|
||||||
|
cluster_type: this.selectedCluster!.type,
|
||||||
|
attribute: this._attributes[this._selectedAttributeIndex].id,
|
||||||
|
manufacturer: this._manufacturerCodeOverride
|
||||||
|
? parseInt(this._manufacturerCodeOverride as string, 10)
|
||||||
|
: this.selectedNode!.attributes.manufacturer_code,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeSetAttributeServiceData():
|
||||||
|
| SetAttributeServiceData
|
||||||
|
| undefined {
|
||||||
|
if (!this.selectedEntity || !this.selectedCluster || !this.selectedNode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
entity_id: this.selectedEntity!.entity_id,
|
||||||
|
cluster_id: this.selectedCluster!.id,
|
||||||
|
cluster_type: this.selectedCluster!.type,
|
||||||
|
attribute: this._attributes[this._selectedAttributeIndex].id,
|
||||||
|
value: this._attributeValue,
|
||||||
|
manufacturer: this._manufacturerCodeOverride
|
||||||
|
? parseInt(this._manufacturerCodeOverride as string, 10)
|
||||||
|
: this.selectedNode!.attributes.manufacturer_code,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onAttributeValueChanged(value: ChangeEvent): void {
|
||||||
|
this._attributeValue = value.detail!.value;
|
||||||
|
this._setAttributeServiceData = this._computeSetAttributeServiceData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onManufacturerCodeOverrideChanged(value: ChangeEvent): void {
|
||||||
|
this._manufacturerCodeOverride = value.detail!.value;
|
||||||
|
this._setAttributeServiceData = this._computeSetAttributeServiceData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _onGetZigbeeAttributeClick(): Promise<void> {
|
||||||
|
const data = this._computeReadAttributeServiceData();
|
||||||
|
if (data && this.hass) {
|
||||||
|
this._attributeValue = await readAttributeValue(this.hass, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onHelpTap(): void {
|
||||||
|
this.showHelp = !this.showHelp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _selectedAttributeChanged(event: ItemSelectedEvent): void {
|
||||||
|
this._selectedAttributeIndex = event.target!.selected;
|
||||||
|
this._attributeValue = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderStyle(): TemplateResult {
|
||||||
|
if (!this._haStyle) {
|
||||||
|
this._haStyle = document.importNode(
|
||||||
|
(document.getElementById("ha-style")!
|
||||||
|
.children[0] as HTMLTemplateElement).content,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!this._ironFlex) {
|
||||||
|
this._ironFlex = document.importNode(
|
||||||
|
(document.getElementById("iron-flex")!
|
||||||
|
.children[0] as HTMLTemplateElement).content,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return html`
|
||||||
|
${this._ironFlex} ${this._haStyle}
|
||||||
|
<style>
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-actions.warning ha-call-service-button {
|
||||||
|
color: var(--google-red-500);
|
||||||
|
}
|
||||||
|
|
||||||
|
.attribute-picker {
|
||||||
|
@apply --layout-horizontal;
|
||||||
|
@apply --layout-center-center;
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-text {
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-help-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
right: 0;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-service-description {
|
||||||
|
display: block;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"zha-cluster-attributes": ZHAClusterAttributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("zha-cluster-attributes", ZHAClusterAttributes);
|
282
src/panels/config/zha/zha-cluster-commands.ts
Normal file
282
src/panels/config/zha/zha-cluster-commands.ts
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||||
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
PropertyValues,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../components/ha-service-description";
|
||||||
|
import {
|
||||||
|
Cluster,
|
||||||
|
Command,
|
||||||
|
fetchCommandsForCluster,
|
||||||
|
ZHADeviceEntity,
|
||||||
|
} from "../../../data/zha";
|
||||||
|
import "../../../resources/ha-style";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import "../ha-config-section";
|
||||||
|
import {
|
||||||
|
ChangeEvent,
|
||||||
|
IssueCommandServiceData,
|
||||||
|
ItemSelectedEvent,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
|
export class ZHAClusterCommands extends LitElement {
|
||||||
|
public hass?: HomeAssistant;
|
||||||
|
public isWide?: boolean;
|
||||||
|
public selectedNode?: HassEntity;
|
||||||
|
public selectedEntity?: ZHADeviceEntity;
|
||||||
|
public selectedCluster?: Cluster;
|
||||||
|
private _showHelp: boolean;
|
||||||
|
private _haStyle?: DocumentFragment;
|
||||||
|
private _ironFlex?: DocumentFragment;
|
||||||
|
private _commands: Command[];
|
||||||
|
private _selectedCommandIndex: number;
|
||||||
|
private _manufacturerCodeOverride?: number;
|
||||||
|
private _issueClusterCommandServiceData?: IssueCommandServiceData;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._showHelp = false;
|
||||||
|
this._selectedCommandIndex = -1;
|
||||||
|
this._commands = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties(): PropertyDeclarations {
|
||||||
|
return {
|
||||||
|
hass: {},
|
||||||
|
isWide: {},
|
||||||
|
selectedNode: {},
|
||||||
|
selectedEntity: {},
|
||||||
|
selectedCluster: {},
|
||||||
|
_showHelp: {},
|
||||||
|
_commands: {},
|
||||||
|
_selectedCommandIndex: {},
|
||||||
|
_manufacturerCodeOverride: {},
|
||||||
|
_issueClusterCommandServiceData: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updated(changedProperties: PropertyValues): void {
|
||||||
|
if (changedProperties.has("selectedCluster")) {
|
||||||
|
this._commands = [];
|
||||||
|
this._selectedCommandIndex = -1;
|
||||||
|
this._fetchCommandsForCluster();
|
||||||
|
}
|
||||||
|
super.update(changedProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
return html`
|
||||||
|
${this.renderStyle()}
|
||||||
|
<ha-config-section .isWide="${this.isWide}">
|
||||||
|
<div class="sectionHeader" slot="header">
|
||||||
|
<span>Cluster Commands</span>
|
||||||
|
<paper-icon-button
|
||||||
|
class="toggle-help-icon"
|
||||||
|
@click="${this._onHelpTap}"
|
||||||
|
icon="hass:help-circle"
|
||||||
|
>
|
||||||
|
</paper-icon-button>
|
||||||
|
</div>
|
||||||
|
<span slot="introduction">View and issue cluster commands.</span>
|
||||||
|
|
||||||
|
<paper-card class="content">
|
||||||
|
<div class="command-picker">
|
||||||
|
<paper-dropdown-menu
|
||||||
|
label="Commands of the selected cluster"
|
||||||
|
class="flex"
|
||||||
|
>
|
||||||
|
<paper-listbox
|
||||||
|
slot="dropdown-content"
|
||||||
|
.selected="${this._selectedCommandIndex}"
|
||||||
|
@iron-select="${this._selectedCommandChanged}"
|
||||||
|
>
|
||||||
|
${
|
||||||
|
this._commands.map(
|
||||||
|
(entry) => html`
|
||||||
|
<paper-item
|
||||||
|
>${entry.name + " (id: " + entry.id + ")"}</paper-item
|
||||||
|
>
|
||||||
|
`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
${
|
||||||
|
this._showHelp
|
||||||
|
? html`
|
||||||
|
<div class="helpText">Select a command to interact with</div>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
${
|
||||||
|
this._selectedCommandIndex !== -1
|
||||||
|
? html`
|
||||||
|
<div class="input-text">
|
||||||
|
<paper-input
|
||||||
|
label="Manufacturer code override"
|
||||||
|
type="number"
|
||||||
|
.value="${this._manufacturerCodeOverride}"
|
||||||
|
@value-changed="${
|
||||||
|
this._onManufacturerCodeOverrideChanged
|
||||||
|
}"
|
||||||
|
placeholder="Value"
|
||||||
|
></paper-input>
|
||||||
|
</div>
|
||||||
|
<div class="card-actions">
|
||||||
|
<ha-call-service-button
|
||||||
|
.hass="${this.hass}"
|
||||||
|
domain="zha"
|
||||||
|
service="issue_zigbee_cluster_command"
|
||||||
|
.serviceData="${this._issueClusterCommandServiceData}"
|
||||||
|
>Issue Zigbee Command</ha-call-service-button
|
||||||
|
>
|
||||||
|
${
|
||||||
|
this._showHelp
|
||||||
|
? html`
|
||||||
|
<ha-service-description
|
||||||
|
.hass="${this.hass}"
|
||||||
|
domain="zha"
|
||||||
|
service="issue_zigbee_cluster_command"
|
||||||
|
></ha-service-description>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
</paper-card>
|
||||||
|
</ha-config-section>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _fetchCommandsForCluster(): Promise<void> {
|
||||||
|
if (this.selectedEntity && this.selectedCluster && this.hass) {
|
||||||
|
this._commands = await fetchCommandsForCluster(
|
||||||
|
this.hass,
|
||||||
|
this.selectedEntity!.entity_id,
|
||||||
|
this.selectedEntity!.device_info!.identifiers[0][1],
|
||||||
|
this.selectedCluster!.id,
|
||||||
|
this.selectedCluster!.type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeIssueClusterCommandServiceData():
|
||||||
|
| IssueCommandServiceData
|
||||||
|
| undefined {
|
||||||
|
if (!this.selectedEntity || !this.selectedCluster) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
entity_id: this.selectedEntity!.entity_id,
|
||||||
|
cluster_id: this.selectedCluster!.id,
|
||||||
|
cluster_type: this.selectedCluster!.type,
|
||||||
|
command: this._commands[this._selectedCommandIndex].id,
|
||||||
|
command_type: this._commands[this._selectedCommandIndex].type,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onManufacturerCodeOverrideChanged(value: ChangeEvent): void {
|
||||||
|
this._manufacturerCodeOverride = value.detail!.value;
|
||||||
|
this._issueClusterCommandServiceData = this._computeIssueClusterCommandServiceData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onHelpTap(): void {
|
||||||
|
this._showHelp = !this._showHelp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _selectedCommandChanged(event: ItemSelectedEvent): void {
|
||||||
|
this._selectedCommandIndex = event.target!.selected;
|
||||||
|
this._issueClusterCommandServiceData = this._computeIssueClusterCommandServiceData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderStyle(): TemplateResult {
|
||||||
|
if (!this._haStyle) {
|
||||||
|
this._haStyle = document.importNode(
|
||||||
|
(document.getElementById("ha-style")!
|
||||||
|
.children[0] as HTMLTemplateElement).content,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!this._ironFlex) {
|
||||||
|
this._ironFlex = document.importNode(
|
||||||
|
(document.getElementById("iron-flex")!
|
||||||
|
.children[0] as HTMLTemplateElement).content,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return html`
|
||||||
|
${this._ironFlex} ${this._haStyle}
|
||||||
|
<style>
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-actions.warning ha-call-service-button {
|
||||||
|
color: var(--google-red-500);
|
||||||
|
}
|
||||||
|
|
||||||
|
.command-picker {
|
||||||
|
@apply --layout-horizontal;
|
||||||
|
@apply --layout-center-center;
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-text {
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionHeader {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helpText {
|
||||||
|
color: grey;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-help-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
right: 0;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-service-description {
|
||||||
|
display: block;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"zha-cluster-commands": ZHAClusterCommands;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("zha-cluster-commands", ZHAClusterCommands);
|
165
src/panels/config/zha/zha-clusters.ts
Normal file
165
src/panels/config/zha/zha-clusters.ts
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||||
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
PropertyValues,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../components/ha-service-description";
|
||||||
|
import {
|
||||||
|
Cluster,
|
||||||
|
fetchClustersForZhaNode,
|
||||||
|
ZHADeviceEntity,
|
||||||
|
} from "../../../data/zha";
|
||||||
|
import "../../../resources/ha-style";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import "../ha-config-section";
|
||||||
|
import { ItemSelectedEvent } from "./types";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// for fire event
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"zha-cluster-selected": {
|
||||||
|
cluster?: Cluster;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const computeClusterKey = (cluster: Cluster): string => {
|
||||||
|
return `${cluster.name} (id: ${cluster.id}, type: ${cluster.type})`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class ZHAClusters extends LitElement {
|
||||||
|
public hass?: HomeAssistant;
|
||||||
|
public isWide?: boolean;
|
||||||
|
public showHelp: boolean;
|
||||||
|
public selectedEntity?: ZHADeviceEntity;
|
||||||
|
private _selectedClusterIndex: number;
|
||||||
|
private _clusters: Cluster[];
|
||||||
|
private _haStyle?: DocumentFragment;
|
||||||
|
private _ironFlex?: DocumentFragment;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.showHelp = false;
|
||||||
|
this._selectedClusterIndex = -1;
|
||||||
|
this._clusters = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties(): PropertyDeclarations {
|
||||||
|
return {
|
||||||
|
hass: {},
|
||||||
|
isWide: {},
|
||||||
|
showHelp: {},
|
||||||
|
selectedEntity: {},
|
||||||
|
_selectedClusterIndex: {},
|
||||||
|
_clusters: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updated(changedProperties: PropertyValues): void {
|
||||||
|
if (changedProperties.has("selectedEntity")) {
|
||||||
|
this._clusters = [];
|
||||||
|
this._selectedClusterIndex = -1;
|
||||||
|
fireEvent(this, "zha-cluster-selected", {
|
||||||
|
cluster: undefined,
|
||||||
|
});
|
||||||
|
this._fetchClustersForZhaNode();
|
||||||
|
}
|
||||||
|
super.update(changedProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
return html`
|
||||||
|
${this._renderStyle()}
|
||||||
|
<div class="node-picker">
|
||||||
|
<paper-dropdown-menu label="Clusters" class="flex">
|
||||||
|
<paper-listbox
|
||||||
|
slot="dropdown-content"
|
||||||
|
.selected="${this._selectedClusterIndex}"
|
||||||
|
@iron-select="${this._selectedClusterChanged}"
|
||||||
|
>
|
||||||
|
${
|
||||||
|
this._clusters.map(
|
||||||
|
(entry) => html`
|
||||||
|
<paper-item>${computeClusterKey(entry)}</paper-item>
|
||||||
|
`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
${
|
||||||
|
this.showHelp
|
||||||
|
? html`
|
||||||
|
<div class="helpText">
|
||||||
|
Select cluster to view attributes and commands
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _fetchClustersForZhaNode(): Promise<void> {
|
||||||
|
if (this.hass) {
|
||||||
|
this._clusters = await fetchClustersForZhaNode(
|
||||||
|
this.hass,
|
||||||
|
this.selectedEntity!.entity_id,
|
||||||
|
this.selectedEntity!.device_info!.identifiers[0][1]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _selectedClusterChanged(event: ItemSelectedEvent): void {
|
||||||
|
this._selectedClusterIndex = event.target!.selected;
|
||||||
|
fireEvent(this, "zha-cluster-selected", {
|
||||||
|
cluster: this._clusters[this._selectedClusterIndex],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderStyle(): TemplateResult {
|
||||||
|
if (!this._haStyle) {
|
||||||
|
this._haStyle = document.importNode(
|
||||||
|
(document.getElementById("ha-style")!
|
||||||
|
.children[0] as HTMLTemplateElement).content,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!this._ironFlex) {
|
||||||
|
this._ironFlex = document.importNode(
|
||||||
|
(document.getElementById("iron-flex")!
|
||||||
|
.children[0] as HTMLTemplateElement).content,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return html`
|
||||||
|
${this._ironFlex} ${this._haStyle}
|
||||||
|
<style>
|
||||||
|
.node-picker {
|
||||||
|
@apply --layout-horizontal;
|
||||||
|
@apply --layout-center-center;
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
.helpText {
|
||||||
|
color: grey;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"zha-cluster": ZHAClusters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("zha-clusters", ZHAClusters);
|
177
src/panels/config/zha/zha-entities.ts
Normal file
177
src/panels/config/zha/zha-entities.ts
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||||
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
PropertyValues,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@polymer/paper-button/paper-button";
|
||||||
|
import "@polymer/paper-item/paper-item";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { fetchEntitiesForZhaNode } from "../../../data/zha";
|
||||||
|
import "../../../resources/ha-style";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { ItemSelectedEvent } from "./types";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// for fire event
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"zha-entity-selected": {
|
||||||
|
entity?: HassEntity;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ZHAEntities extends LitElement {
|
||||||
|
public hass?: HomeAssistant;
|
||||||
|
public showHelp?: boolean;
|
||||||
|
public selectedNode?: HassEntity;
|
||||||
|
private _selectedEntityIndex: number;
|
||||||
|
private _entities: HassEntity[];
|
||||||
|
private _haStyle?: DocumentFragment;
|
||||||
|
private _ironFlex?: DocumentFragment;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._entities = [];
|
||||||
|
this._selectedEntityIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties(): PropertyDeclarations {
|
||||||
|
return {
|
||||||
|
hass: {},
|
||||||
|
showHelp: {},
|
||||||
|
selectedNode: {},
|
||||||
|
_selectedEntityIndex: {},
|
||||||
|
_entities: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updated(changedProperties: PropertyValues): void {
|
||||||
|
if (changedProperties.has("selectedNode")) {
|
||||||
|
this._entities = [];
|
||||||
|
this._selectedEntityIndex = -1;
|
||||||
|
fireEvent(this, "zha-entity-selected", {
|
||||||
|
entity: undefined,
|
||||||
|
});
|
||||||
|
this._fetchEntitiesForZhaNode();
|
||||||
|
}
|
||||||
|
super.update(changedProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
return html`
|
||||||
|
${this._renderStyle()}
|
||||||
|
<div class="node-picker">
|
||||||
|
<paper-dropdown-menu label="Entities" class="flex">
|
||||||
|
<paper-listbox
|
||||||
|
slot="dropdown-content"
|
||||||
|
.selected="${this._selectedEntityIndex}"
|
||||||
|
@iron-select="${this._selectedEntityChanged}"
|
||||||
|
>
|
||||||
|
${
|
||||||
|
this._entities.map(
|
||||||
|
(entry) => html`
|
||||||
|
<paper-item>${entry.entity_id}</paper-item>
|
||||||
|
`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
${
|
||||||
|
this.showHelp
|
||||||
|
? html`
|
||||||
|
<div class="helpText">
|
||||||
|
Select entity to view per-entity options
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
${
|
||||||
|
this._selectedEntityIndex !== -1
|
||||||
|
? html`
|
||||||
|
<div class="actions">
|
||||||
|
<paper-button @click="${this._showEntityInformation}"
|
||||||
|
>Entity Information</paper-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _fetchEntitiesForZhaNode(): Promise<void> {
|
||||||
|
if (this.hass) {
|
||||||
|
const fetchedEntities = await fetchEntitiesForZhaNode(this.hass);
|
||||||
|
this._entities = fetchedEntities[this.selectedNode!.attributes.ieee];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _selectedEntityChanged(event: ItemSelectedEvent): void {
|
||||||
|
this._selectedEntityIndex = event.target!.selected;
|
||||||
|
fireEvent(this, "zha-entity-selected", {
|
||||||
|
entity: this._entities[this._selectedEntityIndex],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _showEntityInformation(): void {
|
||||||
|
fireEvent(this, "hass-more-info", {
|
||||||
|
entityId: this._entities[this._selectedEntityIndex].entity_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderStyle(): TemplateResult {
|
||||||
|
if (!this._haStyle) {
|
||||||
|
this._haStyle = document.importNode(
|
||||||
|
(document.getElementById("ha-style")!
|
||||||
|
.children[0] as HTMLTemplateElement).content,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!this._ironFlex) {
|
||||||
|
this._ironFlex = document.importNode(
|
||||||
|
(document.getElementById("iron-flex")!
|
||||||
|
.children[0] as HTMLTemplateElement).content,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return html`
|
||||||
|
${this._ironFlex} ${this._haStyle}
|
||||||
|
<style>
|
||||||
|
.node-picker {
|
||||||
|
@apply --layout-horizontal;
|
||||||
|
@apply --layout-center-center;
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
.actions {
|
||||||
|
border-top: 1px solid #e8e8e8;
|
||||||
|
padding: 5px 16px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.actions paper-button:not([disabled]) {
|
||||||
|
color: var(--primary-color);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.helpText {
|
||||||
|
color: grey;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"zha-entities": ZHAEntities;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("zha-entities", ZHAEntities);
|
@ -1,42 +1,45 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
import "@polymer/paper-button/paper-button";
|
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
|
||||||
import "@polymer/paper-card/paper-card";
|
|
||||||
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||||
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@polymer/paper-button/paper-button";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
import "../../../components/ha-service-description";
|
import "../../../components/ha-service-description";
|
||||||
import "../ha-config-section";
|
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import "../../../resources/ha-style";
|
import "../../../resources/ha-style";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import "../ha-config-section";
|
||||||
|
|
||||||
export class ZHANetwork extends LitElement {
|
export class ZHANetwork extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
public isWide?: boolean;
|
public isWide?: boolean;
|
||||||
public showDescription: boolean;
|
private _showHelp: boolean;
|
||||||
private _haStyle?: DocumentFragment;
|
private _haStyle?: DocumentFragment;
|
||||||
private _ironFlex?: DocumentFragment;
|
private _ironFlex?: DocumentFragment;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.showDescription = false;
|
this._showHelp = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get properties(): PropertyDeclarations {
|
static get properties(): PropertyDeclarations {
|
||||||
return {
|
return {
|
||||||
hass: {},
|
hass: {},
|
||||||
isWide: {},
|
isWide: {},
|
||||||
showDescription: {},
|
_showHelp: {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
${this.renderStyle()}
|
${this.renderStyle()}
|
||||||
<ha-config-section .is-wide="${this.isWide}">
|
<ha-config-section .isWide="${this.isWide}">
|
||||||
<div style="position: relative" slot="header">
|
<div style="position: relative" slot="header">
|
||||||
<span>Zigbee Home Automation network management</span>
|
<span>Network Management</span>
|
||||||
<paper-icon-button class="toggle-help-icon" @click="${
|
<paper-icon-button class="toggle-help-icon" @click="${
|
||||||
this._onHelpTap
|
this._onHelpTap
|
||||||
}" icon="hass:help-circle"></paper-icon-button>
|
}" icon="hass:help-circle"></paper-icon-button>
|
||||||
@ -49,7 +52,7 @@ export class ZHANetwork extends LitElement {
|
|||||||
this.hass
|
this.hass
|
||||||
}" domain="zha" service="permit">Permit</ha-call-service-button>
|
}" domain="zha" service="permit">Permit</ha-call-service-button>
|
||||||
${
|
${
|
||||||
this.showDescription
|
this._showHelp
|
||||||
? html`
|
? html`
|
||||||
<ha-service-description
|
<ha-service-description
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
@ -65,7 +68,7 @@ export class ZHANetwork extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _onHelpTap(): void {
|
private _onHelpTap(): void {
|
||||||
this.showDescription = !this.showDescription;
|
this._showHelp = !this._showHelp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderStyle(): TemplateResult {
|
private renderStyle(): TemplateResult {
|
||||||
|
325
src/panels/config/zha/zha-node.ts
Normal file
325
src/panels/config/zha/zha-node.ts
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||||
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@polymer/paper-button/paper-button";
|
||||||
|
import "@polymer/paper-card/paper-card";
|
||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
import "@polymer/paper-item/paper-item";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event";
|
||||||
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
|
import sortByName from "../../../common/entity/states_sort_by_name";
|
||||||
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../components/ha-service-description";
|
||||||
|
import "../../../resources/ha-style";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import "../ha-config-section";
|
||||||
|
import {
|
||||||
|
ItemSelectedEvent,
|
||||||
|
NodeServiceData,
|
||||||
|
ZHAEntitySelectedParams,
|
||||||
|
} from "./types";
|
||||||
|
import "./zha-clusters";
|
||||||
|
import "./zha-entities";
|
||||||
|
import { reconfigureNode } from "../../../data/zha";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// for fire event
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"zha-node-selected": {
|
||||||
|
node?: HassEntity;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ZHANode extends LitElement {
|
||||||
|
public hass?: HomeAssistant;
|
||||||
|
public isWide?: boolean;
|
||||||
|
private _showHelp: boolean;
|
||||||
|
private _selectedNodeIndex: number;
|
||||||
|
private _selectedNode?: HassEntity;
|
||||||
|
private _selectedEntity?: HassEntity;
|
||||||
|
private _serviceData?: {};
|
||||||
|
private _haStyle?: DocumentFragment;
|
||||||
|
private _ironFlex?: DocumentFragment;
|
||||||
|
private _nodes: HassEntity[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._showHelp = false;
|
||||||
|
this._selectedNodeIndex = -1;
|
||||||
|
this._nodes = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties(): PropertyDeclarations {
|
||||||
|
return {
|
||||||
|
hass: {},
|
||||||
|
isWide: {},
|
||||||
|
_showHelp: {},
|
||||||
|
_selectedNodeIndex: {},
|
||||||
|
_selectedNode: {},
|
||||||
|
_serviceData: {},
|
||||||
|
_selectedEntity: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
this._nodes = this._computeNodes(this.hass);
|
||||||
|
return html`
|
||||||
|
${this.renderStyle()}
|
||||||
|
<ha-config-section .isWide="${this.isWide}">
|
||||||
|
<div class="sectionHeader" slot="header">
|
||||||
|
<span>Node Management</span>
|
||||||
|
<paper-icon-button
|
||||||
|
class="toggle-help-icon"
|
||||||
|
@click="${this._onHelpTap}"
|
||||||
|
icon="hass:help-circle"
|
||||||
|
></paper-icon-button>
|
||||||
|
</div>
|
||||||
|
<span slot="introduction">
|
||||||
|
Run ZHA commands that affect a single node. Pick a node to see a list
|
||||||
|
of available commands. <br /><br />Note: Sleepy (battery powered)
|
||||||
|
devices need to be awake when executing commands against them. You can
|
||||||
|
generally wake a sleepy device by triggering it. <br /><br />Some
|
||||||
|
devices such as Xiaomi sensors have a wake up button that you can
|
||||||
|
press at ~5 second intervals that keep devices awake while you
|
||||||
|
interact with them.
|
||||||
|
</span>
|
||||||
|
<paper-card class="content">
|
||||||
|
<div class="node-picker">
|
||||||
|
<paper-dropdown-menu label="Nodes" class="flex">
|
||||||
|
<paper-listbox
|
||||||
|
slot="dropdown-content"
|
||||||
|
@iron-select="${this._selectedNodeChanged}"
|
||||||
|
>
|
||||||
|
${
|
||||||
|
this._nodes.map(
|
||||||
|
(entry) => html`
|
||||||
|
<paper-item
|
||||||
|
>${this._computeSelectCaption(entry)}</paper-item
|
||||||
|
>
|
||||||
|
`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
${
|
||||||
|
this._showHelp
|
||||||
|
? html`
|
||||||
|
<div class="helpText">
|
||||||
|
Select node to view per-node options
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
${this._selectedNodeIndex !== -1 ? this._renderNodeActions() : ""}
|
||||||
|
${this._selectedNodeIndex !== -1 ? this._renderEntities() : ""}
|
||||||
|
${this._selectedEntity ? this._renderClusters() : ""}
|
||||||
|
</paper-card>
|
||||||
|
</ha-config-section>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderNodeActions(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="card-actions">
|
||||||
|
<paper-button @click="${this._showNodeInformation}"
|
||||||
|
>Node Information</paper-button
|
||||||
|
>
|
||||||
|
<paper-button @click="${this._onReconfigureNodeClick}"
|
||||||
|
>Reconfigure Node</paper-button
|
||||||
|
>
|
||||||
|
${
|
||||||
|
this._showHelp
|
||||||
|
? html`
|
||||||
|
<ha-service-description
|
||||||
|
.hass="${this.hass}"
|
||||||
|
domain="zha"
|
||||||
|
service="reconfigure_device"
|
||||||
|
/>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
<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"
|
||||||
|
/>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderEntities(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<zha-entities
|
||||||
|
.hass="${this.hass}"
|
||||||
|
.selectedNode="${this._selectedNode}"
|
||||||
|
.showHelp="${this._showHelp}"
|
||||||
|
@zha-entity-selected="${this._onEntitySelected}"
|
||||||
|
></zha-entities>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderClusters(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<zha-clusters
|
||||||
|
.hass="${this.hass}"
|
||||||
|
.selectedEntity="${this._selectedEntity}"
|
||||||
|
.showHelp="${this._showHelp}"
|
||||||
|
></zha-clusters>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onHelpTap(): void {
|
||||||
|
this._showHelp = !this._showHelp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _selectedNodeChanged(event: ItemSelectedEvent): void {
|
||||||
|
this._selectedNodeIndex = event!.target!.selected;
|
||||||
|
this._selectedNode = this._nodes[this._selectedNodeIndex];
|
||||||
|
this._selectedEntity = undefined;
|
||||||
|
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!.attributes.ieee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _showNodeInformation(): void {
|
||||||
|
fireEvent(this, "hass-more-info", {
|
||||||
|
entityId: this._selectedNode!.entity_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeNodeServiceData(): NodeServiceData {
|
||||||
|
return {
|
||||||
|
ieee_address: this._selectedNode!.attributes.ieee,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeSelectCaption(stateObj: HassEntity): string {
|
||||||
|
return (
|
||||||
|
computeStateName(stateObj) + " (Node:" + stateObj.attributes.ieee + ")"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeNodes(hass?: HomeAssistant): HassEntity[] {
|
||||||
|
if (hass) {
|
||||||
|
return Object.keys(hass.states)
|
||||||
|
.map((key) => hass.states[key])
|
||||||
|
.filter((ent) => ent.entity_id.match("zha[.]"))
|
||||||
|
.sort(sortByName);
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onEntitySelected(
|
||||||
|
entitySelectedEvent: HASSDomEvent<ZHAEntitySelectedParams>
|
||||||
|
): void {
|
||||||
|
this._selectedEntity = entitySelectedEvent.detail.entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderStyle(): TemplateResult {
|
||||||
|
if (!this._haStyle) {
|
||||||
|
this._haStyle = document.importNode(
|
||||||
|
(document.getElementById("ha-style")!
|
||||||
|
.children[0] as HTMLTemplateElement).content,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!this._ironFlex) {
|
||||||
|
this._ironFlex = document.importNode(
|
||||||
|
(document.getElementById("iron-flex")!
|
||||||
|
.children[0] as HTMLTemplateElement).content,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return html`
|
||||||
|
${this._ironFlex} ${this._haStyle}
|
||||||
|
<style>
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-info {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionHeader {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-text {
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helpText {
|
||||||
|
color: grey;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-picker {
|
||||||
|
@apply --layout-horizontal;
|
||||||
|
@apply --layout-center-center;
|
||||||
|
padding-left: 28px;
|
||||||
|
padding-right: 28px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-service-description {
|
||||||
|
display: block;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-help-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
right: 0;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"zha-node": ZHANode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("zha-node", ZHANode);
|
@ -20,7 +20,7 @@ import formatTime from "../../common/datetime/format_time";
|
|||||||
import EventsMixin from "../../mixins/events-mixin";
|
import EventsMixin from "../../mixins/events-mixin";
|
||||||
import LocalizeMixin from "../../mixins/localize-mixin";
|
import LocalizeMixin from "../../mixins/localize-mixin";
|
||||||
|
|
||||||
const OPT_IN_PANEL = "lovelace";
|
const OPT_IN_PANEL = "states";
|
||||||
let registeredDialog = false;
|
let registeredDialog = false;
|
||||||
|
|
||||||
class HaPanelDevInfo extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
class HaPanelDevInfo extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||||
@ -167,7 +167,7 @@ class HaPanelDevInfo extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
|||||||
</template>
|
</template>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a href='/lovelace'>Try out the new Lovelace UI</a>
|
<a href="[[_nonDefaultLink()]]">[[_nonDefaultLinkText()]]</a>
|
||||||
<div id="love" style="cursor:pointer;" on-click="_toggleDefaultPage">[[_defaultPageText()]]</div
|
<div id="love" style="cursor:pointer;" on-click="_toggleDefaultPage">[[_defaultPageText()]]</div
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -366,6 +366,26 @@ class HaPanelDevInfo extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_nonDefaultLink() {
|
||||||
|
if (
|
||||||
|
localStorage.defaultPage === OPT_IN_PANEL &&
|
||||||
|
OPT_IN_PANEL === "states"
|
||||||
|
) {
|
||||||
|
return "/lovelace";
|
||||||
|
}
|
||||||
|
return "/states";
|
||||||
|
}
|
||||||
|
|
||||||
|
_nonDefaultLinkText() {
|
||||||
|
if (
|
||||||
|
localStorage.defaultPage === OPT_IN_PANEL &&
|
||||||
|
OPT_IN_PANEL === "states"
|
||||||
|
) {
|
||||||
|
return "Go to the Lovelace UI";
|
||||||
|
}
|
||||||
|
return "Go to the states UI";
|
||||||
|
}
|
||||||
|
|
||||||
_defaultPageText() {
|
_defaultPageText() {
|
||||||
return `>> ${
|
return `>> ${
|
||||||
localStorage.defaultPage === OPT_IN_PANEL ? "Remove" : "Set"
|
localStorage.defaultPage === OPT_IN_PANEL ? "Remove" : "Set"
|
||||||
|
@ -3,14 +3,17 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult } from "lit-html";
|
} from "lit-element";
|
||||||
import { classMap } from "lit-html/directives/classMap";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||||
import { callAlarmAction } from "../../../data/alarm_control_panel";
|
import {
|
||||||
|
callAlarmAction,
|
||||||
|
FORMAT_NUMBER,
|
||||||
|
} from "../../../data/alarm_control_panel";
|
||||||
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
||||||
|
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
@ -97,7 +100,7 @@ class HuiAlarmPanelCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
@ -150,7 +153,7 @@ class HuiAlarmPanelCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
`
|
`
|
||||||
}
|
}
|
||||||
${
|
${
|
||||||
stateObj.attributes.code_format !== "Number"
|
stateObj.attributes.code_format !== FORMAT_NUMBER
|
||||||
? html``
|
? html``
|
||||||
: html`
|
: html`
|
||||||
<div id="keypad">
|
<div id="keypad">
|
||||||
@ -206,7 +209,7 @@ class HuiAlarmPanelCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
private _handleActionClick(e: MouseEvent): void {
|
private _handleActionClick(e: MouseEvent): void {
|
||||||
callAlarmAction(
|
callAlarmAction(
|
||||||
this.hass!,
|
this.hass!,
|
||||||
this._config!.entity_id,
|
this._config!.entity,
|
||||||
(e.currentTarget! as any).action,
|
(e.currentTarget! as any).action,
|
||||||
this._code!
|
this._code!
|
||||||
);
|
);
|
||||||
|
@ -3,8 +3,8 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult } from "lit-html";
|
} from "lit-element";
|
||||||
|
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../components/hui-entities-toggle";
|
import "../components/hui-entities-toggle";
|
||||||
@ -21,7 +21,7 @@ import { createRowElement } from "../common/create-row-element";
|
|||||||
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 ConfigEntity extends EntityConfig {
|
export interface EntitiesCardEntityConfig extends EntityConfig {
|
||||||
type?: string;
|
type?: string;
|
||||||
secondary_info?: "entity-id" | "last-changed";
|
secondary_info?: "entity-id" | "last-changed";
|
||||||
action_name?: string;
|
action_name?: string;
|
||||||
@ -30,10 +30,10 @@ export interface ConfigEntity extends EntityConfig {
|
|||||||
url?: string;
|
url?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Config extends LovelaceCardConfig {
|
export interface EntitiesCardConfig extends LovelaceCardConfig {
|
||||||
show_header_toggle?: boolean;
|
show_header_toggle?: boolean;
|
||||||
title?: string;
|
title?: string;
|
||||||
entities: ConfigEntity[];
|
entities: EntitiesCardEntityConfig[];
|
||||||
theme?: string;
|
theme?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,8 +49,8 @@ class HuiEntitiesCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected _hass?: HomeAssistant;
|
protected _hass?: HomeAssistant;
|
||||||
protected _config?: Config;
|
protected _config?: EntitiesCardConfig;
|
||||||
protected _configEntities?: ConfigEntity[];
|
protected _configEntities?: EntitiesCardEntityConfig[];
|
||||||
|
|
||||||
set hass(hass: HomeAssistant) {
|
set hass(hass: HomeAssistant) {
|
||||||
this._hass = hass;
|
this._hass = hass;
|
||||||
@ -81,7 +81,7 @@ class HuiEntitiesCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
return (this._config.title ? 1 : 0) + this._config.entities.length;
|
return (this._config.title ? 1 : 0) + this._config.entities.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: EntitiesCardConfig): void {
|
||||||
const entities = processConfigEntities(config.entities);
|
const entities = processConfigEntities(config.entities);
|
||||||
|
|
||||||
this._config = { theme: "default", ...config };
|
this._config = { theme: "default", ...config };
|
||||||
@ -95,7 +95,7 @@ class HuiEntitiesCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this._hass) {
|
if (!this._config || !this._hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
@ -171,7 +171,7 @@ class HuiEntitiesCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderEntity(entityConf: ConfigEntity): TemplateResult {
|
private renderEntity(entityConf: EntitiesCardEntityConfig): TemplateResult {
|
||||||
const element = createRowElement(entityConf);
|
const element = createRowElement(entityConf);
|
||||||
if (this._hass) {
|
if (this._hass) {
|
||||||
element.hass = this._hass;
|
element.hass = this._hass;
|
||||||
@ -189,7 +189,7 @@ class HuiEntitiesCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleClick(entityConf: ConfigEntity): void {
|
private _handleClick(entityConf: EntitiesCardEntityConfig): void {
|
||||||
const entityId = entityConf.entity;
|
const entityId = entityConf.entity;
|
||||||
fireEvent(this, "hass-more-info", { entityId });
|
fireEvent(this, "hass-more-info", { entityId });
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { TemplateResult } from "lit-html";
|
import { styleMap } from "lit-html/directives/style-map";
|
||||||
import { styleMap } from "lit-html/directives/styleMap";
|
|
||||||
|
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ class HuiEntityButtonCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { html, LitElement } from "@polymer/lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
|
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
interface Config extends LovelaceCardConfig {
|
interface Config extends LovelaceCardConfig {
|
||||||
@ -40,7 +39,7 @@ export class HuiErrorCard extends LitElement implements LovelaceCard {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult } from "lit-html";
|
} from "lit-element";
|
||||||
import { styleMap } from "lit-html/directives/styleMap";
|
import { styleMap } from "lit-html/directives/style-map";
|
||||||
|
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||||
@ -56,6 +56,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
private _config?: Config;
|
private _config?: Config;
|
||||||
|
private _updated?: boolean;
|
||||||
|
|
||||||
static get properties(): PropertyDeclarations {
|
static get properties(): PropertyDeclarations {
|
||||||
return {
|
return {
|
||||||
@ -78,7 +79,12 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
|||||||
this._config = { min: 0, max: 100, theme: "default", ...config };
|
this._config = { min: 0, max: 100, theme: "default", ...config };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
public connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
this._setBaseUnit();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
@ -148,12 +154,8 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(): void {
|
protected firstUpdated(): void {
|
||||||
(this.shadowRoot!.querySelector(
|
this._updated = true;
|
||||||
"ha-card"
|
this._setBaseUnit();
|
||||||
)! as HTMLElement).style.setProperty(
|
|
||||||
"--base-unit",
|
|
||||||
this._computeBaseUnit()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues): void {
|
protected updated(changedProps: PropertyValues): void {
|
||||||
@ -169,6 +171,19 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _setBaseUnit(): void {
|
||||||
|
if (!this.isConnected || !this._updated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const baseUnit = this._computeBaseUnit();
|
||||||
|
if (baseUnit === "0px") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(this.shadowRoot!.querySelector(
|
||||||
|
"ha-card"
|
||||||
|
)! as HTMLElement).style.setProperty("--base-unit", baseUnit);
|
||||||
|
}
|
||||||
|
|
||||||
private _computeSeverity(numberValue: number): string {
|
private _computeSeverity(numberValue: number): string {
|
||||||
const sections = this._config!.severity;
|
const sections = this._config!.severity;
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult } from "lit-html";
|
} from "lit-element";
|
||||||
import { classMap } from "lit-html/directives/classMap";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
@ -114,7 +114,7 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { html } from "@polymer/lit-element";
|
import { html, TemplateResult } from "lit-element";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
|
|
||||||
import { computeCardSize } from "../common/compute-card-size";
|
import { computeCardSize } from "../common/compute-card-size";
|
||||||
import { HuiStackCard } from "./hui-stack-card";
|
import { HuiStackCard } from "./hui-stack-card";
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||||
import { TemplateResult } from "lit-html";
|
import { styleMap } from "lit-html/directives/style-map";
|
||||||
import { styleMap } from "lit-html/directives/styleMap";
|
|
||||||
|
|
||||||
export interface Config extends LovelaceCardConfig {
|
export interface Config extends LovelaceCardConfig {
|
||||||
aspect_ratio?: string;
|
aspect_ratio?: string;
|
||||||
@ -31,7 +35,13 @@ export class HuiIframeCard extends LitElement implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
return 1 + this.offsetHeight / 50;
|
if (!this._config) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
const aspectRatio = this._config.aspect_ratio
|
||||||
|
? Number(this._config.aspect_ratio.replace("%", ""))
|
||||||
|
: 50;
|
||||||
|
return 1 + aspectRatio / 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: Config): void {
|
||||||
@ -42,7 +52,7 @@ export class HuiIframeCard extends LitElement implements LovelaceCard {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
@ -75,7 +85,6 @@ export class HuiIframeCard extends LitElement implements LovelaceCard {
|
|||||||
#root {
|
#root {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-top: ${this._config!.aspect_ratio || "50%"};
|
|
||||||
}
|
}
|
||||||
iframe {
|
iframe {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -3,11 +3,11 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult } from "lit-html";
|
} from "lit-element";
|
||||||
|
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { styleMap } from "lit-html/directives/styleMap";
|
import { styleMap } from "lit-html/directives/style-map";
|
||||||
import { HomeAssistant, LightEntity } from "../../../types";
|
import { HomeAssistant, LightEntity } from "../../../types";
|
||||||
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
@ -82,7 +82,7 @@ export class HuiLightCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
this._config = { theme: "default", ...config };
|
this._config = { theme: "default", ...config };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass || !this._config) {
|
if (!this.hass || !this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,10 @@ class HuiMapCard extends PolymerElement {
|
|||||||
const stateObj = this.hass.states[entityId];
|
const stateObj = this.hass.states[entityId];
|
||||||
if (
|
if (
|
||||||
computeStateDomain(stateObj) === "geo_location" &&
|
computeStateDomain(stateObj) === "geo_location" &&
|
||||||
this._configGeoLocationSources.includes(stateObj.attributes.source)
|
(this._configGeoLocationSources.includes(
|
||||||
|
stateObj.attributes.source
|
||||||
|
) ||
|
||||||
|
this._configGeoLocationSources.includes("all"))
|
||||||
) {
|
) {
|
||||||
allEntities.push(entityId);
|
allEntities.push(entityId);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { classMap } from "lit-html/directives/classMap";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
import "../../../components/ha-card";
|
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 { LovelaceCardConfig } from "../../../data/lovelace";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
|
|
||||||
export interface Config extends LovelaceCardConfig {
|
export interface Config extends LovelaceCardConfig {
|
||||||
content: string;
|
content: string;
|
||||||
@ -42,7 +46,7 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
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 { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { TemplateResult } from "lit-html";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
import { classMap } from "lit-html/directives/classMap";
|
|
||||||
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";
|
||||||
|
|
||||||
@ -49,7 +53,7 @@ export class HuiPictureCard extends LitElement implements LovelaceCard {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { html, LitElement } from "@polymer/lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
|
|
||||||
import { createHuiElement } from "../common/create-hui-element";
|
import { createHuiElement } from "../common/create-hui-element";
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ class HuiPictureElementsCard extends LitElement implements LovelaceCard {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html/lib/shady-render";
|
html,
|
||||||
import { classMap } from "lit-html/directives/classMap";
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../components/hui-image";
|
import "../components/hui-image";
|
||||||
@ -65,7 +69,7 @@ class HuiPictureEntityCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
this._config = { show_name: true, show_state: true, ...config };
|
this._config = { show_name: true, show_state: true, ...config };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { classMap } from "lit-html/directives/classMap";
|
html,
|
||||||
import { TemplateResult } from "lit-html";
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
||||||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||||
@ -83,7 +87,7 @@ class HuiPictureGlanceCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult } from "lit-html";
|
} from "lit-element";
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
@ -192,7 +192,7 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { html, LitElement } from "@polymer/lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
import { repeat } from "lit-html/directives/repeat";
|
import { repeat } from "lit-html/directives/repeat";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||||
import "@polymer/paper-checkbox/paper-checkbox";
|
import "@polymer/paper-checkbox/paper-checkbox";
|
||||||
|
|
||||||
@ -79,7 +78,7 @@ class HuiShoppingListCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { html, LitElement } from "@polymer/lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
|
|
||||||
import { createCardElement } from "../common/create-card-element";
|
import { createCardElement } from "../common/create-card-element";
|
||||||
|
|
||||||
@ -12,10 +11,6 @@ interface Config extends LovelaceCardConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export abstract class HuiStackCard extends LitElement implements LovelaceCard {
|
export abstract class HuiStackCard extends LitElement implements LovelaceCard {
|
||||||
protected _cards?: LovelaceCard[];
|
|
||||||
private _config?: Config;
|
|
||||||
private _hass?: HomeAssistant;
|
|
||||||
|
|
||||||
static get properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
_config: {},
|
_config: {},
|
||||||
@ -33,6 +28,9 @@ export abstract class HuiStackCard extends LitElement implements LovelaceCard {
|
|||||||
element.hass = this._hass;
|
element.hass = this._hass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
protected _cards?: LovelaceCard[];
|
||||||
|
private _config?: Config;
|
||||||
|
private _hass?: HomeAssistant;
|
||||||
|
|
||||||
public abstract getCardSize(): number;
|
public abstract getCardSize(): number;
|
||||||
|
|
||||||
@ -42,15 +40,12 @@ export abstract class HuiStackCard extends LitElement implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
this._config = config;
|
this._config = config;
|
||||||
this._cards = config.cards.map((card) => {
|
this._cards = config.cards.map((card) => {
|
||||||
const element = createCardElement(card) as LovelaceCard;
|
const element = this._createCardElement(card) as LovelaceCard;
|
||||||
if (this._hass) {
|
|
||||||
element.hass = this._hass;
|
|
||||||
}
|
|
||||||
return element;
|
return element;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
@ -62,4 +57,31 @@ export abstract class HuiStackCard extends LitElement implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected abstract renderStyle(): TemplateResult;
|
protected abstract renderStyle(): TemplateResult;
|
||||||
|
|
||||||
|
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
||||||
|
const element = createCardElement(cardConfig) as LovelaceCard;
|
||||||
|
if (this._hass) {
|
||||||
|
element.hass = this._hass;
|
||||||
|
}
|
||||||
|
element.addEventListener(
|
||||||
|
"ll-rebuild",
|
||||||
|
(ev) => {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this._rebuildCard(element, cardConfig);
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _rebuildCard(
|
||||||
|
cardElToReplace: LovelaceCard,
|
||||||
|
config: LovelaceCardConfig
|
||||||
|
): void {
|
||||||
|
const newCardEl = this._createCardElement(config);
|
||||||
|
cardElToReplace.parentElement!.replaceChild(newCardEl, cardElToReplace);
|
||||||
|
this._cards = this._cards!.map((curCardEl) =>
|
||||||
|
curCardEl === cardElToReplace ? newCardEl : curCardEl
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { classMap } from "lit-html/directives/classMap";
|
} from "lit-element";
|
||||||
import { TemplateResult } from "lit-html";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../../../components/ha-icon";
|
import "../../../components/ha-icon";
|
||||||
@ -51,18 +51,6 @@ export interface Config extends LovelaceCardConfig {
|
|||||||
name?: string;
|
name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatTemp(temps: string[]): string {
|
|
||||||
return temps.filter(Boolean).join("-");
|
|
||||||
}
|
|
||||||
|
|
||||||
function computeTemperatureStepSize(hass: HomeAssistant, config: Config) {
|
|
||||||
const stateObj = hass.states[config.entity];
|
|
||||||
if (stateObj.attributes.target_temp_step) {
|
|
||||||
return stateObj.attributes.target_temp_step;
|
|
||||||
}
|
|
||||||
return hass.config.unit_system.temperature === UNIT_F ? 1 : 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
||||||
implements LovelaceCard {
|
implements LovelaceCard {
|
||||||
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
||||||
@ -79,6 +67,8 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
private _roundSliderStyle?: TemplateResult;
|
private _roundSliderStyle?: TemplateResult;
|
||||||
private _jQuery?: any;
|
private _jQuery?: any;
|
||||||
private _broadCard?: boolean;
|
private _broadCard?: boolean;
|
||||||
|
private _loaded?: boolean;
|
||||||
|
private _updated?: boolean;
|
||||||
|
|
||||||
static get properties(): PropertyDeclarations {
|
static get properties(): PropertyDeclarations {
|
||||||
return {
|
return {
|
||||||
@ -101,7 +91,14 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
this._config = { theme: "default", ...config };
|
this._config = { theme: "default", ...config };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
public connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
if (this._updated && !this._loaded) {
|
||||||
|
this._initialLoad();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass || !this._config) {
|
if (!this.hass || !this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
@ -157,7 +154,10 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(): void {
|
protected firstUpdated(): void {
|
||||||
this._initialLoad();
|
this._updated = true;
|
||||||
|
if (this.isConnected && !this._loaded) {
|
||||||
|
this._initialLoad();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues): void {
|
protected updated(changedProps: PropertyValues): void {
|
||||||
@ -189,13 +189,23 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get _stepSize(): number {
|
||||||
|
const stateObj = this.hass!.states[this._config!.entity];
|
||||||
|
if (stateObj.attributes.target_temp_step) {
|
||||||
|
return stateObj.attributes.target_temp_step;
|
||||||
|
}
|
||||||
|
return this.hass!.config.unit_system.temperature === UNIT_F ? 1 : 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
private async _initialLoad(): Promise<void> {
|
private async _initialLoad(): Promise<void> {
|
||||||
const radius = this.clientWidth / 3;
|
this._loaded = true;
|
||||||
|
|
||||||
|
const radius = this.clientWidth / 3.2;
|
||||||
this._broadCard = this.clientWidth > 390;
|
this._broadCard = this.clientWidth > 390;
|
||||||
|
|
||||||
(this.shadowRoot!.querySelector(
|
(this.shadowRoot!.querySelector(
|
||||||
"#thermostat"
|
"#thermostat"
|
||||||
)! as HTMLElement).style.minHeight = radius * 2 + "px";
|
)! as HTMLElement).style.height = radius * 2 + "px";
|
||||||
|
|
||||||
const loaded = await loadRoundslider();
|
const loaded = await loadRoundslider();
|
||||||
await new Promise((resolve) => afterNextRender(resolve));
|
await new Promise((resolve) => afterNextRender(resolve));
|
||||||
@ -212,7 +222,6 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
: "min-range";
|
: "min-range";
|
||||||
|
|
||||||
const [sliderValue, uiValue] = this._genSliderValue(stateObj);
|
const [sliderValue, uiValue] = this._genSliderValue(stateObj);
|
||||||
const step = computeTemperatureStepSize(this.hass!, this._config!);
|
|
||||||
|
|
||||||
this._jQuery("#thermostat", this.shadowRoot).roundSlider({
|
this._jQuery("#thermostat", this.shadowRoot).roundSlider({
|
||||||
...thermostatConfig,
|
...thermostatConfig,
|
||||||
@ -220,11 +229,10 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
min: stateObj.attributes.min_temp,
|
min: stateObj.attributes.min_temp,
|
||||||
max: stateObj.attributes.max_temp,
|
max: stateObj.attributes.max_temp,
|
||||||
sliderType: _sliderType,
|
sliderType: _sliderType,
|
||||||
create: () => this._loaded(),
|
|
||||||
change: (value) => this._setTemperature(value),
|
change: (value) => this._setTemperature(value),
|
||||||
drag: (value) => this._dragEvent(value),
|
drag: (value) => this._dragEvent(value),
|
||||||
value: sliderValue,
|
value: sliderValue,
|
||||||
step,
|
step: this._stepSize,
|
||||||
});
|
});
|
||||||
this._updateSetTemp(uiValue);
|
this._updateSetTemp(uiValue);
|
||||||
}
|
}
|
||||||
@ -240,10 +248,13 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
sliderValue = `${stateObj.attributes.target_temp_low}, ${
|
sliderValue = `${stateObj.attributes.target_temp_low}, ${
|
||||||
stateObj.attributes.target_temp_high
|
stateObj.attributes.target_temp_high
|
||||||
}`;
|
}`;
|
||||||
uiValue = formatTemp([
|
uiValue = this.formatTemp(
|
||||||
String(stateObj.attributes.target_temp_low),
|
[
|
||||||
String(stateObj.attributes.target_temp_high),
|
String(stateObj.attributes.target_temp_low),
|
||||||
]);
|
String(stateObj.attributes.target_temp_high),
|
||||||
|
],
|
||||||
|
false
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
sliderValue = stateObj.attributes.temperature;
|
sliderValue = stateObj.attributes.temperature;
|
||||||
uiValue = "" + stateObj.attributes.temperature;
|
uiValue = "" + stateObj.attributes.temperature;
|
||||||
@ -252,18 +263,12 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
return [sliderValue, uiValue];
|
return [sliderValue, uiValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _loaded(): void {
|
|
||||||
(this.shadowRoot!.querySelector(
|
|
||||||
"#thermostat"
|
|
||||||
)! as HTMLElement).style.minHeight = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _updateSetTemp(value: string): void {
|
private _updateSetTemp(value: string): void {
|
||||||
this.shadowRoot!.querySelector("#set-temperature")!.innerHTML = value;
|
this.shadowRoot!.querySelector("#set-temperature")!.innerHTML = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _dragEvent(e): void {
|
private _dragEvent(e): void {
|
||||||
this._updateSetTemp(formatTemp(String(e.value).split(",")));
|
this._updateSetTemp(this.formatTemp(String(e.value).split(","), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setTemperature(e): void {
|
private _setTemperature(e): void {
|
||||||
@ -314,6 +319,21 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private formatTemp(temps: string[], spaceStepSize: boolean): string {
|
||||||
|
temps = temps.filter(Boolean);
|
||||||
|
|
||||||
|
// If we are sliding the slider, append 0 to the temperatures if we're
|
||||||
|
// having a 0.5 step size, so that the text doesn't jump while sliding
|
||||||
|
if (spaceStepSize) {
|
||||||
|
const stepSize = this._stepSize;
|
||||||
|
temps = temps.map((val) =>
|
||||||
|
val.includes(".") || stepSize === 1 ? val : `${val}.0`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return temps.join("-");
|
||||||
|
}
|
||||||
|
|
||||||
private renderStyle(): TemplateResult {
|
private renderStyle(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
${this._roundSliderStyle}
|
${this._roundSliderStyle}
|
||||||
@ -370,39 +390,37 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
--mode-color: var(--unknown-color);
|
--mode-color: var(--unknown-color);
|
||||||
}
|
}
|
||||||
.no-title {
|
.no-title {
|
||||||
--title-margin-top: 33% !important;
|
--title-position-top: 33% !important;
|
||||||
}
|
}
|
||||||
.large {
|
.large {
|
||||||
--thermostat-padding-top: 25px;
|
--thermostat-padding-top: 25px;
|
||||||
--thermostat-margin-bottom: 25px;
|
--thermostat-margin-bottom: 25px;
|
||||||
--title-font-size: 28px;
|
--title-font-size: 28px;
|
||||||
--title-margin-top: 20%;
|
--title-position-top: 27%;
|
||||||
--climate-info-margin-top: 17%;
|
--climate-info-position-top: 81%;
|
||||||
--modes-margin-top: 2%;
|
|
||||||
--set-temperature-font-size: 25px;
|
--set-temperature-font-size: 25px;
|
||||||
--current-temperature-font-size: 71px;
|
--current-temperature-font-size: 71px;
|
||||||
--current-temperature-margin-top: 10%;
|
--current-temperature-position-top: 10%;
|
||||||
--current-temperature-text-padding-left: 15px;
|
--current-temperature-text-padding-left: 15px;
|
||||||
--uom-font-size: 20px;
|
--uom-font-size: 20px;
|
||||||
--uom-margin-left: -18px;
|
--uom-margin-left: -18px;
|
||||||
--current-mode-font-size: 18px;
|
--current-mode-font-size: 18px;
|
||||||
--set-temperature-padding-bottom: 5px;
|
--set-temperature-margin-bottom: -5px;
|
||||||
}
|
}
|
||||||
.small {
|
.small {
|
||||||
--thermostat-padding-top: 15px;
|
--thermostat-padding-top: 15px;
|
||||||
--thermostat-margin-bottom: 15px;
|
--thermostat-margin-bottom: 15px;
|
||||||
--title-font-size: 18px;
|
--title-font-size: 18px;
|
||||||
--title-margin-top: 20%;
|
--title-position-top: 28%;
|
||||||
--climate-info-margin-top: 7.5%;
|
--climate-info-position-top: 79%;
|
||||||
--modes-margin-top: 1%;
|
|
||||||
--set-temperature-font-size: 16px;
|
--set-temperature-font-size: 16px;
|
||||||
--current-temperature-font-size: 25px;
|
--current-temperature-font-size: 25px;
|
||||||
--current-temperature-margin-top: 5%;
|
--current-temperature-position-top: 5%;
|
||||||
--current-temperature-text-padding-left: 7px;
|
--current-temperature-text-padding-left: 7px;
|
||||||
--uom-font-size: 12px;
|
--uom-font-size: 12px;
|
||||||
--uom-margin-left: -5px;
|
--uom-margin-left: -5px;
|
||||||
--current-mode-font-size: 14px;
|
--current-mode-font-size: 14px;
|
||||||
--set-temperature-padding-bottom: 0px;
|
--set-temperature-margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
#thermostat {
|
#thermostat {
|
||||||
margin: 0 auto var(--thermostat-margin-bottom);
|
margin: 0 auto var(--thermostat-margin-bottom);
|
||||||
@ -449,21 +467,28 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
}
|
}
|
||||||
#set-temperature {
|
#set-temperature {
|
||||||
font-size: var(--set-temperature-font-size);
|
font-size: var(--set-temperature-font-size);
|
||||||
padding-bottom: var(--set-temperature-padding-bottom);
|
margin-bottom: var(--set-temperature-margin-bottom);
|
||||||
}
|
}
|
||||||
.title {
|
.title {
|
||||||
font-size: var(--title-font-size);
|
font-size: var(--title-font-size);
|
||||||
margin-top: var(--title-margin-top);
|
position: absolute;
|
||||||
|
top: var(--title-position-top);
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
.climate-info {
|
.climate-info {
|
||||||
margin-top: var(--climate-info-margin-top);
|
position: absolute;
|
||||||
|
top: var(--climate-info-position-top);
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
.current-mode {
|
.current-mode {
|
||||||
font-size: var(--current-mode-font-size);
|
font-size: var(--current-mode-font-size);
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
}
|
}
|
||||||
.modes {
|
.modes {
|
||||||
margin-top: var(--modes-margin-top);
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
.modes ha-icon {
|
.modes ha-icon {
|
||||||
color: var(--disabled-text-color);
|
color: var(--disabled-text-color);
|
||||||
@ -475,7 +500,10 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
|||||||
color: var(--mode-color);
|
color: var(--mode-color);
|
||||||
}
|
}
|
||||||
.current-temperature {
|
.current-temperature {
|
||||||
margin-top: var(--current-temperature-margin-top);
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
font-size: var(--current-temperature-font-size);
|
font-size: var(--current-temperature-font-size);
|
||||||
}
|
}
|
||||||
.current-temperature-text {
|
.current-temperature-text {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { html } from "@polymer/lit-element";
|
import { html, TemplateResult } from "lit-element";
|
||||||
|
|
||||||
import { computeCardSize } from "../common/compute-card-size";
|
import { computeCardSize } from "../common/compute-card-size";
|
||||||
import { HuiStackCard } from "./hui-stack-card";
|
import { HuiStackCard } from "./hui-stack-card";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
|
|
||||||
class HuiVerticalStackCard extends HuiStackCard {
|
class HuiVerticalStackCard extends HuiStackCard {
|
||||||
public getCardSize() {
|
public getCardSize() {
|
||||||
|
@ -106,7 +106,7 @@ export const createCardElement = (
|
|||||||
|
|
||||||
customElements.whenDefined(tag).then(() => {
|
customElements.whenDefined(tag).then(() => {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
fireEvent(element, "rebuild-view");
|
fireEvent(element, "ll-rebuild");
|
||||||
});
|
});
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
|
@ -72,7 +72,7 @@ export const createHuiElement = (
|
|||||||
|
|
||||||
customElements.whenDefined(tag).then(() => {
|
customElements.whenDefined(tag).then(() => {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
fireEvent(element, "rebuild-view");
|
fireEvent(element, "ll-rebuild");
|
||||||
});
|
});
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
|
@ -52,6 +52,9 @@ const DOMAIN_TO_ELEMENT_TYPE = {
|
|||||||
timer: "timer",
|
timer: "timer",
|
||||||
switch: "toggle",
|
switch: "toggle",
|
||||||
vacuum: "toggle",
|
vacuum: "toggle",
|
||||||
|
// Temporary. Once climate is rewritten,
|
||||||
|
// water heater should get it's own row.
|
||||||
|
water_heater: "climate",
|
||||||
};
|
};
|
||||||
const TIMEOUT = 2000;
|
const TIMEOUT = 2000;
|
||||||
|
|
||||||
@ -115,7 +118,7 @@ export const createRowElement = (
|
|||||||
|
|
||||||
customElements.whenDefined(tag).then(() => {
|
customElements.whenDefined(tag).then(() => {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
fireEvent(element, "rebuild-view");
|
fireEvent(element, "ll-rebuild");
|
||||||
});
|
});
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { directive, PropertyPart } from "lit-html";
|
import { directive, PropertyPart } from "lit-html";
|
||||||
import "@material/mwc-ripple";
|
// See https://github.com/home-assistant/home-assistant-polymer/pull/2457
|
||||||
|
// on how to undo mwc -> paper migration
|
||||||
|
// import "@material/mwc-ripple";
|
||||||
|
import "@polymer/paper-ripple";
|
||||||
|
|
||||||
const isTouch =
|
const isTouch =
|
||||||
"ontouchstart" in window ||
|
"ontouchstart" in window ||
|
||||||
@ -25,7 +28,7 @@ class LongPress extends HTMLElement implements LongPress {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.holdTime = 500;
|
this.holdTime = 500;
|
||||||
this.ripple = document.createElement("mwc-ripple");
|
this.ripple = document.createElement("paper-ripple");
|
||||||
this.timer = undefined;
|
this.timer = undefined;
|
||||||
this.held = false;
|
this.held = false;
|
||||||
this.cooldownStart = false;
|
this.cooldownStart = false;
|
||||||
@ -34,6 +37,7 @@ class LongPress extends HTMLElement implements LongPress {
|
|||||||
|
|
||||||
public connectedCallback() {
|
public connectedCallback() {
|
||||||
Object.assign(this.style, {
|
Object.assign(this.style, {
|
||||||
|
borderRadius: "50%", // paper-ripple
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
width: isTouch ? "100px" : "50px",
|
width: isTouch ? "100px" : "50px",
|
||||||
height: isTouch ? "100px" : "50px",
|
height: isTouch ? "100px" : "50px",
|
||||||
@ -42,7 +46,9 @@ class LongPress extends HTMLElement implements LongPress {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.appendChild(this.ripple);
|
this.appendChild(this.ripple);
|
||||||
this.ripple.primary = true;
|
this.ripple.style.color = "#03a9f4"; // paper-ripple
|
||||||
|
this.ripple.style.color = "var(--primary-color)"; // paper-ripple
|
||||||
|
// this.ripple.primary = true;
|
||||||
|
|
||||||
[
|
[
|
||||||
"touchcancel",
|
"touchcancel",
|
||||||
@ -140,14 +146,17 @@ class LongPress extends HTMLElement implements LongPress {
|
|||||||
top: `${y}px`,
|
top: `${y}px`,
|
||||||
display: null,
|
display: null,
|
||||||
});
|
});
|
||||||
this.ripple.disabled = false;
|
this.ripple.holdDown = true; // paper-ripple
|
||||||
this.ripple.active = true;
|
this.ripple.simulatedRipple(); // paper-ripple
|
||||||
this.ripple.unbounded = true;
|
// this.ripple.disabled = false;
|
||||||
|
// this.ripple.active = true;
|
||||||
|
// this.ripple.unbounded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private stopAnimation() {
|
private stopAnimation() {
|
||||||
this.ripple.active = false;
|
this.ripple.holdDown = false; // paper-ripple
|
||||||
this.ripple.disabled = true;
|
// this.ripple.active = false;
|
||||||
|
// this.ripple.disabled = true;
|
||||||
this.style.display = "none";
|
this.style.display = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,7 +183,6 @@ export const longPressBind = (element: LongPressElement) => {
|
|||||||
longpress.bind(element);
|
longpress.bind(element);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const longPress = () =>
|
export const longPress = directive(() => (part: PropertyPart) => {
|
||||||
directive((part: PropertyPart) => {
|
longPressBind(part.committer.element);
|
||||||
longPressBind(part.committer.element);
|
});
|
||||||
});
|
|
||||||
|
@ -14,6 +14,7 @@ import computeStateDomain from "../../../common/entity/compute_state_domain";
|
|||||||
import { LocalizeFunc } from "../../../mixins/localize-base-mixin";
|
import { LocalizeFunc } from "../../../mixins/localize-base-mixin";
|
||||||
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";
|
||||||
|
|
||||||
const DEFAULT_VIEW_ENTITY_ID = "group.default_view";
|
const DEFAULT_VIEW_ENTITY_ID = "group.default_view";
|
||||||
const DOMAINS_BADGES = [
|
const DOMAINS_BADGES = [
|
||||||
@ -24,11 +25,15 @@ const DOMAINS_BADGES = [
|
|||||||
"sun",
|
"sun",
|
||||||
"timer",
|
"timer",
|
||||||
];
|
];
|
||||||
const HIDE_DOMAIN = new Set(["persistent_notification", "configurator"]);
|
const HIDE_DOMAIN = new Set([
|
||||||
|
"persistent_notification",
|
||||||
|
"configurator",
|
||||||
|
"geo_location",
|
||||||
|
]);
|
||||||
|
|
||||||
const computeCards = (
|
const computeCards = (
|
||||||
title: string,
|
states: Array<[string, HassEntity]>,
|
||||||
states: Array<[string, HassEntity]>
|
entityCardOptions: Partial<EntitiesCardConfig>
|
||||||
): LovelaceCardConfig[] => {
|
): LovelaceCardConfig[] => {
|
||||||
const cards: LovelaceCardConfig[] = [];
|
const cards: LovelaceCardConfig[] = [];
|
||||||
|
|
||||||
@ -68,7 +73,7 @@ const computeCards = (
|
|||||||
type: "weather-forecast",
|
type: "weather-forecast",
|
||||||
entity: entityId,
|
entity: entityId,
|
||||||
});
|
});
|
||||||
} else if (domain === "weblink") {
|
} else if (domain === "weblink" && stateObj) {
|
||||||
const conf: WeblinkConfig = {
|
const conf: WeblinkConfig = {
|
||||||
type: "weblink",
|
type: "weblink",
|
||||||
url: stateObj.state,
|
url: stateObj.state,
|
||||||
@ -85,9 +90,9 @@ const computeCards = (
|
|||||||
|
|
||||||
if (entities.length > 0) {
|
if (entities.length > 0) {
|
||||||
cards.unshift({
|
cards.unshift({
|
||||||
title,
|
|
||||||
type: "entities",
|
type: "entities",
|
||||||
entities,
|
entities,
|
||||||
|
...entityCardOptions,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,10 +157,13 @@ const generateViewConfig = (
|
|||||||
splitted.groups.forEach((groupEntity) => {
|
splitted.groups.forEach((groupEntity) => {
|
||||||
cards = cards.concat(
|
cards = cards.concat(
|
||||||
computeCards(
|
computeCards(
|
||||||
computeStateName(groupEntity),
|
|
||||||
groupEntity.attributes.entity_id.map(
|
groupEntity.attributes.entity_id.map(
|
||||||
(entityId): [string, HassEntity] => [entityId, entities[entityId]]
|
(entityId): [string, HassEntity] => [entityId, entities[entityId]]
|
||||||
)
|
),
|
||||||
|
{
|
||||||
|
title: computeStateName(groupEntity),
|
||||||
|
show_header_toggle: groupEntity.attributes.control !== "hidden",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -165,10 +173,12 @@ const generateViewConfig = (
|
|||||||
.forEach((domain) => {
|
.forEach((domain) => {
|
||||||
cards = cards.concat(
|
cards = cards.concat(
|
||||||
computeCards(
|
computeCards(
|
||||||
localize(`domain.${domain}`),
|
|
||||||
ungroupedEntitites[domain].map(
|
ungroupedEntitites[domain].map(
|
||||||
(entityId): [string, HassEntity] => [entityId, entities[entityId]]
|
(entityId): [string, HassEntity] => [entityId, entities[entityId]]
|
||||||
)
|
),
|
||||||
|
{
|
||||||
|
title: localize(`domain.${domain}`),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -237,6 +247,16 @@ export const generateLovelaceConfig = (
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Add map of geo locations to default view if loaded
|
||||||
|
if (hass.config.components.includes("geo_location")) {
|
||||||
|
if (views[0] && views[0].cards) {
|
||||||
|
views[0].cards.push({
|
||||||
|
type: "map",
|
||||||
|
geo_location_sources: ["all"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure we don't have Home as title and first tab.
|
// Make sure we don't have Home as title and first tab.
|
||||||
if (views.length > 1 && title === "Home") {
|
if (views.length > 1 && title === "Home") {
|
||||||
title = "Home Assistant";
|
title = "Home Assistant";
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { PropertyValues } from "@polymer/lit-element";
|
import { PropertyValues } from "lit-element";
|
||||||
|
|
||||||
// Check if config or Entity changed
|
// Check if config or Entity changed
|
||||||
export function hasConfigOrEntityChanged(
|
export function hasConfigOrEntityChanged(
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-textarea";
|
import "@polymer/paper-input/paper-textarea";
|
||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
@ -51,7 +55,7 @@ export class HuiActionEditor extends LitElement {
|
|||||||
return config.service || "";
|
return config.service || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass || !this.actions) {
|
if (!this.hass || !this.actions) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import { html, LitElement, PropertyDeclarations } from "lit-element";
|
||||||
import "@polymer/paper-button/paper-button";
|
import "@polymer/paper-button/paper-button";
|
||||||
import "@polymer/paper-menu-button/paper-menu-button";
|
import "@polymer/paper-menu-button/paper-menu-button";
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
@ -46,10 +46,6 @@ export class HuiCardOptions extends hassLocalizeLitMixin(LitElement) {
|
|||||||
paper-button {
|
paper-button {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
letter-spacing: 0.05em;
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
paper-icon-button {
|
paper-icon-button {
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
|
@ -3,8 +3,8 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult } from "lit-html";
|
} from "lit-element";
|
||||||
import { PaperToggleButtonElement } from "@polymer/paper-toggle-button/paper-toggle-button";
|
import { PaperToggleButtonElement } from "@polymer/paper-toggle-button/paper-toggle-button";
|
||||||
|
|
||||||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||||
@ -35,7 +35,7 @@ class HuiEntitiesToggle extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._toggleEntities) {
|
if (!this._toggleEntities) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
@ -19,7 +23,7 @@ export class HuiEntityEditor extends LitElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.entities) {
|
if (!this.entities) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-button/paper-button";
|
import "@polymer/paper-button/paper-button";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event";
|
import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event";
|
||||||
@ -28,7 +32,7 @@ export class HuiThemeSelectionEditor extends hassLocalizeLitMixin(LitElement) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
const themes = ["Backend-selected", "default"].concat(
|
const themes = ["Backend-selected", "default"].concat(
|
||||||
Object.keys(this.hass!.themes.themes).sort()
|
Object.keys(this.hass!.themes.themes).sort()
|
||||||
);
|
);
|
||||||
|
@ -3,8 +3,8 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { TemplateResult } from "lit-html";
|
} from "lit-element";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import format_date from "../../../common/datetime/format_date";
|
import format_date from "../../../common/datetime/format_date";
|
||||||
@ -49,7 +49,7 @@ class HuiTimestampDisplay extends hassLocalizeLitMixin(LitElement) {
|
|||||||
this._clearInterval();
|
this._clearInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.ts || !this.hass) {
|
if (!this.ts || !this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { html, LitElement } from "@polymer/lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
import "@polymer/paper-button/paper-button";
|
import "@polymer/paper-button/paper-button";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
@ -39,7 +38,7 @@ export class HuiCardPicker extends hassLocalizeLitMixin(LitElement) {
|
|||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
public cardPicked?: (cardConf: LovelaceCardConfig) => void;
|
public cardPicked?: (cardConf: LovelaceCardConfig) => void;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
${this.renderStyle()}
|
${this.renderStyle()}
|
||||||
<h3>${this.localize("ui.panel.lovelace.editor.edit_card.pick_card")}</h3>
|
<h3>${this.localize("ui.panel.lovelace.editor.edit_card.pick_card")}</h3>
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { HASSDomEvent } from "../../../../common/dom/fire_event";
|
import { HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||||
@ -48,7 +52,7 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._params) {
|
if (!this._params) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-dialog/paper-dialog";
|
import "@polymer/paper-dialog/paper-dialog";
|
||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
// tslint:disable-next-line:no-duplicate-imports
|
// tslint:disable-next-line:no-duplicate-imports
|
||||||
@ -23,7 +27,7 @@ export class HuiDialogMoveCardView extends hassLocalizeLitMixin(LitElement) {
|
|||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._params) {
|
if (!this._params) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-dialog/paper-dialog";
|
import "@polymer/paper-dialog/paper-dialog";
|
||||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||||
|
|
||||||
@ -17,7 +21,7 @@ export class HuiDialogPickCard extends hassLocalizeLitMixin(LitElement) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
<paper-dialog
|
<paper-dialog
|
||||||
with-backdrop
|
with-backdrop
|
||||||
|
@ -3,9 +3,9 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
PropertyDeclarations,
|
PropertyDeclarations,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "@polymer/lit-element";
|
TemplateResult,
|
||||||
import { classMap } from "lit-html/directives/classMap";
|
} from "lit-element";
|
||||||
import { TemplateResult } from "lit-html";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
|
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
@ -107,7 +107,7 @@ export class HuiEditCard extends hassLocalizeLitMixin(LitElement) {
|
|||||||
this._loadConfigElement(this.cardConfig!);
|
this._loadConfigElement(this.cardConfig!);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
let content;
|
let content;
|
||||||
let preview;
|
let preview;
|
||||||
if (this._configElement !== undefined) {
|
if (this._configElement !== undefined) {
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-textarea";
|
import "@polymer/paper-input/paper-textarea";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
@ -21,7 +25,7 @@ export class HuiYAMLEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
${this.renderStyle()}
|
${this.renderStyle()}
|
||||||
<paper-textarea
|
<paper-textarea
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { html } from "@polymer/lit-element";
|
import { html } from "lit-element";
|
||||||
|
|
||||||
export const configElementStyle = html`
|
export const configElementStyle = html`
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
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";
|
||||||
@ -49,7 +53,7 @@ export class HuiAlarmPanelCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.states || [];
|
return this._config!.states || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
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";
|
||||||
@ -12,7 +16,10 @@ import { hassLocalizeLitMixin } from "../../../../mixins/lit-localize-mixin";
|
|||||||
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, ConfigEntity } from "../../cards/hui-entities-card";
|
import {
|
||||||
|
EntitiesCardConfig,
|
||||||
|
EntitiesCardEntityConfig,
|
||||||
|
} from "../../cards/hui-entities-card";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
|
||||||
import "../../../../components/entity/state-badge";
|
import "../../../../components/entity/state-badge";
|
||||||
@ -53,16 +60,16 @@ export class HuiEntitiesCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
}
|
}
|
||||||
|
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
private _config?: Config;
|
private _config?: EntitiesCardConfig;
|
||||||
private _configEntities?: ConfigEntity[];
|
private _configEntities?: EntitiesCardEntityConfig[];
|
||||||
|
|
||||||
public setConfig(config: Config): void {
|
public setConfig(config: EntitiesCardConfig): void {
|
||||||
config = cardConfigStruct(config);
|
config = cardConfigStruct(config);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
this._configEntities = processEditorEntities(config.entities);
|
this._configEntities = processEditorEntities(config.entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
@ -68,7 +72,7 @@ export class HuiEntityButtonCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.theme || "default";
|
return this._config!.theme || "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
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";
|
||||||
|
|
||||||
@ -70,7 +74,7 @@ export class HuiGaugeCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.severity || undefined;
|
return this._config!.severity || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
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";
|
||||||
@ -68,7 +72,7 @@ export class HuiGlanceCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.columns || NaN;
|
return this._config!.columns || NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
@ -44,7 +48,7 @@ export class HuiIframeCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.aspect_ratio || "";
|
return this._config!.aspect_ratio || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
@ -47,7 +51,7 @@ export class HuiLightCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.entity || "";
|
return this._config!.entity || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
@ -64,7 +68,7 @@ export class HuiMapCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.entities || [];
|
return this._config!.entities || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import "@polymer/paper-input/paper-textarea";
|
import "@polymer/paper-input/paper-textarea";
|
||||||
|
|
||||||
@ -40,7 +44,7 @@ export class HuiMarkdownCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.content || "";
|
return this._config!.content || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
@ -34,7 +38,7 @@ export class HuiMediaControlCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.entity || "";
|
return this._config!.entity || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
@ -51,7 +55,7 @@ export class HuiPictureCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.hold_action || { action: "none" };
|
return this._config!.hold_action || { action: "none" };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
@ -42,7 +46,7 @@ export class HuiPlantStatusCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.name || "";
|
return this._config!.name || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
@ -75,7 +79,7 @@ export class HuiSensorCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.hours_to_show || "24";
|
return this._config!.hours_to_show || "24";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
@ -33,7 +37,7 @@ export class HuiShoppingListEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.title || "";
|
return this._config!.title || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
@ -47,7 +51,7 @@ export class HuiThermostatCardEditor extends hassLocalizeLitMixin(LitElement)
|
|||||||
return this._config!.theme || "default";
|
return this._config!.theme || "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
import { struct } from "../../common/structs/struct";
|
import { struct } from "../../common/structs/struct";
|
||||||
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
import { EntitiesEditorEvent, EditorTarget } from "../types";
|
||||||
@ -41,7 +45,7 @@ export class HuiWeatherForecastCardEditor
|
|||||||
return this._config!.name || "";
|
return this._config!.name || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
import "@polymer/paper-dialog/paper-dialog";
|
import "@polymer/paper-dialog/paper-dialog";
|
||||||
@ -41,7 +45,7 @@ export class HuiSaveConfig extends hassLocalizeLitMixin(LitElement) {
|
|||||||
return this.shadowRoot!.querySelector("paper-dialog")!;
|
return this.shadowRoot!.querySelector("paper-dialog")!;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
${this.renderStyle()}
|
${this.renderStyle()}
|
||||||
<paper-dialog with-backdrop>
|
<paper-dialog with-backdrop>
|
||||||
@ -108,6 +112,7 @@ export class HuiSaveConfig extends hassLocalizeLitMixin(LitElement) {
|
|||||||
try {
|
try {
|
||||||
const lovelace = this._params!.lovelace;
|
const lovelace = this._params!.lovelace;
|
||||||
await lovelace.saveConfig(lovelace.config);
|
await lovelace.saveConfig(lovelace.config);
|
||||||
|
lovelace.setEditMode(true);
|
||||||
this._saving = false;
|
this._saving = false;
|
||||||
this._closeDialog();
|
this._closeDialog();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
import "@polymer/paper-dialog/paper-dialog";
|
import "@polymer/paper-dialog/paper-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.
|
||||||
@ -47,7 +51,7 @@ export class HuiDialogEditLovelace extends hassLocalizeLitMixin(LitElement) {
|
|||||||
return this.shadowRoot!.querySelector("paper-dialog")!;
|
return this.shadowRoot!.querySelector("paper-dialog")!;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
${this.renderStyle()}
|
${this.renderStyle()}
|
||||||
<paper-dialog with-backdrop>
|
<paper-dialog with-backdrop>
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { EditorTarget } from "../types";
|
import { EditorTarget } from "../types";
|
||||||
@ -33,7 +37,7 @@ export class HuiLovelaceEditor extends hassLocalizeLitMixin(LitElement) {
|
|||||||
return this.config.title || "";
|
return this.config.title || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
${configElementStyle}
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { HASSDomEvent } from "../../../../common/dom/fire_event";
|
import { HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||||
@ -34,7 +38,7 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
(this.shadowRoot!.children[0] as any).showDialog();
|
(this.shadowRoot!.children[0] as any).showDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._params) {
|
if (!this._params) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
import "@polymer/paper-tabs/paper-tab";
|
import "@polymer/paper-tabs/paper-tab";
|
||||||
@ -83,7 +87,7 @@ export class HuiEditView extends hassLocalizeLitMixin(LitElement) {
|
|||||||
return this.shadowRoot!.querySelector("paper-dialog")!;
|
return this.shadowRoot!.querySelector("paper-dialog")!;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
let content;
|
let content;
|
||||||
switch (this._curTab) {
|
switch (this._curTab) {
|
||||||
case "tab-settings":
|
case "tab-settings":
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import {
|
||||||
import { TemplateResult } from "lit-html";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyDeclarations,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
import { EditorTarget } from "../types";
|
import { EditorTarget } from "../types";
|
||||||
@ -59,7 +63,7 @@ export class HuiViewEditor extends hassLocalizeLitMixin(LitElement) {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { html, LitElement } from "@polymer/lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
|
|
||||||
import "../../../components/ha-icon";
|
import "../../../components/ha-icon";
|
||||||
|
|
||||||
@ -8,7 +8,6 @@ import { longPress } from "../common/directives/long-press-directive";
|
|||||||
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
||||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
|
|
||||||
interface Config extends LovelaceElementConfig {
|
interface Config extends LovelaceElementConfig {
|
||||||
icon: string;
|
icon: string;
|
||||||
@ -31,7 +30,7 @@ export class HuiIconElement extends hassLocalizeLitMixin(LitElement)
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { html, LitElement } from "@polymer/lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
|
|
||||||
import "../components/hui-image";
|
import "../components/hui-image";
|
||||||
|
|
||||||
@ -8,7 +8,6 @@ import { longPress } from "../common/directives/long-press-directive";
|
|||||||
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
||||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
|
|
||||||
interface Config extends LovelaceElementConfig {
|
interface Config extends LovelaceElementConfig {
|
||||||
image?: string;
|
image?: string;
|
||||||
@ -40,7 +39,7 @@ export class HuiImageElement extends hassLocalizeLitMixin(LitElement)
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { html, LitElement } from "@polymer/lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
|
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
|
|
||||||
@ -37,7 +36,7 @@ export class HuiServiceButtonElement extends LitElement
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { html, LitElement } from "@polymer/lit-element";
|
import { html, LitElement, TemplateResult } from "lit-element";
|
||||||
|
|
||||||
import "../../../components/entity/ha-state-label-badge";
|
import "../../../components/entity/ha-state-label-badge";
|
||||||
|
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { TemplateResult } from "lit-html";
|
|
||||||
|
|
||||||
export class HuiStateBadgeElement extends LitElement
|
export class HuiStateBadgeElement extends LitElement
|
||||||
implements LovelaceElement {
|
implements LovelaceElement {
|
||||||
@ -24,7 +23,7 @@ export class HuiStateBadgeElement extends LitElement
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult | void {
|
||||||
if (
|
if (
|
||||||
!this._config ||
|
!this._config ||
|
||||||
!this.hass ||
|
!this.hass ||
|
||||||
|
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