mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-12 11:56:34 +00:00
Use new localized context state and source in logbook (#12742)
This commit is contained in:
parent
7db6e0b779
commit
a02b817d7f
@ -1,6 +1,10 @@
|
|||||||
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
|
import {
|
||||||
|
BINARY_STATE_OFF,
|
||||||
|
BINARY_STATE_ON,
|
||||||
|
DOMAINS_WITH_DYNAMIC_PICTURE,
|
||||||
|
} from "../common/const";
|
||||||
import { computeDomain } from "../common/entity/compute_domain";
|
import { computeDomain } from "../common/entity/compute_domain";
|
||||||
import { BINARY_STATE_OFF, BINARY_STATE_ON } from "../common/const";
|
|
||||||
import { computeStateDisplay } from "../common/entity/compute_state_display";
|
import { computeStateDisplay } from "../common/entity/compute_state_display";
|
||||||
import { LocalizeFunc } from "../common/translations/localize";
|
import { LocalizeFunc } from "../common/translations/localize";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
@ -10,26 +14,43 @@ const LOGBOOK_LOCALIZE_PATH = "ui.components.logbook.messages";
|
|||||||
export const CONTINUOUS_DOMAINS = ["proximity", "sensor"];
|
export const CONTINUOUS_DOMAINS = ["proximity", "sensor"];
|
||||||
|
|
||||||
export interface LogbookEntry {
|
export interface LogbookEntry {
|
||||||
// Python timestamp. Do *1000 to get JS timestamp.
|
// Base data
|
||||||
when: number;
|
when: number; // Python timestamp. Do *1000 to get JS timestamp.
|
||||||
name: string;
|
name: string;
|
||||||
message?: string;
|
message?: string;
|
||||||
entity_id?: string;
|
entity_id?: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
source?: string;
|
source?: string; // The trigger source
|
||||||
domain?: string;
|
domain?: string;
|
||||||
|
state?: string; // The state of the entity
|
||||||
|
// Context data
|
||||||
context_id?: string;
|
context_id?: string;
|
||||||
context_user_id?: string;
|
context_user_id?: string;
|
||||||
context_event_type?: string;
|
context_event_type?: string;
|
||||||
context_domain?: string;
|
context_domain?: string;
|
||||||
context_service?: string;
|
context_service?: string; // Service calls only
|
||||||
context_entity_id?: string;
|
context_entity_id?: string;
|
||||||
context_entity_id_name?: string;
|
context_entity_id_name?: string; // Legacy, not longer sent
|
||||||
context_name?: string;
|
context_name?: string;
|
||||||
|
context_state?: string; // The state of the entity
|
||||||
|
context_source?: string; // The trigger source
|
||||||
context_message?: string;
|
context_message?: string;
|
||||||
state?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Localization mapping for all the triggers in core
|
||||||
|
// in homeassistant.components.homeassistant.triggers
|
||||||
|
//
|
||||||
|
const triggerPhrases = {
|
||||||
|
"numeric state of": "triggered_by_numeric_state_of", // number state trigger
|
||||||
|
"state of": "triggered_by_state_of", // state trigger
|
||||||
|
event: "triggered_by_event", // event trigger
|
||||||
|
time: "triggered_by_time", // time trigger
|
||||||
|
"time pattern": "triggered_by_time_pattern", // time trigger
|
||||||
|
"Home Assistant stopping": "triggered_by_homeassistant_stopping", // stop event
|
||||||
|
"Home Assistant starting": "triggered_by_homeassistant_starting", // start event
|
||||||
|
};
|
||||||
|
|
||||||
const DATA_CACHE: {
|
const DATA_CACHE: {
|
||||||
[cacheKey: string]: { [entityId: string]: Promise<LogbookEntry[]> };
|
[cacheKey: string]: { [entityId: string]: Promise<LogbookEntry[]> };
|
||||||
} = {};
|
} = {};
|
||||||
@ -39,17 +60,13 @@ export const getLogbookDataForContext = async (
|
|||||||
startDate: string,
|
startDate: string,
|
||||||
contextId?: string
|
contextId?: string
|
||||||
): Promise<LogbookEntry[]> => {
|
): Promise<LogbookEntry[]> => {
|
||||||
const localize = await hass.loadBackendTranslation("device_class");
|
await hass.loadBackendTranslation("device_class");
|
||||||
return addLogbookMessage(
|
return getLogbookDataFromServer(
|
||||||
hass,
|
|
||||||
localize,
|
|
||||||
await getLogbookDataFromServer(
|
|
||||||
hass,
|
hass,
|
||||||
startDate,
|
startDate,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
contextId
|
contextId
|
||||||
)
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -60,13 +77,9 @@ export const getLogbookData = async (
|
|||||||
entityIds?: string[],
|
entityIds?: string[],
|
||||||
deviceIds?: string[]
|
deviceIds?: string[]
|
||||||
): Promise<LogbookEntry[]> => {
|
): Promise<LogbookEntry[]> => {
|
||||||
const localize = await hass.loadBackendTranslation("device_class");
|
await hass.loadBackendTranslation("device_class");
|
||||||
return addLogbookMessage(
|
return deviceIds?.length
|
||||||
hass,
|
? getLogbookDataFromServer(
|
||||||
localize,
|
|
||||||
// bypass cache if we have a device ID
|
|
||||||
deviceIds?.length
|
|
||||||
? await getLogbookDataFromServer(
|
|
||||||
hass,
|
hass,
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
@ -74,28 +87,7 @@ export const getLogbookData = async (
|
|||||||
undefined,
|
undefined,
|
||||||
deviceIds
|
deviceIds
|
||||||
)
|
)
|
||||||
: await getLogbookDataCache(hass, startDate, endDate, entityIds)
|
: getLogbookDataCache(hass, startDate, endDate, entityIds);
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addLogbookMessage = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
localize: LocalizeFunc,
|
|
||||||
logbookData: LogbookEntry[]
|
|
||||||
): LogbookEntry[] => {
|
|
||||||
for (const entry of logbookData) {
|
|
||||||
const stateObj = hass!.states[entry.entity_id!];
|
|
||||||
if (entry.state && stateObj) {
|
|
||||||
entry.message = getLogbookMessage(
|
|
||||||
hass,
|
|
||||||
localize,
|
|
||||||
entry.state,
|
|
||||||
stateObj,
|
|
||||||
computeDomain(entry.entity_id!)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return logbookData;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getLogbookDataCache = async (
|
const getLogbookDataCache = async (
|
||||||
@ -204,7 +196,49 @@ export const clearLogbookCache = (startDate: string, endDate: string) => {
|
|||||||
DATA_CACHE[`${startDate}${endDate}`] = {};
|
DATA_CACHE[`${startDate}${endDate}`] = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getLogbookMessage = (
|
export const createHistoricState = (
|
||||||
|
currentStateObj: HassEntity,
|
||||||
|
state?: string
|
||||||
|
): HassEntity => <HassEntity>(<unknown>{
|
||||||
|
entity_id: currentStateObj.entity_id,
|
||||||
|
state: state,
|
||||||
|
attributes: {
|
||||||
|
// Rebuild the historical state by copying static attributes only
|
||||||
|
device_class: currentStateObj?.attributes.device_class,
|
||||||
|
source_type: currentStateObj?.attributes.source_type,
|
||||||
|
has_date: currentStateObj?.attributes.has_date,
|
||||||
|
has_time: currentStateObj?.attributes.has_time,
|
||||||
|
// We do not want to use dynamic entity pictures (e.g., from media player) for the log book rendering,
|
||||||
|
// as they would present a false state in the log (played media right now vs actual historic data).
|
||||||
|
entity_picture_local: DOMAINS_WITH_DYNAMIC_PICTURE.has(
|
||||||
|
computeDomain(currentStateObj.entity_id)
|
||||||
|
)
|
||||||
|
? undefined
|
||||||
|
: currentStateObj?.attributes.entity_picture_local,
|
||||||
|
entity_picture: DOMAINS_WITH_DYNAMIC_PICTURE.has(
|
||||||
|
computeDomain(currentStateObj.entity_id)
|
||||||
|
)
|
||||||
|
? undefined
|
||||||
|
: currentStateObj?.attributes.entity_picture,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const localizeTriggerSource = (
|
||||||
|
localize: LocalizeFunc,
|
||||||
|
source: string
|
||||||
|
) => {
|
||||||
|
for (const triggerPhrase in triggerPhrases) {
|
||||||
|
if (source.startsWith(triggerPhrase)) {
|
||||||
|
return source.replace(
|
||||||
|
triggerPhrase,
|
||||||
|
`${localize(`ui.components.logbook.${triggerPhrases[triggerPhrase]}`)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const localizeStateMessage = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
localize: LocalizeFunc,
|
localize: LocalizeFunc,
|
||||||
state: string,
|
state: string,
|
||||||
|
@ -10,7 +10,6 @@ import {
|
|||||||
import type { HassEntity } from "home-assistant-js-websocket";
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { customElement, eventOptions, property } from "lit/decorators";
|
import { customElement, eventOptions, property } from "lit/decorators";
|
||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import { DOMAINS_WITH_DYNAMIC_PICTURE } from "../../common/const";
|
|
||||||
import { formatDate } from "../../common/datetime/format_date";
|
import { formatDate } from "../../common/datetime/format_date";
|
||||||
import { formatTimeWithSeconds } from "../../common/datetime/format_time";
|
import { formatTimeWithSeconds } from "../../common/datetime/format_time";
|
||||||
import { restoreScroll } from "../../common/decorators/restore-scroll";
|
import { restoreScroll } from "../../common/decorators/restore-scroll";
|
||||||
@ -21,7 +20,12 @@ import { computeRTL, emitRTLDirection } from "../../common/util/compute_rtl";
|
|||||||
import "../../components/entity/state-badge";
|
import "../../components/entity/state-badge";
|
||||||
import "../../components/ha-circular-progress";
|
import "../../components/ha-circular-progress";
|
||||||
import "../../components/ha-relative-time";
|
import "../../components/ha-relative-time";
|
||||||
import { LogbookEntry } from "../../data/logbook";
|
import {
|
||||||
|
createHistoricState,
|
||||||
|
localizeTriggerSource,
|
||||||
|
localizeStateMessage,
|
||||||
|
LogbookEntry,
|
||||||
|
} from "../../data/logbook";
|
||||||
import { TraceContexts } from "../../data/trace";
|
import { TraceContexts } from "../../data/trace";
|
||||||
import {
|
import {
|
||||||
haStyle,
|
haStyle,
|
||||||
@ -31,9 +35,12 @@ import {
|
|||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import { brandsUrl } from "../../util/brands-url";
|
import { brandsUrl } from "../../util/brands-url";
|
||||||
|
|
||||||
const EVENT_LOCALIZE_MAP = {
|
const triggerDomains = ["script", "automation"];
|
||||||
script_started: "from_script",
|
|
||||||
};
|
const hasContext = (item: LogbookEntry) =>
|
||||||
|
item.context_event_type || item.context_state || item.context_message;
|
||||||
|
const stripEntityId = (message: string, entityId?: string) =>
|
||||||
|
entityId ? message.replace(entityId, " ") : message;
|
||||||
|
|
||||||
@customElement("ha-logbook-renderer")
|
@customElement("ha-logbook-renderer")
|
||||||
class HaLogbookRenderer extends LitElement {
|
class HaLogbookRenderer extends LitElement {
|
||||||
@ -128,40 +135,22 @@ class HaLogbookRenderer extends LitElement {
|
|||||||
if (!item || index === undefined) {
|
if (!item || index === undefined) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
const seenEntityIds: string[] = [];
|
|
||||||
const previous = this.entries[index - 1];
|
const previous = this.entries[index - 1];
|
||||||
|
const seenEntityIds: string[] = [];
|
||||||
const currentStateObj = item.entity_id
|
const currentStateObj = item.entity_id
|
||||||
? this.hass.states[item.entity_id]
|
? this.hass.states[item.entity_id]
|
||||||
: undefined;
|
: undefined;
|
||||||
const item_username =
|
const historicStateObj = currentStateObj
|
||||||
item.context_user_id && this.userIdToName[item.context_user_id];
|
? createHistoricState(currentStateObj, item.state!)
|
||||||
|
: undefined;
|
||||||
const domain = item.entity_id
|
const domain = item.entity_id
|
||||||
? computeDomain(item.entity_id)
|
? computeDomain(item.entity_id)
|
||||||
: // Domain is there if there is no entity ID.
|
: // Domain is there if there is no entity ID.
|
||||||
item.domain!;
|
item.domain!;
|
||||||
const historicStateObj = item.entity_id ? <HassEntity>(<unknown>{
|
|
||||||
entity_id: item.entity_id,
|
|
||||||
state: item.state,
|
|
||||||
attributes: {
|
|
||||||
// Rebuild the historical state by copying static attributes only
|
|
||||||
device_class: currentStateObj?.attributes.device_class,
|
|
||||||
source_type: currentStateObj?.attributes.source_type,
|
|
||||||
has_date: currentStateObj?.attributes.has_date,
|
|
||||||
has_time: currentStateObj?.attributes.has_time,
|
|
||||||
// We do not want to use dynamic entity pictures (e.g., from media player) for the log book rendering,
|
|
||||||
// as they would present a false state in the log (played media right now vs actual historic data).
|
|
||||||
entity_picture_local: DOMAINS_WITH_DYNAMIC_PICTURE.has(domain)
|
|
||||||
? undefined
|
|
||||||
: currentStateObj?.attributes.entity_picture_local,
|
|
||||||
entity_picture: DOMAINS_WITH_DYNAMIC_PICTURE.has(domain)
|
|
||||||
? undefined
|
|
||||||
: currentStateObj?.attributes.entity_picture,
|
|
||||||
},
|
|
||||||
}) : undefined;
|
|
||||||
const overrideImage =
|
const overrideImage =
|
||||||
!historicStateObj &&
|
!historicStateObj &&
|
||||||
!item.icon &&
|
!item.icon &&
|
||||||
|
!item.state &&
|
||||||
domain &&
|
domain &&
|
||||||
isComponentLoaded(this.hass, domain)
|
isComponentLoaded(this.hass, domain)
|
||||||
? brandsUrl({
|
? brandsUrl({
|
||||||
@ -204,45 +193,13 @@ class HaLogbookRenderer extends LitElement {
|
|||||||
${!this.noName // Used for more-info panel (single entity case)
|
${!this.noName // Used for more-info panel (single entity case)
|
||||||
? this._renderEntity(item.entity_id, item.name)
|
? this._renderEntity(item.entity_id, item.name)
|
||||||
: ""}
|
: ""}
|
||||||
${item.message
|
${this._renderMessage(
|
||||||
? html`${this._formatMessageWithPossibleEntity(
|
item,
|
||||||
item.message,
|
|
||||||
seenEntityIds,
|
seenEntityIds,
|
||||||
item.entity_id
|
domain,
|
||||||
)}`
|
historicStateObj
|
||||||
: item.source
|
)}
|
||||||
? html` ${this._formatMessageWithPossibleEntity(
|
${this._renderContextMessage(item, seenEntityIds)}
|
||||||
item.source,
|
|
||||||
seenEntityIds,
|
|
||||||
undefined,
|
|
||||||
"ui.components.logbook.by"
|
|
||||||
)}`
|
|
||||||
: ""}
|
|
||||||
${item_username
|
|
||||||
? ` ${this.hass.localize(
|
|
||||||
"ui.components.logbook.by_user"
|
|
||||||
)} ${item_username}`
|
|
||||||
: ``}
|
|
||||||
${item.context_event_type
|
|
||||||
? this._formatEventBy(item, seenEntityIds)
|
|
||||||
: ""}
|
|
||||||
${item.context_message
|
|
||||||
? html` ${this._formatMessageWithPossibleEntity(
|
|
||||||
item.context_message,
|
|
||||||
seenEntityIds,
|
|
||||||
item.context_entity_id,
|
|
||||||
"ui.components.logbook.for"
|
|
||||||
)}`
|
|
||||||
: ""}
|
|
||||||
${item.context_entity_id &&
|
|
||||||
!seenEntityIds.includes(item.context_entity_id)
|
|
||||||
? // Another entity such as an automation or script
|
|
||||||
html` ${this.hass.localize("ui.components.logbook.for")}
|
|
||||||
${this._renderEntity(
|
|
||||||
item.context_entity_id,
|
|
||||||
item.context_entity_id_name
|
|
||||||
)}`
|
|
||||||
: ""}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="secondary">
|
<div class="secondary">
|
||||||
<span
|
<span
|
||||||
@ -257,7 +214,8 @@ class HaLogbookRenderer extends LitElement {
|
|||||||
.datetime=${item.when * 1000}
|
.datetime=${item.when * 1000}
|
||||||
capitalize
|
capitalize
|
||||||
></ha-relative-time>
|
></ha-relative-time>
|
||||||
${["script", "automation"].includes(item.domain!) &&
|
${item.context_user_id ? html`${this._renderUser(item)}` : ""}
|
||||||
|
${triggerDomains.includes(item.domain!) &&
|
||||||
item.context_id! in this.traceContexts
|
item.context_id! in this.traceContexts
|
||||||
? html`
|
? html`
|
||||||
-
|
-
|
||||||
@ -294,38 +252,149 @@ class HaLogbookRenderer extends LitElement {
|
|||||||
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
|
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _formatEventBy(item: LogbookEntry, seenEntities: string[]) {
|
private _renderMessage(
|
||||||
|
item: LogbookEntry,
|
||||||
|
seenEntityIds: string[],
|
||||||
|
domain?: string,
|
||||||
|
historicStateObj?: HassEntity
|
||||||
|
) {
|
||||||
|
if (item.entity_id) {
|
||||||
|
if (item.state) {
|
||||||
|
return historicStateObj
|
||||||
|
? localizeStateMessage(
|
||||||
|
this.hass,
|
||||||
|
this.hass.localize,
|
||||||
|
item.state,
|
||||||
|
historicStateObj,
|
||||||
|
domain!
|
||||||
|
)
|
||||||
|
: item.state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemHasContext = hasContext(item);
|
||||||
|
let message = item.message;
|
||||||
|
if (triggerDomains.includes(domain!) && item.source) {
|
||||||
|
if (itemHasContext) {
|
||||||
|
// These domains include the trigger source in the message
|
||||||
|
// but if we have the context we want to display that instead
|
||||||
|
// as otherwise we display duplicate triggers
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
message = localizeTriggerSource(this.hass.localize, item.source);
|
||||||
|
}
|
||||||
|
return message
|
||||||
|
? this._formatMessageWithPossibleEntity(
|
||||||
|
itemHasContext
|
||||||
|
? stripEntityId(message, item.context_entity_id)
|
||||||
|
: message,
|
||||||
|
seenEntityIds,
|
||||||
|
undefined
|
||||||
|
)
|
||||||
|
: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderUser(item: LogbookEntry) {
|
||||||
|
const item_username =
|
||||||
|
item.context_user_id && this.userIdToName[item.context_user_id];
|
||||||
|
if (item_username) {
|
||||||
|
return `- ${item_username}`;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderUnseenContextSourceEntity(
|
||||||
|
item: LogbookEntry,
|
||||||
|
seenEntityIds: string[]
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
!item.context_entity_id ||
|
||||||
|
seenEntityIds.includes(item.context_entity_id!)
|
||||||
|
) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
// We don't know what caused this entity
|
||||||
|
// to be included since its an integration
|
||||||
|
// described event.
|
||||||
|
return html` (${this._renderEntity(
|
||||||
|
item.context_entity_id,
|
||||||
|
item.context_entity_id_name
|
||||||
|
)})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderContextMessage(item: LogbookEntry, seenEntityIds: string[]) {
|
||||||
|
// State change
|
||||||
|
if (item.context_state) {
|
||||||
|
const historicStateObj =
|
||||||
|
item.context_entity_id && item.context_entity_id in this.hass.states
|
||||||
|
? createHistoricState(
|
||||||
|
this.hass.states[item.context_entity_id],
|
||||||
|
item.context_state
|
||||||
|
)
|
||||||
|
: undefined;
|
||||||
|
return html`${this.hass.localize(
|
||||||
|
"ui.components.logbook.triggered_by_state_of"
|
||||||
|
)}
|
||||||
|
${this._renderEntity(item.context_entity_id, item.context_entity_id_name)}
|
||||||
|
${historicStateObj
|
||||||
|
? localizeStateMessage(
|
||||||
|
this.hass,
|
||||||
|
this.hass.localize,
|
||||||
|
item.context_state,
|
||||||
|
historicStateObj,
|
||||||
|
computeDomain(item.context_entity_id!)
|
||||||
|
)
|
||||||
|
: item.context_state}`;
|
||||||
|
}
|
||||||
|
// Service call
|
||||||
if (item.context_event_type === "call_service") {
|
if (item.context_event_type === "call_service") {
|
||||||
return `${this.hass.localize("ui.components.logbook.from_service")} ${
|
return html`${this.hass.localize(
|
||||||
item.context_domain
|
"ui.components.logbook.triggered_by_service"
|
||||||
}.${item.context_service}`;
|
)}
|
||||||
|
${item.context_domain}.${item.context_service}`;
|
||||||
}
|
}
|
||||||
if (item.context_event_type === "automation_triggered") {
|
if (
|
||||||
if (seenEntities.includes(item.context_entity_id!)) {
|
!item.context_message ||
|
||||||
|
seenEntityIds.includes(item.context_entity_id!)
|
||||||
|
) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
seenEntities.push(item.context_entity_id!);
|
// Automation or script
|
||||||
return html`${this.hass.localize("ui.components.logbook.from_automation")}
|
if (
|
||||||
${this._renderEntity(item.context_entity_id, item.context_name)}`;
|
item.context_event_type === "automation_triggered" ||
|
||||||
|
item.context_event_type === "script_started"
|
||||||
|
) {
|
||||||
|
// context_source is available in 2022.6 and later
|
||||||
|
const triggerMsg = item.context_source
|
||||||
|
? item.context_source
|
||||||
|
: item.context_message.replace("triggered by ", "");
|
||||||
|
const contextTriggerSource = localizeTriggerSource(
|
||||||
|
this.hass.localize,
|
||||||
|
triggerMsg
|
||||||
|
);
|
||||||
|
return html`${this.hass.localize(
|
||||||
|
item.context_event_type === "automation_triggered"
|
||||||
|
? "ui.components.logbook.triggered_by_automation"
|
||||||
|
: "ui.components.logbook.triggered_by_script"
|
||||||
|
)}
|
||||||
|
${this._renderEntity(item.context_entity_id, item.context_entity_id_name)}
|
||||||
|
${item.context_message
|
||||||
|
? this._formatMessageWithPossibleEntity(
|
||||||
|
contextTriggerSource,
|
||||||
|
seenEntityIds
|
||||||
|
)
|
||||||
|
: ""}`;
|
||||||
}
|
}
|
||||||
if (item.context_name) {
|
// Generic externally described logbook platform
|
||||||
return `${this.hass.localize("ui.components.logbook.from")} ${
|
// These are not localizable
|
||||||
item.context_name
|
return html` ${this.hass.localize("ui.components.logbook.triggered_by")}
|
||||||
}`;
|
${item.context_name}
|
||||||
}
|
${this._formatMessageWithPossibleEntity(
|
||||||
if (item.context_event_type === "state_changed") {
|
item.context_message,
|
||||||
return "";
|
seenEntityIds,
|
||||||
}
|
item.context_entity_id
|
||||||
if (item.context_event_type! in EVENT_LOCALIZE_MAP) {
|
)}
|
||||||
return `${this.hass.localize(
|
${this._renderUnseenContextSourceEntity(item, seenEntityIds)}`;
|
||||||
`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(
|
private _renderEntity(
|
||||||
@ -353,8 +422,7 @@ class HaLogbookRenderer extends LitElement {
|
|||||||
private _formatMessageWithPossibleEntity(
|
private _formatMessageWithPossibleEntity(
|
||||||
message: string,
|
message: string,
|
||||||
seenEntities: string[],
|
seenEntities: string[],
|
||||||
possibleEntity?: string,
|
possibleEntity?: string
|
||||||
localizePrefix?: string
|
|
||||||
) {
|
) {
|
||||||
//
|
//
|
||||||
// As we are looking at a log(book), we are doing entity_id
|
// As we are looking at a log(book), we are doing entity_id
|
||||||
@ -376,7 +444,7 @@ class HaLogbookRenderer extends LitElement {
|
|||||||
seenEntities.push(entityId);
|
seenEntities.push(entityId);
|
||||||
const messageEnd = messageParts.splice(i);
|
const messageEnd = messageParts.splice(i);
|
||||||
messageEnd.shift(); // remove the entity
|
messageEnd.shift(); // remove the entity
|
||||||
return html` ${messageParts.join(" ")}
|
return html`${messageParts.join(" ")}
|
||||||
${this._renderEntity(
|
${this._renderEntity(
|
||||||
entityId,
|
entityId,
|
||||||
this.hass.states[entityId].attributes.friendly_name
|
this.hass.states[entityId].attributes.friendly_name
|
||||||
@ -404,8 +472,8 @@ class HaLogbookRenderer extends LitElement {
|
|||||||
0,
|
0,
|
||||||
message.length - possibleEntityName.length
|
message.length - possibleEntityName.length
|
||||||
);
|
);
|
||||||
return html` ${localizePrefix ? this.hass.localize(localizePrefix) : ""}
|
return html`${message}
|
||||||
${message} ${this._renderEntity(possibleEntity, possibleEntityName)}`;
|
${this._renderEntity(possibleEntity, possibleEntityName)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
|
@ -344,14 +344,17 @@
|
|||||||
},
|
},
|
||||||
"logbook": {
|
"logbook": {
|
||||||
"entries_not_found": "No logbook events found.",
|
"entries_not_found": "No logbook events found.",
|
||||||
"by_user": "by user",
|
"triggered_by": "triggered by",
|
||||||
"by": "by",
|
"triggered_by_automation": "triggered by automation",
|
||||||
"from": "from",
|
"triggered_by_script": "triggered by script",
|
||||||
"for": "for",
|
"triggered_by_service": "triggered by service",
|
||||||
"event": "event",
|
"triggered_by_numeric_state_of": "triggered by numeric state of",
|
||||||
"from_service": "from service",
|
"triggered_by_state_of": "triggered by state of",
|
||||||
"from_automation": "from automation",
|
"triggered_by_event": "triggered by event",
|
||||||
"from_script": "from script",
|
"triggered_by_time": "triggered by time",
|
||||||
|
"triggered_by_time_pattern": "triggered by time pattern",
|
||||||
|
"triggered_by_homeassistant_stopping": "triggered by Home Assistant stopping",
|
||||||
|
"triggered_by_homeassistant_starting": "triggered by Home Assistant starting",
|
||||||
"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