Use automatic_backups_configured flag to signal if backup onboardin… (#24367)

* Use `automatic_backups_configured` flag to signal if backup onboarding was done

* fix

* dont show a newly created password without showing it
This commit is contained in:
Bram Kragten 2025-02-25 11:42:46 +01:00 committed by GitHub
parent 5c933a43b2
commit a906285a03
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 74 additions and 28 deletions

View File

@ -38,6 +38,7 @@ export const sortWeekdays = (weekdays) =>
weekdays.sort((a, b) => BACKUP_DAYS.indexOf(a) - BACKUP_DAYS.indexOf(b)); weekdays.sort((a, b) => BACKUP_DAYS.indexOf(a) - BACKUP_DAYS.indexOf(b));
export interface BackupConfig { export interface BackupConfig {
automatic_backups_configured: boolean;
last_attempted_automatic_backup: string | null; last_attempted_automatic_backup: string | null;
last_completed_automatic_backup: string | null; last_completed_automatic_backup: string | null;
next_automatic_backup: string | null; next_automatic_backup: string | null;
@ -64,6 +65,7 @@ export interface BackupConfig {
} }
export interface BackupMutableConfig { export interface BackupMutableConfig {
automatic_backups_configured?: boolean;
create_backup?: { create_backup?: {
agent_ids?: string[]; agent_ids?: string[];
include_addons?: string[]; include_addons?: string[];

View File

@ -73,6 +73,7 @@ class MoreInfoUpdate extends LitElement {
if (updateType === "home_assistant") { if (updateType === "home_assistant") {
const isBackupConfigValid = const isBackupConfigValid =
!!this._backupConfig && !!this._backupConfig &&
!!this._backupConfig.automatic_backups_configured &&
!!this._backupConfig.create_backup.password && !!this._backupConfig.create_backup.password &&
this._backupConfig.create_backup.agent_ids.length > 0; this._backupConfig.create_backup.agent_ids.length > 0;

View File

@ -1,5 +1,5 @@
import { mdiClose, mdiContentCopy, mdiDownload } from "@mdi/js"; import { mdiClose, mdiContentCopy, mdiDownload } from "@mdi/js";
import type { CSSResultGroup } from "lit"; import type { CSSResultGroup, PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import { isComponentLoaded } from "../../../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../../../common/config/is_component_loaded";
@ -53,7 +53,10 @@ type Step = (typeof STEPS)[number];
const FULL_DIALOG_STEPS = new Set<Step>(["setup"]); const FULL_DIALOG_STEPS = new Set<Step>(["setup"]);
const SAVE_STEPS = new Set<Step>(["schedule", "data", "locations"]);
const RECOMMENDED_CONFIG: BackupConfig = { const RECOMMENDED_CONFIG: BackupConfig = {
automatic_backups_configured: false,
create_backup: { create_backup: {
agent_ids: [], agent_ids: [],
include_folders: [], include_folders: [],
@ -95,29 +98,23 @@ class DialogBackupOnboarding extends LitElement implements HassDialog {
public showDialog(params: BackupOnboardingDialogParams): void { public showDialog(params: BackupOnboardingDialogParams): void {
this._params = params; this._params = params;
this._step = this._firstStep;
this._config = RECOMMENDED_CONFIG;
const agents: string[] = []; if (this._params.config?.create_backup.password) {
// Enable local location by default // onboarding wizard was started before, but not finished.
if (isComponentLoaded(this.hass, "hassio")) { this._config = this._params.config;
agents.push(HASSIO_LOCAL_AGENT); this._step = "setup";
} else { } else {
agents.push(CORE_LOCAL_AGENT); this._step = this._firstStep;
}
// Enable cloud location if logged in
if (this._params.cloudStatus?.logged_in) {
agents.push(CLOUD_AGENT);
}
this._config = { this._config = {
...this._config, ...RECOMMENDED_CONFIG,
create_backup: { create_backup: {
...this._config.create_backup, ...RECOMMENDED_CONFIG.create_backup,
agent_ids: agents, agent_ids: this._defaultAgents,
password: generateEncryptionKey(), password: generateEncryptionKey(),
}, },
}; };
}
this._opened = true; this._opened = true;
} }
@ -139,7 +136,7 @@ class DialogBackupOnboarding extends LitElement implements HassDialog {
return this._params?.skipWelcome ? STEPS[1] : STEPS[0]; return this._params?.skipWelcome ? STEPS[1] : STEPS[0];
} }
private async _done() { private async _save(done = false) {
if (!this._config) { if (!this._config) {
return; return;
} }
@ -152,6 +149,7 @@ class DialogBackupOnboarding extends LitElement implements HassDialog {
}, },
schedule: this._config.schedule, schedule: this._config.schedule,
retention: this._config.retention, retention: this._config.retention,
automatic_backups_configured: done,
}; };
if (isComponentLoaded(this.hass, "hassio")) { if (isComponentLoaded(this.hass, "hassio")) {
@ -163,9 +161,12 @@ class DialogBackupOnboarding extends LitElement implements HassDialog {
this._config.create_backup.include_addons || []; this._config.create_backup.include_addons || [];
} }
try {
await updateBackupConfig(this.hass, params); await updateBackupConfig(this.hass, params);
}
private async _done() {
try {
await this._save(true);
this._params?.submit!(true); this._params?.submit!(true);
this._dialog.close(); this._dialog.close();
} catch (err) { } catch (err) {
@ -184,6 +185,9 @@ class DialogBackupOnboarding extends LitElement implements HassDialog {
} }
private _nextStep() { private _nextStep() {
if (this._step && SAVE_STEPS.has(this._step)) {
this._save();
}
const index = STEPS.indexOf(this._step!); const index = STEPS.indexOf(this._step!);
if (index === STEPS.length - 1) { if (index === STEPS.length - 1) {
return; return;
@ -191,6 +195,12 @@ class DialogBackupOnboarding extends LitElement implements HassDialog {
this._step = STEPS[index + 1]; this._step = STEPS[index + 1];
} }
protected updated(changedProps: PropertyValues) {
if (changedProps.has("_step") && this._step === "key") {
this._save();
}
}
protected render() { protected render() {
if (!this._opened || !this._params || !this._step) { if (!this._opened || !this._params || !this._step) {
return nothing; return nothing;
@ -250,6 +260,36 @@ class DialogBackupOnboarding extends LitElement implements HassDialog {
`; `;
} }
private get _defaultAgents(): string[] {
const agents: string[] = [];
// Enable local location by default
if (isComponentLoaded(this.hass, "hassio")) {
agents.push(HASSIO_LOCAL_AGENT);
} else {
agents.push(CORE_LOCAL_AGENT);
}
// Enable cloud location if logged in
if (this._params?.cloudStatus?.logged_in) {
agents.push(CLOUD_AGENT);
}
return agents;
}
private _useRecommended() {
if (!this._config?.create_backup.password) {
return;
}
this._config = {
...RECOMMENDED_CONFIG,
create_backup: {
...RECOMMENDED_CONFIG.create_backup,
agent_ids: this._defaultAgents,
password: this._config.create_backup.password,
},
};
this._done();
}
private get _stepTitle(): string { private get _stepTitle(): string {
switch (this._step) { switch (this._step) {
case "key": case "key":
@ -345,7 +385,7 @@ class DialogBackupOnboarding extends LitElement implements HassDialog {
case "setup": case "setup":
return html` return html`
<ha-md-list class="full"> <ha-md-list class="full">
<ha-md-list-item type="button" @click=${this._done}> <ha-md-list-item type="button" @click=${this._useRecommended}>
<span slot="headline"> <span slot="headline">
${this.hass.localize( ${this.hass.localize(
"ui.panel.config.backup.dialogs.onboarding.setup.recommended_heading" "ui.panel.config.backup.dialogs.onboarding.setup.recommended_heading"

View File

@ -1,9 +1,11 @@
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import type { BackupConfig } from "../../../../data/backup";
import type { CloudStatus } from "../../../../data/cloud"; import type { CloudStatus } from "../../../../data/cloud";
export interface BackupOnboardingDialogParams { export interface BackupOnboardingDialogParams {
submit?: (value: boolean) => void; submit?: (value: boolean) => void;
cancel?: () => void; cancel?: () => void;
config: BackupConfig;
cloudStatus?: CloudStatus; cloudStatus?: CloudStatus;
skipWelcome?: boolean; skipWelcome?: boolean;
} }

View File

@ -505,7 +505,7 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
} }
private get _needsOnboarding() { private get _needsOnboarding() {
return !this.config?.create_backup.password; return !this.config?.automatic_backups_configured;
} }
private async _uploadBackup(ev) { private async _uploadBackup(ev) {

View File

@ -78,6 +78,7 @@ class HaConfigBackupOverview extends LitElement {
private async _setupAutomaticBackup(skipWelcome = false) { private async _setupAutomaticBackup(skipWelcome = false) {
const success = await showBackupOnboardingDialog(this, { const success = await showBackupOnboardingDialog(this, {
config: this.config!,
cloudStatus: this.cloudStatus, cloudStatus: this.cloudStatus,
skipWelcome, skipWelcome,
}); });
@ -128,7 +129,7 @@ class HaConfigBackupOverview extends LitElement {
} }
private get _needsOnboarding() { private get _needsOnboarding() {
return this.config && !this.config.create_backup.password; return this.config && !this.config.automatic_backups_configured;
} }
protected render(): TemplateResult { protected render(): TemplateResult {