From d0cc4c27158e273734e5e3f4607c2afe2ce44181 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 19 Sep 2019 18:10:02 +0200 Subject: [PATCH 01/45] Move views to own folder + use update vs updated in panel view (#3761) * Move views to own folder + use update vs updated in panel view * updated -> update --- cast/src/receiver/layout/hc-lovelace.ts | 2 +- src/panels/lovelace/hui-root.ts | 8 +++---- src/panels/lovelace/hui-view-editable.ts | 3 --- .../lovelace/{ => views}/hui-panel-view.ts | 14 +++++------ .../lovelace/views/hui-view-editable.ts | 3 +++ src/panels/lovelace/{ => views}/hui-view.ts | 24 +++++++++---------- 6 files changed, 27 insertions(+), 27 deletions(-) delete mode 100644 src/panels/lovelace/hui-view-editable.ts rename src/panels/lovelace/{ => views}/hui-panel-view.ts (78%) create mode 100644 src/panels/lovelace/views/hui-view-editable.ts rename src/panels/lovelace/{ => views}/hui-view.ts (91%) diff --git a/cast/src/receiver/layout/hc-lovelace.ts b/cast/src/receiver/layout/hc-lovelace.ts index 3c52475fd6..fd5513eb81 100644 --- a/cast/src/receiver/layout/hc-lovelace.ts +++ b/cast/src/receiver/layout/hc-lovelace.ts @@ -8,7 +8,7 @@ import { property, } from "lit-element"; import { LovelaceConfig } from "../../../../src/data/lovelace"; -import "../../../../src/panels/lovelace/hui-view"; +import "../../../../src/panels/lovelace/views/hui-view"; import { HomeAssistant } from "../../../../src/types"; import { Lovelace } from "../../../../src/panels/lovelace/types"; import "./hc-launch-screen"; diff --git a/src/panels/lovelace/hui-root.ts b/src/panels/lovelace/hui-root.ts index 13ab3dbb79..9f57cd25a8 100644 --- a/src/panels/lovelace/hui-root.ts +++ b/src/panels/lovelace/hui-root.ts @@ -35,13 +35,13 @@ import { navigate } from "../../common/navigate"; import { fireEvent } from "../../common/dom/fire_event"; import { swapView } from "./editor/config-util"; -import "./hui-view"; +import "./views/hui-view"; // Not a duplicate import, this one is for type // tslint:disable-next-line -import { HUIView } from "./hui-view"; -import "./hui-panel-view"; +import { HUIView } from "./views/hui-view"; +import "./views/hui-panel-view"; // tslint:disable-next-line -import { HUIPanelView } from "./hui-panel-view"; +import { HUIPanelView } from "./views/hui-panel-view"; import { showEditViewDialog } from "./editor/view-editor/show-edit-view-dialog"; import { showEditLovelaceDialog } from "./editor/lovelace-editor/show-edit-lovelace-dialog"; import { Lovelace } from "./types"; diff --git a/src/panels/lovelace/hui-view-editable.ts b/src/panels/lovelace/hui-view-editable.ts deleted file mode 100644 index 676b70ab17..0000000000 --- a/src/panels/lovelace/hui-view-editable.ts +++ /dev/null @@ -1,3 +0,0 @@ -// hui-view dependencies for when in edit mode. -import "./components/hui-card-options"; -import "../../components/ha-fab"; diff --git a/src/panels/lovelace/hui-panel-view.ts b/src/panels/lovelace/views/hui-panel-view.ts similarity index 78% rename from src/panels/lovelace/hui-panel-view.ts rename to src/panels/lovelace/views/hui-panel-view.ts index dfdcf5d1ce..525465c05f 100644 --- a/src/panels/lovelace/hui-panel-view.ts +++ b/src/panels/lovelace/views/hui-panel-view.ts @@ -5,12 +5,12 @@ import { UpdatingElement, } from "lit-element"; -import applyThemesOnElement from "../../common/dom/apply_themes_on_element"; +import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; -import { HomeAssistant } from "../../types"; -import { LovelaceCard } from "./types"; -import { createCardElement } from "./common/create-card-element"; -import { LovelaceViewConfig } from "../../data/lovelace"; +import { HomeAssistant } from "../../../types"; +import { LovelaceCard } from "../types"; +import { createCardElement } from "../common/create-card-element"; +import { LovelaceViewConfig } from "../../../data/lovelace"; @customElement("hui-panel-view") export class HUIPanelView extends UpdatingElement { @@ -22,8 +22,8 @@ export class HUIPanelView extends UpdatingElement { this.style.setProperty("background", "var(--lovelace-background)"); } - protected updated(changedProperties: PropertyValues): void { - super.updated(changedProperties); + protected update(changedProperties: PropertyValues): void { + super.update(changedProperties); const hass = this.hass!; const hassChanged = changedProperties.has("hass"); diff --git a/src/panels/lovelace/views/hui-view-editable.ts b/src/panels/lovelace/views/hui-view-editable.ts new file mode 100644 index 0000000000..4ef6e29420 --- /dev/null +++ b/src/panels/lovelace/views/hui-view-editable.ts @@ -0,0 +1,3 @@ +// hui-view dependencies for when in edit mode. +import "../components/hui-card-options"; +import "../../../components/ha-fab"; diff --git a/src/panels/lovelace/hui-view.ts b/src/panels/lovelace/views/hui-view.ts similarity index 91% rename from src/panels/lovelace/hui-view.ts rename to src/panels/lovelace/views/hui-view.ts index 8d78e0e84a..5edef27a25 100644 --- a/src/panels/lovelace/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -6,24 +6,24 @@ import { TemplateResult, } from "lit-element"; -import "../../components/entity/ha-state-label-badge"; +import "../../../components/entity/ha-state-label-badge"; // This one is for types // tslint:disable-next-line -import { HaStateLabelBadge } from "../../components/entity/ha-state-label-badge"; +import { HaStateLabelBadge } from "../../../components/entity/ha-state-label-badge"; -import applyThemesOnElement from "../../common/dom/apply_themes_on_element"; +import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; -import { LovelaceViewConfig, LovelaceCardConfig } from "../../data/lovelace"; -import { HomeAssistant } from "../../types"; +import { LovelaceViewConfig, LovelaceCardConfig } from "../../../data/lovelace"; +import { HomeAssistant } from "../../../types"; import { classMap } from "lit-html/directives/class-map"; -import { Lovelace, LovelaceCard } from "./types"; -import { createCardElement } from "./common/create-card-element"; -import { computeCardSize } from "./common/compute-card-size"; -import { showEditCardDialog } from "./editor/card-editor/show-edit-card-dialog"; -import { HuiErrorCard } from "./cards/hui-error-card"; +import { Lovelace, LovelaceCard } from "../types"; +import { createCardElement } from "../common/create-card-element"; +import { computeCardSize } from "../common/compute-card-size"; +import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog"; +import { HuiErrorCard } from "../cards/hui-error-card"; -import { computeRTL } from "../../common/util/compute_rtl"; -import { processConfigEntities } from "./common/process-config-entities"; +import { computeRTL } from "../../../common/util/compute_rtl"; +import { processConfigEntities } from "../common/process-config-entities"; let editCodeLoaded = false; From 145259e82f615b92f6653e51828f20a8caf9ce84 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 20 Sep 2019 01:27:54 +0200 Subject: [PATCH 02/45] Add Language Urdu (#3750) * Add Urdu * Changed name to native name --- src/translations/translationMetadata.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/translations/translationMetadata.json b/src/translations/translationMetadata.json index 9fe6e8de64..1d151dac63 100644 --- a/src/translations/translationMetadata.json +++ b/src/translations/translationMetadata.json @@ -151,6 +151,9 @@ "uk": { "nativeName": "Українська" }, + "ur": { + "nativeName": "اُردُو" + }, "vi": { "nativeName": "Tiếng Việt" }, From eee0c2e53ff2653d0139e2bef1fc8911e9428aab Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Fri, 20 Sep 2019 17:19:38 +0200 Subject: [PATCH 03/45] Add support for automation description (#3723) * Add support for automation annotation * Update label and add placeholder * Rename annotation to description * Adress review comments, fix lint errors --- src/components/ha-textarea.js | 7 ++++++- src/data/automation.ts | 1 + .../config/automation/ha-automation-editor.ts | 1 + src/panels/config/js/automation.tsx | 14 +++++++++++++- src/translations/en.json | 6 +++++- 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/components/ha-textarea.js b/src/components/ha-textarea.js index ef941a39ce..70de137543 100644 --- a/src/components/ha-textarea.js +++ b/src/components/ha-textarea.js @@ -21,7 +21,11 @@ class HaTextarea extends PolymerElement { display: block; } - + `; } @@ -29,6 +33,7 @@ class HaTextarea extends PolymerElement { return { name: String, label: String, + placeholder: String, value: { type: String, notify: true, diff --git a/src/data/automation.ts b/src/data/automation.ts index ad968cc1df..241edf3008 100644 --- a/src/data/automation.ts +++ b/src/data/automation.ts @@ -13,6 +13,7 @@ export interface AutomationEntity extends HassEntityBase { export interface AutomationConfig { alias: string; + description: string; trigger: any[]; condition?: any[]; action: any[]; diff --git a/src/panels/config/automation/ha-automation-editor.ts b/src/panels/config/automation/ha-automation-editor.ts index 92e34d43cb..547f0219b7 100644 --- a/src/panels/config/automation/ha-automation-editor.ts +++ b/src/panels/config/automation/ha-automation-editor.ts @@ -183,6 +183,7 @@ class HaAutomationEditor extends LitElement { alias: this.hass.localize( "ui.panel.config.automation.editor.default_name" ), + description: "", trigger: [{ platform: "state" }], condition: [], action: [{ service: "" }], diff --git a/src/panels/config/js/automation.tsx b/src/panels/config/js/automation.tsx index bb3ff51ee8..e94284cbf2 100644 --- a/src/panels/config/js/automation.tsx +++ b/src/panels/config/js/automation.tsx @@ -3,6 +3,7 @@ import { h, Component } from "preact"; import "@polymer/paper-input/paper-input"; import "../ha-config-section"; import "../../../components/ha-card"; +import "../../../components/ha-textarea"; import Trigger from "./trigger/index"; import Condition from "./condition/index"; @@ -38,7 +39,7 @@ export default class Automation extends Component { } public render({ automation, isWide, hass, localize }) { - const { alias, trigger, condition, action } = automation; + const { alias, description, trigger, condition, action } = automation; return (
@@ -55,6 +56,17 @@ export default class Automation extends Component { value={alias} onvalue-changed={this.onChange} /> +
diff --git a/src/translations/en.json b/src/translations/en.json index 9ef2dd6626..b1c4c24edd 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -699,13 +699,17 @@ "add_automation": "Add automation" }, "editor": { - "introduction": "Use automations to bring your home alive", + "introduction": "Use automations to bring your home alive.", "default_name": "New Automation", "load_error_not_editable": "Only automations in automations.yaml are editable.", "load_error_unknown": "Error loading automation ({err_no}).", "save": "Save", "unsaved_confirm": "You have unsaved changes. Are you sure you want to leave?", "alias": "Name", + "description": { + "label": "Description", + "placeholder": "Optional description" + }, "triggers": { "header": "Triggers", "introduction": "Triggers are what starts the processing of an automation rule. It is possible to specify multiple triggers for the same rule. Once a trigger starts, Home Assistant will validate the conditions, if any, and call the action.", From 9a7eb3d4062c7d40b08afc262238e4681ab1d09f Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Fri, 20 Sep 2019 16:10:14 -0500 Subject: [PATCH 04/45] light-card: icon option (#3771) * light-card: icon option closes https://github.com/home-assistant/home-assistant-polymer/issues/3768 * add theme select label property * address review comments --- src/panels/lovelace/cards/hui-light-card.ts | 2 +- src/panels/lovelace/cards/types.ts | 1 + .../components/hui-theme-select-editor.ts | 5 +- .../config-elements/hui-light-card-editor.ts | 54 ++++++++++++------- src/translations/en.json | 3 ++ 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/panels/lovelace/cards/hui-light-card.ts b/src/panels/lovelace/cards/hui-light-card.ts index a1efbf274c..bb90cbef11 100644 --- a/src/panels/lovelace/cards/hui-light-card.ts +++ b/src/panels/lovelace/cards/hui-light-card.ts @@ -107,7 +107,7 @@ export class HuiLightCard extends LitElement implements LovelaceCard { diff --git a/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts index 8f1eba6876..df776a158b 100644 --- a/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts @@ -23,6 +23,7 @@ const cardConfigStruct = struct({ name: "string?", entity: "string?", theme: "string?", + icon: "string?", }); @customElement("hui-light-card-editor") @@ -49,6 +50,10 @@ export class HuiLightCardEditor extends LitElement return this._config!.entity || ""; } + get _icon(): string { + return this._config!.icon || ""; + } + protected render(): TemplateResult | void { if (!this.hass) { return html``; @@ -57,28 +62,37 @@ export class HuiLightCardEditor extends LitElement return html` ${configElementStyle}
- +
- - + +
+ +
`; } diff --git a/src/translations/en.json b/src/translations/en.json index b1c4c24edd..db4e7a8dac 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1110,6 +1110,9 @@ "para_no_id": "This element doesn't have an ID. Please add an ID to this element in 'ui-lovelace.yaml'.", "para_migrate": "Home Assistant can add ID's to all your cards and views automatically for you by pressing the 'Migrate config' button.", "migrate": "Migrate config" + }, + "theme": { + "theme": "Theme (Optional)" } }, "warning": { From 5e28e1b320f89d588893c8cd054f7535f087d40c Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Sat, 21 Sep 2019 04:59:27 -0500 Subject: [PATCH 05/45] Switch paper-toggle-button to mwc-switch (#3683) * Switch paper-toggle-button to mwc-switch Closes https://github.com/home-assistant/home-assistant-polymer/issues/3352 * ha-switch * apply not-checked theming Thanks @bramkragten! * address review comments --- gallery/src/components/demo-cards.js | 6 +-- gallery/src/components/demo-more-infos.js | 6 +-- hassio/src/addon-view/hassio-addon-info.js | 24 ++++++------ package.json | 2 +- src/components/entity/ha-entity-toggle.ts | 16 ++++---- .../ha-push-notifications-toggle.js | 8 ++-- src/components/ha-switch.ts | 37 +++++++++++++++++++ .../dialog-config-entry-system-options.ts | 15 +++++--- .../more-info/controls/more-info-climate.ts | 6 +-- .../more-info/controls/more-info-fan.js | 9 +++-- .../controls/more-info-water_heater.js | 12 +++--- .../config/cloud/account/cloud-account.js | 13 +++---- .../config/cloud/account/cloud-alexa-pref.ts | 20 +++++----- .../config/cloud/account/cloud-google-pref.ts | 14 +++---- .../config/cloud/account/cloud-remote-pref.ts | 14 +++---- .../config/cloud/account/cloud-webhooks.ts | 7 ++-- src/panels/config/cloud/alexa/cloud-alexa.ts | 29 ++++++++------- .../cloud-google-assistant.ts | 37 ++++++++++--------- .../dialog-entity-registry-detail.ts | 17 +++++---- .../components/hui-entities-toggle.ts | 15 ++++---- src/panels/lovelace/components/hui-image.ts | 2 - .../config-elements/config-elements-style.ts | 2 +- .../hui-entities-card-editor.ts | 6 +-- .../hui-entity-button-card-editor.ts | 8 ++-- .../config-elements/hui-gauge-card-editor.ts | 8 ++-- .../config-elements/hui-glance-card-editor.ts | 14 +++---- .../config-elements/hui-map-card-editor.ts | 4 +- .../editor/view-editor/hui-view-editor.ts | 10 ++--- src/panels/profile/ha-advanced-mode-card.ts | 4 +- src/panels/profile/ha-force-narrow-row.ts | 16 ++++---- src/resources/ha-style.ts | 2 +- yarn.lock | 35 +++++++++++++----- 32 files changed, 240 insertions(+), 178 deletions(-) create mode 100644 src/components/ha-switch.ts diff --git a/gallery/src/components/demo-cards.js b/gallery/src/components/demo-cards.js index 0516e3078a..a73bc53a2f 100644 --- a/gallery/src/components/demo-cards.js +++ b/gallery/src/components/demo-cards.js @@ -1,9 +1,9 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "@polymer/app-layout/app-toolbar/app-toolbar"; -import "@polymer/paper-toggle-button/paper-toggle-button"; import "./demo-card"; +import "../../../src/components/ha-switch"; class DemoCards extends PolymerElement { static get template() { @@ -26,9 +26,7 @@ class DemoCards extends PolymerElement {
- Show config + Show config
diff --git a/gallery/src/components/demo-more-infos.js b/gallery/src/components/demo-more-infos.js index 3bd1626a54..8f82e2a8ab 100644 --- a/gallery/src/components/demo-more-infos.js +++ b/gallery/src/components/demo-more-infos.js @@ -1,9 +1,9 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "@polymer/app-layout/app-toolbar/app-toolbar"; -import "@polymer/paper-toggle-button/paper-toggle-button"; import "./demo-more-info"; +import "../../../src/components/ha-switch"; class DemoMoreInfos extends PolymerElement { static get template() { @@ -26,9 +26,7 @@ class DemoMoreInfos extends PolymerElement {
- Show entity + Show entity
diff --git a/hassio/src/addon-view/hassio-addon-info.js b/hassio/src/addon-view/hassio-addon-info.js index dc6c05d696..10df924f6e 100644 --- a/hassio/src/addon-view/hassio-addon-info.js +++ b/hassio/src/addon-view/hassio-addon-info.js @@ -2,19 +2,19 @@ import "@polymer/iron-icon/iron-icon"; import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; import "@polymer/paper-tooltip/paper-tooltip"; -import "@polymer/paper-toggle-button/paper-toggle-button"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../../src/components/ha-label-badge"; import "../../../src/components/ha-markdown"; import "../../../src/components/buttons/ha-call-api-button"; +import "../../../src/components/ha-switch"; import "../../../src/resources/ha-style"; +import "../components/hassio-card-content"; + import { EventsMixin } from "../../../src/mixins/events-mixin"; import { navigate } from "../../../src/common/navigate"; - import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio-markdown"; -import "../components/hassio-card-content"; const PERMIS_DESC = { rating: { @@ -122,7 +122,7 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) { width: 16px; color: var(--secondary-text-color); } - paper-toggle-button { + ha-switch { display: inline; } iron-icon.running { @@ -348,26 +348,26 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) { diff --git a/src/panels/config/cloud/account/cloud-account.js b/src/panels/config/cloud/account/cloud-account.js index d78754d9b9..0b9c3ed411 100644 --- a/src/panels/config/cloud/account/cloud-account.js +++ b/src/panels/config/cloud/account/cloud-account.js @@ -1,6 +1,5 @@ import "@material/mwc-button"; import "@polymer/paper-item/paper-item-body"; -import "@polymer/paper-toggle-button/paper-toggle-button"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -8,18 +7,18 @@ import "../../../../components/ha-card"; import "../../../../components/buttons/ha-call-api-button"; import "../../../../layouts/hass-subpage"; import "../../../../resources/ha-style"; - import "../../ha-config-section"; import "./cloud-webhooks"; - -import formatDateTime from "../../../../common/datetime/format_date_time"; -import { EventsMixin } from "../../../../mixins/events-mixin"; -import LocalizeMixin from "../../../../mixins/localize-mixin"; -import { fetchCloudSubscriptionInfo } from "../../../../data/cloud"; import "./cloud-alexa-pref"; import "./cloud-google-pref"; import "./cloud-remote-pref"; +import { EventsMixin } from "../../../../mixins/events-mixin"; +import { fetchCloudSubscriptionInfo } from "../../../../data/cloud"; + +import formatDateTime from "../../../../common/datetime/format_date_time"; +import LocalizeMixin from "../../../../mixins/localize-mixin"; + /* * @appliesMixin EventsMixin * @appliesMixin LocalizeMixin diff --git a/src/panels/config/cloud/account/cloud-alexa-pref.ts b/src/panels/config/cloud/account/cloud-alexa-pref.ts index dcbeee76be..ab8c787b6a 100644 --- a/src/panels/config/cloud/account/cloud-alexa-pref.ts +++ b/src/panels/config/cloud/account/cloud-alexa-pref.ts @@ -7,12 +7,12 @@ import { property, } from "lit-element"; import "@material/mwc-button"; -import "@polymer/paper-toggle-button/paper-toggle-button"; -// tslint:disable-next-line -import { PaperToggleButtonElement } from "@polymer/paper-toggle-button/paper-toggle-button"; import "../../../../components/ha-card"; +import "../../../../components/ha-switch"; +// tslint:disable-next-line: no-duplicate-imports +import { HaSwitch } from "../../../../components/ha-switch"; import { fireEvent } from "../../../../common/dom/fire_event"; import { HomeAssistant } from "../../../../types"; import { CloudStatusLoggedIn, updateCloudPref } from "../../../../data/cloud"; @@ -32,10 +32,10 @@ export class CloudAlexaPref extends LitElement { return html` - + >
With the Alexa integration for Home Assistant Cloud you'll be able to control all your Home Assistant devices via any Alexa-enabled device. @@ -70,10 +70,10 @@ export class CloudAlexaPref extends LitElement { allows you to always see the latest states in the Alexa app and use the state changes to create routines.

- + > ` : ""}
@@ -102,7 +102,7 @@ export class CloudAlexaPref extends LitElement { } private async _enabledToggleChanged(ev) { - const toggle = ev.target as PaperToggleButtonElement; + const toggle = ev.target as HaSwitch; try { await updateCloudPref(this.hass!, { alexa_enabled: toggle.checked! }); fireEvent(this, "ha-refresh-cloud-status"); @@ -112,7 +112,7 @@ export class CloudAlexaPref extends LitElement { } private async _reportToggleChanged(ev) { - const toggle = ev.target as PaperToggleButtonElement; + const toggle = ev.target as HaSwitch; try { await updateCloudPref(this.hass!, { alexa_report_state: toggle.checked!, @@ -133,7 +133,7 @@ export class CloudAlexaPref extends LitElement { a { color: var(--primary-color); } - ha-card > paper-toggle-button { + ha-card > ha-switch { margin: -4px 0; position: absolute; right: 8px; diff --git a/src/panels/config/cloud/account/cloud-google-pref.ts b/src/panels/config/cloud/account/cloud-google-pref.ts index 9035eaebd9..102bb513c0 100644 --- a/src/panels/config/cloud/account/cloud-google-pref.ts +++ b/src/panels/config/cloud/account/cloud-google-pref.ts @@ -7,13 +7,13 @@ import { css, } from "lit-element"; import "@material/mwc-button"; -import "@polymer/paper-toggle-button/paper-toggle-button"; -// tslint:disable-next-line -import { PaperToggleButtonElement } from "@polymer/paper-toggle-button/paper-toggle-button"; import "../../../../components/buttons/ha-call-api-button"; import "../../../../components/ha-card"; +import "../../../../components/ha-switch"; +// tslint:disable-next-line +import { HaSwitch } from "../../../../components/ha-switch"; import { fireEvent } from "../../../../common/dom/fire_event"; import { HomeAssistant } from "../../../../types"; import { CloudStatusLoggedIn, updateCloudPref } from "../../../../data/cloud"; @@ -43,11 +43,11 @@ export class CloudGooglePref extends LitElement { return html` - + >
With the Google Assistant integration for Home Assistant Cloud you'll be able to control all your Home Assistant devices via any Google @@ -110,7 +110,7 @@ export class CloudGooglePref extends LitElement { } private async _toggleChanged(ev) { - const toggle = ev.target as PaperToggleButtonElement; + const toggle = ev.target as HaSwitch; try { await updateCloudPref(this.hass!, { [toggle.id]: toggle.checked! }); fireEvent(this, "ha-refresh-cloud-status"); @@ -138,7 +138,7 @@ export class CloudGooglePref extends LitElement { a { color: var(--primary-color); } - ha-card > paper-toggle-button { + ha-card > ha-switch { margin: -4px 0; position: absolute; right: 8px; diff --git a/src/panels/config/cloud/account/cloud-remote-pref.ts b/src/panels/config/cloud/account/cloud-remote-pref.ts index 1c70724251..3d54ff8fbf 100644 --- a/src/panels/config/cloud/account/cloud-remote-pref.ts +++ b/src/panels/config/cloud/account/cloud-remote-pref.ts @@ -8,13 +8,13 @@ import { css, } from "lit-element"; import "@material/mwc-button"; -import "@polymer/paper-toggle-button/paper-toggle-button"; import "@polymer/paper-item/paper-item-body"; -// tslint:disable-next-line -import { PaperToggleButtonElement } from "@polymer/paper-toggle-button/paper-toggle-button"; import "../../../../components/ha-card"; +import "../../../../components/ha-switch"; +// tslint:disable-next-line +import { HaSwitch } from "../../../../components/ha-switch"; import { fireEvent } from "../../../../common/dom/fire_event"; import { HomeAssistant } from "../../../../types"; import { @@ -59,10 +59,10 @@ export class CloudRemotePref extends LitElement { return html` - + >
Home Assistant Cloud provides a secure remote connection to your instance while away from home. Your instance @@ -95,7 +95,7 @@ export class CloudRemotePref extends LitElement { } private async _toggleChanged(ev) { - const toggle = ev.target as PaperToggleButtonElement; + const toggle = ev.target as HaSwitch; try { if (toggle.checked) { @@ -118,7 +118,7 @@ export class CloudRemotePref extends LitElement { a { color: var(--primary-color); } - ha-card > paper-toggle-button { + ha-card > ha-switch { margin: -4px 0; position: absolute; right: 8px; diff --git a/src/panels/config/cloud/account/cloud-webhooks.ts b/src/panels/config/cloud/account/cloud-webhooks.ts index bd0f0077f5..ba0d30c4d6 100644 --- a/src/panels/config/cloud/account/cloud-webhooks.ts +++ b/src/panels/config/cloud/account/cloud-webhooks.ts @@ -4,11 +4,12 @@ import { PropertyDeclarations, PropertyValues, } from "lit-element"; -import "@polymer/paper-toggle-button/paper-toggle-button"; import "@polymer/paper-item/paper-item"; import "@polymer/paper-item/paper-item-body"; import "@polymer/paper-spinner/paper-spinner"; + import "../../../../components/ha-card"; +import "../../../../components/ha-switch"; import { HomeAssistant, WebhookError } from "../../../../types"; import { Webhook, fetchWebhooks } from "../../../../data/webhook"; @@ -116,9 +117,7 @@ export class CloudWebhooks extends LitElement { ` : html` - + `}
` diff --git a/src/panels/config/cloud/alexa/cloud-alexa.ts b/src/panels/config/cloud/alexa/cloud-alexa.ts index ee94b90ec5..afdb072eae 100644 --- a/src/panels/config/cloud/alexa/cloud-alexa.ts +++ b/src/panels/config/cloud/alexa/cloud-alexa.ts @@ -7,12 +7,15 @@ import { customElement, property, } from "lit-element"; -import "@polymer/paper-toggle-button"; import "@polymer/paper-icon-button"; +import memoizeOne from "memoize-one"; + import "../../../../layouts/hass-subpage"; import "../../../../layouts/hass-loading-screen"; import "../../../../components/ha-card"; +import "../../../../components/ha-switch"; import "../../../../components/entity/state-info"; + import { HomeAssistant } from "../../../../types"; import { CloudStatusLoggedIn, @@ -20,19 +23,20 @@ import { updateCloudAlexaEntityConfig, AlexaEntityConfig, } from "../../../../data/cloud"; -import memoizeOne from "memoize-one"; import { generateFilter, isEmptyFilter, EntityFilter, } from "../../../../common/entity/entity_filter"; import { compare } from "../../../../common/string/compare"; -import computeStateName from "../../../../common/entity/compute_state_name"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { PolymerChangedEvent } from "../../../../polymer-types"; import { showDomainTogglerDialog } from "../../../../dialogs/domain-toggler/show-dialog-domain-toggler"; -import computeDomain from "../../../../common/entity/compute_domain"; import { AlexaEntity, fetchCloudAlexaEntities } from "../../../../data/alexa"; +// tslint:disable-next-line: no-duplicate-imports +import { HaSwitch } from "../../../../components/ha-switch"; + +import computeStateName from "../../../../common/entity/compute_state_name"; +import computeDomain from "../../../../common/entity/compute_domain"; const DEFAULT_CONFIG_EXPOSE = true; const IGNORE_INTERFACES = ["Alexa.EndpointHealth"]; @@ -126,14 +130,14 @@ class CloudAlexa extends LitElement { ) .join(", ")} - Expose to Alexa - +
`); @@ -227,9 +231,9 @@ class CloudAlexa extends LitElement { fireEvent(this, "hass-more-info", { entityId }); } - private async _exposeChanged(ev: PolymerChangedEvent) { + private async _exposeChanged(ev: Event) { const entityId = (ev.currentTarget as any).entityId; - const newExposed = ev.detail.value; + const newExposed = (ev.target as HaSwitch).checked; await this._updateExposed(entityId, newExposed); } @@ -328,9 +332,8 @@ class CloudAlexa extends LitElement { display: flex; flex-wrap: wrap; padding: 4px; - --paper-toggle-button-label-spacing: 16px; } - paper-toggle-button { + ha-switch { clear: both; } ha-card { @@ -344,7 +347,7 @@ class CloudAlexa extends LitElement { state-info { cursor: pointer; } - paper-toggle-button { + ha-switch { padding: 8px 0; } diff --git a/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts b/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts index 084ff1bab9..08683dfb92 100644 --- a/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts +++ b/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts @@ -7,12 +7,15 @@ import { customElement, property, } from "lit-element"; -import "@polymer/paper-toggle-button"; +import memoizeOne from "memoize-one"; import "@polymer/paper-icon-button"; + import "../../../../layouts/hass-subpage"; import "../../../../layouts/hass-loading-screen"; import "../../../../components/ha-card"; import "../../../../components/entity/state-info"; +import "../../../../components/ha-switch"; + import { HomeAssistant } from "../../../../types"; import { CloudStatusLoggedIn, @@ -21,23 +24,24 @@ import { cloudSyncGoogleAssistant, GoogleEntityConfig, } from "../../../../data/cloud"; -import memoizeOne from "memoize-one"; import { generateFilter, isEmptyFilter, EntityFilter, } from "../../../../common/entity/entity_filter"; import { compare } from "../../../../common/string/compare"; -import computeStateName from "../../../../common/entity/compute_state_name"; import { fireEvent } from "../../../../common/dom/fire_event"; import { showToast } from "../../../../util/toast"; -import { PolymerChangedEvent } from "../../../../polymer-types"; import { showDomainTogglerDialog } from "../../../../dialogs/domain-toggler/show-dialog-domain-toggler"; -import computeDomain from "../../../../common/entity/compute_domain"; import { GoogleEntity, fetchCloudGoogleEntities, } from "../../../../data/google_assistant"; +// tslint:disable-next-line: no-duplicate-imports +import { HaSwitch } from "../../../../components/ha-switch"; + +import computeStateName from "../../../../common/entity/compute_state_name"; +import computeDomain from "../../../../common/entity/compute_domain"; const DEFAULT_CONFIG_EXPOSE = true; @@ -122,23 +126,23 @@ class CloudGoogleAssistant extends LitElement { .map((trait) => trait.substr(trait.lastIndexOf(".") + 1)) .join(", ")} - Expose to Google Assistant - + ${entity.might_2fa ? html` - Disable two factor authentication - + ` : ""}
@@ -234,9 +238,9 @@ class CloudGoogleAssistant extends LitElement { fireEvent(this, "hass-more-info", { entityId }); } - private async _exposeChanged(ev: PolymerChangedEvent) { + private async _exposeChanged(ev: Event) { const entityId = (ev.currentTarget as any).entityId; - const newExposed = ev.detail.value; + const newExposed = (ev.target as HaSwitch).checked; await this._updateExposed(entityId, newExposed); } @@ -251,9 +255,9 @@ class CloudGoogleAssistant extends LitElement { this._ensureEntitySync(); } - private async _disable2FAChanged(ev: PolymerChangedEvent) { + private async _disable2FAChanged(ev: Event) { const entityId = (ev.currentTarget as any).entityId; - const newDisable2FA = ev.detail.value; + const newDisable2FA = (ev.target as HaSwitch).checked; const curDisable2FA = Boolean( (this._entityConfigs[entityId] || {}).disable_2fa ); @@ -348,7 +352,6 @@ class CloudGoogleAssistant extends LitElement { display: flex; flex-wrap: wrap; padding: 4px; - --paper-toggle-button-label-spacing: 16px; } ha-card { margin: 4px; @@ -361,7 +364,7 @@ class CloudGoogleAssistant extends LitElement { state-info { cursor: pointer; } - paper-toggle-button { + ha-switch { padding: 8px 0; } diff --git a/src/panels/config/entity_registry/dialog-entity-registry-detail.ts b/src/panels/config/entity_registry/dialog-entity-registry-detail.ts index 2a6ac0553f..b1bbbd03b9 100644 --- a/src/panels/config/entity_registry/dialog-entity-registry-detail.ts +++ b/src/panels/config/entity_registry/dialog-entity-registry-detail.ts @@ -8,16 +8,19 @@ import { } from "lit-element"; import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable"; import "@polymer/paper-input/paper-input"; -import "@polymer/paper-toggle-button/paper-toggle-button"; import "../../../components/dialog/ha-paper-dialog"; +import "../../../components/ha-switch"; import { EntityRegistryDetailDialogParams } from "./show-dialog-entity-registry-detail"; import { PolymerChangedEvent } from "../../../polymer-types"; import { haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; -import computeDomain from "../../../common/entity/compute_domain"; import { HassEntity } from "home-assistant-js-websocket"; +// tslint:disable-next-line: no-duplicate-imports +import { HaSwitch } from "../../../components/ha-switch"; + +import computeDomain from "../../../common/entity/compute_domain"; import computeStateName from "../../../common/entity/compute_state_name"; class DialogEntityRegistryDetail extends LitElement { @@ -95,9 +98,9 @@ class DialogEntityRegistryDetail extends LitElement { .disabled=${this._submitting} >
-
@@ -121,7 +124,7 @@ class DialogEntityRegistryDetail extends LitElement {
Note: this might not work yet with all integrations.
-
+
@@ -190,8 +193,8 @@ class DialogEntityRegistryDetail extends LitElement { this._params = undefined; } } - private _disabledByChanged(ev: PolymerChangedEvent): void { - this._disabledBy = ev.detail.value ? null : "user"; + private _disabledByChanged(ev: Event): void { + this._disabledBy = (ev.target as HaSwitch).checked ? null : "user"; } static get styles(): CSSResult[] { diff --git a/src/panels/lovelace/components/hui-entities-toggle.ts b/src/panels/lovelace/components/hui-entities-toggle.ts index 2d5feeaa8b..8c9c601e62 100644 --- a/src/panels/lovelace/components/hui-entities-toggle.ts +++ b/src/panels/lovelace/components/hui-entities-toggle.ts @@ -8,8 +8,11 @@ import { css, CSSResult, } from "lit-element"; -import { PaperToggleButtonElement } from "@polymer/paper-toggle-button/paper-toggle-button"; +import "../../../components/ha-switch"; + +// tslint:disable-next-line: no-duplicate-imports +import { HaSwitch } from "../../../components/ha-switch"; import { DOMAINS_TOGGLE } from "../../../common/const"; import { turnOnOffEntities } from "../common/entity/turn-on-off-entities"; import { HomeAssistant } from "../../../types"; @@ -40,14 +43,14 @@ class HuiEntitiesToggle extends LitElement { } return html` - + > `; } @@ -57,9 +60,7 @@ class HuiEntitiesToggle extends LitElement { width: 38px; display: block; } - paper-toggle-button { - cursor: pointer; - --paper-toggle-button-label-spacing: 0; + ha-switch { padding: 13px 5px; margin: -4px -5px; } @@ -68,7 +69,7 @@ class HuiEntitiesToggle extends LitElement { private _callService(ev: MouseEvent): void { forwardHaptic("light"); - const turnOn = (ev.target as PaperToggleButtonElement).checked; + const turnOn = (ev.target as HaSwitch).checked; turnOnOffEntities(this.hass!, this._toggleEntities!, turnOn!); } } diff --git a/src/panels/lovelace/components/hui-image.ts b/src/panels/lovelace/components/hui-image.ts index 35be160e27..b2785b31c9 100644 --- a/src/panels/lovelace/components/hui-image.ts +++ b/src/panels/lovelace/components/hui-image.ts @@ -1,5 +1,3 @@ -import "@polymer/paper-toggle-button/paper-toggle-button"; - import { STATES_OFF } from "../../../common/const"; import parseAspectRatio from "../../../common/util/parse-aspect-ratio"; diff --git a/src/panels/lovelace/editor/config-elements/config-elements-style.ts b/src/panels/lovelace/editor/config-elements/config-elements-style.ts index f153988b27..01b7b1672a 100644 --- a/src/panels/lovelace/editor/config-elements/config-elements-style.ts +++ b/src/panels/lovelace/editor/config-elements/config-elements-style.ts @@ -2,7 +2,7 @@ import { html } from "lit-element"; export const configElementStyle = html` - - `; - } - - static get properties() { - return { - hass: Object, - hassInfo: Object, - error: String, - }; - } - - ready() { - super.ready(); - this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev)); - } - - apiCalled(ev) { - if (ev.detail.success) { - this.errors = null; - return; - } - - const response = ev.detail.response; - - if (typeof response.body === "object") { - this.errors = response.body.message || "Unknown error"; - } else { - this.errors = response.body; - } - } - - computeUpdateAvailable(hassInfo) { - return hassInfo.version !== hassInfo.last_version; - } - - computeReleaseNotesUrl(version) { - return `https://${ - version.includes("b") ? "rc" : "www" - }.home-assistant.io/latest-release-notes/`; - } -} - -customElements.define("hassio-hass-update", HassioHassUpdate); diff --git a/hassio/src/dashboard/hassio-update.ts b/hassio/src/dashboard/hassio-update.ts new file mode 100644 index 0000000000..07b532cbae --- /dev/null +++ b/hassio/src/dashboard/hassio-update.ts @@ -0,0 +1,153 @@ +import { + LitElement, + TemplateResult, + html, + CSSResult, + css, + property, + customElement, +} from "lit-element"; + +import { HomeAssistant } from "../../../src/types"; +import { + HassioHomeAssistantInfo, + HassioHassOSInfo, + HassioSupervisorInfo, +} from "../../../src/data/hassio"; + +import { hassioStyle } from "../resources/hassio-style"; + +import "@material/mwc-button"; +import "@polymer/paper-card/paper-card"; +import "../../../src/components/buttons/ha-call-api-button"; +import "../components/hassio-card-content"; + +@customElement("hassio-update") +export class HassioUpdate extends LitElement { + @property() public hass!: HomeAssistant; + + @property() public hassInfo: HassioHomeAssistantInfo; + @property() public hassOsInfo?: HassioHassOSInfo; + @property() public supervisorInfo: HassioSupervisorInfo; + + @property() public error?: string; + + protected render(): TemplateResult | void { + if ( + this.hassInfo.version === this.hassInfo.last_version && + this.supervisorInfo.version === this.supervisorInfo.last_version && + (!this.hassOsInfo || + this.hassOsInfo.version === this.hassOsInfo.version_latest) + ) { + return html``; + } + + return html` +
+ ${this.error + ? html` +
Error: ${this.error}
+ ` + : ""} +
+ ${this._renderUpdateCard( + "Home Assistant", + this.hassInfo.version, + this.hassInfo.last_version, + "hassio/homeassistant/update", + `https://${ + this.hassInfo.last_version.includes("b") ? "rc" : "www" + }.home-assistant.io/latest-release-notes/` + )} + ${this._renderUpdateCard( + "Hass.io Supervisor", + this.supervisorInfo.version, + this.supervisorInfo.last_version, + "hassio/supervisor/update", + `https://github.com//home-assistant/hassio/releases/tag/${ + this.supervisorInfo.last_version + }` + )} + ${this.hassOsInfo + ? this._renderUpdateCard( + "HassOS", + this.hassOsInfo.version, + this.hassOsInfo.version_latest, + "hassio/hassos/update", + `https://github.com//home-assistant/hassos/releases/tag/${ + this.hassOsInfo.version_latest + }` + ) + : ""} +
+
+ `; + } + + private _renderUpdateCard( + name: string, + curVersion: string, + lastVersion: string, + apiPath: string, + releaseNotesUrl: string + ): TemplateResult { + if (lastVersion === curVersion) { + return html``; + } + return html` + +
+ ${name} ${lastVersion} is available and you are currently running + ${name} ${curVersion}. +
+
+ + Update + + + Release notes + +
+
+ `; + } + + private _apiCalled(ev) { + if (ev.detail.success) { + this.error = ""; + return; + } + + const response = ev.detail.response; + + typeof response.body === "object" + ? (this.error = response.body.message || "Unknown error") + : (this.error = response.body); + } + + static get styles(): CSSResult[] { + return [ + hassioStyle, + css` + :host { + width: 33%; + } + paper-card { + display: inline-block; + margin-bottom: 32px; + } + .errors { + color: var(--google-red-500); + padding: 16px; + } + a { + text-decoration: none; + } + `, + ]; + } +} diff --git a/hassio/src/hassio-main.ts b/hassio/src/hassio-main.ts index 0d030a5479..29966015f5 100644 --- a/hassio/src/hassio-main.ts +++ b/hassio/src/hassio-main.ts @@ -13,9 +13,11 @@ import { HomeAssistant } from "../../src/types"; import { fetchHassioSupervisorInfo, fetchHassioHostInfo, + fetchHassioHassOsInfo, fetchHassioHomeAssistantInfo, HassioSupervisorInfo, HassioHostInfo, + HassioHassOSInfo, HassioHomeAssistantInfo, fetchHassioAddonInfo, createHassioSession, @@ -66,6 +68,7 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) { @property() private _supervisorInfo: HassioSupervisorInfo; @property() private _hostInfo: HassioHostInfo; + @property() private _hassOsInfo?: HassioHassOSInfo; @property() private _hassInfo: HassioHomeAssistantInfo; protected firstUpdated(changedProps: PropertyValues) { @@ -113,6 +116,7 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) { supervisorInfo: this._supervisorInfo, hostInfo: this._hostInfo, hassInfo: this._hassInfo, + hassOsInfo: this._hassOsInfo, route, }); } else { @@ -121,6 +125,7 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) { el.supervisorInfo = this._supervisorInfo; el.hostInfo = this._hostInfo; el.hassInfo = this._hassInfo; + el.hassOsInfo = this._hassOsInfo; el.route = route; } } @@ -139,6 +144,10 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) { this._supervisorInfo = supervisorInfo; this._hostInfo = hostInfo; this._hassInfo = hassInfo; + + if (this._hostInfo.features && this._hostInfo.features.includes("hassos")) { + this._hassOsInfo = await fetchHassioHassOsInfo(this.hass); + } } private async _redirectIngress(addonSlug: string) { diff --git a/hassio/src/hassio-pages-with-tabs.ts b/hassio/src/hassio-pages-with-tabs.ts index 018fd2f4d3..fad59ec5d9 100644 --- a/hassio/src/hassio-pages-with-tabs.ts +++ b/hassio/src/hassio-pages-with-tabs.ts @@ -27,6 +27,7 @@ import { HassioSupervisorInfo, HassioHostInfo, HassioHomeAssistantInfo, + HassioHassOSInfo, } from "../../src/data/hassio"; const HAS_REFRESH_BUTTON = ["store", "snapshots"]; @@ -39,6 +40,7 @@ class HassioPagesWithTabs extends LitElement { @property() public supervisorInfo!: HassioSupervisorInfo; @property() public hostInfo!: HassioHostInfo; @property() public hassInfo!: HassioHomeAssistantInfo; + @property() public hassOsInfo!: HassioHassOSInfo; protected render(): TemplateResult | void { const page = this._page; @@ -79,6 +81,7 @@ class HassioPagesWithTabs extends LitElement { .supervisorInfo=${this.supervisorInfo} .hostInfo=${this.hostInfo} .hassInfo=${this.hassInfo} + .hassOsInfo=${this.hassOsInfo} > `; diff --git a/hassio/src/hassio-tabs-router.ts b/hassio/src/hassio-tabs-router.ts index 53f9b16def..a90a683fc0 100644 --- a/hassio/src/hassio-tabs-router.ts +++ b/hassio/src/hassio-tabs-router.ts @@ -15,6 +15,7 @@ import { HassioSupervisorInfo, HassioHostInfo, HassioHomeAssistantInfo, + HassioHassOSInfo, } from "../../src/data/hassio"; @customElement("hassio-tabs-router") @@ -23,6 +24,7 @@ class HassioTabsRouter extends HassRouterPage { @property() public supervisorInfo: HassioSupervisorInfo; @property() public hostInfo: HassioHostInfo; @property() public hassInfo: HassioHomeAssistantInfo; + @property() public hassOsInfo!: HassioHassOSInfo; protected routerOptions: RouterOptions = { routes: { @@ -49,12 +51,14 @@ class HassioTabsRouter extends HassRouterPage { supervisorInfo: this.supervisorInfo, hostInfo: this.hostInfo, hassInfo: this.hassInfo, + hassOsInfo: this.hassOsInfo, }); } else { el.hass = this.hass; el.supervisorInfo = this.supervisorInfo; el.hostInfo = this.hostInfo; el.hassInfo = this.hassInfo; + el.hassOsInfo = this.hassOsInfo; } } } diff --git a/hassio/src/system/hassio-host-info.js b/hassio/src/system/hassio-host-info.js index 73d22c1c1c..e64d2a83dc 100644 --- a/hassio/src/system/hassio-host-info.js +++ b/hassio/src/system/hassio-host-info.js @@ -107,7 +107,7 @@ class HassioHostInfo extends EventsMixin(PolymerElement) { >Import from USB -