diff --git a/src/components/ha-filter-states.ts b/src/components/ha-filter-states.ts
index cb454ba7ab1d..8667e17df40e 100644
--- a/src/components/ha-filter-states.ts
+++ b/src/components/ha-filter-states.ts
@@ -1,9 +1,9 @@
import "@material/mwc-list/mwc-list";
-import type { SelectedDetail } from "@material/mwc-list";
+import type { List, SelectedDetail } from "@material/mwc-list";
import { mdiFilterVariantRemove } from "@mdi/js";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
-import { customElement, property, state } from "lit/decorators";
+import { customElement, property, query, state } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
import { haStyleScrollbar } from "../resources/styles";
import type { HomeAssistant } from "../types";
@@ -32,6 +32,8 @@ export class HaFilterStates extends LitElement {
@state() private _shouldRender = false;
+ @query("mwc-list") private _list!: List;
+
protected render() {
if (!this.states) {
return nothing;
@@ -84,12 +86,21 @@ export class HaFilterStates extends LitElement {
`;
}
- protected updated(changed) {
+ protected willUpdate(changed) {
if (changed.has("expanded") && this.expanded) {
- setTimeout(() => {
+ this._shouldRender = true;
+ }
+ }
+
+ protected updated(changed) {
+ if ((changed.has("expanded") || changed.has("states")) && this.expanded) {
+ setTimeout(async () => {
if (!this.expanded) return;
- this.renderRoot.querySelector("mwc-list")!.style.height =
- `${this.clientHeight - 49}px`;
+ const list = this._list;
+ if (!list) {
+ return;
+ }
+ list.style.height = `${this.clientHeight - 49}px`;
}, 300);
}
}
diff --git a/src/panels/config/backup/components/overview/ha-backup-overview-backups.ts b/src/panels/config/backup/components/overview/ha-backup-overview-backups.ts
index d2a6accbedf9..0f025e89374d 100644
--- a/src/panels/config/backup/components/overview/ha-backup-overview-backups.ts
+++ b/src/panels/config/backup/components/overview/ha-backup-overview-backups.ts
@@ -62,7 +62,10 @@ class HaBackupOverviewBackups extends LitElement {
-
+
${automaticStats.count} automatic backups
@@ -72,7 +75,10 @@ class HaBackupOverviewBackups extends LitElement {
-
+
${manualStats.count} manual backups
@@ -83,7 +89,10 @@ class HaBackupOverviewBackups extends LitElement {
-
+
Show all backups
diff --git a/src/panels/config/backup/ha-config-backup-backups.ts b/src/panels/config/backup/ha-config-backup-backups.ts
index ed478a577e32..04ee5413d0d5 100644
--- a/src/panels/config/backup/ha-config-backup-backups.ts
+++ b/src/panels/config/backup/ha-config-backup-backups.ts
@@ -28,6 +28,7 @@ import type {
import "../../../components/ha-button";
import "../../../components/ha-button-menu";
import "../../../components/ha-fab";
+import "../../../components/ha-filter-states";
import "../../../components/ha-icon";
import "../../../components/ha-icon-next";
import "../../../components/ha-icon-overflow-menu";
@@ -46,6 +47,7 @@ import {
} from "../../../data/backup";
import type { ManagerStateEvent } from "../../../data/backup_manager";
import type { CloudStatus } from "../../../data/cloud";
+import type { DataTableFiltersValues } from "../../../data/data_table_filters";
import { extractApiErrorMessage } from "../../../data/hassio/common";
import {
showAlertDialog,
@@ -89,6 +91,14 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
@state() private _selected: string[] = [];
+ @storage({
+ storage: "sessionStorage",
+ key: "backups-table-filters",
+ state: true,
+ subscribe: false,
+ })
+ private _filters: DataTableFiltersValues = {};
+
@storage({ key: "backups-table-grouping", state: false, subscribe: false })
private _activeGrouping?: string = "formatted_type";
@@ -102,6 +112,27 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
@query("hass-tabs-subpage-data-table", true)
private _dataTable!: HaTabsSubpageDataTable;
+ public connectedCallback() {
+ super.connectedCallback();
+ window.addEventListener("location-changed", this._locationChanged);
+ window.addEventListener("popstate", this._popState);
+ this._setFiltersFromUrl();
+ }
+
+ disconnectedCallback(): void {
+ super.disconnectedCallback();
+ window.removeEventListener("location-changed", this._locationChanged);
+ window.removeEventListener("popstate", this._popState);
+ }
+
+ private _locationChanged = () => {
+ this._setFiltersFromUrl();
+ };
+
+ private _popState = () => {
+ this._setFiltersFromUrl();
+ };
+
private _columns = memoizeOne(
(localize: LocalizeFunc): DataTableColumnContainer => ({
name: {
@@ -230,13 +261,28 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
return capitalizeFirstLetter(type);
}
- private _data = memoizeOne((backups: BackupContent[]): BackupRow[] =>
- backups.map((backup) => ({
- ...backup,
- formatted_type: this._formatBackupType(
- backup.with_automatic_settings ? "automatic" : "manual"
- ),
- }))
+ private _data = memoizeOne(
+ (
+ backups: BackupContent[],
+ filters: DataTableFiltersValues
+ ): BackupRow[] => {
+ const typeFilter = filters["ha-filter-states"] as string[] | undefined;
+ let filteredBackups = backups;
+ if (typeFilter?.length) {
+ filteredBackups = filteredBackups.filter(
+ (backup) =>
+ (backup.with_automatic_settings &&
+ typeFilter.includes("automatic")) ||
+ (!backup.with_automatic_settings && typeFilter.includes("manual"))
+ );
+ }
+ return filteredBackups.map((backup) => ({
+ ...backup,
+ formatted_type: this._formatBackupType(
+ backup.with_automatic_settings ? "automatic" : "manual"
+ ),
+ }));
+ }
);
protected render(): TemplateResult {
@@ -257,6 +303,15 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
back-path="/config/backup/overview"
clickable
id="backup_id"
+ has-filters
+ .filters=${Object.values(this._filters).filter((filter) =>
+ Array.isArray(filter)
+ ? filter.length
+ : filter &&
+ Object.values(filter).some((val) =>
+ Array.isArray(val) ? val.length : val
+ )
+ ).length}
selectable
.selected=${this._selected.length}
.initialGroupColumn=${this._activeGrouping}
@@ -268,7 +323,7 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
.route=${this.route}
@row-click=${this._showBackupDetails}
.columns=${this._columns(this.hass.localize)}
- .data=${this._data(this.backups)}
+ .data=${this._data(this.backups, this._filters)}
.noDataText=${this.hass.localize("ui.panel.config.backup.no_backups")}
.searchLabel=${this.hass.localize(
"ui.panel.config.backup.picker.search"
@@ -324,6 +379,16 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
`
: nothing}
+
${!this._needsOnboarding
? html`
[
+ {
+ value: "automatic",
+ label: "Automatic",
+ },
+ {
+ value: "manual",
+ label: "Manual",
+ },
+ ]);
+
+ private _filterChanged(ev) {
+ const type = ev.target.localName;
+ this._filters = { ...this._filters, [type]: ev.detail.value };
+ }
+
+ private _setFiltersFromUrl() {
+ const searchParams = new URLSearchParams(window.location.search);
+ const type = searchParams.get("type");
+
+ if (!type) {
+ return;
+ }
+
+ this._filters = {
+ "ha-filter-states": type === "all" ? [] : [type],
+ };
+ }
+
private get _needsOnboarding() {
return !this.config?.create_backup.password;
}