mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-28 15:27:20 +00:00
Teach logbook about additional context data (#12667)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
parent
09ee8dbeb6
commit
01a53439c4
@ -25,6 +25,7 @@ export interface LogbookEntry {
|
|||||||
context_entity_id?: string;
|
context_entity_id?: string;
|
||||||
context_entity_id_name?: string;
|
context_entity_id_name?: string;
|
||||||
context_name?: string;
|
context_name?: string;
|
||||||
|
context_message?: string;
|
||||||
state?: string;
|
state?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,9 +22,17 @@ import "../../components/ha-circular-progress";
|
|||||||
import "../../components/ha-relative-time";
|
import "../../components/ha-relative-time";
|
||||||
import { LogbookEntry } from "../../data/logbook";
|
import { LogbookEntry } from "../../data/logbook";
|
||||||
import { TraceContexts } from "../../data/trace";
|
import { TraceContexts } from "../../data/trace";
|
||||||
import { haStyle, haStyleScrollbar } from "../../resources/styles";
|
import {
|
||||||
|
haStyle,
|
||||||
|
haStyleScrollbar,
|
||||||
|
buttonLinkStyle,
|
||||||
|
} from "../../resources/styles";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
|
|
||||||
|
const EVENT_LOCALIZE_MAP = {
|
||||||
|
script_started: "from_script",
|
||||||
|
};
|
||||||
|
|
||||||
@customElement("ha-logbook")
|
@customElement("ha-logbook")
|
||||||
class HaLogbook extends LitElement {
|
class HaLogbook extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
@ -119,6 +127,7 @@ class HaLogbook extends LitElement {
|
|||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const seenEntityIds: string[] = [];
|
||||||
const previous = this.entries[index - 1];
|
const previous = this.entries[index - 1];
|
||||||
const stateObj = item.entity_id
|
const stateObj = item.entity_id
|
||||||
? this.hass.states[item.entity_id]
|
? this.hass.states[item.entity_id]
|
||||||
@ -167,42 +176,48 @@ class HaLogbook extends LitElement {
|
|||||||
: ""}
|
: ""}
|
||||||
<div class="message-relative_time">
|
<div class="message-relative_time">
|
||||||
<div class="message">
|
<div class="message">
|
||||||
${!this.noName
|
${!this.noName // Used for more-info panel (single entity case)
|
||||||
? html`<a
|
? this._renderEntity(item.entity_id, item.name)
|
||||||
href="#"
|
: ""}
|
||||||
@click=${this._entityClicked}
|
${item.message
|
||||||
.entityId=${item.entity_id}
|
? html`${this._formatMessageWithPossibleEntity(
|
||||||
><span class="name">${item.name}</span></a
|
item.message,
|
||||||
>`
|
seenEntityIds,
|
||||||
|
item.entity_id
|
||||||
|
)}`
|
||||||
|
: item.source
|
||||||
|
? html` ${this._formatMessageWithPossibleEntity(
|
||||||
|
item.source,
|
||||||
|
seenEntityIds,
|
||||||
|
undefined,
|
||||||
|
"ui.components.logbook.by"
|
||||||
|
)}`
|
||||||
: ""}
|
: ""}
|
||||||
${item.message}
|
|
||||||
${item_username
|
${item_username
|
||||||
? ` ${this.hass.localize(
|
? ` ${this.hass.localize(
|
||||||
"ui.components.logbook.by"
|
"ui.components.logbook.by_user"
|
||||||
)} ${item_username}`
|
)} ${item_username}`
|
||||||
: !item.context_event_type
|
: ``}
|
||||||
? ""
|
${item.context_event_type
|
||||||
: item.context_event_type === "call_service"
|
? this._formatEventBy(item, seenEntityIds)
|
||||||
? // Service Call
|
: ""}
|
||||||
` ${this.hass.localize("ui.components.logbook.by_service")}
|
${item.context_message
|
||||||
${item.context_domain}.${item.context_service}`
|
? html` ${this._formatMessageWithPossibleEntity(
|
||||||
: item.context_entity_id === item.entity_id
|
item.context_message,
|
||||||
? // HomeKit or something that self references
|
seenEntityIds,
|
||||||
` ${this.hass.localize("ui.components.logbook.by")}
|
item.context_entity_id,
|
||||||
${
|
"ui.components.logbook.for"
|
||||||
item.context_name
|
)}`
|
||||||
? item.context_name
|
: ""}
|
||||||
: item.context_event_type
|
${item.context_entity_id &&
|
||||||
}`
|
!seenEntityIds.includes(item.context_entity_id)
|
||||||
: // Another entity such as an automation or script
|
? // Another entity such as an automation or script
|
||||||
html` ${this.hass.localize("ui.components.logbook.by")}
|
html` ${this.hass.localize("ui.components.logbook.for")}
|
||||||
<a
|
${this._renderEntity(
|
||||||
href="#"
|
item.context_entity_id,
|
||||||
@click=${this._entityClicked}
|
item.context_entity_id_name
|
||||||
.entityId=${item.context_entity_id}
|
)}`
|
||||||
class="name"
|
: ""}
|
||||||
>${item.context_entity_id_name}</a
|
|
||||||
>`}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="secondary">
|
<div class="secondary">
|
||||||
<span
|
<span
|
||||||
@ -254,6 +269,123 @@ class HaLogbook extends LitElement {
|
|||||||
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
|
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _formatEventBy(item: LogbookEntry, seenEntities: string[]) {
|
||||||
|
if (item.context_event_type === "call_service") {
|
||||||
|
return `${this.hass.localize("ui.components.logbook.from_service")} ${
|
||||||
|
item.context_domain
|
||||||
|
}.${item.context_service}`;
|
||||||
|
}
|
||||||
|
if (item.context_event_type === "automation_triggered") {
|
||||||
|
if (seenEntities.includes(item.context_entity_id!)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
seenEntities.push(item.context_entity_id!);
|
||||||
|
return html`${this.hass.localize("ui.components.logbook.from_automation")}
|
||||||
|
${this._renderEntity(item.context_entity_id, item.context_name)}`;
|
||||||
|
}
|
||||||
|
if (item.context_name) {
|
||||||
|
return `${this.hass.localize("ui.components.logbook.from")} ${
|
||||||
|
item.context_name
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
if (item.context_event_type === "state_changed") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (item.context_event_type! in EVENT_LOCALIZE_MAP) {
|
||||||
|
return `${this.hass.localize(
|
||||||
|
`ui.components.logbook.${EVENT_LOCALIZE_MAP[item.context_event_type!]}`
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
return `${this.hass.localize(
|
||||||
|
"ui.components.logbook.from"
|
||||||
|
)} ${this.hass.localize("ui.components.logbook.event")} ${
|
||||||
|
item.context_event_type
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderEntity(
|
||||||
|
entityId: string | undefined,
|
||||||
|
entityName: string | undefined
|
||||||
|
) {
|
||||||
|
const hasState = entityId && entityId in this.hass.states;
|
||||||
|
const displayName =
|
||||||
|
entityName ||
|
||||||
|
(hasState
|
||||||
|
? this.hass.states[entityId].attributes.friendly_name || entityId
|
||||||
|
: entityId);
|
||||||
|
if (!hasState) {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
return html`<button
|
||||||
|
class="link"
|
||||||
|
@click=${this._entityClicked}
|
||||||
|
.entityId=${entityId}
|
||||||
|
>
|
||||||
|
${displayName}
|
||||||
|
</button>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _formatMessageWithPossibleEntity(
|
||||||
|
message: string,
|
||||||
|
seenEntities: string[],
|
||||||
|
possibleEntity?: string,
|
||||||
|
localizePrefix?: string
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
// As we are looking at a log(book), we are doing entity_id
|
||||||
|
// "highlighting"/"colorizing". The goal is to make it easy for
|
||||||
|
// the user to access the entity that caused the event.
|
||||||
|
//
|
||||||
|
// If there is an entity_id in the message that is also in the
|
||||||
|
// state machine, we search the message for the entity_id and
|
||||||
|
// replace it with _renderEntity
|
||||||
|
//
|
||||||
|
if (message.indexOf(".") !== -1) {
|
||||||
|
const messageParts = message.split(" ");
|
||||||
|
for (let i = 0, size = messageParts.length; i < size; i++) {
|
||||||
|
if (messageParts[i] in this.hass.states) {
|
||||||
|
const entityId = messageParts[i];
|
||||||
|
if (seenEntities.includes(entityId)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
seenEntities.push(entityId);
|
||||||
|
const messageEnd = messageParts.splice(i);
|
||||||
|
messageEnd.shift(); // remove the entity
|
||||||
|
return html` ${messageParts.join(" ")}
|
||||||
|
${this._renderEntity(
|
||||||
|
entityId,
|
||||||
|
this.hass.states[entityId].attributes.friendly_name
|
||||||
|
)}
|
||||||
|
${messageEnd.join(" ")}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// When we have a message has a specific entity_id attached to
|
||||||
|
// it, and the entity_id is not in the message, we look
|
||||||
|
// for the friendly name of the entity and replace that with
|
||||||
|
// _renderEntity if its there so the user can quickly get to
|
||||||
|
// that entity.
|
||||||
|
//
|
||||||
|
if (possibleEntity && possibleEntity in this.hass.states) {
|
||||||
|
const possibleEntityName =
|
||||||
|
this.hass.states[possibleEntity].attributes.friendly_name;
|
||||||
|
if (possibleEntityName && message.endsWith(possibleEntityName)) {
|
||||||
|
if (seenEntities.includes(possibleEntity)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
seenEntities.push(possibleEntity);
|
||||||
|
message = message.substring(
|
||||||
|
0,
|
||||||
|
message.length - possibleEntityName.length
|
||||||
|
);
|
||||||
|
return html` ${localizePrefix ? this.hass.localize(localizePrefix) : ""}
|
||||||
|
${message} ${this._renderEntity(possibleEntity, possibleEntityName)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
private _entityClicked(ev: Event) {
|
private _entityClicked(ev: Event) {
|
||||||
const entityId = (ev.currentTarget as any).entityId;
|
const entityId = (ev.currentTarget as any).entityId;
|
||||||
if (!entityId) {
|
if (!entityId) {
|
||||||
@ -275,6 +407,7 @@ class HaLogbook extends LitElement {
|
|||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
haStyleScrollbar,
|
haStyleScrollbar,
|
||||||
|
buttonLinkStyle,
|
||||||
css`
|
css`
|
||||||
:host([virtualize]) {
|
:host([virtualize]) {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -344,8 +344,14 @@
|
|||||||
},
|
},
|
||||||
"logbook": {
|
"logbook": {
|
||||||
"entries_not_found": "No logbook events found.",
|
"entries_not_found": "No logbook events found.",
|
||||||
|
"by_user": "by user",
|
||||||
"by": "by",
|
"by": "by",
|
||||||
"by_service": "by service",
|
"from": "from",
|
||||||
|
"for": "for",
|
||||||
|
"event": "event",
|
||||||
|
"from_service": "from service",
|
||||||
|
"from_automation": "from automation",
|
||||||
|
"from_script": "from script",
|
||||||
"show_trace": "[%key:ui::panel::config::automation::editor::show_trace%]",
|
"show_trace": "[%key:ui::panel::config::automation::editor::show_trace%]",
|
||||||
"retrieval_error": "Could not load logbook",
|
"retrieval_error": "Could not load logbook",
|
||||||
"messages": {
|
"messages": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user