Skip to content

Commit

Permalink
Introduce a target picker for the logbook card (#23007)
Browse files Browse the repository at this point in the history
* target picker logbookcard wip

* migration

* fixes

* change property

* Update src/panels/lovelace/cards/hui-logbook-card.ts

* prettier
  • Loading branch information
silamon authored Dec 19, 2024
1 parent 95559cb commit e0494cc
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/data/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const baseActionStruct = object({
enabled: optional(boolean()),
});

const targetStruct = object({
export const targetStruct = object({
entity_id: optional(union([string(), array(string())])),
device_id: optional(union([string(), array(string())])),
area_id: optional(union([string(), array(string())])),
Expand Down
80 changes: 73 additions & 7 deletions src/panels/lovelace/cards/hui-logbook-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { CSSResultGroup, PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
import type { HassServiceTarget } from "home-assistant-js-websocket";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import "../../../components/ha-card";
Expand All @@ -14,6 +16,8 @@ import "../components/hui-warning";
import type { EntityConfig } from "../entity-rows/types";
import type { LovelaceCard, LovelaceCardEditor } from "../types";
import type { LogbookCardConfig } from "./types";
import { resolveEntityIDs } from "../../../data/selector";
import { ensureArray } from "../../../common/array/ensure-array";

export const DEFAULT_HOURS_TO_SHOW = 24;

Expand All @@ -40,7 +44,9 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard {
);

return {
entities: foundEntities,
target: {
entity_id: foundEntities,
},
};
}

Expand All @@ -50,15 +56,53 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard {

@state() private _time?: HaLogbook["time"];

@state() private _entityId?: string[];
@state() private _targetPickerValue: HassServiceTarget = {};

public getCardSize(): number {
return 9 + (this._config?.title ? 1 : 0);
}

public validateTarget(
config: LogbookCardConfig
): HassServiceTarget | undefined {
if (
(config.entities && !config.entities.length) ||
(config.target &&
!config.target.area_id?.length &&
!config.target.device_id?.length &&
!config.target.entity_id?.length &&
!config.target.floor_id?.length &&
!config.target.label_id?.length)
) {
return undefined;
}

if (config.entities) {
return {
entity_id: processConfigEntities<EntityConfig>(config.entities).map(
(entity) => entity.entity
),
};
}

if (config.target?.entity_id) {
return {
...config.target,
entity_id: processConfigEntities<EntityConfig>(
ensureArray(config.target!.entity_id)
).map((entity) => entity.entity),
};
}

return config.target;
}

public setConfig(config: LogbookCardConfig): void {
if (!config.entities.length) {
throw new Error("Entities must be specified");
const target = this.validateTarget(config);
if (!target) {
throw new Error(
"The provided target in the logbook card has no entities. Targets can include entities, devices, labels, or areas, with devices, areas, and labels resolving to entities."
);
}

this._config = {
Expand All @@ -68,11 +112,33 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard {
this._time = {
recent: this._config!.hours_to_show! * 60 * 60,
};
this._entityId = processConfigEntities<EntityConfig>(config.entities).map(
(entity) => entity.entity

this._targetPickerValue = target;
}

private _getEntityIds(): string[] | undefined {
const entities = this._getMemoizedEntityIds(
this._targetPickerValue,
this.hass.entities,
this.hass.devices,
this.hass.areas
);
if (entities.length === 0) {
return undefined;
}
return entities;
}

private _getMemoizedEntityIds = memoizeOne(
(
targetPickerValue: HassServiceTarget,
entities: HomeAssistant["entities"],
devices: HomeAssistant["devices"],
areas: HomeAssistant["areas"]
): string[] =>
resolveEntityIDs(this.hass, targetPickerValue, entities, devices, areas)
);

protected updated(changedProperties: PropertyValues) {
super.updated(changedProperties);
if (!this._config || !this.hass) {
Expand Down Expand Up @@ -116,7 +182,7 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard {
<ha-logbook
.hass=${this.hass}
.time=${this._time}
.entityIds=${this._entityId}
.entityIds=${this._getEntityIds()}
narrow
relative-time
virtualize
Expand Down
7 changes: 6 additions & 1 deletion src/panels/lovelace/cards/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { HassServiceTarget } from "home-assistant-js-websocket";
import type { HaDurationData } from "../../../components/ha-duration-input";
import type { ActionConfig } from "../../../data/lovelace/config/action";
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
Expand Down Expand Up @@ -296,7 +297,11 @@ export interface LightCardConfig extends LovelaceCardConfig {

export interface LogbookCardConfig extends LovelaceCardConfig {
type: "logbook";
entities: string[];
/**
* @deprecated Use target instead
*/
entities?: string[];
target: HassServiceTarget;
title?: string;
hours_to_show?: number;
theme?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import {
optional,
string,
} from "superstruct";
import type { HassServiceTarget } from "home-assistant-js-websocket";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/entity/ha-entities-picker";
import "../../../../components/ha-target-picker";
import "../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../components/ha-form/types";
import { filterLogbookCompatibleEntities } from "../../../../data/logbook";
Expand All @@ -19,6 +21,7 @@ import type { LogbookCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { DEFAULT_HOURS_TO_SHOW } from "../../cards/hui-logbook-card";
import { targetStruct } from "../../../../data/script";

const cardConfigStruct = assign(
baseLovelaceCardConfig,
Expand All @@ -27,6 +30,7 @@ const cardConfigStruct = assign(
title: optional(string()),
hours_to_show: optional(number()),
theme: optional(string()),
target: optional(targetStruct),
})
);

Expand Down Expand Up @@ -60,8 +64,20 @@ export class HuiLogbookCardEditor
this._config = config;
}

get _entities(): string[] {
return this._config!.entities || [];
get _targetPicker(): HassServiceTarget {
const entities = this._config!.entities || [];
if (this._config!.entities) {
this._config = {
...this._config!,
entities: undefined,
target: { entity_id: entities },
};
}
return (
this._config!.target || {
entity_id: entities,
}
);
}

protected render() {
Expand All @@ -77,25 +93,19 @@ export class HuiLogbookCardEditor
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>
<h3>
${`${this.hass!.localize(
"ui.panel.lovelace.editor.card.generic.entities"
)} (${this.hass!.localize(
"ui.panel.lovelace.editor.card.config.required"
)})`}
</h3>
<ha-entities-picker
<ha-target-picker
.hass=${this.hass}
.value=${this._entities}
.entityFilter=${filterLogbookCompatibleEntities}
.value=${this._targetPicker}
add-on-top
@value-changed=${this._entitiesChanged}
>
</ha-entities-picker>
></ha-target-picker>
`;
}

private _entitiesChanged(ev: CustomEvent): void {
this._config = { ...this._config!, entities: ev.detail.value };
this._config = { ...this._config!, target: ev.detail.value };
fireEvent(this, "config-changed", { config: this._config });
}

Expand Down

0 comments on commit e0494cc

Please sign in to comment.