diff --git a/hassio/src/backups/hassio-backups.ts b/hassio/src/backups/hassio-backups.ts
index 8e8aebb183..382f8ec669 100644
--- a/hassio/src/backups/hassio-backups.ts
+++ b/hassio/src/backups/hassio-backups.ts
@@ -3,11 +3,11 @@ import { ActionDetail } from "@material/mwc-list";
import "@material/mwc-list/mwc-list-item";
import { mdiBackupRestore, mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js";
import {
- css,
CSSResultGroup,
- html,
LitElement,
PropertyValues,
+ css,
+ html,
nothing,
} from "lit";
import { customElement, property, query, state } from "lit/decorators";
@@ -26,9 +26,9 @@ import "../../../src/components/ha-fab";
import "../../../src/components/ha-icon-button";
import "../../../src/components/ha-svg-icon";
import {
+ HassioBackup,
fetchHassioBackups,
friendlyFolderName,
- HassioBackup,
reloadHassioBackups,
removeBackup,
} from "../../../src/data/hassio/backup";
@@ -43,6 +43,7 @@ import type { HaTabsSubpageDataTable } from "../../../src/layouts/hass-tabs-subp
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant, Route } from "../../../src/types";
import { showBackupUploadDialog } from "../dialogs/backup/show-dialog-backup-upload";
+import { showHassioBackupLocationDialog } from "../dialogs/backup/show-dialog-hassio-backu-location";
import { showHassioBackupDialog } from "../dialogs/backup/show-dialog-hassio-backup";
import { showHassioCreateBackupDialog } from "../dialogs/backup/show-dialog-hassio-create-backup";
import { supervisorTabs } from "../hassio-tabs";
@@ -204,6 +205,9 @@ export class HassioBackups extends LitElement {
${this.supervisor.localize("common.reload")}
+
+ ${this.supervisor.localize("dialog.backup_location.title")}
+
${atLeastVersion(this.hass.config.version, 0, 116)
? html`
${this.supervisor.localize("backup.upload_backup")}
@@ -270,6 +274,9 @@ export class HassioBackups extends LitElement {
this.refreshData();
break;
case 1:
+ showHassioBackupLocationDialog(this, { supervisor: this.supervisor });
+ break;
+ case 2:
this._showUploadBackupDialog();
break;
}
diff --git a/hassio/src/dialogs/backup/dialog-hassio-backup-location.ts b/hassio/src/dialogs/backup/dialog-hassio-backup-location.ts
new file mode 100644
index 0000000000..18292149bd
--- /dev/null
+++ b/hassio/src/dialogs/backup/dialog-hassio-backup-location.ts
@@ -0,0 +1,154 @@
+import "@material/mwc-button/mwc-button";
+import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
+import { customElement, property, state } from "lit/decorators";
+import memoizeOne from "memoize-one";
+import { fireEvent } from "../../../../src/common/dom/fire_event";
+import "../../../../src/components/ha-dialog";
+import "../../../../src/components/ha-form/ha-form";
+import type { SchemaUnion } from "../../../../src/components/ha-form/types";
+import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
+import { changeMountOptions } from "../../../../src/data/supervisor/mounts";
+import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
+import { HomeAssistant } from "../../../../src/types";
+import { HassioBackupLocationDialogParams } from "./show-dialog-hassio-backu-location";
+
+const SCHEMA = memoizeOne(
+ () =>
+ [
+ {
+ name: "default_backup_mount",
+ required: true,
+ selector: { backup_location: {} },
+ },
+ ] as const
+);
+
+@customElement("dialog-hassio-backup-location")
+class HassioBackupLocationDialog extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property({ attribute: false })
+ public _dialogParams?: HassioBackupLocationDialogParams;
+
+ @state() private _data?: { default_backup_mount: string | null };
+
+ @state() private _waiting?: boolean;
+
+ @state() private _error?: string;
+
+ public async showDialog(
+ dialogParams: HassioBackupLocationDialogParams
+ ): Promise {
+ this._dialogParams = dialogParams;
+ }
+
+ public closeDialog(): void {
+ this._data = undefined;
+ this._error = undefined;
+ this._waiting = undefined;
+ this._dialogParams = undefined;
+ fireEvent(this, "dialog-closed", { dialog: this.localName });
+ }
+
+ protected render() {
+ if (!this._dialogParams) {
+ return nothing;
+ }
+ return html`
+
+ ${this._error
+ ? html`${this._error}`
+ : nothing}
+
+
+
+ ${this._dialogParams.supervisor.localize("common.cancel")}
+
+
+ ${this._dialogParams.supervisor.localize("common.save")}
+
+
+ `;
+ }
+
+ private _computeLabelCallback = (
+ // @ts-ignore
+ schema: SchemaUnion>
+ ): string =>
+ this._dialogParams!.supervisor.localize(
+ `dialog.backup_location.options.${schema.name}.name`
+ ) || schema.name;
+
+ private _computeHelperCallback = (
+ // @ts-ignore
+ schema: SchemaUnion>
+ ): string =>
+ this._dialogParams!.supervisor.localize(
+ `dialog.backup_location.options.${schema.name}.description`
+ );
+
+ private _valueChanged(ev: CustomEvent) {
+ const newLocation = ev.detail.value.default_backup_mount;
+ this._data = {
+ default_backup_mount: newLocation === "/backup" ? null : newLocation,
+ };
+ }
+
+ private async _changeMount() {
+ if (!this._data) {
+ return;
+ }
+ this._error = undefined;
+ this._waiting = true;
+ try {
+ await changeMountOptions(this.hass, this._data);
+ } catch (err: any) {
+ this._error = extractApiErrorMessage(err);
+ this._waiting = false;
+ return;
+ }
+ this.closeDialog();
+ }
+
+ static get styles(): CSSResultGroup {
+ return [
+ haStyle,
+ haStyleDialog,
+ css`
+ .delete-btn {
+ --mdc-theme-primary: var(--error-color);
+ }
+ `,
+ ];
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "dialog-hassio-backup-location": HassioBackupLocationDialog;
+ }
+}
diff --git a/hassio/src/dialogs/backup/show-dialog-hassio-backu-location.ts b/hassio/src/dialogs/backup/show-dialog-hassio-backu-location.ts
new file mode 100644
index 0000000000..43a82f1141
--- /dev/null
+++ b/hassio/src/dialogs/backup/show-dialog-hassio-backu-location.ts
@@ -0,0 +1,17 @@
+import { fireEvent } from "../../../../src/common/dom/fire_event";
+import { Supervisor } from "../../../../src/data/supervisor/supervisor";
+
+export interface HassioBackupLocationDialogParams {
+ supervisor: Supervisor;
+}
+
+export const showHassioBackupLocationDialog = (
+ element: HTMLElement,
+ dialogParams: HassioBackupLocationDialogParams
+): void => {
+ fireEvent(element, "show-dialog", {
+ dialogTag: "dialog-hassio-backup-location",
+ dialogImport: () => import("./dialog-hassio-backup-location"),
+ dialogParams,
+ });
+};
diff --git a/src/components/ha-mount-picker.ts b/src/components/ha-mount-picker.ts
index d7bdc80af5..6e0da26b4a 100644
--- a/src/components/ha-mount-picker.ts
+++ b/src/components/ha-mount-picker.ts
@@ -55,9 +55,10 @@ class HaMountPicker extends LitElement {
graphic="icon"
.value=${__BACKUP_DATA_DISK__}
>
- ${this.hass.localize("ui.components.mount-picker.use_datadisk")}
+
+ ${this.hass.localize("ui.components.mount-picker.use_datadisk") ||
+ "Use data disk for backup"}
+
`;
return html`
@@ -91,7 +92,7 @@ class HaMountPicker extends LitElement {
? `:${mount.port}`
: nothing}${mount.type === SupervisorMountType.NFS
? mount.path
- : ` :${mount.share}`}
${mount.state !== SupervisorMountState.ACTIVE
? html`