mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-26 18:56:39 +00:00
Add floor and label support to describe action (#20403)
This commit is contained in:
parent
2d4a8e2e45
commit
08b25f9c2a
@ -136,7 +136,7 @@ export class DemoAutomationDescribeAction extends LitElement {
|
|||||||
<div class="action">
|
<div class="action">
|
||||||
<span>
|
<span>
|
||||||
${this._action
|
${this._action
|
||||||
? describeAction(this.hass, [], this._action)
|
? describeAction(this.hass, [], [], [], this._action)
|
||||||
: "<invalid YAML>"}
|
: "<invalid YAML>"}
|
||||||
</span>
|
</span>
|
||||||
<ha-yaml-editor
|
<ha-yaml-editor
|
||||||
@ -149,7 +149,7 @@ export class DemoAutomationDescribeAction extends LitElement {
|
|||||||
${ACTIONS.map(
|
${ACTIONS.map(
|
||||||
(conf) => html`
|
(conf) => html`
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<span>${describeAction(this.hass, [], conf as any)}</span>
|
<span>${describeAction(this.hass, [], [], [], conf as any)}</span>
|
||||||
<pre>${dump(conf)}</pre>
|
<pre>${dump(conf)}</pre>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { consume } from "@lit-labs/context";
|
||||||
import {
|
import {
|
||||||
mdiAlertCircle,
|
mdiAlertCircle,
|
||||||
mdiCircle,
|
mdiCircle,
|
||||||
@ -6,14 +7,13 @@ import {
|
|||||||
mdiProgressWrench,
|
mdiProgressWrench,
|
||||||
mdiRecordCircleOutline,
|
mdiRecordCircleOutline,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
|
||||||
import {
|
import {
|
||||||
css,
|
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
html,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
css,
|
||||||
|
html,
|
||||||
nothing,
|
nothing,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
@ -23,27 +23,31 @@ import { relativeTime } from "../../common/datetime/relative_time";
|
|||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import { toggleAttribute } from "../../common/dom/toggle_attribute";
|
import { toggleAttribute } from "../../common/dom/toggle_attribute";
|
||||||
import {
|
import {
|
||||||
EntityRegistryEntry,
|
floorsContext,
|
||||||
subscribeEntityRegistry,
|
fullEntitiesContext,
|
||||||
} from "../../data/entity_registry";
|
labelsContext,
|
||||||
|
} from "../../data/context";
|
||||||
|
import { EntityRegistryEntry } from "../../data/entity_registry";
|
||||||
|
import { FloorRegistryEntry } from "../../data/floor_registry";
|
||||||
|
import { LabelRegistryEntry } from "../../data/label_registry";
|
||||||
import { LogbookEntry } from "../../data/logbook";
|
import { LogbookEntry } from "../../data/logbook";
|
||||||
import {
|
import {
|
||||||
ChooseAction,
|
ChooseAction,
|
||||||
ChooseActionChoice,
|
ChooseActionChoice,
|
||||||
getActionType,
|
|
||||||
IfAction,
|
IfAction,
|
||||||
ParallelAction,
|
ParallelAction,
|
||||||
RepeatAction,
|
RepeatAction,
|
||||||
|
getActionType,
|
||||||
} from "../../data/script";
|
} from "../../data/script";
|
||||||
import { describeAction } from "../../data/script_i18n";
|
import { describeAction } from "../../data/script_i18n";
|
||||||
import {
|
import {
|
||||||
ActionTraceStep,
|
ActionTraceStep,
|
||||||
AutomationTraceExtended,
|
AutomationTraceExtended,
|
||||||
ChooseActionTraceStep,
|
ChooseActionTraceStep,
|
||||||
getDataFromPath,
|
|
||||||
IfActionTraceStep,
|
IfActionTraceStep,
|
||||||
isTriggerPath,
|
|
||||||
TriggerTraceStep,
|
TriggerTraceStep,
|
||||||
|
getDataFromPath,
|
||||||
|
isTriggerPath,
|
||||||
} from "../../data/trace";
|
} from "../../data/trace";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import "./ha-timeline";
|
import "./ha-timeline";
|
||||||
@ -200,6 +204,8 @@ class ActionRenderer {
|
|||||||
constructor(
|
constructor(
|
||||||
private hass: HomeAssistant,
|
private hass: HomeAssistant,
|
||||||
private entityReg: EntityRegistryEntry[],
|
private entityReg: EntityRegistryEntry[],
|
||||||
|
private labelReg: LabelRegistryEntry[],
|
||||||
|
private floorReg: FloorRegistryEntry[],
|
||||||
private entries: TemplateResult[],
|
private entries: TemplateResult[],
|
||||||
private trace: AutomationTraceExtended,
|
private trace: AutomationTraceExtended,
|
||||||
private logbookRenderer: LogbookRenderer,
|
private logbookRenderer: LogbookRenderer,
|
||||||
@ -310,7 +316,14 @@ class ActionRenderer {
|
|||||||
|
|
||||||
this._renderEntry(
|
this._renderEntry(
|
||||||
path,
|
path,
|
||||||
describeAction(this.hass, this.entityReg, data, actionType),
|
describeAction(
|
||||||
|
this.hass,
|
||||||
|
this.entityReg,
|
||||||
|
this.labelReg,
|
||||||
|
this.floorReg,
|
||||||
|
data,
|
||||||
|
actionType
|
||||||
|
),
|
||||||
undefined,
|
undefined,
|
||||||
data.enabled === false
|
data.enabled === false
|
||||||
);
|
);
|
||||||
@ -475,7 +488,13 @@ class ActionRenderer {
|
|||||||
|
|
||||||
const name =
|
const name =
|
||||||
repeatConfig.alias ||
|
repeatConfig.alias ||
|
||||||
describeAction(this.hass, this.entityReg, repeatConfig);
|
describeAction(
|
||||||
|
this.hass,
|
||||||
|
this.entityReg,
|
||||||
|
this.labelReg,
|
||||||
|
this.floorReg,
|
||||||
|
repeatConfig
|
||||||
|
);
|
||||||
|
|
||||||
this._renderEntry(repeatPath, name, undefined, disabled);
|
this._renderEntry(repeatPath, name, undefined, disabled);
|
||||||
|
|
||||||
@ -631,15 +650,17 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean }) public allowPick = false;
|
@property({ type: Boolean }) public allowPick = false;
|
||||||
|
|
||||||
@state() private _entityReg: EntityRegistryEntry[] = [];
|
@state()
|
||||||
|
@consume({ context: fullEntitiesContext, subscribe: true })
|
||||||
|
_entityReg!: EntityRegistryEntry[];
|
||||||
|
|
||||||
public hassSubscribe(): UnsubscribeFunc[] {
|
@state()
|
||||||
return [
|
@consume({ context: labelsContext, subscribe: true })
|
||||||
subscribeEntityRegistry(this.hass.connection!, (entities) => {
|
_labelReg!: LabelRegistryEntry[];
|
||||||
this._entityReg = entities;
|
|
||||||
}),
|
@state()
|
||||||
];
|
@consume({ context: floorsContext, subscribe: true })
|
||||||
}
|
_floorReg!: FloorRegistryEntry[];
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this.trace) {
|
if (!this.trace) {
|
||||||
@ -657,6 +678,8 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
const actionRenderer = new ActionRenderer(
|
const actionRenderer = new ActionRenderer(
|
||||||
this.hass,
|
this.hass,
|
||||||
this._entityReg,
|
this._entityReg,
|
||||||
|
this._labelReg,
|
||||||
|
this._floorReg,
|
||||||
entries,
|
entries,
|
||||||
this.trace,
|
this.trace,
|
||||||
logbookRenderer,
|
logbookRenderer,
|
||||||
|
@ -2,6 +2,8 @@ import { createContext } from "@lit-labs/context";
|
|||||||
import { HassConfig } from "home-assistant-js-websocket";
|
import { HassConfig } from "home-assistant-js-websocket";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import { EntityRegistryEntry } from "./entity_registry";
|
import { EntityRegistryEntry } from "./entity_registry";
|
||||||
|
import { FloorRegistryEntry } from "./floor_registry";
|
||||||
|
import { LabelRegistryEntry } from "./label_registry";
|
||||||
|
|
||||||
export const connectionContext =
|
export const connectionContext =
|
||||||
createContext<HomeAssistant["connection"]>("connection");
|
createContext<HomeAssistant["connection"]>("connection");
|
||||||
@ -25,3 +27,7 @@ export const panelsContext = createContext<HomeAssistant["panels"]>("panels");
|
|||||||
|
|
||||||
export const fullEntitiesContext =
|
export const fullEntitiesContext =
|
||||||
createContext<EntityRegistryEntry[]>("extendedEntities");
|
createContext<EntityRegistryEntry[]>("extendedEntities");
|
||||||
|
|
||||||
|
export const floorsContext = createContext<FloorRegistryEntry[]>("floors");
|
||||||
|
|
||||||
|
export const labelsContext = createContext<LabelRegistryEntry[]>("labels");
|
||||||
|
@ -14,7 +14,9 @@ import {
|
|||||||
computeEntityRegistryName,
|
computeEntityRegistryName,
|
||||||
entityRegistryById,
|
entityRegistryById,
|
||||||
} from "./entity_registry";
|
} from "./entity_registry";
|
||||||
|
import { FloorRegistryEntry } from "./floor_registry";
|
||||||
import { domainToName } from "./integration";
|
import { domainToName } from "./integration";
|
||||||
|
import { LabelRegistryEntry } from "./label_registry";
|
||||||
import {
|
import {
|
||||||
ActionType,
|
ActionType,
|
||||||
ActionTypes,
|
ActionTypes,
|
||||||
@ -40,6 +42,8 @@ const actionTranslationBaseKey =
|
|||||||
export const describeAction = <T extends ActionType>(
|
export const describeAction = <T extends ActionType>(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entityRegistry: EntityRegistryEntry[],
|
entityRegistry: EntityRegistryEntry[],
|
||||||
|
labelRegistry: LabelRegistryEntry[],
|
||||||
|
floorRegistry: FloorRegistryEntry[],
|
||||||
action: ActionTypes[T],
|
action: ActionTypes[T],
|
||||||
actionType?: T,
|
actionType?: T,
|
||||||
ignoreAlias = false
|
ignoreAlias = false
|
||||||
@ -48,6 +52,8 @@ export const describeAction = <T extends ActionType>(
|
|||||||
return tryDescribeAction(
|
return tryDescribeAction(
|
||||||
hass,
|
hass,
|
||||||
entityRegistry,
|
entityRegistry,
|
||||||
|
labelRegistry,
|
||||||
|
floorRegistry,
|
||||||
action,
|
action,
|
||||||
actionType,
|
actionType,
|
||||||
ignoreAlias
|
ignoreAlias
|
||||||
@ -66,6 +72,8 @@ export const describeAction = <T extends ActionType>(
|
|||||||
const tryDescribeAction = <T extends ActionType>(
|
const tryDescribeAction = <T extends ActionType>(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entityRegistry: EntityRegistryEntry[],
|
entityRegistry: EntityRegistryEntry[],
|
||||||
|
labelRegistry: LabelRegistryEntry[],
|
||||||
|
floorRegistry: FloorRegistryEntry[],
|
||||||
action: ActionTypes[T],
|
action: ActionTypes[T],
|
||||||
actionType?: T,
|
actionType?: T,
|
||||||
ignoreAlias = false
|
ignoreAlias = false
|
||||||
@ -82,10 +90,12 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
|
|
||||||
const targets: string[] = [];
|
const targets: string[] = [];
|
||||||
if (config.target) {
|
if (config.target) {
|
||||||
for (const [key, label] of Object.entries({
|
for (const [key, name] of Object.entries({
|
||||||
area_id: "areas",
|
area_id: "areas",
|
||||||
device_id: "devices",
|
device_id: "devices",
|
||||||
entity_id: "entities",
|
entity_id: "entities",
|
||||||
|
floor_id: "floors",
|
||||||
|
label_id: "labels",
|
||||||
})) {
|
})) {
|
||||||
if (!(key in config.target)) {
|
if (!(key in config.target)) {
|
||||||
continue;
|
continue;
|
||||||
@ -99,7 +109,7 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
targets.push(
|
targets.push(
|
||||||
hass.localize(
|
hass.localize(
|
||||||
`${actionTranslationBaseKey}.service.description.target_template`,
|
`${actionTranslationBaseKey}.service.description.target_template`,
|
||||||
{ name: label }
|
{ name }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -147,6 +157,32 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (key === "floor_id") {
|
||||||
|
const floor = floorRegistry.find(
|
||||||
|
(flr) => flr.floor_id === targetThing
|
||||||
|
);
|
||||||
|
if (floor?.name) {
|
||||||
|
targets.push(floor.name);
|
||||||
|
} else {
|
||||||
|
targets.push(
|
||||||
|
hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.service.description.target_unknown_floor`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (key === "label_id") {
|
||||||
|
const label = labelRegistry.find(
|
||||||
|
(lbl) => lbl.label_id === targetThing
|
||||||
|
);
|
||||||
|
if (label?.name) {
|
||||||
|
targets.push(label.name);
|
||||||
|
} else {
|
||||||
|
targets.push(
|
||||||
|
hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.service.description.target_unknown_label`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
targets.push(targetThing);
|
targets.push(targetThing);
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,14 @@ import type { HaYamlEditor } from "../../../../components/ha-yaml-editor";
|
|||||||
import { ACTION_ICONS, YAML_ONLY_ACTION_TYPES } from "../../../../data/action";
|
import { ACTION_ICONS, YAML_ONLY_ACTION_TYPES } from "../../../../data/action";
|
||||||
import { AutomationClipboard } from "../../../../data/automation";
|
import { AutomationClipboard } from "../../../../data/automation";
|
||||||
import { validateConfig } from "../../../../data/config";
|
import { validateConfig } from "../../../../data/config";
|
||||||
import { fullEntitiesContext } from "../../../../data/context";
|
import {
|
||||||
|
floorsContext,
|
||||||
|
fullEntitiesContext,
|
||||||
|
labelsContext,
|
||||||
|
} from "../../../../data/context";
|
||||||
import { EntityRegistryEntry } from "../../../../data/entity_registry";
|
import { EntityRegistryEntry } from "../../../../data/entity_registry";
|
||||||
|
import { FloorRegistryEntry } from "../../../../data/floor_registry";
|
||||||
|
import { LabelRegistryEntry } from "../../../../data/label_registry";
|
||||||
import {
|
import {
|
||||||
Action,
|
Action,
|
||||||
NonConditionAction,
|
NonConditionAction,
|
||||||
@ -146,6 +152,14 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
@consume({ context: fullEntitiesContext, subscribe: true })
|
@consume({ context: fullEntitiesContext, subscribe: true })
|
||||||
_entityReg!: EntityRegistryEntry[];
|
_entityReg!: EntityRegistryEntry[];
|
||||||
|
|
||||||
|
@state()
|
||||||
|
@consume({ context: labelsContext, subscribe: true })
|
||||||
|
_labelReg!: LabelRegistryEntry[];
|
||||||
|
|
||||||
|
@state()
|
||||||
|
@consume({ context: floorsContext, subscribe: true })
|
||||||
|
_floorReg!: FloorRegistryEntry[];
|
||||||
|
|
||||||
@state() private _warnings?: string[];
|
@state() private _warnings?: string[];
|
||||||
|
|
||||||
@state() private _uiModeAvailable = true;
|
@state() private _uiModeAvailable = true;
|
||||||
@ -210,7 +224,13 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
.path=${ACTION_ICONS[type!]}
|
.path=${ACTION_ICONS[type!]}
|
||||||
></ha-svg-icon>`}
|
></ha-svg-icon>`}
|
||||||
${capitalizeFirstLetter(
|
${capitalizeFirstLetter(
|
||||||
describeAction(this.hass, this._entityReg, this.action)
|
describeAction(
|
||||||
|
this.hass,
|
||||||
|
this._entityReg,
|
||||||
|
this._labelReg,
|
||||||
|
this._floorReg,
|
||||||
|
this.action
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
@ -573,7 +593,15 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
),
|
),
|
||||||
inputType: "string",
|
inputType: "string",
|
||||||
placeholder: capitalizeFirstLetter(
|
placeholder: capitalizeFirstLetter(
|
||||||
describeAction(this.hass, this._entityReg, this.action, undefined, true)
|
describeAction(
|
||||||
|
this.hass,
|
||||||
|
this._entityReg,
|
||||||
|
this._labelReg,
|
||||||
|
this._floorReg,
|
||||||
|
this.action,
|
||||||
|
undefined,
|
||||||
|
true
|
||||||
|
)
|
||||||
),
|
),
|
||||||
defaultValue: this.action.alias,
|
defaultValue: this.action.alias,
|
||||||
confirmText: this.hass.localize("ui.common.submit"),
|
confirmText: this.hass.localize("ui.common.submit"),
|
||||||
|
@ -35,7 +35,11 @@ import { customElement, property, state } from "lit/decorators";
|
|||||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||||
import { listenMediaQuery } from "../../common/dom/media_query";
|
import { listenMediaQuery } from "../../common/dom/media_query";
|
||||||
import { CloudStatus, fetchCloudStatus } from "../../data/cloud";
|
import { CloudStatus, fetchCloudStatus } from "../../data/cloud";
|
||||||
import { fullEntitiesContext } from "../../data/context";
|
import {
|
||||||
|
floorsContext,
|
||||||
|
fullEntitiesContext,
|
||||||
|
labelsContext,
|
||||||
|
} from "../../data/context";
|
||||||
import {
|
import {
|
||||||
entityRegistryByEntityId,
|
entityRegistryByEntityId,
|
||||||
entityRegistryById,
|
entityRegistryById,
|
||||||
@ -45,6 +49,8 @@ import { HassRouterPage, RouterOptions } from "../../layouts/hass-router-page";
|
|||||||
import { PageNavigation } from "../../layouts/hass-tabs-subpage";
|
import { PageNavigation } from "../../layouts/hass-tabs-subpage";
|
||||||
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
|
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
|
||||||
import { HomeAssistant, Route } from "../../types";
|
import { HomeAssistant, Route } from "../../types";
|
||||||
|
import { subscribeLabelRegistry } from "../../data/label_registry";
|
||||||
|
import { subscribeFloorRegistry } from "../../data/floor_registry";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// for fire event
|
// for fire event
|
||||||
@ -379,11 +385,27 @@ class HaPanelConfig extends SubscribeMixin(HassRouterPage) {
|
|||||||
initialValue: [],
|
initialValue: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
private _labelsContext = new ContextProvider(this, {
|
||||||
|
context: labelsContext,
|
||||||
|
initialValue: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
private _floorsContext = new ContextProvider(this, {
|
||||||
|
context: floorsContext,
|
||||||
|
initialValue: [],
|
||||||
|
});
|
||||||
|
|
||||||
public hassSubscribe(): UnsubscribeFunc[] {
|
public hassSubscribe(): UnsubscribeFunc[] {
|
||||||
return [
|
return [
|
||||||
subscribeEntityRegistry(this.hass.connection!, (entities) => {
|
subscribeEntityRegistry(this.hass.connection!, (entities) => {
|
||||||
this._entitiesContext.setValue(entities);
|
this._entitiesContext.setValue(entities);
|
||||||
}),
|
}),
|
||||||
|
subscribeLabelRegistry(this.hass.connection!, (labels) => {
|
||||||
|
this._labelsContext.setValue(labels);
|
||||||
|
}),
|
||||||
|
subscribeFloorRegistry(this.hass.connection!, (floors) => {
|
||||||
|
this._floorsContext.setValue(floors);
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3241,7 +3241,9 @@
|
|||||||
"target_template": "templated {name}",
|
"target_template": "templated {name}",
|
||||||
"target_unknown_entity": "unknown entity",
|
"target_unknown_entity": "unknown entity",
|
||||||
"target_unknown_device": "unknown device",
|
"target_unknown_device": "unknown device",
|
||||||
"target_unknown_area": "unknown area"
|
"target_unknown_area": "unknown area",
|
||||||
|
"target_unknown_floor": "unknown floor",
|
||||||
|
"target_unknown_label": "unknown label"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"play_media": {
|
"play_media": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user