mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-14 04:46:34 +00:00
Introduce a target picker for the logbook card (#23007)
* target picker logbookcard wip * migration * fixes * change property * Update src/panels/lovelace/cards/hui-logbook-card.ts * prettier
This commit is contained in:
parent
95559cbc2a
commit
e0494ccb57
@ -40,7 +40,7 @@ export const baseActionStruct = object({
|
|||||||
enabled: optional(boolean()),
|
enabled: optional(boolean()),
|
||||||
});
|
});
|
||||||
|
|
||||||
const targetStruct = object({
|
export const targetStruct = object({
|
||||||
entity_id: optional(union([string(), array(string())])),
|
entity_id: optional(union([string(), array(string())])),
|
||||||
device_id: optional(union([string(), array(string())])),
|
device_id: optional(union([string(), array(string())])),
|
||||||
area_id: optional(union([string(), array(string())])),
|
area_id: optional(union([string(), array(string())])),
|
||||||
|
@ -2,6 +2,8 @@ import type { CSSResultGroup, PropertyValues } 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, state } from "lit/decorators";
|
||||||
import { classMap } from "lit/directives/class-map";
|
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 { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
@ -14,6 +16,8 @@ import "../components/hui-warning";
|
|||||||
import type { EntityConfig } from "../entity-rows/types";
|
import type { EntityConfig } from "../entity-rows/types";
|
||||||
import type { LovelaceCard, LovelaceCardEditor } from "../types";
|
import type { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import type { LogbookCardConfig } 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;
|
export const DEFAULT_HOURS_TO_SHOW = 24;
|
||||||
|
|
||||||
@ -40,7 +44,9 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entities: foundEntities,
|
target: {
|
||||||
|
entity_id: foundEntities,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,15 +56,53 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
@state() private _time?: HaLogbook["time"];
|
@state() private _time?: HaLogbook["time"];
|
||||||
|
|
||||||
@state() private _entityId?: string[];
|
@state() private _targetPickerValue: HassServiceTarget = {};
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
return 9 + (this._config?.title ? 1 : 0);
|
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 {
|
public setConfig(config: LogbookCardConfig): void {
|
||||||
if (!config.entities.length) {
|
const target = this.validateTarget(config);
|
||||||
throw new Error("Entities must be specified");
|
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 = {
|
this._config = {
|
||||||
@ -68,11 +112,33 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard {
|
|||||||
this._time = {
|
this._time = {
|
||||||
recent: this._config!.hours_to_show! * 60 * 60,
|
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) {
|
protected updated(changedProperties: PropertyValues) {
|
||||||
super.updated(changedProperties);
|
super.updated(changedProperties);
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
@ -116,7 +182,7 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard {
|
|||||||
<ha-logbook
|
<ha-logbook
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.time=${this._time}
|
.time=${this._time}
|
||||||
.entityIds=${this._entityId}
|
.entityIds=${this._getEntityIds()}
|
||||||
narrow
|
narrow
|
||||||
relative-time
|
relative-time
|
||||||
virtualize
|
virtualize
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { HassServiceTarget } from "home-assistant-js-websocket";
|
||||||
import type { HaDurationData } from "../../../components/ha-duration-input";
|
import type { HaDurationData } from "../../../components/ha-duration-input";
|
||||||
import type { ActionConfig } from "../../../data/lovelace/config/action";
|
import type { ActionConfig } from "../../../data/lovelace/config/action";
|
||||||
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||||
@ -296,7 +297,11 @@ export interface LightCardConfig extends LovelaceCardConfig {
|
|||||||
|
|
||||||
export interface LogbookCardConfig extends LovelaceCardConfig {
|
export interface LogbookCardConfig extends LovelaceCardConfig {
|
||||||
type: "logbook";
|
type: "logbook";
|
||||||
entities: string[];
|
/**
|
||||||
|
* @deprecated Use target instead
|
||||||
|
*/
|
||||||
|
entities?: string[];
|
||||||
|
target: HassServiceTarget;
|
||||||
title?: string;
|
title?: string;
|
||||||
hours_to_show?: number;
|
hours_to_show?: number;
|
||||||
theme?: string;
|
theme?: string;
|
||||||
|
@ -9,8 +9,10 @@ import {
|
|||||||
optional,
|
optional,
|
||||||
string,
|
string,
|
||||||
} from "superstruct";
|
} from "superstruct";
|
||||||
|
import type { HassServiceTarget } from "home-assistant-js-websocket";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import "../../../../components/entity/ha-entities-picker";
|
import "../../../../components/entity/ha-entities-picker";
|
||||||
|
import "../../../../components/ha-target-picker";
|
||||||
import "../../../../components/ha-form/ha-form";
|
import "../../../../components/ha-form/ha-form";
|
||||||
import type { SchemaUnion } from "../../../../components/ha-form/types";
|
import type { SchemaUnion } from "../../../../components/ha-form/types";
|
||||||
import { filterLogbookCompatibleEntities } from "../../../../data/logbook";
|
import { filterLogbookCompatibleEntities } from "../../../../data/logbook";
|
||||||
@ -19,6 +21,7 @@ import type { LogbookCardConfig } from "../../cards/types";
|
|||||||
import type { LovelaceCardEditor } from "../../types";
|
import type { LovelaceCardEditor } from "../../types";
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
import { DEFAULT_HOURS_TO_SHOW } from "../../cards/hui-logbook-card";
|
import { DEFAULT_HOURS_TO_SHOW } from "../../cards/hui-logbook-card";
|
||||||
|
import { targetStruct } from "../../../../data/script";
|
||||||
|
|
||||||
const cardConfigStruct = assign(
|
const cardConfigStruct = assign(
|
||||||
baseLovelaceCardConfig,
|
baseLovelaceCardConfig,
|
||||||
@ -27,6 +30,7 @@ const cardConfigStruct = assign(
|
|||||||
title: optional(string()),
|
title: optional(string()),
|
||||||
hours_to_show: optional(number()),
|
hours_to_show: optional(number()),
|
||||||
theme: optional(string()),
|
theme: optional(string()),
|
||||||
|
target: optional(targetStruct),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -60,8 +64,20 @@ export class HuiLogbookCardEditor
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
get _entities(): string[] {
|
get _targetPicker(): HassServiceTarget {
|
||||||
return this._config!.entities || [];
|
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() {
|
protected render() {
|
||||||
@ -77,25 +93,19 @@ export class HuiLogbookCardEditor
|
|||||||
.computeLabel=${this._computeLabelCallback}
|
.computeLabel=${this._computeLabelCallback}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
></ha-form>
|
></ha-form>
|
||||||
<h3>
|
|
||||||
${`${this.hass!.localize(
|
<ha-target-picker
|
||||||
"ui.panel.lovelace.editor.card.generic.entities"
|
|
||||||
)} (${this.hass!.localize(
|
|
||||||
"ui.panel.lovelace.editor.card.config.required"
|
|
||||||
)})`}
|
|
||||||
</h3>
|
|
||||||
<ha-entities-picker
|
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._entities}
|
|
||||||
.entityFilter=${filterLogbookCompatibleEntities}
|
.entityFilter=${filterLogbookCompatibleEntities}
|
||||||
|
.value=${this._targetPicker}
|
||||||
|
add-on-top
|
||||||
@value-changed=${this._entitiesChanged}
|
@value-changed=${this._entitiesChanged}
|
||||||
>
|
></ha-target-picker>
|
||||||
</ha-entities-picker>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _entitiesChanged(ev: CustomEvent): void {
|
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 });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user