Skip to content

Commit

Permalink
Handle backup state
Browse files Browse the repository at this point in the history
  • Loading branch information
piitaya committed Dec 9, 2024
1 parent 7f4186c commit de0c375
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 31 deletions.
17 changes: 16 additions & 1 deletion src/components/ha-file-upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ export class HaFileUpload extends LitElement {
}
}

private get _name() {
if (this.value === undefined) {
return "";
}
if (typeof this.value === "string") {
return this.value;
}
const files =
this.value instanceof FileList
? Array.from(this.value)
: ensureArray(this.value);

return files.map((file) => file.name).join(", ");
}

public render(): TemplateResult {
return html`
${this.uploading
Expand All @@ -65,7 +80,7 @@ export class HaFileUpload extends LitElement {
>${this.value
? this.hass?.localize(
"ui.components.file-upload.uploading_name",
{ name: this.value.toString() }
{ name: this._name }
)
: this.hass?.localize(
"ui.components.file-upload.uploading"
Expand Down
17 changes: 0 additions & 17 deletions src/data/backup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,23 +196,6 @@ export const uploadBackup = async (
}
};

type BackupEvent = BackupProgressEvent;

type BackupProgressEvent = {
event_type: "backup_progress";
done: boolean;
stage: string;
success?: boolean;
};

export const subscribeBackupEvents = (
hass: HomeAssistant,
callback: (event: BackupEvent) => void
) =>
hass.connection.subscribeMessage<BackupEvent>(callback, {
type: "backup/subscribe_events",
});

export const getPreferredAgentForDownload = (agents: string[]) => {
const localAgents = agents.filter(
(agent) => agent.split(".")[0] === "backup"
Expand Down
99 changes: 99 additions & 0 deletions src/data/backup_manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import type { HomeAssistant } from "../types";

export enum BackupManagerState {
IDLE = "idle",
CREATE_BACKUP = "create_backup",
RECEIVE_BACKUP = "receive_backup",
RESTORE_BACKUP = "restore_backup",
}

export enum CreateBackupStage {
ADDON_REPOSITORIES = "addon_repositories",
ADDONS = "addons",
AWAIT_ADDON_RESTARTS = "await_addon_restarts",
DOCKER_CONFIG = "docker_config",
FINISHING_FILE = "finishing_file",
FOLDERS = "folders",
HOME_ASSISTANT = "home_assistant",
UPLOAD_TO_AGENTS = "upload_to_agents",
}

export enum CreateBackupState {
COMPLETED = "completed",
FAILED = "failed",
IN_PROGRESS = "in_progress",
}

export enum ReceiveBackupStage {
RECEIVE_FILE = "receive_file",
UPLOAD_TO_AGENTS = "upload_to_agents",
}

export enum ReceiveBackupState {
COMPLETED = "completed",
FAILED = "failed",
IN_PROGRESS = "in_progress",
}

export enum RestoreBackupStage {
ADDON_REPOSITORIES = "addon_repositories",
ADDONS = "addons",
AWAIT_ADDON_RESTARTS = "await_addon_restarts",
AWAIT_HOME_ASSISTANT_RESTART = "await_home_assistant_restart",
CHECK_HOME_ASSISTANT = "check_home_assistant",
DOCKER_CONFIG = "docker_config",
DOWNLOAD_FROM_AGENT = "download_from_agent",
FOLDERS = "folders",
HOME_ASSISTANT = "home_assistant",
REMOVE_DELTA_ADDONS = "remove_delta_addons",
}

export enum RestoreBackupState {
COMPLETED = "completed",
FAILED = "failed",
IN_PROGRESS = "in_progress",
}

type IdleEvent = {
manager_state: BackupManagerState.IDLE;
};

type CreateBackupEvent = {
manager_state: BackupManagerState.CREATE_BACKUP;
stage: CreateBackupStage | null;
state: CreateBackupState;
};

type ReceiveBackupEvent = {
manager_state: BackupManagerState.RECEIVE_BACKUP;
stage: ReceiveBackupStage | null;
state: ReceiveBackupState;
};

type RestoreBackupEvent = {
manager_state: BackupManagerState.RESTORE_BACKUP;
stage: RestoreBackupStage | null;
state: RestoreBackupState;
};

export type ManagerStateEvent =
| IdleEvent
| CreateBackupEvent
| ReceiveBackupEvent
| RestoreBackupEvent;

export const subscribeBackupEvents = (
hass: HomeAssistant,
callback: (event: ManagerStateEvent) => void
) =>
hass.connection.subscribeMessage<ManagerStateEvent>(callback, {
type: "backup/subscribe_events",
});

export const isBackupInProgress = (state: ManagerStateEvent) =>
(state.manager_state === BackupManagerState.CREATE_BACKUP &&
state.state === CreateBackupState.IN_PROGRESS) ||
(state.manager_state === BackupManagerState.RECEIVE_BACKUP &&
state.state === ReceiveBackupState.IN_PROGRESS) ||
(state.manager_state === BackupManagerState.RESTORE_BACKUP &&
state.state === RestoreBackupState.IN_PROGRESS);
6 changes: 3 additions & 3 deletions src/panels/config/backup/components/ha-backup-summary-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const ICONS: Record<SummaryStatus, string> = {
@customElement("ha-backup-summary-card")
class HaBackupSummaryCard extends LitElement {
@property()
public title!: string;
public heading!: string;

@property()
public description!: string;
Expand All @@ -49,7 +49,7 @@ class HaBackupSummaryCard extends LitElement {
`}
<div class="content">
<p class="title">${this.title}</p>
<p class="heading">${this.heading}</p>
<p class="description">${this.description}</p>
</div>
${this.hasAction
Expand Down Expand Up @@ -116,7 +116,7 @@ class HaBackupSummaryCard extends LitElement {
flex: 1;
min-width: 0;
}
.title {
.heading {
font-size: 22px;
font-style: normal;
font-weight: 400;
Expand Down
39 changes: 29 additions & 10 deletions src/panels/config/backup/ha-config-backup-dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { relativeTime } from "../../../common/datetime/relative_time";
import type { HASSDomEvent } from "../../../common/dom/fire_event";
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
import { navigate } from "../../../common/navigate";
import type { LocalizeFunc } from "../../../common/translations/localize";
import type {
Expand Down Expand Up @@ -43,9 +44,14 @@ import {
generateBackup,
getBackupDownloadUrl,
getPreferredAgentForDownload,
subscribeBackupEvents,
updateBackupConfig,
} from "../../../data/backup";
import type { ManagerStateEvent } from "../../../data/backup_manager";
import {
BackupManagerState,
isBackupInProgress,
subscribeBackupEvents,
} from "../../../data/backup_manager";
import { extractApiErrorMessage } from "../../../data/hassio/common";
import {
showAlertDialog,
Expand All @@ -62,9 +68,8 @@ import { fileDownload } from "../../../util/file_download";
import "./components/ha-backup-summary-card";
import { showGenerateBackupDialog } from "./dialogs/show-dialog-generate-backup";
import { showNewBackupDialog } from "./dialogs/show-dialog-new-backup";
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
import { showUploadBackupDialog } from "./dialogs/show-dialog-upload-backup";
import { showSetBackupEncryptionKeyDialog } from "./dialogs/show-dialog-set-backup-encryption-key";
import { showUploadBackupDialog } from "./dialogs/show-dialog-upload-backup";

@customElement("ha-config-backup-dashboard")
class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
Expand All @@ -74,7 +79,9 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {

@property({ attribute: false }) public route!: Route;

@state() private _backupInProgress = false;
@state() private _manager: ManagerStateEvent = {
manager_state: BackupManagerState.IDLE,
};

@state() private _backups: BackupContent[] = [];

Expand Down Expand Up @@ -172,6 +179,8 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
}

protected render(): TemplateResult {
const backupInProgress = isBackupInProgress(this._manager);

return html`
<hass-tabs-subpage-data-table
hasFab
Expand Down Expand Up @@ -202,7 +211,7 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
${this._needsOnboarding
? html`
<ha-backup-summary-card
title="Set up default backup"
heading="Set up default backup"
description="Have a one-click backup automation with selected data and locations."
has-action
status="info"
Expand All @@ -214,10 +223,10 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
`
: html`
<ha-backup-summary-card
title="Automatically backed up"
heading="Automatically backed up"
description="Your configuration has been backed up."
has-action
.status=${this._backupInProgress ? "loading" : "success"}
.status=${backupInProgress ? "loading" : "info"}
>
<ha-button
slot="action"
Expand Down Expand Up @@ -282,7 +291,7 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
<ha-fab
slot="fab"
?disabled=${this._backupInProgress}
?disabled=${backupInProgress}
.label=${this.hass.localize("ui.panel.config.backup.create_backup")}
extended
@click=${this._newBackup}
Expand All @@ -300,14 +309,19 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
}
}

private _isProgress = false;

private async _subscribeEvents() {
this._unsubscribeEvents();
if (!this.isConnected) {
return;
}

this._subscribed = subscribeBackupEvents(this.hass!, (event) => {
if (event.event_type === "backup_progress" && event.done) {
this._manager = event;
const isProgress = isBackupInProgress(this._manager);
if (isProgress !== this._isProgress) {
this._isProgress = isProgress;
this._fetchBackupInfo();
}
});
Expand Down Expand Up @@ -336,7 +350,6 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
private async _fetchBackupInfo() {
const info = await fetchBackupInfo(this.hass);
this._backups = info.backups;
this._backupInProgress = info.backing_up;
}

private async _fetchBackupConfig() {
Expand Down Expand Up @@ -391,6 +404,12 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
return;
}

if (!isComponentLoaded(this.hass, "hassio")) {
delete params.include_folders;
delete params.include_all_addons;
delete params.include_addons;
}

this._generateBackup(params);
return;
}
Expand Down

0 comments on commit de0c375

Please sign in to comment.