diff --git a/src/panels/config/backup/dialogs/dialog-generate-backup.ts b/src/panels/config/backup/dialogs/dialog-generate-backup.ts index 97e011e104..0d794e6bc6 100644 --- a/src/panels/config/backup/dialogs/dialog-generate-backup.ts +++ b/src/panels/config/backup/dialogs/dialog-generate-backup.ts @@ -76,6 +76,9 @@ class DialogGenerateBackup extends LitElement implements HassDialog { } private _dialogClosed() { + if (this._params!.cancel) { + this._params!.cancel(); + } this._step = undefined; this._formData = undefined; this._agents = []; @@ -307,7 +310,7 @@ class DialogGenerateBackup extends LitElement implements HassDialog { // TODO: Fetch all addons const ALL_ADDONS = []; - const { slug } = await generateBackup(this.hass, { + const { backup_id } = await generateBackup(this.hass, { name, agent_ids: agents_mode === "all" @@ -318,7 +321,7 @@ class DialogGenerateBackup extends LitElement implements HassDialog { addons_included: addons_mode === "all" ? ALL_ADDONS : addons, }); - this._params!.submit?.({ slug }); + this._params!.submit?.({ backup_id }); this.closeDialog(); } diff --git a/src/panels/config/backup/dialogs/dialog-new-backup.ts b/src/panels/config/backup/dialogs/dialog-new-backup.ts new file mode 100644 index 0000000000..ae7a60efb2 --- /dev/null +++ b/src/panels/config/backup/dialogs/dialog-new-backup.ts @@ -0,0 +1,147 @@ +import { mdiBackupRestore, mdiClose, mdiCogs } from "@mdi/js"; +import type { CSSResultGroup } from "lit"; +import { LitElement, css, html, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { fireEvent } from "../../../../common/dom/fire_event"; +import "../../../../components/ha-dialog-header"; +import "../../../../components/ha-icon-button"; +import "../../../../components/ha-icon-next"; +import "../../../../components/ha-md-dialog"; +import "../../../../components/ha-md-list"; +import "../../../../components/ha-md-list-item"; +import "../../../../components/ha-svg-icon"; +import type { HassDialog } from "../../../../dialogs/make-dialog-manager"; +import { haStyle, haStyleDialog } from "../../../../resources/styles"; +import type { HomeAssistant } from "../../../../types"; +import type { NewBackupDialogParams } from "./show-dialog-new-backup"; + +@customElement("ha-dialog-new-backup") +class DialogNewBackup extends LitElement implements HassDialog { + @property({ attribute: false }) public hass!: HomeAssistant; + + @state() private _opened = false; + + @state() private _params?: NewBackupDialogParams; + + public showDialog(params: NewBackupDialogParams): void { + this._opened = true; + this._params = params; + } + + public closeDialog(): void { + if (this._params!.cancel) { + this._params!.cancel(); + } + if (this._opened) { + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + this._opened = false; + this._params = undefined; + } + + protected render() { + if (!this._opened || !this._params) { + return nothing; + } + + const heading = "New backup"; + + return html` + + + + + ${heading} + + +
+ + + + Use automatic backup settings + + Trigger a backup using the configured settings for automatic backups + + + + + + + Create a manual backup + + Create a backup with custom settings (e.g. specific add-ons, + database, etc.) + + + + +
+
+ `; + } + + private async _manual() { + this._params!.submit?.("manual"); + this.closeDialog(); + } + + private async _automatic() { + this._params!.submit?.("automatic"); + this.closeDialog(); + } + + static get styles(): CSSResultGroup { + return [ + haStyle, + haStyleDialog, + css` + ha-md-dialog { + --dialog-content-padding: 0; + max-width: 500px; + } + div[slot="content"] { + margin-top: -16px; + } + @media all and (max-width: 450px), all and (max-height: 500px) { + ha-md-dialog { + max-width: none; + } + div[slot="content"] { + margin-top: 0; + } + } + + ha-md-list { + background: none; + } + ha-md-list-item { + } + ha-icon-next { + width: 24px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-dialog-new-backup": DialogNewBackup; + } +} diff --git a/src/panels/config/backup/dialogs/show-dialog-generate-backup.ts b/src/panels/config/backup/dialogs/show-dialog-generate-backup.ts index 79bd55a3b3..05ef818ed8 100644 --- a/src/panels/config/backup/dialogs/show-dialog-generate-backup.ts +++ b/src/panels/config/backup/dialogs/show-dialog-generate-backup.ts @@ -1,7 +1,7 @@ import { fireEvent } from "../../../../common/dom/fire_event"; export interface GenerateBackupDialogParams { - submit?: (response: { slug: string }) => void; + submit?: (response: { backup_id: string }) => void; cancel?: () => void; } @@ -12,7 +12,7 @@ export const showGenerateBackupDialog = ( element: HTMLElement, params: GenerateBackupDialogParams ) => - new Promise<{ slug: string } | null>((resolve) => { + new Promise<{ backup_id: string } | null>((resolve) => { const origCancel = params.cancel; const origSubmit = params.submit; fireEvent(element, "show-dialog", { diff --git a/src/panels/config/backup/dialogs/show-dialog-new-backup.ts b/src/panels/config/backup/dialogs/show-dialog-new-backup.ts new file mode 100644 index 0000000000..a084bd4f11 --- /dev/null +++ b/src/panels/config/backup/dialogs/show-dialog-new-backup.ts @@ -0,0 +1,37 @@ +import { fireEvent } from "../../../../common/dom/fire_event"; + +export type NewBackupType = "automatic" | "manual"; +export interface NewBackupDialogParams { + submit?: (type: NewBackupType) => void; + cancel?: () => void; +} + +export const loadNewBackupDialog = () => import("./dialog-new-backup"); + +export const showNewBackupDialog = ( + element: HTMLElement, + params: NewBackupDialogParams +) => + new Promise((resolve) => { + const origCancel = params.cancel; + const origSubmit = params.submit; + fireEvent(element, "show-dialog", { + dialogTag: "ha-dialog-new-backup", + dialogImport: loadNewBackupDialog, + dialogParams: { + ...params, + cancel: () => { + resolve(null); + if (origCancel) { + origCancel(); + } + }, + submit: (response) => { + resolve(response); + if (origSubmit) { + origSubmit(response); + } + }, + }, + }); + }); diff --git a/src/panels/config/backup/ha-config-backup-dashboard.ts b/src/panels/config/backup/ha-config-backup-dashboard.ts index 72700deb65..70313b02ba 100644 --- a/src/panels/config/backup/ha-config-backup-dashboard.ts +++ b/src/panels/config/backup/ha-config-backup-dashboard.ts @@ -20,6 +20,7 @@ import "../../../components/ha-icon"; import "../../../components/ha-icon-next"; import "../../../components/ha-icon-overflow-menu"; import "../../../components/ha-svg-icon"; +import { getSignedPath } from "../../../data/auth"; import { fetchBackupInfo, getBackupDownloadUrl, @@ -37,10 +38,10 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import { haStyle } from "../../../resources/styles"; import type { HomeAssistant, Route } from "../../../types"; import { brandsUrl } from "../../../util/brands-url"; +import { fileDownload } from "../../../util/file_download"; import "./components/ha-backup-summary-card"; import { showGenerateBackupDialog } from "./dialogs/show-dialog-generate-backup"; -import { getSignedPath } from "../../../data/auth"; -import { fileDownload } from "../../../util/file_download"; +import { showNewBackupDialog } from "./dialogs/show-dialog-new-backup"; @customElement("ha-config-backup-dashboard") class HaConfigBackupDashboard extends SubscribeMixin(LitElement) { @@ -232,7 +233,7 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) { ?disabled=${this._backingUp} .label=${this.hass.localize("ui.panel.config.backup.create_backup")} extended - @click=${this._generateBackup} + @click=${this._newBackup} > @@ -251,6 +252,20 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) { this._backingUp = info.backing_up; } + private async _newBackup(): Promise { + const type = await showNewBackupDialog(this, {}); + + if (!type) { + return; + } + + if (type === "manual") { + await this._generateBackup(); + } else { + // Todo: implement trigger automatic backup + } + } + private async _generateBackup(): Promise { const response = await showGenerateBackupDialog(this, {});