diff --git a/hassio/src/addon-view/info/hassio-addon-info.ts b/hassio/src/addon-view/info/hassio-addon-info.ts index 51f02f651c..cfdd2fb439 100644 --- a/hassio/src/addon-view/info/hassio-addon-info.ts +++ b/hassio/src/addon-view/info/hassio-addon-info.ts @@ -50,7 +50,6 @@ import { startHassioAddon, stopHassioAddon, uninstallHassioAddon, - updateHassioAddon, validateHassioAddonOption, } from "../../../../src/data/hassio/addon"; import { @@ -69,6 +68,7 @@ import { HomeAssistant } from "../../../../src/types"; import { bytesToString } from "../../../../src/util/bytes-to-string"; import "../../components/hassio-card-content"; import "../../components/supervisor-metric"; +import { showDialogSupervisorAddonUpdate } from "../../dialogs/addon/show-dialog-addon-update"; import { showHassioMarkdownDialog } from "../../dialogs/markdown/show-dialog-hassio-markdown"; import { hassioStyle } from "../../resources/hassio-style"; import { addonArchIsSupported } from "../../util/addon"; @@ -210,12 +210,9 @@ class HassioAddonInfo extends LitElement { : ""}
- + Update - + ${this.addon.changelog ? html` @@ -936,38 +933,8 @@ class HassioAddonInfo extends LitElement { button.progress = false; } - private async _updateClicked(ev: CustomEvent): Promise { - const button = ev.currentTarget as any; - button.progress = true; - - const confirmed = await showConfirmationDialog(this, { - title: this.addon.name, - text: "Are you sure you want to update this add-on?", - confirmText: "update add-on", - dismissText: "no", - }); - - if (!confirmed) { - button.progress = false; - return; - } - - this._error = undefined; - try { - await updateHassioAddon(this.hass, this.addon.slug); - const eventdata = { - success: true, - response: undefined, - path: "update", - }; - fireEvent(this, "hass-api-called", eventdata); - } catch (err) { - showAlertDialog(this, { - title: "Failed to update addon", - text: extractApiErrorMessage(err), - }); - } - button.progress = false; + private async _updateClicked(): Promise { + showDialogSupervisorAddonUpdate(this, { addon: this.addon }); } private async _startClicked(ev: CustomEvent): Promise { diff --git a/hassio/src/dialogs/addon/dialog-supervisor-addon-update.ts b/hassio/src/dialogs/addon/dialog-supervisor-addon-update.ts new file mode 100644 index 0000000000..00c9854ef3 --- /dev/null +++ b/hassio/src/dialogs/addon/dialog-supervisor-addon-update.ts @@ -0,0 +1,179 @@ +import "@material/mwc-button/mwc-button"; +import { + css, + CSSResult, + customElement, + html, + internalProperty, + LitElement, + TemplateResult, +} from "lit-element"; +import { fireEvent } from "../../../../src/common/dom/fire_event"; +import "../../../../src/components/ha-circular-progress"; +import "../../../../src/components/ha-dialog"; +import "../../../../src/components/ha-settings-row"; +import "../../../../src/components/ha-svg-icon"; +import "../../../../src/components/ha-switch"; +import { + HassioAddonDetails, + updateHassioAddon, +} from "../../../../src/data/hassio/addon"; +import { extractApiErrorMessage } from "../../../../src/data/hassio/common"; +import { createHassioPartialSnapshot } from "../../../../src/data/hassio/snapshot"; +import { haStyle, haStyleDialog } from "../../../../src/resources/styles"; +import type { HomeAssistant } from "../../../../src/types"; +import { SupervisorDialogSupervisorAddonUpdateParams } from "./show-dialog-addon-update"; + +@customElement("dialog-supervisor-addon-update") +class DialogSupervisorAddonUpdate extends LitElement { + public hass!: HomeAssistant; + + public addon!: HassioAddonDetails; + + @internalProperty() private _opened = false; + + @internalProperty() private _createSnapshot = true; + + @internalProperty() private _action: "snapshot" | "update" | null = null; + + @internalProperty() private _error?: string; + + public async showDialog( + params: SupervisorDialogSupervisorAddonUpdateParams + ): Promise { + this._opened = true; + this.addon = params.addon; + await this.updateComplete; + } + + public closeDialog(): void { + this._action = null; + this._createSnapshot = true; + this._opened = false; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + + public focus(): void { + this.updateComplete.then(() => + (this.shadowRoot?.querySelector( + "[dialogInitialFocus]" + ) as HTMLElement)?.focus() + ); + } + + protected render(): TemplateResult { + return html` + + ${this._action === null + ? html`
+ Are you sure you want to update this add-on to version + ${this.addon.version_latest}? +
+ + + + Snapshot + + + Create a snapshot of the add-on before updating + + + + + + Cancel + + + Update + ` + : html` + +

+ ${this._action === "update" + ? `Update to version ${this.addon.version_latest} in progress` + : "Creating snapshot in progress"} +

`} + ${this._error ? html`

${this._error}

` : ""} +
+ `; + } + + private _toggleSnapshot() { + this._createSnapshot = !this._createSnapshot; + } + + private async _update() { + if (this._createSnapshot) { + this._action = "snapshot"; + try { + await createHassioPartialSnapshot(this.hass, { + name: `addon_${this.addon.slug}_${this.addon.version}`, + addons: [this.addon.slug], + homeassistant: false, + }); + } catch (err) { + this._error = extractApiErrorMessage(err); + this._action = null; + return; + } + } + + this._action = "update"; + try { + await updateHassioAddon(this.hass, this.addon.slug); + } catch (err) { + this._error = extractApiErrorMessage(err); + this._action = null; + return; + } + fireEvent(this, "supervisor-colllection-refresh", { colllection: "addon" }); + fireEvent(this, "supervisor-colllection-refresh", { + colllection: "supervisor", + }); + this.closeDialog(); + } + + static get styles(): CSSResult[] { + return [ + haStyle, + haStyleDialog, + css` + .form { + color: var(--primary-text-color); + } + + ha-settings-row { + margin-top: 32px; + padding: 0; + } + + ha-circular-progress { + display: block; + margin: 32px; + text-align: center; + } + + .progress-text { + text-align: center; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "dialog-supervisor-addon-update": DialogSupervisorAddonUpdate; + } +} diff --git a/hassio/src/dialogs/addon/show-dialog-addon-update.ts b/hassio/src/dialogs/addon/show-dialog-addon-update.ts new file mode 100644 index 0000000000..bb6bebe683 --- /dev/null +++ b/hassio/src/dialogs/addon/show-dialog-addon-update.ts @@ -0,0 +1,17 @@ +import { fireEvent } from "../../../../src/common/dom/fire_event"; +import { HassioAddonDetails } from "../../../../src/data/hassio/addon"; + +export interface SupervisorDialogSupervisorAddonUpdateParams { + addon: HassioAddonDetails; +} + +export const showDialogSupervisorAddonUpdate = ( + element: HTMLElement, + dialogParams: SupervisorDialogSupervisorAddonUpdateParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "dialog-supervisor-addon-update", + dialogImport: () => import("./dialog-supervisor-addon-update"), + dialogParams, + }); +}; diff --git a/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts b/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts index 9bdeec7793..34042058d3 100755 --- a/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts +++ b/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts @@ -95,7 +95,7 @@ class HassioSnapshotDialog extends LitElement { @internalProperty() private _snapshotPassword!: string; - @internalProperty() private _restoreHass: boolean | null | undefined = true; + @internalProperty() private _restoreHass = true; public async showDialog(params: HassioSnapshotDialogParams) { this._snapshot = await fetchHassioSnapshotInfo(this.hass, params.slug); @@ -109,6 +109,9 @@ class HassioSnapshotDialog extends LitElement { this._dialogParams = params; this._onboarding = params.onboarding ?? false; this.supervisor = params.supervisor; + if (!this._snapshot.homeassistant) { + this._restoreHass = false; + } } protected render(): TemplateResult { @@ -134,15 +137,17 @@ class HassioSnapshotDialog extends LitElement { (${this._computeSize})
${this._formatDatetime(this._snapshot.date)}
-
Home Assistant:
- - Home Assistant ${this._snapshot.homeassistant} - + ${this._snapshot.homeassistant + ? html`
Home Assistant:
+ + Home Assistant ${this._snapshot.homeassistant} + ` + : ""} ${this._folders.length ? html`
Folders:
@@ -334,7 +339,7 @@ class HassioSnapshotDialog extends LitElement { .map((folder) => folder.slug); const data: { - homeassistant: boolean | null | undefined; + homeassistant: boolean; addons: any; folders: any; password?: string; diff --git a/src/data/hassio/addon.ts b/src/data/hassio/addon.ts index 06a4760d42..5ebc579547 100644 --- a/src/data/hassio/addon.ts +++ b/src/data/hassio/addon.ts @@ -300,7 +300,7 @@ export const updateHassioAddon = async ( if (atLeastVersion(hass.config.version, 2021, 2, 4)) { await hass.callWS({ type: "supervisor/api", - endpoint: `/addons/${slug}/update`, + endpoint: `/store/addons/${slug}/update`, method: "post", timeout: null, }); diff --git a/src/data/hassio/snapshot.ts b/src/data/hassio/snapshot.ts index ecd82ded1c..307571a75f 100644 --- a/src/data/hassio/snapshot.ts +++ b/src/data/hassio/snapshot.ts @@ -29,9 +29,10 @@ export interface HassioFullSnapshotCreateParams { } export interface HassioPartialSnapshotCreateParams { name: string; - folders: string[]; - addons: string[]; + folders?: string[]; + addons?: string[]; password?: string; + homeassistant?: boolean; } export const fetchHassioSnapshots = async ( @@ -116,7 +117,7 @@ export const createHassioFullSnapshot = async ( export const createHassioPartialSnapshot = async ( hass: HomeAssistant, - data: HassioFullSnapshotCreateParams + data: HassioPartialSnapshotCreateParams ) => { if (atLeastVersion(hass.config.version, 2021, 2, 4)) { await hass.callWS({