@memberjunction/ng-core-entity-forms 2.87.0 → 2.88.0
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/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.js +7 -7
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/condition-editor/condition-editor.component.d.ts +29 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/condition-editor/condition-editor.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/condition-editor/condition-editor.component.js +198 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/condition-editor/condition-editor.component.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/confirmation-dialog/confirmation-dialog.component.d.ts +14 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/confirmation-dialog/confirmation-dialog.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/confirmation-dialog/confirmation-dialog.component.js +98 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/confirmation-dialog/confirmation-dialog.component.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/custom-node/custom-node.component.d.ts +44 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/custom-node/custom-node.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/custom-node/custom-node.component.js +282 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/custom-node/custom-node.component.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/execution-panel/execution-panel.component.d.ts +35 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/execution-panel/execution-panel.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/execution-panel/execution-panel.component.js +287 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/execution-panel/execution-panel.component.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/flow-editor/flow-editor.component.d.ts +106 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/flow-editor/flow-editor.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/flow-editor/flow-editor.component.js +951 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/flow-editor/flow-editor.component.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/prompt-editor/prompt-editor.component.d.ts +30 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/prompt-editor/prompt-editor.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/prompt-editor/prompt-editor.component.js +450 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/prompt-editor/prompt-editor.component.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/properties-panel/properties-panel.component.d.ts +25 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/properties-panel/properties-panel.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/properties-panel/properties-panel.component.js +423 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/properties-panel/properties-panel.component.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/simple-condition-editor/simple-condition-editor.component.d.ts +21 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/simple-condition-editor/simple-condition-editor.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/simple-condition-editor/simple-condition-editor.component.js +182 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/simple-condition-editor/simple-condition-editor.component.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/step/step.component.d.ts +34 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/step/step.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/step/step.component.js +171 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/step/step.component.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/toolbar/toolbar.component.d.ts +17 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/toolbar/toolbar.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/toolbar/toolbar.component.js +78 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/toolbar/toolbar.component.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/connection.model.d.ts +17 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/connection.model.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/connection.model.js +11 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/connection.model.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/mj-extended.model.d.ts +21 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/mj-extended.model.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/mj-extended.model.js +2 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/mj-extended.model.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/module.model.d.ts +33 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/module.model.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/module.model.js +2 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/module.model.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/step.model.d.ts +44 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/step.model.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/step.model.js +166 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/models/step.model.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/flow-editor.service.d.ts +14 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/flow-editor.service.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/flow-editor.service.js +31 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/flow-editor.service.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/flow-executor.service.d.ts +63 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/flow-executor.service.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/flow-executor.service.js +294 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/flow-executor.service.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/mj-flow-transformer.service.d.ts +77 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/mj-flow-transformer.service.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/mj-flow-transformer.service.js +408 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/mj-flow-transformer.service.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/module-manager.service.d.ts +19 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/module-manager.service.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/module-manager.service.js +116 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/module-manager.service.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/prompt-manager.service.d.ts +25 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/prompt-manager.service.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/prompt-manager.service.js +90 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/services/prompt-manager.service.js.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/mj-integrated-flow-editor.component.d.ts +52 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/mj-integrated-flow-editor.component.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/mj-integrated-flow-editor.component.js +500 -0
- package/dist/lib/custom/AIAgents/FlowAgentType/mj-integrated-flow-editor.component.js.map +1 -0
- package/dist/lib/custom/custom-forms.module.d.ts +2 -1
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +10 -4
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/dist/lib/generated/Entities/Component/sections/details.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/Component/sections/details.component.js +40 -4
- package/dist/lib/generated/Entities/Component/sections/details.component.js.map +1 -1
- package/package.json +16 -16
|
@@ -0,0 +1,951 @@
|
|
|
1
|
+
import { Component, ViewChild, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { StepComponent } from '../step/step.component';
|
|
4
|
+
import { SimpleConditionEditorComponent } from '../simple-condition-editor/simple-condition-editor.component';
|
|
5
|
+
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
|
|
6
|
+
import { STEP_CONFIGS } from '../../models/step.model';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
import * as i1 from "../../services/flow-editor.service";
|
|
9
|
+
import * as i2 from "../../services/flow-executor.service";
|
|
10
|
+
import * as i3 from "@angular/common";
|
|
11
|
+
const _c0 = ["reteEditor"];
|
|
12
|
+
function FlowEditorComponent_div_7_Template(rf, ctx) { if (rf & 1) {
|
|
13
|
+
i0.ɵɵelementStart(0, "div", 29)(1, "div", 30);
|
|
14
|
+
i0.ɵɵnamespaceSVG();
|
|
15
|
+
i0.ɵɵelementStart(2, "svg", 31);
|
|
16
|
+
i0.ɵɵelement(3, "line", 32);
|
|
17
|
+
i0.ɵɵelementEnd();
|
|
18
|
+
i0.ɵɵnamespaceHTML();
|
|
19
|
+
i0.ɵɵelementStart(4, "span");
|
|
20
|
+
i0.ɵɵtext(5, "First output from a step");
|
|
21
|
+
i0.ɵɵelementEnd()();
|
|
22
|
+
i0.ɵɵelementStart(6, "div", 30);
|
|
23
|
+
i0.ɵɵnamespaceSVG();
|
|
24
|
+
i0.ɵɵelementStart(7, "svg", 31);
|
|
25
|
+
i0.ɵɵelement(8, "line", 33);
|
|
26
|
+
i0.ɵɵelementEnd();
|
|
27
|
+
i0.ɵɵnamespaceHTML();
|
|
28
|
+
i0.ɵɵelementStart(9, "span");
|
|
29
|
+
i0.ɵɵtext(10, "Second output from a step");
|
|
30
|
+
i0.ɵɵelementEnd()();
|
|
31
|
+
i0.ɵɵelementStart(11, "div", 30);
|
|
32
|
+
i0.ɵɵnamespaceSVG();
|
|
33
|
+
i0.ɵɵelementStart(12, "svg", 31);
|
|
34
|
+
i0.ɵɵelement(13, "line", 34);
|
|
35
|
+
i0.ɵɵelementEnd();
|
|
36
|
+
i0.ɵɵnamespaceHTML();
|
|
37
|
+
i0.ɵɵelementStart(14, "span");
|
|
38
|
+
i0.ɵɵtext(15, "Third output from a step");
|
|
39
|
+
i0.ɵɵelementEnd()();
|
|
40
|
+
i0.ɵɵelementStart(16, "div", 30);
|
|
41
|
+
i0.ɵɵnamespaceSVG();
|
|
42
|
+
i0.ɵɵelementStart(17, "svg", 31);
|
|
43
|
+
i0.ɵɵelement(18, "line", 35);
|
|
44
|
+
i0.ɵɵelementEnd();
|
|
45
|
+
i0.ɵɵnamespaceHTML();
|
|
46
|
+
i0.ɵɵelementStart(19, "span");
|
|
47
|
+
i0.ɵɵtext(20, "Backward connection (loop)");
|
|
48
|
+
i0.ɵɵelementEnd()();
|
|
49
|
+
i0.ɵɵelementStart(21, "div", 36);
|
|
50
|
+
i0.ɵɵtext(22, " Colors help distinguish multiple paths from the same source step ");
|
|
51
|
+
i0.ɵɵelementEnd()();
|
|
52
|
+
} }
|
|
53
|
+
function FlowEditorComponent__svg_g_36__svg_g_3_Template(rf, ctx) { if (rf & 1) {
|
|
54
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
55
|
+
i0.ɵɵnamespaceSVG();
|
|
56
|
+
i0.ɵɵelementStart(0, "g");
|
|
57
|
+
i0.ɵɵelement(1, "rect", 40);
|
|
58
|
+
i0.ɵɵelementStart(2, "rect", 41);
|
|
59
|
+
i0.ɵɵlistener("click", function FlowEditorComponent__svg_g_36__svg_g_3_Template_rect_click_2_listener($event) { i0.ɵɵrestoreView(_r5); const connection_r3 = i0.ɵɵnextContext().$implicit; const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onConnectionClick($event, connection_r3)); });
|
|
60
|
+
i0.ɵɵelementEnd();
|
|
61
|
+
i0.ɵɵelementStart(3, "text", 42);
|
|
62
|
+
i0.ɵɵtext(4);
|
|
63
|
+
i0.ɵɵelementEnd()();
|
|
64
|
+
} if (rf & 2) {
|
|
65
|
+
const connection_r3 = i0.ɵɵnextContext().$implicit;
|
|
66
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
67
|
+
i0.ɵɵadvance();
|
|
68
|
+
i0.ɵɵattribute("x", ctx_r3.getConnectionMidpoint(connection_r3).x - ctx_r3.getConditionBoxWidth(connection_r3) / 2)("y", ctx_r3.getConnectionMidpoint(connection_r3).y - 15)("width", ctx_r3.getConditionBoxWidth(connection_r3))("transform", "translate(2, 2)");
|
|
69
|
+
i0.ɵɵadvance();
|
|
70
|
+
i0.ɵɵattribute("x", ctx_r3.getConnectionMidpoint(connection_r3).x - ctx_r3.getConditionBoxWidth(connection_r3) / 2)("y", ctx_r3.getConnectionMidpoint(connection_r3).y - 15)("width", ctx_r3.getConditionBoxWidth(connection_r3));
|
|
71
|
+
i0.ɵɵadvance();
|
|
72
|
+
i0.ɵɵattribute("x", ctx_r3.getConnectionMidpoint(connection_r3).x)("y", ctx_r3.getConnectionMidpoint(connection_r3).y + 4);
|
|
73
|
+
i0.ɵɵadvance();
|
|
74
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r3.getConditionLabel(connection_r3), " ");
|
|
75
|
+
} }
|
|
76
|
+
function FlowEditorComponent__svg_g_36_Template(rf, ctx) { if (rf & 1) {
|
|
77
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
78
|
+
i0.ɵɵnamespaceSVG();
|
|
79
|
+
i0.ɵɵelementStart(0, "g")(1, "path", 37);
|
|
80
|
+
i0.ɵɵlistener("click", function FlowEditorComponent__svg_g_36_Template_path_click_1_listener($event) { const connection_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onConnectionClick($event, connection_r3)); });
|
|
81
|
+
i0.ɵɵelementEnd();
|
|
82
|
+
i0.ɵɵelementStart(2, "path", 38);
|
|
83
|
+
i0.ɵɵlistener("click", function FlowEditorComponent__svg_g_36_Template_path_click_2_listener($event) { const connection_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onConnectionClick($event, connection_r3)); });
|
|
84
|
+
i0.ɵɵelementEnd();
|
|
85
|
+
i0.ɵɵtemplate(3, FlowEditorComponent__svg_g_36__svg_g_3_Template, 5, 10, "g", 39);
|
|
86
|
+
i0.ɵɵelementEnd();
|
|
87
|
+
} if (rf & 2) {
|
|
88
|
+
const connection_r3 = ctx.$implicit;
|
|
89
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
90
|
+
i0.ɵɵadvance();
|
|
91
|
+
i0.ɵɵattribute("d", ctx_r3.getConnectionPath(connection_r3))("stroke", ctx_r3.getConnectionColor(connection_r3))("stroke-dasharray", ctx_r3.getConnectionDashArray(connection_r3))("marker-end", ctx_r3.getConnectionMarker(connection_r3));
|
|
92
|
+
i0.ɵɵadvance();
|
|
93
|
+
i0.ɵɵattribute("d", ctx_r3.getConnectionPath(connection_r3));
|
|
94
|
+
i0.ɵɵadvance();
|
|
95
|
+
i0.ɵɵproperty("ngIf", connection_r3.condition);
|
|
96
|
+
} }
|
|
97
|
+
function FlowEditorComponent__svg_path_37_Template(rf, ctx) { if (rf & 1) {
|
|
98
|
+
i0.ɵɵnamespaceSVG();
|
|
99
|
+
i0.ɵɵelement(0, "path", 43);
|
|
100
|
+
} if (rf & 2) {
|
|
101
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
102
|
+
i0.ɵɵattribute("d", ctx_r3.getTempConnectionPath());
|
|
103
|
+
} }
|
|
104
|
+
function FlowEditorComponent_app_step_39_Template(rf, ctx) { if (rf & 1) {
|
|
105
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
106
|
+
i0.ɵɵelementStart(0, "app-step", 44);
|
|
107
|
+
i0.ɵɵlistener("stepSelected", function FlowEditorComponent_app_step_39_Template_app_step_stepSelected_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.selectStep($event)); })("stepDeleted", function FlowEditorComponent_app_step_39_Template_app_step_stepDeleted_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.deleteStep($event)); })("stepUpdated", function FlowEditorComponent_app_step_39_Template_app_step_stepUpdated_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.updateStep($event)); })("socketMouseDown", function FlowEditorComponent_app_step_39_Template_app_step_socketMouseDown_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onSocketMouseDown($event)); })("socketMouseEnter", function FlowEditorComponent_app_step_39_Template_app_step_socketMouseEnter_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onSocketMouseEnter($event)); })("socketMouseLeave", function FlowEditorComponent_app_step_39_Template_app_step_socketMouseLeave_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onSocketMouseLeave($event)); })("mousedown", function FlowEditorComponent_app_step_39_Template_app_step_mousedown_0_listener($event) { const step_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onStepDragStart($event, step_r7)); });
|
|
108
|
+
i0.ɵɵelementEnd();
|
|
109
|
+
} if (rf & 2) {
|
|
110
|
+
const step_r7 = ctx.$implicit;
|
|
111
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
112
|
+
i0.ɵɵstyleProp("left", step_r7.position[0], "px")("top", step_r7.position[1], "px")("position", "absolute");
|
|
113
|
+
i0.ɵɵproperty("step", step_r7)("selected", ctx_r3.selectedStepId === step_r7.id)("executing", ctx_r3.executingStepId === step_r7.id);
|
|
114
|
+
i0.ɵɵattribute("data-step-id", step_r7.id);
|
|
115
|
+
} }
|
|
116
|
+
function FlowEditorComponent_div_40_Template(rf, ctx) { if (rf & 1) {
|
|
117
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
118
|
+
i0.ɵɵelementStart(0, "div", 45);
|
|
119
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_div_40_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeConditionEditor()); });
|
|
120
|
+
i0.ɵɵelementStart(1, "div", 46);
|
|
121
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_div_40_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r8); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
122
|
+
i0.ɵɵelementStart(2, "app-simple-condition-editor", 47);
|
|
123
|
+
i0.ɵɵlistener("save", function FlowEditorComponent_div_40_Template_app_simple_condition_editor_save_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.saveConnectionConditions($event)); })("cancel", function FlowEditorComponent_div_40_Template_app_simple_condition_editor_cancel_2_listener() { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeConditionEditor()); });
|
|
124
|
+
i0.ɵɵelementEnd()()();
|
|
125
|
+
} if (rf & 2) {
|
|
126
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
127
|
+
i0.ɵɵadvance(2);
|
|
128
|
+
i0.ɵɵproperty("connection", ctx_r3.editingConnection);
|
|
129
|
+
} }
|
|
130
|
+
function FlowEditorComponent_app_confirmation_dialog_41_Template(rf, ctx) { if (rf & 1) {
|
|
131
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
132
|
+
i0.ɵɵelementStart(0, "app-confirmation-dialog", 48);
|
|
133
|
+
i0.ɵɵlistener("confirm", function FlowEditorComponent_app_confirmation_dialog_41_Template_app_confirmation_dialog_confirm_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.confirmDeleteStep()); })("cancel", function FlowEditorComponent_app_confirmation_dialog_41_Template_app_confirmation_dialog_cancel_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.cancelDeleteStep()); });
|
|
134
|
+
i0.ɵɵelementEnd();
|
|
135
|
+
} if (rf & 2) {
|
|
136
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
137
|
+
i0.ɵɵproperty("title", "Delete Step")("message", "Are you sure you want to delete this " + ctx_r3.stepToDelete.config.name + " step? This action cannot be undone.")("confirmText", "Delete");
|
|
138
|
+
} }
|
|
139
|
+
function FlowEditorComponent_app_confirmation_dialog_42_Template(rf, ctx) { if (rf & 1) {
|
|
140
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
141
|
+
i0.ɵɵelementStart(0, "app-confirmation-dialog", 48);
|
|
142
|
+
i0.ɵɵlistener("confirm", function FlowEditorComponent_app_confirmation_dialog_42_Template_app_confirmation_dialog_confirm_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.confirmDeleteConnection()); })("cancel", function FlowEditorComponent_app_confirmation_dialog_42_Template_app_confirmation_dialog_cancel_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.cancelDeleteConnection()); });
|
|
143
|
+
i0.ɵɵelementEnd();
|
|
144
|
+
} if (rf & 2) {
|
|
145
|
+
i0.ɵɵproperty("title", "Delete Connection")("message", "Are you sure you want to delete this connection? This action cannot be undone.")("confirmText", "Delete");
|
|
146
|
+
} }
|
|
147
|
+
export class FlowEditorComponent {
|
|
148
|
+
constructor(flowEditorService, flowExecutor, changeDetector) {
|
|
149
|
+
this.flowEditorService = flowEditorService;
|
|
150
|
+
this.flowExecutor = flowExecutor;
|
|
151
|
+
this.changeDetector = changeDetector;
|
|
152
|
+
this.toggleExecution = new EventEmitter();
|
|
153
|
+
this.stepMoved = new EventEmitter();
|
|
154
|
+
this.steps = [];
|
|
155
|
+
this.connections = [];
|
|
156
|
+
this.selectedStepId = null;
|
|
157
|
+
this.executingStepId = null;
|
|
158
|
+
this.showExecutionPanel = false;
|
|
159
|
+
this.legendCollapsed = true;
|
|
160
|
+
// Fixed dimensions for all steps
|
|
161
|
+
this.STEP_WIDTH = 320;
|
|
162
|
+
this.STEP_HEIGHT = 140;
|
|
163
|
+
this.nextStepId = 1;
|
|
164
|
+
this.isDragging = false;
|
|
165
|
+
this.dragOffset = { x: 0, y: 0 };
|
|
166
|
+
this.currentScale = 1;
|
|
167
|
+
this.canvasOffset = { x: 50, y: 50 };
|
|
168
|
+
// Connection creation state
|
|
169
|
+
this.tempConnection = null;
|
|
170
|
+
this.isCreatingConnection = false;
|
|
171
|
+
// Condition editing
|
|
172
|
+
this.editingConnection = null;
|
|
173
|
+
// Deletion confirmation
|
|
174
|
+
this.stepToDelete = null;
|
|
175
|
+
this.connectionToDelete = null;
|
|
176
|
+
this.currentDraggedStep = null;
|
|
177
|
+
this.handleMouseMove = (event) => {
|
|
178
|
+
if (this.isDragging && this.currentDraggedStep) {
|
|
179
|
+
const rect = this.reteEditor.nativeElement.getBoundingClientRect();
|
|
180
|
+
const mouseX = (event.clientX - rect.left - this.canvasOffset.x) / this.currentScale;
|
|
181
|
+
const mouseY = (event.clientY - rect.top - this.canvasOffset.y) / this.currentScale;
|
|
182
|
+
// Update position by subtracting the initial offset
|
|
183
|
+
this.currentDraggedStep.position[0] = mouseX - this.dragOffset.x;
|
|
184
|
+
this.currentDraggedStep.position[1] = mouseY - this.dragOffset.y;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
this.handleMouseUp = () => {
|
|
188
|
+
if (this.isDragging && this.currentDraggedStep) {
|
|
189
|
+
// Emit an event that the step position has changed
|
|
190
|
+
this.stepMoved.emit(this.currentDraggedStep);
|
|
191
|
+
}
|
|
192
|
+
this.isDragging = false;
|
|
193
|
+
this.currentDraggedStep = null;
|
|
194
|
+
document.removeEventListener('mousemove', this.handleMouseMove);
|
|
195
|
+
document.removeEventListener('mouseup', this.handleMouseUp);
|
|
196
|
+
};
|
|
197
|
+
this.handleConnectionMouseMove = (event) => {
|
|
198
|
+
if (this.isCreatingConnection && this.tempConnection) {
|
|
199
|
+
const rect = this.reteEditor.nativeElement.getBoundingClientRect();
|
|
200
|
+
this.tempConnection.mouseX = (event.clientX - rect.left - this.canvasOffset.x) / this.currentScale;
|
|
201
|
+
this.tempConnection.mouseY = (event.clientY - rect.top - this.canvasOffset.y) / this.currentScale;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
this.handleConnectionMouseUp = (event) => {
|
|
205
|
+
if (this.isCreatingConnection && this.tempConnection) {
|
|
206
|
+
// Check if we're over a socket
|
|
207
|
+
const target = event.target;
|
|
208
|
+
if (target.classList.contains('socket') && target._connectionTarget) {
|
|
209
|
+
const connectionTarget = target._connectionTarget;
|
|
210
|
+
const sourceStep = this.tempConnection.source;
|
|
211
|
+
const targetStep = connectionTarget.step;
|
|
212
|
+
// Create the connection
|
|
213
|
+
if (this.tempConnection.sourceType === 'output') {
|
|
214
|
+
this.createConnection(sourceStep.id, targetStep.id);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
this.createConnection(targetStep.id, sourceStep.id);
|
|
218
|
+
}
|
|
219
|
+
// Force change detection to show the new connection
|
|
220
|
+
this.changeDetector.detectChanges();
|
|
221
|
+
}
|
|
222
|
+
// Clean up
|
|
223
|
+
this.isCreatingConnection = false;
|
|
224
|
+
this.tempConnection = null;
|
|
225
|
+
document.removeEventListener('mousemove', this.handleConnectionMouseMove);
|
|
226
|
+
document.removeEventListener('mouseup', this.handleConnectionMouseUp);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
ngOnInit() {
|
|
231
|
+
// Subscribe to current executing step to highlight it
|
|
232
|
+
this.flowExecutor.currentStepId.subscribe(stepId => {
|
|
233
|
+
this.executingStepId = stepId;
|
|
234
|
+
this.changeDetector.detectChanges();
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
ngAfterViewInit() {
|
|
238
|
+
this.initializeEditor();
|
|
239
|
+
// Load the actual data from the service instead of creating example flow
|
|
240
|
+
this.loadFlowData();
|
|
241
|
+
}
|
|
242
|
+
initializeEditor() {
|
|
243
|
+
// Setup canvas events
|
|
244
|
+
this.setupCanvasEvents();
|
|
245
|
+
}
|
|
246
|
+
loadFlowData() {
|
|
247
|
+
// Load steps and connections from the service
|
|
248
|
+
this.steps = this.flowEditorService.getAllSteps();
|
|
249
|
+
this.connections = this.flowEditorService.connections || [];
|
|
250
|
+
// Log the loaded data
|
|
251
|
+
if (this.steps.length > 0 || this.connections.length > 0) {
|
|
252
|
+
// Auto-arrange steps with proper spacing
|
|
253
|
+
this.autoArrangeSteps();
|
|
254
|
+
// The template will automatically render the steps and connections
|
|
255
|
+
// through Angular's change detection
|
|
256
|
+
this.changeDetector.detectChanges();
|
|
257
|
+
// Fit entire flow in view after DOM is ready
|
|
258
|
+
// Need longer delay to ensure canvas element has dimensions
|
|
259
|
+
setTimeout(() => {
|
|
260
|
+
this.fitToView();
|
|
261
|
+
}, 500);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
centerOnStartingStep() {
|
|
265
|
+
// Find a starting step or the first step
|
|
266
|
+
const startingStep = this.steps.find(s => s.mjData?.startingStep) || this.steps[0];
|
|
267
|
+
if (startingStep) {
|
|
268
|
+
// Center the canvas on this step
|
|
269
|
+
const container = this.reteEditor.nativeElement;
|
|
270
|
+
const rect = container.getBoundingClientRect();
|
|
271
|
+
// Calculate offset to center the step
|
|
272
|
+
this.canvasOffset.x = (rect.width / 2) - (startingStep.position[0] * this.currentScale) - 120; // 120 is half step width
|
|
273
|
+
this.canvasOffset.y = (rect.height / 2) - (startingStep.position[1] * this.currentScale) - 60; // 60 is half step height
|
|
274
|
+
// Ensure we don't go too far up
|
|
275
|
+
this.canvasOffset.y = Math.min(this.canvasOffset.y, 50);
|
|
276
|
+
this.updateCanvasTransform();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
createExampleFlow() {
|
|
280
|
+
// Create example steps with more spacing
|
|
281
|
+
this.createStep('prompt', [100, 200]);
|
|
282
|
+
this.createStep('agent', [500, 200]);
|
|
283
|
+
this.createStep('action', [900, 200]);
|
|
284
|
+
this.createStep('prompt', [1300, 100]);
|
|
285
|
+
this.createStep('action', [1300, 300]);
|
|
286
|
+
// Create connections
|
|
287
|
+
this.createConnection(1, 2);
|
|
288
|
+
this.createConnection(2, 3);
|
|
289
|
+
this.createConnection(3, 4);
|
|
290
|
+
this.createConnection(3, 5);
|
|
291
|
+
}
|
|
292
|
+
createStep(type, position) {
|
|
293
|
+
const config = STEP_CONFIGS[type];
|
|
294
|
+
const step = {
|
|
295
|
+
id: this.nextStepId++,
|
|
296
|
+
type: type,
|
|
297
|
+
name: config.name,
|
|
298
|
+
position: position,
|
|
299
|
+
config: config
|
|
300
|
+
};
|
|
301
|
+
this.steps.push(step);
|
|
302
|
+
// console.log('Step created:', step);
|
|
303
|
+
// console.log('Total steps:', this.steps.length);
|
|
304
|
+
// console.log('Current steps array:', this.steps);
|
|
305
|
+
// Update the service with all steps
|
|
306
|
+
this.flowEditorService.setAllSteps(this.steps);
|
|
307
|
+
// Force Angular change detection
|
|
308
|
+
this.changeDetector.detectChanges();
|
|
309
|
+
// Log the DOM elements after change detection
|
|
310
|
+
setTimeout(() => {
|
|
311
|
+
// Step elements have been created
|
|
312
|
+
}, 0);
|
|
313
|
+
return step;
|
|
314
|
+
}
|
|
315
|
+
createConnection(sourceId, targetId) {
|
|
316
|
+
const connection = {
|
|
317
|
+
id: `${sourceId}-${targetId}`,
|
|
318
|
+
source: sourceId,
|
|
319
|
+
target: targetId,
|
|
320
|
+
sourceOutput: 'out',
|
|
321
|
+
targetInput: 'in',
|
|
322
|
+
condition: {
|
|
323
|
+
expression: 'success',
|
|
324
|
+
label: 'Success'
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
this.connections.push(connection);
|
|
328
|
+
// console.log('Connection created:', connection);
|
|
329
|
+
// console.log('Total connections:', this.connections.length);
|
|
330
|
+
this.changeDetector.detectChanges();
|
|
331
|
+
}
|
|
332
|
+
setupCanvasEvents() {
|
|
333
|
+
const container = this.reteEditor.nativeElement;
|
|
334
|
+
// Click on empty canvas to deselect
|
|
335
|
+
container.addEventListener('click', (e) => {
|
|
336
|
+
// Only deselect if clicking on the canvas itself or the SVG
|
|
337
|
+
const target = e.target;
|
|
338
|
+
if (target === container || target.tagName === 'svg' || target.classList.contains('canvas-wrapper')) {
|
|
339
|
+
this.selectedStepId = null;
|
|
340
|
+
this.flowEditorService.selectNode(null);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
// Setup drop handling on the container itself
|
|
344
|
+
container.addEventListener('dragover', (e) => {
|
|
345
|
+
e.preventDefault();
|
|
346
|
+
e.dataTransfer.dropEffect = 'copy';
|
|
347
|
+
container.classList.add('drag-over');
|
|
348
|
+
});
|
|
349
|
+
container.addEventListener('dragleave', (e) => {
|
|
350
|
+
const rect = container.getBoundingClientRect();
|
|
351
|
+
if (e.clientX < rect.left || e.clientX > rect.right ||
|
|
352
|
+
e.clientY < rect.top || e.clientY > rect.bottom) {
|
|
353
|
+
container.classList.remove('drag-over');
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
container.addEventListener('drop', (e) => {
|
|
357
|
+
e.preventDefault();
|
|
358
|
+
e.stopPropagation();
|
|
359
|
+
container.classList.remove('drag-over');
|
|
360
|
+
const plainData = e.dataTransfer?.getData('text/plain') || '';
|
|
361
|
+
const stepType = e.dataTransfer?.getData('stepType');
|
|
362
|
+
// Handle drag and drop of steps
|
|
363
|
+
// Check if this is a step drop
|
|
364
|
+
if (plainData.startsWith('step:')) {
|
|
365
|
+
// Extract the step type from the plain data
|
|
366
|
+
const extractedType = plainData.replace('step:', '');
|
|
367
|
+
const rect = container.getBoundingClientRect();
|
|
368
|
+
let x = (e.clientX - rect.left - this.canvasOffset.x) / this.currentScale;
|
|
369
|
+
let y = (e.clientY - rect.top - this.canvasOffset.y) / this.currentScale;
|
|
370
|
+
// Snap to grid for better alignment (optional)
|
|
371
|
+
const gridSize = 50;
|
|
372
|
+
x = Math.round(x / gridSize) * gridSize;
|
|
373
|
+
y = Math.round(y / gridSize) * gridSize;
|
|
374
|
+
// Create step at calculated position
|
|
375
|
+
this.createStep(extractedType, [x, y]);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
// Pan canvas
|
|
379
|
+
let isPanning = false;
|
|
380
|
+
let startX = 0;
|
|
381
|
+
let startY = 0;
|
|
382
|
+
container.addEventListener('mousedown', (e) => {
|
|
383
|
+
const target = e.target;
|
|
384
|
+
// Only pan if clicking on empty canvas area
|
|
385
|
+
if (target.classList.contains('canvas-wrapper') || target.classList.contains('steps-container') || target.classList.contains('rete-container')) {
|
|
386
|
+
isPanning = true;
|
|
387
|
+
startX = e.clientX - this.canvasOffset.x;
|
|
388
|
+
startY = e.clientY - this.canvasOffset.y;
|
|
389
|
+
container.style.cursor = 'grabbing';
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
document.addEventListener('mousemove', (e) => {
|
|
393
|
+
if (isPanning) {
|
|
394
|
+
this.canvasOffset.x = e.clientX - startX;
|
|
395
|
+
this.canvasOffset.y = e.clientY - startY;
|
|
396
|
+
this.updateCanvasTransform();
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
document.addEventListener('mouseup', () => {
|
|
400
|
+
isPanning = false;
|
|
401
|
+
container.style.cursor = 'grab';
|
|
402
|
+
});
|
|
403
|
+
// Zoom
|
|
404
|
+
container.addEventListener('wheel', (e) => {
|
|
405
|
+
e.preventDefault();
|
|
406
|
+
const delta = e.deltaY > 0 ? 0.9 : 1.1;
|
|
407
|
+
this.currentScale = Math.max(0.1, Math.min(2, this.currentScale * delta));
|
|
408
|
+
this.updateCanvasTransform();
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
updateCanvasTransform() {
|
|
412
|
+
const canvasWrapper = this.reteEditor.nativeElement.querySelector('.canvas-wrapper');
|
|
413
|
+
if (canvasWrapper) {
|
|
414
|
+
canvasWrapper.style.transform = `translate(${this.canvasOffset.x}px, ${this.canvasOffset.y}px) scale(${this.currentScale})`;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
selectStep(step) {
|
|
418
|
+
// Toggle selection if clicking the same step
|
|
419
|
+
if (this.selectedStepId === step.id) {
|
|
420
|
+
this.selectedStepId = null;
|
|
421
|
+
this.flowEditorService.selectNode(null);
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
this.selectedStepId = step.id;
|
|
425
|
+
this.flowEditorService.selectNode(step);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
deleteStep(step) {
|
|
429
|
+
this.stepToDelete = step;
|
|
430
|
+
}
|
|
431
|
+
confirmDeleteStep() {
|
|
432
|
+
if (!this.stepToDelete)
|
|
433
|
+
return;
|
|
434
|
+
const stepId = this.stepToDelete.id;
|
|
435
|
+
this.steps = this.steps.filter(s => s.id !== stepId);
|
|
436
|
+
this.connections = this.connections.filter(c => c.source !== stepId && c.target !== stepId);
|
|
437
|
+
// Update the service with all steps
|
|
438
|
+
this.flowEditorService.setAllSteps(this.steps);
|
|
439
|
+
if (this.selectedStepId === stepId) {
|
|
440
|
+
this.selectedStepId = null;
|
|
441
|
+
this.flowEditorService.selectNode(null);
|
|
442
|
+
}
|
|
443
|
+
this.stepToDelete = null;
|
|
444
|
+
}
|
|
445
|
+
cancelDeleteStep() {
|
|
446
|
+
this.stepToDelete = null;
|
|
447
|
+
}
|
|
448
|
+
deleteConnection(connection) {
|
|
449
|
+
this.connectionToDelete = connection;
|
|
450
|
+
}
|
|
451
|
+
confirmDeleteConnection() {
|
|
452
|
+
if (!this.connectionToDelete)
|
|
453
|
+
return;
|
|
454
|
+
this.connections = this.connections.filter(c => c.id !== this.connectionToDelete.id);
|
|
455
|
+
this.connectionToDelete = null;
|
|
456
|
+
}
|
|
457
|
+
cancelDeleteConnection() {
|
|
458
|
+
this.connectionToDelete = null;
|
|
459
|
+
}
|
|
460
|
+
onConnectionClick(event, connection) {
|
|
461
|
+
event.stopPropagation();
|
|
462
|
+
// Check if Shift key is held for delete
|
|
463
|
+
if (event.shiftKey) {
|
|
464
|
+
this.deleteConnection(connection);
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
// Open condition editor
|
|
468
|
+
this.editingConnection = { ...connection };
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
getConnectionMidpoint(connection) {
|
|
472
|
+
const source = this.steps.find(s => s.id === connection.source);
|
|
473
|
+
const target = this.steps.find(s => s.id === connection.target);
|
|
474
|
+
if (!source || !target) {
|
|
475
|
+
return { x: 0, y: 0 };
|
|
476
|
+
}
|
|
477
|
+
// Use fixed dimensions for all steps
|
|
478
|
+
const sourceDimensions = { width: this.STEP_WIDTH, height: this.STEP_HEIGHT };
|
|
479
|
+
const targetDimensions = { width: this.STEP_WIDTH, height: this.STEP_HEIGHT };
|
|
480
|
+
const x1 = source.position[0] + sourceDimensions.width; // Output socket center at edge
|
|
481
|
+
const y1 = source.position[1] + (sourceDimensions.height / 2);
|
|
482
|
+
const x2 = target.position[0]; // Input socket center at edge
|
|
483
|
+
const y2 = target.position[1] + (targetDimensions.height / 2);
|
|
484
|
+
// For backward connections, adjust midpoint to be on the curve
|
|
485
|
+
if (this.isBackwardConnection(connection)) {
|
|
486
|
+
const midX = (x1 + x2) / 2;
|
|
487
|
+
const midY = (y1 + y2) / 2 + 50; // Offset down to match the curve
|
|
488
|
+
return { x: midX, y: midY };
|
|
489
|
+
}
|
|
490
|
+
// Return the midpoint of the connection
|
|
491
|
+
const midpoint = {
|
|
492
|
+
x: (x1 + x2) / 2,
|
|
493
|
+
y: (y1 + y2) / 2
|
|
494
|
+
};
|
|
495
|
+
return midpoint;
|
|
496
|
+
}
|
|
497
|
+
saveConnectionConditions(updatedConnection) {
|
|
498
|
+
const index = this.connections.findIndex(c => c.id === updatedConnection.id);
|
|
499
|
+
if (index !== -1) {
|
|
500
|
+
this.connections[index] = updatedConnection;
|
|
501
|
+
}
|
|
502
|
+
this.closeConditionEditor();
|
|
503
|
+
}
|
|
504
|
+
closeConditionEditor() {
|
|
505
|
+
this.editingConnection = null;
|
|
506
|
+
}
|
|
507
|
+
getConditionPreview(connection) {
|
|
508
|
+
if (!connection.condition) {
|
|
509
|
+
return 'Always';
|
|
510
|
+
}
|
|
511
|
+
return connection.condition.expression;
|
|
512
|
+
}
|
|
513
|
+
getConditionLabel(connection) {
|
|
514
|
+
if (!connection.condition) {
|
|
515
|
+
return 'Always';
|
|
516
|
+
}
|
|
517
|
+
const label = connection.condition.label || connection.condition.expression;
|
|
518
|
+
// Truncate if too long
|
|
519
|
+
const maxLength = 12;
|
|
520
|
+
if (label.length > maxLength) {
|
|
521
|
+
return label.substring(0, maxLength - 2) + '...';
|
|
522
|
+
}
|
|
523
|
+
return label;
|
|
524
|
+
}
|
|
525
|
+
getConditionBoxWidth(connection) {
|
|
526
|
+
const label = this.getConditionLabel(connection);
|
|
527
|
+
// Estimate width based on character count (approx 7px per character + padding)
|
|
528
|
+
const estimatedWidth = Math.max(80, Math.min(140, label.length * 7 + 30));
|
|
529
|
+
return estimatedWidth;
|
|
530
|
+
}
|
|
531
|
+
getConnectionColor(connection) {
|
|
532
|
+
// Check if this is a backward connection
|
|
533
|
+
if (this.isBackwardConnection(connection)) {
|
|
534
|
+
return '#EF4444'; // Red for backward connections
|
|
535
|
+
}
|
|
536
|
+
// Define a palette of distinct colors for forward connections
|
|
537
|
+
const colorPalette = [
|
|
538
|
+
'#3B82F6', // Blue
|
|
539
|
+
'#10B981', // Green
|
|
540
|
+
'#F59E0B', // Amber
|
|
541
|
+
'#8B5CF6', // Purple
|
|
542
|
+
'#EC4899', // Pink
|
|
543
|
+
'#14B8A6', // Teal
|
|
544
|
+
'#F97316', // Orange
|
|
545
|
+
'#06B6D4', // Cyan
|
|
546
|
+
];
|
|
547
|
+
// Get all forward connections from the same source
|
|
548
|
+
const sourceConnections = this.connections
|
|
549
|
+
.filter(c => c.source === connection.source && !this.isBackwardConnection(c))
|
|
550
|
+
.sort((a, b) => (a.id || '').localeCompare(b.id || '')); // Sort by ID for consistency
|
|
551
|
+
// Find the index of this connection among connections from the same source
|
|
552
|
+
const connectionIndex = sourceConnections.findIndex(c => c.id === connection.id);
|
|
553
|
+
// Use modulo to cycle through colors if there are more connections than colors
|
|
554
|
+
return colorPalette[connectionIndex % colorPalette.length];
|
|
555
|
+
}
|
|
556
|
+
isBackwardConnection(connection) {
|
|
557
|
+
// A connection is backward if the target step is positioned to the left of the source step
|
|
558
|
+
const sourceStep = this.steps.find(s => s.id === connection.source);
|
|
559
|
+
const targetStep = this.steps.find(s => s.id === connection.target);
|
|
560
|
+
if (!sourceStep || !targetStep)
|
|
561
|
+
return false;
|
|
562
|
+
// Check if target is to the left of source (backward in the flow)
|
|
563
|
+
return targetStep.position[0] < sourceStep.position[0];
|
|
564
|
+
}
|
|
565
|
+
getConnectionDashArray(connection) {
|
|
566
|
+
// Return dash array for backward connections, solid for forward
|
|
567
|
+
return this.isBackwardConnection(connection) ? '10,5' : '';
|
|
568
|
+
}
|
|
569
|
+
getConnectionMarker(connection) {
|
|
570
|
+
// Add arrow marker for backward connections
|
|
571
|
+
return this.isBackwardConnection(connection) ? 'url(#backward-arrow)' : '';
|
|
572
|
+
}
|
|
573
|
+
updateStep(step) {
|
|
574
|
+
// Step updated, trigger any necessary updates
|
|
575
|
+
this.flowEditorService.updateNode(step);
|
|
576
|
+
}
|
|
577
|
+
onStepDragStart(event, step) {
|
|
578
|
+
event.preventDefault();
|
|
579
|
+
this.isDragging = true;
|
|
580
|
+
this.currentDraggedStep = step;
|
|
581
|
+
// Calculate the offset between the mouse position and the step position
|
|
582
|
+
// We need to account for the canvas transform (scale and offset)
|
|
583
|
+
const rect = this.reteEditor.nativeElement.getBoundingClientRect();
|
|
584
|
+
const mouseX = (event.clientX - rect.left - this.canvasOffset.x) / this.currentScale;
|
|
585
|
+
const mouseY = (event.clientY - rect.top - this.canvasOffset.y) / this.currentScale;
|
|
586
|
+
// Store the offset between mouse and step position
|
|
587
|
+
this.dragOffset.x = mouseX - step.position[0];
|
|
588
|
+
this.dragOffset.y = mouseY - step.position[1];
|
|
589
|
+
// Add document level mouse move and up listeners
|
|
590
|
+
document.addEventListener('mousemove', this.handleMouseMove);
|
|
591
|
+
document.addEventListener('mouseup', this.handleMouseUp);
|
|
592
|
+
}
|
|
593
|
+
onStepDragEnd() {
|
|
594
|
+
this.handleMouseUp();
|
|
595
|
+
}
|
|
596
|
+
getConnectionPath(connection) {
|
|
597
|
+
const source = this.steps.find(s => s.id === connection.source);
|
|
598
|
+
const target = this.steps.find(s => s.id === connection.target);
|
|
599
|
+
if (!source || !target) {
|
|
600
|
+
return '';
|
|
601
|
+
}
|
|
602
|
+
// Use fixed dimensions for all steps
|
|
603
|
+
const sourceDimensions = { width: this.STEP_WIDTH, height: this.STEP_HEIGHT };
|
|
604
|
+
const targetDimensions = { width: this.STEP_WIDTH, height: this.STEP_HEIGHT };
|
|
605
|
+
// Socket positions - sockets are at 50% of total step height
|
|
606
|
+
// The sockets are 16px diameter circles centered at edges
|
|
607
|
+
// Output socket center is at right edge (the socket extends beyond with right: -8px)
|
|
608
|
+
// Input socket center is at left edge (the socket extends beyond with left: -8px)
|
|
609
|
+
// Socket positioning: sockets are 16px diameter circles
|
|
610
|
+
// With right: -8px, the socket center is at the step edge (not beyond)
|
|
611
|
+
// With left: -8px, the socket center is at the step edge (not beyond)
|
|
612
|
+
const x1 = source.position[0] + sourceDimensions.width; // Output socket center at right edge
|
|
613
|
+
const y1 = source.position[1] + (sourceDimensions.height / 2); // 50% of step height
|
|
614
|
+
const x2 = target.position[0]; // Input socket center at left edge
|
|
615
|
+
const y2 = target.position[1] + (targetDimensions.height / 2); // 50% of step height
|
|
616
|
+
// Check if this is a backward connection
|
|
617
|
+
if (this.isBackwardConnection(connection)) {
|
|
618
|
+
// For backward connections, create a more pronounced curve that goes below
|
|
619
|
+
const dx = x2 - x1;
|
|
620
|
+
// Make the curve go below the steps for better visibility
|
|
621
|
+
const curveOffset = 100; // How far below to curve
|
|
622
|
+
const midX = (x1 + x2) / 2;
|
|
623
|
+
const midY = Math.max(y1, y2) + curveOffset;
|
|
624
|
+
// Create a path that curves below with a smoother quadratic curve
|
|
625
|
+
const cp1x = x1 + 50;
|
|
626
|
+
const cp1y = y1 + curveOffset / 2;
|
|
627
|
+
const cp2x = x2 - 50;
|
|
628
|
+
const cp2y = y2 + curveOffset / 2;
|
|
629
|
+
return `M ${x1} ${y1} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${x2} ${y2}`;
|
|
630
|
+
}
|
|
631
|
+
// For forward connections, use the standard bezier curve
|
|
632
|
+
const dx = x2 - x1;
|
|
633
|
+
const controlPointOffset = Math.max(50, Math.min(150, Math.abs(dx) * 0.4));
|
|
634
|
+
const path = `M ${x1} ${y1} C ${x1 + controlPointOffset} ${y1}, ${x2 - controlPointOffset} ${y2}, ${x2} ${y2}`;
|
|
635
|
+
return path;
|
|
636
|
+
}
|
|
637
|
+
onZoomIn() {
|
|
638
|
+
this.currentScale = Math.min(2, this.currentScale * 1.2);
|
|
639
|
+
this.updateCanvasTransform();
|
|
640
|
+
}
|
|
641
|
+
onZoomOut() {
|
|
642
|
+
this.currentScale = Math.max(0.1, this.currentScale * 0.8);
|
|
643
|
+
this.updateCanvasTransform();
|
|
644
|
+
}
|
|
645
|
+
onResetView() {
|
|
646
|
+
// Fit entire flow in view
|
|
647
|
+
this.fitToView();
|
|
648
|
+
}
|
|
649
|
+
onAutoArrange() {
|
|
650
|
+
// Recalculate optimal positions for all steps
|
|
651
|
+
this.autoArrangeSteps();
|
|
652
|
+
// Fit all steps in view
|
|
653
|
+
this.fitToView();
|
|
654
|
+
}
|
|
655
|
+
autoArrangeSteps() {
|
|
656
|
+
if (this.steps.length === 0)
|
|
657
|
+
return;
|
|
658
|
+
// Spacing adjusted for larger step dimensions and condition text
|
|
659
|
+
// Step width is 320px, so we need spacing > 320px to avoid overlap
|
|
660
|
+
const horizontalSpacing = 500; // Balanced spacing - enough room for connections without being too spread out
|
|
661
|
+
const verticalSpacing = 200; // Good vertical separation
|
|
662
|
+
// Build adjacency map for BFS traversal
|
|
663
|
+
const adjacencyMap = new Map();
|
|
664
|
+
const incomingEdges = new Map();
|
|
665
|
+
this.steps.forEach(step => {
|
|
666
|
+
adjacencyMap.set(step.id, []);
|
|
667
|
+
incomingEdges.set(step.id, 0);
|
|
668
|
+
});
|
|
669
|
+
this.connections.forEach(conn => {
|
|
670
|
+
const sourceSteps = adjacencyMap.get(conn.source) || [];
|
|
671
|
+
sourceSteps.push(conn.target);
|
|
672
|
+
adjacencyMap.set(conn.source, sourceSteps);
|
|
673
|
+
const targetCount = incomingEdges.get(conn.target) || 0;
|
|
674
|
+
incomingEdges.set(conn.target, targetCount + 1);
|
|
675
|
+
});
|
|
676
|
+
// Find starting nodes (no incoming edges or marked as starting)
|
|
677
|
+
const startingSteps = this.steps.filter(step => incomingEdges.get(step.id) === 0 || step.mjData?.startingStep);
|
|
678
|
+
// Use BFS to assign levels
|
|
679
|
+
const levels = new Map();
|
|
680
|
+
const queue = [...startingSteps];
|
|
681
|
+
startingSteps.forEach(step => levels.set(step.id, 0));
|
|
682
|
+
while (queue.length > 0) {
|
|
683
|
+
const current = queue.shift();
|
|
684
|
+
const currentLevel = levels.get(current.id) || 0;
|
|
685
|
+
const neighbors = adjacencyMap.get(current.id) || [];
|
|
686
|
+
neighbors.forEach(neighborId => {
|
|
687
|
+
if (!levels.has(neighborId)) {
|
|
688
|
+
levels.set(neighborId, currentLevel + 1);
|
|
689
|
+
const neighborStep = this.steps.find(s => s.id === neighborId);
|
|
690
|
+
if (neighborStep)
|
|
691
|
+
queue.push(neighborStep);
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
// Group steps by level
|
|
696
|
+
const stepsByLevel = new Map();
|
|
697
|
+
this.steps.forEach(step => {
|
|
698
|
+
const level = levels.get(step.id) || 0;
|
|
699
|
+
if (!stepsByLevel.has(level)) {
|
|
700
|
+
stepsByLevel.set(level, []);
|
|
701
|
+
}
|
|
702
|
+
stepsByLevel.get(level).push(step);
|
|
703
|
+
});
|
|
704
|
+
// Calculate positions
|
|
705
|
+
const startX = 100;
|
|
706
|
+
const startY = 50;
|
|
707
|
+
stepsByLevel.forEach((stepsInLevel, level) => {
|
|
708
|
+
const x = startX + (level * horizontalSpacing);
|
|
709
|
+
const totalHeight = (stepsInLevel.length - 1) * verticalSpacing;
|
|
710
|
+
const startYForLevel = startY + Math.max(0, (400 - totalHeight) / 2);
|
|
711
|
+
stepsInLevel.forEach((step, index) => {
|
|
712
|
+
const y = startYForLevel + (index * verticalSpacing);
|
|
713
|
+
step.position = [x, y];
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
fitToView() {
|
|
718
|
+
if (this.steps.length === 0) {
|
|
719
|
+
// If no steps, just reset to default view
|
|
720
|
+
this.currentScale = 1;
|
|
721
|
+
this.canvasOffset = { x: 0, y: 0 };
|
|
722
|
+
this.updateCanvasTransform();
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
// Get viewport dimensions
|
|
726
|
+
const viewportWidth = this.reteEditor.nativeElement.clientWidth;
|
|
727
|
+
const viewportHeight = this.reteEditor.nativeElement.clientHeight;
|
|
728
|
+
// Check if DOM is ready - if not, retry
|
|
729
|
+
if (viewportWidth === 0 || viewportHeight === 0) {
|
|
730
|
+
setTimeout(() => this.fitToView(), 200);
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
// Find bounds of all steps
|
|
734
|
+
let minX = Infinity, minY = Infinity;
|
|
735
|
+
let maxX = -Infinity, maxY = -Infinity;
|
|
736
|
+
this.steps.forEach(step => {
|
|
737
|
+
minX = Math.min(minX, step.position[0]);
|
|
738
|
+
minY = Math.min(minY, step.position[1]);
|
|
739
|
+
maxX = Math.max(maxX, step.position[0] + this.STEP_WIDTH);
|
|
740
|
+
maxY = Math.max(maxY, step.position[1] + this.STEP_HEIGHT);
|
|
741
|
+
});
|
|
742
|
+
// Calculate content dimensions
|
|
743
|
+
const contentWidth = maxX - minX;
|
|
744
|
+
const contentHeight = maxY - minY;
|
|
745
|
+
// Calculate scale to fit content with padding
|
|
746
|
+
const padding = 100;
|
|
747
|
+
const scaleX = (viewportWidth - padding * 2) / contentWidth;
|
|
748
|
+
const scaleY = (viewportHeight - padding * 2) / contentHeight;
|
|
749
|
+
// Use the smaller scale to ensure everything fits
|
|
750
|
+
// But don't zoom out too much or zoom in too much
|
|
751
|
+
const idealScale = Math.min(scaleX, scaleY);
|
|
752
|
+
this.currentScale = Math.max(0.3, Math.min(idealScale, 1.0));
|
|
753
|
+
// Calculate the center point of the content
|
|
754
|
+
const contentCenterX = minX + contentWidth / 2;
|
|
755
|
+
const contentCenterY = minY + contentHeight / 2;
|
|
756
|
+
// Calculate the center point of the viewport
|
|
757
|
+
const viewportCenterX = viewportWidth / 2;
|
|
758
|
+
const viewportCenterY = viewportHeight / 2;
|
|
759
|
+
// Calculate offset to center the content
|
|
760
|
+
this.canvasOffset.x = viewportCenterX - (contentCenterX * this.currentScale);
|
|
761
|
+
this.canvasOffset.y = viewportCenterY - (contentCenterY * this.currentScale);
|
|
762
|
+
this.updateCanvasTransform();
|
|
763
|
+
}
|
|
764
|
+
toggleExecutionPanel() {
|
|
765
|
+
this.showExecutionPanel = !this.showExecutionPanel;
|
|
766
|
+
this.toggleExecution.emit();
|
|
767
|
+
}
|
|
768
|
+
runFlow() {
|
|
769
|
+
// Run the flow with current steps and connections
|
|
770
|
+
if (this.steps.length === 0) {
|
|
771
|
+
alert('Please add some steps to the flow first!');
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
this.flowExecutor.executeFlow(this.steps, this.connections);
|
|
775
|
+
}
|
|
776
|
+
ngOnDestroy() {
|
|
777
|
+
// Cleanup
|
|
778
|
+
document.removeEventListener('mousemove', this.handleConnectionMouseMove);
|
|
779
|
+
document.removeEventListener('mouseup', this.handleConnectionMouseUp);
|
|
780
|
+
}
|
|
781
|
+
// Socket event handlers
|
|
782
|
+
onSocketMouseDown(event) {
|
|
783
|
+
event.event.stopPropagation();
|
|
784
|
+
event.event.preventDefault();
|
|
785
|
+
this.isCreatingConnection = true;
|
|
786
|
+
const rect = this.reteEditor.nativeElement.getBoundingClientRect();
|
|
787
|
+
this.tempConnection = {
|
|
788
|
+
source: event.step,
|
|
789
|
+
sourceType: event.type,
|
|
790
|
+
mouseX: (event.event.clientX - rect.left - this.canvasOffset.x) / this.currentScale,
|
|
791
|
+
mouseY: (event.event.clientY - rect.top - this.canvasOffset.y) / this.currentScale
|
|
792
|
+
};
|
|
793
|
+
// Add document-level listeners for connection creation
|
|
794
|
+
document.addEventListener('mousemove', this.handleConnectionMouseMove);
|
|
795
|
+
document.addEventListener('mouseup', this.handleConnectionMouseUp);
|
|
796
|
+
}
|
|
797
|
+
onSocketMouseEnter(event) {
|
|
798
|
+
if (this.isCreatingConnection && this.tempConnection) {
|
|
799
|
+
const targetStep = event.step;
|
|
800
|
+
const sourceStep = this.tempConnection.source;
|
|
801
|
+
// Check if we can create a connection
|
|
802
|
+
if (this.canCreateConnection(sourceStep, targetStep, this.tempConnection.sourceType, event.type)) {
|
|
803
|
+
// Highlight the socket
|
|
804
|
+
const socket = event.event.target;
|
|
805
|
+
socket.classList.add('can-connect');
|
|
806
|
+
// Store the potential target for the mouseup event
|
|
807
|
+
socket._connectionTarget = {
|
|
808
|
+
step: targetStep,
|
|
809
|
+
type: event.type
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
onSocketMouseLeave(event) {
|
|
815
|
+
const socket = event.target;
|
|
816
|
+
socket.classList.remove('can-connect');
|
|
817
|
+
delete socket._connectionTarget;
|
|
818
|
+
}
|
|
819
|
+
canCreateConnection(source, target, sourceType, targetType) {
|
|
820
|
+
// Don't connect to self
|
|
821
|
+
if (source.id === target.id)
|
|
822
|
+
return false;
|
|
823
|
+
// Only connect output to input
|
|
824
|
+
if (sourceType === 'output' && targetType === 'input') {
|
|
825
|
+
// Check if connection already exists
|
|
826
|
+
return !this.connections.some(c => c.source === source.id && c.target === target.id);
|
|
827
|
+
}
|
|
828
|
+
return false;
|
|
829
|
+
}
|
|
830
|
+
getTempConnectionPath() {
|
|
831
|
+
if (!this.tempConnection)
|
|
832
|
+
return '';
|
|
833
|
+
const source = this.tempConnection.source;
|
|
834
|
+
const sourceType = this.tempConnection.sourceType;
|
|
835
|
+
let x1, y1;
|
|
836
|
+
const socketY = source.position[1] + (this.STEP_HEIGHT / 2);
|
|
837
|
+
if (sourceType === 'output') {
|
|
838
|
+
x1 = source.position[0] + this.STEP_WIDTH; // Output socket center at edge
|
|
839
|
+
y1 = socketY;
|
|
840
|
+
}
|
|
841
|
+
else {
|
|
842
|
+
x1 = source.position[0]; // Input socket center at edge
|
|
843
|
+
y1 = socketY;
|
|
844
|
+
}
|
|
845
|
+
const x2 = this.tempConnection.mouseX;
|
|
846
|
+
const y2 = this.tempConnection.mouseY;
|
|
847
|
+
// Create a smooth bezier curve
|
|
848
|
+
const dx = x2 - x1;
|
|
849
|
+
const controlPointOffset = Math.max(50, Math.min(150, Math.abs(dx) * 0.4));
|
|
850
|
+
if (sourceType === 'output') {
|
|
851
|
+
return `M ${x1} ${y1} C ${x1 + controlPointOffset} ${y1}, ${x2 - controlPointOffset} ${y2}, ${x2} ${y2}`;
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
return `M ${x1} ${y1} C ${x1 - controlPointOffset} ${y1}, ${x2 + controlPointOffset} ${y2}, ${x2} ${y2}`;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
static { this.ɵfac = function FlowEditorComponent_Factory(t) { return new (t || FlowEditorComponent)(i0.ɵɵdirectiveInject(i1.FlowEditorService), i0.ɵɵdirectiveInject(i2.FlowExecutorService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); }; }
|
|
858
|
+
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FlowEditorComponent, selectors: [["app-flow-editor"]], viewQuery: function FlowEditorComponent_Query(rf, ctx) { if (rf & 1) {
|
|
859
|
+
i0.ɵɵviewQuery(_c0, 7);
|
|
860
|
+
} if (rf & 2) {
|
|
861
|
+
let _t;
|
|
862
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.reteEditor = _t.first);
|
|
863
|
+
} }, outputs: { toggleExecution: "toggleExecution", stepMoved: "stepMoved" }, standalone: true, features: [i0.ɵɵStandaloneFeature], decls: 43, vars: 14, consts: [["reteEditor", ""], [1, "flow-editor"], [1, "canvas-header"], [1, "legend-panel"], [1, "legend-header", 3, "click"], [1, "fas"], ["class", "legend-content", 4, "ngIf"], [1, "canvas-controls"], ["title", "Zoom In", 1, "control-button", 3, "click"], [1, "fas", "fa-search-plus"], ["title", "Zoom Out", 1, "control-button", 3, "click"], [1, "fas", "fa-search-minus"], ["title", "Reset View", 1, "control-button", 3, "click"], [1, "fas", "fa-sync-alt"], ["title", "Auto Arrange Steps", 1, "control-button", 3, "click"], [1, "fas", "fa-project-diagram"], ["title", "Toggle Execution Panel", 1, "control-button", 3, "click"], [1, "fas", "fa-play-circle"], [1, "rete-container"], [1, "canvas-wrapper"], [1, "connections-layer"], ["id", "backward-arrow", "markerWidth", "10", "markerHeight", "10", "refX", "9", "refY", "3", "orient", "auto", "markerUnits", "strokeWidth"], ["d", "M0,0 L0,6 L9,3 z", "fill", "#EF4444"], [4, "ngFor", "ngForOf"], ["class", "temp-connection-path", "fill", "none", "stroke", "#28a745", "stroke-width", "3", "stroke-dasharray", "5,5", 4, "ngIf"], [1, "steps-container"], [3, "step", "selected", "executing", "left", "top", "position", "stepSelected", "stepDeleted", "stepUpdated", "socketMouseDown", "socketMouseEnter", "socketMouseLeave", "mousedown", 4, "ngFor", "ngForOf"], ["class", "modal-backdrop", 3, "click", 4, "ngIf"], [3, "title", "message", "confirmText", "confirm", "cancel", 4, "ngIf"], [1, "legend-content"], [1, "legend-item"], ["width", "30", "height", "2"], ["x1", "0", "y1", "1", "x2", "30", "y2", "1", "stroke", "#3B82F6", "stroke-width", "2"], ["x1", "0", "y1", "1", "x2", "30", "y2", "1", "stroke", "#10B981", "stroke-width", "2"], ["x1", "0", "y1", "1", "x2", "30", "y2", "1", "stroke", "#F59E0B", "stroke-width", "2"], ["x1", "0", "y1", "1", "x2", "30", "y2", "1", "stroke", "#EF4444", "stroke-width", "2"], [1, "legend-note"], ["fill", "none", "stroke-width", "3", 1, "connection-path", 2, "cursor", "pointer", "pointer-events", "stroke", 3, "click"], ["fill", "none", "stroke", "transparent", "stroke-width", "20", 1, "connection-hover", 2, "cursor", "pointer", "pointer-events", "stroke", 3, "click"], [4, "ngIf"], ["height", "30", "rx", "15", "fill", "rgba(0,0,0,0.1)", 2, "pointer-events", "none"], ["height", "30", "rx", "15", "fill", "#FFFFFF", "stroke", "#0076B6", "stroke-width", "2", 2, "cursor", "pointer", 3, "click"], ["text-anchor", "middle", "font-size", "12", "font-weight", "600", "fill", "#0076B6", 2, "cursor", "pointer", "pointer-events", "none"], ["fill", "none", "stroke", "#28a745", "stroke-width", "3", "stroke-dasharray", "5,5", 1, "temp-connection-path"], [3, "stepSelected", "stepDeleted", "stepUpdated", "socketMouseDown", "socketMouseEnter", "socketMouseLeave", "mousedown", "step", "selected", "executing"], [1, "modal-backdrop", 3, "click"], [1, "modal-container", 3, "click"], [3, "save", "cancel", "connection"], [3, "confirm", "cancel", "title", "message", "confirmText"]], template: function FlowEditorComponent_Template(rf, ctx) { if (rf & 1) {
|
|
864
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
865
|
+
i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3)(3, "div", 4);
|
|
866
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_Template_div_click_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.legendCollapsed = !ctx.legendCollapsed); });
|
|
867
|
+
i0.ɵɵelement(4, "i", 5);
|
|
868
|
+
i0.ɵɵelementStart(5, "span");
|
|
869
|
+
i0.ɵɵtext(6, "Connection Legend");
|
|
870
|
+
i0.ɵɵelementEnd()();
|
|
871
|
+
i0.ɵɵtemplate(7, FlowEditorComponent_div_7_Template, 23, 0, "div", 6);
|
|
872
|
+
i0.ɵɵelementEnd();
|
|
873
|
+
i0.ɵɵelementStart(8, "div", 7)(9, "button", 8);
|
|
874
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onZoomIn()); });
|
|
875
|
+
i0.ɵɵelement(10, "i", 9);
|
|
876
|
+
i0.ɵɵelementStart(11, "span");
|
|
877
|
+
i0.ɵɵtext(12, "Zoom In");
|
|
878
|
+
i0.ɵɵelementEnd()();
|
|
879
|
+
i0.ɵɵelementStart(13, "button", 10);
|
|
880
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onZoomOut()); });
|
|
881
|
+
i0.ɵɵelement(14, "i", 11);
|
|
882
|
+
i0.ɵɵelementStart(15, "span");
|
|
883
|
+
i0.ɵɵtext(16, "Zoom Out");
|
|
884
|
+
i0.ɵɵelementEnd()();
|
|
885
|
+
i0.ɵɵelementStart(17, "button", 12);
|
|
886
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onResetView()); });
|
|
887
|
+
i0.ɵɵelement(18, "i", 13);
|
|
888
|
+
i0.ɵɵelementStart(19, "span");
|
|
889
|
+
i0.ɵɵtext(20, "Reset View");
|
|
890
|
+
i0.ɵɵelementEnd()();
|
|
891
|
+
i0.ɵɵelementStart(21, "button", 14);
|
|
892
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_Template_button_click_21_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAutoArrange()); });
|
|
893
|
+
i0.ɵɵelement(22, "i", 15);
|
|
894
|
+
i0.ɵɵelementStart(23, "span");
|
|
895
|
+
i0.ɵɵtext(24, "Auto Arrange");
|
|
896
|
+
i0.ɵɵelementEnd()();
|
|
897
|
+
i0.ɵɵelementStart(25, "button", 16);
|
|
898
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_Template_button_click_25_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleExecutionPanel()); });
|
|
899
|
+
i0.ɵɵelement(26, "i", 17);
|
|
900
|
+
i0.ɵɵelementStart(27, "span");
|
|
901
|
+
i0.ɵɵtext(28);
|
|
902
|
+
i0.ɵɵelementEnd()()()();
|
|
903
|
+
i0.ɵɵelementStart(29, "div", 18, 0)(31, "div", 19);
|
|
904
|
+
i0.ɵɵnamespaceSVG();
|
|
905
|
+
i0.ɵɵelementStart(32, "svg", 20)(33, "defs")(34, "marker", 21);
|
|
906
|
+
i0.ɵɵelement(35, "path", 22);
|
|
907
|
+
i0.ɵɵelementEnd()();
|
|
908
|
+
i0.ɵɵtemplate(36, FlowEditorComponent__svg_g_36_Template, 4, 6, "g", 23)(37, FlowEditorComponent__svg_path_37_Template, 1, 1, "path", 24);
|
|
909
|
+
i0.ɵɵelementEnd();
|
|
910
|
+
i0.ɵɵnamespaceHTML();
|
|
911
|
+
i0.ɵɵelementStart(38, "div", 25);
|
|
912
|
+
i0.ɵɵtemplate(39, FlowEditorComponent_app_step_39_Template, 1, 10, "app-step", 26);
|
|
913
|
+
i0.ɵɵelementEnd()()();
|
|
914
|
+
i0.ɵɵtemplate(40, FlowEditorComponent_div_40_Template, 3, 1, "div", 27)(41, FlowEditorComponent_app_confirmation_dialog_41_Template, 1, 3, "app-confirmation-dialog", 28)(42, FlowEditorComponent_app_confirmation_dialog_42_Template, 1, 3, "app-confirmation-dialog", 28);
|
|
915
|
+
i0.ɵɵelementEnd();
|
|
916
|
+
} if (rf & 2) {
|
|
917
|
+
i0.ɵɵadvance(2);
|
|
918
|
+
i0.ɵɵclassProp("collapsed", ctx.legendCollapsed);
|
|
919
|
+
i0.ɵɵadvance(2);
|
|
920
|
+
i0.ɵɵclassProp("fa-chevron-down", !ctx.legendCollapsed)("fa-chevron-right", ctx.legendCollapsed);
|
|
921
|
+
i0.ɵɵadvance(3);
|
|
922
|
+
i0.ɵɵproperty("ngIf", !ctx.legendCollapsed);
|
|
923
|
+
i0.ɵɵadvance(21);
|
|
924
|
+
i0.ɵɵtextInterpolate1("", ctx.showExecutionPanel ? "Hide" : "Show", " Execution");
|
|
925
|
+
i0.ɵɵadvance(8);
|
|
926
|
+
i0.ɵɵproperty("ngForOf", ctx.connections);
|
|
927
|
+
i0.ɵɵadvance();
|
|
928
|
+
i0.ɵɵproperty("ngIf", ctx.tempConnection);
|
|
929
|
+
i0.ɵɵadvance(2);
|
|
930
|
+
i0.ɵɵproperty("ngForOf", ctx.steps);
|
|
931
|
+
i0.ɵɵadvance();
|
|
932
|
+
i0.ɵɵproperty("ngIf", ctx.editingConnection);
|
|
933
|
+
i0.ɵɵadvance();
|
|
934
|
+
i0.ɵɵproperty("ngIf", ctx.stepToDelete);
|
|
935
|
+
i0.ɵɵadvance();
|
|
936
|
+
i0.ɵɵproperty("ngIf", ctx.connectionToDelete);
|
|
937
|
+
} }, dependencies: [CommonModule, i3.NgForOf, i3.NgIf, StepComponent, SimpleConditionEditorComponent, ConfirmationDialogComponent], styles: [".flow-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n.canvas-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.75rem 1rem;\n background-color: var(--white-color);\n border-bottom: 1px solid var(--gray-700);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n\n.canvas-controls[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n}\n\n.rete-container[_ngcontent-%COMP%] {\n flex: 1;\n position: relative;\n overflow: hidden;\n cursor: grab;\n background-color: var(--gray-600);\n \n &.grabbing {\n cursor: grabbing;\n }\n \n &.drag-over {\n background-color: rgba(0, 118, 182, 0.05);\n outline: 2px dashed var(--mj-blue);\n outline-offset: -2px;\n }\n}\n\n.canvas-wrapper[_ngcontent-%COMP%] {\n position: relative;\n width: 5000px; // Large area for workflow\n height: 3000px; // Large height for vertical workflows\n min-height: 600px;\n transform-origin: 0 0;\n}\n\n.connections-layer[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n width: 5000px; // Match canvas-wrapper width\n height: 3000px; // Match canvas-wrapper height\n pointer-events: none;\n z-index: 1;\n overflow: visible;\n \n path {\n pointer-events: auto;\n }\n \n text, rect, circle {\n pointer-events: auto;\n }\n \n .temp-connection-path {\n animation: dash 1s linear infinite;\n }\n \n .connection-path {\n transition: stroke 0.2s ease;\n }\n \n .connection-hover:hover + .connection-path,\n .connection-path:hover {\n stroke: #dc3545 !important;\n }\n \n @keyframes dash {\n to {\n stroke-dashoffset: -10;\n }\n }\n}\n\n.steps-container[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 2;\n pointer-events: none;\n \n app-step {\n pointer-events: auto;\n }\n}\n\n.control-button[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n border: 1px solid var(--light-blue);\n background: var(--white-color);\n border-radius: 0.5rem;\n cursor: pointer;\n transition: all var(--transition-time);\n font-size: 0.875rem;\n color: var(--mj-blue);\n \n &:hover {\n background: var(--light-blue);\n color: var(--navy);\n transform: translateY(-2px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n }\n \n i {\n font-size: 1rem;\n }\n}\n\n.modal-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n.modal-container[_ngcontent-%COMP%] {\n position: relative;\n animation: _ngcontent-%COMP%_modalSlideIn 0.3s ease;\n}\n\n@keyframes _ngcontent-%COMP%_modalSlideIn {\n from {\n opacity: 0;\n transform: translateY(-20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.legend-panel[_ngcontent-%COMP%] {\n position: relative;\n background: var(--white-color);\n border: 1px solid var(--gray-700);\n border-radius: var(--border-radius);\n box-shadow: var(--shadow);\n min-width: 150px;\n transition: all 0.3s ease;\n margin-right: auto;\n margin-left: 1rem;\n \n &.collapsed {\n min-width: auto;\n .legend-header {\n border-bottom: none;\n border-radius: var(--border-radius);\n }\n }\n \n .legend-header {\n padding: 0.75rem;\n background: var(--gray-600);\n border-bottom: 1px solid var(--gray-700);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n user-select: none;\n border-radius: calc(var(--border-radius) - 1px) calc(var(--border-radius) - 1px) 0 0;\n \n &:hover {\n background: var(--gray-650);\n }\n \n i {\n font-size: 0.75rem;\n transition: transform 0.2s;\n }\n \n span {\n font-weight: 600;\n font-size: 0.875rem;\n }\n }\n \n .legend-content {\n position: absolute;\n top: 100%;\n left: 0;\n margin-top: 0.25rem;\n background: var(--white-color);\n border: 1px solid var(--gray-700);\n border-radius: var(--border-radius);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n padding: 1rem;\n min-width: 280px;\n z-index: 1000;\n \n .legend-item {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin-bottom: 0.75rem;\n \n svg {\n flex-shrink: 0;\n }\n \n span {\n font-size: 0.813rem;\n color: var(--gray-800);\n }\n }\n \n .legend-note {\n margin-top: 1rem;\n padding-top: 0.75rem;\n border-top: 1px solid var(--gray-700);\n font-size: 0.75rem;\n color: var(--gray-750);\n font-style: italic;\n }\n }\n}"] }); }
|
|
938
|
+
}
|
|
939
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FlowEditorComponent, [{
|
|
940
|
+
type: Component,
|
|
941
|
+
args: [{ selector: 'app-flow-editor', standalone: true, imports: [CommonModule, StepComponent, SimpleConditionEditorComponent, ConfirmationDialogComponent], template: "<div class=\"flow-editor\">\n <div class=\"canvas-header\">\n <!-- Connection Legend -->\n <div class=\"legend-panel\" [class.collapsed]=\"legendCollapsed\">\n <div class=\"legend-header\" (click)=\"legendCollapsed = !legendCollapsed\">\n <i class=\"fas\" [class.fa-chevron-down]=\"!legendCollapsed\" [class.fa-chevron-right]=\"legendCollapsed\"></i>\n <span>Connection Legend</span>\n </div>\n <div class=\"legend-content\" *ngIf=\"!legendCollapsed\">\n <div class=\"legend-item\">\n <svg width=\"30\" height=\"2\">\n <line x1=\"0\" y1=\"1\" x2=\"30\" y2=\"1\" stroke=\"#3B82F6\" stroke-width=\"2\"/>\n </svg>\n <span>First output from a step</span>\n </div>\n <div class=\"legend-item\">\n <svg width=\"30\" height=\"2\">\n <line x1=\"0\" y1=\"1\" x2=\"30\" y2=\"1\" stroke=\"#10B981\" stroke-width=\"2\"/>\n </svg>\n <span>Second output from a step</span>\n </div>\n <div class=\"legend-item\">\n <svg width=\"30\" height=\"2\">\n <line x1=\"0\" y1=\"1\" x2=\"30\" y2=\"1\" stroke=\"#F59E0B\" stroke-width=\"2\"/>\n </svg>\n <span>Third output from a step</span>\n </div>\n <div class=\"legend-item\">\n <svg width=\"30\" height=\"2\">\n <line x1=\"0\" y1=\"1\" x2=\"30\" y2=\"1\" stroke=\"#EF4444\" stroke-width=\"2\"/>\n </svg>\n <span>Backward connection (loop)</span>\n </div>\n <div class=\"legend-note\">\n Colors help distinguish multiple paths from the same source step\n </div>\n </div>\n </div>\n \n <div class=\"canvas-controls\">\n <button \n class=\"control-button\" \n (click)=\"onZoomIn()\"\n title=\"Zoom In\">\n <i class=\"fas fa-search-plus\"></i>\n <span>Zoom In</span>\n </button>\n <button \n class=\"control-button\" \n (click)=\"onZoomOut()\"\n title=\"Zoom Out\">\n <i class=\"fas fa-search-minus\"></i>\n <span>Zoom Out</span>\n </button>\n <button \n class=\"control-button\" \n (click)=\"onResetView()\"\n title=\"Reset View\">\n <i class=\"fas fa-sync-alt\"></i>\n <span>Reset View</span>\n </button>\n <button \n class=\"control-button\" \n (click)=\"onAutoArrange()\"\n title=\"Auto Arrange Steps\">\n <i class=\"fas fa-project-diagram\"></i>\n <span>Auto Arrange</span>\n </button>\n <button \n class=\"control-button\" \n (click)=\"toggleExecutionPanel()\"\n title=\"Toggle Execution Panel\">\n <i class=\"fas fa-play-circle\"></i>\n <span>{{ showExecutionPanel ? 'Hide' : 'Show' }} Execution</span>\n </button>\n </div>\n </div>\n \n <div #reteEditor class=\"rete-container\">\n <div class=\"canvas-wrapper\">\n <svg class=\"connections-layer\">\n <!-- Define arrow markers for backward connections -->\n <defs>\n <marker id=\"backward-arrow\" markerWidth=\"10\" markerHeight=\"10\" \n refX=\"9\" refY=\"3\" orient=\"auto\" markerUnits=\"strokeWidth\">\n <path d=\"M0,0 L0,6 L9,3 z\" fill=\"#EF4444\" />\n </marker>\n </defs>\n <g *ngFor=\"let connection of connections\">\n <path [attr.d]=\"getConnectionPath(connection)\" \n class=\"connection-path\"\n fill=\"none\"\n [attr.stroke]=\"getConnectionColor(connection)\"\n [attr.stroke-dasharray]=\"getConnectionDashArray(connection)\"\n [attr.marker-end]=\"getConnectionMarker(connection)\"\n stroke-width=\"3\"\n style=\"cursor: pointer; pointer-events: stroke\"\n (click)=\"onConnectionClick($event, connection)\"/>\n <path [attr.d]=\"getConnectionPath(connection)\" \n class=\"connection-hover\"\n fill=\"none\"\n stroke=\"transparent\"\n stroke-width=\"20\"\n style=\"cursor: pointer; pointer-events: stroke\"\n (click)=\"onConnectionClick($event, connection)\"/>\n \n <!-- Condition indicator -->\n <g *ngIf=\"connection.condition\">\n <!-- Shadow for condition box -->\n <rect\n [attr.x]=\"getConnectionMidpoint(connection).x - getConditionBoxWidth(connection)/2\"\n [attr.y]=\"getConnectionMidpoint(connection).y - 15\"\n [attr.width]=\"getConditionBoxWidth(connection)\"\n height=\"30\"\n rx=\"15\"\n fill=\"rgba(0,0,0,0.1)\"\n [attr.transform]=\"'translate(2, 2)'\"\n style=\"pointer-events: none\"/>\n <rect\n [attr.x]=\"getConnectionMidpoint(connection).x - getConditionBoxWidth(connection)/2\"\n [attr.y]=\"getConnectionMidpoint(connection).y - 15\"\n [attr.width]=\"getConditionBoxWidth(connection)\"\n height=\"30\"\n rx=\"15\"\n fill=\"#FFFFFF\"\n stroke=\"#0076B6\"\n stroke-width=\"2\"\n style=\"cursor: pointer\"\n (click)=\"onConnectionClick($event, connection)\"/>\n <text \n [attr.x]=\"getConnectionMidpoint(connection).x\"\n [attr.y]=\"getConnectionMidpoint(connection).y + 4\"\n text-anchor=\"middle\"\n font-size=\"12\"\n font-weight=\"600\"\n fill=\"#0076B6\"\n style=\"cursor: pointer; pointer-events: none;\">\n {{ getConditionLabel(connection) }}\n </text>\n </g>\n \n </g>\n <path *ngIf=\"tempConnection\" \n [attr.d]=\"getTempConnectionPath()\" \n class=\"temp-connection-path\"\n fill=\"none\"\n stroke=\"#28a745\"\n stroke-width=\"3\"\n stroke-dasharray=\"5,5\"/>\n </svg>\n \n <div class=\"steps-container\">\n <app-step \n *ngFor=\"let step of steps\"\n [step]=\"step\"\n [selected]=\"selectedStepId === step.id\"\n [executing]=\"executingStepId === step.id\"\n [style.left.px]=\"step.position[0]\"\n [style.top.px]=\"step.position[1]\"\n [style.position]=\"'absolute'\"\n [attr.data-step-id]=\"step.id\"\n (stepSelected)=\"selectStep($event)\"\n (stepDeleted)=\"deleteStep($event)\"\n (stepUpdated)=\"updateStep($event)\"\n (socketMouseDown)=\"onSocketMouseDown($event)\"\n (socketMouseEnter)=\"onSocketMouseEnter($event)\"\n (socketMouseLeave)=\"onSocketMouseLeave($event)\"\n (mousedown)=\"onStepDragStart($event, step)\">\n </app-step>\n </div>\n </div>\n </div>\n \n <!-- Condition Editor Modal -->\n <div class=\"modal-backdrop\" *ngIf=\"editingConnection\" (click)=\"closeConditionEditor()\">\n <div class=\"modal-container\" (click)=\"$event.stopPropagation()\">\n <app-simple-condition-editor\n [connection]=\"editingConnection\"\n (save)=\"saveConnectionConditions($event)\"\n (cancel)=\"closeConditionEditor()\">\n </app-simple-condition-editor>\n </div>\n </div>\n \n <!-- Delete Step Confirmation Dialog -->\n <app-confirmation-dialog\n *ngIf=\"stepToDelete\"\n [title]=\"'Delete Step'\"\n [message]=\"'Are you sure you want to delete this ' + stepToDelete.config.name + ' step? This action cannot be undone.'\"\n [confirmText]=\"'Delete'\"\n (confirm)=\"confirmDeleteStep()\"\n (cancel)=\"cancelDeleteStep()\">\n </app-confirmation-dialog>\n \n <!-- Delete Connection Confirmation Dialog -->\n <app-confirmation-dialog\n *ngIf=\"connectionToDelete\"\n [title]=\"'Delete Connection'\"\n [message]=\"'Are you sure you want to delete this connection? This action cannot be undone.'\"\n [confirmText]=\"'Delete'\"\n (confirm)=\"confirmDeleteConnection()\"\n (cancel)=\"cancelDeleteConnection()\">\n </app-confirmation-dialog>\n</div>", styles: [".flow-editor {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n.canvas-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.75rem 1rem;\n background-color: var(--white-color);\n border-bottom: 1px solid var(--gray-700);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n}\n\n.canvas-controls {\n display: flex;\n gap: 0.5rem;\n}\n\n.rete-container {\n flex: 1;\n position: relative;\n overflow: hidden;\n cursor: grab;\n background-color: var(--gray-600);\n \n &.grabbing {\n cursor: grabbing;\n }\n \n &.drag-over {\n background-color: rgba(0, 118, 182, 0.05);\n outline: 2px dashed var(--mj-blue);\n outline-offset: -2px;\n }\n}\n\n.canvas-wrapper {\n position: relative;\n width: 5000px; // Large area for workflow\n height: 3000px; // Large height for vertical workflows\n min-height: 600px;\n transform-origin: 0 0;\n}\n\n.connections-layer {\n position: absolute;\n top: 0;\n left: 0;\n width: 5000px; // Match canvas-wrapper width\n height: 3000px; // Match canvas-wrapper height\n pointer-events: none;\n z-index: 1;\n overflow: visible;\n \n path {\n pointer-events: auto;\n }\n \n text, rect, circle {\n pointer-events: auto;\n }\n \n .temp-connection-path {\n animation: dash 1s linear infinite;\n }\n \n .connection-path {\n transition: stroke 0.2s ease;\n }\n \n .connection-hover:hover + .connection-path,\n .connection-path:hover {\n stroke: #dc3545 !important;\n }\n \n @keyframes dash {\n to {\n stroke-dashoffset: -10;\n }\n }\n}\n\n.steps-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 2;\n pointer-events: none;\n \n app-step {\n pointer-events: auto;\n }\n}\n\n.control-button {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n border: 1px solid var(--light-blue);\n background: var(--white-color);\n border-radius: 0.5rem;\n cursor: pointer;\n transition: all var(--transition-time);\n font-size: 0.875rem;\n color: var(--mj-blue);\n \n &:hover {\n background: var(--light-blue);\n color: var(--navy);\n transform: translateY(-2px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n }\n \n i {\n font-size: 1rem;\n }\n}\n\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n.modal-container {\n position: relative;\n animation: modalSlideIn 0.3s ease;\n}\n\n@keyframes modalSlideIn {\n from {\n opacity: 0;\n transform: translateY(-20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.legend-panel {\n position: relative;\n background: var(--white-color);\n border: 1px solid var(--gray-700);\n border-radius: var(--border-radius);\n box-shadow: var(--shadow);\n min-width: 150px;\n transition: all 0.3s ease;\n margin-right: auto;\n margin-left: 1rem;\n \n &.collapsed {\n min-width: auto;\n .legend-header {\n border-bottom: none;\n border-radius: var(--border-radius);\n }\n }\n \n .legend-header {\n padding: 0.75rem;\n background: var(--gray-600);\n border-bottom: 1px solid var(--gray-700);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n user-select: none;\n border-radius: calc(var(--border-radius) - 1px) calc(var(--border-radius) - 1px) 0 0;\n \n &:hover {\n background: var(--gray-650);\n }\n \n i {\n font-size: 0.75rem;\n transition: transform 0.2s;\n }\n \n span {\n font-weight: 600;\n font-size: 0.875rem;\n }\n }\n \n .legend-content {\n position: absolute;\n top: 100%;\n left: 0;\n margin-top: 0.25rem;\n background: var(--white-color);\n border: 1px solid var(--gray-700);\n border-radius: var(--border-radius);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n padding: 1rem;\n min-width: 280px;\n z-index: 1000;\n \n .legend-item {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin-bottom: 0.75rem;\n \n svg {\n flex-shrink: 0;\n }\n \n span {\n font-size: 0.813rem;\n color: var(--gray-800);\n }\n }\n \n .legend-note {\n margin-top: 1rem;\n padding-top: 0.75rem;\n border-top: 1px solid var(--gray-700);\n font-size: 0.75rem;\n color: var(--gray-750);\n font-style: italic;\n }\n }\n}\n\n\n"] }]
|
|
942
|
+
}], () => [{ type: i1.FlowEditorService }, { type: i2.FlowExecutorService }, { type: i0.ChangeDetectorRef }], { reteEditor: [{
|
|
943
|
+
type: ViewChild,
|
|
944
|
+
args: ['reteEditor', { static: true }]
|
|
945
|
+
}], toggleExecution: [{
|
|
946
|
+
type: Output
|
|
947
|
+
}], stepMoved: [{
|
|
948
|
+
type: Output
|
|
949
|
+
}] }); })();
|
|
950
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FlowEditorComponent, { className: "FlowEditorComponent", filePath: "src/lib/custom/AIAgents/FlowAgentType/flow-editor-integration/components/flow-editor/flow-editor.component.ts", lineNumber: 18 }); })();
|
|
951
|
+
//# sourceMappingURL=flow-editor.component.js.map
|