mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-22 00:36:34 +00:00
Clean up hassio tabs page (#3068)
* Clean up hassio tabs page * Make load optional * Fix bug
This commit is contained in:
parent
cda29fcd07
commit
70072786a1
@ -16,6 +16,8 @@ import {
|
|||||||
} from "../../src/data/hassio";
|
} from "../../src/data/hassio";
|
||||||
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
|
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
|
||||||
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
|
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")
|
@customElement("hassio-main")
|
||||||
class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
|
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.
|
// Hass.io has a page with tabs, so we route all non-matching routes to it.
|
||||||
defaultPage: "dashboard",
|
defaultPage: "dashboard",
|
||||||
initialLoad: () => this._fetchData(),
|
initialLoad: () => this._fetchData(),
|
||||||
|
showLoading: true,
|
||||||
routes: {
|
routes: {
|
||||||
dashboard: {
|
dashboard: {
|
||||||
tag: "hassio-pages-with-tabs",
|
tag: "hassio-pages-with-tabs",
|
||||||
load: () => import("./hassio-pages-with-tabs"),
|
|
||||||
cache: true,
|
cache: true,
|
||||||
},
|
},
|
||||||
snapshots: "dashboard",
|
snapshots: "dashboard",
|
||||||
@ -82,6 +84,10 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected updatePageEl(el) {
|
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) {
|
if ("setProperties" in el) {
|
||||||
// As long as we have Polymer pages
|
// As long as we have Polymer pages
|
||||||
(el as PolymerElement).setProperties({
|
(el as PolymerElement).setProperties({
|
||||||
@ -89,16 +95,14 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
|
|||||||
supervisorInfo: this._supervisorInfo,
|
supervisorInfo: this._supervisorInfo,
|
||||||
hostInfo: this._hostInfo,
|
hostInfo: this._hostInfo,
|
||||||
hassInfo: this._hassInfo,
|
hassInfo: this._hassInfo,
|
||||||
// @ts-ignore not fighting TS today
|
route,
|
||||||
route: this.routeTail,
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
el.hass = this.hass;
|
el.hass = this.hass;
|
||||||
el.supervisorInfo = this._supervisorInfo;
|
el.supervisorInfo = this._supervisorInfo;
|
||||||
el.hostInfo = this._hostInfo;
|
el.hostInfo = this._hostInfo;
|
||||||
el.hassInfo = this._hassInfo;
|
el.hassInfo = this._hassInfo;
|
||||||
// @ts-ignore not fighting TS today
|
el.route = route;
|
||||||
el.route = this.routeTail;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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`
|
|
||||||
<style include="iron-flex iron-positioning ha-style">
|
|
||||||
: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;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<app-header-layout id="layout" has-scrolling-region>
|
|
||||||
<app-header fixed slot="header">
|
|
||||||
<app-toolbar>
|
|
||||||
<ha-menu-button hassio></ha-menu-button>
|
|
||||||
<div main-title>Hass.io</div>
|
|
||||||
<template is="dom-if" if="[[showRefreshButton(page)]]">
|
|
||||||
<paper-icon-button
|
|
||||||
icon="hassio:refresh"
|
|
||||||
on-click="refreshClicked"
|
|
||||||
></paper-icon-button>
|
|
||||||
</template>
|
|
||||||
</app-toolbar>
|
|
||||||
<paper-tabs
|
|
||||||
scrollable=""
|
|
||||||
selected="[[page]]"
|
|
||||||
attr-for-selected="page-name"
|
|
||||||
on-iron-activate="handlePageSelected"
|
|
||||||
>
|
|
||||||
<paper-tab page-name="dashboard">Dashboard</paper-tab>
|
|
||||||
<paper-tab page-name="snapshots">Snapshots</paper-tab>
|
|
||||||
<paper-tab page-name="store">Add-on store</paper-tab>
|
|
||||||
<paper-tab page-name="system">System</paper-tab>
|
|
||||||
</paper-tabs>
|
|
||||||
</app-header>
|
|
||||||
<template is="dom-if" if='[[equals(page, "dashboard")]]'>
|
|
||||||
<hassio-dashboard
|
|
||||||
hass="[[hass]]"
|
|
||||||
supervisor-info="[[supervisorInfo]]"
|
|
||||||
hass-info="[[hassInfo]]"
|
|
||||||
></hassio-dashboard>
|
|
||||||
</template>
|
|
||||||
<template is="dom-if" if='[[equals(page, "snapshots")]]'>
|
|
||||||
<hassio-snapshots
|
|
||||||
hass="[[hass]]"
|
|
||||||
installed-addons="[[supervisorInfo.addons]]"
|
|
||||||
></hassio-snapshots>
|
|
||||||
</template>
|
|
||||||
<template is="dom-if" if='[[equals(page, "store")]]'>
|
|
||||||
<hassio-addon-store hass="[[hass]]"></hassio-addon-store>
|
|
||||||
</template>
|
|
||||||
<template is="dom-if" if='[[equals(page, "system")]]'>
|
|
||||||
<hassio-system
|
|
||||||
hass="[[hass]]"
|
|
||||||
supervisor-info="[[supervisorInfo]]"
|
|
||||||
host-info="[[hostInfo]]"
|
|
||||||
></hassio-system>
|
|
||||||
</template>
|
|
||||||
</app-header-layout>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
126
hassio/src/hassio-pages-with-tabs.ts
Normal file
126
hassio/src/hassio-pages-with-tabs.ts
Normal file
@ -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`
|
||||||
|
<app-header-layout has-scrolling-region>
|
||||||
|
<app-header fixed slot="header">
|
||||||
|
<app-toolbar>
|
||||||
|
<ha-menu-button hassio></ha-menu-button>
|
||||||
|
<div main-title>Hass.io</div>
|
||||||
|
${HAS_REFRESH_BUTTON.includes(page)
|
||||||
|
? html`
|
||||||
|
<paper-icon-button
|
||||||
|
icon="hassio:refresh"
|
||||||
|
@click=${this.refreshClicked}
|
||||||
|
></paper-icon-button>
|
||||||
|
`
|
||||||
|
: undefined}
|
||||||
|
</app-toolbar>
|
||||||
|
<paper-tabs
|
||||||
|
scrollable
|
||||||
|
attr-for-selected="page-name"
|
||||||
|
.selected=${page}
|
||||||
|
@iron-activate=${this.handlePageSelected}
|
||||||
|
>
|
||||||
|
<paper-tab page-name="dashboard">Dashboard</paper-tab>
|
||||||
|
<paper-tab page-name="snapshots">Snapshots</paper-tab>
|
||||||
|
<paper-tab page-name="store">Add-on store</paper-tab>
|
||||||
|
<paper-tab page-name="system">System</paper-tab>
|
||||||
|
</paper-tabs>
|
||||||
|
</app-header>
|
||||||
|
<hassio-tabs-router
|
||||||
|
.route=${this.route}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.supervisorInfo=${this.supervisorInfo}
|
||||||
|
.hostInfo=${this.hostInfo}
|
||||||
|
.hassInfo=${this.hassInfo}
|
||||||
|
></hassio-tabs-router>
|
||||||
|
</app-header-layout>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
60
hassio/src/hassio-tabs-router.ts
Normal file
60
hassio/src/hassio-tabs-router.ts
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -152,8 +152,10 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
|
|||||||
type: Array,
|
type: Array,
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
supervisorInfo: Object,
|
||||||
installedAddons: {
|
installedAddons: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
computed: "_computeAddons(supervisorInfo)",
|
||||||
observer: "_installedAddonsChanged",
|
observer: "_installedAddonsChanged",
|
||||||
},
|
},
|
||||||
addonList: Array,
|
addonList: Array,
|
||||||
@ -305,6 +307,10 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
|
|||||||
this._updateSnapshots();
|
this._updateSnapshots();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_computeAddons(supervisorInfo) {
|
||||||
|
return supervisorInfo.addons;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("hassio-snapshots", HassioSnapshots);
|
customElements.define("hassio-snapshots", HassioSnapshots);
|
||||||
|
@ -19,7 +19,7 @@ export interface RouteOptions {
|
|||||||
// HTML tag of the route page.
|
// HTML tag of the route page.
|
||||||
tag: string;
|
tag: string;
|
||||||
// Function to load the page.
|
// Function to load the page.
|
||||||
load: () => Promise<unknown>;
|
load?: () => Promise<unknown>;
|
||||||
cache?: boolean;
|
cache?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,13 +48,6 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
|
|
||||||
protected routerOptions!: RouterOptions;
|
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 _currentPage = "";
|
||||||
private _currentLoadProm?: Promise<void>;
|
private _currentLoadProm?: Promise<void>;
|
||||||
private _cache = {};
|
private _cache = {};
|
||||||
@ -91,13 +84,15 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const route = this.route;
|
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);
|
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];
|
let routeOptions = routerOptions.routes[newPage];
|
||||||
|
|
||||||
// Handle redirects
|
// Handle redirects
|
||||||
@ -122,7 +117,9 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._currentPage = newPage;
|
this._currentPage = newPage;
|
||||||
const loadProm = routeOptions.load();
|
const loadProm = routeOptions.load
|
||||||
|
? routeOptions.load()
|
||||||
|
: Promise.resolve();
|
||||||
|
|
||||||
// Check when loading the page source failed.
|
// Check when loading the page source failed.
|
||||||
loadProm.catch(() => {
|
loadProm.catch(() => {
|
||||||
@ -196,7 +193,7 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
|
|
||||||
if (options.preloadAll) {
|
if (options.preloadAll) {
|
||||||
Object.values(options.routes).forEach(
|
Object.values(options.routes).forEach(
|
||||||
(route) => typeof route === "object" && route.load()
|
(route) => typeof route === "object" && route.load && route.load()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user