From 247ba9cfe89c5854f88bb71a0c6aaf626bea6002 Mon Sep 17 00:00:00 2001 From: karwosts Date: Tue, 28 Oct 2025 17:25:07 +0000 Subject: [PATCH 1/2] Add a state filter to logbook card --- src/panels/logbook/ha-logbook.ts | 16 ++++++- src/panels/lovelace/cards/hui-logbook-card.ts | 5 +++ .../hui-logbook-card-editor.ts | 45 ++++++++++++++++++- src/translations/en.json | 3 +- 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/panels/logbook/ha-logbook.ts b/src/panels/logbook/ha-logbook.ts index 230e8fd90546..51c2e4659ad4 100644 --- a/src/panels/logbook/ha-logbook.ts +++ b/src/panels/logbook/ha-logbook.ts @@ -52,6 +52,8 @@ export class HaLogbook extends LitElement { @property({ attribute: false }) public deviceIds?: string[]; + @property({ attribute: false }) public stateFilter?: string[]; + @property({ type: Boolean }) public narrow = false; @property({ type: Boolean, reflect: true }) public virtualize = false; @@ -165,7 +167,7 @@ export class HaLogbook extends LitElement { protected willUpdate(changedProps: PropertyValues): void { let changed = changedProps.has("time"); - for (const key of ["entityIds", "deviceIds"]) { + for (const key of ["entityIds", "deviceIds", "stateFilter"]) { if (!changedProps.has(key)) { continue; } @@ -352,9 +354,19 @@ export class HaLogbook extends LitElement { "recent" in this.time ? findStartOfRecentTime(new Date(), this.time.recent) : undefined; + + let eventsFiltered: LogbookEntry[] | undefined; + if (this.stateFilter && this.stateFilter.length > 0) { + eventsFiltered = streamMessage.events.filter( + (e) => e.state && this.stateFilter?.includes(e.state) + ); + } else { + eventsFiltered = [...streamMessage.events]; + } + // Put newest ones on top. Reverse works in-place so // make a copy first. - const newEntries = [...streamMessage.events].reverse(); + const newEntries = eventsFiltered.reverse(); if (!this._logbookEntries || !this._logbookEntries.length) { this._logbookEntries = newEntries; return; diff --git a/src/panels/lovelace/cards/hui-logbook-card.ts b/src/panels/lovelace/cards/hui-logbook-card.ts index 51a6179edf71..eae2b5baefad 100644 --- a/src/panels/lovelace/cards/hui-logbook-card.ts +++ b/src/panels/lovelace/cards/hui-logbook-card.ts @@ -64,6 +64,8 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard { @state() private _targetPickerValue: HassServiceTarget = {}; + @state() private _stateFilter?: string[]; + public getCardSize(): number { return 9 + (this._config?.title ? 1 : 0); } @@ -129,6 +131,8 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard { }; this._targetPickerValue = target; + + this._stateFilter = ensureArray(config.state_filter); } private _getEntityIds(): string[] | undefined { @@ -209,6 +213,7 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard { .hass=${this.hass} .time=${this._time} .entityIds=${this._getEntityIds()} + .stateFilter=${this._stateFilter} narrow relative-time virtualize diff --git a/src/panels/lovelace/editor/config-elements/hui-logbook-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-logbook-card-editor.ts index 0dcae4b1dd93..2f12200b2089 100644 --- a/src/panels/lovelace/editor/config-elements/hui-logbook-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-logbook-card-editor.ts @@ -10,6 +10,7 @@ import { string, } from "superstruct"; import type { HassServiceTarget } from "home-assistant-js-websocket"; +import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/entity/ha-entities-picker"; import "../../../../components/ha-target-picker"; @@ -24,6 +25,7 @@ import { DEFAULT_HOURS_TO_SHOW } from "../../cards/hui-logbook-card"; import { targetStruct } from "../../../../data/script"; import { getSensorNumericDeviceClasses } from "../../../../data/sensor"; import type { HaEntityPickerEntityFilterFunc } from "../../../../data/entity"; +import { resolveEntityIDs } from "../../../../data/selector"; const cardConfigStruct = assign( baseLovelaceCardConfig, @@ -33,6 +35,7 @@ const cardConfigStruct = assign( hours_to_show: optional(number()), theme: optional(string()), target: optional(targetStruct), + state_filter: optional(array(string())), }) ); @@ -50,6 +53,13 @@ const SCHEMA = [ }, ], }, + { + name: "state_filter", + context: { + filter_entity: "context_entities", + }, + selector: { state: { multiple: true } }, + }, ] as const; @customElement("hui-logbook-card-editor") @@ -106,7 +116,13 @@ export class HuiLogbookCardEditor return html` ({ + ...config, + context_entities: resolveEntityIDs( + this.hass!, + target, + entities, + devices, + areas + ), + }) + ); + private _filterFunc: HaEntityPickerEntityFilterFunc = (entity) => filterLogbookCompatibleEntities(entity, this._sensorNumericDeviceClasses); @@ -131,7 +166,9 @@ export class HuiLogbookCardEditor } private _valueChanged(ev: CustomEvent): void { - fireEvent(this, "config-changed", { config: ev.detail.value }); + const newConfig = { ...ev.detail.value }; + delete newConfig.context_entities; + fireEvent(this, "config-changed", { config: newConfig }); } private _computeLabelCallback = (schema: SchemaUnion) => { @@ -142,6 +179,10 @@ export class HuiLogbookCardEditor )} (${this.hass!.localize( "ui.panel.lovelace.editor.card.config.optional" )})`; + case "state_filter": + return this.hass!.localize( + "ui.panel.lovelace.editor.card.logbook.state_filter" + ); default: return this.hass!.localize( `ui.panel.lovelace.editor.card.generic.${schema.name}` diff --git a/src/translations/en.json b/src/translations/en.json index f3de6f19bede..406473541d5f 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -7651,7 +7651,8 @@ }, "logbook": { "name": "Activity", - "description": "The Activity card shows a list of events for entities." + "description": "The Activity card shows a list of events for entities.", + "state_filter": "State filter" }, "history-graph": { "name": "History graph", From a8570e7d06f44ba49d8b627099edca8b17d49ad6 Mon Sep 17 00:00:00 2001 From: karwosts Date: Wed, 29 Oct 2025 13:04:24 +0000 Subject: [PATCH 2/2] types --- src/panels/lovelace/cards/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts index b90bffb75a8b..81bcbf078281 100644 --- a/src/panels/lovelace/cards/types.ts +++ b/src/panels/lovelace/cards/types.ts @@ -345,6 +345,7 @@ export interface LogbookCardConfig extends LovelaceCardConfig { title?: string; hours_to_show?: number; theme?: string; + state_filter?: string[]; } interface GeoLocationSourceConfig {