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 {
My backups
- +
${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; }