mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Add dialog to change default backup location (#16610)
* Add dialog to change default backup location * Add guard * Update src/components/ha-mount-picker.ts Co-authored-by: Bram Kragten <mail@bramkragten.nl> --------- Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
cefaaadf95
commit
9111f58e52
@ -3,11 +3,11 @@ import { ActionDetail } from "@material/mwc-list";
|
|||||||
import "@material/mwc-list/mwc-list-item";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import { mdiBackupRestore, mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js";
|
import { mdiBackupRestore, mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
html,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
|
css,
|
||||||
|
html,
|
||||||
nothing,
|
nothing,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
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-icon-button";
|
||||||
import "../../../src/components/ha-svg-icon";
|
import "../../../src/components/ha-svg-icon";
|
||||||
import {
|
import {
|
||||||
|
HassioBackup,
|
||||||
fetchHassioBackups,
|
fetchHassioBackups,
|
||||||
friendlyFolderName,
|
friendlyFolderName,
|
||||||
HassioBackup,
|
|
||||||
reloadHassioBackups,
|
reloadHassioBackups,
|
||||||
removeBackup,
|
removeBackup,
|
||||||
} from "../../../src/data/hassio/backup";
|
} 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 { haStyle } from "../../../src/resources/styles";
|
||||||
import { HomeAssistant, Route } from "../../../src/types";
|
import { HomeAssistant, Route } from "../../../src/types";
|
||||||
import { showBackupUploadDialog } from "../dialogs/backup/show-dialog-backup-upload";
|
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 { showHassioBackupDialog } from "../dialogs/backup/show-dialog-hassio-backup";
|
||||||
import { showHassioCreateBackupDialog } from "../dialogs/backup/show-dialog-hassio-create-backup";
|
import { showHassioCreateBackupDialog } from "../dialogs/backup/show-dialog-hassio-create-backup";
|
||||||
import { supervisorTabs } from "../hassio-tabs";
|
import { supervisorTabs } from "../hassio-tabs";
|
||||||
@ -204,6 +205,9 @@ export class HassioBackups extends LitElement {
|
|||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
${this.supervisor.localize("common.reload")}
|
${this.supervisor.localize("common.reload")}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
|
<mwc-list-item>
|
||||||
|
${this.supervisor.localize("dialog.backup_location.title")}
|
||||||
|
</mwc-list-item>
|
||||||
${atLeastVersion(this.hass.config.version, 0, 116)
|
${atLeastVersion(this.hass.config.version, 0, 116)
|
||||||
? html`<mwc-list-item>
|
? html`<mwc-list-item>
|
||||||
${this.supervisor.localize("backup.upload_backup")}
|
${this.supervisor.localize("backup.upload_backup")}
|
||||||
@ -270,6 +274,9 @@ export class HassioBackups extends LitElement {
|
|||||||
this.refreshData();
|
this.refreshData();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
showHassioBackupLocationDialog(this, { supervisor: this.supervisor });
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
this._showUploadBackupDialog();
|
this._showUploadBackupDialog();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
154
hassio/src/dialogs/backup/dialog-hassio-backup-location.ts
Normal file
154
hassio/src/dialogs/backup/dialog-hassio-backup-location.ts
Normal file
@ -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<void> {
|
||||||
|
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`
|
||||||
|
<ha-dialog
|
||||||
|
open
|
||||||
|
scrimClickAction
|
||||||
|
escapeKeyAction
|
||||||
|
.heading=${this._dialogParams.supervisor.localize(
|
||||||
|
"dialog.backup_location.title"
|
||||||
|
)}
|
||||||
|
@closed=${this.closeDialog}
|
||||||
|
>
|
||||||
|
${this._error
|
||||||
|
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||||
|
: nothing}
|
||||||
|
|
||||||
|
<ha-form
|
||||||
|
.hass=${this.hass}
|
||||||
|
.data=${this._data}
|
||||||
|
.schema=${SCHEMA()}
|
||||||
|
.computeLabel=${this._computeLabelCallback}
|
||||||
|
.computeHelper=${this._computeHelperCallback}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
dialogInitialFocus
|
||||||
|
></ha-form>
|
||||||
|
<mwc-button
|
||||||
|
slot="secondaryAction"
|
||||||
|
@click=${this.closeDialog}
|
||||||
|
dialogInitialFocus
|
||||||
|
>
|
||||||
|
${this._dialogParams.supervisor.localize("common.cancel")}
|
||||||
|
</mwc-button>
|
||||||
|
<mwc-button
|
||||||
|
.disabled=${this._waiting || !this._data}
|
||||||
|
slot="primaryAction"
|
||||||
|
@click=${this._changeMount}
|
||||||
|
>
|
||||||
|
${this._dialogParams.supervisor.localize("common.save")}
|
||||||
|
</mwc-button>
|
||||||
|
</ha-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeLabelCallback = (
|
||||||
|
// @ts-ignore
|
||||||
|
schema: SchemaUnion<ReturnType<typeof SCHEMA>>
|
||||||
|
): string =>
|
||||||
|
this._dialogParams!.supervisor.localize(
|
||||||
|
`dialog.backup_location.options.${schema.name}.name`
|
||||||
|
) || schema.name;
|
||||||
|
|
||||||
|
private _computeHelperCallback = (
|
||||||
|
// @ts-ignore
|
||||||
|
schema: SchemaUnion<ReturnType<typeof SCHEMA>>
|
||||||
|
): 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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,
|
||||||
|
});
|
||||||
|
};
|
@ -55,9 +55,10 @@ class HaMountPicker extends LitElement {
|
|||||||
graphic="icon"
|
graphic="icon"
|
||||||
.value=${__BACKUP_DATA_DISK__}
|
.value=${__BACKUP_DATA_DISK__}
|
||||||
>
|
>
|
||||||
<span
|
<span>
|
||||||
>${this.hass.localize("ui.components.mount-picker.use_datadisk")}</span
|
${this.hass.localize("ui.components.mount-picker.use_datadisk") ||
|
||||||
>
|
"Use data disk for backup"}
|
||||||
|
</span>
|
||||||
<ha-svg-icon slot="graphic" .path=${mdiHarddisk}></ha-svg-icon>
|
<ha-svg-icon slot="graphic" .path=${mdiHarddisk}></ha-svg-icon>
|
||||||
</ha-list-item>`;
|
</ha-list-item>`;
|
||||||
return html`
|
return html`
|
||||||
@ -91,7 +92,7 @@ class HaMountPicker extends LitElement {
|
|||||||
? `:${mount.port}`
|
? `:${mount.port}`
|
||||||
: nothing}${mount.type === SupervisorMountType.NFS
|
: nothing}${mount.type === SupervisorMountType.NFS
|
||||||
? mount.path
|
? mount.path
|
||||||
: ` :${mount.share}`}</span
|
: `:${mount.share}`}</span
|
||||||
>
|
>
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
slot="graphic"
|
slot="graphic"
|
||||||
@ -137,6 +138,10 @@ class HaMountPicker extends LitElement {
|
|||||||
try {
|
try {
|
||||||
if (isComponentLoaded(this.hass, "hassio")) {
|
if (isComponentLoaded(this.hass, "hassio")) {
|
||||||
this._mounts = await fetchSupervisorMounts(this.hass);
|
this._mounts = await fetchSupervisorMounts(this.hass);
|
||||||
|
if (this.usage === SupervisorMountUsage.BACKUP && !this.value) {
|
||||||
|
this.value =
|
||||||
|
this._mounts.default_backup_mount || __BACKUP_DATA_DISK__;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this._error = this.hass.localize(
|
this._error = this.hass.localize(
|
||||||
"ui.components.mount-picker.error.no_supervisor"
|
"ui.components.mount-picker.error.no_supervisor"
|
||||||
|
@ -188,7 +188,7 @@ class HaConfigSectionStorage extends LitElement {
|
|||||||
? `:${mount.port}`
|
? `:${mount.port}`
|
||||||
: nothing}${mount.type === SupervisorMountType.NFS
|
: nothing}${mount.type === SupervisorMountType.NFS
|
||||||
? mount.path
|
? mount.path
|
||||||
: ` :${mount.share}`}
|
: `:${mount.share}`}
|
||||||
</span>
|
</span>
|
||||||
${mount.state !== SupervisorMountState.ACTIVE
|
${mount.state !== SupervisorMountState.ACTIVE
|
||||||
? html`<ha-icon-button
|
? html`<ha-icon-button
|
||||||
|
@ -5811,6 +5811,15 @@
|
|||||||
"attributes": "Attributes",
|
"attributes": "Attributes",
|
||||||
"device_path": "Device path"
|
"device_path": "Device path"
|
||||||
},
|
},
|
||||||
|
"backup_location": {
|
||||||
|
"title": "Change default backup location",
|
||||||
|
"options": {
|
||||||
|
"default_backup_mount": {
|
||||||
|
"name": "Default backup location",
|
||||||
|
"description": "The default location for backups."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"datadisk_move": {
|
"datadisk_move": {
|
||||||
"title": "[%key:supervisor::system::host::move_datadisk%]",
|
"title": "[%key:supervisor::system::host::move_datadisk%]",
|
||||||
"description": "You are currently using ''{current_path}'' as data disk. Moving data disks will reboot your device and it's estimated to take {time} minutes. Your Home Assistant installation will not be accessible during this period. Do not disconnect the power during the move!",
|
"description": "You are currently using ''{current_path}'' as data disk. Moving data disks will reboot your device and it's estimated to take {time} minutes. Your Home Assistant installation will not be accessible during this period. Do not disconnect the power during the move!",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user