Trace fixes (#9192)

* Show sub-conditions

* Better show errors in timeline

* Add rendered nodes

* Fix some rendering issues with sub-conditions in timeline

* Improve condition rendering
This commit is contained in:
Paulus Schoutsen 2021-05-17 11:19:47 -07:00 committed by GitHub
parent fd2728c02c
commit f8e8b5ad18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 49 deletions

View File

@ -63,6 +63,8 @@ class HatScriptGraph extends LitElement {
@property({ attribute: false }) public selected;
@property() renderedNodes: Record<string, any> = {};
@property() trackedNodes: Record<string, any> = {};
private selectNode(config, path) {
@ -74,8 +76,9 @@ class HatScriptGraph extends LitElement {
private render_trigger(config: Trigger, i: number) {
const path = `trigger/${i}`;
const tracked = this.trace && path in this.trace.trace;
this.renderedNodes[path] = { config, path };
if (tracked) {
this.trackedNodes[path] = { config, path };
this.trackedNodes[path] = this.renderedNodes[path];
}
return html`
<hat-graph-node
@ -96,8 +99,9 @@ class HatScriptGraph extends LitElement {
const trace = this.trace.trace[path] as ConditionTraceStep[] | undefined;
const track_path =
trace?.[0].result === undefined ? 0 : trace[0].result.result ? 1 : 2;
this.renderedNodes[path] = { config, path };
if (trace) {
this.trackedNodes[path] = { config, path };
this.trackedNodes[path] = this.renderedNodes[path];
}
return html`
<hat-graph
@ -172,8 +176,11 @@ class HatScriptGraph extends LitElement {
const branch_path = `${path}/choose/${i}`;
const track_this =
trace !== undefined && trace[0].result?.choice === i;
this.renderedNodes[branch_path] = { config, path: branch_path };
if (track_this) {
this.trackedNodes[branch_path] = { config, path: branch_path };
this.trackedNodes[branch_path] = this.renderedNodes[
branch_path
];
}
return html`
<hat-graph>
@ -411,8 +418,9 @@ class HatScriptGraph extends LitElement {
const type = Object.keys(NODE_TYPES).find((key) => key in node) || "other";
const nodeEl = NODE_TYPES[type].bind(this)(node, path);
this.renderedNodes[path] = { config: node, path };
if (this.trace && path in this.trace.trace) {
this.trackedNodes[path] = { config: node, path };
this.trackedNodes[path] = this.renderedNodes[path];
}
return nodeEl;
}
@ -483,6 +491,7 @@ class HatScriptGraph extends LitElement {
protected update(changedProps: PropertyValues<this>) {
if (changedProps.has("trace")) {
this.renderedNodes = {};
this.trackedNodes = {};
}
super.update(changedProps);
@ -493,7 +502,7 @@ class HatScriptGraph extends LitElement {
// Select first node if new trace loaded but no selection given.
if (changedProps.has("trace")) {
const tracked = this.getTrackedNodes();
const tracked = this.trackedNodes;
const paths = Object.keys(tracked);
// If trace changed and we have no or an invalid selection, select first option.
@ -509,42 +518,44 @@ class HatScriptGraph extends LitElement {
if (this.trace) {
const sortKeys = Object.keys(this.trace.trace);
const keys = Object.keys(this.trackedNodes).sort(
const keys = Object.keys(this.renderedNodes).sort(
(a, b) => sortKeys.indexOf(a) - sortKeys.indexOf(b)
);
const sortedTrackedNodes = keys.reduce((obj, key) => {
obj[key] = this.trackedNodes[key];
return obj;
}, {});
const sortedTrackedNodes = {};
const sortedRenderedNodes = {};
for (const key of keys) {
sortedRenderedNodes[key] = this.renderedNodes[key];
if (key in this.trackedNodes) {
sortedTrackedNodes[key] = this.trackedNodes[key];
}
}
this.renderedNodes = sortedRenderedNodes;
this.trackedNodes = sortedTrackedNodes;
}
}
}
public getTrackedNodes() {
return this.trackedNodes;
}
public previousTrackedNode() {
const tracked = this.getTrackedNodes();
const nodes = Object.keys(tracked);
for (let i = nodes.indexOf(this.selected) - 1; i >= 0; i--) {
if (tracked[nodes[i]]) {
fireEvent(this, "graph-node-selected", tracked[nodes[i]]);
break;
}
const nodes = Object.keys(this.trackedNodes);
const prevIndex = nodes.indexOf(this.selected) - 1;
if (prevIndex >= 0) {
fireEvent(
this,
"graph-node-selected",
this.trackedNodes[nodes[prevIndex]]
);
}
}
public nextTrackedNode() {
const tracked = this.getTrackedNodes();
const nodes = Object.keys(tracked);
for (let i = nodes.indexOf(this.selected) + 1; i < nodes.length; i++) {
if (tracked[nodes[i]]) {
fireEvent(this, "graph-node-selected", tracked[nodes[i]]);
break;
}
const nodes = Object.keys(this.trackedNodes);
const nextIndex = nodes.indexOf(this.selected) + 1;
if (nextIndex < nodes.length) {
fireEvent(
this,
"graph-node-selected",
this.trackedNodes[nodes[nextIndex]]
);
}
}

View File

@ -245,13 +245,15 @@ class ActionRenderer {
try {
data = getDataFromPath(this.trace.config, path);
} catch (err) {
this.entries.push(
html`Unable to extract path ${path}. Download trace and report as bug`
this._renderEntry(
path,
`Unable to extract path ${path}. Download trace and report as bug`
);
return index + 1;
}
const isTopLevel = path.split("/").length === 2;
const parts = path.split("/");
const isTopLevel = parts.length === 2;
if (!isTopLevel && !actionType) {
this._renderEntry(path, path.replace(/\//g, " "));
@ -267,7 +269,16 @@ class ActionRenderer {
}
this._renderEntry(path, describeAction(this.hass, data, actionType));
return index + 1;
let i = index + 1;
for (; i < this.keys.length; i++) {
if (this.keys[i].split("/").length === parts.length) {
break;
}
}
return i;
}
private _handleTrigger(index: number, triggerStep: TriggerTraceStep): number {
@ -303,7 +314,7 @@ class ActionRenderer {
// +4: executed sequence
const choosePath = this.keys[index];
const startLevel = choosePath.split("/").length - 1;
const startLevel = choosePath.split("/").length;
const chooseTrace = this._getItem(index)[0] as ChooseActionTraceStep;
const defaultExecuted = chooseTrace.result?.choice === "default";

View File

@ -7,8 +7,8 @@ export const describeCondition = (condition: Condition) => {
if (condition.alias) {
return condition.alias;
}
if (condition.condition === "template") {
return "Test a template";
if (["or", "and", "not"].includes(condition.condition)) {
return `multiple conditions using "${condition.condition}"`;
}
return `${condition.condition} condition`;
};

View File

@ -17,7 +17,7 @@ export interface DeviceAction extends DeviceAutomation {
}
export interface DeviceCondition extends DeviceAutomation {
condition: string;
condition: "device";
}
export interface DeviceTrigger extends DeviceAutomation {

View File

@ -38,6 +38,8 @@ export class HaAutomationTracePathDetails extends LitElement {
@property() public logbookEntries!: LogbookEntry[];
@property() renderedNodes: Record<string, any> = {};
@property() public trackedNodes!: Record<string, any>;
@state() private _view: "config" | "changed_variables" | "logbook" = "config";
@ -99,12 +101,12 @@ export class HaAutomationTracePathDetails extends LitElement {
const parts: TemplateResult[][] = [];
let active = false;
const childConditionsPrefix = `${this.selected.path}/conditions/`;
for (const curPath of Object.keys(this.trace.trace)) {
// Include all child conditions too
// Include all trace results until the next rendered node.
// Rendered nodes also include non-chosen choose paths.
if (active) {
if (!curPath.startsWith(childConditionsPrefix)) {
if (curPath in this.renderedNodes) {
break;
}
} else if (curPath === this.selected.path) {
@ -129,9 +131,7 @@ export class HaAutomationTracePathDetails extends LitElement {
return html`
${curPath === this.selected.path
? ""
: html`<h2>
Condition ${curPath.substr(childConditionsPrefix.length)}
</h2>`}
: html`<h2>${curPath.substr(this.selected.path.length + 1)}</h2>`}
${data.length === 1 ? "" : html`<h3>Iteration ${idx + 1}</h3>`}
Executed:
${formatDateTimeWithSeconds(

View File

@ -81,9 +81,9 @@ export class HaAutomationTrace extends LitElement {
? this.hass.states[this._entityId]
: undefined;
const trackedNodes = this.shadowRoot!.querySelector(
"hat-script-graph"
)?.getTrackedNodes();
const graph = this.shadowRoot!.querySelector("hat-script-graph");
const trackedNodes = graph?.trackedNodes;
const renderedNodes = graph?.renderedNodes;
const title = stateObj?.attributes.friendly_name || this._entityId;
@ -234,6 +234,7 @@ export class HaAutomationTrace extends LitElement {
.selected=${this._selected}
.logbookEntries=${this._logbookEntries}
.trackedNodes=${trackedNodes}
.renderedNodes=${renderedNodes}
></ha-automation-trace-path-details>
`
: this._view === "config"
@ -442,9 +443,8 @@ export class HaAutomationTrace extends LitElement {
private _timelinePathPicked(ev) {
const path = ev.detail.value;
const nodes = this.shadowRoot!.querySelector(
"hat-script-graph"
)!.getTrackedNodes();
const nodes = this.shadowRoot!.querySelector("hat-script-graph")!
.trackedNodes;
if (nodes[path]) {
this._selected = nodes[path];
}