Add icon and description for network mount locations (#23390)

* Use custom icon and name for network storage

* Add note to local backup location dialog
This commit is contained in:
Paul Bottein 2024-12-23 11:53:31 +01:00 committed by GitHub
parent 52e1f9315e
commit 6afcd4d770
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 127 additions and 48 deletions

View File

@ -220,6 +220,11 @@ export const CLOUD_AGENT = "cloud.cloud";
export const isLocalAgent = (agentId: string) =>
[CORE_LOCAL_AGENT, HASSIO_LOCAL_AGENT].includes(agentId);
export const isNetworkMountAgent = (agentId: string) => {
const [domain, name] = agentId.split(".");
return domain === "hassio" && name !== "local";
};
export const computeBackupAgentName = (
localize: LocalizeFunc,
agentId: string,
@ -229,6 +234,11 @@ export const computeBackupAgentName = (
return "This system";
}
const [domain, name] = agentId.split(".");
if (isNetworkMountAgent(agentId)) {
return name;
}
const domainName = domainToName(localize, domain);
// If there are multiple agents for a domain, show the name
@ -242,7 +252,23 @@ export const computeBackupAgentName = (
export const compareAgents = (a: string, b: string) => {
const isLocalA = isLocalAgent(a);
const isLocalB = isLocalAgent(b);
return isLocalA === isLocalB ? a.localeCompare(b) : isLocalA ? -1 : 1;
const isNetworkMountAgentA = isNetworkMountAgent(a);
const isNetworkMountAgentB = isNetworkMountAgent(b);
const getPriority = (isLocal: boolean, isNetworkMount: boolean) => {
if (isLocal) return 1;
if (isNetworkMount) return 2;
return 3;
};
const priorityA = getPriority(isLocalA, isNetworkMountAgentA);
const priorityB = getPriority(isLocalB, isNetworkMountAgentB);
if (priorityA !== priorityB) {
return priorityA - priorityB;
}
return a.localeCompare(b);
};
export const generateEncryptionKey = () => {

View File

@ -1,4 +1,4 @@
import { mdiHarddisk } from "@mdi/js";
import { mdiHarddisk, mdiNas } from "@mdi/js";
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
@ -14,6 +14,7 @@ import {
computeBackupAgentName,
fetchBackupAgentsInfo,
isLocalAgent,
isNetworkMountAgent,
} from "../../../../../data/backup";
import type { CloudStatus } from "../../../../../data/cloud";
import type { HomeAssistant } from "../../../../../types";
@ -52,6 +53,9 @@ class HaBackupConfigAgents extends LitElement {
if (agentId === CLOUD_AGENT) {
return "It stores one backup. The oldest backups are deleted.";
}
if (isNetworkMountAgent(agentId)) {
return "Network storage";
}
return "";
}
@ -75,20 +79,27 @@ class HaBackupConfigAgents extends LitElement {
<ha-svg-icon .path=${mdiHarddisk} slot="start">
</ha-svg-icon>
`
: html`
<img
.src=${brandsUrl({
domain,
type: "icon",
useFallback: true,
darkOptimized: this.hass.themes?.darkMode,
})}
crossorigin="anonymous"
referrerpolicy="no-referrer"
alt=""
slot="start"
/>
`}
: isNetworkMountAgent(agentId)
? html`
<ha-svg-icon
.path=${mdiNas}
slot="start"
></ha-svg-icon>
`
: html`
<img
.src=${brandsUrl({
domain,
type: "icon",
useFallback: true,
darkOptimized: this.hass.themes?.darkMode,
})}
crossorigin="anonymous"
referrerpolicy="no-referrer"
alt=""
slot="start"
/>
`}
<div slot="headline">${name}</div>
${description
? html`<div slot="supporting-text">${description}</div>`

View File

@ -1,4 +1,4 @@
import { mdiHarddisk } from "@mdi/js";
import { mdiHarddisk, mdiNas } from "@mdi/js";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
@ -7,7 +7,11 @@ import { computeDomain } from "../../../../common/entity/compute_domain";
import "../../../../components/ha-checkbox";
import "../../../../components/ha-formfield";
import "../../../../components/ha-svg-icon";
import { computeBackupAgentName, isLocalAgent } from "../../../../data/backup";
import {
computeBackupAgentName,
isLocalAgent,
isNetworkMountAgent,
} from "../../../../data/backup";
import type { HomeAssistant } from "../../../../types";
import { brandsUrl } from "../../../../util/brands-url";
@ -54,20 +58,22 @@ class HaBackupAgentsPicker extends LitElement {
? html`
<ha-svg-icon .path=${mdiHarddisk} slot="start"> </ha-svg-icon>
`
: html`
<img
.src=${brandsUrl({
domain,
type: "icon",
useFallback: true,
darkOptimized: this.hass.themes?.darkMode,
})}
crossorigin="anonymous"
referrerpolicy="no-referrer"
alt=""
slot="start"
/>
`}
: isNetworkMountAgent(agentId)
? html` <ha-svg-icon .path=${mdiNas} slot="start"></ha-svg-icon> `
: html`
<img
.src=${brandsUrl({
domain,
type: "icon",
useFallback: true,
darkOptimized: this.hass.themes?.darkMode,
})}
crossorigin="anonymous"
referrerpolicy="no-referrer"
alt=""
slot="start"
/>
`}
${name}
</span>
<ha-checkbox

View File

@ -5,6 +5,7 @@ import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-button";
import { createCloseHeading } from "../../../../components/ha-dialog";
import "../../../../components/ha-form/ha-form";
import "../../../../components/ha-alert";
import type {
HaFormSchema,
SchemaUnion,
@ -83,6 +84,11 @@ class LocalBackupLocationDialog extends LitElement {
@value-changed=${this._valueChanged}
dialogInitialFocus
></ha-form>
<ha-alert alert-type="info">
${this.hass.localize(
`ui.panel.config.backup.dialogs.local_backup_location.note`
)}
</ha-alert>
<ha-button
slot="secondaryAction"
@click=${this.closeDialog}
@ -139,6 +145,10 @@ class LocalBackupLocationDialog extends LitElement {
ha-dialog {
--mdc-dialog-max-width: 500px;
}
ha-form {
display: block;
margin-bottom: 16px;
}
`,
];
}

View File

@ -3,6 +3,7 @@ import {
mdiDotsVertical,
mdiDownload,
mdiHarddisk,
mdiNas,
mdiPlus,
mdiUpload,
} from "@mdi/js";
@ -43,6 +44,7 @@ import {
getBackupDownloadUrl,
getPreferredAgentForDownload,
isLocalAgent,
isNetworkMountAgent,
} from "../../../data/backup";
import type { ManagerStateEvent } from "../../../data/backup_manager";
import type { CloudStatus } from "../../../data/cloud";
@ -183,6 +185,15 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
></ha-svg-icon>
`;
}
if (isNetworkMountAgent(agentId)) {
return html`
<ha-svg-icon
.path=${mdiNas}
title=${name}
slot="graphic"
></ha-svg-icon>
`;
}
const domain = computeDomain(agentId);
return html`
<img

View File

@ -1,5 +1,11 @@
import type { ActionDetail } from "@material/mwc-list";
import { mdiDelete, mdiDotsVertical, mdiDownload, mdiHarddisk } from "@mdi/js";
import {
mdiDelete,
mdiDotsVertical,
mdiDownload,
mdiHarddisk,
mdiNas,
} from "@mdi/js";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { formatDateTime } from "../../../common/datetime/format_date_time";
@ -24,6 +30,7 @@ import {
getBackupDownloadUrl,
getPreferredAgentForDownload,
isLocalAgent,
isNetworkMountAgent,
} from "../../../data/backup";
import type { HassioAddonInfo } from "../../../data/hassio/addon";
import "../../../layouts/hass-subpage";
@ -184,21 +191,28 @@ class HaConfigBackupDetails extends LitElement {
>
</ha-svg-icon>
`
: html`
<img
.src=${brandsUrl({
domain,
type: "icon",
useFallback: true,
darkOptimized:
this.hass.themes?.darkMode,
})}
crossorigin="anonymous"
referrerpolicy="no-referrer"
alt=""
slot="start"
/>
`}
: isNetworkMountAgent(agentId)
? html`
<ha-svg-icon
.path=${mdiNas}
slot="start"
></ha-svg-icon>
`
: html`
<img
.src=${brandsUrl({
domain,
type: "icon",
useFallback: true,
darkOptimized:
this.hass.themes?.darkMode,
})}
crossorigin="anonymous"
referrerpolicy="no-referrer"
alt=""
slot="start"
/>
`}
<div slot="headline">${name}</div>
<div slot="supporting-text">
<span

View File

@ -2214,6 +2214,7 @@
"local_backup_location": {
"title": "Change local backup location",
"description": "Change the default location where local backups are stored on your Home Assistant instance.",
"note": "This location will be used when you create a backup using the supervisor actions in an automation for example.",
"options": {
"default_backup_mount": {
"name": "Default location"