mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 15:26:36 +00:00
Filter backups by type (#23366)
* filter backups by type * Add filter pane * Make sure we show all when you click show all
This commit is contained in:
parent
33df805168
commit
b3b0006ba3
@ -1,9 +1,9 @@
|
|||||||
import "@material/mwc-list/mwc-list";
|
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 { mdiFilterVariantRemove } from "@mdi/js";
|
||||||
import type { CSSResultGroup } from "lit";
|
import type { CSSResultGroup } from "lit";
|
||||||
import { css, html, LitElement, nothing } 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 { fireEvent } from "../common/dom/fire_event";
|
||||||
import { haStyleScrollbar } from "../resources/styles";
|
import { haStyleScrollbar } from "../resources/styles";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
@ -32,6 +32,8 @@ export class HaFilterStates extends LitElement {
|
|||||||
|
|
||||||
@state() private _shouldRender = false;
|
@state() private _shouldRender = false;
|
||||||
|
|
||||||
|
@query("mwc-list") private _list!: List;
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this.states) {
|
if (!this.states) {
|
||||||
return nothing;
|
return nothing;
|
||||||
@ -84,12 +86,21 @@ export class HaFilterStates extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changed) {
|
protected willUpdate(changed) {
|
||||||
if (changed.has("expanded") && this.expanded) {
|
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;
|
if (!this.expanded) return;
|
||||||
this.renderRoot.querySelector("mwc-list")!.style.height =
|
const list = this._list;
|
||||||
`${this.clientHeight - 49}px`;
|
if (!list) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
list.style.height = `${this.clientHeight - 49}px`;
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,10 @@ class HaBackupOverviewBackups extends LitElement {
|
|||||||
<div class="card-header">My backups</div>
|
<div class="card-header">My backups</div>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<ha-md-list>
|
<ha-md-list>
|
||||||
<ha-md-list-item type="link" href="/config/backup/backups">
|
<ha-md-list-item
|
||||||
|
type="link"
|
||||||
|
href="/config/backup/backups?type=automatic"
|
||||||
|
>
|
||||||
<ha-svg-icon slot="start" .path=${mdiCalendarSync}></ha-svg-icon>
|
<ha-svg-icon slot="start" .path=${mdiCalendarSync}></ha-svg-icon>
|
||||||
<div slot="headline">
|
<div slot="headline">
|
||||||
${automaticStats.count} automatic backups
|
${automaticStats.count} automatic backups
|
||||||
@ -72,7 +75,10 @@ class HaBackupOverviewBackups extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
<ha-icon-next slot="end"></ha-icon-next>
|
<ha-icon-next slot="end"></ha-icon-next>
|
||||||
</ha-md-list-item>
|
</ha-md-list-item>
|
||||||
<ha-md-list-item type="link" href="/config/backup/backups">
|
<ha-md-list-item
|
||||||
|
type="link"
|
||||||
|
href="/config/backup/backups?type=manual"
|
||||||
|
>
|
||||||
<ha-svg-icon slot="start" .path=${mdiGestureTap}></ha-svg-icon>
|
<ha-svg-icon slot="start" .path=${mdiGestureTap}></ha-svg-icon>
|
||||||
<div slot="headline">${manualStats.count} manual backups</div>
|
<div slot="headline">${manualStats.count} manual backups</div>
|
||||||
<div slot="supporting-text">
|
<div slot="supporting-text">
|
||||||
@ -83,7 +89,10 @@ class HaBackupOverviewBackups extends LitElement {
|
|||||||
</ha-md-list>
|
</ha-md-list>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<ha-button href="/config/backup/backups" @click=${this._showAll}>
|
<ha-button
|
||||||
|
href="/config/backup/backups?type=all"
|
||||||
|
@click=${this._showAll}
|
||||||
|
>
|
||||||
Show all backups
|
Show all backups
|
||||||
</ha-button>
|
</ha-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -28,6 +28,7 @@ import type {
|
|||||||
import "../../../components/ha-button";
|
import "../../../components/ha-button";
|
||||||
import "../../../components/ha-button-menu";
|
import "../../../components/ha-button-menu";
|
||||||
import "../../../components/ha-fab";
|
import "../../../components/ha-fab";
|
||||||
|
import "../../../components/ha-filter-states";
|
||||||
import "../../../components/ha-icon";
|
import "../../../components/ha-icon";
|
||||||
import "../../../components/ha-icon-next";
|
import "../../../components/ha-icon-next";
|
||||||
import "../../../components/ha-icon-overflow-menu";
|
import "../../../components/ha-icon-overflow-menu";
|
||||||
@ -46,6 +47,7 @@ import {
|
|||||||
} from "../../../data/backup";
|
} from "../../../data/backup";
|
||||||
import type { ManagerStateEvent } from "../../../data/backup_manager";
|
import type { ManagerStateEvent } from "../../../data/backup_manager";
|
||||||
import type { CloudStatus } from "../../../data/cloud";
|
import type { CloudStatus } from "../../../data/cloud";
|
||||||
|
import type { DataTableFiltersValues } from "../../../data/data_table_filters";
|
||||||
import { extractApiErrorMessage } from "../../../data/hassio/common";
|
import { extractApiErrorMessage } from "../../../data/hassio/common";
|
||||||
import {
|
import {
|
||||||
showAlertDialog,
|
showAlertDialog,
|
||||||
@ -89,6 +91,14 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
|
|||||||
|
|
||||||
@state() private _selected: string[] = [];
|
@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 })
|
@storage({ key: "backups-table-grouping", state: false, subscribe: false })
|
||||||
private _activeGrouping?: string = "formatted_type";
|
private _activeGrouping?: string = "formatted_type";
|
||||||
|
|
||||||
@ -102,6 +112,27 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
|
|||||||
@query("hass-tabs-subpage-data-table", true)
|
@query("hass-tabs-subpage-data-table", true)
|
||||||
private _dataTable!: HaTabsSubpageDataTable;
|
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(
|
private _columns = memoizeOne(
|
||||||
(localize: LocalizeFunc): DataTableColumnContainer<BackupRow> => ({
|
(localize: LocalizeFunc): DataTableColumnContainer<BackupRow> => ({
|
||||||
name: {
|
name: {
|
||||||
@ -230,13 +261,28 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
|
|||||||
return capitalizeFirstLetter(type);
|
return capitalizeFirstLetter(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _data = memoizeOne((backups: BackupContent[]): BackupRow[] =>
|
private _data = memoizeOne(
|
||||||
backups.map((backup) => ({
|
(
|
||||||
...backup,
|
backups: BackupContent[],
|
||||||
formatted_type: this._formatBackupType(
|
filters: DataTableFiltersValues
|
||||||
backup.with_automatic_settings ? "automatic" : "manual"
|
): 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 {
|
protected render(): TemplateResult {
|
||||||
@ -257,6 +303,15 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
|
|||||||
back-path="/config/backup/overview"
|
back-path="/config/backup/overview"
|
||||||
clickable
|
clickable
|
||||||
id="backup_id"
|
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
|
selectable
|
||||||
.selected=${this._selected.length}
|
.selected=${this._selected.length}
|
||||||
.initialGroupColumn=${this._activeGrouping}
|
.initialGroupColumn=${this._activeGrouping}
|
||||||
@ -268,7 +323,7 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
|
|||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
@row-click=${this._showBackupDetails}
|
@row-click=${this._showBackupDetails}
|
||||||
.columns=${this._columns(this.hass.localize)}
|
.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")}
|
.noDataText=${this.hass.localize("ui.panel.config.backup.no_backups")}
|
||||||
.searchLabel=${this.hass.localize(
|
.searchLabel=${this.hass.localize(
|
||||||
"ui.panel.config.backup.picker.search"
|
"ui.panel.config.backup.picker.search"
|
||||||
@ -324,6 +379,16 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
|
|||||||
</div>
|
</div>
|
||||||
</div> `
|
</div> `
|
||||||
: nothing}
|
: nothing}
|
||||||
|
<ha-filter-states
|
||||||
|
.hass=${this.hass}
|
||||||
|
label="Type"
|
||||||
|
.value=${this._filters["ha-filter-states"]}
|
||||||
|
.states=${this._states(this.hass.localize)}
|
||||||
|
@data-table-filter-changed=${this._filterChanged}
|
||||||
|
slot="filter-pane"
|
||||||
|
expanded
|
||||||
|
.narrow=${this.narrow}
|
||||||
|
></ha-filter-states>
|
||||||
${!this._needsOnboarding
|
${!this._needsOnboarding
|
||||||
? html`
|
? html`
|
||||||
<ha-fab
|
<ha-fab
|
||||||
@ -341,6 +406,35 @@ class HaConfigBackupBackups extends SubscribeMixin(LitElement) {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _states = memoizeOne((_localize: LocalizeFunc) => [
|
||||||
|
{
|
||||||
|
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() {
|
private get _needsOnboarding() {
|
||||||
return !this.config?.create_backup.password;
|
return !this.config?.create_backup.password;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user