From 927aafcbfa9f329d54d217ef95e52657f8c37c62 Mon Sep 17 00:00:00 2001 From: Ludeeus Date: Fri, 25 Sep 2020 14:50:20 +0000 Subject: [PATCH 01/12] Get discovery information --- src/data/discovery.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/data/discovery.ts diff --git a/src/data/discovery.ts b/src/data/discovery.ts new file mode 100644 index 000000000000..b3a3da659459 --- /dev/null +++ b/src/data/discovery.ts @@ -0,0 +1,17 @@ +export interface DiscoveryInformation { + uuid: string; + base_url: string | null; + external_url: string | null; + internal_url: string | null; + location_name: string; + installation_type: string; + requires_api_password: boolean; + version: string; +} + +export const fetchDiscoveryInformation = async (): Promise< + DiscoveryInformation +> => { + const response = await fetch("/api/discovery_info", { method: "GET" }); + return await response.json(); +}; From 20a4095880d5535a07a66699c569748be50198b0 Mon Sep 17 00:00:00 2001 From: Ludeeus Date: Fri, 25 Sep 2020 16:16:23 +0000 Subject: [PATCH 02/12] Remove unused hass --- hassio/src/components/hassio-upload-snapshot.ts | 1 - src/components/ha-file-upload.ts | 3 --- src/components/ha-picture-upload.ts | 1 - 3 files changed, 5 deletions(-) diff --git a/hassio/src/components/hassio-upload-snapshot.ts b/hassio/src/components/hassio-upload-snapshot.ts index dc838988a851..80901f697e31 100644 --- a/hassio/src/components/hassio-upload-snapshot.ts +++ b/hassio/src/components/hassio-upload-snapshot.ts @@ -38,7 +38,6 @@ export class HassioUploadSnapshot extends LitElement { public render(): TemplateResult { return html` Date: Fri, 25 Sep 2020 16:41:52 +0000 Subject: [PATCH 03/12] auto open file upload dialog --- src/components/ha-file-upload.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/components/ha-file-upload.ts b/src/components/ha-file-upload.ts index 225dbff40e7f..02d2dd687711 100644 --- a/src/components/ha-file-upload.ts +++ b/src/components/ha-file-upload.ts @@ -10,6 +10,7 @@ import { LitElement, property, PropertyValues, + query, TemplateResult, } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; @@ -35,8 +36,20 @@ export class HaFileUpload extends LitElement { @property({ type: Boolean }) private uploading = false; + @property({ type: Boolean, attribute: "auto-open-file-dialog" }) + private autoOpenFileDialog = false; + @internalProperty() private _drag = false; + @query("#input") private _input?: HTMLInputElement; + + protected firstUpdated(changedProperties: PropertyValues) { + super.firstUpdated(changedProperties); + if (this.autoOpenFileDialog) { + this._input?.click(); + } + } + protected updated(changedProperties: PropertyValues) { if (changedProperties.has("_drag") && !this.uploading) { (this.shadowRoot!.querySelector( From e2e00792824fe93bdfe5b3d93c44244e9ab6c9b8 Mon Sep 17 00:00:00 2001 From: Ludeeus Date: Mon, 28 Sep 2020 09:14:35 +0000 Subject: [PATCH 04/12] Add snapshot restore from onboarding --- .../src/components/hassio-upload-snapshot.ts | 5 +- .../snapshot/dialog-hassio-snapshot-upload.ts | 42 ++++- .../snapshot/dialog-hassio-snapshot.ts | 158 +++++++++++------ .../snapshot/show-dialog-hassio-snapshot.ts | 3 +- .../snapshot/show-dialog-snapshot-upload.ts | 3 +- src/data/hassio/snapshot.ts | 42 +++-- src/onboarding/ha-onboarding.ts | 55 +++++- src/onboarding/onboarding-restore-snapshot.ts | 160 ++++++++++++++++++ src/translations/en.json | 4 + 9 files changed, 394 insertions(+), 78 deletions(-) create mode 100644 src/onboarding/onboarding-restore-snapshot.ts diff --git a/hassio/src/components/hassio-upload-snapshot.ts b/hassio/src/components/hassio-upload-snapshot.ts index 80901f697e31..ee1e733b8272 100644 --- a/hassio/src/components/hassio-upload-snapshot.ts +++ b/hassio/src/components/hassio-upload-snapshot.ts @@ -43,6 +43,7 @@ export class HassioUploadSnapshot extends LitElement { accept="application/x-tar" label="Upload snapshot" @file-picked=${this._uploadFile} + auto-open-file-dialog > `; } @@ -54,6 +55,7 @@ export class HassioUploadSnapshot extends LitElement { showAlertDialog(this, { title: "Unsupported file format", text: "Please choose a Home Assistant snapshot file (.tar)", + confirmText: "ok", }); return; } @@ -64,7 +66,8 @@ export class HassioUploadSnapshot extends LitElement { } catch (err) { showAlertDialog(this, { title: "Upload failed", - text: extractApiErrorMessage(err), + text: err.toString(), + confirmText: "ok", }); } finally { this._uploading = false; diff --git a/hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts b/hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts index 38862da37dce..f4dfca8c9ac8 100644 --- a/hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts +++ b/hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts @@ -1,4 +1,6 @@ +import { mdiClose } from "@mdi/js"; import { + css, CSSResult, customElement, html, @@ -8,7 +10,7 @@ import { TemplateResult, } from "lit-element"; import { fireEvent } from "../../../../src/common/dom/fire_event"; -import { createCloseHeading } from "../../../../src/components/ha-dialog"; +import "../../../../src/components/ha-header-bar"; import { HassDialog } from "../../../../src/dialogs/make-dialog-manager"; import { haStyleDialog } from "../../../../src/resources/styles"; import type { HomeAssistant } from "../../../../src/types"; @@ -30,7 +32,11 @@ export class DialogHassioSnapshotUpload extends LitElement } public closeDialog(): void { - this._params?.reloadSnapshot(); + if (!this._params?.onboarding) { + if (this._params?.reloadSnapshot) { + this._params.reloadSnapshot(); + } + } this._params = undefined; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -46,9 +52,19 @@ export class DialogHassioSnapshotUpload extends LitElement scrimClickAction escapeKeyAction hideActions + .heading=${true} @closed=${this.closeDialog} - .heading=${createCloseHeading(this.hass, "Upload snapshot")} > +
+ + + Upload snapshot + + + + + +
(a.name > b.name ? 1 : -1)); this._dialogParams = params; + this._onboarding = params.onboarding ?? false; } protected render(): TemplateResult { @@ -104,12 +108,17 @@ class HassioSnapshotDialog extends LitElement { return html``; } return html` - + +
+ + + ${this._computeName} + + + + + +
${this._snapshot.type === "full" ? "Full snapshot" @@ -182,11 +191,15 @@ class HassioSnapshotDialog extends LitElement { ${this._error ? html`

Error: ${this._error}

` : ""}
Actions:
- - - - Download Snapshot - + ${!this._onboarding + ? html` + + Download Snapshot + ` + : ""} ` : ""} - - - Delete Snapshot - + ${!this._onboarding + ? html` + + Delete Snapshot + ` + : ""} `; } static get styles(): CSSResult[] { return [ + haStyle, haStyleDialog, css` paper-checkbox { @@ -242,6 +261,18 @@ class HassioSnapshotDialog extends LitElement { .no-margin-top { margin-top: 0; } + ha-header-bar { + --mdc-theme-on-primary: var(--primary-text-color); + --mdc-theme-primary: var(--mdc-theme-surface); + flex-shrink: 0; + } + /* overrule the ha-style-dialog max-height on small screens */ + @media all and (max-width: 450px), all and (max-height: 500px) { + ha-header-bar { + --mdc-theme-primary: var(--app-header-background-color); + --mdc-theme-on-primary: var(--app-header-text-color, white); + } + } `, ]; } @@ -272,6 +303,8 @@ class HassioSnapshotDialog extends LitElement { if ( !(await showConfirmationDialog(this, { title: "Are you sure you want partially to restore this snapshot?", + confirmText: "restore", + dismissText: "cancel", })) ) { return; @@ -300,22 +333,31 @@ class HassioSnapshotDialog extends LitElement { data.password = this._snapshotPassword; } - this.hass - .callApi( - "POST", - - `hassio/snapshots/${this._snapshot!.slug}/restore/partial`, - data - ) - .then( - () => { - alert("Snapshot restored!"); - this._closeDialog(); - }, - (error) => { - this._error = error.body.message; - } - ); + if (!this._onboarding) { + this.hass + .callApi( + "POST", + + `hassio/snapshots/${this._snapshot!.slug}/restore/partial`, + data + ) + .then( + () => { + alert("Snapshot restored!"); + this._closeDialog(); + }, + (error) => { + this._error = error.body.message; + } + ); + } else { + fireEvent(this, "restoring"); + fetch(`/api/hassio/snapshots/${this._snapshot!.slug}/restore/partial`, { + method: "POST", + body: JSON.stringify(data), + }); + this._closeDialog(); + } } private async _fullRestoreClicked() { @@ -323,6 +365,8 @@ class HassioSnapshotDialog extends LitElement { !(await showConfirmationDialog(this, { title: "Are you sure you want to wipe your system and restore this snapshot?", + confirmText: "restore", + dismissText: "cancel", })) ) { return; @@ -331,28 +375,38 @@ class HassioSnapshotDialog extends LitElement { const data = this._snapshot!.protected ? { password: this._snapshotPassword } : undefined; - - this.hass - .callApi( - "POST", - `hassio/snapshots/${this._snapshot!.slug}/restore/full`, - data - ) - .then( - () => { - alert("Snapshot restored!"); - this._closeDialog(); - }, - (error) => { - this._error = error.body.message; - } - ); + if (!this._onboarding) { + this.hass + .callApi( + "POST", + `hassio/snapshots/${this._snapshot!.slug}/restore/full`, + data + ) + .then( + () => { + alert("Snapshot restored!"); + this._closeDialog(); + }, + (error) => { + this._error = error.body.message; + } + ); + } else { + fireEvent(this, "restoring"); + fetch(`/api/hassio/snapshots/${this._snapshot!.slug}/restore/full`, { + method: "POST", + body: JSON.stringify(data), + }); + this._closeDialog(); + } } private async _deleteClicked() { if ( !(await showConfirmationDialog(this, { title: "Are you sure you want to delete this snapshot?", + confirmText: "delete", + dismissText: "cancel", })) ) { return; @@ -363,7 +417,9 @@ class HassioSnapshotDialog extends LitElement { .callApi("POST", `hassio/snapshots/${this._snapshot!.slug}/remove`) .then( () => { - this._dialogParams!.onDelete(); + if (this._dialogParams!.onDelete) { + this._dialogParams!.onDelete(); + } this._closeDialog(); }, (error) => { diff --git a/hassio/src/dialogs/snapshot/show-dialog-hassio-snapshot.ts b/hassio/src/dialogs/snapshot/show-dialog-hassio-snapshot.ts index 478f295b7dea..8631815c2923 100644 --- a/hassio/src/dialogs/snapshot/show-dialog-hassio-snapshot.ts +++ b/hassio/src/dialogs/snapshot/show-dialog-hassio-snapshot.ts @@ -2,7 +2,8 @@ import { fireEvent } from "../../../../src/common/dom/fire_event"; export interface HassioSnapshotDialogParams { slug: string; - onDelete: () => void; + onDelete?: () => void; + onboarding?: boolean; } export const showHassioSnapshotDialog = ( diff --git a/hassio/src/dialogs/snapshot/show-dialog-snapshot-upload.ts b/hassio/src/dialogs/snapshot/show-dialog-snapshot-upload.ts index 4d8f1986b939..2fe087f8d39a 100644 --- a/hassio/src/dialogs/snapshot/show-dialog-snapshot-upload.ts +++ b/hassio/src/dialogs/snapshot/show-dialog-snapshot-upload.ts @@ -3,7 +3,8 @@ import "./dialog-hassio-snapshot-upload"; export interface HassioSnapshotUploadDialogParams { showSnapshot: (slug: string) => void; - reloadSnapshot: () => Promise; + reloadSnapshot?: () => Promise; + onboarding?: boolean; } export const showSnapshotUploadDialog = ( diff --git a/src/data/hassio/snapshot.ts b/src/data/hassio/snapshot.ts index f08d5a3428f4..ad70f4f91725 100644 --- a/src/data/hassio/snapshot.ts +++ b/src/data/hassio/snapshot.ts @@ -46,12 +46,22 @@ export const fetchHassioSnapshotInfo = async ( hass: HomeAssistant, snapshot: string ) => { - return hassioApiResultExtractor( - await hass.callApi>( - "GET", - `hassio/snapshots/${snapshot}/info` - ) - ); + if (hass) { + return hassioApiResultExtractor( + await hass.callApi>( + "GET", + `hassio/snapshots/${snapshot}/info` + ) + ); + } else { + // When called from onboarding we don't have hass + const resp = await fetch(`/api/hassio/snapshots/${snapshot}/info`, { + method: "GET", + }); + const data = (await resp.json()).data; + console.log(data); + return data; + } }; export const reloadHassioSnapshots = async (hass: HomeAssistant) => { @@ -85,15 +95,25 @@ export const uploadSnapshot = async ( file: File ): Promise> => { const fd = new FormData(); + let resp; fd.append("file", file); - const resp = await hass.fetchWithAuth("/api/hassio/snapshots/new/upload", { - method: "POST", - body: fd, - }); + if (hass) { + resp = await hass.fetchWithAuth("/api/hassio/snapshots/new/upload", { + method: "POST", + body: fd, + }); + } else { + // When called from onboarding we don't have hass + resp = await fetch("/api/hassio/snapshots/new/upload", { + method: "POST", + body: fd, + }); + } + if (resp.status === 413) { throw new Error("Uploaded snapshot is too large"); } else if (resp.status !== 200) { - throw new Error("Unknown error"); + throw new Error(`${resp.status} ${resp.statusText}`); } return await resp.json(); }; diff --git a/src/onboarding/ha-onboarding.ts b/src/onboarding/ha-onboarding.ts index cdd1a3af0288..15cf10ec6fa6 100644 --- a/src/onboarding/ha-onboarding.ts +++ b/src/onboarding/ha-onboarding.ts @@ -1,21 +1,23 @@ import { Auth, createConnection, + genClientId, getAuth, subscribeConfig, - genClientId, } from "home-assistant-js-websocket"; import { customElement, html, - property, internalProperty, + property, PropertyValues, TemplateResult, } from "lit-element"; import { HASSDomEvent } from "../common/dom/fire_event"; +import { extractSearchParamsObject } from "../common/url/search-params"; import { subscribeOne } from "../common/util/subscribe-one"; -import { hassUrl, AuthUrlSearchParams } from "../data/auth"; +import { AuthUrlSearchParams, hassUrl } from "../data/auth"; +import { fetchDiscoveryInformation } from "../data/discovery"; import { fetchOnboardingOverview, OnboardingResponses, @@ -29,7 +31,6 @@ import { HomeAssistant } from "../types"; import { registerServiceWorker } from "../util/register-service-worker"; import "./onboarding-create-user"; import "./onboarding-loading"; -import { extractSearchParamsObject } from "../common/url/search-params"; type OnboardingEvent = | { @@ -62,6 +63,10 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { @internalProperty() private _loading = false; + @internalProperty() private _restoring = false; + + @internalProperty() private _supervisor?: boolean; + @internalProperty() private _steps?: OnboardingStep[]; protected render(): TemplateResult { @@ -72,10 +77,21 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { } if (step.step === "user") { return html` - + ${!this._restoring + ? html` + ` + : ""} + ${this._supervisor + ? html` + ` + : ""} `; } if (step.step === "core_config") { @@ -100,6 +116,7 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { protected firstUpdated(changedProps: PropertyValues) { super.firstUpdated(changedProps); this._fetchOnboardingSteps(); + this._fetchDiscoveryInformation(); import( /* webpackChunkName: "onboarding-integrations" */ "./onboarding-integrations" ); @@ -127,6 +144,28 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { return this._steps ? this._steps.find((stp) => !stp.done) : undefined; } + private _restoringSnapshot() { + this._restoring = true; + } + + private async _fetchDiscoveryInformation(): Promise { + try { + const response = await fetchDiscoveryInformation(); + this._supervisor = [ + "Home Assistant OS", + "Home Assistant Supervised", + ].includes(response.installation_type); + if (this._supervisor) { + // Only load if we have supervisor + import( + /* webpackChunkName: "onboarding-restore-snapshot" */ "./onboarding-restore-snapshot" + ); + } + } catch (err) { + alert("Something went wrong loading onboarding, try refreshing"); + } + } + private async _fetchOnboardingSteps() { try { const response = await (window.stepsPromise || fetchOnboardingOverview()); diff --git a/src/onboarding/onboarding-restore-snapshot.ts b/src/onboarding/onboarding-restore-snapshot.ts new file mode 100644 index 000000000000..ebdbce701ec6 --- /dev/null +++ b/src/onboarding/onboarding-restore-snapshot.ts @@ -0,0 +1,160 @@ +import { + css, + CSSResult, + customElement, + html, + internalProperty, + LitElement, + property, + TemplateResult, +} from "lit-element"; +import "../../hassio/src/components/hassio-ansi-to-html"; +import { showHassioSnapshotDialog } from "../../hassio/src/dialogs/snapshot/show-dialog-hassio-snapshot"; +import { showSnapshotUploadDialog } from "../../hassio/src/dialogs/snapshot/show-dialog-snapshot-upload"; +import { navigate } from "../common/navigate"; +import type { LocalizeFunc } from "../common/translations/localize"; +import "../components/ha-card"; +import { makeDialogManager } from "../dialogs/make-dialog-manager"; +import { ProvideHassLitMixin } from "../mixins/provide-hass-lit-mixin"; +import { haStyle } from "../resources/styles"; + +declare global { + interface HASSDomEvents { + restoring: undefined; + } +} + +@customElement("onboarding-restore-snapshot") +class OnboardingRestoreSnapshot extends ProvideHassLitMixin(LitElement) { + @property() public localize!: LocalizeFunc; + + @property() public language!: string; + + @property({ type: Boolean }) private restoring = false; + + @internalProperty() private _log?: string; + + protected render(): TemplateResult { + return this.restoring + ? html` +

+ ${this.localize("ui.panel.page-onboarding.restore.in_progress")} +

+ ${this._log + ? html`` + : ""} +
` + : html` + + `; + } + + private _filterLogs(logs: string): string { + // Filter out logs that is not relevant to show during the restore + return logs + .split("\n") + .filter( + (entry) => + !entry.includes("/supervisor/logs") && + !entry.includes("/supervisor/ping") && + !entry.includes("DEBUG") + ) + .slice(-16, -1) // We only show the last 15 lines, anything beyond that is not a part of the restore + .join("\n") + .replace(/\s[A-Z]+\s\(\w+\)\s\[[\w.]+\]/gi, "") + .replace(/\d{2}-\d{2}-\d{2}\s/gi, ""); + } + + private _uploadSnapshot(): void { + showSnapshotUploadDialog(this, { + showSnapshot: (slug: string) => this._showSnapshotDialog(slug), + onboarding: true, + }); + } + + protected firstUpdated(changedProps) { + super.firstUpdated(changedProps); + makeDialogManager(this, this.shadowRoot!); + setInterval(() => this._getLogs(), 1000); + } + + private async _getLogs(): Promise { + if (this.restoring) { + try { + const response = await fetch("/api/hassio/supervisor/logs", { + method: "GET", + }); + const logs = await response.text(); + this._log = this._filterLogs(logs); + if (this._log.match(/\d{2}:\d{2}:\d{2}\s.*Restore\s\w+\sdone/)) { + // The log indicates that the restore done, navigate the user back to base + navigate(this, "/", true); + location.reload(); + } + } catch (err) { + this._log = err.toString(); + } + } + } + + private _showSnapshotDialog(slug: string): void { + showHassioSnapshotDialog(this, { + slug, + onboarding: true, + }); + } + + static get styles(): CSSResult[] { + return [ + haStyle, + css` + .log { + white-space: pre-wrap; + line-height: 22px; + } + ha-card { + padding: 4px; + margin-top: 8px; + } + h2:after { + display: inline-block; + animation: dots steps(1, end) 2s infinite; + content: ""; + } + + @keyframes dots { + 0% { + content: ""; + } + 25% { + content: "."; + } + 50% { + content: ".."; + } + 75% { + content: "..."; + } + } + + @media all and (min-width: 600px) { + ha-card { + width: 600px; + margin-left: -100px; + } + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "onboarding-restore-snapshot": OnboardingRestoreSnapshot; + } +} diff --git a/src/translations/en.json b/src/translations/en.json index 85fa6823adbe..b6ba555f82e0 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2811,6 +2811,10 @@ "intro": "Devices and services are represented in Home Assistant as integrations. You can set them up now, or do it later from the configuration screen.", "more_integrations": "More", "finish": "Finish" + }, + "restore": { + "description": "Alternatively you can restore from a previous snapshot.", + "in_progress": "Restore in progress" } }, "custom": { From 0708c68ae851976b2d17528c99f4ea9b78b4c86d Mon Sep 17 00:00:00 2001 From: Ludeeus Date: Mon, 28 Sep 2020 09:22:29 +0000 Subject: [PATCH 05/12] lint --- src/data/hassio/snapshot.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/data/hassio/snapshot.ts b/src/data/hassio/snapshot.ts index ad70f4f91725..28caec38106e 100644 --- a/src/data/hassio/snapshot.ts +++ b/src/data/hassio/snapshot.ts @@ -53,15 +53,14 @@ export const fetchHassioSnapshotInfo = async ( `hassio/snapshots/${snapshot}/info` ) ); - } else { - // When called from onboarding we don't have hass - const resp = await fetch(`/api/hassio/snapshots/${snapshot}/info`, { - method: "GET", - }); - const data = (await resp.json()).data; - console.log(data); - return data; } + // When called from onboarding we don't have hass + const resp = await fetch(`/api/hassio/snapshots/${snapshot}/info`, { + method: "GET", + }); + const data = (await resp.json()).data; + console.log(data); + return data; }; export const reloadHassioSnapshots = async (hass: HomeAssistant) => { From 9606e6cb0b11b10b30a464dcbeeeb8c97db48009 Mon Sep 17 00:00:00 2001 From: Ludeeus Date: Mon, 28 Sep 2020 09:27:30 +0000 Subject: [PATCH 06/12] console.die --- src/data/hassio/snapshot.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/data/hassio/snapshot.ts b/src/data/hassio/snapshot.ts index 28caec38106e..18157d125573 100644 --- a/src/data/hassio/snapshot.ts +++ b/src/data/hassio/snapshot.ts @@ -59,7 +59,6 @@ export const fetchHassioSnapshotInfo = async ( method: "GET", }); const data = (await resp.json()).data; - console.log(data); return data; }; From b086b39b9619e2002685301444e32f46a648c4e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Mon, 28 Sep 2020 11:31:06 +0200 Subject: [PATCH 07/12] Update hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts Co-authored-by: Bram Kragten --- hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts b/hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts index f4dfca8c9ac8..ed0532d29f25 100644 --- a/hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts +++ b/hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts @@ -32,8 +32,8 @@ export class DialogHassioSnapshotUpload extends LitElement } public closeDialog(): void { - if (!this._params?.onboarding) { - if (this._params?.reloadSnapshot) { + if (this._params && !this._params.onboarding) { + if (this._params.reloadSnapshot) { this._params.reloadSnapshot(); } } From 20ccd3f174534f145abb1e299f7d204920686d5b Mon Sep 17 00:00:00 2001 From: Ludeeus Date: Mon, 28 Sep 2020 09:34:53 +0000 Subject: [PATCH 08/12] lint --- hassio/src/components/hassio-upload-snapshot.ts | 1 - hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hassio/src/components/hassio-upload-snapshot.ts b/hassio/src/components/hassio-upload-snapshot.ts index ee1e733b8272..94c7828ad767 100644 --- a/hassio/src/components/hassio-upload-snapshot.ts +++ b/hassio/src/components/hassio-upload-snapshot.ts @@ -13,7 +13,6 @@ import { import { fireEvent } from "../../../src/common/dom/fire_event"; import "../../../src/components/ha-circular-progress"; import "../../../src/components/ha-svg-icon"; -import { extractApiErrorMessage } from "../../../src/data/hassio/common"; import { HassioSnapshot, uploadSnapshot, diff --git a/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts b/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts index 348a7e120773..790ebc467cb3 100755 --- a/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts +++ b/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts @@ -93,10 +93,10 @@ class HassioSnapshotDialog extends LitElement { public async showDialog(params: HassioSnapshotDialogParams) { this._snapshot = await fetchHassioSnapshotInfo(this.hass, params.slug); this._folders = _computeFolders( - this._snapshot.folders + this._snapshot?.folders ).sort((a: FolderItem, b: FolderItem) => (a.name > b.name ? 1 : -1)); this._addons = _computeAddons( - this._snapshot.addons + this._snapshot?.addons ).sort((a: AddonItem, b: AddonItem) => (a.name > b.name ? 1 : -1)); this._dialogParams = params; From 093b20672fa4b5071af41ef531f7f2f366188878 Mon Sep 17 00:00:00 2001 From: Ludeeus Date: Mon, 28 Sep 2020 09:53:55 +0000 Subject: [PATCH 09/12] Add padding to log --- src/onboarding/onboarding-restore-snapshot.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/onboarding/onboarding-restore-snapshot.ts b/src/onboarding/onboarding-restore-snapshot.ts index ebdbce701ec6..09117d569fea 100644 --- a/src/onboarding/onboarding-restore-snapshot.ts +++ b/src/onboarding/onboarding-restore-snapshot.ts @@ -121,6 +121,10 @@ class OnboardingRestoreSnapshot extends ProvideHassLitMixin(LitElement) { padding: 4px; margin-top: 8px; } + hassio-ansi-to-html { + display: block; + padding: 0 8px; + } h2:after { display: inline-block; animation: dots steps(1, end) 2s infinite; From 644cfcbe851f1681b353e943d28089603724df52 Mon Sep 17 00:00:00 2001 From: Ludeeus Date: Mon, 28 Sep 2020 10:58:38 +0000 Subject: [PATCH 10/12] Add simple log with spinner --- src/onboarding/onboarding-restore-snapshot.ts | 74 +++++++++++-------- src/translations/en.json | 4 +- 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/onboarding/onboarding-restore-snapshot.ts b/src/onboarding/onboarding-restore-snapshot.ts index 09117d569fea..302f4c8128b3 100644 --- a/src/onboarding/onboarding-restore-snapshot.ts +++ b/src/onboarding/onboarding-restore-snapshot.ts @@ -1,3 +1,4 @@ +import "@material/mwc-button/mwc-button"; import { css, CSSResult, @@ -17,6 +18,7 @@ import "../components/ha-card"; import { makeDialogManager } from "../dialogs/make-dialog-manager"; import { ProvideHassLitMixin } from "../mixins/provide-hass-lit-mixin"; import { haStyle } from "../resources/styles"; +import "./onboarding-loading"; declare global { interface HASSDomEvents { @@ -34,18 +36,35 @@ class OnboardingRestoreSnapshot extends ProvideHassLitMixin(LitElement) { @internalProperty() private _log?: string; + @internalProperty() private _showFullLog = false; + protected render(): TemplateResult { return this.restoring - ? html` -

- ${this.localize("ui.panel.page-onboarding.restore.in_progress")} -

+ ? html` ${this._log - ? html`` + ? this._showFullLog + ? html` + ` + : html` + + ` : ""} +
+ + ${this._showFullLog + ? this.localize("ui.panel.page-onboarding.restore.hide_log") + : this.localize("ui.panel.page-onboarding.restore.show_log")} + +
` : html`