From 7aa296e774fc314b55d2e4ba95f8275ff8e35b95 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 15 Mar 2019 22:43:19 -0700 Subject: [PATCH 1/7] move cert info to a dialog (#2940) --- src/data/cloud.ts | 2 +- src/panels/config/cloud/cloud-remote-pref.ts | 63 +++++-------- .../config/cloud/dialog-cloud-certificate.ts | 89 +++++++++++++++++++ .../cloud/show-dialog-cloud-certificate.ts | 18 ++++ 4 files changed, 128 insertions(+), 44 deletions(-) create mode 100644 src/panels/config/cloud/dialog-cloud-certificate.ts create mode 100644 src/panels/config/cloud/show-dialog-cloud-certificate.ts diff --git a/src/data/cloud.ts b/src/data/cloud.ts index b15f8b3066..674d07b2af 100644 --- a/src/data/cloud.ts +++ b/src/data/cloud.ts @@ -11,7 +11,7 @@ interface CloudStatusBase { cloud: "disconnected" | "connecting" | "connected"; } -interface CertificateInformation { +export interface CertificateInformation { common_name: string; expire_date: string; fingerprint: string; diff --git a/src/panels/config/cloud/cloud-remote-pref.ts b/src/panels/config/cloud/cloud-remote-pref.ts index ee79d3f7db..07a747cdb1 100644 --- a/src/panels/config/cloud/cloud-remote-pref.ts +++ b/src/panels/config/cloud/cloud-remote-pref.ts @@ -13,7 +13,6 @@ 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/buttons/ha-call-api-button"; import { fireEvent } from "../../../common/dom/fire_event"; import { HomeAssistant } from "../../../types"; @@ -22,7 +21,7 @@ import { disconnectCloudRemote, CloudStatusLoggedIn, } from "../../../data/cloud"; -import format_date_time from "../../../common/datetime/format_date_time"; +import { showCloudCertificateDialog } from "./show-dialog-cloud-certificate"; @customElement("cloud-remote-pref") export class CloudRemotePref extends LitElement { @@ -64,46 +63,36 @@ export class CloudRemotePref extends LitElement { @change="${this._toggleChanged}" >
- Home Assistant Cloud provides you with a secure remote connection to - your instance while away from home. Your instance + Home Assistant Cloud provides a secure remote connection to your + instance while away from home. Your instance ${remote_connected ? "is" : "will be"} available at https://${remote_domain}. - ${!remote_certificate - ? "" - : html` -
- - Certificate expiration date -
Will be automatically renewed
-
-
- ${format_date_time( - new Date(remote_certificate.expire_date), - this.hass!.language - )} -
-
-
- - Certificate fingerprint - -
- ${remote_certificate.fingerprint} -
-
- `}
Learn how it works + ${remote_certificate + ? html` +
+ + Certificate Info + + ` + : ""}
`; } + private _openCertInfo() { + showCloudCertificateDialog(this, { + certificateInfo: this.cloudStatus!.remote_certificate!, + }); + } + private async _toggleChanged(ev) { const toggle = ev.target as PaperToggleButtonElement; @@ -127,12 +116,6 @@ export class CloudRemotePref extends LitElement { .preparing { padding: 0 16px 16px; } - .data-row { - display: flex; - } - .data-value { - padding: 16px 0; - } a { color: var(--primary-color); } @@ -141,17 +124,11 @@ export class CloudRemotePref extends LitElement { right: 8px; top: 16px; } - ha-call-api-button { - color: var(--primary-color); - font-weight: 500; - } - .unlock { + .card-actions { display: flex; - flex-direction: row; - padding-top: 16px; } - .unlock > div { - flex: 1; + .spacer { + flex-grow: 1; } `; } diff --git a/src/panels/config/cloud/dialog-cloud-certificate.ts b/src/panels/config/cloud/dialog-cloud-certificate.ts new file mode 100644 index 0000000000..a5d86e81e0 --- /dev/null +++ b/src/panels/config/cloud/dialog-cloud-certificate.ts @@ -0,0 +1,89 @@ +import { + html, + LitElement, + css, + CSSResult, + customElement, + property, +} from "lit-element"; + +import "@material/mwc-button"; +import "@polymer/paper-dialog/paper-dialog"; +// This is not a duplicate import, one is for types, one is for element. +// tslint:disable-next-line +import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog"; + +import { HomeAssistant } from "../../../types"; +import { haStyle } from "../../../resources/styles"; +import { CloudCertificateParams as CloudCertificateDialogParams } from "./show-dialog-cloud-certificate"; +import format_date_time from "../../../common/datetime/format_date_time"; + +@customElement("dialog-cloud-certificate") +class DialogCloudCertificate extends LitElement { + public hass!: HomeAssistant; + + @property() + private _params?: CloudCertificateDialogParams; + + public async showDialog(params: CloudCertificateDialogParams) { + this._params = params; + // Wait till dialog is rendered. + await this.updateComplete; + this._dialog.open(); + } + + protected render() { + if (!this._params) { + return html``; + } + const { certificateInfo } = this._params; + + return html` + +

Certificate Information

+
+

+ Certificate expiration date: + ${format_date_time( + new Date(certificateInfo.expire_date), + this.hass!.language + )}
+ (Will be automatically renewed) +

+

+ Certificate fingerprint: ${certificateInfo.fingerprint} +

+
+ +
+ CLOSE +
+
+ `; + } + + private get _dialog(): PaperDialogElement { + return this.shadowRoot!.querySelector("paper-dialog")!; + } + + private _closeDialog() { + this._dialog.close(); + } + + static get styles(): CSSResult[] { + return [ + haStyle, + css` + paper-dialog { + width: 535px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "dialog-cloud-certificate": DialogCloudCertificate; + } +} diff --git a/src/panels/config/cloud/show-dialog-cloud-certificate.ts b/src/panels/config/cloud/show-dialog-cloud-certificate.ts new file mode 100644 index 0000000000..d1d085c4ca --- /dev/null +++ b/src/panels/config/cloud/show-dialog-cloud-certificate.ts @@ -0,0 +1,18 @@ +import { fireEvent } from "../../../common/dom/fire_event"; +import { CertificateInformation } from "../../../data/cloud"; + +export interface CloudCertificateParams { + certificateInfo: CertificateInformation; +} + +export const showCloudCertificateDialog = ( + element: HTMLElement, + webhookDialogParams: CloudCertificateParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "dialog-cloud-certificate", + dialogImport: () => + import(/* webpackChunkName: "dialog-cloud-certificate" */ "./dialog-cloud-certificate"), + dialogParams: webhookDialogParams, + }); +}; From 68909c80ffa37f42bbe68e23ce33a724f3ad7416 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 15 Mar 2019 22:43:27 -0700 Subject: [PATCH 2/7] Hide entity config option for user group (#2941) --- src/dialogs/ha-more-info-dialog.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/dialogs/ha-more-info-dialog.js b/src/dialogs/ha-more-info-dialog.js index 6a07e4e650..c5f1a4c54f 100644 --- a/src/dialogs/ha-more-info-dialog.js +++ b/src/dialogs/ha-more-info-dialog.js @@ -176,14 +176,16 @@ class HaMoreInfoDialog extends DialogMixin(PolymerElement) { return; } - try { - const info = await this.hass.callWS({ - type: "config/entity_registry/get", - entity_id: newVal.entity_id, - }); - this._registryInfo = info; - } catch (err) { - this._registryInfo = null; + if (this.hass.user.is_admin) { + try { + const info = await this.hass.callWS({ + type: "config/entity_registry/get", + entity_id: newVal.entity_id, + }); + this._registryInfo = info; + } catch (err) { + this._registryInfo = null; + } } } From 117ea325869322b66a5cfddd07df86b9607c00bb Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Sat, 16 Mar 2019 01:10:34 -0500 Subject: [PATCH 3/7] Fix markdown style (#2944) --- src/panels/lovelace/cards/hui-markdown-card.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/panels/lovelace/cards/hui-markdown-card.ts b/src/panels/lovelace/cards/hui-markdown-card.ts index da62878edd..9f66d23952 100644 --- a/src/panels/lovelace/cards/hui-markdown-card.ts +++ b/src/panels/lovelace/cards/hui-markdown-card.ts @@ -65,14 +65,13 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { static get styles(): CSSResult { return css` :host { - /* start paper-font-headline style */ + /* start paper-font-body1 style */ font-family: "Roboto", "Noto", sans-serif; -webkit-font-smoothing: antialiased; /* OS X subpixel AA bleed bug */ - text-rendering: optimizeLegibility; - font-size: 24px; + font-size: 14px; font-weight: 400; - letter-spacing: -0.012em; - /* end paper-font-headline style */ + line-height: 20px; + /* end paper-font-body1 style */ } ha-markdown { display: block; From 2d75e797c78f38d223d28c12f6748cbdbcbfaecf Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 15 Mar 2019 23:10:50 -0700 Subject: [PATCH 4/7] Hide service toast in the demo (#2942) * Hide service toast in the demo * Update provide_hass.ts --- src/fake_data/provide_hass.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/fake_data/provide_hass.ts b/src/fake_data/provide_hass.ts index 0adf94c8c9..1d065688a0 100644 --- a/src/fake_data/provide_hass.ts +++ b/src/fake_data/provide_hass.ts @@ -1,4 +1,3 @@ -import { fireEvent } from "../common/dom/fire_event"; import applyThemesOnElement from "../common/dom/apply_themes_on_element"; import { demoConfig } from "./demo_config"; @@ -146,9 +145,6 @@ export const provideHass = ( dockedSidebar: false, moreInfoEntityId: null as any, async callService(domain, service, data) { - fireEvent(elements[0], "hass-notification", { - message: `Called service ${domain}/${service}`, - }); if (data && "entity_id" in data) { await Promise.all( ensureArray(data.entity_id).map((ent) => From 23ca1b972dd0a3bddb500f7f46f38c77c46e0cc3 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 15 Mar 2019 23:15:16 -0700 Subject: [PATCH 5/7] Fix router (#2943) * Fix router * Fix demo * Extract update routes * Lint --- demo/public/index.html | 3 +- src/html/index.html.template | 2 +- src/layouts/app/home-assistant.ts | 2 +- src/layouts/hass-loading-screen.ts | 4 +- src/layouts/hass-router-page.ts | 115 ++++++++----- src/layouts/partial-panel-resolver.ts | 203 +++++++++++------------ src/panels/config/ha-panel-config.ts | 11 +- src/panels/lovelace/ha-panel-lovelace.ts | 2 +- 8 files changed, 183 insertions(+), 159 deletions(-) diff --git a/demo/public/index.html b/demo/public/index.html index a685e87125..5a9e3e49a7 100644 --- a/demo/public/index.html +++ b/demo/public/index.html @@ -96,7 +96,8 @@ -
+
+ +
-
<% if (!latestBuild) { %> diff --git a/src/layouts/app/home-assistant.ts b/src/layouts/app/home-assistant.ts index 62529ef38b..fe7307f8d9 100644 --- a/src/layouts/app/home-assistant.ts +++ b/src/layouts/app/home-assistant.ts @@ -54,7 +54,7 @@ export class HomeAssistantAppEl extends ext(HassBaseMixin(LitElement), [ > ${this._panelUrl === undefined || this._route === undefined ? "" - : hass && hass.states && hass.config && hass.panels && hass.services + : hass && hass.states && hass.config && hass.services ? html` - ${this.isRoot + ${this.rootnav ? html` ` diff --git a/src/layouts/hass-router-page.ts b/src/layouts/hass-router-page.ts index b46119c0e3..3d5cab0d09 100644 --- a/src/layouts/hass-router-page.ts +++ b/src/layouts/hass-router-page.ts @@ -13,14 +13,13 @@ const extractPage = (path: string, defaultPage: string) => { : path.substr(1, subpathStart - 1); }; -interface RouteOptions { +export interface RouteOptions { tag: string; load: () => Promise; cache?: boolean; } export interface RouterOptions { - isRoot?: boolean; defaultPage?: string; preloadAll?: boolean; cacheAll?: boolean; @@ -34,17 +33,19 @@ export interface RouterOptions { const LOADING_SCREEN_THRESHOLD = 400; // ms export class HassRouterPage extends UpdatingElement { - protected static routerOptions: RouterOptions = { routes: {} }; + @property() public route?: Route; - protected static finalize() { - super.finalize(); - this._routerOptions = this.routerOptions; - } + protected routerOptions!: RouterOptions; - private static _routerOptions: RouterOptions; - - @property() public route!: Route; + /** + * Optional variable to define extra routes dynamically. + * It is preferred to use static routes. + */ + protected extraRoutes?: { + [route: string]: RouteOptions; + }; private _currentPage = ""; + private _currentLoadProm?: Promise; private _cache = {}; protected update(changedProps: PropertyValues) { @@ -52,15 +53,13 @@ export class HassRouterPage extends UpdatingElement { if (!changedProps.has("route")) { if (this.lastChild) { - this._updatePageEl(this.lastChild, changedProps); + this.updatePageEl(this.lastChild, changedProps); } return; } const route = this.route; - - const routerOptions = (this.constructor as typeof HassRouterPage) - ._routerOptions; + const routerOptions = this.routerOptions || { routes: {} }; const defaultPage = routerOptions.defaultPage || ""; if (route && route.path === "") { @@ -71,22 +70,22 @@ export class HassRouterPage extends UpdatingElement { if (this._currentPage === newPage) { if (this.lastChild) { - this._updatePageEl(this.lastChild, changedProps); + this.updatePageEl(this.lastChild, changedProps); + } + return; + } + + const routeOptions = routerOptions.routes[newPage]; + + if (!routeOptions) { + this._currentPage = ""; + if (this.lastChild) { + this.removeChild(this.lastChild); } return; } this._currentPage = newPage; - - const routeOptions = routerOptions.routes[newPage]; - - if (!routeOptions) { - if (this.lastChild) { - this._updatePageEl(this.lastChild, changedProps); - } - return; - } - const loadProm = routeOptions.load(); // Check when loading the page source failed. @@ -125,35 +124,69 @@ export class HassRouterPage extends UpdatingElement { if (this.lastChild) { this.removeChild(this.lastChild); } - - const loadingEl = document.createElement("hass-loading-screen"); - loadingEl.isRoot = routerOptions.isRoot; - this.appendChild(loadingEl); + this.appendChild(this.createLoadingScreen()); }, LOADING_SCREEN_THRESHOLD); - loadProm.then(() => { - // Check if we're still trying to show the same page. - if (this._currentPage !== newPage) { - return; - } + this._currentLoadProm = loadProm.then( + () => { + this._currentLoadProm = undefined; + // Check if we're still trying to show the same page. + if (this._currentPage !== newPage) { + return; + } - created = true; - this._createPanel(routerOptions, newPage, routeOptions); - }); + created = true; + this._createPanel(routerOptions, newPage, routeOptions); + }, + () => { + this._currentLoadProm = undefined; + } + ); } protected firstUpdated(changedProps: PropertyValues) { super.firstUpdated(changedProps); - const options = (this.constructor as typeof HassRouterPage)._routerOptions; + const options = this.routerOptions; - if (options.preloadAll) { + if (options && options.preloadAll) { Object.values(options.routes).forEach((route) => route.load()); return; } } - protected _updatePageEl(_pageEl, _changedProps?: PropertyValues) { + protected createLoadingScreen() { + return document.createElement("hass-loading-screen"); + } + + /** + * Rebuild the current panel. + * + * Promise will resolve when rebuilding is done and DOM updated. + */ + protected async rebuild(): Promise { + const oldRoute = this.route; + + if (oldRoute === undefined) { + return; + } + + this.route = undefined; + await this.updateComplete; + // Make sure that the parent didn't override this in the meanwhile. + if (this.route === undefined) { + this.route = oldRoute; + } + } + + /** + * Promise that resolves when the page has rendered. + */ + protected get pageRendered(): Promise { + return this.updateComplete.then(() => this._currentLoadProm); + } + + protected updatePageEl(_pageEl, _changedProps?: PropertyValues) { // default we do nothing } @@ -168,7 +201,7 @@ export class HassRouterPage extends UpdatingElement { const panelEl = this._cache[page] || document.createElement(routeOptions.tag); - this._updatePageEl(panelEl); + this.updatePageEl(panelEl); this.appendChild(panelEl); if (routerOptions.cacheAll || routeOptions.cache) { diff --git a/src/layouts/partial-panel-resolver.ts b/src/layouts/partial-panel-resolver.ts index 7d5628fe82..0693e4b1f7 100644 --- a/src/layouts/partial-panel-resolver.ts +++ b/src/layouts/partial-panel-resolver.ts @@ -1,118 +1,96 @@ -import { property, customElement } from "lit-element"; +import { property, customElement, PropertyValues } from "lit-element"; import { PolymerElement } from "@polymer/polymer"; -import { HomeAssistant } from "../types"; -import { HassRouterPage, RouterOptions } from "./hass-router-page"; +import { HomeAssistant, Panels } from "../types"; +import { + HassRouterPage, + RouterOptions, + RouteOptions, +} from "./hass-router-page"; + +const CACHE_COMPONENTS = ["lovelace", "states"]; +const COMPONENTS = { + calendar: () => + import(/* webpackChunkName: "panel-calendar" */ "../panels/calendar/ha-panel-calendar"), + config: () => + import(/* webpackChunkName: "panel-config" */ "../panels/config/ha-panel-config"), + custom: () => + import(/* webpackChunkName: "panel-custom" */ "../panels/custom/ha-panel-custom"), + "dev-event": () => + import(/* webpackChunkName: "panel-dev-event" */ "../panels/dev-event/ha-panel-dev-event"), + "dev-info": () => + import(/* webpackChunkName: "panel-dev-info" */ "../panels/dev-info/ha-panel-dev-info"), + "dev-mqtt": () => + import(/* webpackChunkName: "panel-dev-mqtt" */ "../panels/dev-mqtt/ha-panel-dev-mqtt"), + "dev-service": () => + import(/* webpackChunkName: "panel-dev-service" */ "../panels/dev-service/ha-panel-dev-service"), + "dev-state": () => + import(/* webpackChunkName: "panel-dev-state" */ "../panels/dev-state/ha-panel-dev-state"), + "dev-template": () => + import(/* webpackChunkName: "panel-dev-template" */ "../panels/dev-template/ha-panel-dev-template"), + lovelace: () => + import(/* webpackChunkName: "panel-lovelace" */ "../panels/lovelace/ha-panel-lovelace"), + states: () => + import(/* webpackChunkName: "panel-states" */ "../panels/states/ha-panel-states"), + history: () => + import(/* webpackChunkName: "panel-history" */ "../panels/history/ha-panel-history"), + iframe: () => + import(/* webpackChunkName: "panel-iframe" */ "../panels/iframe/ha-panel-iframe"), + kiosk: () => + import(/* webpackChunkName: "panel-kiosk" */ "../panels/kiosk/ha-panel-kiosk"), + logbook: () => + import(/* webpackChunkName: "panel-logbook" */ "../panels/logbook/ha-panel-logbook"), + mailbox: () => + import(/* webpackChunkName: "panel-mailbox" */ "../panels/mailbox/ha-panel-mailbox"), + map: () => + import(/* webpackChunkName: "panel-map" */ "../panels/map/ha-panel-map"), + profile: () => + import(/* webpackChunkName: "panel-profile" */ "../panels/profile/ha-panel-profile"), + "shopping-list": () => + import(/* webpackChunkName: "panel-shopping-list" */ "../panels/shopping-list/ha-panel-shopping-list"), +}; + +const getRoutes = (panels: Panels): RouterOptions => { + const routes: { [route: string]: RouteOptions } = {}; + + Object.values(panels).forEach((panel) => { + routes[panel.url_path] = { + load: COMPONENTS[panel.component_name], + tag: `ha-panel-${panel.component_name}`, + cache: CACHE_COMPONENTS.includes(panel.component_name), + }; + }); + + return { + showLoading: true, + routes, + }; +}; @customElement("partial-panel-resolver") class PartialPanelResolver extends HassRouterPage { - protected static routerOptions: RouterOptions = { - isRoot: true, - showLoading: true, - routes: { - calendar: { - tag: "ha-panel-calendar", - load: () => - import(/* webpackChunkName: "panel-calendar" */ "../panels/calendar/ha-panel-calendar"), - }, - config: { - tag: "ha-panel-config", - load: () => - import(/* webpackChunkName: "panel-config" */ "../panels/config/ha-panel-config"), - }, - custom: { - tag: "ha-panel-custom", - load: () => - import(/* webpackChunkName: "panel-custom" */ "../panels/custom/ha-panel-custom"), - }, - "dev-event": { - tag: "ha-panel-dev-event", - load: () => - import(/* webpackChunkName: "panel-dev-event" */ "../panels/dev-event/ha-panel-dev-event"), - }, - "dev-info": { - tag: "ha-panel-dev-info", - load: () => - import(/* webpackChunkName: "panel-dev-info" */ "../panels/dev-info/ha-panel-dev-info"), - }, - "dev-mqtt": { - tag: "ha-panel-dev-mqtt", - load: () => - import(/* webpackChunkName: "panel-dev-mqtt" */ "../panels/dev-mqtt/ha-panel-dev-mqtt"), - }, - "dev-service": { - tag: "ha-panel-dev-service", - load: () => - import(/* webpackChunkName: "panel-dev-service" */ "../panels/dev-service/ha-panel-dev-service"), - }, - "dev-state": { - tag: "ha-panel-dev-state", - load: () => - import(/* webpackChunkName: "panel-dev-state" */ "../panels/dev-state/ha-panel-dev-state"), - }, - "dev-template": { - tag: "ha-panel-dev-template", - load: () => - import(/* webpackChunkName: "panel-dev-template" */ "../panels/dev-template/ha-panel-dev-template"), - }, - lovelace: { - cache: true, - tag: "ha-panel-lovelace", - load: () => - import(/* webpackChunkName: "panel-lovelace" */ "../panels/lovelace/ha-panel-lovelace"), - }, - states: { - cache: true, - tag: "ha-panel-states", - load: () => - import(/* webpackChunkName: "panel-states" */ "../panels/states/ha-panel-states"), - }, - history: { - tag: "ha-panel-history", - load: () => - import(/* webpackChunkName: "panel-history" */ "../panels/history/ha-panel-history"), - }, - iframe: { - tag: "ha-panel-iframe", - load: () => - import(/* webpackChunkName: "panel-iframe" */ "../panels/iframe/ha-panel-iframe"), - }, - kiosk: { - tag: "ha-panel-kiosk", - load: () => - import(/* webpackChunkName: "panel-kiosk" */ "../panels/kiosk/ha-panel-kiosk"), - }, - logbook: { - tag: "ha-panel-logbook", - load: () => - import(/* webpackChunkName: "panel-logbook" */ "../panels/logbook/ha-panel-logbook"), - }, - mailbox: { - tag: "ha-panel-mailbox", - load: () => - import(/* webpackChunkName: "panel-mailbox" */ "../panels/mailbox/ha-panel-mailbox"), - }, - map: { - tag: "ha-panel-map", - load: () => - import(/* webpackChunkName: "panel-map" */ "../panels/map/ha-panel-map"), - }, - profile: { - tag: "ha-panel-profile", - load: () => - import(/* webpackChunkName: "panel-profile" */ "../panels/profile/ha-panel-profile"), - }, - "shopping-list": { - tag: "ha-panel-shopping-list", - load: () => - import(/* webpackChunkName: "panel-shopping-list" */ "../panels/shopping-list/ha-panel-shopping-list"), - }, - }, - }; @property() public hass?: HomeAssistant; @property() public narrow?: boolean; - protected _updatePageEl(el) { + protected updated(changedProps: PropertyValues) { + if (!changedProps.has("hass")) { + return; + } + + const oldHass = changedProps.get("hass") as this["hass"]; + + if (!oldHass || oldHass.panels !== this.hass!.panels) { + this._updateRoutes(); + } + } + + protected createLoadingScreen() { + const el = super.createLoadingScreen(); + el.rootnav = true; + return el; + } + + protected updatePageEl(el) { const hass = this.hass!; if ("setProperties" in el) { @@ -130,6 +108,17 @@ class PartialPanelResolver extends HassRouterPage { el.panel = hass.panels[hass.panelUrl]; } } + + private async _updateRoutes() { + this.routerOptions = getRoutes(this.hass!.panels); + await this.rebuild(); + await this.pageRendered; + + const initEl = document.getElementById("ha-init-skeleton"); + if (initEl) { + initEl.parentElement!.removeChild(initEl); + } + } } declare global { diff --git a/src/panels/config/ha-panel-config.ts b/src/panels/config/ha-panel-config.ts index aad87ca75a..8fbb0629b3 100644 --- a/src/panels/config/ha-panel-config.ts +++ b/src/panels/config/ha-panel-config.ts @@ -8,7 +8,11 @@ import { HassRouterPage, RouterOptions } from "../../layouts/hass-router-page"; @customElement("ha-panel-config") class HaPanelConfig extends HassRouterPage { - protected static routerOptions: RouterOptions = { + @property() public hass!: HomeAssistant; + @property() public _wideSidebar: boolean = false; + @property() public _wide: boolean = false; + + protected routerOptions: RouterOptions = { defaultPage: "dashboard", cacheAll: true, preloadAll: true, @@ -81,9 +85,6 @@ class HaPanelConfig extends HassRouterPage { }, }; - @property() public hass!: HomeAssistant; - @property() public _wideSidebar: boolean = false; - @property() public _wide: boolean = false; @property() private _cloudStatus?: CloudStatus; private _listeners: Array<() => void> = []; @@ -119,7 +120,7 @@ class HaPanelConfig extends HassRouterPage { ); } - protected _updatePageEl(el) { + protected updatePageEl(el) { el.route = this.route; el.hass = this.hass; el.isWide = this.hass.dockedSidebar ? this._wideSidebar : this._wide; diff --git a/src/panels/lovelace/ha-panel-lovelace.ts b/src/panels/lovelace/ha-panel-lovelace.ts index 8bbb0389b9..d59ffaea9f 100644 --- a/src/panels/lovelace/ha-panel-lovelace.ts +++ b/src/panels/lovelace/ha-panel-lovelace.ts @@ -85,7 +85,7 @@ class LovelacePanel extends LitElement { } return html` - + `; } From baa13a1b6c5d2f227648cbcbc5d8cb4ccf1012f8 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 15 Mar 2019 23:16:00 -0700 Subject: [PATCH 6/7] Update translations --- translations/he.json | 18 ++++++++++++++---- translations/hu.json | 20 +++++++++++++++----- translations/ko.json | 18 ++++++++++++++---- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/translations/he.json b/translations/he.json index a5f52daa90..57bf0942dd 100644 --- a/translations/he.json +++ b/translations/he.json @@ -606,7 +606,8 @@ "caption": "ZHA", "description": "ניהול רשת Zigbee לאוטומציה ביתית", "services": { - "reconfigure": "התקן מחדש את התקן ה ZHA. השתמש באפשרות זו אם אתה נתקל בבעיות בהתקן. אם ההתקן המדובר הוא התקן המופעל באמצעות סוללות, ודא שהוא ער ויכול לקבל פקודות בעת שימוש בשירות זה." + "reconfigure": "התקן מחדש את התקן ה ZHA. השתמש באפשרות זו אם אתה נתקל בבעיות בהתקן. אם ההתקן המדובר הוא התקן המופעל באמצעות סוללות, ודא שהוא ער ויכול לקבל פקודות בעת שימוש בשירות זה.", + "updateDeviceName": "הגדר שם מותאם אישית עבור התקן זה במאגר ההתקנים." } }, "area_registry": { @@ -616,7 +617,9 @@ "header": "מאגר האזורים", "introduction": "אזורים משמשים לארגון המיקום של ההתקנים. Home Assistant יעשה שימוש במידע זה בכדי לסייע לך בארגון הממשק, ההרשאות והאינטגרציות שלך עם מערכות אחרות.", "introduction2": "כדי למקם התקנים באזור זה, השתמש בקישור הבא כדי לנווט אל דף האינטגרציות ולאחר מכן לחץ על אינטגרציה מוגדרת כדי להגיע לכרטיסי המכשיר.", - "integrations_page": "דף אינטגרציות" + "integrations_page": "דף אינטגרציות", + "no_areas": "נראה שאין לך אזורים עדיין!", + "create_area": "צור אזור" }, "no_areas": "נראה שעדיין אין אזורים!", "create_area": "צור איזור", @@ -830,11 +833,13 @@ "data": { "name": "שם", "username": "שם משתמש", - "password": "סיסמה" + "password": "סיסמה", + "password_confirm": "אשר סיסמה" }, "create_account": "צור חשבון", "error": { - "required_fields": "מלא את כל השדות הדרושים" + "required_fields": "מלא את כל השדות הדרושים", + "password_not_match": "הסיסמאות אינן תואמות" } } }, @@ -1156,5 +1161,10 @@ "auto": "Auto" } } + }, + "groups": { + "system-admin": "מנהלים", + "system-users": "משתמשים", + "system-read-only": "משתמשים לקריאה בלבד" } } \ No newline at end of file diff --git a/translations/hu.json b/translations/hu.json index cefa098e2e..eb38ab1e39 100644 --- a/translations/hu.json +++ b/translations/hu.json @@ -606,7 +606,8 @@ "caption": "ZHA", "description": "Zigbee Home Automation hálózat menedzsment", "services": { - "reconfigure": "A ZHA készülék újratelepítése (eszköz rendbehozatala). Ezt a funkciót használd, ha problémáid vannak a készülékkel. Ha a kérdéses eszköz akkumulátoros, győződj meg róla, hogy nincs alvó állapotban és fogadja a parancsokat, amikor ezt a szolgáltatást használod." + "reconfigure": "A ZHA készülék újratelepítése (eszköz rendbehozatala). Ezt a funkciót használd, ha problémáid vannak a készülékkel. Ha a kérdéses eszköz akkumulátoros, győződj meg róla, hogy nincs alvó állapotban és fogadja a parancsokat, amikor ezt a szolgáltatást használod.", + "updateDeviceName": "Egyedi név beállítása ehhez az eszközhöz az eszköz nyilvántartásban" } }, "area_registry": { @@ -616,9 +617,11 @@ "header": "Terület Nyilvántartás", "introduction": "A területekkel az eszközök elhelyezkedés szerint rendszerezhetők. Ezen információk felhasználásával a Home Assistant segíteni tud előkészíteni a felületet, a jogosultságokat és az integrációt más rendszerekkel.", "introduction2": "Az eszközök területekbe történő elhelyezéséhez használd az alábbi linket az integrációs oldalra való navigáláshoz, majd kattints egy konfigurált integrációra az eszközkártyák eléréséhez.", - "integrations_page": "Integrációk oldal" + "integrations_page": "Integrációk oldal", + "no_areas": "Úgy tűnik, nem hoztál még létre egy területet sem!", + "create_area": "TERÜLET LÉTREHOZÁSA" }, - "no_areas": "Úgy tűnik nem hoztál létre még egy területet sem!", + "no_areas": "Úgy tűnik, nem hoztál még létre egy területet sem!", "create_area": "TERÜLET LÉTREHOZÁSA", "editor": { "default_name": "Új Terület", @@ -830,11 +833,13 @@ "data": { "name": "Név", "username": "Felhasználónév", - "password": "Jelszó" + "password": "Jelszó", + "password_confirm": "Jelszó megerősítése" }, "create_account": "Fiók Létrehozása", "error": { - "required_fields": "Töltsd ki az összes szükséges mezőt" + "required_fields": "Töltsd ki az összes szükséges mezőt", + "password_not_match": "A jelszavak nem egyeznek" } } }, @@ -1156,5 +1161,10 @@ "auto": "Automatikus" } } + }, + "groups": { + "system-admin": "Adminisztrátorok", + "system-users": "Felhasználók", + "system-read-only": "Csak olvasható felhasználók" } } \ No newline at end of file diff --git a/translations/ko.json b/translations/ko.json index 0b9a632ddc..dc3482770f 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -606,7 +606,8 @@ "caption": "ZHA", "description": "Zigbee 홈 자동화 네트워크 관리", "services": { - "reconfigure": "ZHA 장치를 다시 구성 합니다. (장치 복구). 장치에 문제가 있는 경우 사용해주세요. 장치가 배터리로 작동하는 경우, 이 서비스를 사용할 때 장치가 켜져있고 통신이 가능한 상태인지 확인해주세요." + "reconfigure": "ZHA 장치를 다시 구성 합니다. (장치 복구). 장치에 문제가 있는 경우 사용해주세요. 장치가 배터리로 작동하는 경우, 이 서비스를 사용할 때 장치가 켜져있고 통신이 가능한 상태인지 확인해주세요.", + "updateDeviceName": "이 장치의 사용자 정의 이름을 장치 레지스트리에 설정합니다." } }, "area_registry": { @@ -616,7 +617,9 @@ "header": "영역 등록", "introduction": "영역은 장치가있는 위치를 구성하는데 사용합니다. 이 정보는 Home Assistant 의 인터페이스 정리, 권한 및 다른 시스템과의 통합 구성에 도움을 줍니다.", "introduction2": "특정 영역에 장치를 배치하려면 아래 링크를 따라 통합 구성요소 페이지로 이동 한 다음, 설정된 구성요소의 장치를 클릭하여 영역을 설정 할 수 있습니다.", - "integrations_page": "통합 구성요소 페이지" + "integrations_page": "통합 구성요소 페이지", + "no_areas": "등록된 영역이 없습니다. 거실, 침실과 같이 영역을 등록해보세요!", + "create_area": "영역 만들기" }, "no_areas": "등록된 영역이 없습니다. 거실, 침실과 같이 영역을 등록해보세요!", "create_area": "영역 만들기", @@ -830,11 +833,13 @@ "data": { "name": "이름", "username": "사용자 이름", - "password": "비밀번호" + "password": "비밀번호", + "password_confirm": "비밀번호 확인" }, "create_account": "계정 만들기", "error": { - "required_fields": "필수 입력란을 모두 채워주세요" + "required_fields": "필수 입력란을 모두 채워주세요", + "password_not_match": "비밀번호가 일치하지 않습니다" } } }, @@ -1156,5 +1161,10 @@ "auto": "자동" } } + }, + "groups": { + "system-admin": "관리자", + "system-users": "사용자", + "system-read-only": "읽기 전용 사용자" } } \ No newline at end of file From 27b61776e80d5fdd0bd0a1fb3b2de6abb9f04a93 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 15 Mar 2019 23:17:13 -0700 Subject: [PATCH 7/7] Bumped version to 20190315.1 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 192e35fb82..1d1156fb0a 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20190315.0", + version="20190315.1", description="The Home Assistant frontend", url="https://github.com/home-assistant/home-assistant-polymer", author="The Home Assistant Authors",