Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore snapshot from onboarding #7132

Merged
merged 12 commits into from
Sep 29, 2020
7 changes: 4 additions & 3 deletions hassio/src/components/hassio-upload-snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -38,12 +37,12 @@ export class HassioUploadSnapshot extends LitElement {
public render(): TemplateResult {
return html`
<ha-file-upload
.hass=${this.hass}
.uploading=${this._uploading}
.icon=${mdiFolderUpload}
accept="application/x-tar"
label="Upload snapshot"
@file-picked=${this._uploadFile}
auto-open-file-dialog
></ha-file-upload>
`;
}
Expand All @@ -55,6 +54,7 @@ export class HassioUploadSnapshot extends LitElement {
showAlertDialog(this, {
title: "Unsupported file format",
text: "Please choose a Home Assistant snapshot file (.tar)",
confirmText: "ok",
});
return;
}
Expand All @@ -65,7 +65,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;
Expand Down
42 changes: 37 additions & 5 deletions hassio/src/dialogs/snapshot/dialog-hassio-snapshot-upload.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { mdiClose } from "@mdi/js";
import {
css,
CSSResult,
customElement,
html,
Expand All @@ -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";
Expand All @@ -30,7 +32,11 @@ export class DialogHassioSnapshotUpload extends LitElement
}

public closeDialog(): void {
this._params?.reloadSnapshot();
if (this._params && !this._params.onboarding) {
if (this._params.reloadSnapshot) {
this._params.reloadSnapshot();
}
}
this._params = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
Expand All @@ -46,9 +52,19 @@ export class DialogHassioSnapshotUpload extends LitElement
scrimClickAction
escapeKeyAction
hideActions
.heading=${true}
@closed=${this.closeDialog}
.heading=${createCloseHeading(this.hass, "Upload snapshot")}
>
<div slot="heading">
<ha-header-bar>
<span slot="title">
Upload snapshot
</span>
<mwc-icon-button slot="actionItems" dialogAction="cancel">
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
</mwc-icon-button>
</ha-header-bar>
</div>
<hassio-upload-snapshot
@snapshot-uploaded=${this._snapshotUploaded}
.hass=${this.hass}
Expand All @@ -63,8 +79,24 @@ export class DialogHassioSnapshotUpload extends LitElement
this.closeDialog();
}

static get styles(): CSSResult {
return haStyleDialog;
static get styles(): CSSResult[] {
return [
haStyleDialog,
css`
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);
}
}
`,
];
}
}

Expand Down
162 changes: 109 additions & 53 deletions hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import "@material/mwc-button";
import { mdiDelete, mdiDownload, mdiHistory } from "@mdi/js";
import { mdiClose, mdiDelete, mdiDownload, mdiHistory } from "@mdi/js";
import { PaperCheckboxElement } from "@polymer/paper-checkbox/paper-checkbox";
import "@polymer/paper-input/paper-input";
import {
Expand All @@ -12,7 +12,8 @@ import {
property,
TemplateResult,
} from "lit-element";
import { createCloseHeading } from "../../../../src/components/ha-dialog";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-header-bar";
import "../../../../src/components/ha-svg-icon";
import { getSignedPath } from "../../../../src/data/auth";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
Expand All @@ -22,7 +23,7 @@ import {
} from "../../../../src/data/hassio/snapshot";
import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box";
import { PolymerChangedEvent } from "../../../../src/polymer-types";
import { haStyleDialog } from "../../../../src/resources/styles";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { HassioSnapshotDialogParams } from "./show-dialog-hassio-snapshot";

Expand Down Expand Up @@ -75,6 +76,8 @@ class HassioSnapshotDialog extends LitElement {

@internalProperty() private _error?: string;

@internalProperty() private _onboarding = false;

@internalProperty() private _snapshot?: HassioSnapshotDetail;

@internalProperty() private _folders!: FolderItem[];
Expand All @@ -90,26 +93,32 @@ 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;
this._onboarding = params.onboarding ?? false;
}

protected render(): TemplateResult {
if (!this._dialogParams || !this._snapshot) {
return html``;
}
return html`
<ha-dialog
open
stacked
@closing=${this._closeDialog}
.heading=${createCloseHeading(this.hass, this._computeName)}
>
<ha-dialog open stacked @closing=${this._closeDialog} .heading=${true}>
<div slot="heading">
<ha-header-bar>
<span slot="title">
${this._computeName}
</span>
<mwc-icon-button slot="actionItems" dialogAction="cancel">
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
</mwc-icon-button>
</ha-header-bar>
</div>
<div class="details">
${this._snapshot.type === "full"
? "Full snapshot"
Expand Down Expand Up @@ -182,11 +191,15 @@ class HassioSnapshotDialog extends LitElement {
${this._error ? html` <p class="error">Error: ${this._error}</p> ` : ""}

<div>Actions:</div>

<mwc-button @click=${this._downloadClicked} slot="primaryAction">
<ha-svg-icon path=${mdiDownload} class="icon"></ha-svg-icon>
Download Snapshot
</mwc-button>
${!this._onboarding
? html`<mwc-button
@click=${this._downloadClicked}
slot="primaryAction"
>
<ha-svg-icon path=${mdiDownload} class="icon"></ha-svg-icon>
Download Snapshot
</mwc-button>`
: ""}

<mwc-button
@click=${this._partialRestoreClicked}
Expand All @@ -206,16 +219,22 @@ class HassioSnapshotDialog extends LitElement {
</mwc-button>
`
: ""}
<mwc-button @click=${this._deleteClicked} slot="secondaryAction">
<ha-svg-icon path=${mdiDelete} class="icon warning"></ha-svg-icon>
<span class="warning">Delete Snapshot</span>
</mwc-button>
${!this._onboarding
? html`<mwc-button
@click=${this._deleteClicked}
slot="secondaryAction"
>
<ha-svg-icon path=${mdiDelete} class="icon warning"></ha-svg-icon>
<span class="warning">Delete Snapshot</span>
</mwc-button>`
: ""}
</ha-dialog>
`;
}

static get styles(): CSSResult[] {
return [
haStyle,
haStyleDialog,
css`
paper-checkbox {
Expand All @@ -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);
}
}
`,
];
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -300,29 +333,40 @@ 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() {
if (
!(await showConfirmationDialog(this, {
title:
"Are you sure you want to wipe your system and restore this snapshot?",
confirmText: "restore",
dismissText: "cancel",
}))
) {
return;
Expand All @@ -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;
Expand All @@ -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) => {
Expand Down
Loading