diff --git a/src/panels/config/automation/trace/ha-automation-trace-blueprint-config.ts b/src/components/trace/ha-trace-blueprint-config.ts
similarity index 50%
rename from src/panels/config/automation/trace/ha-automation-trace-blueprint-config.ts
rename to src/components/trace/ha-trace-blueprint-config.ts
index bc3117114b..64e4bbc810 100644
--- a/src/panels/config/automation/trace/ha-automation-trace-blueprint-config.ts
+++ b/src/components/trace/ha-trace-blueprint-config.ts
@@ -1,16 +1,16 @@
import { dump } from "js-yaml";
import { html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
-import "../../../../components/ha-code-editor";
-import "../../../../components/ha-icon-button";
-import { AutomationTraceExtended } from "../../../../data/trace";
-import { HomeAssistant } from "../../../../types";
+import "../ha-code-editor";
+import "../ha-icon-button";
+import { TraceExtended } from "../../data/trace";
+import { HomeAssistant } from "../../types";
-@customElement("ha-automation-trace-blueprint-config")
-export class HaAutomationTraceBlueprintConfig extends LitElement {
+@customElement("ha-trace-blueprint-config")
+export class HaTraceBlueprintConfig extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
- @property() public trace!: AutomationTraceExtended;
+ @property({ attribute: false }) public trace!: TraceExtended;
protected render(): TemplateResult {
return html`
@@ -24,6 +24,6 @@ export class HaAutomationTraceBlueprintConfig extends LitElement {
declare global {
interface HTMLElementTagNameMap {
- "ha-automation-trace-blueprint-config": HaAutomationTraceBlueprintConfig;
+ "ha-trace-blueprint-config": HaTraceBlueprintConfig;
}
}
diff --git a/src/panels/config/automation/trace/ha-automation-trace-config.ts b/src/components/trace/ha-trace-config.ts
similarity index 55%
rename from src/panels/config/automation/trace/ha-automation-trace-config.ts
rename to src/components/trace/ha-trace-config.ts
index c97bb47f8b..237a051110 100644
--- a/src/panels/config/automation/trace/ha-automation-trace-config.ts
+++ b/src/components/trace/ha-trace-config.ts
@@ -1,16 +1,16 @@
import { dump } from "js-yaml";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
-import "../../../../components/ha-code-editor";
-import "../../../../components/ha-icon-button";
-import { AutomationTraceExtended } from "../../../../data/trace";
-import { HomeAssistant } from "../../../../types";
+import "../ha-code-editor";
+import "../ha-icon-button";
+import { TraceExtended } from "../../data/trace";
+import { HomeAssistant } from "../../types";
-@customElement("ha-automation-trace-config")
-export class HaAutomationTraceConfig extends LitElement {
+@customElement("ha-trace-config")
+export class HaTraceConfig extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
- @property() public trace!: AutomationTraceExtended;
+ @property({ attribute: false }) public trace!: TraceExtended;
protected render(): TemplateResult {
return html`
@@ -28,6 +28,6 @@ export class HaAutomationTraceConfig extends LitElement {
declare global {
interface HTMLElementTagNameMap {
- "ha-automation-trace-config": HaAutomationTraceConfig;
+ "ha-trace-config": HaTraceConfig;
}
}
diff --git a/src/panels/config/automation/trace/ha-automation-trace-logbook.ts b/src/components/trace/ha-trace-logbook.ts
similarity index 66%
rename from src/panels/config/automation/trace/ha-automation-trace-logbook.ts
rename to src/components/trace/ha-trace-logbook.ts
index 675d355662..2f4da4de66 100644
--- a/src/panels/config/automation/trace/ha-automation-trace-logbook.ts
+++ b/src/components/trace/ha-trace-logbook.ts
@@ -1,16 +1,19 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
-import "../../../../components/trace/hat-logbook-note";
-import type { LogbookEntry } from "../../../../data/logbook";
-import type { HomeAssistant } from "../../../../types";
-import "../../../logbook/ha-logbook";
+import { LogbookEntry } from "../../data/logbook";
+import { HomeAssistant } from "../../types";
+import "./hat-logbook-note";
+import "../../panels/logbook/ha-logbook";
+import { TraceExtended } from "../../data/trace";
-@customElement("ha-automation-trace-logbook")
-export class HaAutomationTraceLogbook extends LitElement {
+@customElement("ha-trace-logbook")
+export class HaTraceLogbook extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean, reflect: true }) public narrow!: boolean;
+ @property({ attribute: false }) public trace!: TraceExtended;
+
@property({ attribute: false }) public logbookEntries!: LogbookEntry[];
protected render(): TemplateResult {
@@ -22,7 +25,7 @@ export class HaAutomationTraceLogbook extends LitElement {
.entries=${this.logbookEntries}
.narrow=${this.narrow}
>
-
+
`
: html`
No Logbook entries found for this step.
@@ -42,6 +45,6 @@ export class HaAutomationTraceLogbook extends LitElement {
declare global {
interface HTMLElementTagNameMap {
- "ha-automation-trace-logbook": HaAutomationTraceLogbook;
+ "ha-trace-logbook": HaTraceLogbook;
}
}
diff --git a/src/panels/config/automation/trace/ha-automation-trace-path-details.ts b/src/components/trace/ha-trace-path-details.ts
similarity index 87%
rename from src/panels/config/automation/trace/ha-automation-trace-path-details.ts
rename to src/components/trace/ha-trace-path-details.ts
index dc0412b149..45134c532a 100644
--- a/src/panels/config/automation/trace/ha-automation-trace-path-details.ts
+++ b/src/components/trace/ha-trace-path-details.ts
@@ -2,33 +2,33 @@ import { dump } from "js-yaml";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
-import { formatDateTimeWithSeconds } from "../../../../common/datetime/format_date_time";
-import "../../../../components/ha-code-editor";
-import "../../../../components/ha-icon-button";
-import type { NodeInfo } from "../../../../components/trace/hat-graph";
-import "../../../../components/trace/hat-logbook-note";
-import { LogbookEntry } from "../../../../data/logbook";
+import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time";
+import "../ha-code-editor";
+import "../ha-icon-button";
+import type { NodeInfo } from "./hat-graph";
+import "./hat-logbook-note";
+import { LogbookEntry } from "../../data/logbook";
import {
ActionTraceStep,
- AutomationTraceExtended,
ChooseActionTraceStep,
getDataFromPath,
-} from "../../../../data/trace";
-import { HomeAssistant } from "../../../../types";
-import "../../../logbook/ha-logbook";
-import { traceTabStyles } from "./styles";
+ TraceExtended,
+} from "../../data/trace";
+import "../../panels/logbook/ha-logbook";
+import { traceTabStyles } from "./trace-tab-styles";
+import { HomeAssistant } from "../../types";
-@customElement("ha-automation-trace-path-details")
-export class HaAutomationTracePathDetails extends LitElement {
+@customElement("ha-trace-path-details")
+export class HaTracePathDetails extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean, reflect: true }) public narrow!: boolean;
- @property() private selected!: NodeInfo;
+ @property({ attribute: false }) public trace!: TraceExtended;
- @property() public trace!: AutomationTraceExtended;
+ @property({ attribute: false }) public logbookEntries!: LogbookEntry[];
- @property() public logbookEntries!: LogbookEntry[];
+ @property({ attribute: false }) public selected!: NodeInfo;
@property() renderedNodes: Record
= {};
@@ -230,7 +230,7 @@ export class HaAutomationTracePathDetails extends LitElement {
.entries=${entries}
.narrow=${this.narrow}
>
-
+
`
: html`
No Logbook entries found for this step.
@@ -267,6 +267,6 @@ export class HaAutomationTracePathDetails extends LitElement {
declare global {
interface HTMLElementTagNameMap {
- "ha-automation-trace-path-details": HaAutomationTracePathDetails;
+ "ha-trace-path-details": HaTracePathDetails;
}
}
diff --git a/src/panels/config/automation/trace/ha-automation-trace-timeline.ts b/src/components/trace/ha-trace-timeline.ts
similarity index 55%
rename from src/panels/config/automation/trace/ha-automation-trace-timeline.ts
rename to src/components/trace/ha-trace-timeline.ts
index d379dc6934..2680254f93 100644
--- a/src/panels/config/automation/trace/ha-automation-trace-timeline.ts
+++ b/src/components/trace/ha-trace-timeline.ts
@@ -1,17 +1,17 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
-import type { NodeInfo } from "../../../../components/trace/hat-graph";
-import "../../../../components/trace/hat-logbook-note";
-import "../../../../components/trace/hat-trace-timeline";
-import type { LogbookEntry } from "../../../../data/logbook";
-import type { AutomationTraceExtended } from "../../../../data/trace";
-import type { HomeAssistant } from "../../../../types";
+import type { NodeInfo } from "./hat-graph";
+import "./hat-logbook-note";
+import "./hat-trace-timeline";
+import type { LogbookEntry } from "../../data/logbook";
+import type { TraceExtended } from "../../data/trace";
+import type { HomeAssistant } from "../../types";
-@customElement("ha-automation-trace-timeline")
-export class HaAutomationTraceTimeline extends LitElement {
+@customElement("ha-trace-timeline")
+export class HaTraceTimeline extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
- @property({ attribute: false }) public trace!: AutomationTraceExtended;
+ @property({ attribute: false }) public trace!: TraceExtended;
@property({ attribute: false }) public logbookEntries!: LogbookEntry[];
@@ -27,7 +27,7 @@ export class HaAutomationTraceTimeline extends LitElement {
allowPick
>
-
+
`;
}
@@ -45,6 +45,6 @@ export class HaAutomationTraceTimeline extends LitElement {
declare global {
interface HTMLElementTagNameMap {
- "ha-automation-trace-timeline": HaAutomationTraceTimeline;
+ "ha-trace-timeline": HaTraceTimeline;
}
}
diff --git a/src/components/trace/hat-graph-node.ts b/src/components/trace/hat-graph-node.ts
index 5b0ba7ca64..bb418dc23e 100644
--- a/src/components/trace/hat-graph-node.ts
+++ b/src/components/trace/hat-graph-node.ts
@@ -8,7 +8,7 @@ export class HatGraphNode extends LitElement {
@property({ reflect: true, type: Boolean }) disabled?: boolean;
- @property({ reflect: true, type: Boolean }) graphstart?: boolean;
+ @property({ reflect: true, type: Boolean }) graphStart?: boolean;
@property({ reflect: true, type: Boolean }) nofocus?: boolean;
@@ -21,20 +21,20 @@ export class HatGraphNode extends LitElement {
}
render() {
- const height = NODE_SIZE + (this.graphstart ? 2 : SPACING + 1);
+ const height = NODE_SIZE + (this.graphStart ? 2 : SPACING + 1);
const width = SPACING + NODE_SIZE;
return svg`
@@ -219,46 +216,47 @@ export class HaAutomationTrace extends LitElement {
? ""
: this._view === "details"
? html`
-
+ .renderedNodes=${renderedNodes!}
+ >
`
: this._view === "config"
? html`
-
+ >
`
: this._view === "logbook"
? html`
-
+ >
`
: this._view === "blueprint"
? html`
-
+ >
`
: html`
-
+ >
`}
diff --git a/src/panels/config/automation/ha-config-automation.ts b/src/panels/config/automation/ha-config-automation.ts
index 8a61fabf57..a4fa5d38ab 100644
--- a/src/panels/config/automation/ha-config-automation.ts
+++ b/src/panels/config/automation/ha-config-automation.ts
@@ -51,7 +51,7 @@ class HaConfigAutomation extends HassRouterPage {
},
trace: {
tag: "ha-automation-trace",
- load: () => import("./trace/ha-automation-trace"),
+ load: () => import("./ha-automation-trace"),
},
},
};
diff --git a/src/panels/config/script/ha-config-script.ts b/src/panels/config/script/ha-config-script.ts
index f1c11a2b84..4b8f9aefa8 100644
--- a/src/panels/config/script/ha-config-script.ts
+++ b/src/panels/config/script/ha-config-script.ts
@@ -42,6 +42,10 @@ class HaConfigScript extends HassRouterPage {
edit: {
tag: "ha-script-editor",
},
+ trace: {
+ tag: "ha-script-trace",
+ load: () => import("./ha-script-trace"),
+ },
},
};
@@ -81,7 +85,7 @@ class HaConfigScript extends HassRouterPage {
if (
(!changedProps || changedProps.has("route")) &&
- this._currentPage === "edit"
+ this._currentPage !== "dashboard"
) {
pageEl.creatingNew = undefined;
const scriptEntityId = this.routeTail.path.substr(1);
diff --git a/src/panels/config/script/ha-script-editor.ts b/src/panels/config/script/ha-script-editor.ts
index dc7abce376..2b22bd69ef 100644
--- a/src/panels/config/script/ha-script-editor.ts
+++ b/src/panels/config/script/ha-script-editor.ts
@@ -297,7 +297,16 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
-
+
+
+ ${this.hass.localize(
+ "ui.panel.config.script.editor.show_trace"
+ )}
+
+
`,
};
+ columns.trace = {
+ title: "",
+ type: "icon-button",
+ template: (_info, script: any) => html`
+
+
+
+
+
+ `,
+ };
columns.edit = {
title: "",
type: "icon-button",
diff --git a/src/panels/config/script/ha-script-trace.ts b/src/panels/config/script/ha-script-trace.ts
new file mode 100644
index 0000000000..786dfb9d9e
--- /dev/null
+++ b/src/panels/config/script/ha-script-trace.ts
@@ -0,0 +1,502 @@
+import {
+ mdiDownload,
+ mdiPencil,
+ mdiRayEndArrow,
+ mdiRayStartArrow,
+ mdiRefresh,
+} from "@mdi/js";
+import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
+import { customElement, property, state } from "lit/decorators";
+import { classMap } from "lit/directives/class-map";
+import { repeat } from "lit/directives/repeat";
+import { isComponentLoaded } from "../../../common/config/is_component_loaded";
+import { formatDateTimeWithSeconds } from "../../../common/datetime/format_date_time";
+import type { NodeInfo } from "../../../components/trace/hat-graph";
+import "../../../components/trace/hat-script-graph";
+import { getLogbookDataForContext, LogbookEntry } from "../../../data/logbook";
+import { ScriptEntity } from "../../../data/script";
+import {
+ loadTrace,
+ loadTraces,
+ ScriptTrace,
+ ScriptTraceExtended,
+} from "../../../data/trace";
+import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
+import { haStyle } from "../../../resources/styles";
+import { HomeAssistant, Route } from "../../../types";
+import { traceTabStyles } from "../../../components/trace/trace-tab-styles";
+import { configSections } from "../ha-panel-config";
+import "../../../components/trace/ha-trace-blueprint-config";
+import "../../../components/trace/ha-trace-config";
+import "../../../components/trace/ha-trace-logbook";
+import "../../../components/trace/ha-trace-path-details";
+import "../../../components/trace/ha-trace-timeline";
+
+@customElement("ha-script-trace")
+export class HaScriptTrace extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property() public scriptEntityId!: string;
+
+ @property({ attribute: false }) public scripts!: ScriptEntity[];
+
+ @property({ type: Boolean }) public isWide?: boolean;
+
+ @property({ type: Boolean, reflect: true }) public narrow!: boolean;
+
+ @property({ attribute: false }) public route!: Route;
+
+ @state() private _traces?: ScriptTrace[];
+
+ @state() private _runId?: string;
+
+ @state() private _selected?: NodeInfo;
+
+ @state() private _trace?: ScriptTraceExtended;
+
+ @state() private _logbookEntries?: LogbookEntry[];
+
+ @state() private _view:
+ | "details"
+ | "config"
+ | "timeline"
+ | "logbook"
+ | "blueprint" = "details";
+
+ protected render(): TemplateResult {
+ const stateObj = this.scriptEntityId
+ ? this.hass.states[this.scriptEntityId]
+ : undefined;
+
+ const graph = this.shadowRoot!.querySelector("hat-script-graph");
+ const trackedNodes = graph?.trackedNodes;
+ const renderedNodes = graph?.renderedNodes;
+
+ const title = stateObj?.attributes.friendly_name || this.scriptEntityId;
+
+ let devButtons: TemplateResult | string = "";
+ if (__DEV__) {
+ devButtons = html`
+
+
+
`;
+ }
+
+ const actionButtons = html`
+ this._loadTraces()}>
+
+
+
+
+
+ `;
+
+ return html`
+ ${devButtons}
+
+ ${this.narrow
+ ? html` ${title}
+ ${actionButtons}
`
+ : ""}
+
+
+ ${this._traces === undefined
+ ? html`Loading…
`
+ : this._traces.length === 0
+ ? html`No traces found
`
+ : this._trace === undefined
+ ? ""
+ : html`
+
+
+
+
+
+
+
+ ${[
+ ["details", "Step Details"],
+ ["timeline", "Trace Timeline"],
+ ["logbook", "Related logbook entries"],
+ ["config", "Script Config"],
+ ].map(
+ ([view, label]) => html`
+
+ `
+ )}
+ ${this._trace.blueprint_inputs
+ ? html`
+
+ `
+ : ""}
+
+ ${this._selected === undefined ||
+ this._logbookEntries === undefined ||
+ trackedNodes === undefined
+ ? ""
+ : this._view === "details"
+ ? html`
+
+ `
+ : this._view === "config"
+ ? html`
+
+ `
+ : this._view === "logbook"
+ ? html`
+
+ `
+ : this._view === "blueprint"
+ ? html`
+
+ `
+ : html`
+
+ `}
+
+
+ `}
+
+ `;
+ }
+
+ protected firstUpdated(changedProps) {
+ super.firstUpdated(changedProps);
+
+ if (!this.scriptEntityId) {
+ return;
+ }
+
+ const params = new URLSearchParams(location.search);
+ this._loadTraces(params.get("run_id") || undefined);
+ }
+
+ protected updated(changedProps) {
+ super.updated(changedProps);
+
+ // Only reset if automationId has changed and we had one before.
+ if (changedProps.get("scriptEntityId")) {
+ this._traces = undefined;
+ this._runId = undefined;
+ this._trace = undefined;
+ this._logbookEntries = undefined;
+ if (this.scriptEntityId) {
+ this._loadTraces();
+ }
+ }
+
+ if (changedProps.has("_runId") && this._runId) {
+ this._trace = undefined;
+ this._logbookEntries = undefined;
+ this.shadowRoot!.querySelector("select")!.value = this._runId;
+ this._loadTrace();
+ }
+ }
+
+ private _pickOlderTrace() {
+ const curIndex = this._traces!.findIndex((tr) => tr.run_id === this._runId);
+ this._runId = this._traces![curIndex + 1].run_id;
+ this._selected = undefined;
+ }
+
+ private _pickNewerTrace() {
+ const curIndex = this._traces!.findIndex((tr) => tr.run_id === this._runId);
+ this._runId = this._traces![curIndex - 1].run_id;
+ this._selected = undefined;
+ }
+
+ private _pickTrace(ev) {
+ this._runId = ev.target.value;
+ this._selected = undefined;
+ }
+
+ private _pickNode(ev) {
+ this._selected = ev.detail;
+ }
+
+ private async _loadTraces(runId?: string) {
+ this._traces = await loadTraces(
+ this.hass,
+ "script",
+ this.scriptEntityId.split(".")[1]
+ );
+ // Newest will be on top.
+ this._traces.reverse();
+
+ if (runId) {
+ this._runId = runId;
+ }
+
+ // Check if current run ID still exists
+ if (
+ this._runId &&
+ !this._traces.some((trace) => trace.run_id === this._runId)
+ ) {
+ this._runId = undefined;
+ this._selected = undefined;
+
+ // If we came here from a trace passed into the url, clear it.
+ if (runId) {
+ const params = new URLSearchParams(location.search);
+ params.delete("run_id");
+ history.replaceState(
+ null,
+ "",
+ `${location.pathname}?${params.toString()}`
+ );
+ }
+
+ await showAlertDialog(this, {
+ text: "Chosen trace is no longer available",
+ });
+ }
+
+ // See if we can set a default runID
+ if (!this._runId && this._traces.length > 0) {
+ this._runId = this._traces[0].run_id;
+ }
+ }
+
+ private async _loadTrace() {
+ const trace = await loadTrace(
+ this.hass,
+ "script",
+ this.scriptEntityId.split(".")[1],
+ this._runId!
+ );
+ this._logbookEntries = isComponentLoaded(this.hass, "logbook")
+ ? await getLogbookDataForContext(
+ this.hass,
+ trace.timestamp.start,
+ trace.context.id
+ )
+ : [];
+
+ this._trace = trace;
+ }
+
+ private _downloadTrace() {
+ const aEl = document.createElement("a");
+ aEl.download = `trace ${this.scriptEntityId} ${
+ this._trace!.timestamp.start
+ }.json`;
+ aEl.href = `data:application/json;charset=utf-8,${encodeURI(
+ JSON.stringify(
+ {
+ trace: this._trace,
+ logbookEntries: this._logbookEntries,
+ },
+ undefined,
+ 2
+ )
+ )}`;
+ aEl.click();
+ }
+
+ private _importTrace() {
+ const traceText = prompt("Enter downloaded trace");
+ if (!traceText) {
+ return;
+ }
+ localStorage.devTrace = traceText;
+ this._loadLocalTrace(traceText);
+ }
+
+ private _loadLocalStorageTrace() {
+ if (localStorage.devTrace) {
+ this._loadLocalTrace(localStorage.devTrace);
+ }
+ }
+
+ private _loadLocalTrace(traceText: string) {
+ const traceInfo = JSON.parse(traceText);
+ this._trace = traceInfo.trace;
+ this._logbookEntries = traceInfo.logbookEntries;
+ }
+
+ private _showTab(ev) {
+ this._view = (ev.target as any).view;
+ }
+
+ private _timelinePathPicked(ev) {
+ const path = ev.detail.value;
+ const nodes = this.shadowRoot!.querySelector("hat-script-graph")!
+ .trackedNodes;
+ if (nodes[path]) {
+ this._selected = nodes[path];
+ }
+ }
+
+ static get styles(): CSSResultGroup {
+ return [
+ haStyle,
+ traceTabStyles,
+ css`
+ .toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-size: 20px;
+ height: var(--header-height);
+ padding: 0 16px;
+ background-color: var(--primary-background-color);
+ font-weight: 400;
+ color: var(--app-header-text-color, white);
+ border-bottom: var(--app-header-border-bottom, none);
+ box-sizing: border-box;
+ }
+
+ .toolbar > * {
+ display: flex;
+ align-items: center;
+ }
+
+ :host([narrow]) .toolbar > * {
+ display: contents;
+ }
+
+ .main {
+ height: calc(100% - 56px);
+ display: flex;
+ background-color: var(--card-background-color);
+ }
+
+ :host([narrow]) .main {
+ height: auto;
+ flex-direction: column;
+ }
+
+ .container {
+ padding: 16px;
+ }
+
+ .graph {
+ border-right: 1px solid var(--divider-color);
+ overflow-x: auto;
+ max-width: 50%;
+ }
+ :host([narrow]) .graph {
+ max-width: 100%;
+ }
+
+ .info {
+ flex: 1;
+ background-color: var(--card-background-color);
+ }
+
+ .linkButton {
+ color: var(--primary-text-color);
+ }
+ `,
+ ];
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "ha-script-trace": HaScriptTrace;
+ }
+}
diff --git a/src/translations/en.json b/src/translations/en.json
index c556a89876..d7a4efd15d 100755
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -303,7 +303,7 @@
"entries_not_found": "No logbook entries found.",
"by": "by",
"by_service": "by service",
- "show_trace": "Show trace",
+ "show_trace": "[%key:ui::panel::config::automation::editor::show_trace%]",
"retrieval_error": "Error during logbook entry retrieval",
"messages": {
"was_away": "was detected away",
@@ -1640,6 +1640,7 @@
"show_info": "Show info about script",
"run_script": "Run script",
"edit_script": "Edit script",
+ "dev_script": "Debug script",
"headers": {
"name": "Name"
},
@@ -1653,6 +1654,7 @@
"id_already_exists_save_error": "You can't save this script because the ID is not unique, pick another ID or leave it blank to automatically generate one.",
"id_already_exists": "This ID already exists",
"introduction": "Use scripts to run a sequence of actions.",
+ "show_trace": "[%key:ui::panel::config::automation::editor::show_trace%]",
"header": "Script: {name}",
"default_name": "New Script",
"modes": {