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));
export interface BackupConfig {
automatic_backups_configured: boolean;
last_attempted_automatic_backup: string | null;
last_completed_automatic_backup: string | null;
next_automatic_backup: string | null;
@ -64,6 +65,7 @@ export interface BackupConfig {
}
export interface BackupMutableConfig {
automatic_backups_configured?: boolean;
create_backup?: {
agent_ids?: string[];
include_addons?: string[];

View File

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

View File

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

View File

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

View File

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

View File

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