mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-18 23:06:40 +00:00
Reintroduce backup switch when updating core and addons (#23814)
This commit is contained in:
parent
bc21877008
commit
5453da75ea
@ -9,6 +9,7 @@ import {
|
|||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../src/common/dom/fire_event";
|
||||||
import "../../../src/components/buttons/ha-progress-button";
|
import "../../../src/components/buttons/ha-progress-button";
|
||||||
import "../../../src/components/ha-alert";
|
import "../../../src/components/ha-alert";
|
||||||
@ -18,7 +19,11 @@ import "../../../src/components/ha-checkbox";
|
|||||||
import "../../../src/components/ha-faded";
|
import "../../../src/components/ha-faded";
|
||||||
import "../../../src/components/ha-icon-button";
|
import "../../../src/components/ha-icon-button";
|
||||||
import "../../../src/components/ha-markdown";
|
import "../../../src/components/ha-markdown";
|
||||||
|
import "../../../src/components/ha-md-list";
|
||||||
|
import "../../../src/components/ha-md-list-item";
|
||||||
import "../../../src/components/ha-svg-icon";
|
import "../../../src/components/ha-svg-icon";
|
||||||
|
import "../../../src/components/ha-switch";
|
||||||
|
import type { HaSwitch } from "../../../src/components/ha-switch";
|
||||||
import type { HassioAddonDetails } from "../../../src/data/hassio/addon";
|
import type { HassioAddonDetails } from "../../../src/data/hassio/addon";
|
||||||
import {
|
import {
|
||||||
fetchHassioAddonChangelog,
|
fetchHassioAddonChangelog,
|
||||||
@ -121,6 +126,8 @@ class UpdateAvailableCard extends LitElement {
|
|||||||
|
|
||||||
const changelog = changelogUrl(this._updateType, this._version_latest);
|
const changelog = changelogUrl(this._updateType, this._version_latest);
|
||||||
|
|
||||||
|
const createBackupTexts = this._computeCreateBackupTexts();
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-card
|
<ha-card
|
||||||
outlined
|
outlined
|
||||||
@ -160,6 +167,30 @@ class UpdateAvailableCard extends LitElement {
|
|||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
${createBackupTexts
|
||||||
|
? html`
|
||||||
|
<hr />
|
||||||
|
<ha-md-list>
|
||||||
|
<ha-md-list-item>
|
||||||
|
<span slot="headline">
|
||||||
|
${createBackupTexts.title}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
${createBackupTexts.description
|
||||||
|
? html`
|
||||||
|
<span slot="supporting-text">
|
||||||
|
${createBackupTexts.description}
|
||||||
|
</span>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
|
<ha-switch
|
||||||
|
slot="end"
|
||||||
|
id="create-backup"
|
||||||
|
></ha-switch>
|
||||||
|
</ha-md-list-item>
|
||||||
|
</ha-md-list>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
`
|
`
|
||||||
: html`<ha-circular-progress
|
: html`<ha-circular-progress
|
||||||
aria-label="Updating"
|
aria-label="Updating"
|
||||||
@ -227,6 +258,48 @@ class UpdateAvailableCard extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _computeCreateBackupTexts():
|
||||||
|
| { title: string; description?: string }
|
||||||
|
| undefined {
|
||||||
|
// Addon backup
|
||||||
|
if (
|
||||||
|
this._updateType === "addon" &&
|
||||||
|
atLeastVersion(this.hass.config.version, 2025, 2, 0)
|
||||||
|
) {
|
||||||
|
const version = this._version;
|
||||||
|
return {
|
||||||
|
title: this.supervisor.localize("update_available.create_backup.addon"),
|
||||||
|
description: this.supervisor.localize(
|
||||||
|
"update_available.create_backup.addon_description",
|
||||||
|
{ version: version }
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Old behavior
|
||||||
|
if (this._updateType && ["core", "addon"].includes(this._updateType)) {
|
||||||
|
return {
|
||||||
|
title: this.supervisor.localize(
|
||||||
|
"update_available.create_backup.generic"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
get _shouldCreateBackup(): boolean {
|
||||||
|
if (this._updateType && !["core", "addon"].includes(this._updateType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const createBackupSwitch = this.shadowRoot?.getElementById(
|
||||||
|
"create-backup"
|
||||||
|
) as HaSwitch;
|
||||||
|
if (createBackupSwitch) {
|
||||||
|
return createBackupSwitch.checked;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
get _version(): string {
|
get _version(): string {
|
||||||
return this._updateType
|
return this._updateType
|
||||||
? this._updateType === "addon"
|
? this._updateType === "addon"
|
||||||
@ -341,14 +414,22 @@ class UpdateAvailableCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _update() {
|
private async _update() {
|
||||||
|
if (this._shouldCreateBackup && this.supervisor.info.state === "freeze") {
|
||||||
|
this._error = this.supervisor.localize("backup.backup_already_running");
|
||||||
|
return;
|
||||||
|
}
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._updating = true;
|
this._updating = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (this._updateType === "addon") {
|
if (this._updateType === "addon") {
|
||||||
await updateHassioAddon(this.hass, this.addonSlug!);
|
await updateHassioAddon(
|
||||||
|
this.hass,
|
||||||
|
this.addonSlug!,
|
||||||
|
this._shouldCreateBackup
|
||||||
|
);
|
||||||
} else if (this._updateType === "core") {
|
} else if (this._updateType === "core") {
|
||||||
await updateCore(this.hass);
|
await updateCore(this.hass, this._shouldCreateBackup);
|
||||||
} else if (this._updateType === "os") {
|
} else if (this._updateType === "os") {
|
||||||
await updateOS(this.hass);
|
await updateOS(this.hass);
|
||||||
} else if (this._updateType === "supervisor") {
|
} else if (this._updateType === "supervisor") {
|
||||||
@ -403,6 +484,17 @@ class UpdateAvailableCard extends LitElement {
|
|||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
margin: 16px 0 0 0;
|
margin: 16px 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ha-md-list {
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: -16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-md-list-item {
|
||||||
|
--md-list-item-leading-space: 0;
|
||||||
|
--md-list-item-trailing-space: 0;
|
||||||
|
--md-item-overflow: visible;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -313,21 +313,34 @@ export const installHassioAddon = async (
|
|||||||
|
|
||||||
export const updateHassioAddon = async (
|
export const updateHassioAddon = async (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
slug: string
|
slug: string,
|
||||||
|
backup: boolean
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
|
if (atLeastVersion(hass.config.version, 2025, 2, 0)) {
|
||||||
|
await hass.callWS({
|
||||||
|
type: "hassio/update/addon",
|
||||||
|
addon: slug,
|
||||||
|
backup: backup,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||||
await hass.callWS({
|
await hass.callWS({
|
||||||
type: "supervisor/api",
|
type: "supervisor/api",
|
||||||
endpoint: `/store/addons/${slug}/update`,
|
endpoint: `/store/addons/${slug}/update`,
|
||||||
method: "post",
|
method: "post",
|
||||||
timeout: null,
|
timeout: null,
|
||||||
|
data: { backup },
|
||||||
});
|
});
|
||||||
} else {
|
return;
|
||||||
await hass.callApi<HassioResponse<void>>(
|
|
||||||
"POST",
|
|
||||||
`hassio/addons/${slug}/update`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await hass.callApi<HassioResponse<void>>(
|
||||||
|
"POST",
|
||||||
|
`hassio/addons/${slug}/update`,
|
||||||
|
{ backup }
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const restartHassioAddon = async (
|
export const restartHassioAddon = async (
|
||||||
|
@ -6,15 +6,27 @@ export const restartCore = async (hass: HomeAssistant) => {
|
|||||||
await hass.callService("homeassistant", "restart");
|
await hass.callService("homeassistant", "restart");
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateCore = async (hass: HomeAssistant) => {
|
export const updateCore = async (hass: HomeAssistant, backup: boolean) => {
|
||||||
|
if (atLeastVersion(hass.config.version, 2025, 2, 0)) {
|
||||||
|
await hass.callWS({
|
||||||
|
type: "hassio/update/core",
|
||||||
|
backup: backup,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||||
await hass.callWS({
|
await hass.callWS({
|
||||||
type: "supervisor/api",
|
type: "supervisor/api",
|
||||||
endpoint: "/core/update",
|
endpoint: "/core/update",
|
||||||
method: "post",
|
method: "post",
|
||||||
timeout: null,
|
timeout: null,
|
||||||
|
data: { backup },
|
||||||
});
|
});
|
||||||
} else {
|
return;
|
||||||
await hass.callApi<HassioResponse<void>>("POST", "hassio/core/update");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await hass.callApi<HassioResponse<void>>("POST", "hassio/core/update", {
|
||||||
|
backup,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,7 @@ import { caseInsensitiveStringCompare } from "../common/string/compare";
|
|||||||
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
|
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import { showToast } from "../util/toast";
|
import { showToast } from "../util/toast";
|
||||||
|
import type { EntitySources } from "./entity_sources";
|
||||||
|
|
||||||
export enum UpdateEntityFeature {
|
export enum UpdateEntityFeature {
|
||||||
INSTALL = 1,
|
INSTALL = 1,
|
||||||
@ -60,6 +61,10 @@ export const updateReleaseNotes = (hass: HomeAssistant, entityId: string) =>
|
|||||||
entity_id: entityId,
|
entity_id: entityId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const HOME_ASSISTANT_CORE_TITLE = "Home Assistant Core";
|
||||||
|
const HOME_ASSISTANT_SUPERVISOR_TITLE = "Home Assistant Supervisor";
|
||||||
|
const HOME_ASSISTANT_OS_TITLE = "Home Assistant Operating System";
|
||||||
|
|
||||||
export const filterUpdateEntities = (
|
export const filterUpdateEntities = (
|
||||||
entities: HassEntities,
|
entities: HassEntities,
|
||||||
language?: string
|
language?: string
|
||||||
@ -69,22 +74,22 @@ export const filterUpdateEntities = (
|
|||||||
(entity) => computeStateDomain(entity) === "update"
|
(entity) => computeStateDomain(entity) === "update"
|
||||||
) as UpdateEntity[]
|
) as UpdateEntity[]
|
||||||
).sort((a, b) => {
|
).sort((a, b) => {
|
||||||
if (a.attributes.title === "Home Assistant Core") {
|
if (a.attributes.title === HOME_ASSISTANT_CORE_TITLE) {
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
if (b.attributes.title === "Home Assistant Core") {
|
if (b.attributes.title === HOME_ASSISTANT_CORE_TITLE) {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
if (a.attributes.title === "Home Assistant Operating System") {
|
if (a.attributes.title === HOME_ASSISTANT_OS_TITLE) {
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
if (b.attributes.title === "Home Assistant Operating System") {
|
if (b.attributes.title === HOME_ASSISTANT_OS_TITLE) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
if (a.attributes.title === "Home Assistant Supervisor") {
|
if (a.attributes.title === HOME_ASSISTANT_SUPERVISOR_TITLE) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (b.attributes.title === "Home Assistant Supervisor") {
|
if (b.attributes.title === HOME_ASSISTANT_SUPERVISOR_TITLE) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return caseInsensitiveStringCompare(
|
return caseInsensitiveStringCompare(
|
||||||
@ -201,3 +206,32 @@ export const computeUpdateStateDisplay = (
|
|||||||
|
|
||||||
return hass.formatEntityState(stateObj);
|
return hass.formatEntityState(stateObj);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type UpdateType = "addon" | "home_assistant" | "generic";
|
||||||
|
|
||||||
|
export const getUpdateType = (
|
||||||
|
stateObj: UpdateEntity,
|
||||||
|
entitySources: EntitySources
|
||||||
|
): UpdateType => {
|
||||||
|
const entity_id = stateObj.entity_id;
|
||||||
|
const domain = entitySources[entity_id]?.domain;
|
||||||
|
if (domain !== "hassio") {
|
||||||
|
return "generic";
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = stateObj.attributes.title || "";
|
||||||
|
if (title === HOME_ASSISTANT_CORE_TITLE) {
|
||||||
|
return "home_assistant";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
![
|
||||||
|
HOME_ASSISTANT_CORE_TITLE,
|
||||||
|
HOME_ASSISTANT_SUPERVISOR_TITLE,
|
||||||
|
HOME_ASSISTANT_OS_TITLE,
|
||||||
|
].includes(title)
|
||||||
|
) {
|
||||||
|
return "addon";
|
||||||
|
}
|
||||||
|
return "generic";
|
||||||
|
};
|
||||||
|
@ -2,6 +2,7 @@ import "@material/mwc-linear-progress/mwc-linear-progress";
|
|||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { BINARY_STATE_OFF } from "../../../common/const";
|
import { BINARY_STATE_OFF } from "../../../common/const";
|
||||||
|
import { relativeTime } from "../../../common/datetime/relative_time";
|
||||||
import { supportsFeature } from "../../../common/entity/supports-feature";
|
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||||
import "../../../components/ha-alert";
|
import "../../../components/ha-alert";
|
||||||
import "../../../components/ha-button";
|
import "../../../components/ha-button";
|
||||||
@ -10,10 +11,18 @@ import "../../../components/ha-circular-progress";
|
|||||||
import "../../../components/ha-faded";
|
import "../../../components/ha-faded";
|
||||||
import "../../../components/ha-formfield";
|
import "../../../components/ha-formfield";
|
||||||
import "../../../components/ha-markdown";
|
import "../../../components/ha-markdown";
|
||||||
import "../../../components/ha-settings-row";
|
import "../../../components/ha-md-list";
|
||||||
|
import "../../../components/ha-md-list-item";
|
||||||
|
import "../../../components/ha-switch";
|
||||||
|
import type { HaSwitch } from "../../../components/ha-switch";
|
||||||
|
import type { BackupConfig } from "../../../data/backup";
|
||||||
|
import { fetchBackupConfig } from "../../../data/backup";
|
||||||
import { isUnavailableState } from "../../../data/entity";
|
import { isUnavailableState } from "../../../data/entity";
|
||||||
|
import type { EntitySources } from "../../../data/entity_sources";
|
||||||
|
import { fetchEntitySourcesWithCache } from "../../../data/entity_sources";
|
||||||
import type { UpdateEntity } from "../../../data/update";
|
import type { UpdateEntity } from "../../../data/update";
|
||||||
import {
|
import {
|
||||||
|
getUpdateType,
|
||||||
UpdateEntityFeature,
|
UpdateEntityFeature,
|
||||||
updateIsInstalling,
|
updateIsInstalling,
|
||||||
updateReleaseNotes,
|
updateReleaseNotes,
|
||||||
@ -33,6 +42,103 @@ class MoreInfoUpdate extends LitElement {
|
|||||||
|
|
||||||
@state() private _markdownLoading = true;
|
@state() private _markdownLoading = true;
|
||||||
|
|
||||||
|
@state() private _backupConfig?: BackupConfig;
|
||||||
|
|
||||||
|
@state() private _entitySources?: EntitySources;
|
||||||
|
|
||||||
|
private async _fetchBackupConfig() {
|
||||||
|
const { config } = await fetchBackupConfig(this.hass);
|
||||||
|
this._backupConfig = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _fetchEntitySources() {
|
||||||
|
this._entitySources = await fetchEntitySourcesWithCache(this.hass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeCreateBackupTexts():
|
||||||
|
| { title: string; description?: string }
|
||||||
|
| undefined {
|
||||||
|
if (
|
||||||
|
!this.stateObj ||
|
||||||
|
!supportsFeature(this.stateObj, UpdateEntityFeature.BACKUP)
|
||||||
|
) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateType = this._entitySources
|
||||||
|
? getUpdateType(this.stateObj, this._entitySources)
|
||||||
|
: "generic";
|
||||||
|
|
||||||
|
// Automatic or manual for Home Assistant update
|
||||||
|
if (updateType === "home_assistant") {
|
||||||
|
const isBackupConfigValid =
|
||||||
|
!!this._backupConfig &&
|
||||||
|
!!this._backupConfig.create_backup.password &&
|
||||||
|
this._backupConfig.create_backup.agent_ids.length > 0;
|
||||||
|
|
||||||
|
if (!isBackupConfigValid) {
|
||||||
|
return {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.update.create_backup.manual"
|
||||||
|
),
|
||||||
|
description: this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.update.create_backup.manual_description"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastAutomaticBackupDate = this._backupConfig
|
||||||
|
?.last_completed_automatic_backup
|
||||||
|
? new Date(this._backupConfig?.last_completed_automatic_backup)
|
||||||
|
: null;
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.update.create_backup.automatic"
|
||||||
|
),
|
||||||
|
description: lastAutomaticBackupDate
|
||||||
|
? this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.update.create_backup.automatic_description_last",
|
||||||
|
{
|
||||||
|
relative_time: relativeTime(
|
||||||
|
lastAutomaticBackupDate,
|
||||||
|
this.hass.locale,
|
||||||
|
now,
|
||||||
|
true
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
: this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.update.create_backup.automatic_description_none"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addon backup
|
||||||
|
if (updateType === "addon") {
|
||||||
|
const version = this.stateObj.attributes.installed_version;
|
||||||
|
return {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.update.create_backup.addon"
|
||||||
|
),
|
||||||
|
description: version
|
||||||
|
? this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.update.create_backup.addon_description",
|
||||||
|
{ version: version }
|
||||||
|
)
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to generic UI
|
||||||
|
return {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.update.create_backup.generic"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (
|
if (
|
||||||
!this.hass ||
|
!this.hass ||
|
||||||
@ -47,6 +153,8 @@ class MoreInfoUpdate extends LitElement {
|
|||||||
this.stateObj.attributes.skipped_version ===
|
this.stateObj.attributes.skipped_version ===
|
||||||
this.stateObj.attributes.latest_version;
|
this.stateObj.attributes.latest_version;
|
||||||
|
|
||||||
|
const createBackupTexts = this._computeCreateBackupTexts();
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="summary">
|
<div class="summary">
|
||||||
@ -133,6 +241,27 @@ class MoreInfoUpdate extends LitElement {
|
|||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
|
${createBackupTexts
|
||||||
|
? html`
|
||||||
|
<ha-md-list>
|
||||||
|
<ha-md-list-item>
|
||||||
|
<span slot="headline">${createBackupTexts.title}</span>
|
||||||
|
${createBackupTexts.description
|
||||||
|
? html`
|
||||||
|
<span slot="supporting-text">
|
||||||
|
${createBackupTexts.description}
|
||||||
|
</span>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
|
<ha-switch
|
||||||
|
slot="end"
|
||||||
|
id="create-backup"
|
||||||
|
.disabled=${updateIsInstalling(this.stateObj)}
|
||||||
|
></ha-switch>
|
||||||
|
</ha-md-list-item>
|
||||||
|
</ha-md-list>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
${this.stateObj.state === BINARY_STATE_OFF &&
|
${this.stateObj.state === BINARY_STATE_OFF &&
|
||||||
this.stateObj.attributes.skipped_version
|
this.stateObj.attributes.skipped_version
|
||||||
@ -186,6 +315,14 @@ class MoreInfoUpdate extends LitElement {
|
|||||||
if (supportsFeature(this.stateObj!, UpdateEntityFeature.RELEASE_NOTES)) {
|
if (supportsFeature(this.stateObj!, UpdateEntityFeature.RELEASE_NOTES)) {
|
||||||
this._fetchReleaseNotes();
|
this._fetchReleaseNotes();
|
||||||
}
|
}
|
||||||
|
if (supportsFeature(this.stateObj!, UpdateEntityFeature.BACKUP)) {
|
||||||
|
this._fetchEntitySources().then(() => {
|
||||||
|
const type = getUpdateType(this.stateObj!, this._entitySources!);
|
||||||
|
if (type === "home_assistant") {
|
||||||
|
this._fetchBackupConfig();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _markdownLoaded() {
|
private async _markdownLoaded() {
|
||||||
@ -205,11 +342,28 @@ class MoreInfoUpdate extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _shouldCreateBackup(): boolean {
|
||||||
|
if (!supportsFeature(this.stateObj!, UpdateEntityFeature.BACKUP)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const createBackupSwitch = this.shadowRoot?.getElementById(
|
||||||
|
"create-backup"
|
||||||
|
) as HaSwitch;
|
||||||
|
if (createBackupSwitch) {
|
||||||
|
return createBackupSwitch.checked;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private _handleInstall(): void {
|
private _handleInstall(): void {
|
||||||
const installData: Record<string, any> = {
|
const installData: Record<string, any> = {
|
||||||
entity_id: this.stateObj!.entity_id,
|
entity_id: this.stateObj!.entity_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this._shouldCreateBackup) {
|
||||||
|
installData.backup = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
supportsFeature(this.stateObj!, UpdateEntityFeature.SPECIFIC_VERSION) &&
|
supportsFeature(this.stateObj!, UpdateEntityFeature.SPECIFIC_VERSION) &&
|
||||||
this.stateObj!.attributes.latest_version
|
this.stateObj!.attributes.latest_version
|
||||||
@ -289,14 +443,18 @@ class MoreInfoUpdate extends LitElement {
|
|||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-settings-row {
|
ha-md-list {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 24px;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin-bottom: -16px;
|
margin-bottom: -16px;
|
||||||
margin-top: -4px;
|
margin-top: -4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ha-md-list-item {
|
||||||
|
--md-list-item-leading-space: 24px;
|
||||||
|
--md-list-item-trailing-space: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1276,7 +1276,17 @@
|
|||||||
"install": "Install",
|
"install": "Install",
|
||||||
"update": "Update",
|
"update": "Update",
|
||||||
"auto_update_enabled_title": "Can not skip version",
|
"auto_update_enabled_title": "Can not skip version",
|
||||||
"auto_update_enabled_text": "Automatic updates for this item have been enabled; skipping it is, therefore, unavailable. You can either install this update now or wait for Home Assistant to do it automatically."
|
"auto_update_enabled_text": "Automatic updates for this item have been enabled; skipping it is, therefore, unavailable. You can either install this update now or wait for Home Assistant to do it automatically.",
|
||||||
|
"create_backup": {
|
||||||
|
"automatic": "Automatic backup before update",
|
||||||
|
"automatic_description_last": "Last automatic backup {relative_time}.",
|
||||||
|
"automatic_description_none": "No automatic backup yet.",
|
||||||
|
"manual": "Create manual backup before update",
|
||||||
|
"manual_description": "Includes Home Assistant settings and history.",
|
||||||
|
"addon": "Keep backup of the last version",
|
||||||
|
"addon_description": "For easily restoring to version {version}",
|
||||||
|
"generic": "Create backup"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"updater": {
|
"updater": {
|
||||||
"title": "Update instructions"
|
"title": "Update instructions"
|
||||||
@ -8478,7 +8488,12 @@
|
|||||||
"open_release_notes": "Open release notes",
|
"open_release_notes": "Open release notes",
|
||||||
"description": "You have {version} installed. Press update to update to version {newest_version}",
|
"description": "You have {version} installed. Press update to update to version {newest_version}",
|
||||||
"updating": "Updating {name} to version {version}",
|
"updating": "Updating {name} to version {version}",
|
||||||
"no_update": "No update available for {name}"
|
"no_update": "No update available for {name}",
|
||||||
|
"create_backup": {
|
||||||
|
"addon": "[%key:ui::dialogs::more_info_control::update::create_backup::addon%]",
|
||||||
|
"addon_description": "[%key:ui::dialogs::more_info_control::update::create_backup::addon_description%]",
|
||||||
|
"generic": "[%key:ui::dialogs::more_info_control::update::create_backup::generic%]"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"restart": {
|
"restart": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user