diff --git a/src/data/supervisor/mounts.ts b/src/data/supervisor/mounts.ts index 6c2f19a01a..7d83c35b05 100644 --- a/src/data/supervisor/mounts.ts +++ b/src/data/supervisor/mounts.ts @@ -17,6 +17,10 @@ export enum SupervisorMountState { UNKNOWN = "unknown", } +interface MountOptions { + default_backup_mount?: string | null; +} + interface SupervisorMountBase { name: string; usage: SupervisorMountUsage; @@ -53,6 +57,7 @@ export type SupervisorMountRequestParams = | SupervisorCIFSMountRequestParams; export interface SupervisorMounts { + default_backup_mount: string | null; mounts: SupervisorMount[]; } @@ -111,3 +116,15 @@ export const reloadSupervisorMount = async ( method: "post", timeout: null, }); + +export const changeMountOptions = async ( + hass: HomeAssistant, + data: MountOptions +): Promise => + hass.callWS({ + type: "supervisor/api", + endpoint: `/mounts/options`, + method: "post", + timeout: null, + data, + }); diff --git a/src/panels/config/storage/ha-config-section-storage.ts b/src/panels/config/storage/ha-config-section-storage.ts index a70454576d..210bbba63a 100644 --- a/src/panels/config/storage/ha-config-section-storage.ts +++ b/src/panels/config/storage/ha-config-section-storage.ts @@ -15,6 +15,7 @@ import "../../../components/ha-button-menu"; import "../../../components/ha-icon-button"; import "../../../components/ha-metric"; import "../../../components/ha-svg-icon"; +import "../../../components/ha-icon-next"; import { extractApiErrorMessage } from "../../../data/hassio/common"; import { HassioHostInfo, fetchHassioHostInfo } from "../../../data/hassio/host"; import { @@ -22,6 +23,7 @@ import { SupervisorMountState, SupervisorMountType, SupervisorMountUsage, + SupervisorMounts, fetchSupervisorMounts, reloadSupervisorMount, } from "../../../data/supervisor/mounts"; @@ -35,6 +37,7 @@ import { import "../core/ha-config-analytics"; import { showMoveDatadiskDialog } from "./show-dialog-move-datadisk"; import { showMountViewDialog } from "./show-dialog-view-mount"; +import { navigate } from "../../../common/navigate"; @customElement("ha-config-section-storage") class HaConfigSectionStorage extends LitElement { @@ -48,7 +51,7 @@ class HaConfigSectionStorage extends LitElement { @state() private _hostInfo?: HassioHostInfo; - @state() private _mounts?: SupervisorMount[]; + @state() private _mountsInfo?: SupervisorMounts | null; protected firstUpdated(changedProps: PropertyValues) { super.firstUpdated(changedProps); @@ -57,7 +60,14 @@ class HaConfigSectionStorage extends LitElement { } } - protected render(): TemplateResult { + protected render(): TemplateResult | typeof nothing { + if (this._mountsInfo === undefined) { + return nothing; + } + const validMounts = this._mountsInfo?.mounts.filter((mount) => + [SupervisorMountType.CIFS, SupervisorMountType.NFS].includes(mount.type) + ); + const isHAOS = this._hostInfo?.features.includes("haos"); return html` ` : ""} + - ${this._mounts?.length + ${this._mountsInfo === null + ? html` + ${isHAOS + ? html`${this.hass.localize( + "ui.panel.config.storage.network_mounts.not_supported.haos" + )} + + ${this.hass.localize( + "ui.panel.config.storage.network_mounts.not_supported.navigate_to_updates" + )} + ` + : this.hass.localize( + "ui.panel.config.storage.network_mounts.not_supported.supervised" + )} + ` + : validMounts?.length ? html` - ${this._mounts.map( + ${validMounts.map( (mount) => html`
@@ -155,18 +190,20 @@ class HaConfigSectionStorage extends LitElement { ? mount.path : ` :${mount.share}`} - + ${mount.state !== SupervisorMountState.ACTIVE + ? html`` + : html``} ` )} ` - : html`
+ : html`

${this.hass.localize( @@ -174,14 +211,15 @@ class HaConfigSectionStorage extends LitElement { )}

`} - -
- - ${this.hass.localize( - "ui.panel.config.storage.network_mounts.add_title" - )} - -
+ ${this._mountsInfo !== null + ? html`
+ + ${this.hass.localize( + "ui.panel.config.storage.network_mounts.add_title" + )} + +
` + : nothing}
@@ -190,13 +228,15 @@ class HaConfigSectionStorage extends LitElement { private async _load() { try { - [this._hostInfo] = await Promise.all([ - fetchHassioHostInfo(this.hass), - this._reloadMounts(), - ]); + this._hostInfo = await fetchHassioHostInfo(this.hass); } catch (err: any) { this._error = err.message || err; } + if (this._hostInfo?.features.includes("mount")) { + await this._reloadMounts(); + } else { + this._mountsInfo = null; + } } private _moveDatadisk(): void { @@ -205,6 +245,10 @@ class HaConfigSectionStorage extends LitElement { }); } + private async _navigateToUpdates(): Promise { + navigate("/config/updates"); + } + private async _reloadMount(ev: Event): Promise { ev.stopPropagation(); const mount: SupervisorMount = (ev.currentTarget as any).mount; @@ -224,7 +268,9 @@ class HaConfigSectionStorage extends LitElement { } private _addMount(): void { - showMountViewDialog(this, { reloadMounts: this._reloadMounts }); + showMountViewDialog(this, { + reloadMounts: this._reloadMounts, + }); } private _changeMount(ev: Event): void { @@ -237,12 +283,10 @@ class HaConfigSectionStorage extends LitElement { private async _reloadMounts(): Promise { try { - const allMounts = await fetchSupervisorMounts(this.hass); - this._mounts = allMounts.mounts.filter((mount) => - [SupervisorMountType.CIFS, SupervisorMountType.NFS].includes(mount.type) - ); + this._mountsInfo = await fetchSupervisorMounts(this.hass); } catch (err: any) { this._error = err.message || err; + this._mountsInfo = null; } } @@ -274,6 +318,10 @@ class HaConfigSectionStorage extends LitElement { color: var(--warning-color); } + .mounts-not-supported { + padding: 0 16px 16px; + } + .reload-btn { float: right; position: relative; @@ -295,6 +343,14 @@ class HaConfigSectionStorage extends LitElement { border-radius: 50%; margin-bottom: 8px; } + ha-list-item { + --mdc-list-item-meta-size: auto; + --mdc-list-item-meta-display: flex; + } + ha-svg-icon, + ha-icon-next { + width: 24px; + } `; } diff --git a/src/translations/en.json b/src/translations/en.json index af26725b52..883c6542bd 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3987,6 +3987,12 @@ "add_title": "Add network storage", "update_title": "Update network storage", "no_mounts": "No connected network storage", + "not_supported": { + "title": "The operating system does not support network storage", + "supervised": "Network storage is not supported on this host", + "haos": "To use network storage you need to run at least Home Assistant Operating System 10.0", + "navigate_to_updates": "Go to updates" + }, "mount_usage": { "backup": "Backup", "media": "Media" @@ -4008,6 +4014,10 @@ "title": "Server", "description": "This is the domain name (FQDN) or IP address of the storage server you want to connect to" }, + "default_backup_mount": { + "title": "Default backup location", + "description": "This will be the default location for backups" + }, "path": { "title": "Remote share path", "description": "This is the path of the remote share on your storage server"