mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 17:26:42 +00:00
Clean up hassio panel (#3067)
* Clean up hassio panel * Extract dialog manager code * Convert markdown dialog to show-dialog * Extract snapshot dialog
This commit is contained in:
parent
31e351c75c
commit
cda29fcd07
@ -12,6 +12,7 @@ import "../../../src/resources/ha-style";
|
|||||||
import EventsMixin from "../../../src/mixins/events-mixin";
|
import EventsMixin from "../../../src/mixins/events-mixin";
|
||||||
import { navigate } from "../../../src/common/navigate";
|
import { navigate } from "../../../src/common/navigate";
|
||||||
|
|
||||||
|
import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio-markdown";
|
||||||
import "../components/hassio-card-content";
|
import "../components/hassio-card-content";
|
||||||
|
|
||||||
const PERMIS_DESC = {
|
const PERMIS_DESC = {
|
||||||
@ -517,7 +518,7 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) {
|
|||||||
|
|
||||||
showMoreInfo(e) {
|
showMoreInfo(e) {
|
||||||
const id = e.target.getAttribute("id");
|
const id = e.target.getAttribute("id");
|
||||||
this.fire("hassio-markdown-dialog", {
|
showHassioMarkdownDialog(this, {
|
||||||
title: PERMIS_DESC[id].title,
|
title: PERMIS_DESC[id].title,
|
||||||
content: PERMIS_DESC[id].description,
|
content: PERMIS_DESC[id].description,
|
||||||
});
|
});
|
||||||
@ -528,7 +529,7 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) {
|
|||||||
.callApi("get", `hassio/addons/${this.addonSlug}/changelog`)
|
.callApi("get", `hassio/addons/${this.addonSlug}/changelog`)
|
||||||
.then((resp) => resp, () => "Error getting changelog")
|
.then((resp) => resp, () => "Error getting changelog")
|
||||||
.then((content) => {
|
.then((content) => {
|
||||||
this.fire("hassio-markdown-dialog", {
|
showHassioMarkdownDialog(this, {
|
||||||
title: "Changelog",
|
title: "Changelog",
|
||||||
content: content,
|
content: content,
|
||||||
});
|
});
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
import "@polymer/app-layout/app-header-layout/app-header-layout";
|
import "@polymer/app-layout/app-header-layout/app-header-layout";
|
||||||
import "@polymer/app-layout/app-header/app-header";
|
import "@polymer/app-layout/app-header/app-header";
|
||||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||||
import "@polymer/app-route/app-route";
|
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
|
||||||
import "../../../src/components/ha-menu-button";
|
|
||||||
import "../../../src/resources/ha-style";
|
import "../../../src/resources/ha-style";
|
||||||
import "../hassio-markdown-dialog";
|
|
||||||
import "./hassio-addon-audio";
|
import "./hassio-addon-audio";
|
||||||
import "./hassio-addon-config";
|
import "./hassio-addon-config";
|
||||||
import "./hassio-addon-info";
|
import "./hassio-addon-info";
|
||||||
@ -51,16 +48,9 @@ class HassioAddonView extends PolymerElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<app-route
|
|
||||||
route="[[route]]"
|
|
||||||
pattern="/addon/:slug"
|
|
||||||
data="{{routeData}}"
|
|
||||||
active="{{routeMatches}}"
|
|
||||||
></app-route>
|
|
||||||
<app-header-layout has-scrolling-region="">
|
<app-header-layout has-scrolling-region="">
|
||||||
<app-header fixed="" slot="header">
|
<app-header fixed="" slot="header">
|
||||||
<app-toolbar>
|
<app-toolbar>
|
||||||
<ha-menu-button hassio></ha-menu-button>
|
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon="hassio:arrow-left"
|
icon="hassio:arrow-left"
|
||||||
on-click="backTapped"
|
on-click="backTapped"
|
||||||
@ -72,14 +62,14 @@ class HassioAddonView extends PolymerElement {
|
|||||||
<hassio-addon-info
|
<hassio-addon-info
|
||||||
hass="[[hass]]"
|
hass="[[hass]]"
|
||||||
addon="[[addon]]"
|
addon="[[addon]]"
|
||||||
addon-slug="[[routeData.slug]]"
|
addon-slug="[[addonSlug]]"
|
||||||
></hassio-addon-info>
|
></hassio-addon-info>
|
||||||
|
|
||||||
<template is="dom-if" if="[[addon.version]]">
|
<template is="dom-if" if="[[addon.version]]">
|
||||||
<hassio-addon-config
|
<hassio-addon-config
|
||||||
hass="[[hass]]"
|
hass="[[hass]]"
|
||||||
addon="[[addon]]"
|
addon="[[addon]]"
|
||||||
addon-slug="[[routeData.slug]]"
|
addon-slug="[[addonSlug]]"
|
||||||
></hassio-addon-config>
|
></hassio-addon-config>
|
||||||
|
|
||||||
<template is="dom-if" if="[[addon.audio]]">
|
<template is="dom-if" if="[[addon.audio]]">
|
||||||
@ -93,50 +83,38 @@ class HassioAddonView extends PolymerElement {
|
|||||||
<hassio-addon-network
|
<hassio-addon-network
|
||||||
hass="[[hass]]"
|
hass="[[hass]]"
|
||||||
addon="[[addon]]"
|
addon="[[addon]]"
|
||||||
addon-slug="[[routeData.slug]]"
|
addon-slug="[[addonSlug]]"
|
||||||
></hassio-addon-network>
|
></hassio-addon-network>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<hassio-addon-logs
|
<hassio-addon-logs
|
||||||
hass="[[hass]]"
|
hass="[[hass]]"
|
||||||
addon-slug="[[routeData.slug]]"
|
addon-slug="[[addonSlug]]"
|
||||||
></hassio-addon-logs>
|
></hassio-addon-logs>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</app-header-layout>
|
</app-header-layout>
|
||||||
|
|
||||||
<hassio-markdown-dialog
|
|
||||||
title="[[markdownTitle]]"
|
|
||||||
content="[[markdownContent]]"
|
|
||||||
></hassio-markdown-dialog>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
hass: Object,
|
hass: Object,
|
||||||
route: Object,
|
route: {
|
||||||
routeData: {
|
|
||||||
type: Object,
|
type: Object,
|
||||||
observer: "routeDataChanged",
|
observer: "routeDataChanged",
|
||||||
},
|
},
|
||||||
routeMatches: Boolean,
|
addonSlug: {
|
||||||
addon: Object,
|
|
||||||
|
|
||||||
markdownTitle: String,
|
|
||||||
markdownContent: {
|
|
||||||
type: String,
|
type: String,
|
||||||
value: "",
|
computed: "_computeSlug(route)",
|
||||||
},
|
},
|
||||||
|
addon: Object,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ready() {
|
ready() {
|
||||||
super.ready();
|
super.ready();
|
||||||
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
|
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
|
||||||
this.addEventListener("hassio-markdown-dialog", (ev) =>
|
|
||||||
this.openMarkdown(ev)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apiCalled(ev) {
|
apiCalled(ev) {
|
||||||
@ -147,13 +125,13 @@ class HassioAddonView extends PolymerElement {
|
|||||||
if (path.substr(path.lastIndexOf("/") + 1) === "uninstall") {
|
if (path.substr(path.lastIndexOf("/") + 1) === "uninstall") {
|
||||||
this.backTapped();
|
this.backTapped();
|
||||||
} else {
|
} else {
|
||||||
this.routeDataChanged(this.routeData);
|
this.routeDataChanged(this.route);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
routeDataChanged(routeData) {
|
routeDataChanged(routeData) {
|
||||||
if (!this.routeMatches || !routeData || !routeData.slug) return;
|
const addon = routeData.path.substr(1);
|
||||||
this.hass.callApi("get", `hassio/addons/${routeData.slug}/info`).then(
|
this.hass.callApi("get", `hassio/addons/${addon}/info`).then(
|
||||||
(info) => {
|
(info) => {
|
||||||
this.addon = info.data;
|
this.addon = info.data;
|
||||||
},
|
},
|
||||||
@ -167,12 +145,8 @@ class HassioAddonView extends PolymerElement {
|
|||||||
history.back();
|
history.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
openMarkdown(ev) {
|
_computeSlug(route) {
|
||||||
this.setProperties({
|
return route.path.substr(1);
|
||||||
markdownTitle: ev.detail.title,
|
|
||||||
markdownContent: ev.detail.content,
|
|
||||||
});
|
|
||||||
this.shadowRoot.querySelector("hassio-markdown-dialog").openDialog();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,10 +4,13 @@ import "@polymer/paper-icon-button/paper-icon-button";
|
|||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
|
||||||
import "../../src/components/ha-markdown";
|
import "../../../../src/components/ha-markdown";
|
||||||
import "../../src/resources/ha-style";
|
import "../../../../src/resources/ha-style";
|
||||||
import "../../src/components/dialog/ha-paper-dialog";
|
import "../../../../src/components/dialog/ha-paper-dialog";
|
||||||
|
import { customElement } from "lit-element";
|
||||||
|
import { PaperDialogElement } from "@polymer/paper-dialog";
|
||||||
|
|
||||||
|
@customElement("dialog-hassio-markdown")
|
||||||
class HassioMarkdownDialog extends PolymerElement {
|
class HassioMarkdownDialog extends PolymerElement {
|
||||||
static get template() {
|
static get template() {
|
||||||
return html`
|
return html`
|
||||||
@ -72,8 +75,14 @@ class HassioMarkdownDialog extends PolymerElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
openDialog() {
|
public showDialog(params) {
|
||||||
this.$.dialog.open();
|
this.setProperties(params);
|
||||||
|
(this.$.dialog as PaperDialogElement).open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"dialog-hassio-markdown": HassioMarkdownDialog;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
customElements.define("hassio-markdown-dialog", HassioMarkdownDialog);
|
|
18
hassio/src/dialogs/markdown/show-dialog-hassio-markdown.ts
Normal file
18
hassio/src/dialogs/markdown/show-dialog-hassio-markdown.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
|
|
||||||
|
export interface HassioMarkdownDialogParams {
|
||||||
|
title: string;
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showHassioMarkdownDialog = (
|
||||||
|
element: HTMLElement,
|
||||||
|
dialogParams: HassioMarkdownDialogParams
|
||||||
|
): void => {
|
||||||
|
fireEvent(element, "show-dialog", {
|
||||||
|
dialogTag: "dialog-hassio-markdown",
|
||||||
|
dialogImport: () =>
|
||||||
|
import(/* webpackChunkName: "dialog-hassio-markdown" */ "./dialog-hassio-markdown"),
|
||||||
|
dialogParams,
|
||||||
|
});
|
||||||
|
};
|
@ -6,12 +6,24 @@ import "@polymer/paper-icon-button/paper-icon-button";
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
import { getSignedPath } from "../../../src/auth/data";
|
import { getSignedPath } from "../../../../src/auth/data";
|
||||||
|
|
||||||
import "../../../src/resources/ha-style";
|
import "../../../../src/resources/ha-style";
|
||||||
import "../../../src/components/dialog/ha-paper-dialog";
|
import "../../../../src/components/dialog/ha-paper-dialog";
|
||||||
|
import { customElement } from "lit-element";
|
||||||
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
|
import { PaperDialogElement } from "@polymer/paper-dialog";
|
||||||
|
import { HassioSnapshotDialogParams } from "./show-dialog-hassio-snapshot";
|
||||||
|
|
||||||
|
@customElement("dialog-hassio-snapshot")
|
||||||
|
class HassioSnapshotDialog extends PolymerElement {
|
||||||
|
public hass!: HomeAssistant;
|
||||||
|
protected error?: string;
|
||||||
|
private snapshot?: any;
|
||||||
|
private dialogParams?: HassioSnapshotDialogParams;
|
||||||
|
private restoreHass!: boolean;
|
||||||
|
private snapshotPassword!: string;
|
||||||
|
|
||||||
class HassioSnapshot extends PolymerElement {
|
|
||||||
static get template() {
|
static get template() {
|
||||||
return html`
|
return html`
|
||||||
<style include="ha-style-dialog">
|
<style include="ha-style-dialog">
|
||||||
@ -139,15 +151,6 @@ class HassioSnapshot extends PolymerElement {
|
|||||||
static get properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
hass: Object,
|
hass: Object,
|
||||||
snapshotSlug: {
|
|
||||||
type: String,
|
|
||||||
notify: true,
|
|
||||||
observer: "_snapshotSlugChanged",
|
|
||||||
},
|
|
||||||
snapshotDeleted: {
|
|
||||||
type: Boolean,
|
|
||||||
notify: true,
|
|
||||||
},
|
|
||||||
snapshot: Object,
|
snapshot: Object,
|
||||||
restoreHass: {
|
restoreHass: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -158,39 +161,43 @@ class HassioSnapshot extends PolymerElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_snapshotSlugChanged(snapshotSlug) {
|
public showDialog(params: HassioSnapshotDialogParams) {
|
||||||
if (!snapshotSlug || snapshotSlug === "update") return;
|
this.dialogParams = params;
|
||||||
this.hass.callApi("get", `hassio/snapshots/${snapshotSlug}/info`).then(
|
this.hass.callApi("GET", `hassio/snapshots/${params.slug}/info`).then(
|
||||||
(info) => {
|
(info: any) => {
|
||||||
info.data.folders = this._computeFolders(info.data.folders);
|
info.data.folders = this._computeFolders(info.data.folders);
|
||||||
info.data.addons = this._computeAddons(info.data.addons);
|
info.data.addons = this._computeAddons(info.data.addons);
|
||||||
this.snapshot = info.data;
|
this.setProperties({ snapshot: info.data });
|
||||||
this.$.dialog.open();
|
(this.$.dialog as PaperDialogElement).open();
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this.snapshot = null;
|
this.dialogParams = undefined;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeFolders(folders) {
|
protected _computeFolders(folders) {
|
||||||
const list = [];
|
const list: Array<{ slug: string; name: string; checked: boolean }> = [];
|
||||||
if (folders.includes("homeassistant"))
|
if (folders.includes("homeassistant")) {
|
||||||
list.push({
|
list.push({
|
||||||
slug: "homeassistant",
|
slug: "homeassistant",
|
||||||
name: "Home Assistant configuration",
|
name: "Home Assistant configuration",
|
||||||
checked: true,
|
checked: true,
|
||||||
});
|
});
|
||||||
if (folders.includes("ssl"))
|
}
|
||||||
|
if (folders.includes("ssl")) {
|
||||||
list.push({ slug: "ssl", name: "SSL", checked: true });
|
list.push({ slug: "ssl", name: "SSL", checked: true });
|
||||||
if (folders.includes("share"))
|
}
|
||||||
|
if (folders.includes("share")) {
|
||||||
list.push({ slug: "share", name: "Share", checked: true });
|
list.push({ slug: "share", name: "Share", checked: true });
|
||||||
if (folders.includes("addons/local"))
|
}
|
||||||
|
if (folders.includes("addons/local")) {
|
||||||
list.push({ slug: "addons/local", name: "Local add-ons", checked: true });
|
list.push({ slug: "addons/local", name: "Local add-ons", checked: true });
|
||||||
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeAddons(addons) {
|
protected _computeAddons(addons) {
|
||||||
return addons.map((addon) => ({
|
return addons.map((addon) => ({
|
||||||
slug: addon.slug,
|
slug: addon.slug,
|
||||||
name: addon.name,
|
name: addon.name,
|
||||||
@ -199,11 +206,11 @@ class HassioSnapshot extends PolymerElement {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
_isFullSnapshot(type) {
|
protected _isFullSnapshot(type) {
|
||||||
return type === "full";
|
return type === "full";
|
||||||
}
|
}
|
||||||
|
|
||||||
_partialRestoreClicked() {
|
protected _partialRestoreClicked() {
|
||||||
if (!confirm("Are you sure you want to restore this snapshot?")) {
|
if (!confirm("Are you sure you want to restore this snapshot?")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -216,21 +223,24 @@ class HassioSnapshot extends PolymerElement {
|
|||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
homeassistant: this.restoreHass,
|
homeassistant: this.restoreHass,
|
||||||
addons: addons,
|
addons,
|
||||||
folders: folders,
|
folders,
|
||||||
};
|
};
|
||||||
if (this.snapshot.protected) data.password = this.snapshotPassword;
|
if (this.snapshot.protected) {
|
||||||
|
// @ts-ignore
|
||||||
|
data.password = this.snapshotPassword;
|
||||||
|
}
|
||||||
|
|
||||||
this.hass
|
this.hass
|
||||||
.callApi(
|
.callApi(
|
||||||
"post",
|
"POST",
|
||||||
`hassio/snapshots/${this.snapshotSlug}/restore/partial`,
|
`hassio/snapshots/${this.dialogParams!.slug}/restore/partial`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
alert("Snapshot restored!");
|
alert("Snapshot restored!");
|
||||||
this.$.dialog.close();
|
(this.$.dialog as PaperDialogElement).close();
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
this.error = error.body.message;
|
this.error = error.body.message;
|
||||||
@ -238,23 +248,23 @@ class HassioSnapshot extends PolymerElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_fullRestoreClicked() {
|
protected _fullRestoreClicked() {
|
||||||
if (!confirm("Are you sure you want to restore this snapshot?")) {
|
if (!confirm("Are you sure you want to restore this snapshot?")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const data = this.snapshot.protected
|
const data = this.snapshot.protected
|
||||||
? { password: this.snapshotPassword }
|
? { password: this.snapshotPassword }
|
||||||
: null;
|
: undefined;
|
||||||
this.hass
|
this.hass
|
||||||
.callApi(
|
.callApi(
|
||||||
"post",
|
"POST",
|
||||||
`hassio/snapshots/${this.snapshotSlug}/restore/full`,
|
`hassio/snapshots/${this.dialogParams!.slug}/restore/full`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
alert("Snapshot restored!");
|
alert("Snapshot restored!");
|
||||||
this.$.dialog.close();
|
(this.$.dialog as PaperDialogElement).close();
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
this.error = error.body.message;
|
this.error = error.body.message;
|
||||||
@ -262,16 +272,16 @@ class HassioSnapshot extends PolymerElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_deleteClicked() {
|
protected _deleteClicked() {
|
||||||
if (!confirm("Are you sure you want to delete this snapshot?")) {
|
if (!confirm("Are you sure you want to delete this snapshot?")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.hass
|
this.hass
|
||||||
.callApi("post", `hassio/snapshots/${this.snapshotSlug}/remove`)
|
.callApi("POST", `hassio/snapshots/${this.dialogParams!.slug}/remove`)
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
this.$.dialog.close();
|
(this.$.dialog as PaperDialogElement).close();
|
||||||
this.snapshotDeleted = true;
|
this.dialogParams!.onDelete();
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
this.error = error.body.message;
|
this.error = error.body.message;
|
||||||
@ -279,19 +289,19 @@ class HassioSnapshot extends PolymerElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _downloadClicked() {
|
protected async _downloadClicked() {
|
||||||
let signedPath;
|
let signedPath;
|
||||||
try {
|
try {
|
||||||
signedPath = await getSignedPath(
|
signedPath = await getSignedPath(
|
||||||
this.hass,
|
this.hass,
|
||||||
`/api/hassio/snapshots/${this.snapshotSlug}/download`
|
`/api/hassio/snapshots/${this.dialogParams!.slug}/download`
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(`Error: ${err.message}`);
|
alert(`Error: ${err.message}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const name = this._computeName(this.snapshot).replace(/[^a-z0-9]+/gi, "_");
|
const name = this._computeName(this.snapshot).replace(/[^a-z0-9]+/gi, "_");
|
||||||
const a = document.createElement("A");
|
const a = document.createElement("a");
|
||||||
a.href = signedPath.path;
|
a.href = signedPath.path;
|
||||||
a.download = `Hass_io_${name}.tar`;
|
a.download = `Hass_io_${name}.tar`;
|
||||||
this.$.dialog.appendChild(a);
|
this.$.dialog.appendChild(a);
|
||||||
@ -299,23 +309,23 @@ class HassioSnapshot extends PolymerElement {
|
|||||||
this.$.dialog.removeChild(a);
|
this.$.dialog.removeChild(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeName(snapshot) {
|
protected _computeName(snapshot) {
|
||||||
return snapshot.name || snapshot.slug;
|
return snapshot.name || snapshot.slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeType(type) {
|
protected _computeType(type) {
|
||||||
return type === "full" ? "Full snapshot" : "Partial snapshot";
|
return type === "full" ? "Full snapshot" : "Partial snapshot";
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeSize(size) {
|
protected _computeSize(size) {
|
||||||
return Math.ceil(size * 10) / 10 + " MB";
|
return Math.ceil(size * 10) / 10 + " MB";
|
||||||
}
|
}
|
||||||
|
|
||||||
_sortAddons(a, b) {
|
protected _sortAddons(a, b) {
|
||||||
return a.name < b.name ? -1 : 1;
|
return a.name < b.name ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_formatDatetime(datetime) {
|
protected _formatDatetime(datetime) {
|
||||||
return new Date(datetime).toLocaleDateString(navigator.language, {
|
return new Date(datetime).toLocaleDateString(navigator.language, {
|
||||||
weekday: "long",
|
weekday: "long",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
@ -326,8 +336,14 @@ class HassioSnapshot extends PolymerElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_dialogClosed() {
|
protected _dialogClosed() {
|
||||||
this.snapshotSlug = null;
|
this.dialogParams = undefined;
|
||||||
|
this.snapshot = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"dialog-hassio-snapshot": HassioSnapshotDialog;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
customElements.define("hassio-snapshot", HassioSnapshot);
|
|
18
hassio/src/dialogs/snapshot/show-dialog-hassio-snapshot.ts
Normal file
18
hassio/src/dialogs/snapshot/show-dialog-hassio-snapshot.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
|
|
||||||
|
export interface HassioSnapshotDialogParams {
|
||||||
|
slug: string;
|
||||||
|
onDelete: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showHassioSnapshotDialog = (
|
||||||
|
element: HTMLElement,
|
||||||
|
dialogParams: HassioSnapshotDialogParams
|
||||||
|
): void => {
|
||||||
|
fireEvent(element, "show-dialog", {
|
||||||
|
dialogTag: "dialog-hassio-snapshot",
|
||||||
|
dialogImport: () =>
|
||||||
|
import(/* webpackChunkName: "dialog-hassio-snapshot" */ "./dialog-hassio-snapshot"),
|
||||||
|
dialogParams,
|
||||||
|
});
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
window.loadES5Adapter().then(() => {
|
window.loadES5Adapter().then(() => {
|
||||||
import(/* webpackChunkName: "hassio-icons" */ "./resources/hassio-icons.js");
|
import(/* webpackChunkName: "hassio-icons" */ "./resources/hassio-icons");
|
||||||
import(/* webpackChunkName: "hassio-main" */ "./hassio-main.js");
|
import(/* webpackChunkName: "hassio-main" */ "./hassio-main");
|
||||||
});
|
});
|
||||||
const styleEl = document.createElement("style");
|
const styleEl = document.createElement("style");
|
||||||
styleEl.innerHTML = `
|
styleEl.innerHTML = `
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|
||||||
|
|
||||||
class HassioData extends PolymerElement {
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
|
|
||||||
supervisor: {
|
|
||||||
type: Object,
|
|
||||||
notify: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
host: {
|
|
||||||
type: Object,
|
|
||||||
notify: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
homeassistant: {
|
|
||||||
type: Object,
|
|
||||||
notify: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
connectedCallback() {
|
|
||||||
super.connectedCallback();
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
return Promise.all([
|
|
||||||
this.fetchSupervisorInfo(),
|
|
||||||
this.fetchHostInfo(),
|
|
||||||
this.fetchHassInfo(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchSupervisorInfo() {
|
|
||||||
return this.hass.callApi("get", "hassio/supervisor/info").then((info) => {
|
|
||||||
this.supervisor = info.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchHostInfo() {
|
|
||||||
return this.hass.callApi("get", "hassio/host/info").then((info) => {
|
|
||||||
this.host = info.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchHassInfo() {
|
|
||||||
return this.hass
|
|
||||||
.callApi("get", "hassio/homeassistant/info")
|
|
||||||
.then((info) => {
|
|
||||||
this.homeassistant = info.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define("hassio-data", HassioData);
|
|
@ -1,158 +0,0 @@
|
|||||||
import "@polymer/app-route/app-route";
|
|
||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|
||||||
|
|
||||||
import "../../src/layouts/hass-loading-screen";
|
|
||||||
import "./addon-view/hassio-addon-view";
|
|
||||||
import "./ingress-view/hassio-ingress-view";
|
|
||||||
import "./hassio-data";
|
|
||||||
import "./hassio-pages-with-tabs";
|
|
||||||
|
|
||||||
import "../../src/resources/ha-style";
|
|
||||||
import applyThemesOnElement from "../../src/common/dom/apply_themes_on_element";
|
|
||||||
import EventsMixin from "../../src/mixins/events-mixin";
|
|
||||||
import NavigateMixin from "../../src/mixins/navigate-mixin";
|
|
||||||
import { fireEvent } from "../../src/common/dom/fire_event";
|
|
||||||
|
|
||||||
class HassioMain extends EventsMixin(NavigateMixin(PolymerElement)) {
|
|
||||||
static get template() {
|
|
||||||
return html`
|
|
||||||
<app-route
|
|
||||||
route="[[route]]"
|
|
||||||
pattern="/:page"
|
|
||||||
data="{{routeData}}"
|
|
||||||
></app-route>
|
|
||||||
<hassio-data
|
|
||||||
id="data"
|
|
||||||
hass="[[hass]]"
|
|
||||||
supervisor="{{supervisorInfo}}"
|
|
||||||
homeassistant="{{hassInfo}}"
|
|
||||||
host="{{hostInfo}}"
|
|
||||||
></hassio-data>
|
|
||||||
|
|
||||||
<template is="dom-if" if="[[!loaded]]">
|
|
||||||
<hass-loading-screen></hass-loading-screen>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template is="dom-if" if="[[loaded]]">
|
|
||||||
<template is="dom-if" if="[[equalsDashboard(routeData.page)]]">
|
|
||||||
<hassio-pages-with-tabs
|
|
||||||
hass="[[hass]]"
|
|
||||||
page="[[routeData.page]]"
|
|
||||||
supervisor-info="[[supervisorInfo]]"
|
|
||||||
hass-info="[[hassInfo]]"
|
|
||||||
host-info="[[hostInfo]]"
|
|
||||||
></hassio-pages-with-tabs>
|
|
||||||
</template>
|
|
||||||
<template is="dom-if" if="[[equalsAddon(routeData.page)]]">
|
|
||||||
<hassio-addon-view
|
|
||||||
hass="[[hass]]"
|
|
||||||
route="[[route]]"
|
|
||||||
></hassio-addon-view>
|
|
||||||
</template>
|
|
||||||
<template is="dom-if" if="[[equalsIngress(routeData.page)]]">
|
|
||||||
<hassio-ingress-view
|
|
||||||
hass="[[hass]]"
|
|
||||||
route="[[route]]"
|
|
||||||
></hassio-ingress-view>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
route: {
|
|
||||||
type: Object,
|
|
||||||
// Fake route object
|
|
||||||
value: {
|
|
||||||
prefix: "/hassio",
|
|
||||||
path: "/dashboard",
|
|
||||||
__queryParams: {},
|
|
||||||
},
|
|
||||||
observer: "routeChanged",
|
|
||||||
},
|
|
||||||
routeData: Object,
|
|
||||||
supervisorInfo: Object,
|
|
||||||
hostInfo: Object,
|
|
||||||
hassInfo: Object,
|
|
||||||
loaded: {
|
|
||||||
type: Boolean,
|
|
||||||
computed: "computeIsLoaded(supervisorInfo, hostInfo, hassInfo)",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ready() {
|
|
||||||
super.ready();
|
|
||||||
applyThemesOnElement(this, this.hass.themes, this.hass.selectedTheme, true);
|
|
||||||
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
|
|
||||||
// Paulus - March 17, 2019
|
|
||||||
// We went to a single hass-toggle-menu event in HA 0.90. However, the
|
|
||||||
// supervisor UI can also run under older versions of Home Assistant.
|
|
||||||
// So here we are going to translate toggle events into the appropriate
|
|
||||||
// open and close events. These events are a no-op in newer versions of
|
|
||||||
// Home Assistant.
|
|
||||||
this.addEventListener("hass-toggle-menu", () => {
|
|
||||||
fireEvent(
|
|
||||||
window.parent.customPanel,
|
|
||||||
this.hass.dockedSidebar ? "hass-close-menu" : "hass-open-menu"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
// Paulus - March 19, 2019
|
|
||||||
// We changed the navigate event to fire directly on the window, as that's
|
|
||||||
// where we are listening for it. However, the older panel_custom will
|
|
||||||
// listen on this element for navigation events, so we need to forward them.
|
|
||||||
window.addEventListener("location-changed", (ev) =>
|
|
||||||
fireEvent(this, ev.type, ev.detail, {
|
|
||||||
bubbles: false,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
connectedCallback() {
|
|
||||||
super.connectedCallback();
|
|
||||||
this.routeChanged(this.route);
|
|
||||||
}
|
|
||||||
|
|
||||||
apiCalled(ev) {
|
|
||||||
if (ev.detail.success) {
|
|
||||||
let tries = 1;
|
|
||||||
|
|
||||||
const tryUpdate = () => {
|
|
||||||
this.$.data.refresh().catch(function() {
|
|
||||||
tries += 1;
|
|
||||||
setTimeout(tryUpdate, Math.min(tries, 5) * 1000);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
tryUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
computeIsLoaded(supervisorInfo, hostInfo, hassInfo) {
|
|
||||||
return supervisorInfo !== null && hostInfo !== null && hassInfo !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
routeChanged(route) {
|
|
||||||
if (route.path === "" && route.prefix === "/hassio") {
|
|
||||||
this.navigate("/hassio/dashboard", true);
|
|
||||||
}
|
|
||||||
fireEvent(this, "iron-resize");
|
|
||||||
}
|
|
||||||
|
|
||||||
equalsAddon(page) {
|
|
||||||
return page && page === "addon";
|
|
||||||
}
|
|
||||||
|
|
||||||
equalsDashboard(page) {
|
|
||||||
return !page || !["addon", "ingress"].includes(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
equalsIngress(page) {
|
|
||||||
return page && page === "ingress";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define("hassio-main", HassioMain);
|
|
138
hassio/src/hassio-main.ts
Normal file
138
hassio/src/hassio-main.ts
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
import { customElement, PropertyValues, property } from "lit-element";
|
||||||
|
import { PolymerElement } from "@polymer/polymer";
|
||||||
|
|
||||||
|
import "../../src/resources/ha-style";
|
||||||
|
import applyThemesOnElement from "../../src/common/dom/apply_themes_on_element";
|
||||||
|
import { fireEvent } from "../../src/common/dom/fire_event";
|
||||||
|
import {
|
||||||
|
HassRouterPage,
|
||||||
|
RouterOptions,
|
||||||
|
} from "../../src/layouts/hass-router-page";
|
||||||
|
import { HomeAssistant } from "../../src/types";
|
||||||
|
import {
|
||||||
|
fetchHassioSupervisorInfo,
|
||||||
|
fetchHassioHostInfo,
|
||||||
|
fetchHassioHomeAssistantInfo,
|
||||||
|
} from "../../src/data/hassio";
|
||||||
|
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
|
||||||
|
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
|
||||||
|
|
||||||
|
@customElement("hassio-main")
|
||||||
|
class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
protected routerOptions: RouterOptions = {
|
||||||
|
// Hass.io has a page with tabs, so we route all non-matching routes to it.
|
||||||
|
defaultPage: "dashboard",
|
||||||
|
initialLoad: () => this._fetchData(),
|
||||||
|
routes: {
|
||||||
|
dashboard: {
|
||||||
|
tag: "hassio-pages-with-tabs",
|
||||||
|
load: () => import("./hassio-pages-with-tabs"),
|
||||||
|
cache: true,
|
||||||
|
},
|
||||||
|
snapshots: "dashboard",
|
||||||
|
store: "dashboard",
|
||||||
|
system: "dashboard",
|
||||||
|
addon: {
|
||||||
|
tag: "hassio-addon-view",
|
||||||
|
load: () => import("./addon-view/hassio-addon-view"),
|
||||||
|
},
|
||||||
|
ingress: {
|
||||||
|
tag: "hassio-ingress-view",
|
||||||
|
load: () => import("./ingress-view/hassio-ingress-view"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
@property() private _supervisorInfo: any;
|
||||||
|
@property() private _hostInfo: any;
|
||||||
|
@property() private _hassInfo: any;
|
||||||
|
|
||||||
|
protected firstUpdated(changedProps: PropertyValues) {
|
||||||
|
super.firstUpdated(changedProps);
|
||||||
|
|
||||||
|
applyThemesOnElement(this, this.hass.themes, this.hass.selectedTheme, true);
|
||||||
|
this.addEventListener("hass-api-called", (ev) => this._apiCalled(ev));
|
||||||
|
// Paulus - March 17, 2019
|
||||||
|
// We went to a single hass-toggle-menu event in HA 0.90. However, the
|
||||||
|
// supervisor UI can also run under older versions of Home Assistant.
|
||||||
|
// So here we are going to translate toggle events into the appropriate
|
||||||
|
// open and close events. These events are a no-op in newer versions of
|
||||||
|
// Home Assistant.
|
||||||
|
this.addEventListener("hass-toggle-menu", () => {
|
||||||
|
fireEvent(
|
||||||
|
(window.parent as any).customPanel,
|
||||||
|
// @ts-ignore
|
||||||
|
this.hass.dockedSidebar ? "hass-close-menu" : "hass-open-menu"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
// Paulus - March 19, 2019
|
||||||
|
// We changed the navigate event to fire directly on the window, as that's
|
||||||
|
// where we are listening for it. However, the older panel_custom will
|
||||||
|
// listen on this element for navigation events, so we need to forward them.
|
||||||
|
window.addEventListener("location-changed", (ev) =>
|
||||||
|
// @ts-ignore
|
||||||
|
fireEvent(this, ev.type, ev.detail, {
|
||||||
|
bubbles: false,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
makeDialogManager(this, document.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
// @ts-ignore not fighting TS today
|
||||||
|
route: this.routeTail,
|
||||||
|
});
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _fetchData() {
|
||||||
|
const [supervisorInfo, hostInfo, hassInfo] = await Promise.all([
|
||||||
|
fetchHassioSupervisorInfo(this.hass),
|
||||||
|
fetchHassioHostInfo(this.hass),
|
||||||
|
fetchHassioHomeAssistantInfo(this.hass),
|
||||||
|
]);
|
||||||
|
this._supervisorInfo = supervisorInfo;
|
||||||
|
this._hostInfo = hostInfo;
|
||||||
|
this._hassInfo = hassInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _apiCalled(ev) {
|
||||||
|
if (!ev.detail.success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tries = 1;
|
||||||
|
|
||||||
|
const tryUpdate = () => {
|
||||||
|
this._fetchData().catch(() => {
|
||||||
|
tries += 1;
|
||||||
|
setTimeout(tryUpdate, Math.min(tries, 5) * 1000);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
tryUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hassio-main": HassioMain;
|
||||||
|
}
|
||||||
|
}
|
@ -11,8 +11,6 @@ import "../../src/components/ha-menu-button";
|
|||||||
import "../../src/resources/ha-style";
|
import "../../src/resources/ha-style";
|
||||||
import "./addon-store/hassio-addon-store";
|
import "./addon-store/hassio-addon-store";
|
||||||
import "./dashboard/hassio-dashboard";
|
import "./dashboard/hassio-dashboard";
|
||||||
import "./hassio-markdown-dialog";
|
|
||||||
import "./snapshots/hassio-snapshot";
|
|
||||||
import "./snapshots/hassio-snapshots";
|
import "./snapshots/hassio-snapshots";
|
||||||
import "./system/hassio-system";
|
import "./system/hassio-system";
|
||||||
|
|
||||||
@ -69,8 +67,6 @@ class HassioPagesWithTabs extends NavigateMixin(PolymerElement) {
|
|||||||
<hassio-snapshots
|
<hassio-snapshots
|
||||||
hass="[[hass]]"
|
hass="[[hass]]"
|
||||||
installed-addons="[[supervisorInfo.addons]]"
|
installed-addons="[[supervisorInfo.addons]]"
|
||||||
snapshot-slug="{{snapshotSlug}}"
|
|
||||||
snapshot-deleted="{{snapshotDeleted}}"
|
|
||||||
></hassio-snapshots>
|
></hassio-snapshots>
|
||||||
</template>
|
</template>
|
||||||
<template is="dom-if" if='[[equals(page, "store")]]'>
|
<template is="dom-if" if='[[equals(page, "store")]]'>
|
||||||
@ -84,47 +80,23 @@ class HassioPagesWithTabs extends NavigateMixin(PolymerElement) {
|
|||||||
></hassio-system>
|
></hassio-system>
|
||||||
</template>
|
</template>
|
||||||
</app-header-layout>
|
</app-header-layout>
|
||||||
|
|
||||||
<hassio-markdown-dialog
|
|
||||||
title="[[markdownTitle]]"
|
|
||||||
content="[[markdownContent]]"
|
|
||||||
></hassio-markdown-dialog>
|
|
||||||
|
|
||||||
<template is="dom-if" if='[[equals(page, "snapshots")]]'>
|
|
||||||
<hassio-snapshot
|
|
||||||
hass="[[hass]]"
|
|
||||||
snapshot-slug="{{snapshotSlug}}"
|
|
||||||
snapshot-deleted="{{snapshotDeleted}}"
|
|
||||||
></hassio-snapshot>
|
|
||||||
</template>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
hass: Object,
|
hass: Object,
|
||||||
page: String,
|
page: {
|
||||||
|
type: String,
|
||||||
|
computed: "_computePage(route)",
|
||||||
|
},
|
||||||
|
route: Object,
|
||||||
supervisorInfo: Object,
|
supervisorInfo: Object,
|
||||||
hostInfo: Object,
|
hostInfo: Object,
|
||||||
hassInfo: Object,
|
hassInfo: Object,
|
||||||
snapshotSlug: String,
|
|
||||||
snapshotDeleted: Boolean,
|
|
||||||
|
|
||||||
markdownTitle: String,
|
|
||||||
markdownContent: {
|
|
||||||
type: String,
|
|
||||||
value: "",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ready() {
|
|
||||||
super.ready();
|
|
||||||
this.addEventListener("hassio-markdown-dialog", (ev) =>
|
|
||||||
this.openMarkdown(ev)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePageSelected(ev) {
|
handlePageSelected(ev) {
|
||||||
const newPage = ev.detail.item.getAttribute("page-name");
|
const newPage = ev.detail.item.getAttribute("page-name");
|
||||||
if (newPage !== this.page) {
|
if (newPage !== this.page) {
|
||||||
@ -149,12 +121,8 @@ class HassioPagesWithTabs extends NavigateMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openMarkdown(ev) {
|
_computePage(route) {
|
||||||
this.setProperties({
|
return route.prefix.substr(route.prefix.indexOf("/", 1) + 1);
|
||||||
markdownTitle: ev.detail.title,
|
|
||||||
markdownContent: ev.detail.content,
|
|
||||||
});
|
|
||||||
this.shadowRoot.querySelector("hassio-markdown-dialog").openDialog();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,14 +17,6 @@ import {
|
|||||||
import "../../../src/layouts/hass-loading-screen";
|
import "../../../src/layouts/hass-loading-screen";
|
||||||
import "../../../src/layouts/hass-subpage";
|
import "../../../src/layouts/hass-subpage";
|
||||||
|
|
||||||
const extractAddon = (path: string) => {
|
|
||||||
path = path.substr("/ingress".length);
|
|
||||||
const subpathStart = path.indexOf("/", 1);
|
|
||||||
return subpathStart === -1
|
|
||||||
? path.substr(1)
|
|
||||||
: path.substr(1, subpathStart - 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
@customElement("hassio-ingress-view")
|
@customElement("hassio-ingress-view")
|
||||||
class HassioIngressView extends LitElement {
|
class HassioIngressView extends LitElement {
|
||||||
@property() public hass!: HomeAssistant;
|
@property() public hass!: HomeAssistant;
|
||||||
@ -55,10 +47,10 @@ class HassioIngressView extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const addon = extractAddon(this.route.path);
|
const addon = this.route.path.substr(1);
|
||||||
|
|
||||||
const oldRoute = changedProps.get("route") as this["route"] | undefined;
|
const oldRoute = changedProps.get("route") as this["route"] | undefined;
|
||||||
const oldAddon = oldRoute ? extractAddon(oldRoute.path) : undefined;
|
const oldAddon = oldRoute ? oldRoute.path.substr(1) : undefined;
|
||||||
|
|
||||||
if (addon && addon !== oldAddon) {
|
if (addon && addon !== oldAddon) {
|
||||||
this._createSession();
|
this._createSession();
|
||||||
|
@ -11,6 +11,8 @@ import "../components/hassio-card-content";
|
|||||||
import "../resources/hassio-style";
|
import "../resources/hassio-style";
|
||||||
import EventsMixin from "../../../src/mixins/events-mixin";
|
import EventsMixin from "../../../src/mixins/events-mixin";
|
||||||
|
|
||||||
|
import { showHassioSnapshotDialog } from "../dialogs/snapshot/show-dialog-hassio-snapshot";
|
||||||
|
|
||||||
class HassioSnapshots extends EventsMixin(PolymerElement) {
|
class HassioSnapshots extends EventsMixin(PolymerElement) {
|
||||||
static get template() {
|
static get template() {
|
||||||
return html`
|
return html`
|
||||||
@ -287,6 +289,10 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_snapshotClicked(ev) {
|
_snapshotClicked(ev) {
|
||||||
|
showHassioSnapshotDialog(this, {
|
||||||
|
slug: ev.model.snapshot.slug,
|
||||||
|
onDelete: () => this._updateSnapshots(),
|
||||||
|
});
|
||||||
this.snapshotSlug = ev.model.snapshot.slug;
|
this.snapshotSlug = ev.model.snapshot.slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,13 +300,6 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
|
|||||||
return type === "full";
|
return type === "full";
|
||||||
}
|
}
|
||||||
|
|
||||||
_snapshotDeletedChanged(snapshotDeleted) {
|
|
||||||
if (snapshotDeleted) {
|
|
||||||
this._updateSnapshots();
|
|
||||||
this.snapshotDeleted = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshData() {
|
refreshData() {
|
||||||
this.hass.callApi("post", "hassio/snapshots/reload").then(() => {
|
this.hass.callApi("post", "hassio/snapshots/reload").then(() => {
|
||||||
this._updateSnapshots();
|
this._updateSnapshots();
|
||||||
|
@ -6,6 +6,8 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|||||||
import "../../../src/components/buttons/ha-call-api-button";
|
import "../../../src/components/buttons/ha-call-api-button";
|
||||||
import EventsMixin from "../../../src/mixins/events-mixin";
|
import EventsMixin from "../../../src/mixins/events-mixin";
|
||||||
|
|
||||||
|
import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio-markdown";
|
||||||
|
|
||||||
class HassioHostInfo extends EventsMixin(PolymerElement) {
|
class HassioHostInfo extends EventsMixin(PolymerElement) {
|
||||||
static get template() {
|
static get template() {
|
||||||
return html`
|
return html`
|
||||||
@ -173,7 +175,7 @@ class HassioHostInfo extends EventsMixin(PolymerElement) {
|
|||||||
() => "Error getting hardware info"
|
() => "Error getting hardware info"
|
||||||
)
|
)
|
||||||
.then((content) => {
|
.then((content) => {
|
||||||
this.fire("hassio-markdown-dialog", {
|
showHassioMarkdownDialog(this, {
|
||||||
title: "Hardware",
|
title: "Hardware",
|
||||||
content: content,
|
content: content,
|
||||||
});
|
});
|
||||||
|
@ -77,10 +77,22 @@ export const createHassioSession = async (hass: HomeAssistant) => {
|
|||||||
};path=/api/hassio_ingress/`;
|
};path=/api/hassio_ingress/`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchHassioAddonInfo = async (
|
export const fetchHassioAddonInfo = (hass: HomeAssistant, addon: string) =>
|
||||||
hass: HomeAssistant,
|
|
||||||
addon: string
|
|
||||||
) =>
|
|
||||||
hass
|
hass
|
||||||
.callApi<HassioResponse<HassioAddon>>("GET", `hassio/addons/${addon}/info`)
|
.callApi<HassioResponse<HassioAddon>>("GET", `hassio/addons/${addon}/info`)
|
||||||
.then(hassioApiResultExtractor);
|
.then(hassioApiResultExtractor);
|
||||||
|
|
||||||
|
export const fetchHassioSupervisorInfo = (hass: HomeAssistant) =>
|
||||||
|
hass
|
||||||
|
.callApi<HassioResponse<any>>("GET", "hassio/supervisor/info")
|
||||||
|
.then(hassioApiResultExtractor);
|
||||||
|
|
||||||
|
export const fetchHassioHostInfo = (hass: HomeAssistant) =>
|
||||||
|
hass
|
||||||
|
.callApi<HassioResponse<any>>("GET", "hassio/host/info")
|
||||||
|
.then(hassioApiResultExtractor);
|
||||||
|
|
||||||
|
export const fetchHassioHomeAssistantInfo = (hass: HomeAssistant) =>
|
||||||
|
hass
|
||||||
|
.callApi<HassioResponse<any>>("GET", "hassio/homeassistant/info")
|
||||||
|
.then(hassioApiResultExtractor);
|
||||||
|
57
src/dialogs/make-dialog-manager.ts
Normal file
57
src/dialogs/make-dialog-manager.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { HASSDomEvent, ValidHassDomEvent } from "../common/dom/fire_event";
|
||||||
|
import { ProvideHassElement } from "../mixins/provide-hass-lit-mixin";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// for fire event
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"show-dialog": ShowDialogParams<unknown>;
|
||||||
|
}
|
||||||
|
// for add event listener
|
||||||
|
interface HTMLElementEventMap {
|
||||||
|
"show-dialog": HASSDomEvent<ShowDialogParams<unknown>>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HassDialog<T = HASSDomEvents[ValidHassDomEvent]> extends HTMLElement {
|
||||||
|
showDialog(params: T);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ShowDialogParams<T> {
|
||||||
|
dialogTag: keyof HTMLElementTagNameMap;
|
||||||
|
dialogImport: () => Promise<unknown>;
|
||||||
|
dialogParams: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LOADED = {};
|
||||||
|
|
||||||
|
export const showDialog = async (
|
||||||
|
element: HTMLElement & ProvideHassElement,
|
||||||
|
root: ShadowRoot | HTMLElement,
|
||||||
|
dialogImport: () => Promise<unknown>,
|
||||||
|
dialogTag: string,
|
||||||
|
dialogParams: unknown
|
||||||
|
) => {
|
||||||
|
if (!(dialogTag in LOADED)) {
|
||||||
|
LOADED[dialogTag] = dialogImport().then(() => {
|
||||||
|
const dialogEl = document.createElement(dialogTag) as HassDialog;
|
||||||
|
element.provideHass(dialogEl);
|
||||||
|
root.appendChild(dialogEl);
|
||||||
|
return dialogEl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const dialogElement = await LOADED[dialogTag];
|
||||||
|
dialogElement.showDialog(dialogParams);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const makeDialogManager = (
|
||||||
|
element: HTMLElement & ProvideHassElement,
|
||||||
|
root: ShadowRoot | HTMLElement
|
||||||
|
) => {
|
||||||
|
element.addEventListener(
|
||||||
|
"show-dialog",
|
||||||
|
async (e: HASSDomEvent<ShowDialogParams<unknown>>) => {
|
||||||
|
const { dialogTag, dialogImport, dialogParams } = e.detail;
|
||||||
|
showDialog(element, root, dialogImport, dialogTag, dialogParams);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
@ -1,6 +1,10 @@
|
|||||||
import { Constructor, LitElement } from "lit-element";
|
import { Constructor, LitElement } from "lit-element";
|
||||||
import { HASSDomEvent, ValidHassDomEvent } from "../../common/dom/fire_event";
|
import { HASSDomEvent } from "../../common/dom/fire_event";
|
||||||
import { HassBaseEl } from "./hass-base-mixin";
|
import { HassBaseEl } from "./hass-base-mixin";
|
||||||
|
import {
|
||||||
|
makeDialogManager,
|
||||||
|
showDialog,
|
||||||
|
} from "../../dialogs/make-dialog-manager";
|
||||||
|
|
||||||
interface RegisterDialogParams {
|
interface RegisterDialogParams {
|
||||||
dialogShowEvent: keyof HASSDomEvents;
|
dialogShowEvent: keyof HASSDomEvents;
|
||||||
@ -8,31 +12,17 @@ interface RegisterDialogParams {
|
|||||||
dialogImport: () => Promise<unknown>;
|
dialogImport: () => Promise<unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ShowDialogParams<T> {
|
|
||||||
dialogTag: keyof HTMLElementTagNameMap;
|
|
||||||
dialogImport: () => Promise<unknown>;
|
|
||||||
dialogParams: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface HassDialog<T = HASSDomEvents[ValidHassDomEvent]> extends HTMLElement {
|
|
||||||
showDialog(params: T);
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// for fire event
|
// for fire event
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
"register-dialog": RegisterDialogParams;
|
"register-dialog": RegisterDialogParams;
|
||||||
"show-dialog": ShowDialogParams<unknown>;
|
|
||||||
}
|
}
|
||||||
// for add event listener
|
// for add event listener
|
||||||
interface HTMLElementEventMap {
|
interface HTMLElementEventMap {
|
||||||
"register-dialog": HASSDomEvent<RegisterDialogParams>;
|
"register-dialog": HASSDomEvent<RegisterDialogParams>;
|
||||||
"show-dialog": HASSDomEvent<ShowDialogParams<unknown>>;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOADED = {};
|
|
||||||
|
|
||||||
export const dialogManagerMixin = (
|
export const dialogManagerMixin = (
|
||||||
superClass: Constructor<LitElement & HassBaseEl>
|
superClass: Constructor<LitElement & HassBaseEl>
|
||||||
) =>
|
) =>
|
||||||
@ -43,13 +33,7 @@ export const dialogManagerMixin = (
|
|||||||
this.addEventListener("register-dialog", (e) =>
|
this.addEventListener("register-dialog", (e) =>
|
||||||
this.registerDialog(e.detail)
|
this.registerDialog(e.detail)
|
||||||
);
|
);
|
||||||
this.addEventListener(
|
makeDialogManager(this, this.shadowRoot!);
|
||||||
"show-dialog",
|
|
||||||
async (e: HASSDomEvent<ShowDialogParams<unknown>>) => {
|
|
||||||
const { dialogTag, dialogImport, dialogParams } = e.detail;
|
|
||||||
this._showDialog(dialogImport, dialogTag, dialogParams);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerDialog({
|
private registerDialog({
|
||||||
@ -58,28 +42,13 @@ export const dialogManagerMixin = (
|
|||||||
dialogImport,
|
dialogImport,
|
||||||
}: RegisterDialogParams) {
|
}: RegisterDialogParams) {
|
||||||
this.addEventListener(dialogShowEvent, (showEv) => {
|
this.addEventListener(dialogShowEvent, (showEv) => {
|
||||||
this._showDialog(
|
showDialog(
|
||||||
|
this,
|
||||||
|
this.shadowRoot!,
|
||||||
dialogImport,
|
dialogImport,
|
||||||
dialogTag,
|
dialogTag,
|
||||||
(showEv as HASSDomEvent<unknown>).detail
|
(showEv as HASSDomEvent<unknown>).detail
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _showDialog(
|
|
||||||
dialogImport: () => Promise<unknown>,
|
|
||||||
dialogTag: string,
|
|
||||||
dialogParams: unknown
|
|
||||||
) {
|
|
||||||
if (!(dialogTag in LOADED)) {
|
|
||||||
LOADED[dialogTag] = dialogImport().then(() => {
|
|
||||||
const dialogEl = document.createElement(dialogTag) as HassDialog;
|
|
||||||
this.provideHass(dialogEl);
|
|
||||||
this.shadowRoot!.appendChild(dialogEl);
|
|
||||||
return dialogEl;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const element = await LOADED[dialogTag];
|
|
||||||
element.showDialog(dialogParams);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,7 @@ export class HassBaseEl {
|
|||||||
protected hassDisconnected() {}
|
protected hassDisconnected() {}
|
||||||
protected hassChanged(_hass: HomeAssistant, _oldHass?: HomeAssistant) {}
|
protected hassChanged(_hass: HomeAssistant, _oldHass?: HomeAssistant) {}
|
||||||
protected panelUrlChanged(_newPanelUrl: string) {}
|
protected panelUrlChanged(_newPanelUrl: string) {}
|
||||||
protected provideHass(_el: HTMLElement) {}
|
public provideHass(_el: HTMLElement) {}
|
||||||
protected _updateHass(_obj: Partial<HomeAssistant>) {}
|
protected _updateHass(_obj: Partial<HomeAssistant>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ export default <T>(superClass: Constructor<T>): Constructor<T & HassBaseEl> =>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected provideHass(el) {
|
public provideHass(el) {
|
||||||
this.__provideHass.push(el);
|
this.__provideHass.push(el);
|
||||||
el.hass = this.hass;
|
el.hass = this.hass;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { UpdatingElement, property, PropertyValues } from "lit-element";
|
import { UpdatingElement, property, PropertyValues } from "lit-element";
|
||||||
import "./hass-error-screen";
|
import "./hass-error-screen";
|
||||||
|
import "./hass-loading-screen";
|
||||||
import { Route } from "../types";
|
import { Route } from "../types";
|
||||||
import { navigate } from "../common/navigate";
|
import { navigate } from "../common/navigate";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
@ -15,18 +16,27 @@ const extractPage = (path: string, defaultPage: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface RouteOptions {
|
export interface RouteOptions {
|
||||||
|
// HTML tag of the route page.
|
||||||
tag: string;
|
tag: string;
|
||||||
|
// Function to load the page.
|
||||||
load: () => Promise<unknown>;
|
load: () => Promise<unknown>;
|
||||||
cache?: boolean;
|
cache?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RouterOptions {
|
export interface RouterOptions {
|
||||||
|
// The default route to show if path does not define a page.
|
||||||
defaultPage?: string;
|
defaultPage?: string;
|
||||||
|
// If all routes should be preloaded
|
||||||
preloadAll?: boolean;
|
preloadAll?: boolean;
|
||||||
|
// If a route has been shown, should we keep the element in memory
|
||||||
cacheAll?: boolean;
|
cacheAll?: boolean;
|
||||||
|
// Should we show a loading spinner while we load the element for the route
|
||||||
showLoading?: boolean;
|
showLoading?: boolean;
|
||||||
|
// Promise that resolves when the initial data is loaded which is needed to show any route.
|
||||||
|
initialLoad?: () => Promise<unknown>;
|
||||||
routes: {
|
routes: {
|
||||||
[route: string]: RouteOptions;
|
// If it's a string, it is another route whose options should be adopted.
|
||||||
|
[route: string]: RouteOptions | string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +58,7 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
private _currentPage = "";
|
private _currentPage = "";
|
||||||
private _currentLoadProm?: Promise<void>;
|
private _currentLoadProm?: Promise<void>;
|
||||||
private _cache = {};
|
private _cache = {};
|
||||||
|
private _initialLoadDone = false;
|
||||||
private _computeTail = memoizeOne((route: Route) => {
|
private _computeTail = memoizeOne((route: Route) => {
|
||||||
const dividerPos = route.path.indexOf("/", 1);
|
const dividerPos = route.path.indexOf("/", 1);
|
||||||
return dividerPos === -1
|
return dividerPos === -1
|
||||||
@ -64,6 +75,12 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
protected update(changedProps: PropertyValues) {
|
protected update(changedProps: PropertyValues) {
|
||||||
super.update(changedProps);
|
super.update(changedProps);
|
||||||
|
|
||||||
|
const routerOptions = this.routerOptions || { routes: {} };
|
||||||
|
|
||||||
|
if (routerOptions && routerOptions.initialLoad && !this._initialLoadDone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!changedProps.has("route")) {
|
if (!changedProps.has("route")) {
|
||||||
// Do not update if we have a currentLoadProm, because that means
|
// Do not update if we have a currentLoadProm, because that means
|
||||||
// that there is still an old panel shown and we're moving to a new one.
|
// that there is still an old panel shown and we're moving to a new one.
|
||||||
@ -74,14 +91,20 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const route = this.route;
|
const route = this.route;
|
||||||
const routerOptions = this.routerOptions || { routes: {} };
|
|
||||||
const defaultPage = routerOptions.defaultPage || "";
|
const defaultPage = routerOptions.defaultPage || "";
|
||||||
|
|
||||||
if (route && route.path === "") {
|
if (route && route.path === "") {
|
||||||
navigate(this, `${route.prefix}/${defaultPage}`, true);
|
navigate(this, `${route.prefix}/${defaultPage}`, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newPage = route ? extractPage(route.path, defaultPage) : "not_found";
|
let newPage = route ? extractPage(route.path, defaultPage) : "not_found";
|
||||||
|
let routeOptions = routerOptions.routes[newPage];
|
||||||
|
|
||||||
|
// Handle redirects
|
||||||
|
while (typeof routeOptions === "string") {
|
||||||
|
newPage = routeOptions;
|
||||||
|
routeOptions = routerOptions.routes[newPage];
|
||||||
|
}
|
||||||
|
|
||||||
if (this._currentPage === newPage) {
|
if (this._currentPage === newPage) {
|
||||||
if (this.lastChild) {
|
if (this.lastChild) {
|
||||||
@ -90,8 +113,6 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const routeOptions = routerOptions.routes[newPage];
|
|
||||||
|
|
||||||
if (!routeOptions) {
|
if (!routeOptions) {
|
||||||
this._currentPage = "";
|
this._currentPage = "";
|
||||||
if (this.lastChild) {
|
if (this.lastChild) {
|
||||||
@ -151,7 +172,12 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
created = true;
|
created = true;
|
||||||
this._createPanel(routerOptions, newPage, routeOptions);
|
this._createPanel(
|
||||||
|
routerOptions,
|
||||||
|
newPage,
|
||||||
|
// @ts-ignore TS forgot this is not a string.
|
||||||
|
routeOptions
|
||||||
|
);
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this._currentLoadProm = undefined;
|
this._currentLoadProm = undefined;
|
||||||
@ -164,10 +190,28 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
|
|
||||||
const options = this.routerOptions;
|
const options = this.routerOptions;
|
||||||
|
|
||||||
if (options && options.preloadAll) {
|
if (!options) {
|
||||||
Object.values(options.routes).forEach((route) => route.load());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.preloadAll) {
|
||||||
|
Object.values(options.routes).forEach(
|
||||||
|
(route) => typeof route === "object" && route.load()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.initialLoad) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!this._initialLoadDone) {
|
||||||
|
this.appendChild(this.createLoadingScreen());
|
||||||
|
}
|
||||||
|
}, LOADING_SCREEN_THRESHOLD);
|
||||||
|
|
||||||
|
options.initialLoad().then(() => {
|
||||||
|
this._initialLoadDone = true;
|
||||||
|
this.requestUpdate("route");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected createLoadingScreen() {
|
protected createLoadingScreen() {
|
||||||
|
@ -74,6 +74,8 @@ class PartialPanelResolver extends HassRouterPage {
|
|||||||
@property() public narrow?: boolean;
|
@property() public narrow?: boolean;
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues) {
|
protected updated(changedProps: PropertyValues) {
|
||||||
|
super.updated(changedProps);
|
||||||
|
|
||||||
if (!changedProps.has("hass")) {
|
if (!changedProps.has("hass")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
32
src/mixins/provide-hass-lit-mixin.ts
Normal file
32
src/mixins/provide-hass-lit-mixin.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { UpdatingElement, Constructor, PropertyValues } from "lit-element";
|
||||||
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
|
export interface ProvideHassElement {
|
||||||
|
provideHass(element: HTMLElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
|
||||||
|
export const ProvideHassLitMixin = <T extends UpdatingElement>(
|
||||||
|
superClass: Constructor<T>
|
||||||
|
): Constructor<T & ProvideHassElement> =>
|
||||||
|
// @ts-ignore
|
||||||
|
class extends superClass {
|
||||||
|
protected hass!: HomeAssistant;
|
||||||
|
private __provideHass: HTMLElement[] = [];
|
||||||
|
|
||||||
|
public provideHass(el) {
|
||||||
|
this.__provideHass.push(el);
|
||||||
|
el.hass = this.hass;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updated(changedProps: PropertyValues) {
|
||||||
|
super.updated(changedProps);
|
||||||
|
|
||||||
|
if (changedProps.has("hass")) {
|
||||||
|
this.__provideHass.forEach((el) => {
|
||||||
|
(el as any).hass = this.hass;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user