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()
);
}