diff --git a/src/data/selector.ts b/src/data/selector.ts
index c72dacc4f1..5623ecc268 100644
--- a/src/data/selector.ts
+++ b/src/data/selector.ts
@@ -1,4 +1,7 @@
-import type { HassEntity } from "home-assistant-js-websocket";
+import type {
+ HassEntity,
+ HassServiceTarget,
+} from "home-assistant-js-websocket";
import { ensureArray } from "../common/array/ensure-array";
import { computeStateDomain } from "../common/entity/compute_state_domain";
import { supportsFeature } from "../common/entity/supports-feature";
@@ -871,3 +874,65 @@ export const computeCreateDomains = (
return [...new Set(createDomains)];
};
+
+export const resolveEntityIDs = (
+ hass: HomeAssistant,
+ targetPickerValue: HassServiceTarget,
+ entities: HomeAssistant["entities"],
+ devices: HomeAssistant["devices"],
+ areas: HomeAssistant["areas"]
+): string[] => {
+ if (!targetPickerValue) {
+ return [];
+ }
+
+ const targetSelector = { target: {} };
+ const targetEntities = new Set(ensureArray(targetPickerValue.entity_id));
+ const targetDevices = new Set(ensureArray(targetPickerValue.device_id));
+ const targetAreas = new Set(ensureArray(targetPickerValue.area_id));
+ const targetFloors = new Set(ensureArray(targetPickerValue.floor_id));
+ const targetLabels = new Set(ensureArray(targetPickerValue.label_id));
+
+ targetLabels.forEach((labelId) => {
+ const expanded = expandLabelTarget(
+ hass,
+ labelId,
+ areas,
+ devices,
+ entities,
+ targetSelector
+ );
+ expanded.devices.forEach((id) => targetDevices.add(id));
+ expanded.entities.forEach((id) => targetEntities.add(id));
+ expanded.areas.forEach((id) => targetAreas.add(id));
+ });
+
+ targetFloors.forEach((floorId) => {
+ const expanded = expandFloorTarget(hass, floorId, areas, targetSelector);
+ expanded.areas.forEach((id) => targetAreas.add(id));
+ });
+
+ targetAreas.forEach((areaId) => {
+ const expanded = expandAreaTarget(
+ hass,
+ areaId,
+ devices,
+ entities,
+ targetSelector
+ );
+ expanded.devices.forEach((id) => targetDevices.add(id));
+ expanded.entities.forEach((id) => targetEntities.add(id));
+ });
+
+ targetDevices.forEach((deviceId) => {
+ const expanded = expandDeviceTarget(
+ hass,
+ deviceId,
+ entities,
+ targetSelector
+ );
+ expanded.entities.forEach((id) => targetEntities.add(id));
+ });
+
+ return Array.from(targetEntities);
+};
diff --git a/src/panels/history/ha-panel-history.ts b/src/panels/history/ha-panel-history.ts
index c167c48da1..39ff903a0c 100644
--- a/src/panels/history/ha-panel-history.ts
+++ b/src/panels/history/ha-panel-history.ts
@@ -50,12 +50,7 @@ import {
} from "../../data/history";
import type { Statistics } from "../../data/recorder";
import { fetchStatistics } from "../../data/recorder";
-import {
- expandAreaTarget,
- expandDeviceTarget,
- expandFloorTarget,
- expandLabelTarget,
-} from "../../data/selector";
+import { resolveEntityIDs } from "../../data/selector";
import { getSensorNumericDeviceClasses } from "../../data/sensor";
import { showAlertDialog } from "../../dialogs/generic/show-dialog-box";
import { haStyle } from "../../resources/styles";
@@ -543,66 +538,8 @@ class HaPanelHistory extends LitElement {
entities: HomeAssistant["entities"],
devices: HomeAssistant["devices"],
areas: HomeAssistant["areas"]
- ): string[] => {
- if (!targetPickerValue) {
- return [];
- }
-
- const targetSelector = { target: {} };
- const targetEntities = new Set(ensureArray(targetPickerValue.entity_id));
- const targetDevices = new Set(ensureArray(targetPickerValue.device_id));
- const targetAreas = new Set(ensureArray(targetPickerValue.area_id));
- const targetFloors = new Set(ensureArray(targetPickerValue.floor_id));
- const targetLabels = new Set(ensureArray(targetPickerValue.label_id));
-
- targetLabels.forEach((labelId) => {
- const expanded = expandLabelTarget(
- this.hass,
- labelId,
- areas,
- devices,
- entities,
- targetSelector
- );
- expanded.devices.forEach((id) => targetDevices.add(id));
- expanded.entities.forEach((id) => targetEntities.add(id));
- expanded.areas.forEach((id) => targetAreas.add(id));
- });
-
- targetFloors.forEach((floorId) => {
- const expanded = expandFloorTarget(
- this.hass,
- floorId,
- areas,
- targetSelector
- );
- expanded.areas.forEach((id) => targetAreas.add(id));
- });
-
- targetAreas.forEach((areaId) => {
- const expanded = expandAreaTarget(
- this.hass,
- areaId,
- devices,
- entities,
- targetSelector
- );
- expanded.devices.forEach((id) => targetDevices.add(id));
- expanded.entities.forEach((id) => targetEntities.add(id));
- });
-
- targetDevices.forEach((deviceId) => {
- const expanded = expandDeviceTarget(
- this.hass,
- deviceId,
- entities,
- targetSelector
- );
- expanded.entities.forEach((id) => targetEntities.add(id));
- });
-
- return Array.from(targetEntities);
- }
+ ): string[] =>
+ resolveEntityIDs(this.hass, targetPickerValue, entities, devices, areas)
);
private _dateRangeChanged(ev) {
diff --git a/src/panels/logbook/ha-panel-logbook.ts b/src/panels/logbook/ha-panel-logbook.ts
index 54c9f9b022..a69adc24a6 100644
--- a/src/panels/logbook/ha-panel-logbook.ts
+++ b/src/panels/logbook/ha-panel-logbook.ts
@@ -2,6 +2,8 @@ import { mdiRefresh } from "@mdi/js";
import type { PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
+import type { HassServiceTarget } from "home-assistant-js-websocket";
+import memoizeOne from "memoize-one";
import { navigate } from "../../common/navigate";
import { constructUrlCurrentPath } from "../../common/url/construct-url";
import {
@@ -15,10 +17,14 @@ import "../../components/ha-icon-button";
import "../../components/ha-icon-button-arrow-prev";
import "../../components/ha-menu-button";
import "../../components/ha-top-app-bar-fixed";
+import "../../components/ha-target-picker";
import { filterLogbookCompatibleEntities } from "../../data/logbook";
import { haStyle } from "../../resources/styles";
import type { HomeAssistant } from "../../types";
import "./ha-logbook";
+import { storage } from "../../common/decorators/storage";
+import { ensureArray } from "../../common/array/ensure-array";
+import { resolveEntityIDs } from "../../data/selector";
@customElement("ha-panel-logbook")
export class HaPanelLogbook extends LitElement {
@@ -33,6 +39,13 @@ export class HaPanelLogbook extends LitElement {
@state()
private _showBack?: boolean;
+ @storage({
+ key: "logbookPickedValue",
+ state: true,
+ subscribe: false,
+ })
+ private _targetPickerValue: HassServiceTarget = {};
+
public constructor() {
super();
@@ -82,21 +95,19 @@ export class HaPanelLogbook extends LitElement {
@change=${this._dateRangeChanged}
>
-
+ .value=${this._targetPickerValue}
+ addOnTop
+ @value-changed=${this._targetsChanged}
+ >
@@ -140,32 +151,62 @@ export class HaPanelLogbook extends LitElement {
this._applyURLParams();
};
+ private _getEntityIds(): string[] | undefined {
+ const entities = this.__getEntityIds(
+ this._targetPickerValue,
+ this.hass.entities,
+ this.hass.devices,
+ this.hass.areas
+ );
+ if (entities.length === 0) {
+ return undefined;
+ }
+ return entities;
+ }
+
+ private __getEntityIds = memoizeOne(
+ (
+ targetPickerValue: HassServiceTarget,
+ entities: HomeAssistant["entities"],
+ devices: HomeAssistant["devices"],
+ areas: HomeAssistant["areas"]
+ ): string[] =>
+ resolveEntityIDs(this.hass, targetPickerValue, entities, devices, areas)
+ );
+
private _applyURLParams() {
- const searchParams = new URLSearchParams(location.search);
-
- if (searchParams.has("entity_id")) {
- const entityIdsRaw = searchParams.get("entity_id");
-
- if (!entityIdsRaw) {
- this._entityIds = undefined;
- } else {
- const entityIds = entityIdsRaw.split(",").sort();
-
- // Check if different
- if (
- !this._entityIds ||
- entityIds.length !== this._entityIds.length ||
- !this._entityIds.every((val, idx) => val === entityIds[idx])
- ) {
- this._entityIds = entityIds;
- }
- }
- } else {
- this._entityIds = undefined;
+ const searchParams = extractSearchParamsObject();
+ const entityIds = searchParams.entity_id;
+ const deviceIds = searchParams.device_id;
+ const areaIds = searchParams.area_id;
+ const floorIds = searchParams.floor_id;
+ const labelsIds = searchParams.label_id;
+ if (entityIds || deviceIds || areaIds || floorIds || labelsIds) {
+ this._targetPickerValue = {};
+ }
+ if (entityIds) {
+ const splitIds = entityIds.split(",");
+ this._targetPickerValue!.entity_id = splitIds;
+ }
+ if (deviceIds) {
+ const splitIds = deviceIds.split(",");
+ this._targetPickerValue!.device_id = splitIds;
+ }
+ if (areaIds) {
+ const splitIds = areaIds.split(",");
+ this._targetPickerValue!.area_id = splitIds;
+ }
+ if (floorIds) {
+ const splitIds = floorIds.split(",");
+ this._targetPickerValue!.floor_id = splitIds;
+ }
+ if (labelsIds) {
+ const splitIds = labelsIds.split(",");
+ this._targetPickerValue!.label_id = splitIds;
}
- const startDateStr = searchParams.get("start_date");
- const endDateStr = searchParams.get("end_date");
+ const startDateStr = searchParams.start_date;
+ const endDateStr = searchParams.end_date;
if (startDateStr || endDateStr) {
const startDate = startDateStr
@@ -195,27 +236,48 @@ export class HaPanelLogbook extends LitElement {
endDate.setDate(endDate.getDate() + 1);
endDate.setMilliseconds(endDate.getMilliseconds() - 1);
}
- this._updatePath({
- start_date: startDate.toISOString(),
- end_date: endDate.toISOString(),
- });
+ this._time = {
+ range: [startDate, endDate],
+ };
+ this._updatePath();
}
- private _entityPicked(ev) {
- this._updatePath({
- entity_id: ev.target.value || undefined,
- });
+ private _targetsChanged(ev) {
+ this._targetPickerValue = ev.detail.value || {};
+ this._updatePath();
}
- private _updatePath(update: Record) {
- const params = extractSearchParamsObject();
- for (const [key, value] of Object.entries(update)) {
- if (value === undefined) {
- delete params[key];
- } else {
- params[key] = value;
- }
+ private _updatePath() {
+ const params: Record = {};
+
+ if (this._targetPickerValue.entity_id) {
+ params.entity_id = ensureArray(this._targetPickerValue.entity_id).join(
+ ","
+ );
}
+ if (this._targetPickerValue.label_id) {
+ params.label_id = ensureArray(this._targetPickerValue.label_id).join(",");
+ }
+ if (this._targetPickerValue.floor_id) {
+ params.floor_id = ensureArray(this._targetPickerValue.floor_id).join(",");
+ }
+ if (this._targetPickerValue.area_id) {
+ params.area_id = ensureArray(this._targetPickerValue.area_id).join(",");
+ }
+ if (this._targetPickerValue.device_id) {
+ params.device_id = ensureArray(this._targetPickerValue.device_id).join(
+ ","
+ );
+ }
+
+ if (this._time.range[0]) {
+ params.start_date = this._time.range[0].toISOString();
+ }
+
+ if (this._time.range[1]) {
+ params.end_date = this._time.range[1].toISOString();
+ }
+
navigate(`/logbook?${createSearchParam(params)}`, { replace: true });
}