mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-22 00:36:34 +00:00
Save data table filters in session storage (#20894)
* Save data table filters in session storage * typing fix * remove url logic, rename storage key
This commit is contained in:
parent
91e5fcacd5
commit
2921161336
@ -108,6 +108,8 @@ export const storage =
|
||||
subscribe?: boolean;
|
||||
state?: boolean;
|
||||
stateOptions?: InternalPropertyDeclaration;
|
||||
serializer?: (value: any) => any;
|
||||
deserializer?: (value: any) => any;
|
||||
}): any =>
|
||||
(clsElement: ClassElement) => {
|
||||
const storageName = options.storage || "localStorage";
|
||||
@ -141,7 +143,9 @@ export const storage =
|
||||
|
||||
const getValue = (): any =>
|
||||
storageInstance.hasKey(storageKey!)
|
||||
? storageInstance.getValue(storageKey!)
|
||||
? options.deserializer
|
||||
? options.deserializer(storageInstance.getValue(storageKey!))
|
||||
: storageInstance.getValue(storageKey!)
|
||||
: initVal;
|
||||
|
||||
const setValue = (el: ReactiveElement, value: any) => {
|
||||
@ -149,7 +153,10 @@ export const storage =
|
||||
if (options.state) {
|
||||
oldValue = getValue();
|
||||
}
|
||||
storageInstance.setValue(storageKey!, value);
|
||||
storageInstance.setValue(
|
||||
storageKey!,
|
||||
options.serializer ? options.serializer(value) : value
|
||||
);
|
||||
if (options.state) {
|
||||
el.requestUpdate(clsElement.key, oldValue);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ declare global {
|
||||
|
||||
export interface NavigateOptions {
|
||||
replace?: boolean;
|
||||
data?: any;
|
||||
}
|
||||
|
||||
export const navigate = (path: string, options?: NavigateOptions) => {
|
||||
@ -24,7 +25,7 @@ export const navigate = (path: string, options?: NavigateOptions) => {
|
||||
if (__DEMO__) {
|
||||
if (replace) {
|
||||
mainWindow.history.replaceState(
|
||||
mainWindow.history.state?.root ? { root: true } : null,
|
||||
mainWindow.history.state?.root ? { root: true } : options?.data ?? null,
|
||||
"",
|
||||
`${mainWindow.location.pathname}#${path}`
|
||||
);
|
||||
@ -33,12 +34,12 @@ export const navigate = (path: string, options?: NavigateOptions) => {
|
||||
}
|
||||
} else if (replace) {
|
||||
mainWindow.history.replaceState(
|
||||
mainWindow.history.state?.root ? { root: true } : null,
|
||||
mainWindow.history.state?.root ? { root: true } : options?.data ?? null,
|
||||
"",
|
||||
path
|
||||
);
|
||||
} else {
|
||||
mainWindow.history.pushState(null, "", path);
|
||||
mainWindow.history.pushState(options?.data ?? null, "", path);
|
||||
}
|
||||
fireEvent(mainWindow, "location-changed", {
|
||||
replace,
|
||||
|
@ -1,7 +1,14 @@
|
||||
import { SelectedDetail } from "@material/mwc-list";
|
||||
import "@material/mwc-menu/mwc-menu-surface";
|
||||
import { mdiFilterVariantRemove } from "@mdi/js";
|
||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import {
|
||||
css,
|
||||
CSSResultGroup,
|
||||
html,
|
||||
LitElement,
|
||||
nothing,
|
||||
PropertyValues,
|
||||
} from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { Blueprints, fetchBlueprints } from "../data/blueprint";
|
||||
@ -25,6 +32,16 @@ export class HaFilterBlueprints extends LitElement {
|
||||
|
||||
@state() private _blueprints?: Blueprints;
|
||||
|
||||
public willUpdate(properties: PropertyValues) {
|
||||
super.willUpdate(properties);
|
||||
|
||||
if (!this.hasUpdated) {
|
||||
if (this.value?.length) {
|
||||
this._findRelated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<ha-expansion-panel
|
||||
@ -96,7 +113,6 @@ export class HaFilterBlueprints extends LitElement {
|
||||
ev: CustomEvent<SelectedDetail<Set<number>>>
|
||||
) {
|
||||
const blueprints = this._blueprints!;
|
||||
const relatedPromises: Promise<RelatedResult>[] = [];
|
||||
|
||||
if (!ev.detail.index.size) {
|
||||
fireEvent(this, "data-table-filter-changed", {
|
||||
@ -112,13 +128,33 @@ export class HaFilterBlueprints extends LitElement {
|
||||
for (const index of ev.detail.index) {
|
||||
const blueprintId = Object.keys(blueprints)[index];
|
||||
value.push(blueprintId);
|
||||
}
|
||||
|
||||
this.value = value;
|
||||
|
||||
this._findRelated();
|
||||
}
|
||||
|
||||
private async _findRelated() {
|
||||
if (!this.value?.length) {
|
||||
fireEvent(this, "data-table-filter-changed", {
|
||||
value: [],
|
||||
items: undefined,
|
||||
});
|
||||
this.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const relatedPromises: Promise<RelatedResult>[] = [];
|
||||
|
||||
for (const blueprintId of this.value) {
|
||||
if (this.type) {
|
||||
relatedPromises.push(
|
||||
findRelated(this.hass, `${this.type}_blueprint`, blueprintId)
|
||||
);
|
||||
}
|
||||
}
|
||||
this.value = value;
|
||||
|
||||
const results = await Promise.all(relatedPromises);
|
||||
const items: Set<string> = new Set();
|
||||
for (const result of results) {
|
||||
@ -128,7 +164,7 @@ export class HaFilterBlueprints extends LitElement {
|
||||
}
|
||||
|
||||
fireEvent(this, "data-table-filter-changed", {
|
||||
value,
|
||||
value: this.value,
|
||||
items: this.type ? items : undefined,
|
||||
});
|
||||
}
|
||||
|
@ -41,6 +41,9 @@ export class HaFilterDevices extends LitElement {
|
||||
|
||||
if (!this.hasUpdated) {
|
||||
loadVirtualizer();
|
||||
if (this.value?.length) {
|
||||
this._findRelated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,9 @@ export class HaFilterEntities extends LitElement {
|
||||
|
||||
if (!this.hasUpdated) {
|
||||
loadVirtualizer();
|
||||
if (this.value?.length) {
|
||||
this._findRelated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,15 +189,12 @@ export class HaFilterEntities extends LitElement {
|
||||
return;
|
||||
}
|
||||
|
||||
const value: string[] = [];
|
||||
|
||||
for (const entityId of this.value) {
|
||||
value.push(entityId);
|
||||
if (this.type) {
|
||||
relatedPromises.push(findRelated(this.hass, "entity", entityId));
|
||||
}
|
||||
}
|
||||
this.value = value;
|
||||
|
||||
const results = await Promise.all(relatedPromises);
|
||||
const items: Set<string> = new Set();
|
||||
for (const result of results) {
|
||||
@ -204,7 +204,7 @@ export class HaFilterEntities extends LitElement {
|
||||
}
|
||||
|
||||
fireEvent(this, "data-table-filter-changed", {
|
||||
value,
|
||||
value: this.value,
|
||||
items: this.type ? items : undefined,
|
||||
});
|
||||
}
|
||||
|
@ -1,7 +1,14 @@
|
||||
import "@material/mwc-menu/mwc-menu-surface";
|
||||
import { mdiFilterVariantRemove, mdiTextureBox } from "@mdi/js";
|
||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
|
||||
import {
|
||||
CSSResultGroup,
|
||||
LitElement,
|
||||
PropertyValues,
|
||||
css,
|
||||
html,
|
||||
nothing,
|
||||
} from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { repeat } from "lit/directives/repeat";
|
||||
@ -42,6 +49,16 @@ export class HaFilterFloorAreas extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _floors?: FloorRegistryEntry[];
|
||||
|
||||
public willUpdate(properties: PropertyValues) {
|
||||
super.willUpdate(properties);
|
||||
|
||||
if (!this.hasUpdated) {
|
||||
if (this.value?.floors?.length || this.value?.areas?.length) {
|
||||
this._findRelated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
const areas = this._areas(this.hass.areas, this._floors);
|
||||
|
||||
@ -190,6 +207,10 @@ export class HaFilterFloorAreas extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
}
|
||||
|
||||
protected firstUpdated() {
|
||||
this._findRelated();
|
||||
}
|
||||
|
||||
private _expandedWillChange(ev) {
|
||||
this._shouldRender = ev.detail.expanded;
|
||||
}
|
||||
|
28
src/data/data_table_filters.ts
Normal file
28
src/data/data_table_filters.ts
Normal file
@ -0,0 +1,28 @@
|
||||
export interface DataTableFilters {
|
||||
[key: string]: {
|
||||
value: string[] | { key: string[] } | undefined;
|
||||
items: Set<string> | undefined;
|
||||
};
|
||||
}
|
||||
|
||||
export const serializeFilters = (value: DataTableFilters) => {
|
||||
const serializedValue = {};
|
||||
Object.entries(value).forEach(([key, val]) => {
|
||||
serializedValue[key] = {
|
||||
value: val.value,
|
||||
items: val.items instanceof Set ? Array.from(val.items) : val.items,
|
||||
};
|
||||
});
|
||||
return serializedValue;
|
||||
};
|
||||
|
||||
export const deserializeFilters = (value: DataTableFilters) => {
|
||||
const deserializedValue = {};
|
||||
Object.entries(value).forEach(([key, val]) => {
|
||||
deserializedValue[key] = {
|
||||
value: val.value,
|
||||
items: Array.isArray(val.items) ? new Set(val.items) : val.items,
|
||||
};
|
||||
});
|
||||
return deserializedValue;
|
||||
};
|
@ -114,6 +114,11 @@ import { showCategoryRegistryDetailDialog } from "../category/show-dialog-catego
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import { showNewAutomationDialog } from "./show-dialog-new-automation";
|
||||
import {
|
||||
DataTableFilters,
|
||||
deserializeFilters,
|
||||
serializeFilters,
|
||||
} from "../../../data/data_table_filters";
|
||||
|
||||
type AutomationItem = AutomationEntity & {
|
||||
name: string;
|
||||
@ -140,10 +145,15 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _filteredAutomations?: string[] | null;
|
||||
|
||||
@state() private _filters: Record<
|
||||
string,
|
||||
{ value: string[] | undefined; items: Set<string> | undefined }
|
||||
> = {};
|
||||
@storage({
|
||||
storage: "sessionStorage",
|
||||
key: "automation-table-filters-full",
|
||||
state: true,
|
||||
subscribe: false,
|
||||
serializer: serializeFilters,
|
||||
deserializer: deserializeFilters,
|
||||
})
|
||||
private _filters: DataTableFilters = {};
|
||||
|
||||
@state() private _expandedFilter?: string;
|
||||
|
||||
@ -916,7 +926,7 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _filterChanged(ev) {
|
||||
const type = ev.target.localName;
|
||||
this._filters[type] = ev.detail;
|
||||
this._filters = { ...this._filters, [type]: ev.detail };
|
||||
this._applyFilters();
|
||||
}
|
||||
|
||||
@ -935,7 +945,11 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
|
||||
items.intersection(filter.items)
|
||||
: new Set([...items].filter((x) => filter.items!.has(x)));
|
||||
}
|
||||
if (key === "ha-filter-categories" && filter.value?.length) {
|
||||
if (
|
||||
key === "ha-filter-categories" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
const categoryItems: Set<string> = new Set();
|
||||
this.automations
|
||||
.filter(
|
||||
@ -956,13 +970,17 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
|
||||
items.intersection(categoryItems)
|
||||
: new Set([...items].filter((x) => categoryItems!.has(x)));
|
||||
}
|
||||
if (key === "ha-filter-labels" && filter.value?.length) {
|
||||
if (
|
||||
key === "ha-filter-labels" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
const labelItems: Set<string> = new Set();
|
||||
this.automations
|
||||
.filter((automation) =>
|
||||
this._entityReg
|
||||
.find((reg) => reg.entity_id === automation.entity_id)
|
||||
?.labels.some((lbl) => filter.value!.includes(lbl))
|
||||
?.labels.some((lbl) => (filter.value as string[]).includes(lbl))
|
||||
)
|
||||
.forEach((automation) => labelItems.add(automation.entity_id));
|
||||
if (!items) {
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
import {
|
||||
CSSResultGroup,
|
||||
LitElement,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
css,
|
||||
html,
|
||||
@ -85,6 +86,11 @@ import "../integrations/ha-integration-overflow-menu";
|
||||
import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||
import {
|
||||
serializeFilters,
|
||||
deserializeFilters,
|
||||
DataTableFilters,
|
||||
} from "../../../data/data_table_filters";
|
||||
|
||||
interface DeviceRowData extends DeviceRegistryEntry {
|
||||
device?: DeviceRowData;
|
||||
@ -118,10 +124,15 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _filter: string = history.state?.filter || "";
|
||||
|
||||
@state() private _filters: Record<
|
||||
string,
|
||||
{ value: string[] | undefined; items: Set<string> | undefined }
|
||||
> = {};
|
||||
@storage({
|
||||
storage: "sessionStorage",
|
||||
key: "devices-table-filters-full",
|
||||
state: true,
|
||||
subscribe: false,
|
||||
serializer: serializeFilters,
|
||||
deserializer: deserializeFilters,
|
||||
})
|
||||
private _filters: DataTableFilters = {};
|
||||
|
||||
@state() private _expandedFilter?: string;
|
||||
|
||||
@ -180,14 +191,11 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
|
||||
},
|
||||
]);
|
||||
|
||||
firstUpdated() {
|
||||
this._filters = {
|
||||
"ha-filter-states": {
|
||||
value: [],
|
||||
items: undefined,
|
||||
},
|
||||
};
|
||||
this._setFiltersFromUrl();
|
||||
willUpdate(changedProps: PropertyValues) {
|
||||
super.willUpdate(changedProps);
|
||||
if (!this.hasUpdated) {
|
||||
this._setFiltersFromUrl();
|
||||
}
|
||||
}
|
||||
|
||||
private _setFiltersFromUrl() {
|
||||
@ -196,7 +204,7 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
|
||||
...this._filters,
|
||||
"ha-filter-states": {
|
||||
value: [
|
||||
...(this._filters["ha-filter-states"]?.value || []),
|
||||
...((this._filters["ha-filter-states"]?.value as string[]) || []),
|
||||
"disabled",
|
||||
],
|
||||
items: undefined,
|
||||
@ -212,7 +220,7 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
|
||||
...this._filters,
|
||||
"ha-filter-states": {
|
||||
value: [
|
||||
...(this._filters["ha-filter-states"]?.value || []),
|
||||
...((this._filters["ha-filter-states"]?.value as string[]) || []),
|
||||
"disabled",
|
||||
],
|
||||
items: undefined,
|
||||
@ -253,10 +261,7 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
|
||||
entities: EntityRegistryEntry[],
|
||||
areas: HomeAssistant["areas"],
|
||||
manifests: IntegrationManifest[],
|
||||
filters: Record<
|
||||
string,
|
||||
{ value: string[] | undefined; items: Set<string> | undefined }
|
||||
>,
|
||||
filters: DataTableFilters,
|
||||
localize: LocalizeFunc,
|
||||
labelReg?: LabelRegistryEntry[]
|
||||
) => {
|
||||
@ -295,15 +300,21 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
|
||||
const filteredDomains = new Set<string>();
|
||||
|
||||
Object.entries(filters).forEach(([key, filter]) => {
|
||||
if (key === "config_entry" && filter.value?.length) {
|
||||
if (
|
||||
key === "config_entry" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
outputDevices = outputDevices.filter((device) =>
|
||||
device.config_entries.some((entryId) =>
|
||||
filter.value?.includes(entryId)
|
||||
(filter.value as string[]).includes(entryId)
|
||||
)
|
||||
);
|
||||
|
||||
const configEntries = entries.filter(
|
||||
(entry) => entry.entry_id && filter.value?.includes(entry.entry_id)
|
||||
(entry) =>
|
||||
entry.entry_id &&
|
||||
(filter.value as string[]).includes(entry.entry_id)
|
||||
);
|
||||
|
||||
configEntries.forEach((configEntry) => {
|
||||
@ -312,17 +323,31 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
|
||||
if (configEntries.length === 1) {
|
||||
filteredConfigEntry = configEntries[0];
|
||||
}
|
||||
} else if (key === "ha-filter-integrations" && filter.value?.length) {
|
||||
} else if (
|
||||
key === "ha-filter-integrations" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
const entryIds = entries
|
||||
.filter((entry) => filter.value!.includes(entry.domain))
|
||||
.filter((entry) =>
|
||||
(filter.value as string[]).includes(entry.domain)
|
||||
)
|
||||
.map((entry) => entry.entry_id);
|
||||
outputDevices = outputDevices.filter((device) =>
|
||||
device.config_entries.some((entryId) => entryIds.includes(entryId))
|
||||
);
|
||||
filter.value!.forEach((domain) => filteredDomains.add(domain));
|
||||
} else if (key === "ha-filter-labels" && filter.value?.length) {
|
||||
(filter.value as string[]).forEach((domain) =>
|
||||
filteredDomains.add(domain)
|
||||
);
|
||||
} else if (
|
||||
key === "ha-filter-labels" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
outputDevices = outputDevices.filter((device) =>
|
||||
device.labels.some((lbl) => filter.value!.includes(lbl))
|
||||
device.labels.some((lbl) =>
|
||||
(filter.value as string[]).includes(lbl)
|
||||
)
|
||||
);
|
||||
} else if (filter.items) {
|
||||
outputDevices = outputDevices.filter((device) =>
|
||||
@ -331,7 +356,9 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
});
|
||||
|
||||
const stateFilters = filters["ha-filter-states"]?.value;
|
||||
const stateFilters = filters["ha-filter-states"]?.value as
|
||||
| string[]
|
||||
| undefined;
|
||||
|
||||
const showDisabled =
|
||||
stateFilters?.length && stateFilters.includes("disabled");
|
||||
@ -698,7 +725,8 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
</ha-fab>
|
||||
${this._filters.config_entry?.value?.length
|
||||
${Array.isArray(this._filters.config_entry?.value) &&
|
||||
this._filters.config_entry?.value.length
|
||||
? html`<ha-alert slot="filter-pane">
|
||||
Filtering by config entry
|
||||
${this.entries?.find(
|
||||
|
@ -98,6 +98,11 @@ import { configSections } from "../ha-panel-config";
|
||||
import "../integrations/ha-integration-overflow-menu";
|
||||
import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import {
|
||||
serializeFilters,
|
||||
deserializeFilters,
|
||||
DataTableFilters,
|
||||
} from "../../../data/data_table_filters";
|
||||
|
||||
export interface StateEntity
|
||||
extends Omit<EntityRegistryEntry, "id" | "unique_id"> {
|
||||
@ -143,10 +148,15 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _searchParms = new URLSearchParams(window.location.search);
|
||||
|
||||
@state() private _filters: Record<
|
||||
string,
|
||||
{ value: string[] | undefined; items: Set<string> | undefined }
|
||||
> = {};
|
||||
@storage({
|
||||
storage: "sessionStorage",
|
||||
key: "entities-table-filters-full",
|
||||
state: true,
|
||||
subscribe: false,
|
||||
serializer: serializeFilters,
|
||||
deserializer: deserializeFilters,
|
||||
})
|
||||
private _filters: DataTableFilters = {};
|
||||
|
||||
@state() private _selected: string[] = [];
|
||||
|
||||
@ -414,16 +424,13 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
devices: HomeAssistant["devices"],
|
||||
areas: HomeAssistant["areas"],
|
||||
stateEntities: StateEntity[],
|
||||
filters: Record<
|
||||
string,
|
||||
{ value: string[] | undefined; items: Set<string> | undefined }
|
||||
>,
|
||||
filters: DataTableFilters,
|
||||
entries?: ConfigEntry[],
|
||||
labelReg?: LabelRegistryEntry[]
|
||||
) => {
|
||||
const result: EntityRow[] = [];
|
||||
|
||||
const stateFilters = filters["ha-filter-states"]?.value;
|
||||
const stateFilters = filters["ha-filter-states"]?.value as string[];
|
||||
|
||||
const showEnabled =
|
||||
!stateFilters?.length || stateFilters.includes("enabled");
|
||||
@ -448,11 +455,15 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
const filteredDomains = new Set<string>();
|
||||
|
||||
Object.entries(filters).forEach(([key, filter]) => {
|
||||
if (key === "config_entry" && filter.value?.length) {
|
||||
if (
|
||||
key === "config_entry" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
filteredEntities = filteredEntities.filter(
|
||||
(entity) =>
|
||||
entity.config_entry_id &&
|
||||
filter.value?.includes(entity.config_entry_id)
|
||||
(filter.value as string[]).includes(entity.config_entry_id)
|
||||
);
|
||||
|
||||
if (!entries) {
|
||||
@ -461,7 +472,9 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
|
||||
const configEntries = entries.filter(
|
||||
(entry) => entry.entry_id && filter.value?.includes(entry.entry_id)
|
||||
(entry) =>
|
||||
entry.entry_id &&
|
||||
(filter.value as string[]).includes(entry.entry_id)
|
||||
);
|
||||
|
||||
configEntries.forEach((configEntry) => {
|
||||
@ -470,29 +483,45 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
if (configEntries.length === 1) {
|
||||
filteredConfigEntry = configEntries[0];
|
||||
}
|
||||
} else if (key === "ha-filter-integrations" && filter.value?.length) {
|
||||
} else if (
|
||||
key === "ha-filter-integrations" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
if (!entries) {
|
||||
this._loadConfigEntries();
|
||||
return;
|
||||
}
|
||||
const entryIds = entries
|
||||
.filter((entry) => filter.value!.includes(entry.domain))
|
||||
.filter((entry) =>
|
||||
(filter.value as string[]).includes(entry.domain)
|
||||
)
|
||||
.map((entry) => entry.entry_id);
|
||||
|
||||
filteredEntities = filteredEntities.filter(
|
||||
(entity) =>
|
||||
filter.value?.includes(entity.platform) ||
|
||||
(filter.value as string[]).includes(entity.platform) ||
|
||||
(entity.config_entry_id &&
|
||||
entryIds.includes(entity.config_entry_id))
|
||||
);
|
||||
filter.value!.forEach((domain) => filteredDomains.add(domain));
|
||||
} else if (key === "ha-filter-domains" && filter.value?.length) {
|
||||
} else if (
|
||||
key === "ha-filter-domains" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
filteredEntities = filteredEntities.filter((entity) =>
|
||||
filter.value?.includes(computeDomain(entity.entity_id))
|
||||
(filter.value as string[]).includes(computeDomain(entity.entity_id))
|
||||
);
|
||||
} else if (key === "ha-filter-labels" && filter.value?.length) {
|
||||
} else if (
|
||||
key === "ha-filter-labels" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
filteredEntities = filteredEntities.filter((entity) =>
|
||||
entity.labels.some((lbl) => filter.value!.includes(lbl))
|
||||
entity.labels.some((lbl) =>
|
||||
(filter.value as string[]).includes(lbl)
|
||||
)
|
||||
);
|
||||
} else if (filter.items) {
|
||||
filteredEntities = filteredEntities.filter((entity) =>
|
||||
@ -811,7 +840,8 @@ ${
|
||||
|
||||
</ha-button-menu-new>
|
||||
${
|
||||
this._filters.config_entry?.value?.length
|
||||
Array.isArray(this._filters.config_entry?.value) &&
|
||||
this._filters.config_entry?.value.length
|
||||
? html`<ha-alert slot="filter-pane">
|
||||
Filtering by config entry
|
||||
${this._entries?.find(
|
||||
@ -913,6 +943,9 @@ ${
|
||||
}
|
||||
|
||||
protected firstUpdated() {
|
||||
if (Object.keys(this._filters).length) {
|
||||
return;
|
||||
}
|
||||
this._filters = {
|
||||
"ha-filter-states": {
|
||||
value: ["enabled"],
|
||||
|
@ -96,6 +96,11 @@ import "../integrations/ha-integration-overflow-menu";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import { isHelperDomain } from "./const";
|
||||
import { showHelperDetailDialog } from "./show-dialog-helper-detail";
|
||||
import {
|
||||
serializeFilters,
|
||||
deserializeFilters,
|
||||
DataTableFilters,
|
||||
} from "../../../data/data_table_filters";
|
||||
|
||||
type HelperItem = {
|
||||
id: string;
|
||||
@ -164,10 +169,15 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _activeFilters?: string[];
|
||||
|
||||
@state() private _filters: Record<
|
||||
string,
|
||||
{ value: string[] | undefined; items: Set<string> | undefined }
|
||||
> = {};
|
||||
@storage({
|
||||
storage: "sessionStorage",
|
||||
key: "helpers-table-filters-full",
|
||||
state: true,
|
||||
subscribe: false,
|
||||
serializer: serializeFilters,
|
||||
deserializer: deserializeFilters,
|
||||
})
|
||||
private _filters: DataTableFilters = {};
|
||||
|
||||
@state() private _expandedFilter?: string;
|
||||
|
||||
@ -722,7 +732,7 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _filterChanged(ev) {
|
||||
const type = ev.target.localName;
|
||||
this._filters[type] = ev.detail;
|
||||
this._filters = { ...this._filters, [type]: ev.detail };
|
||||
this._applyFilters();
|
||||
}
|
||||
|
||||
@ -741,13 +751,17 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
||||
items.intersection(filter.items)
|
||||
: new Set([...items].filter((x) => filter.items!.has(x)));
|
||||
}
|
||||
if (key === "ha-filter-labels" && filter.value?.length) {
|
||||
if (
|
||||
key === "ha-filter-labels" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
const labelItems: Set<string> = new Set();
|
||||
this._stateItems
|
||||
.filter((stateItem) =>
|
||||
this._entityReg
|
||||
.find((reg) => reg.entity_id === stateItem.entity_id)
|
||||
?.labels.some((lbl) => filter.value!.includes(lbl))
|
||||
?.labels.some((lbl) => (filter.value as string[]).includes(lbl))
|
||||
)
|
||||
.forEach((stateItem) => labelItems.add(stateItem.entity_id));
|
||||
if (!items) {
|
||||
@ -760,7 +774,11 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
||||
items.intersection(labelItems)
|
||||
: new Set([...items].filter((x) => labelItems!.has(x)));
|
||||
}
|
||||
if (key === "ha-filter-categories" && filter.value?.length) {
|
||||
if (
|
||||
key === "ha-filter-categories" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
const categoryItems: Set<string> = new Set();
|
||||
this._stateItems
|
||||
.filter(
|
||||
|
@ -104,6 +104,11 @@ import { showAssignCategoryDialog } from "../category/show-dialog-assign-categor
|
||||
import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import {
|
||||
serializeFilters,
|
||||
deserializeFilters,
|
||||
DataTableFilters,
|
||||
} from "../../../data/data_table_filters";
|
||||
|
||||
type SceneItem = SceneEntity & {
|
||||
name: string;
|
||||
@ -132,10 +137,15 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _filteredScenes?: string[] | null;
|
||||
|
||||
@state() private _filters: Record<
|
||||
string,
|
||||
{ value: string[] | undefined; items: Set<string> | undefined }
|
||||
> = {};
|
||||
@storage({
|
||||
storage: "sessionStorage",
|
||||
key: "scene-table-filters-full",
|
||||
state: true,
|
||||
subscribe: false,
|
||||
serializer: serializeFilters,
|
||||
deserializer: deserializeFilters,
|
||||
})
|
||||
private _filters: DataTableFilters = {};
|
||||
|
||||
@state() private _expandedFilter?: string;
|
||||
|
||||
@ -783,7 +793,7 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _filterChanged(ev) {
|
||||
const type = ev.target.localName;
|
||||
this._filters[type] = ev.detail;
|
||||
this._filters = { ...this._filters, [type]: ev.detail };
|
||||
this._applyFilters();
|
||||
}
|
||||
|
||||
@ -802,7 +812,11 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
|
||||
items.intersection(filter.items)
|
||||
: new Set([...items].filter((x) => filter.items!.has(x)));
|
||||
}
|
||||
if (key === "ha-filter-categories" && filter.value?.length) {
|
||||
if (
|
||||
key === "ha-filter-categories" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
const categoryItems: Set<string> = new Set();
|
||||
this.scenes
|
||||
.filter(
|
||||
@ -822,13 +836,17 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
|
||||
items.intersection(categoryItems)
|
||||
: new Set([...items].filter((x) => categoryItems!.has(x)));
|
||||
}
|
||||
if (key === "ha-filter-labels" && filter.value?.length) {
|
||||
if (
|
||||
key === "ha-filter-labels" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
const labelItems: Set<string> = new Set();
|
||||
this.scenes
|
||||
.filter((scene) =>
|
||||
this._entityReg
|
||||
.find((reg) => reg.entity_id === scene.entity_id)
|
||||
?.labels.some((lbl) => filter.value!.includes(lbl))
|
||||
?.labels.some((lbl) => (filter.value as string[]).includes(lbl))
|
||||
)
|
||||
.forEach((scene) => labelItems.add(scene.entity_id));
|
||||
if (!items) {
|
||||
|
@ -106,6 +106,11 @@ import { showAssignCategoryDialog } from "../category/show-dialog-assign-categor
|
||||
import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import {
|
||||
serializeFilters,
|
||||
deserializeFilters,
|
||||
DataTableFilters,
|
||||
} from "../../../data/data_table_filters";
|
||||
|
||||
type ScriptItem = ScriptEntity & {
|
||||
name: string;
|
||||
@ -136,10 +141,15 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _filteredScripts?: string[] | null;
|
||||
|
||||
@state() private _filters: Record<
|
||||
string,
|
||||
{ value: string[] | undefined; items: Set<string> | undefined }
|
||||
> = {};
|
||||
@storage({
|
||||
storage: "sessionStorage",
|
||||
key: "script-table-filters-full",
|
||||
state: true,
|
||||
subscribe: false,
|
||||
serializer: serializeFilters,
|
||||
deserializer: deserializeFilters,
|
||||
})
|
||||
private _filters: DataTableFilters = {};
|
||||
|
||||
@state() private _expandedFilter?: string;
|
||||
|
||||
@ -812,7 +822,7 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _filterChanged(ev) {
|
||||
const type = ev.target.localName;
|
||||
this._filters[type] = ev.detail;
|
||||
this._filters = { ...this._filters, [type]: ev.detail };
|
||||
this._applyFilters();
|
||||
}
|
||||
|
||||
@ -836,7 +846,11 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
|
||||
items.intersection(filter.items)
|
||||
: new Set([...items].filter((x) => filter.items!.has(x)));
|
||||
}
|
||||
if (key === "ha-filter-categories" && filter.value?.length) {
|
||||
if (
|
||||
key === "ha-filter-categories" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
const categoryItems: Set<string> = new Set();
|
||||
this.scripts
|
||||
.filter(
|
||||
@ -856,13 +870,17 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
|
||||
items.intersection(categoryItems)
|
||||
: new Set([...items].filter((x) => categoryItems!.has(x)));
|
||||
}
|
||||
if (key === "ha-filter-labels" && filter.value?.length) {
|
||||
if (
|
||||
key === "ha-filter-labels" &&
|
||||
Array.isArray(filter.value) &&
|
||||
filter.value.length
|
||||
) {
|
||||
const labelItems: Set<string> = new Set();
|
||||
this.scripts
|
||||
.filter((script) =>
|
||||
this._entityReg
|
||||
.find((reg) => reg.entity_id === script.entity_id)
|
||||
?.labels.some((lbl) => filter.value!.includes(lbl))
|
||||
?.labels.some((lbl) => (filter.value as string[]).includes(lbl))
|
||||
)
|
||||
.forEach((script) => labelItems.add(script.entity_id));
|
||||
if (!items) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user