mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-28 11:46:42 +00:00
Convert cloud dashboard to use Lit router (#3223)
This commit is contained in:
parent
e595637a10
commit
b2b18cb814
@ -34,6 +34,9 @@ export interface RouterOptions {
|
|||||||
showLoading?: boolean;
|
showLoading?: boolean;
|
||||||
// Promise that resolves when the initial data is loaded which is needed to show any route.
|
// Promise that resolves when the initial data is loaded which is needed to show any route.
|
||||||
initialLoad?: () => Promise<unknown>;
|
initialLoad?: () => Promise<unknown>;
|
||||||
|
// Hook that is called before rendering a new route. Allowing redirects.
|
||||||
|
// If string returned, that page will be rendered instead.
|
||||||
|
beforeRender?: (page: string) => string | undefined;
|
||||||
routes: {
|
routes: {
|
||||||
// If it's a string, it is another route whose options should be adopted.
|
// If it's a string, it is another route whose options should be adopted.
|
||||||
[route: string]: RouteOptions | string;
|
[route: string]: RouteOptions | string;
|
||||||
@ -48,7 +51,7 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
|
|
||||||
protected routerOptions!: RouterOptions;
|
protected routerOptions!: RouterOptions;
|
||||||
|
|
||||||
private _currentPage = "";
|
protected _currentPage = "";
|
||||||
private _currentLoadProm?: Promise<void>;
|
private _currentLoadProm?: Promise<void>;
|
||||||
private _cache = {};
|
private _cache = {};
|
||||||
private _initialLoadDone = false;
|
private _initialLoadDone = false;
|
||||||
@ -101,6 +104,25 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
routeOptions = routerOptions.routes[newPage];
|
routeOptions = routerOptions.routes[newPage];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (routerOptions.beforeRender) {
|
||||||
|
const result = routerOptions.beforeRender(newPage);
|
||||||
|
if (result !== undefined) {
|
||||||
|
newPage = result;
|
||||||
|
routeOptions = routerOptions.routes[newPage];
|
||||||
|
|
||||||
|
// Handle redirects
|
||||||
|
while (typeof routeOptions === "string") {
|
||||||
|
newPage = routeOptions;
|
||||||
|
routeOptions = routerOptions.routes[newPage];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the url if we know where we're mounted.
|
||||||
|
if (route) {
|
||||||
|
navigate(this, `${route.prefix}/${result}`, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this._currentPage === newPage) {
|
if (this._currentPage === newPage) {
|
||||||
if (this.lastChild) {
|
if (this.lastChild) {
|
||||||
this.updatePageEl(this.lastChild, changedProps);
|
this.updatePageEl(this.lastChild, changedProps);
|
||||||
@ -245,6 +267,10 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
return this.updateComplete.then(() => this._currentLoadProm);
|
return this.updateComplete.then(() => this._currentLoadProm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected createElement(tag: string) {
|
||||||
|
return document.createElement(tag);
|
||||||
|
}
|
||||||
|
|
||||||
protected updatePageEl(_pageEl, _changedProps?: PropertyValues) {
|
protected updatePageEl(_pageEl, _changedProps?: PropertyValues) {
|
||||||
// default we do nothing
|
// default we do nothing
|
||||||
}
|
}
|
||||||
@ -262,8 +288,7 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
this.removeChild(this.lastChild);
|
this.removeChild(this.lastChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
const panelEl =
|
const panelEl = this._cache[page] || this.createElement(routeOptions.tag);
|
||||||
this._cache[page] || document.createElement(routeOptions.tag);
|
|
||||||
this.updatePageEl(panelEl);
|
this.updatePageEl(panelEl);
|
||||||
this.appendChild(panelEl);
|
this.appendChild(panelEl);
|
||||||
|
|
||||||
|
@ -1,145 +0,0 @@
|
|||||||
import "@polymer/app-route/app-route";
|
|
||||||
import { timeOut } from "@polymer/polymer/lib/utils/async";
|
|
||||||
import { Debouncer } from "@polymer/polymer/lib/utils/debounce";
|
|
||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|
||||||
|
|
||||||
import "../ha-config-section";
|
|
||||||
import "./ha-config-cloud-account";
|
|
||||||
import "./ha-config-cloud-forgot-password";
|
|
||||||
import "./ha-config-cloud-login";
|
|
||||||
import "./ha-config-cloud-register";
|
|
||||||
import NavigateMixin from "../../../mixins/navigate-mixin";
|
|
||||||
|
|
||||||
const LOGGED_IN_URLS = ["/account"];
|
|
||||||
const NOT_LOGGED_IN_URLS = ["/login", "/register", "/forgot-password"];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @appliesMixin NavigateMixin
|
|
||||||
*/
|
|
||||||
class HaConfigCloud extends NavigateMixin(PolymerElement) {
|
|
||||||
static get template() {
|
|
||||||
return html`
|
|
||||||
<app-route
|
|
||||||
route="[[route]]"
|
|
||||||
pattern="/:page"
|
|
||||||
data="{{_routeData}}"
|
|
||||||
tail="{{_routeTail}}"
|
|
||||||
></app-route>
|
|
||||||
|
|
||||||
<template
|
|
||||||
is="dom-if"
|
|
||||||
if='[[_equals(_routeData.page, "account")]]'
|
|
||||||
restamp=""
|
|
||||||
>
|
|
||||||
<ha-config-cloud-account
|
|
||||||
hass="[[hass]]"
|
|
||||||
cloud-status="[[cloudStatus]]"
|
|
||||||
is-wide="[[isWide]]"
|
|
||||||
></ha-config-cloud-account>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template
|
|
||||||
is="dom-if"
|
|
||||||
if='[[_equals(_routeData.page, "login")]]'
|
|
||||||
restamp=""
|
|
||||||
>
|
|
||||||
<ha-config-cloud-login
|
|
||||||
page-name="login"
|
|
||||||
hass="[[hass]]"
|
|
||||||
is-wide="[[isWide]]"
|
|
||||||
email="{{_loginEmail}}"
|
|
||||||
flash-message="{{_flashMessage}}"
|
|
||||||
></ha-config-cloud-login>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template
|
|
||||||
is="dom-if"
|
|
||||||
if='[[_equals(_routeData.page, "register")]]'
|
|
||||||
restamp=""
|
|
||||||
>
|
|
||||||
<ha-config-cloud-register
|
|
||||||
page-name="register"
|
|
||||||
hass="[[hass]]"
|
|
||||||
is-wide="[[isWide]]"
|
|
||||||
email="{{_loginEmail}}"
|
|
||||||
></ha-config-cloud-register>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template
|
|
||||||
is="dom-if"
|
|
||||||
if='[[_equals(_routeData.page, "forgot-password")]]'
|
|
||||||
restamp=""
|
|
||||||
>
|
|
||||||
<ha-config-cloud-forgot-password
|
|
||||||
page-name="forgot-password"
|
|
||||||
hass="[[hass]]"
|
|
||||||
email="{{_loginEmail}}"
|
|
||||||
></ha-config-cloud-forgot-password>
|
|
||||||
</template>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
isWide: Boolean,
|
|
||||||
loadingAccount: {
|
|
||||||
type: Boolean,
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
cloudStatus: {
|
|
||||||
type: Object,
|
|
||||||
},
|
|
||||||
_flashMessage: {
|
|
||||||
type: String,
|
|
||||||
value: "",
|
|
||||||
},
|
|
||||||
|
|
||||||
route: Object,
|
|
||||||
|
|
||||||
_routeData: Object,
|
|
||||||
_routeTail: Object,
|
|
||||||
_loginEmail: String,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static get observers() {
|
|
||||||
return ["_checkRoute(route, cloudStatus)"];
|
|
||||||
}
|
|
||||||
|
|
||||||
ready() {
|
|
||||||
super.ready();
|
|
||||||
this.addEventListener("cloud-done", (ev) => {
|
|
||||||
this._flashMessage = ev.detail.flashMessage;
|
|
||||||
this.navigate("/config/cloud/login");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_checkRoute(route) {
|
|
||||||
this._debouncer = Debouncer.debounce(
|
|
||||||
this._debouncer,
|
|
||||||
timeOut.after(0),
|
|
||||||
() => {
|
|
||||||
if (
|
|
||||||
!this.cloudStatus ||
|
|
||||||
(!this.cloudStatus.logged_in &&
|
|
||||||
!NOT_LOGGED_IN_URLS.includes(route.path))
|
|
||||||
) {
|
|
||||||
this.navigate("/config/cloud/login", true);
|
|
||||||
} else if (
|
|
||||||
this.cloudStatus.logged_in &&
|
|
||||||
!LOGGED_IN_URLS.includes(route.path)
|
|
||||||
) {
|
|
||||||
this.navigate("/config/cloud/account", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_equals(a, b) {
|
|
||||||
return a === b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define("ha-config-cloud", HaConfigCloud);
|
|
134
src/panels/config/cloud/ha-config-cloud.ts
Normal file
134
src/panels/config/cloud/ha-config-cloud.ts
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import "./ha-config-cloud-account";
|
||||||
|
import "./ha-config-cloud-login";
|
||||||
|
import {
|
||||||
|
HassRouterPage,
|
||||||
|
RouterOptions,
|
||||||
|
} from "../../../layouts/hass-router-page";
|
||||||
|
import { property, customElement } from "lit-element";
|
||||||
|
import { HomeAssistant, Route } from "../../../types";
|
||||||
|
import { navigate } from "../../../common/navigate";
|
||||||
|
import { CloudStatus } from "../../../data/cloud";
|
||||||
|
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||||
|
import { PolymerElement } from "@polymer/polymer";
|
||||||
|
|
||||||
|
const LOGGED_IN_URLS = ["account"];
|
||||||
|
const NOT_LOGGED_IN_URLS = ["login", "register", "forgot-password"];
|
||||||
|
|
||||||
|
@customElement("ha-config-cloud")
|
||||||
|
class HaConfigCloud extends HassRouterPage {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
@property() public isWide!: boolean;
|
||||||
|
@property() public route!: Route;
|
||||||
|
@property() public cloudStatus!: CloudStatus;
|
||||||
|
|
||||||
|
protected routerOptions: RouterOptions = {
|
||||||
|
defaultPage: "login",
|
||||||
|
showLoading: true,
|
||||||
|
initialLoad: () => this._cloudStatusLoaded,
|
||||||
|
// Guard the different pages based on if we're logged in.
|
||||||
|
beforeRender: (page: string) => {
|
||||||
|
if (this.cloudStatus.logged_in) {
|
||||||
|
if (!LOGGED_IN_URLS.includes(page)) {
|
||||||
|
return "account";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!NOT_LOGGED_IN_URLS.includes(page)) {
|
||||||
|
return "login";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
login: {
|
||||||
|
tag: "ha-config-cloud-login",
|
||||||
|
},
|
||||||
|
register: {
|
||||||
|
tag: "ha-config-cloud-register",
|
||||||
|
load: () => import("./ha-config-cloud-register"),
|
||||||
|
},
|
||||||
|
"forgot-password": {
|
||||||
|
tag: "ha-config-cloud-forgot-password",
|
||||||
|
load: () => import("./ha-config-cloud-forgot-password"),
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
tag: "ha-config-cloud-account",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
@property() private _flashMessage = "";
|
||||||
|
@property() private _loginEmail = "";
|
||||||
|
private _resolveCloudStatusLoaded!: () => void;
|
||||||
|
private _cloudStatusLoaded = new Promise((resolve) => {
|
||||||
|
this._resolveCloudStatusLoaded = resolve;
|
||||||
|
});
|
||||||
|
|
||||||
|
protected firstUpdated(changedProps) {
|
||||||
|
super.firstUpdated(changedProps);
|
||||||
|
this.addEventListener("cloud-done", (ev) => {
|
||||||
|
this._flashMessage = (ev as any).detail.flashMessage;
|
||||||
|
navigate(this, "/config/cloud/login");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updated(changedProps) {
|
||||||
|
super.updated(changedProps);
|
||||||
|
|
||||||
|
if (changedProps.has("cloudStatus")) {
|
||||||
|
const oldStatus = changedProps.get("cloudStatus") as
|
||||||
|
| CloudStatus
|
||||||
|
| undefined;
|
||||||
|
if (oldStatus === undefined) {
|
||||||
|
this._resolveCloudStatusLoaded();
|
||||||
|
} else if (oldStatus.logged_in !== this.cloudStatus.logged_in) {
|
||||||
|
navigate(this, this.route.prefix, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected createElement(tag: string) {
|
||||||
|
const el = super.createElement(tag);
|
||||||
|
el.addEventListener("email-changed", (ev) => {
|
||||||
|
this._loginEmail = (ev as PolymerChangedEvent<string>).detail.value;
|
||||||
|
});
|
||||||
|
el.addEventListener("flash-message-changed", (ev) => {
|
||||||
|
this._flashMessage = (ev as PolymerChangedEvent<string>).detail.value;
|
||||||
|
});
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updatePageEl(el) {
|
||||||
|
// We are not going to update if the current page if we are not logged in
|
||||||
|
// and the current page requires being logged in. Happens when we log out.
|
||||||
|
if (
|
||||||
|
this.cloudStatus &&
|
||||||
|
!this.cloudStatus.logged_in &&
|
||||||
|
LOGGED_IN_URLS.includes(this._currentPage)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("setProperties" in el) {
|
||||||
|
// As long as we have Polymer pages
|
||||||
|
(el as PolymerElement).setProperties({
|
||||||
|
hass: this.hass,
|
||||||
|
email: this._loginEmail,
|
||||||
|
isWide: this.isWide,
|
||||||
|
cloudStatus: this.cloudStatus,
|
||||||
|
flashMessage: this._flashMessage,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
el.hass = this.hass;
|
||||||
|
el.email = this._loginEmail;
|
||||||
|
el.isWide = this.isWide;
|
||||||
|
el.cloudStatus = this.cloudStatus;
|
||||||
|
el.flashMessage = this._flashMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-config-cloud": HaConfigCloud;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user