@memberjunction/ng-task-graph-editor 6.1.0-edge.2 → 6.1.0-edge.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +180 -4
- package/README.md +197 -0
- package/dist/lib/debug-variables.d.ts +27 -0
- package/dist/lib/debug-variables.d.ts.map +1 -0
- package/dist/lib/debug-variables.js +96 -0
- package/dist/lib/debug-variables.js.map +1 -0
- package/dist/lib/pane-split.d.ts +11 -0
- package/dist/lib/pane-split.d.ts.map +1 -0
- package/dist/lib/pane-split.js +36 -0
- package/dist/lib/pane-split.js.map +1 -0
- package/dist/lib/task-graph-canvas-adapter.d.ts +41 -3
- package/dist/lib/task-graph-canvas-adapter.d.ts.map +1 -1
- package/dist/lib/task-graph-canvas-adapter.js +175 -36
- package/dist/lib/task-graph-canvas-adapter.js.map +1 -1
- package/dist/lib/task-graph-debug-toolbar.component.d.ts +27 -0
- package/dist/lib/task-graph-debug-toolbar.component.d.ts.map +1 -0
- package/dist/lib/task-graph-debug-toolbar.component.js +153 -0
- package/dist/lib/task-graph-debug-toolbar.component.js.map +1 -0
- package/dist/lib/task-graph-debugger.component.d.ts +96 -0
- package/dist/lib/task-graph-debugger.component.d.ts.map +1 -0
- package/dist/lib/task-graph-debugger.component.js +371 -0
- package/dist/lib/task-graph-debugger.component.js.map +1 -0
- package/dist/lib/task-graph-editor.component.d.ts +40 -3
- package/dist/lib/task-graph-editor.component.d.ts.map +1 -1
- package/dist/lib/task-graph-editor.component.js +83 -10
- package/dist/lib/task-graph-editor.component.js.map +1 -1
- package/dist/lib/task-graph-editor.module.d.ts +9 -5
- package/dist/lib/task-graph-editor.module.d.ts.map +1 -1
- package/dist/lib/task-graph-editor.module.js +52 -5
- package/dist/lib/task-graph-editor.module.js.map +1 -1
- package/dist/lib/task-graph-run-prefs.d.ts +34 -0
- package/dist/lib/task-graph-run-prefs.d.ts.map +1 -0
- package/dist/lib/task-graph-run-prefs.js +67 -0
- package/dist/lib/task-graph-run-prefs.js.map +1 -0
- package/dist/lib/task-graph-run-view.component.d.ts +180 -3
- package/dist/lib/task-graph-run-view.component.d.ts.map +1 -1
- package/dist/lib/task-graph-run-view.component.js +560 -23
- package/dist/lib/task-graph-run-view.component.js.map +1 -1
- package/dist/lib/task-graph-runtime-source.d.ts +7 -1
- package/dist/lib/task-graph-runtime-source.d.ts.map +1 -1
- package/dist/lib/task-graph-runtime-source.js +14 -2
- package/dist/lib/task-graph-runtime-source.js.map +1 -1
- package/dist/lib/task-graph-variables.component.d.ts +23 -0
- package/dist/lib/task-graph-variables.component.d.ts.map +1 -0
- package/dist/lib/task-graph-variables.component.js +192 -0
- package/dist/lib/task-graph-variables.component.js.map +1 -0
- package/dist/lib/workflow-debug-host.d.ts +23 -0
- package/dist/lib/workflow-debug-host.d.ts.map +1 -0
- package/dist/lib/workflow-debug-host.js +101 -0
- package/dist/lib/workflow-debug-host.js.map +1 -0
- package/dist/public-api.d.ts +7 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +7 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +11 -10
|
@@ -16,14 +16,20 @@
|
|
|
16
16
|
*
|
|
17
17
|
* @module @memberjunction/ng-task-graph-editor
|
|
18
18
|
*/
|
|
19
|
-
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, } from '@angular/core';
|
|
19
|
+
import { ChangeDetectionStrategy, Component, EventEmitter, HostListener, Input, Output, } from '@angular/core';
|
|
20
20
|
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
21
21
|
import { LogError, RunView } from '@memberjunction/core';
|
|
22
|
+
import { UUIDsEqual } from '@memberjunction/global';
|
|
23
|
+
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
24
|
+
import { ToPaneSizePair } from './pane-split';
|
|
25
|
+
import { TaskGraphRunPrefsStore } from './task-graph-run-prefs';
|
|
22
26
|
import { GraphLayoutBounds, LayoutGraphNodes, ProjectTaskRowsToSpec, } from '@memberjunction/ai-core-plus';
|
|
23
|
-
import { BuildRuntimeStatus } from './task-graph-runtime-source';
|
|
27
|
+
import { BuildRuntimeStatus, IsRuntimeSettled, NormalizeRuntimeState } from './task-graph-runtime-source';
|
|
24
28
|
import * as i0 from "@angular/core";
|
|
25
29
|
import * as i1 from "@memberjunction/ng-ui-components";
|
|
26
|
-
import * as i2 from "
|
|
30
|
+
import * as i2 from "angular-split";
|
|
31
|
+
import * as i3 from "./task-graph-variables.component";
|
|
32
|
+
import * as i4 from "./task-graph-editor.component";
|
|
27
33
|
function TaskGraphRunViewComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
28
34
|
i0.ɵɵelement(0, "mj-alert", 0);
|
|
29
35
|
} if (rf & 2) {
|
|
@@ -39,7 +45,7 @@ function TaskGraphRunViewComponent_Conditional_2_Template(rf, ctx) { if (rf & 1)
|
|
|
39
45
|
i0.ɵɵelement(0, "mj-empty-state", 2);
|
|
40
46
|
} }
|
|
41
47
|
function TaskGraphRunViewComponent_Conditional_3_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
42
|
-
i0.ɵɵelementStart(0, "span",
|
|
48
|
+
i0.ɵɵelementStart(0, "span", 7);
|
|
43
49
|
i0.ɵɵtext(1);
|
|
44
50
|
i0.ɵɵelementEnd();
|
|
45
51
|
} if (rf & 2) {
|
|
@@ -47,26 +53,114 @@ function TaskGraphRunViewComponent_Conditional_3_Conditional_4_Template(rf, ctx)
|
|
|
47
53
|
i0.ɵɵadvance();
|
|
48
54
|
i0.ɵɵtextInterpolate1("", ctx_r0.SkippedCount, " not taken");
|
|
49
55
|
} }
|
|
56
|
+
function TaskGraphRunViewComponent_Conditional_3_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
57
|
+
i0.ɵɵelementStart(0, "span", 8);
|
|
58
|
+
i0.ɵɵtext(1, "Finished");
|
|
59
|
+
i0.ɵɵelementEnd();
|
|
60
|
+
} }
|
|
61
|
+
function TaskGraphRunViewComponent_Conditional_3_Conditional_6_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
62
|
+
i0.ɵɵtext(0);
|
|
63
|
+
} if (rf & 2) {
|
|
64
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
65
|
+
i0.ɵɵtextInterpolate1(" Waiting on ", ctx_r0.WaitingStepName, " ");
|
|
66
|
+
} }
|
|
67
|
+
function TaskGraphRunViewComponent_Conditional_3_Conditional_6_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
68
|
+
i0.ɵɵtext(0, " Waiting to start \u2014 Continue or Step ");
|
|
69
|
+
} }
|
|
70
|
+
function TaskGraphRunViewComponent_Conditional_3_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
71
|
+
i0.ɵɵelementStart(0, "span", 9);
|
|
72
|
+
i0.ɵɵconditionalCreate(1, TaskGraphRunViewComponent_Conditional_3_Conditional_6_Conditional_1_Template, 1, 1)(2, TaskGraphRunViewComponent_Conditional_3_Conditional_6_Conditional_2_Template, 1, 0);
|
|
73
|
+
i0.ɵɵelementEnd();
|
|
74
|
+
} if (rf & 2) {
|
|
75
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
76
|
+
i0.ɵɵadvance();
|
|
77
|
+
i0.ɵɵconditional(ctx_r0.PausedAtTaskID ? 1 : 2);
|
|
78
|
+
} }
|
|
79
|
+
function TaskGraphRunViewComponent_Conditional_3_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
80
|
+
i0.ɵɵelementStart(0, "span", 10);
|
|
81
|
+
i0.ɵɵtext(1);
|
|
82
|
+
i0.ɵɵelementEnd();
|
|
83
|
+
} if (rf & 2) {
|
|
84
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
85
|
+
i0.ɵɵadvance();
|
|
86
|
+
i0.ɵɵtextInterpolate1("", ctx_r0.RunningCount, " running");
|
|
87
|
+
} }
|
|
88
|
+
function TaskGraphRunViewComponent_Conditional_3_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
89
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
90
|
+
i0.ɵɵelementStart(0, "button", 23);
|
|
91
|
+
i0.ɵɵlistener("click", function TaskGraphRunViewComponent_Conditional_3_Conditional_8_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OnToggleSelectedBreakpoint()); });
|
|
92
|
+
i0.ɵɵelement(1, "i", 24);
|
|
93
|
+
i0.ɵɵelementEnd();
|
|
94
|
+
i0.ɵɵelementStart(2, "span", 25);
|
|
95
|
+
i0.ɵɵtext(3);
|
|
96
|
+
i0.ɵɵelementEnd();
|
|
97
|
+
} if (rf & 2) {
|
|
98
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
99
|
+
i0.ɵɵclassProp("run-view-bp-on", ctx_r0.HasSelectedBreakpoint);
|
|
100
|
+
i0.ɵɵproperty("title", ctx_r0.HasSelectedBreakpoint ? "Remove breakpoint" : "Break before this step");
|
|
101
|
+
i0.ɵɵattribute("aria-pressed", ctx_r0.HasSelectedBreakpoint)("aria-label", ctx_r0.HasSelectedBreakpoint ? "Remove breakpoint from " + ctx_r0.SelectedTaskName : "Add breakpoint on " + ctx_r0.SelectedTaskName);
|
|
102
|
+
i0.ɵɵadvance();
|
|
103
|
+
i0.ɵɵclassProp("fa-solid", ctx_r0.HasSelectedBreakpoint)("fa-regular", !ctx_r0.HasSelectedBreakpoint);
|
|
104
|
+
i0.ɵɵadvance(2);
|
|
105
|
+
i0.ɵɵtextInterpolate(ctx_r0.SelectedTaskName);
|
|
106
|
+
} }
|
|
107
|
+
function TaskGraphRunViewComponent_Conditional_3_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
108
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
109
|
+
i0.ɵɵelementStart(0, "button", 26);
|
|
110
|
+
i0.ɵɵlistener("click", function TaskGraphRunViewComponent_Conditional_3_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OnToggleInvocation()); });
|
|
111
|
+
i0.ɵɵelement(1, "i", 27);
|
|
112
|
+
i0.ɵɵelementStart(2, "span");
|
|
113
|
+
i0.ɵɵtext(3, "Data");
|
|
114
|
+
i0.ɵɵelementEnd()();
|
|
115
|
+
} }
|
|
50
116
|
function TaskGraphRunViewComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
51
117
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
52
|
-
i0.ɵɵelementStart(0, "div",
|
|
118
|
+
i0.ɵɵelementStart(0, "div", 4)(1, "div", 5)(2, "span", 6);
|
|
53
119
|
i0.ɵɵtext(3);
|
|
54
120
|
i0.ɵɵelementEnd();
|
|
55
|
-
i0.ɵɵconditionalCreate(4, TaskGraphRunViewComponent_Conditional_3_Conditional_4_Template, 2, 1, "span",
|
|
121
|
+
i0.ɵɵconditionalCreate(4, TaskGraphRunViewComponent_Conditional_3_Conditional_4_Template, 2, 1, "span", 7);
|
|
122
|
+
i0.ɵɵconditionalCreate(5, TaskGraphRunViewComponent_Conditional_3_Conditional_5_Template, 2, 0, "span", 8)(6, TaskGraphRunViewComponent_Conditional_3_Conditional_6_Template, 3, 1, "span", 9)(7, TaskGraphRunViewComponent_Conditional_3_Conditional_7_Template, 2, 1, "span", 10);
|
|
123
|
+
i0.ɵɵconditionalCreate(8, TaskGraphRunViewComponent_Conditional_3_Conditional_8_Template, 4, 10);
|
|
124
|
+
i0.ɵɵelementEnd();
|
|
125
|
+
i0.ɵɵelementStart(9, "div", 11);
|
|
126
|
+
i0.ɵɵconditionalCreate(10, TaskGraphRunViewComponent_Conditional_3_Conditional_10_Template, 4, 0, "button", 12);
|
|
127
|
+
i0.ɵɵelementStart(11, "as-split", 13);
|
|
128
|
+
i0.ɵɵlistener("dragEnd", function TaskGraphRunViewComponent_Conditional_3_Template_as_split_dragEnd_11_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnInvocationSplitDragEnd($event.sizes)); });
|
|
129
|
+
i0.ɵɵelementStart(12, "as-split-area", 14)(13, "div", 15)(14, "div", 16)(15, "span");
|
|
130
|
+
i0.ɵɵtext(16, "Data");
|
|
56
131
|
i0.ɵɵelementEnd();
|
|
57
|
-
i0.ɵɵelementStart(
|
|
58
|
-
i0.ɵɵlistener("
|
|
59
|
-
i0.ɵɵ
|
|
132
|
+
i0.ɵɵelementStart(17, "button", 17);
|
|
133
|
+
i0.ɵɵlistener("click", function TaskGraphRunViewComponent_Conditional_3_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnToggleInvocation()); });
|
|
134
|
+
i0.ɵɵelement(18, "i", 18);
|
|
135
|
+
i0.ɵɵelementEnd()();
|
|
136
|
+
i0.ɵɵelement(19, "mj-task-graph-variables", 19);
|
|
137
|
+
i0.ɵɵelementEnd()();
|
|
138
|
+
i0.ɵɵelementStart(20, "as-split-area", 20)(21, "div", 21)(22, "mj-task-graph-editor", 22);
|
|
139
|
+
i0.ɵɵlistener("SelectionChanged", function TaskGraphRunViewComponent_Conditional_3_Template_mj_task_graph_editor_SelectionChanged_22_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnSelectionChanged($event)); })("ConnectionSelected", function TaskGraphRunViewComponent_Conditional_3_Template_mj_task_graph_editor_ConnectionSelected_22_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnConnectionSelected($event)); })("LegendToggled", function TaskGraphRunViewComponent_Conditional_3_Template_mj_task_graph_editor_LegendToggled_22_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.LegendToggled.emit($event)); })("BeforeContextMenu", function TaskGraphRunViewComponent_Conditional_3_Template_mj_task_graph_editor_BeforeContextMenu_22_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnBeforeContextMenu($event)); })("AfterContextMenuAction", function TaskGraphRunViewComponent_Conditional_3_Template_mj_task_graph_editor_AfterContextMenuAction_22_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnAfterContextMenuAction($event)); });
|
|
140
|
+
i0.ɵɵelementEnd()()()()()();
|
|
60
141
|
} if (rf & 2) {
|
|
61
142
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
143
|
+
i0.ɵɵstyleProp("height", ctx_r0.Height);
|
|
62
144
|
i0.ɵɵadvance(3);
|
|
63
145
|
i0.ɵɵtextInterpolate2("", ctx_r0.CompletedCount, " of ", ctx_r0.TotalCount, " complete");
|
|
64
146
|
i0.ɵɵadvance();
|
|
65
147
|
i0.ɵɵconditional(ctx_r0.SkippedCount > 0 ? 4 : -1);
|
|
66
148
|
i0.ɵɵadvance();
|
|
67
|
-
i0.ɵɵ
|
|
149
|
+
i0.ɵɵconditional(ctx_r0.IsSettled ? 5 : ctx_r0.GraphPaused ? 6 : ctx_r0.RunningCount > 0 ? 7 : -1);
|
|
150
|
+
i0.ɵɵadvance(3);
|
|
151
|
+
i0.ɵɵconditional(ctx_r0.AllowBreakpointEditing && ctx_r0.SelectedTaskID ? 8 : -1);
|
|
152
|
+
i0.ɵɵadvance(2);
|
|
153
|
+
i0.ɵɵconditional(ctx_r0.ShowVariables && !ctx_r0.Prefs.InvocationOpen ? 10 : -1);
|
|
154
|
+
i0.ɵɵadvance();
|
|
155
|
+
i0.ɵɵproperty("gutterSize", 8);
|
|
68
156
|
i0.ɵɵadvance();
|
|
69
|
-
i0.ɵɵproperty("
|
|
157
|
+
i0.ɵɵproperty("size", ctx_r0.InvocationPaneSize)("minSize", 14)("visible", ctx_r0.InvocationPaneOpen);
|
|
158
|
+
i0.ɵɵadvance(7);
|
|
159
|
+
i0.ɵɵproperty("InputPayload", ctx_r0.SelectedTask == null ? null : ctx_r0.SelectedTask.InputPayload)("OutputPayload", ctx_r0.SelectedTask == null ? null : ctx_r0.SelectedTask.OutputPayload)("Invocation", ctx_r0.Invocation);
|
|
160
|
+
i0.ɵɵadvance();
|
|
161
|
+
i0.ɵɵproperty("size", ctx_r0.CanvasPaneSize)("minSize", 40);
|
|
162
|
+
i0.ɵɵadvance(2);
|
|
163
|
+
i0.ɵɵproperty("Spec", ctx_r0.Spec)("RuntimeStatus", ctx_r0.RuntimeStatus)("NodePositions", ctx_r0.Positions)("DebugOverlay", ctx_r0.Overlay)("ReadOnly", true)("ShowToolbar", ctx_r0.ShowToolbar)("ToolbarVisibility", ctx_r0.ToolbarVisibility)("ToolbarAlign", ctx_r0.ToolbarAlign)("ShowPalette", false)("ShowProperties", false)("ShowMinimap", false)("ShowStatusBar", false)("ShowLegend", ctx_r0.ShowLegend);
|
|
70
164
|
} }
|
|
71
165
|
/** Statuses at which a graph has stopped moving, so polling can stop with it. */
|
|
72
166
|
const SETTLED = new Set(['Complete', 'Failed', 'Cancelled', 'Skipped']);
|
|
@@ -82,6 +176,7 @@ export class TaskGraphRunViewComponent extends BaseAngularComponent {
|
|
|
82
176
|
if (value === this.parentTaskID)
|
|
83
177
|
return;
|
|
84
178
|
this.parentTaskID = value;
|
|
179
|
+
this.settledEmitted = false;
|
|
85
180
|
void this.load();
|
|
86
181
|
}
|
|
87
182
|
get ParentTaskID() {
|
|
@@ -100,9 +195,136 @@ export class TaskGraphRunViewComponent extends BaseAngularComponent {
|
|
|
100
195
|
PollIntervalSeconds = 3;
|
|
101
196
|
/** Height of the canvas. Hosts embed this in very different amounts of space. */
|
|
102
197
|
Height = '320px';
|
|
198
|
+
/**
|
|
199
|
+
* Whether the canvas legend shows. **Off by default here**, unlike the editor.
|
|
200
|
+
*
|
|
201
|
+
* The legend explains the authoring vocabulary — what a conditional edge means, what a duplicate
|
|
202
|
+
* default looks like. That is what someone drawing a graph needs. A run view answers a different
|
|
203
|
+
* question, "what happened", which the legend helps with not at all while covering a corner of
|
|
204
|
+
* the canvas the graph is usually occupying.
|
|
205
|
+
*/
|
|
206
|
+
ShowLegend = false;
|
|
207
|
+
/**
|
|
208
|
+
* Whether the canvas toolbar rides above the graph.
|
|
209
|
+
*
|
|
210
|
+
* Debug and other run hosts leave this on and set `ToolbarVisibility` to `minimized` so the
|
|
211
|
+
* graph is the picture, not a floating tool strip. The chip in the corner restores the bar.
|
|
212
|
+
*/
|
|
213
|
+
ShowToolbar = true;
|
|
214
|
+
ToolbarVisibility = 'minimized';
|
|
215
|
+
ToolbarAlign = 'left';
|
|
216
|
+
/**
|
|
217
|
+
* The latest live dispatcher frame, handed in by the host.
|
|
218
|
+
*
|
|
219
|
+
* The host owns the subscription (`GraphQLDataProvider.TaskGraphFrames` or anything shaped like
|
|
220
|
+
* it) and binds each arrival here; the widget folds it into the overlay. Frames are advisory —
|
|
221
|
+
* a task frame patches the node's status in place for sub-second feedback, and the frames that
|
|
222
|
+
* imply CASCADES (a skip, a block, settlement) trigger a debounced row reload, because the
|
|
223
|
+
* dispatcher's propagation writes rows this component cannot infer from one frame. Rows remain
|
|
224
|
+
* the truth; the existing poll (if enabled) remains the safety net.
|
|
225
|
+
*/
|
|
226
|
+
set LiveFrame(frame) {
|
|
227
|
+
if (!frame)
|
|
228
|
+
return;
|
|
229
|
+
this.foldFrame(frame);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Replay: render the run as it stood at this moment, reconstructed from each step's
|
|
233
|
+
* `StartedAt`/`CompletedAt`. Null (the default) renders the present. A step that had not
|
|
234
|
+
* started reads Pending; one mid-flight reads In Progress; one already finished reads its
|
|
235
|
+
* final status — the same three answers the rows would have given a viewer at that time.
|
|
236
|
+
*/
|
|
237
|
+
set ReplayAt(value) {
|
|
238
|
+
if (value?.getTime() === this.replayAt?.getTime())
|
|
239
|
+
return;
|
|
240
|
+
this.replayAt = value;
|
|
241
|
+
this.applyReplay();
|
|
242
|
+
}
|
|
243
|
+
get ReplayAt() {
|
|
244
|
+
return this.replayAt;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Armed breakpoint task IDs, from the parent row's `$.debug.breakpoints`. Empty by default so
|
|
248
|
+
* embeds (agent-run timeline, test harness) never grow debugger chrome they did not ask for.
|
|
249
|
+
*/
|
|
250
|
+
set Breakpoints(value) {
|
|
251
|
+
this.breakpoints = value ?? [];
|
|
252
|
+
this.rebuildOverlay();
|
|
253
|
+
}
|
|
254
|
+
get Breakpoints() {
|
|
255
|
+
return this.breakpoints;
|
|
256
|
+
}
|
|
257
|
+
/** The step a breakpoint actually stopped on. */
|
|
258
|
+
set PausedAtTaskID(value) {
|
|
259
|
+
this.pausedAtTaskID = value;
|
|
260
|
+
if (value)
|
|
261
|
+
this.SelectedTaskID = value;
|
|
262
|
+
this.rebuildOverlay();
|
|
263
|
+
}
|
|
264
|
+
get PausedAtTaskID() {
|
|
265
|
+
return this.pausedAtTaskID;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* The graph is claim-gated. Combined with `PausedAtTaskID` so start-paused (no specific
|
|
269
|
+
* step yet) can still light the entry node as waiting.
|
|
270
|
+
*/
|
|
271
|
+
set GraphPaused(value) {
|
|
272
|
+
this.graphPaused = value;
|
|
273
|
+
this.rebuildOverlay();
|
|
274
|
+
}
|
|
275
|
+
get GraphPaused() {
|
|
276
|
+
return this.graphPaused;
|
|
277
|
+
}
|
|
278
|
+
/** Operator-forced edge verdicts, keyed by `MJ: Task Dependencies` row ID. */
|
|
279
|
+
set EdgeOverrides(value) {
|
|
280
|
+
this.edgeOverrides = value ?? {};
|
|
281
|
+
this.rebuildOverlay();
|
|
282
|
+
}
|
|
283
|
+
get EdgeOverrides() {
|
|
284
|
+
return this.edgeOverrides;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Whether this host may arm/disarm breakpoints from the selected-step control.
|
|
288
|
+
* Off by default — the run view also renders where those controls would be wrong.
|
|
289
|
+
*/
|
|
290
|
+
AllowBreakpointEditing = false;
|
|
291
|
+
/** Compact debug key under the summary line. Off unless the host is a debugger. */
|
|
292
|
+
ShowDebugLegend = false;
|
|
293
|
+
/** VS Code VARIABLES pane to the left of the canvas. Off unless the host is debugging. */
|
|
294
|
+
ShowVariables = false;
|
|
295
|
+
/** The parent bag's `data` / `context` roots, for the Invocation scope. */
|
|
296
|
+
Invocation = null;
|
|
103
297
|
NodeSelected = new EventEmitter();
|
|
298
|
+
/** The legend was toggled from the toolbar, so a host can remember the choice. */
|
|
299
|
+
LegendToggled = new EventEmitter();
|
|
104
300
|
/** Emitted once, when every step has reached a terminal status. */
|
|
105
301
|
Settled = new EventEmitter();
|
|
302
|
+
/** A connection was clicked. `EdgeID` is the dependency row id when the projection carried one. */
|
|
303
|
+
ConnectionSelected = new EventEmitter();
|
|
304
|
+
/** Intent only — the host owns `SetBreakpoints`. */
|
|
305
|
+
BreakpointToggled = new EventEmitter();
|
|
306
|
+
/** Intent only — the host owns `OverrideEdge`. */
|
|
307
|
+
EdgeOverrideRequested = new EventEmitter();
|
|
308
|
+
/** What each running step says it is doing, from `NodeProgress` frames. Keyed by task row id. */
|
|
309
|
+
LiveActivity = new Map();
|
|
310
|
+
/** The last step the person selected, so the breakpoint control has a target. */
|
|
311
|
+
SelectedTaskID = null;
|
|
312
|
+
/** Stable overlay object — rebuilt only when debug inputs change, so the editor does not re-project every CD cycle. */
|
|
313
|
+
Overlay = { showConditions: true };
|
|
314
|
+
breakpoints = [];
|
|
315
|
+
pausedAtTaskID = null;
|
|
316
|
+
graphPaused = false;
|
|
317
|
+
edgeOverrides = {};
|
|
318
|
+
/** `Settled` is once-per-parent — a finished poll must not re-fire the host. */
|
|
319
|
+
settledEmitted = false;
|
|
320
|
+
/** Left data pane + split sizes. One JSON bag in `MJ: User Settings`. */
|
|
321
|
+
get Prefs() {
|
|
322
|
+
return this.prefsStore.Value;
|
|
323
|
+
}
|
|
324
|
+
prefsStore = new TaskGraphRunPrefsStore({
|
|
325
|
+
Get: () => undefined,
|
|
326
|
+
Set: () => { },
|
|
327
|
+
});
|
|
106
328
|
Spec = null;
|
|
107
329
|
RuntimeStatus = null;
|
|
108
330
|
Positions = new Map();
|
|
@@ -111,25 +333,69 @@ export class TaskGraphRunViewComponent extends BaseAngularComponent {
|
|
|
111
333
|
/** Rows by id, so a selection event can hand the host the whole task rather than an id. */
|
|
112
334
|
taskByID = new Map();
|
|
113
335
|
parentTaskID = null;
|
|
336
|
+
replayAt = null;
|
|
114
337
|
pollTimer = null;
|
|
338
|
+
frameReloadTimer = null;
|
|
115
339
|
destroyed = false;
|
|
116
340
|
constructor(cdr) {
|
|
117
341
|
super();
|
|
118
342
|
this.cdr = cdr;
|
|
343
|
+
try {
|
|
344
|
+
this.prefsStore = new TaskGraphRunPrefsStore({
|
|
345
|
+
Get: (key) => UserInfoEngine.Instance.GetSetting(key),
|
|
346
|
+
Set: (key, value) => UserInfoEngine.Instance.SetSettingDebounced(key, value),
|
|
347
|
+
});
|
|
348
|
+
this.prefsStore.Restore();
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
// Engine not configured yet (unit tests, pre-bootstrap) — keep the default.
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
get InvocationPaneOpen() {
|
|
355
|
+
return this.ShowVariables && this.Prefs.InvocationOpen;
|
|
356
|
+
}
|
|
357
|
+
get InvocationPaneSize() {
|
|
358
|
+
return this.InvocationPaneOpen ? this.Prefs.InvocationSplit[0] : 0;
|
|
359
|
+
}
|
|
360
|
+
get CanvasPaneSize() {
|
|
361
|
+
return this.InvocationPaneOpen ? this.Prefs.InvocationSplit[1] : 100;
|
|
362
|
+
}
|
|
363
|
+
OnToggleInvocation() {
|
|
364
|
+
this.prefsStore.SetInvocationOpen(!this.Prefs.InvocationOpen);
|
|
365
|
+
this.cdr.markForCheck();
|
|
366
|
+
}
|
|
367
|
+
OnInvocationSplitDragEnd(sizes) {
|
|
368
|
+
const pair = ToPaneSizePair(sizes);
|
|
369
|
+
if (!pair)
|
|
370
|
+
return;
|
|
371
|
+
this.prefsStore.SetInvocationSplit(pair);
|
|
372
|
+
this.cdr.markForCheck();
|
|
119
373
|
}
|
|
120
374
|
ngOnDestroy() {
|
|
121
375
|
this.destroyed = true;
|
|
122
376
|
this.stopPolling();
|
|
377
|
+
if (this.frameReloadTimer) {
|
|
378
|
+
clearTimeout(this.frameReloadTimer);
|
|
379
|
+
this.frameReloadTimer = null;
|
|
380
|
+
}
|
|
123
381
|
}
|
|
124
|
-
/** Steps in a terminal state, for the host's summary line. */
|
|
382
|
+
/** Steps in a terminal state, for the host's summary line. Uses the same map the canvas paints. */
|
|
125
383
|
get CompletedCount() {
|
|
126
|
-
return
|
|
384
|
+
return this.countRuntime('Complete');
|
|
127
385
|
}
|
|
128
386
|
get TotalCount() {
|
|
129
|
-
return this.taskByID.size;
|
|
387
|
+
return this.Spec?.tasks.length ?? this.taskByID.size;
|
|
130
388
|
}
|
|
131
389
|
get SkippedCount() {
|
|
132
|
-
return
|
|
390
|
+
return this.countRuntime('Skipped');
|
|
391
|
+
}
|
|
392
|
+
get RunningCount() {
|
|
393
|
+
return this.countRuntime('In Progress');
|
|
394
|
+
}
|
|
395
|
+
get IsSettled() {
|
|
396
|
+
if (!this.Spec || this.Spec.tasks.length === 0)
|
|
397
|
+
return false;
|
|
398
|
+
return IsRuntimeSettled(this.RuntimeStatus ?? {}, this.Spec.tasks.map((t) => t.tempId));
|
|
133
399
|
}
|
|
134
400
|
/**
|
|
135
401
|
* A node was selected on the canvas.
|
|
@@ -142,7 +408,142 @@ export class TaskGraphRunViewComponent extends BaseAngularComponent {
|
|
|
142
408
|
const tempId = args?.Task?.tempId;
|
|
143
409
|
if (!tempId)
|
|
144
410
|
return;
|
|
411
|
+
this.SelectedTaskID = tempId;
|
|
145
412
|
this.NodeSelected.emit({ TaskID: tempId, Task: this.taskByID.get(tempId) ?? null });
|
|
413
|
+
this.cdr.markForCheck();
|
|
414
|
+
}
|
|
415
|
+
OnConnectionSelected(connection) {
|
|
416
|
+
if (!connection) {
|
|
417
|
+
this.ConnectionSelected.emit({ EdgeID: null, FromTaskID: '', ToTaskID: '' });
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const data = connection.Data ?? {};
|
|
421
|
+
const edgeID = typeof data['EdgeID'] === 'string' ? data['EdgeID'] : null;
|
|
422
|
+
const from = typeof data['FromTempId'] === 'string' ? data['FromTempId'] : connection.SourceNodeID;
|
|
423
|
+
const to = typeof data['ToTempId'] === 'string' ? data['ToTempId'] : connection.TargetNodeID;
|
|
424
|
+
this.ConnectionSelected.emit({
|
|
425
|
+
EdgeID: edgeID,
|
|
426
|
+
FromTaskID: from,
|
|
427
|
+
ToTaskID: to,
|
|
428
|
+
Condition: connection.Condition,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
countRuntime(state) {
|
|
432
|
+
if (!this.RuntimeStatus) {
|
|
433
|
+
return [...this.taskByID.values()].filter((t) => NormalizeRuntimeState(t.Status) === state).length;
|
|
434
|
+
}
|
|
435
|
+
return Object.values(this.RuntimeStatus).filter((s) => s === state).length;
|
|
436
|
+
}
|
|
437
|
+
get HasSelectedBreakpoint() {
|
|
438
|
+
return !!this.SelectedTaskID && this.hasBreakpoint(this.SelectedTaskID);
|
|
439
|
+
}
|
|
440
|
+
get SelectedTaskName() {
|
|
441
|
+
if (!this.SelectedTaskID)
|
|
442
|
+
return '';
|
|
443
|
+
return this.taskByID.get(this.SelectedTaskID)?.Name ?? 'this step';
|
|
444
|
+
}
|
|
445
|
+
get WaitingStepName() {
|
|
446
|
+
if (this.pausedAtTaskID) {
|
|
447
|
+
return this.taskByID.get(this.pausedAtTaskID)?.Name
|
|
448
|
+
?? this.Spec?.tasks.find((t) => t.tempId === this.pausedAtTaskID)?.name
|
|
449
|
+
?? 'this step';
|
|
450
|
+
}
|
|
451
|
+
const entry = this.Spec?.tasks.find((t) => (t.dependsOn?.length ?? 0) === 0);
|
|
452
|
+
return entry?.name ?? 'the first step';
|
|
453
|
+
}
|
|
454
|
+
get SelectedTask() {
|
|
455
|
+
return this.SelectedTaskID ? this.taskByID.get(this.SelectedTaskID) ?? null : null;
|
|
456
|
+
}
|
|
457
|
+
OnToggleSelectedBreakpoint() {
|
|
458
|
+
if (!this.AllowBreakpointEditing || !this.SelectedTaskID)
|
|
459
|
+
return;
|
|
460
|
+
this.BreakpointToggled.emit({
|
|
461
|
+
TaskID: this.SelectedTaskID,
|
|
462
|
+
Enabled: !this.HasSelectedBreakpoint,
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
/** Debug attaches here: replace Edit/Remove with breakpoint / path-override items. */
|
|
466
|
+
OnBeforeContextMenu(event) {
|
|
467
|
+
if (!this.AllowBreakpointEditing) {
|
|
468
|
+
event.Cancel = true;
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (event.Target === 'node' && event.Node) {
|
|
472
|
+
const on = this.hasBreakpoint(event.Node.ID);
|
|
473
|
+
event.Items = [{
|
|
474
|
+
ID: 'toggle-breakpoint',
|
|
475
|
+
Label: on ? 'Remove Breakpoint' : 'Add Breakpoint',
|
|
476
|
+
Icon: 'fa-circle',
|
|
477
|
+
Shortcut: 'F9',
|
|
478
|
+
}];
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
if (event.Target === 'connection' && event.Connection?.Condition?.trim()) {
|
|
482
|
+
const edgeID = typeof event.Connection.Data?.['EdgeID'] === 'string'
|
|
483
|
+
? event.Connection.Data['EdgeID']
|
|
484
|
+
: null;
|
|
485
|
+
if (!edgeID) {
|
|
486
|
+
event.Cancel = true;
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
event.Items = [
|
|
490
|
+
{ ID: 'force-true', Label: 'Take this path', Icon: 'fa-check' },
|
|
491
|
+
{ ID: 'force-false', Label: 'Skip this path', Icon: 'fa-xmark' },
|
|
492
|
+
{ ID: 'force-clear', Label: 'Clear override', Icon: 'fa-rotate-left' },
|
|
493
|
+
];
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
event.Cancel = true;
|
|
497
|
+
}
|
|
498
|
+
OnAfterContextMenuAction(event) {
|
|
499
|
+
if (event.ActionID === 'toggle-breakpoint' && event.Node) {
|
|
500
|
+
this.BreakpointToggled.emit({
|
|
501
|
+
TaskID: event.Node.ID,
|
|
502
|
+
Enabled: !this.hasBreakpoint(event.Node.ID),
|
|
503
|
+
});
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
const edgeID = typeof event.Connection?.Data?.['EdgeID'] === 'string'
|
|
507
|
+
? event.Connection.Data['EdgeID']
|
|
508
|
+
: null;
|
|
509
|
+
if (!edgeID)
|
|
510
|
+
return;
|
|
511
|
+
if (event.ActionID === 'force-true')
|
|
512
|
+
this.EdgeOverrideRequested.emit({ EdgeID: edgeID, Verdict: 'true' });
|
|
513
|
+
if (event.ActionID === 'force-false')
|
|
514
|
+
this.EdgeOverrideRequested.emit({ EdgeID: edgeID, Verdict: 'false' });
|
|
515
|
+
if (event.ActionID === 'force-clear')
|
|
516
|
+
this.EdgeOverrideRequested.emit({ EdgeID: edgeID, Verdict: null });
|
|
517
|
+
}
|
|
518
|
+
hasBreakpoint(taskID) {
|
|
519
|
+
return this.breakpoints.some((id) => UUIDsEqual(id, taskID));
|
|
520
|
+
}
|
|
521
|
+
OnDebugHotkey(event) {
|
|
522
|
+
if (!this.AllowBreakpointEditing)
|
|
523
|
+
return;
|
|
524
|
+
if (isTypingTarget(event.target))
|
|
525
|
+
return;
|
|
526
|
+
if (event.key === 'F9') {
|
|
527
|
+
event.preventDefault();
|
|
528
|
+
this.OnToggleSelectedBreakpoint();
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
rebuildOverlay() {
|
|
532
|
+
this.Overlay = {
|
|
533
|
+
breakpoints: this.breakpoints,
|
|
534
|
+
// A finished graph is not "paused here" — the durable bag can still name the last
|
|
535
|
+
// breakpoint after every step is terminal.
|
|
536
|
+
pausedAtTaskID: this.IsSettled ? null : this.pausedAtTaskID,
|
|
537
|
+
paused: !this.IsSettled && this.graphPaused,
|
|
538
|
+
edgeOverrides: this.edgeOverrides,
|
|
539
|
+
showConditions: true,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
emitSettledOnce() {
|
|
543
|
+
if (this.settledEmitted || !this.IsSettled)
|
|
544
|
+
return;
|
|
545
|
+
this.settledEmitted = true;
|
|
546
|
+
this.Settled.emit();
|
|
146
547
|
}
|
|
147
548
|
/**
|
|
148
549
|
* Reads the graph and projects it onto the canvas.
|
|
@@ -194,10 +595,10 @@ export class TaskGraphRunViewComponent extends BaseAngularComponent {
|
|
|
194
595
|
const taskRows = (tasks.Results ?? []);
|
|
195
596
|
const depRows = (deps.Success ? (deps.Results ?? []) : []);
|
|
196
597
|
this.project(taskRows, depRows);
|
|
598
|
+
this.rebuildOverlay();
|
|
599
|
+
this.emitSettledOnce();
|
|
197
600
|
if (this.LiveUpdates && !this.isSettled(taskRows))
|
|
198
601
|
this.schedulePoll();
|
|
199
|
-
else if (taskRows.length > 0)
|
|
200
|
-
this.Settled.emit();
|
|
201
602
|
}
|
|
202
603
|
catch (e) {
|
|
203
604
|
this.fail(e instanceof Error ? e.message : String(e));
|
|
@@ -216,9 +617,37 @@ export class TaskGraphRunViewComponent extends BaseAngularComponent {
|
|
|
216
617
|
// case where an id match is exact. Name correlation exists for specs whose tempIds were
|
|
217
618
|
// never real, and would be needlessly lossy here.
|
|
218
619
|
const knownIDs = new Set(taskRows.map((t) => t.ID));
|
|
219
|
-
this.RuntimeStatus =
|
|
620
|
+
this.RuntimeStatus = this.replayAt
|
|
621
|
+
? this.statusAt(this.replayAt)
|
|
622
|
+
: BuildRuntimeStatus(taskRows, new Map(), knownIDs);
|
|
220
623
|
this.Positions = this.resolvePositions(projection.AuthoredPositions, taskRows, depRows);
|
|
221
624
|
}
|
|
625
|
+
/** Re-derives the overlay for the current replay position (or the present) from held rows. */
|
|
626
|
+
applyReplay() {
|
|
627
|
+
if (this.taskByID.size === 0)
|
|
628
|
+
return;
|
|
629
|
+
const rows = [...this.taskByID.values()];
|
|
630
|
+
this.RuntimeStatus = this.replayAt
|
|
631
|
+
? this.statusAt(this.replayAt)
|
|
632
|
+
: BuildRuntimeStatus(rows, new Map(), new Set(rows.map((t) => t.ID)));
|
|
633
|
+
this.cdr.markForCheck();
|
|
634
|
+
}
|
|
635
|
+
/** The overlay as it stood at `moment`, from each row's own timestamps. */
|
|
636
|
+
statusAt(moment) {
|
|
637
|
+
const at = moment.getTime();
|
|
638
|
+
const status = {};
|
|
639
|
+
for (const [id, row] of this.taskByID) {
|
|
640
|
+
const started = row.StartedAt?.getTime?.() ?? (row.StartedAt ? new Date(row.StartedAt).getTime() : null);
|
|
641
|
+
const completed = row.CompletedAt?.getTime?.() ?? (row.CompletedAt ? new Date(row.CompletedAt).getTime() : null);
|
|
642
|
+
if (started == null || started > at)
|
|
643
|
+
status[id] = 'Pending';
|
|
644
|
+
else if (completed == null || completed > at)
|
|
645
|
+
status[id] = 'In Progress';
|
|
646
|
+
else
|
|
647
|
+
status[id] = NormalizeRuntimeState(row.Status);
|
|
648
|
+
}
|
|
649
|
+
return status;
|
|
650
|
+
}
|
|
222
651
|
/**
|
|
223
652
|
* The author's arrangement where there is one, a computed layout everywhere else.
|
|
224
653
|
*
|
|
@@ -241,6 +670,67 @@ export class TaskGraphRunViewComponent extends BaseAngularComponent {
|
|
|
241
670
|
isSettled(taskRows) {
|
|
242
671
|
return taskRows.length > 0 && taskRows.every((t) => SETTLED.has(t.Status));
|
|
243
672
|
}
|
|
673
|
+
/**
|
|
674
|
+
* Folds one live frame into the overlay.
|
|
675
|
+
*
|
|
676
|
+
* Direct status frames patch in place — a new `RuntimeStatus` object, because the canvas is
|
|
677
|
+
* OnPush and mutation would render nothing. Frames whose consequences the dispatcher computes
|
|
678
|
+
* across the whole graph (skips cascade, blocks propagate, settlement rolls up) reload the rows
|
|
679
|
+
* instead: inferring a cascade client-side would be a second implementation of the engine's
|
|
680
|
+
* rules, free to drift.
|
|
681
|
+
*/
|
|
682
|
+
foldFrame(frame) {
|
|
683
|
+
switch (frame.kind) {
|
|
684
|
+
case 'TaskStarted':
|
|
685
|
+
case 'TaskCompleted':
|
|
686
|
+
case 'TaskFailed':
|
|
687
|
+
if (frame.taskId && frame.status && this.RuntimeStatus) {
|
|
688
|
+
const row = this.taskByID.get(frame.taskId);
|
|
689
|
+
if (row)
|
|
690
|
+
row.Status = frame.status;
|
|
691
|
+
this.RuntimeStatus = { ...this.RuntimeStatus, [frame.taskId]: NormalizeRuntimeState(frame.status) };
|
|
692
|
+
if (frame.kind !== 'TaskStarted')
|
|
693
|
+
this.LiveActivity.delete(frame.taskId);
|
|
694
|
+
this.rebuildOverlay();
|
|
695
|
+
this.emitSettledOnce();
|
|
696
|
+
this.cdr.markForCheck();
|
|
697
|
+
}
|
|
698
|
+
break;
|
|
699
|
+
case 'NodeProgress':
|
|
700
|
+
if (frame.taskId && frame.progressMessage) {
|
|
701
|
+
this.LiveActivity.set(frame.taskId, { Message: frame.progressMessage, Percent: frame.progressPercent });
|
|
702
|
+
this.cdr.markForCheck();
|
|
703
|
+
}
|
|
704
|
+
break;
|
|
705
|
+
case 'GraphSettled':
|
|
706
|
+
this.scheduleFrameReload();
|
|
707
|
+
// The engine said the graph is done — do not wait for the row reload to tell the host.
|
|
708
|
+
if (!this.settledEmitted) {
|
|
709
|
+
this.settledEmitted = true;
|
|
710
|
+
this.Settled.emit();
|
|
711
|
+
}
|
|
712
|
+
break;
|
|
713
|
+
case 'TaskSkipped':
|
|
714
|
+
case 'TaskBlocked':
|
|
715
|
+
case 'TaskAwaitingHuman':
|
|
716
|
+
case 'GraphResumed':
|
|
717
|
+
this.scheduleFrameReload();
|
|
718
|
+
break;
|
|
719
|
+
default:
|
|
720
|
+
// GateDecision / ClaimChanged / PassCompleted / GraphPaused / BreakpointHit are
|
|
721
|
+
// console-chrome concerns the HOST renders; unknown kinds are a newer server.
|
|
722
|
+
break;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
/** One reload per burst of cascade frames, not one per frame. */
|
|
726
|
+
scheduleFrameReload() {
|
|
727
|
+
if (this.frameReloadTimer)
|
|
728
|
+
return;
|
|
729
|
+
this.frameReloadTimer = setTimeout(() => {
|
|
730
|
+
this.frameReloadTimer = null;
|
|
731
|
+
void this.load();
|
|
732
|
+
}, 250);
|
|
733
|
+
}
|
|
244
734
|
schedulePoll() {
|
|
245
735
|
this.pollTimer = setTimeout(() => void this.load(), Math.max(1, this.PollIntervalSeconds) * 1000);
|
|
246
736
|
}
|
|
@@ -261,15 +751,17 @@ export class TaskGraphRunViewComponent extends BaseAngularComponent {
|
|
|
261
751
|
return { Width: box.Width, Height: box.Height };
|
|
262
752
|
}
|
|
263
753
|
static ɵfac = function TaskGraphRunViewComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TaskGraphRunViewComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
264
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TaskGraphRunViewComponent, selectors: [["mj-task-graph-run-view"]],
|
|
265
|
-
i0.ɵɵ
|
|
754
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TaskGraphRunViewComponent, selectors: [["mj-task-graph-run-view"]], hostBindings: function TaskGraphRunViewComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
755
|
+
i0.ɵɵlistener("keydown", function TaskGraphRunViewComponent_keydown_HostBindingHandler($event) { return ctx.OnDebugHotkey($event); }, i0.ɵɵresolveDocument);
|
|
756
|
+
} }, inputs: { ParentTaskID: "ParentTaskID", WorkflowName: "WorkflowName", LiveUpdates: "LiveUpdates", PollIntervalSeconds: "PollIntervalSeconds", Height: "Height", ShowLegend: "ShowLegend", ShowToolbar: "ShowToolbar", ToolbarVisibility: "ToolbarVisibility", ToolbarAlign: "ToolbarAlign", LiveFrame: "LiveFrame", ReplayAt: "ReplayAt", Breakpoints: "Breakpoints", PausedAtTaskID: "PausedAtTaskID", GraphPaused: "GraphPaused", EdgeOverrides: "EdgeOverrides", AllowBreakpointEditing: "AllowBreakpointEditing", ShowDebugLegend: "ShowDebugLegend", ShowVariables: "ShowVariables", Invocation: "Invocation" }, outputs: { NodeSelected: "NodeSelected", LegendToggled: "LegendToggled", Settled: "Settled", ConnectionSelected: "ConnectionSelected", BreakpointToggled: "BreakpointToggled", EdgeOverrideRequested: "EdgeOverrideRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 1, consts: [["Variant", "error", 3, "Message"], [1, "run-view-loading"], ["Icon", "fa-solid fa-diagram-project", "Title", "No steps yet", "Message", "This workflow has not created any steps."], [1, "run-view", 3, "height"], [1, "run-view"], [1, "run-view-summary"], [1, "run-view-count"], [1, "run-view-skipped"], [1, "run-view-done"], [1, "run-view-waiting"], [1, "run-view-running"], [1, "run-view-body"], ["type", "button", "title", "Show invocation and output", "aria-label", "Show invocation and output", 1, "run-view-vars-rail"], ["direction", "horizontal", "unit", "percent", 1, "run-view-split", 3, "dragEnd", "gutterSize"], [3, "size", "minSize", "visible"], [1, "run-view-vars"], [1, "run-view-vars-bar"], ["type", "button", "title", "Minimize", "aria-label", "Minimize invocation and output", 1, "run-view-vars-min", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-left"], [3, "InputPayload", "OutputPayload", "Invocation"], [3, "size", "minSize"], [1, "run-view-canvas"], [3, "SelectionChanged", "ConnectionSelected", "LegendToggled", "BeforeContextMenu", "AfterContextMenuAction", "Spec", "RuntimeStatus", "NodePositions", "DebugOverlay", "ReadOnly", "ShowToolbar", "ToolbarVisibility", "ToolbarAlign", "ShowPalette", "ShowProperties", "ShowMinimap", "ShowStatusBar", "ShowLegend"], ["type", "button", 1, "run-view-bp", 3, "click", "title"], ["aria-hidden", "true", 1, "fa-circle"], [1, "run-view-bp-name"], ["type", "button", "title", "Show invocation and output", "aria-label", "Show invocation and output", 1, "run-view-vars-rail", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-code"]], template: function TaskGraphRunViewComponent_Template(rf, ctx) { if (rf & 1) {
|
|
757
|
+
i0.ɵɵconditionalCreate(0, TaskGraphRunViewComponent_Conditional_0_Template, 1, 1, "mj-alert", 0)(1, TaskGraphRunViewComponent_Conditional_1_Template, 2, 0, "div", 1)(2, TaskGraphRunViewComponent_Conditional_2_Template, 1, 0, "mj-empty-state", 2)(3, TaskGraphRunViewComponent_Conditional_3_Template, 23, 30, "div", 3);
|
|
266
758
|
} if (rf & 2) {
|
|
267
759
|
i0.ɵɵconditional(ctx.ErrorMessage ? 0 : ctx.IsLoading ? 1 : !ctx.Spec || ctx.Spec.tasks.length === 0 ? 2 : 3);
|
|
268
|
-
} }, dependencies: [i1.MJEmptyStateComponent, i1.MJAlertComponent, i2.TaskGraphEditorComponent], styles: ["[_nghost-%COMP%] { display: block; }\n\n.run-view[_ngcontent-%COMP%] {
|
|
760
|
+
} }, dependencies: [i1.MJEmptyStateComponent, i1.MJAlertComponent, i2.SplitComponent, i2.SplitAreaComponent, i3.TaskGraphVariablesComponent, i4.TaskGraphEditorComponent], styles: ["\n\n\n[_nghost-%COMP%] { display: block; height: 100%; min-height: 0; }\n\n.run-view[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2);\n height: 100%;\n min-height: 0;\n}\n\n.run-view-summary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3);\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n}\n\n.run-view-count[_ngcontent-%COMP%] { font-weight: 500; }\n\n\n\n\n.run-view-skipped[_ngcontent-%COMP%] { color: var(--mj-text-tertiary); }\n.run-view-running[_ngcontent-%COMP%] { color: var(--mj-brand-primary); font-weight: 600; }\n.run-view-waiting[_ngcontent-%COMP%] { color: var(--mj-brand-primary); font-weight: 700; }\n.run-view-done[_ngcontent-%COMP%] { color: var(--mj-status-success); font-weight: 600; }\n\n.run-view-body[_ngcontent-%COMP%] {\n display: flex;\n flex: 1 1 auto;\n min-height: 0;\n min-width: 0;\n}\n\n.run-view-vars-rail[_ngcontent-%COMP%] {\n flex: 0 0 28px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-start;\n gap: var(--mj-space-2);\n padding: var(--mj-space-3) 0;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n.run-view-vars-rail[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n.run-view-vars-rail[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n writing-mode: vertical-rl;\n transform: rotate(180deg);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n font-size: var(--mj-font-size-xs);\n font-weight: 700;\n}\n.run-view-vars-rail[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 11px; }\n\n.run-view-split[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-height: 0;\n min-width: 0;\n}\n\n[_nghost-%COMP%] .run-view-split > .as-split-gutter {\n background: transparent;\n}\n[_nghost-%COMP%] .run-view-split > .as-split-gutter::after {\n content: '';\n display: block;\n margin: auto;\n background: var(--mj-border-default);\n border-radius: 1px;\n}\n[_nghost-%COMP%] .run-view-split.as-horizontal > .as-split-gutter::after {\n width: 3px;\n height: 32px;\n}\n[_nghost-%COMP%] .run-view-split > .as-split-gutter:hover::after {\n background: var(--mj-brand-primary);\n}\n[_nghost-%COMP%] .run-view-split > .as-split-area {\n overflow: hidden;\n}\n\n\n\n\n\n.run-view-canvas[_ngcontent-%COMP%] {\n height: 100%;\n min-height: 0;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.run-view-vars[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n min-width: 0;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n.run-view-vars-bar[_ngcontent-%COMP%] {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n padding: 4px 8px;\n border-bottom: 1px solid var(--mj-border-default);\n color: var(--mj-text-secondary);\n font-size: var(--mj-font-size-xs);\n font-weight: 700;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n.run-view-vars-min[_ngcontent-%COMP%] {\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n border-radius: var(--mj-radius-sm);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n}\n.run-view-vars-min[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n.run-view-vars[_ngcontent-%COMP%] mj-task-graph-variables[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.run-view-loading[_ngcontent-%COMP%] {\n padding: var(--mj-space-4);\n color: var(--mj-text-secondary);\n font-size: var(--mj-font-size-sm);\n}\n\n.run-view-bp[_ngcontent-%COMP%] {\n margin-left: auto;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n}\n.run-view-bp[_ngcontent-%COMP%]:hover { color: var(--mj-status-error); }\n.run-view-bp-on[_ngcontent-%COMP%], \n.run-view-bp-on[_ngcontent-%COMP%]:hover { color: var(--mj-status-error); }\n.run-view-bp[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 10px; }\n.run-view-bp-name[_ngcontent-%COMP%] {\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-muted);\n}\n\n.run-view-legend[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: var(--mj-space-3);\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-muted);\n}\n.run-view-legend[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n.run-view-key-break[_ngcontent-%COMP%] { color: var(--mj-status-error); font-size: 8px; }\n.run-view-key-paused[_ngcontent-%COMP%] { color: var(--mj-brand-primary); font-size: 10px; }\n.run-view-key-forced[_ngcontent-%COMP%] { color: var(--mj-status-warning); font-size: 10px; }\n.run-view-key-if[_ngcontent-%COMP%] {\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-style: italic;\n}"], changeDetection: 0 });
|
|
269
761
|
}
|
|
270
762
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TaskGraphRunViewComponent, [{
|
|
271
763
|
type: Component,
|
|
272
|
-
args: [{ standalone: false, selector: 'mj-task-graph-run-view', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (ErrorMessage) {\n <mj-alert Variant=\"error\" [Message]=\"ErrorMessage\"></mj-alert>\n} @else if (IsLoading) {\n <div class=\"run-view-loading\">Loading the workflow’s steps…</div>\n} @else if (!Spec || Spec.tasks.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-diagram-project\"\n Title=\"No steps yet\"\n Message=\"This workflow has not created any steps.\">\n </mj-empty-state>\n} @else {\n <div class=\"run-view\">\n <div class=\"run-view-summary\">\n <span class=\"run-view-count\">{{ CompletedCount }} of {{ TotalCount }} complete</span>\n @if (SkippedCount > 0) {\n <span class=\"run-view-skipped\">{{ SkippedCount }} not taken</span>\n }\n </div>\n\n <div class=\"run-view-canvas\" [style.height]=\"Height\">\n <mj-task-graph-editor\n [Spec]=\"Spec\"\n [RuntimeStatus]=\"RuntimeStatus\"\n [NodePositions]=\"Positions\"\n [ReadOnly]=\"true\"\n [ShowToolbar]=\"false\"\n [ShowPalette]=\"false\"\n [ShowProperties]=\"false\"\n [ShowMinimap]=\"false\"\n [ShowStatusBar]=\"false\"\n (SelectionChanged)=\"OnSelectionChanged($event)\">\n </mj-task-graph-editor>\n </div>\n </div>\n}\n", styles: [":host { display: block; }\n\n.run-view { display: flex; flex-direction: column; gap: var(--mj-space-2); }\n\n.run-view-summary {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3);\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n}\n\n.run-view-count { font-weight: 500; }\n\n/* Not-taken reads as neutral, never as a failure: a skipped branch is a normal outcome, and\n colouring it like an error sends people hunting for a bug that does not exist. */\n.run-view-skipped { color: var(--mj-text-tertiary); }\n\n.run-view-canvas {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.run-view-loading {\n padding: var(--mj-space-4);\n color: var(--mj-text-secondary);\n font-size: var(--mj-font-size-sm);\n}\n"] }]
|
|
764
|
+
args: [{ standalone: false, selector: 'mj-task-graph-run-view', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (ErrorMessage) {\n <mj-alert Variant=\"error\" [Message]=\"ErrorMessage\"></mj-alert>\n} @else if (IsLoading) {\n <div class=\"run-view-loading\">Loading the workflow’s steps…</div>\n} @else if (!Spec || Spec.tasks.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-diagram-project\"\n Title=\"No steps yet\"\n Message=\"This workflow has not created any steps.\">\n </mj-empty-state>\n} @else {\n <div class=\"run-view\" [style.height]=\"Height\">\n <div class=\"run-view-summary\">\n <span class=\"run-view-count\">{{ CompletedCount }} of {{ TotalCount }} complete</span>\n @if (SkippedCount > 0) {\n <span class=\"run-view-skipped\">{{ SkippedCount }} not taken</span>\n }\n @if (IsSettled) {\n <span class=\"run-view-done\">Finished</span>\n } @else if (GraphPaused) {\n <span class=\"run-view-waiting\">\n @if (PausedAtTaskID) { Waiting on {{ WaitingStepName }} }\n @else { Waiting to start \u2014 Continue or Step }\n </span>\n } @else if (RunningCount > 0) {\n <span class=\"run-view-running\">{{ RunningCount }} running</span>\n }\n @if (AllowBreakpointEditing && SelectedTaskID) {\n <button\n type=\"button\"\n class=\"run-view-bp\"\n [class.run-view-bp-on]=\"HasSelectedBreakpoint\"\n (click)=\"OnToggleSelectedBreakpoint()\"\n [attr.aria-pressed]=\"HasSelectedBreakpoint\"\n [attr.aria-label]=\"HasSelectedBreakpoint ? 'Remove breakpoint from ' + SelectedTaskName : 'Add breakpoint on ' + SelectedTaskName\"\n [title]=\"HasSelectedBreakpoint ? 'Remove breakpoint' : 'Break before this step'\">\n <i class=\"fa-circle\" [class.fa-solid]=\"HasSelectedBreakpoint\" [class.fa-regular]=\"!HasSelectedBreakpoint\" aria-hidden=\"true\"></i>\n </button>\n <span class=\"run-view-bp-name\">{{ SelectedTaskName }}</span>\n }\n </div>\n\n <div class=\"run-view-body\">\n @if (ShowVariables && !Prefs.InvocationOpen) {\n <button type=\"button\" class=\"run-view-vars-rail\"\n (click)=\"OnToggleInvocation()\"\n title=\"Show invocation and output\"\n aria-label=\"Show invocation and output\">\n <i class=\"fa-solid fa-code\" aria-hidden=\"true\"></i>\n <span>Data</span>\n </button>\n }\n <as-split class=\"run-view-split\" direction=\"horizontal\" unit=\"percent\"\n [gutterSize]=\"8\" (dragEnd)=\"OnInvocationSplitDragEnd($event.sizes)\">\n <as-split-area [size]=\"InvocationPaneSize\" [minSize]=\"14\" [visible]=\"InvocationPaneOpen\">\n <div class=\"run-view-vars\">\n <div class=\"run-view-vars-bar\">\n <span>Data</span>\n <button type=\"button\" class=\"run-view-vars-min\"\n (click)=\"OnToggleInvocation()\"\n title=\"Minimize\"\n aria-label=\"Minimize invocation and output\">\n <i class=\"fa-solid fa-chevron-left\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <mj-task-graph-variables\n [InputPayload]=\"SelectedTask?.InputPayload\"\n [OutputPayload]=\"SelectedTask?.OutputPayload\"\n [Invocation]=\"Invocation\">\n </mj-task-graph-variables>\n </div>\n </as-split-area>\n <as-split-area [size]=\"CanvasPaneSize\" [minSize]=\"40\">\n <div class=\"run-view-canvas\">\n <mj-task-graph-editor\n [Spec]=\"Spec\"\n [RuntimeStatus]=\"RuntimeStatus\"\n [NodePositions]=\"Positions\"\n [DebugOverlay]=\"Overlay\"\n [ReadOnly]=\"true\"\n [ShowToolbar]=\"ShowToolbar\"\n [ToolbarVisibility]=\"ToolbarVisibility\"\n [ToolbarAlign]=\"ToolbarAlign\"\n [ShowPalette]=\"false\"\n [ShowProperties]=\"false\"\n [ShowMinimap]=\"false\"\n [ShowStatusBar]=\"false\"\n [ShowLegend]=\"ShowLegend\"\n (SelectionChanged)=\"OnSelectionChanged($event)\"\n (ConnectionSelected)=\"OnConnectionSelected($event)\"\n (LegendToggled)=\"LegendToggled.emit($event)\"\n (BeforeContextMenu)=\"OnBeforeContextMenu($event)\"\n (AfterContextMenuAction)=\"OnAfterContextMenuAction($event)\">\n </mj-task-graph-editor>\n </div>\n </as-split-area>\n </as-split>\n </div>\n </div>\n}\n", styles: ["/* `height: 100%` here resolves to auto when the host's parent has no definite height, so this is\n safe for both callers: one that gives the widget a box to fill, and one that asks for 320px. */\n:host { display: block; height: 100%; min-height: 0; }\n\n.run-view {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2);\n height: 100%;\n min-height: 0;\n}\n\n.run-view-summary {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3);\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n}\n\n.run-view-count { font-weight: 500; }\n\n/* Not-taken reads as neutral, never as a failure: a skipped branch is a normal outcome, and\n colouring it like an error sends people hunting for a bug that does not exist. */\n.run-view-skipped { color: var(--mj-text-tertiary); }\n.run-view-running { color: var(--mj-brand-primary); font-weight: 600; }\n.run-view-waiting { color: var(--mj-brand-primary); font-weight: 700; }\n.run-view-done { color: var(--mj-status-success); font-weight: 600; }\n\n.run-view-body {\n display: flex;\n flex: 1 1 auto;\n min-height: 0;\n min-width: 0;\n}\n\n.run-view-vars-rail {\n flex: 0 0 28px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-start;\n gap: var(--mj-space-2);\n padding: var(--mj-space-3) 0;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n.run-view-vars-rail:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n.run-view-vars-rail span {\n writing-mode: vertical-rl;\n transform: rotate(180deg);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n font-size: var(--mj-font-size-xs);\n font-weight: 700;\n}\n.run-view-vars-rail i { font-size: 11px; }\n\n.run-view-split {\n flex: 1 1 auto;\n min-height: 0;\n min-width: 0;\n}\n\n:host ::ng-deep .run-view-split > .as-split-gutter {\n background: transparent;\n}\n:host ::ng-deep .run-view-split > .as-split-gutter::after {\n content: '';\n display: block;\n margin: auto;\n background: var(--mj-border-default);\n border-radius: 1px;\n}\n:host ::ng-deep .run-view-split.as-horizontal > .as-split-gutter::after {\n width: 3px;\n height: 32px;\n}\n:host ::ng-deep .run-view-split > .as-split-gutter:hover::after {\n background: var(--mj-brand-primary);\n}\n:host ::ng-deep .run-view-split > .as-split-area {\n overflow: hidden;\n}\n\n/* Takes what the summary line leaves, rather than a percentage of an ancestor that may not have a\n definite height \u2014 which is what left a canvas stopping halfway down its pane with dead space\n below it. */\n.run-view-canvas {\n height: 100%;\n min-height: 0;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.run-view-vars {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n min-width: 0;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n.run-view-vars-bar {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n padding: 4px 8px;\n border-bottom: 1px solid var(--mj-border-default);\n color: var(--mj-text-secondary);\n font-size: var(--mj-font-size-xs);\n font-weight: 700;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n.run-view-vars-min {\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n border-radius: var(--mj-radius-sm);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n}\n.run-view-vars-min:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n.run-view-vars mj-task-graph-variables {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.run-view-loading {\n padding: var(--mj-space-4);\n color: var(--mj-text-secondary);\n font-size: var(--mj-font-size-sm);\n}\n\n.run-view-bp {\n margin-left: auto;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n}\n.run-view-bp:hover { color: var(--mj-status-error); }\n.run-view-bp-on,\n.run-view-bp-on:hover { color: var(--mj-status-error); }\n.run-view-bp i { font-size: 10px; }\n.run-view-bp-name {\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-muted);\n}\n\n.run-view-legend {\n display: flex;\n flex-wrap: wrap;\n gap: var(--mj-space-3);\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-muted);\n}\n.run-view-legend span {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n.run-view-key-break { color: var(--mj-status-error); font-size: 8px; }\n.run-view-key-paused { color: var(--mj-brand-primary); font-size: 10px; }\n.run-view-key-forced { color: var(--mj-status-warning); font-size: 10px; }\n.run-view-key-if {\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-style: italic;\n}\n"] }]
|
|
273
765
|
}], () => [{ type: i0.ChangeDetectorRef }], { ParentTaskID: [{
|
|
274
766
|
type: Input
|
|
275
767
|
}], WorkflowName: [{
|
|
@@ -280,10 +772,55 @@ export class TaskGraphRunViewComponent extends BaseAngularComponent {
|
|
|
280
772
|
type: Input
|
|
281
773
|
}], Height: [{
|
|
282
774
|
type: Input
|
|
775
|
+
}], ShowLegend: [{
|
|
776
|
+
type: Input
|
|
777
|
+
}], ShowToolbar: [{
|
|
778
|
+
type: Input
|
|
779
|
+
}], ToolbarVisibility: [{
|
|
780
|
+
type: Input
|
|
781
|
+
}], ToolbarAlign: [{
|
|
782
|
+
type: Input
|
|
783
|
+
}], LiveFrame: [{
|
|
784
|
+
type: Input
|
|
785
|
+
}], ReplayAt: [{
|
|
786
|
+
type: Input
|
|
787
|
+
}], Breakpoints: [{
|
|
788
|
+
type: Input
|
|
789
|
+
}], PausedAtTaskID: [{
|
|
790
|
+
type: Input
|
|
791
|
+
}], GraphPaused: [{
|
|
792
|
+
type: Input
|
|
793
|
+
}], EdgeOverrides: [{
|
|
794
|
+
type: Input
|
|
795
|
+
}], AllowBreakpointEditing: [{
|
|
796
|
+
type: Input
|
|
797
|
+
}], ShowDebugLegend: [{
|
|
798
|
+
type: Input
|
|
799
|
+
}], ShowVariables: [{
|
|
800
|
+
type: Input
|
|
801
|
+
}], Invocation: [{
|
|
802
|
+
type: Input
|
|
283
803
|
}], NodeSelected: [{
|
|
284
804
|
type: Output
|
|
805
|
+
}], LegendToggled: [{
|
|
806
|
+
type: Output
|
|
285
807
|
}], Settled: [{
|
|
286
808
|
type: Output
|
|
809
|
+
}], ConnectionSelected: [{
|
|
810
|
+
type: Output
|
|
811
|
+
}], BreakpointToggled: [{
|
|
812
|
+
type: Output
|
|
813
|
+
}], EdgeOverrideRequested: [{
|
|
814
|
+
type: Output
|
|
815
|
+
}], OnDebugHotkey: [{
|
|
816
|
+
type: HostListener,
|
|
817
|
+
args: ['document:keydown', ['$event']]
|
|
287
818
|
}] }); })();
|
|
288
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TaskGraphRunViewComponent, { className: "TaskGraphRunViewComponent", filePath: "src/lib/task-graph-run-view.component.ts", lineNumber:
|
|
819
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TaskGraphRunViewComponent, { className: "TaskGraphRunViewComponent", filePath: "src/lib/task-graph-run-view.component.ts", lineNumber: 108 }); })();
|
|
820
|
+
function isTypingTarget(target) {
|
|
821
|
+
if (!(target instanceof HTMLElement))
|
|
822
|
+
return false;
|
|
823
|
+
const tag = target.tagName;
|
|
824
|
+
return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable;
|
|
825
|
+
}
|
|
289
826
|
//# sourceMappingURL=task-graph-run-view.component.js.map
|