From 70072786a1f5cb9a2955bebd8c2d3bd94adee158 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 7 Apr 2019 11:58:51 -0700 Subject: [PATCH] Clean up hassio tabs page (#3068) * Clean up hassio tabs page * Make load optional * Fix bug --- hassio/src/hassio-main.ts | 14 ++- hassio/src/hassio-pages-with-tabs.js | 129 ----------------------- hassio/src/hassio-pages-with-tabs.ts | 126 ++++++++++++++++++++++ hassio/src/hassio-tabs-router.ts | 60 +++++++++++ hassio/src/snapshots/hassio-snapshots.js | 6 ++ src/layouts/hass-router-page.ts | 23 ++-- 6 files changed, 211 insertions(+), 147 deletions(-) delete mode 100644 hassio/src/hassio-pages-with-tabs.js create mode 100644 hassio/src/hassio-pages-with-tabs.ts create mode 100644 hassio/src/hassio-tabs-router.ts diff --git a/hassio/src/hassio-main.ts b/hassio/src/hassio-main.ts index 448d2bc61c..e57ce9d180 100644 --- a/hassio/src/hassio-main.ts +++ b/hassio/src/hassio-main.ts @@ -16,6 +16,8 @@ import { } from "../../src/data/hassio"; import { makeDialogManager } from "../../src/dialogs/make-dialog-manager"; import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin"; +// Don't codesplit it, that way the dashboard always loads fast. +import "./hassio-pages-with-tabs"; @customElement("hassio-main") class HassioMain extends ProvideHassLitMixin(HassRouterPage) { @@ -25,10 +27,10 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) { // Hass.io has a page with tabs, so we route all non-matching routes to it. defaultPage: "dashboard", initialLoad: () => this._fetchData(), + showLoading: true, routes: { dashboard: { tag: "hassio-pages-with-tabs", - load: () => import("./hassio-pages-with-tabs"), cache: true, }, snapshots: "dashboard", @@ -82,6 +84,10 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) { } protected updatePageEl(el) { + // the tabs page does its own routing so needs full route. + const route = + el.nodeName === "HASSIO-PAGES-WITH-TABS" ? this.route : this.routeTail; + if ("setProperties" in el) { // As long as we have Polymer pages (el as PolymerElement).setProperties({ @@ -89,16 +95,14 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) { supervisorInfo: this._supervisorInfo, hostInfo: this._hostInfo, hassInfo: this._hassInfo, - // @ts-ignore not fighting TS today - route: this.routeTail, + route, }); } else { el.hass = this.hass; el.supervisorInfo = this._supervisorInfo; el.hostInfo = this._hostInfo; el.hassInfo = this._hassInfo; - // @ts-ignore not fighting TS today - el.route = this.routeTail; + el.route = route; } } diff --git a/hassio/src/hassio-pages-with-tabs.js b/hassio/src/hassio-pages-with-tabs.js deleted file mode 100644 index ddb1f379f2..0000000000 --- a/hassio/src/hassio-pages-with-tabs.js +++ /dev/null @@ -1,129 +0,0 @@ -import "@polymer/app-layout/app-header-layout/app-header-layout"; -import "@polymer/app-layout/app-header/app-header"; -import "@polymer/app-layout/app-toolbar/app-toolbar"; -import "@polymer/paper-icon-button/paper-icon-button"; -import "@polymer/paper-tabs/paper-tab"; -import "@polymer/paper-tabs/paper-tabs"; -import { html } from "@polymer/polymer/lib/utils/html-tag"; -import { PolymerElement } from "@polymer/polymer/polymer-element"; - -import "../../src/components/ha-menu-button"; -import "../../src/resources/ha-style"; -import "./addon-store/hassio-addon-store"; -import "./dashboard/hassio-dashboard"; -import "./snapshots/hassio-snapshots"; -import "./system/hassio-system"; - -import scrollToTarget from "../../src/common/dom/scroll-to-target"; - -import NavigateMixin from "../../src/mixins/navigate-mixin"; - -class HassioPagesWithTabs extends NavigateMixin(PolymerElement) { - static get template() { - return html` - - - - - -
Hass.io
- -
- - Dashboard - Snapshots - Add-on store - System - -
- - - - -
- `; - } - - static get properties() { - return { - hass: Object, - page: { - type: String, - computed: "_computePage(route)", - }, - route: Object, - supervisorInfo: Object, - hostInfo: Object, - hassInfo: Object, - }; - } - - handlePageSelected(ev) { - const newPage = ev.detail.item.getAttribute("page-name"); - if (newPage !== this.page) { - this.navigate(`/hassio/${newPage}`); - } - scrollToTarget(this, this.$.layout.header.scrollTarget); - } - - equals(a, b) { - return a === b; - } - - showRefreshButton(page) { - return page === "store" || page === "snapshots"; - } - - refreshClicked() { - if (this.page === "snapshots") { - this.shadowRoot.querySelector("hassio-snapshots").refreshData(); - } else { - this.shadowRoot.querySelector("hassio-addon-store").refreshData(); - } - } - - _computePage(route) { - return route.prefix.substr(route.prefix.indexOf("/", 1) + 1); - } -} - -customElements.define("hassio-pages-with-tabs", HassioPagesWithTabs); diff --git a/hassio/src/hassio-pages-with-tabs.ts b/hassio/src/hassio-pages-with-tabs.ts new file mode 100644 index 0000000000..9e33d12c27 --- /dev/null +++ b/hassio/src/hassio-pages-with-tabs.ts @@ -0,0 +1,126 @@ +import { + LitElement, + TemplateResult, + html, + CSSResultArray, + css, + customElement, + property, +} from "lit-element"; +import "@polymer/app-layout/app-header-layout/app-header-layout"; +import "@polymer/app-layout/app-header/app-header"; +import "@polymer/app-layout/app-toolbar/app-toolbar"; +import "@polymer/paper-icon-button/paper-icon-button"; +import "@polymer/paper-tabs/paper-tab"; +import "@polymer/paper-tabs/paper-tabs"; + +import "../../src/components/ha-menu-button"; +import "../../src/resources/ha-style"; +import "./hassio-tabs-router"; + +import scrollToTarget from "../../src/common/dom/scroll-to-target"; + +import { haStyle } from "../../src/resources/styles"; +import { HomeAssistant, Route } from "../../src/types"; +import { navigate } from "../../src/common/navigate"; + +const HAS_REFRESH_BUTTON = ["store", "snapshots"]; + +@customElement("hassio-pages-with-tabs") +class HassioPagesWithTabs extends LitElement { + @property() public hass!: HomeAssistant; + @property() public route!: Route; + @property() public supervisorInfo!: any; + @property() public hostInfo!: any; + @property() public hassInfo!: any; + + protected render(): TemplateResult | void { + const page = this._page; + return html` + + + + +
Hass.io
+ ${HAS_REFRESH_BUTTON.includes(page) + ? html` + + ` + : undefined} +
+ + Dashboard + Snapshots + Add-on store + System + +
+ +
+ `; + } + + private handlePageSelected(ev) { + const newPage = ev.detail.item.getAttribute("page-name"); + if (newPage !== this._page) { + navigate(this, `/hassio/${newPage}`); + } + + scrollToTarget( + this, + // @ts-ignore + this.shadowRoot!.querySelector("app-header-layout").header.scrollTarget + ); + } + + private refreshClicked() { + if (this._page === "snapshots") { + // @ts-ignore + this.shadowRoot.querySelector("hassio-snapshots").refreshData(); + } else { + // @ts-ignore + this.shadowRoot.querySelector("hassio-addon-store").refreshData(); + } + } + + private get _page() { + return this.route.path.substr(1); + } + + static get styles(): CSSResultArray { + return [ + haStyle, + css` + :host { + color: var(--primary-text-color); + --paper-card-header-color: var(--primary-text-color); + } + paper-tabs { + margin-left: 12px; + --paper-tabs-selection-bar-color: #fff; + text-transform: uppercase; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hassio-pages-with-tabs": HassioPagesWithTabs; + } +} diff --git a/hassio/src/hassio-tabs-router.ts b/hassio/src/hassio-tabs-router.ts new file mode 100644 index 0000000000..11f8d12710 --- /dev/null +++ b/hassio/src/hassio-tabs-router.ts @@ -0,0 +1,60 @@ +import { + HassRouterPage, + RouterOptions, +} from "../../src/layouts/hass-router-page"; +import { customElement, property } from "lit-element"; +import { PolymerElement } from "@polymer/polymer"; +import { HomeAssistant } from "../../src/types"; +// Don't codesplit it, that way the dashboard always loads fast. +import "./dashboard/hassio-dashboard"; + +@customElement("hassio-tabs-router") +class HassioTabsRouter extends HassRouterPage { + @property() public hass!: HomeAssistant; + @property() public supervisorInfo: any; + @property() public hostInfo: any; + @property() public hassInfo: any; + + protected routerOptions: RouterOptions = { + routes: { + dashboard: { + tag: "hassio-dashboard", + }, + snapshots: { + tag: "hassio-snapshots", + load: () => import("./snapshots/hassio-snapshots"), + }, + store: { + tag: "hassio-addon-store", + load: () => import("./addon-store/hassio-addon-store"), + }, + system: { + tag: "hassio-system", + load: () => import("./system/hassio-system"), + }, + }, + }; + + protected updatePageEl(el) { + if ("setProperties" in el) { + // As long as we have Polymer pages + (el as PolymerElement).setProperties({ + hass: this.hass, + supervisorInfo: this.supervisorInfo, + hostInfo: this.hostInfo, + hassInfo: this.hassInfo, + }); + } else { + el.hass = this.hass; + el.supervisorInfo = this.supervisorInfo; + el.hostInfo = this.hostInfo; + el.hassInfo = this.hassInfo; + } + } +} + +declare global { + interface HTMLElementTagNameMap { + "hassio-tabs-router": HassioTabsRouter; + } +} diff --git a/hassio/src/snapshots/hassio-snapshots.js b/hassio/src/snapshots/hassio-snapshots.js index c1771fb93f..2ea513b4a7 100644 --- a/hassio/src/snapshots/hassio-snapshots.js +++ b/hassio/src/snapshots/hassio-snapshots.js @@ -152,8 +152,10 @@ class HassioSnapshots extends EventsMixin(PolymerElement) { type: Array, value: [], }, + supervisorInfo: Object, installedAddons: { type: Array, + computed: "_computeAddons(supervisorInfo)", observer: "_installedAddonsChanged", }, addonList: Array, @@ -305,6 +307,10 @@ class HassioSnapshots extends EventsMixin(PolymerElement) { this._updateSnapshots(); }); } + + _computeAddons(supervisorInfo) { + return supervisorInfo.addons; + } } customElements.define("hassio-snapshots", HassioSnapshots); diff --git a/src/layouts/hass-router-page.ts b/src/layouts/hass-router-page.ts index efcc71dc62..2cd6b3873a 100644 --- a/src/layouts/hass-router-page.ts +++ b/src/layouts/hass-router-page.ts @@ -19,7 +19,7 @@ export interface RouteOptions { // HTML tag of the route page. tag: string; // Function to load the page. - load: () => Promise; + load?: () => Promise; cache?: boolean; } @@ -48,13 +48,6 @@ export class HassRouterPage extends UpdatingElement { protected routerOptions!: RouterOptions; - /** - * 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 = {}; @@ -91,13 +84,15 @@ export class HassRouterPage extends UpdatingElement { } const route = this.route; - const defaultPage = routerOptions.defaultPage || ""; + const defaultPage = routerOptions.defaultPage; - if (route && route.path === "") { + if (route && route.path === "" && defaultPage !== undefined) { navigate(this, `${route.prefix}/${defaultPage}`, true); } - let newPage = route ? extractPage(route.path, defaultPage) : "not_found"; + let newPage = route + ? extractPage(route.path, defaultPage || "") + : "not_found"; let routeOptions = routerOptions.routes[newPage]; // Handle redirects @@ -122,7 +117,9 @@ export class HassRouterPage extends UpdatingElement { } this._currentPage = newPage; - const loadProm = routeOptions.load(); + const loadProm = routeOptions.load + ? routeOptions.load() + : Promise.resolve(); // Check when loading the page source failed. loadProm.catch(() => { @@ -196,7 +193,7 @@ export class HassRouterPage extends UpdatingElement { if (options.preloadAll) { Object.values(options.routes).forEach( - (route) => typeof route === "object" && route.load() + (route) => typeof route === "object" && route.load && route.load() ); }