@memberjunction/ng-flow-editor 0.0.1 → 4.1.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/README.md +151 -43
- package/dist/lib/agent-editor/agent-flow-transformer.service.d.ts +83 -0
- package/dist/lib/agent-editor/agent-flow-transformer.service.d.ts.map +1 -0
- package/dist/lib/agent-editor/agent-flow-transformer.service.js +447 -0
- package/dist/lib/agent-editor/agent-flow-transformer.service.js.map +1 -0
- package/dist/lib/agent-editor/agent-properties-panel.component.d.ts +92 -0
- package/dist/lib/agent-editor/agent-properties-panel.component.d.ts.map +1 -0
- package/dist/lib/agent-editor/agent-properties-panel.component.js +1139 -0
- package/dist/lib/agent-editor/agent-properties-panel.component.js.map +1 -0
- package/dist/lib/agent-editor/agent-step-list.component.d.ts +17 -0
- package/dist/lib/agent-editor/agent-step-list.component.d.ts.map +1 -0
- package/dist/lib/agent-editor/agent-step-list.component.js +278 -0
- package/dist/lib/agent-editor/agent-step-list.component.js.map +1 -0
- package/dist/lib/agent-editor/flow-agent-editor.component.d.ts +134 -0
- package/dist/lib/agent-editor/flow-agent-editor.component.d.ts.map +1 -0
- package/dist/lib/agent-editor/flow-agent-editor.component.js +999 -0
- package/dist/lib/agent-editor/flow-agent-editor.component.js.map +1 -0
- package/dist/lib/components/flow-editor.component.d.ts +169 -0
- package/dist/lib/components/flow-editor.component.d.ts.map +1 -0
- package/dist/lib/components/flow-editor.component.js +1090 -0
- package/dist/lib/components/flow-editor.component.js.map +1 -0
- package/dist/lib/components/flow-node.component.d.ts +50 -0
- package/dist/lib/components/flow-node.component.d.ts.map +1 -0
- package/dist/lib/components/flow-node.component.js +358 -0
- package/dist/lib/components/flow-node.component.js.map +1 -0
- package/dist/lib/components/flow-palette.component.d.ts +17 -0
- package/dist/lib/components/flow-palette.component.d.ts.map +1 -0
- package/dist/lib/components/flow-palette.component.js +110 -0
- package/dist/lib/components/flow-palette.component.js.map +1 -0
- package/dist/lib/components/flow-status-bar.component.d.ts +13 -0
- package/dist/lib/components/flow-status-bar.component.d.ts.map +1 -0
- package/dist/lib/components/flow-status-bar.component.js +81 -0
- package/dist/lib/components/flow-status-bar.component.js.map +1 -0
- package/dist/lib/components/flow-toolbar.component.d.ts +25 -0
- package/dist/lib/components/flow-toolbar.component.d.ts.map +1 -0
- package/dist/lib/components/flow-toolbar.component.js +192 -0
- package/dist/lib/components/flow-toolbar.component.js.map +1 -0
- package/dist/lib/flow-editor.module.d.ts +19 -0
- package/dist/lib/flow-editor.module.d.ts.map +1 -0
- package/dist/lib/flow-editor.module.js +84 -0
- package/dist/lib/flow-editor.module.js.map +1 -0
- package/dist/lib/interfaces/flow-types.d.ts +153 -0
- package/dist/lib/interfaces/flow-types.d.ts.map +1 -0
- package/dist/lib/interfaces/flow-types.js +6 -0
- package/dist/lib/interfaces/flow-types.js.map +1 -0
- package/dist/lib/services/flow-layout.service.d.ts +21 -0
- package/dist/lib/services/flow-layout.service.d.ts.map +1 -0
- package/dist/lib/services/flow-layout.service.js +76 -0
- package/dist/lib/services/flow-layout.service.js.map +1 -0
- package/dist/lib/services/flow-state.service.d.ts +37 -0
- package/dist/lib/services/flow-state.service.d.ts.map +1 -0
- package/dist/lib/services/flow-state.service.js +89 -0
- package/dist/lib/services/flow-state.service.js.map +1 -0
- package/dist/public-api.d.ts +14 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +22 -0
- package/dist/public-api.js.map +1 -0
- package/package.json +51 -6
|
@@ -0,0 +1,999 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter, ViewChild, ViewEncapsulation, HostListener, HostBinding } from '@angular/core';
|
|
2
|
+
import { Metadata, RunView, CompositeKey } from '@memberjunction/core';
|
|
3
|
+
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
4
|
+
import { AgentFlowTransformerService, AGENT_STEP_TYPE_CONFIGS } from './agent-flow-transformer.service';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "./agent-flow-transformer.service";
|
|
7
|
+
import * as i2 from "@angular/common";
|
|
8
|
+
import * as i3 from "../components/flow-editor.component";
|
|
9
|
+
import * as i4 from "./agent-properties-panel.component";
|
|
10
|
+
import * as i5 from "./agent-step-list.component";
|
|
11
|
+
const _c0 = ["flowEditor"];
|
|
12
|
+
function FlowAgentEditorComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
13
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
14
|
+
i0.ɵɵelementStart(0, "button", 26);
|
|
15
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Conditional_3_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.flowEditor == null ? null : ctx_r1.flowEditor.Undo()); });
|
|
16
|
+
i0.ɵɵelement(1, "i", 27);
|
|
17
|
+
i0.ɵɵelementEnd();
|
|
18
|
+
} if (rf & 2) {
|
|
19
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
20
|
+
i0.ɵɵproperty("disabled", !(ctx_r1.flowEditor == null ? null : ctx_r1.flowEditor.CanUndo));
|
|
21
|
+
} }
|
|
22
|
+
function FlowAgentEditorComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
23
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
24
|
+
i0.ɵɵelementStart(0, "button", 28);
|
|
25
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Conditional_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.flowEditor == null ? null : ctx_r1.flowEditor.Redo()); });
|
|
26
|
+
i0.ɵɵelement(1, "i", 29);
|
|
27
|
+
i0.ɵɵelementEnd();
|
|
28
|
+
} if (rf & 2) {
|
|
29
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
30
|
+
i0.ɵɵproperty("disabled", !(ctx_r1.flowEditor == null ? null : ctx_r1.flowEditor.CanRedo));
|
|
31
|
+
} }
|
|
32
|
+
function FlowAgentEditorComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
33
|
+
i0.ɵɵelementStart(0, "span", 12);
|
|
34
|
+
i0.ɵɵelement(1, "i", 30);
|
|
35
|
+
i0.ɵɵtext(2, " Editing ");
|
|
36
|
+
i0.ɵɵelementEnd();
|
|
37
|
+
} }
|
|
38
|
+
function FlowAgentEditorComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
39
|
+
i0.ɵɵelementStart(0, "span", 13);
|
|
40
|
+
i0.ɵɵelement(1, "i", 31);
|
|
41
|
+
i0.ɵɵtext(2, " Read Only ");
|
|
42
|
+
i0.ɵɵelementEnd();
|
|
43
|
+
} }
|
|
44
|
+
function FlowAgentEditorComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
45
|
+
i0.ɵɵelementStart(0, "span", 15);
|
|
46
|
+
i0.ɵɵelement(1, "i", 32);
|
|
47
|
+
i0.ɵɵtext(2, " Unsaved ");
|
|
48
|
+
i0.ɵɵelementEnd();
|
|
49
|
+
} }
|
|
50
|
+
function FlowAgentEditorComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
51
|
+
i0.ɵɵelementStart(0, "span", 16);
|
|
52
|
+
i0.ɵɵtext(1);
|
|
53
|
+
i0.ɵɵpipe(2, "date");
|
|
54
|
+
i0.ɵɵelementEnd();
|
|
55
|
+
} if (rf & 2) {
|
|
56
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
57
|
+
i0.ɵɵadvance();
|
|
58
|
+
i0.ɵɵtextInterpolate1(" Saved ", i0.ɵɵpipeBind2(2, 1, ctx_r1.lastSaved, "shortTime"), " ");
|
|
59
|
+
} }
|
|
60
|
+
function FlowAgentEditorComponent_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
61
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
62
|
+
i0.ɵɵelementStart(0, "button", 33);
|
|
63
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Conditional_21_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Save()); });
|
|
64
|
+
i0.ɵɵelement(1, "i", 34);
|
|
65
|
+
i0.ɵɵtext(2);
|
|
66
|
+
i0.ɵɵelementEnd();
|
|
67
|
+
} if (rf & 2) {
|
|
68
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
69
|
+
i0.ɵɵproperty("disabled", ctx_r1.isSaving || !ctx_r1.hasUnsavedChanges);
|
|
70
|
+
i0.ɵɵadvance();
|
|
71
|
+
i0.ɵɵproperty("ngClass", ctx_r1.isSaving ? "fa-spinner fa-spin" : "fa-floppy-disk");
|
|
72
|
+
i0.ɵɵadvance();
|
|
73
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.isSaving ? "Saving..." : "Save", " ");
|
|
74
|
+
} }
|
|
75
|
+
function FlowAgentEditorComponent_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
76
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
77
|
+
i0.ɵɵelementStart(0, "button", 35);
|
|
78
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Conditional_22_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelFullscreenEdit()); });
|
|
79
|
+
i0.ɵɵelement(1, "i", 36);
|
|
80
|
+
i0.ɵɵtext(2, " Cancel ");
|
|
81
|
+
i0.ɵɵelementEnd();
|
|
82
|
+
} }
|
|
83
|
+
function FlowAgentEditorComponent_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
84
|
+
i0.ɵɵelement(0, "div", 19);
|
|
85
|
+
} }
|
|
86
|
+
function FlowAgentEditorComponent_Conditional_24_Template(rf, ctx) { if (rf & 1) {
|
|
87
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
88
|
+
i0.ɵɵelementStart(0, "button", 37);
|
|
89
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Conditional_24_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleFullscreenEditMode()); });
|
|
90
|
+
i0.ɵɵelement(1, "i", 38);
|
|
91
|
+
i0.ɵɵtext(2, " Edit ");
|
|
92
|
+
i0.ɵɵelementEnd();
|
|
93
|
+
} }
|
|
94
|
+
function FlowAgentEditorComponent_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
95
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
96
|
+
i0.ɵɵelementStart(0, "button", 39);
|
|
97
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Conditional_25_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleFullScreen()); });
|
|
98
|
+
i0.ɵɵelement(1, "i", 40);
|
|
99
|
+
i0.ɵɵtext(2, " Expand ");
|
|
100
|
+
i0.ɵɵelementEnd();
|
|
101
|
+
} }
|
|
102
|
+
function FlowAgentEditorComponent_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
103
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
104
|
+
i0.ɵɵelementStart(0, "button", 41);
|
|
105
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Conditional_26_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleFullScreen()); });
|
|
106
|
+
i0.ɵɵelement(1, "i", 36);
|
|
107
|
+
i0.ɵɵtext(2, " Close ");
|
|
108
|
+
i0.ɵɵelementEnd();
|
|
109
|
+
} }
|
|
110
|
+
function FlowAgentEditorComponent_Conditional_27_Template(rf, ctx) { if (rf & 1) {
|
|
111
|
+
i0.ɵɵelementStart(0, "div", 23);
|
|
112
|
+
i0.ɵɵelement(1, "i", 42);
|
|
113
|
+
i0.ɵɵelementStart(2, "span");
|
|
114
|
+
i0.ɵɵtext(3, "Loading flow...");
|
|
115
|
+
i0.ɵɵelementEnd()();
|
|
116
|
+
} }
|
|
117
|
+
function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
118
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
119
|
+
i0.ɵɵelementStart(0, "div", 43)(1, "mj-flow-editor", 45, 0);
|
|
120
|
+
i0.ɵɵlistener("NodeSelected", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_NodeSelected_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onNodeSelected($event)); })("NodeAdded", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_NodeAdded_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onNodeAdded($event)); })("NodeRemoved", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_NodeRemoved_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onNodeRemoved($event)); })("ConnectionCreated", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_ConnectionCreated_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onConnectionCreated($event)); })("ConnectionRemoved", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_ConnectionRemoved_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onConnectionRemoved($event)); })("ConnectionReassigned", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_ConnectionReassigned_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onConnectionReassigned($event)); })("ConnectionSelected", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_ConnectionSelected_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onConnectionSelected($event)); })("NodesChanged", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_NodesChanged_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onNodesChanged($event)); })("ConnectionsChanged", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_ConnectionsChanged_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onConnectionsChanged($event)); })("GridToggled", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_GridToggled_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onGridPrefChanged($event)); })("MinimapToggled", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_MinimapToggled_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onMinimapPrefChanged($event)); })("LegendToggled", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_flow_editor_LegendToggled_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onLegendPrefChanged($event)); });
|
|
121
|
+
i0.ɵɵelementEnd();
|
|
122
|
+
i0.ɵɵelementStart(3, "div", 46)(4, "mj-agent-properties-panel", 47);
|
|
123
|
+
i0.ɵɵlistener("StepChanged", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_agent_properties_panel_StepChanged_4_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onStepChanged($event)); })("PathChanged", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_agent_properties_panel_PathChanged_4_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onPathChanged($event)); })("DeleteStepRequested", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_agent_properties_panel_DeleteStepRequested_4_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDeleteStepRequested($event)); })("DeletePathRequested", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_agent_properties_panel_DeletePathRequested_4_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDeletePathRequested($event)); })("CloseRequested", function FlowAgentEditorComponent_Conditional_28_Conditional_1_Template_mj_agent_properties_panel_CloseRequested_4_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onCloseProperties()); });
|
|
124
|
+
i0.ɵɵelementEnd()()();
|
|
125
|
+
} if (rf & 2) {
|
|
126
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
127
|
+
i0.ɵɵadvance();
|
|
128
|
+
i0.ɵɵproperty("Nodes", ctx_r1.nodes)("Connections", ctx_r1.connections)("NodeTypes", ctx_r1.nodeTypes)("ReadOnly", !ctx_r1.isEditingActive)("ShowMinimap", ctx_r1.prefShowMinimap)("ShowPalette", ctx_r1.isEditingActive)("ShowGrid", ctx_r1.prefShowGrid)("ShowLegend", ctx_r1.prefShowLegend)("ShowStatusBar", true)("ShowToolbar", true)("AutoLayoutDirection", "vertical");
|
|
129
|
+
i0.ɵɵadvance(2);
|
|
130
|
+
i0.ɵɵclassProp("mj-agent-editor-properties--visible", ctx_r1.showPropertiesPanel);
|
|
131
|
+
i0.ɵɵadvance();
|
|
132
|
+
i0.ɵɵproperty("Step", ctx_r1.selectedStep)("SelectedConnection", ctx_r1.selectedConnection)("PathEntity", ctx_r1.selectedPathEntity)("ReadOnly", !ctx_r1.isEditingActive)("Actions", ctx_r1.availableActions)("Prompts", ctx_r1.availablePrompts)("Agents", ctx_r1.availableAgents)("AllSteps", ctx_r1.steps);
|
|
133
|
+
} }
|
|
134
|
+
function FlowAgentEditorComponent_Conditional_28_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
135
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
136
|
+
i0.ɵɵelementStart(0, "div", 44)(1, "mj-agent-step-list", 48);
|
|
137
|
+
i0.ɵɵlistener("StepClicked", function FlowAgentEditorComponent_Conditional_28_Conditional_2_Template_mj_agent_step_list_StepClicked_1_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onStepClickedInList($event)); });
|
|
138
|
+
i0.ɵɵelementEnd();
|
|
139
|
+
i0.ɵɵelementStart(2, "div", 46)(3, "mj-agent-properties-panel", 47);
|
|
140
|
+
i0.ɵɵlistener("StepChanged", function FlowAgentEditorComponent_Conditional_28_Conditional_2_Template_mj_agent_properties_panel_StepChanged_3_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onStepChanged($event)); })("PathChanged", function FlowAgentEditorComponent_Conditional_28_Conditional_2_Template_mj_agent_properties_panel_PathChanged_3_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onPathChanged($event)); })("DeleteStepRequested", function FlowAgentEditorComponent_Conditional_28_Conditional_2_Template_mj_agent_properties_panel_DeleteStepRequested_3_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDeleteStepRequested($event)); })("DeletePathRequested", function FlowAgentEditorComponent_Conditional_28_Conditional_2_Template_mj_agent_properties_panel_DeletePathRequested_3_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDeletePathRequested($event)); })("CloseRequested", function FlowAgentEditorComponent_Conditional_28_Conditional_2_Template_mj_agent_properties_panel_CloseRequested_3_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onCloseProperties()); });
|
|
141
|
+
i0.ɵɵelementEnd()()();
|
|
142
|
+
} if (rf & 2) {
|
|
143
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
144
|
+
i0.ɵɵadvance();
|
|
145
|
+
i0.ɵɵproperty("Steps", ctx_r1.steps)("Paths", ctx_r1.paths)("SelectedStepID", (ctx_r1.selectedStep == null ? null : ctx_r1.selectedStep.ID) || null);
|
|
146
|
+
i0.ɵɵadvance();
|
|
147
|
+
i0.ɵɵclassProp("mj-agent-editor-properties--visible", ctx_r1.showPropertiesPanel);
|
|
148
|
+
i0.ɵɵadvance();
|
|
149
|
+
i0.ɵɵproperty("Step", ctx_r1.selectedStep)("SelectedConnection", ctx_r1.selectedConnection)("PathEntity", ctx_r1.selectedPathEntity)("ReadOnly", !ctx_r1.isEditingActive)("Actions", ctx_r1.availableActions)("Prompts", ctx_r1.availablePrompts)("Agents", ctx_r1.availableAgents)("AllSteps", ctx_r1.steps);
|
|
150
|
+
} }
|
|
151
|
+
function FlowAgentEditorComponent_Conditional_28_Template(rf, ctx) { if (rf & 1) {
|
|
152
|
+
i0.ɵɵelementStart(0, "div", 24);
|
|
153
|
+
i0.ɵɵconditionalCreate(1, FlowAgentEditorComponent_Conditional_28_Conditional_1_Template, 5, 21, "div", 43);
|
|
154
|
+
i0.ɵɵconditionalCreate(2, FlowAgentEditorComponent_Conditional_28_Conditional_2_Template, 4, 13, "div", 44);
|
|
155
|
+
i0.ɵɵelementEnd();
|
|
156
|
+
} if (rf & 2) {
|
|
157
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
158
|
+
i0.ɵɵadvance();
|
|
159
|
+
i0.ɵɵconditional(ctx_r1.viewMode === "diagram" ? 1 : -1);
|
|
160
|
+
i0.ɵɵadvance();
|
|
161
|
+
i0.ɵɵconditional(ctx_r1.viewMode === "list" ? 2 : -1);
|
|
162
|
+
} }
|
|
163
|
+
function FlowAgentEditorComponent_Conditional_29_Template(rf, ctx) { if (rf & 1) {
|
|
164
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
165
|
+
i0.ɵɵelementStart(0, "div", 25)(1, "div", 49)(2, "div", 50);
|
|
166
|
+
i0.ɵɵelement(3, "i", 51);
|
|
167
|
+
i0.ɵɵelementEnd();
|
|
168
|
+
i0.ɵɵelementStart(4, "h3", 52);
|
|
169
|
+
i0.ɵɵtext(5, "Unsaved Changes");
|
|
170
|
+
i0.ɵɵelementEnd();
|
|
171
|
+
i0.ɵɵelementStart(6, "p", 53);
|
|
172
|
+
i0.ɵɵtext(7, " You have unsaved changes to this flow. What would you like to do? ");
|
|
173
|
+
i0.ɵɵelementEnd();
|
|
174
|
+
i0.ɵɵelementStart(8, "div", 54)(9, "button", 55);
|
|
175
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Conditional_29_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onUnsavedDialogSave()); });
|
|
176
|
+
i0.ɵɵelement(10, "i", 56);
|
|
177
|
+
i0.ɵɵtext(11, " Save & Close ");
|
|
178
|
+
i0.ɵɵelementEnd();
|
|
179
|
+
i0.ɵɵelementStart(12, "button", 57);
|
|
180
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Conditional_29_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onUnsavedDialogDiscard()); });
|
|
181
|
+
i0.ɵɵtext(13, " Discard Changes ");
|
|
182
|
+
i0.ɵɵelementEnd();
|
|
183
|
+
i0.ɵɵelementStart(14, "button", 58);
|
|
184
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Conditional_29_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onUnsavedDialogCancel()); });
|
|
185
|
+
i0.ɵɵtext(15, " Cancel ");
|
|
186
|
+
i0.ɵɵelementEnd()()()();
|
|
187
|
+
} }
|
|
188
|
+
/**
|
|
189
|
+
* Flow Agent Editor — wraps the generic FlowEditorComponent with
|
|
190
|
+
* MJ agent-specific CRUD, properties panel, and data transformation.
|
|
191
|
+
*/
|
|
192
|
+
export class FlowAgentEditorComponent {
|
|
193
|
+
cdr;
|
|
194
|
+
transformer;
|
|
195
|
+
elRef;
|
|
196
|
+
renderer;
|
|
197
|
+
// ── Host Bindings ─────────────────────────────────────────────
|
|
198
|
+
get HostFullScreen() { return this.FullScreen; }
|
|
199
|
+
// ── Inputs ──────────────────────────────────────────────────
|
|
200
|
+
AgentID = null;
|
|
201
|
+
EditMode = true;
|
|
202
|
+
FullScreen = false;
|
|
203
|
+
// ── Outputs ─────────────────────────────────────────────────
|
|
204
|
+
FlowSaved = new EventEmitter();
|
|
205
|
+
FlowChanged = new EventEmitter();
|
|
206
|
+
FullScreenToggled = new EventEmitter();
|
|
207
|
+
StepSelected = new EventEmitter();
|
|
208
|
+
// ── View Children ───────────────────────────────────────────
|
|
209
|
+
flowEditor;
|
|
210
|
+
// ── State ───────────────────────────────────────────────────
|
|
211
|
+
nodes = [];
|
|
212
|
+
connections = [];
|
|
213
|
+
nodeTypes = AGENT_STEP_TYPE_CONFIGS;
|
|
214
|
+
viewMode = 'diagram';
|
|
215
|
+
isLoading = true;
|
|
216
|
+
isSaving = false;
|
|
217
|
+
hasUnsavedChanges = false;
|
|
218
|
+
lastSaved = null;
|
|
219
|
+
// Fullscreen self-contained edit mode
|
|
220
|
+
fullscreenEditMode = false;
|
|
221
|
+
showUnsavedDialog = false;
|
|
222
|
+
// Entity data
|
|
223
|
+
steps = [];
|
|
224
|
+
paths = [];
|
|
225
|
+
deletedStepIDs = [];
|
|
226
|
+
deletedPathIDs = [];
|
|
227
|
+
// Selected items
|
|
228
|
+
selectedStep = null;
|
|
229
|
+
selectedConnection = null;
|
|
230
|
+
selectedPathEntity = null;
|
|
231
|
+
showPropertiesPanel = false;
|
|
232
|
+
// Picker data (includes icon fields for node rendering)
|
|
233
|
+
availableActions = [];
|
|
234
|
+
availablePrompts = [];
|
|
235
|
+
availableAgents = [];
|
|
236
|
+
// Permission state — cached once on init
|
|
237
|
+
userCanUpdate = false;
|
|
238
|
+
// User view preferences (persisted via UserInfoEngine)
|
|
239
|
+
prefShowGrid = true;
|
|
240
|
+
prefShowMinimap = true;
|
|
241
|
+
prefShowLegend = true;
|
|
242
|
+
static PREF_KEY = 'flow-editor/view-prefs';
|
|
243
|
+
// Initial zoom state
|
|
244
|
+
needsInitialZoom = false;
|
|
245
|
+
resizeObserver = null;
|
|
246
|
+
// Fullscreen DOM relocation state
|
|
247
|
+
originalParent = null;
|
|
248
|
+
originalNextSibling = null;
|
|
249
|
+
backdropElement = null;
|
|
250
|
+
constructor(cdr, transformer, elRef, renderer) {
|
|
251
|
+
this.cdr = cdr;
|
|
252
|
+
this.transformer = transformer;
|
|
253
|
+
this.elRef = elRef;
|
|
254
|
+
this.renderer = renderer;
|
|
255
|
+
}
|
|
256
|
+
// ── Lifecycle ───────────────────────────────────────────────
|
|
257
|
+
ngOnInit() {
|
|
258
|
+
this.loadViewPreferences();
|
|
259
|
+
this.checkUpdatePermission();
|
|
260
|
+
if (this.AgentID) {
|
|
261
|
+
this.loadAll();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
ngOnChanges(changes) {
|
|
265
|
+
if (changes['AgentID'] && !changes['AgentID'].firstChange && this.AgentID) {
|
|
266
|
+
this.loadAll();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
ngOnDestroy() {
|
|
270
|
+
this.teardownResizeObserver();
|
|
271
|
+
// Restore element to original parent if still in fullscreen
|
|
272
|
+
if (this.FullScreen) {
|
|
273
|
+
this.restoreFromFullscreen();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// ── Data Loading ────────────────────────────────────────────
|
|
277
|
+
async loadAll() {
|
|
278
|
+
this.isLoading = true;
|
|
279
|
+
this.cdr.detectChanges();
|
|
280
|
+
try {
|
|
281
|
+
await Promise.all([
|
|
282
|
+
this.loadStepsAndPaths(),
|
|
283
|
+
this.loadPickerData()
|
|
284
|
+
]);
|
|
285
|
+
this.rebuildFlowModel();
|
|
286
|
+
}
|
|
287
|
+
finally {
|
|
288
|
+
this.isLoading = false;
|
|
289
|
+
this.cdr.detectChanges();
|
|
290
|
+
// Flag that we need an initial zoom; it will fire when the host element
|
|
291
|
+
// first becomes visible (e.g. Kendo PanelBar expands)
|
|
292
|
+
this.setupInitialZoomObserver();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
async loadStepsAndPaths() {
|
|
296
|
+
if (!this.AgentID)
|
|
297
|
+
return;
|
|
298
|
+
const rv = new RunView();
|
|
299
|
+
const [stepsResult, pathsResult] = await rv.RunViews([
|
|
300
|
+
{
|
|
301
|
+
EntityName: 'MJ: AI Agent Steps',
|
|
302
|
+
ExtraFilter: `AgentID='${this.AgentID}'`,
|
|
303
|
+
OrderBy: 'Name ASC',
|
|
304
|
+
ResultType: 'entity_object'
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
EntityName: 'MJ: AI Agent Step Paths',
|
|
308
|
+
ExtraFilter: `OriginStepID IN (SELECT ID FROM [__mj].[AIAgentStep] WHERE AgentID='${this.AgentID}')`,
|
|
309
|
+
OrderBy: 'Priority DESC',
|
|
310
|
+
ResultType: 'entity_object'
|
|
311
|
+
}
|
|
312
|
+
]);
|
|
313
|
+
this.steps = stepsResult.Success ? stepsResult.Results : [];
|
|
314
|
+
this.paths = pathsResult.Success ? pathsResult.Results : [];
|
|
315
|
+
this.deletedStepIDs = [];
|
|
316
|
+
this.deletedPathIDs = [];
|
|
317
|
+
}
|
|
318
|
+
async loadPickerData() {
|
|
319
|
+
const rv = new RunView();
|
|
320
|
+
const [actionsResult, promptsResult, agentsResult] = await rv.RunViews([
|
|
321
|
+
{
|
|
322
|
+
EntityName: 'Actions',
|
|
323
|
+
Fields: ['ID', 'Name', 'IconClass'],
|
|
324
|
+
ExtraFilter: `Status='Active'`,
|
|
325
|
+
OrderBy: 'Name ASC',
|
|
326
|
+
ResultType: 'simple'
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
EntityName: 'AI Prompts',
|
|
330
|
+
Fields: ['ID', 'Name'],
|
|
331
|
+
ExtraFilter: '',
|
|
332
|
+
OrderBy: 'Name ASC',
|
|
333
|
+
ResultType: 'simple'
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
EntityName: 'AI Agents',
|
|
337
|
+
Fields: ['ID', 'Name', 'IconClass', 'LogoURL'],
|
|
338
|
+
ExtraFilter: this.AgentID ? `ID <> '${this.AgentID}'` : '',
|
|
339
|
+
OrderBy: 'Name ASC',
|
|
340
|
+
ResultType: 'simple'
|
|
341
|
+
}
|
|
342
|
+
]);
|
|
343
|
+
this.availableActions = actionsResult.Success
|
|
344
|
+
? actionsResult.Results
|
|
345
|
+
: [];
|
|
346
|
+
this.availablePrompts = promptsResult.Success
|
|
347
|
+
? promptsResult.Results
|
|
348
|
+
: [];
|
|
349
|
+
this.availableAgents = agentsResult.Success
|
|
350
|
+
? agentsResult.Results
|
|
351
|
+
: [];
|
|
352
|
+
}
|
|
353
|
+
rebuildFlowModel() {
|
|
354
|
+
this.nodes = this.transformer.StepsToNodes(this.steps, this.availableActions, this.availableAgents);
|
|
355
|
+
this.connections = this.transformer.PathsToConnections(this.paths);
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Observe the host element's size. When it transitions from zero to non-zero height
|
|
359
|
+
* (i.e. the collapsed Kendo panel expands), trigger the initial auto-arrange or zoom-to-fit.
|
|
360
|
+
*/
|
|
361
|
+
setupInitialZoomObserver() {
|
|
362
|
+
if (this.nodes.length === 0)
|
|
363
|
+
return;
|
|
364
|
+
this.needsInitialZoom = true;
|
|
365
|
+
this.teardownResizeObserver();
|
|
366
|
+
this.resizeObserver = new ResizeObserver((entries) => {
|
|
367
|
+
for (const entry of entries) {
|
|
368
|
+
const height = entry.contentRect.height;
|
|
369
|
+
if (height > 0 && this.needsInitialZoom) {
|
|
370
|
+
this.needsInitialZoom = false;
|
|
371
|
+
this.teardownResizeObserver();
|
|
372
|
+
// Short delay for Foblex canvas to finish its own init after becoming visible
|
|
373
|
+
setTimeout(() => this.applyInitialZoom(), 100);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
this.resizeObserver.observe(this.elRef.nativeElement);
|
|
378
|
+
}
|
|
379
|
+
applyInitialZoom() {
|
|
380
|
+
if (!this.flowEditor || this.nodes.length === 0)
|
|
381
|
+
return;
|
|
382
|
+
const allAtOrigin = this.nodes.every(n => n.Position.X === 0 && n.Position.Y === 0);
|
|
383
|
+
if (allAtOrigin) {
|
|
384
|
+
this.flowEditor.AutoArrange();
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
this.flowEditor.ZoomToFit();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
teardownResizeObserver() {
|
|
391
|
+
if (this.resizeObserver) {
|
|
392
|
+
this.resizeObserver.disconnect();
|
|
393
|
+
this.resizeObserver = null;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
// ── Save ────────────────────────────────────────────────────
|
|
397
|
+
async Save() {
|
|
398
|
+
if (this.isSaving || !this.AgentID)
|
|
399
|
+
return;
|
|
400
|
+
this.isSaving = true;
|
|
401
|
+
this.cdr.detectChanges();
|
|
402
|
+
try {
|
|
403
|
+
// Update positions from canvas to entities
|
|
404
|
+
this.syncPositionsFromCanvas();
|
|
405
|
+
// Delete removed items first
|
|
406
|
+
await this.deleteRemovedEntities();
|
|
407
|
+
// Save all steps
|
|
408
|
+
for (const step of this.steps) {
|
|
409
|
+
const result = await step.Save();
|
|
410
|
+
if (!result) {
|
|
411
|
+
console.error(`Failed to save step: ${step.Name}`, step.LatestResult);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// Save all paths
|
|
415
|
+
for (const path of this.paths) {
|
|
416
|
+
const result = await path.Save();
|
|
417
|
+
if (!result) {
|
|
418
|
+
console.error(`Failed to save path: ${path.ID}`, path.LatestResult);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
this.hasUnsavedChanges = false;
|
|
422
|
+
this.lastSaved = new Date();
|
|
423
|
+
// Exit self-contained fullscreen edit mode after successful save
|
|
424
|
+
if (this.fullscreenEditMode) {
|
|
425
|
+
this.fullscreenEditMode = false;
|
|
426
|
+
}
|
|
427
|
+
this.FlowSaved.emit();
|
|
428
|
+
}
|
|
429
|
+
catch (err) {
|
|
430
|
+
console.error('Error saving flow:', err);
|
|
431
|
+
}
|
|
432
|
+
finally {
|
|
433
|
+
this.isSaving = false;
|
|
434
|
+
this.cdr.detectChanges();
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
syncPositionsFromCanvas() {
|
|
438
|
+
this.syncPositionsToEntities();
|
|
439
|
+
}
|
|
440
|
+
/** Write current FlowNode positions back to the underlying step entities.
|
|
441
|
+
* Called on every node move so that rebuildFlowModel() never loses drag changes. */
|
|
442
|
+
syncPositionsToEntities() {
|
|
443
|
+
for (const node of this.nodes) {
|
|
444
|
+
const step = this.steps.find(s => s.ID === node.ID);
|
|
445
|
+
if (step) {
|
|
446
|
+
this.transformer.ApplyNodePosition(step, node);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
async deleteRemovedEntities() {
|
|
451
|
+
const md = new Metadata();
|
|
452
|
+
for (const pathId of this.deletedPathIDs) {
|
|
453
|
+
const pathEntity = await md.GetEntityObject('MJ: AI Agent Step Paths');
|
|
454
|
+
await pathEntity.InnerLoad(CompositeKey.FromID(pathId));
|
|
455
|
+
await pathEntity.Delete();
|
|
456
|
+
}
|
|
457
|
+
for (const stepId of this.deletedStepIDs) {
|
|
458
|
+
const stepEntity = await md.GetEntityObject('MJ: AI Agent Steps');
|
|
459
|
+
await stepEntity.InnerLoad(CompositeKey.FromID(stepId));
|
|
460
|
+
await stepEntity.Delete();
|
|
461
|
+
}
|
|
462
|
+
this.deletedPathIDs = [];
|
|
463
|
+
this.deletedStepIDs = [];
|
|
464
|
+
}
|
|
465
|
+
// ── Flow Editor Event Handlers ──────────────────────────────
|
|
466
|
+
async onNodeAdded(event) {
|
|
467
|
+
if (!this.AgentID)
|
|
468
|
+
return;
|
|
469
|
+
const md = new Metadata();
|
|
470
|
+
const step = await md.GetEntityObject('MJ: AI Agent Steps');
|
|
471
|
+
step.NewRecord(); // This generates a UUID immediately - available before Save()
|
|
472
|
+
step.AgentID = this.AgentID;
|
|
473
|
+
step.Name = event.Node.Label;
|
|
474
|
+
step.StepType = event.Node.Type;
|
|
475
|
+
step.Status = 'Active';
|
|
476
|
+
step.StartingStep = this.steps.length === 0; // First step is starting step
|
|
477
|
+
step.PositionX = Math.round(event.DropPosition.X);
|
|
478
|
+
step.PositionY = Math.round(event.DropPosition.Y);
|
|
479
|
+
step.OnErrorBehavior = 'fail';
|
|
480
|
+
step.RetryCount = 0;
|
|
481
|
+
step.TimeoutSeconds = 600;
|
|
482
|
+
// Add the unsaved step to the array - it already has a UUID from NewRecord()
|
|
483
|
+
// This allows connections to be drawn immediately without waiting for a database save
|
|
484
|
+
this.steps.push(step);
|
|
485
|
+
// Build a FlowNode using the entity's pre-generated ID so Foblex can track it
|
|
486
|
+
const newNode = this.transformer.StepToNode(step, this.availableActions, this.availableAgents);
|
|
487
|
+
this.nodes.push(newNode);
|
|
488
|
+
this.markDirty();
|
|
489
|
+
// Select the new node
|
|
490
|
+
setTimeout(() => {
|
|
491
|
+
this.flowEditor?.SelectNode(step.ID);
|
|
492
|
+
this.onNodeSelected(newNode);
|
|
493
|
+
}, 100);
|
|
494
|
+
this.cdr.detectChanges();
|
|
495
|
+
}
|
|
496
|
+
async onConnectionCreated(event) {
|
|
497
|
+
if (!this.AgentID)
|
|
498
|
+
return;
|
|
499
|
+
// Prevent duplicate
|
|
500
|
+
const exists = this.paths.some(p => p.OriginStepID === event.SourceNodeID && p.DestinationStepID === event.TargetNodeID);
|
|
501
|
+
if (exists)
|
|
502
|
+
return;
|
|
503
|
+
const md = new Metadata();
|
|
504
|
+
const path = await md.GetEntityObject('MJ: AI Agent Step Paths');
|
|
505
|
+
path.NewRecord(); // Generates UUID immediately - available before Save()
|
|
506
|
+
path.OriginStepID = event.SourceNodeID;
|
|
507
|
+
path.DestinationStepID = event.TargetNodeID;
|
|
508
|
+
path.Priority = 0;
|
|
509
|
+
// Add unsaved path to the array - save will happen on main Save() button
|
|
510
|
+
this.paths.push(path);
|
|
511
|
+
this.rebuildFlowModel();
|
|
512
|
+
this.markDirty();
|
|
513
|
+
this.cdr.detectChanges();
|
|
514
|
+
}
|
|
515
|
+
onNodeSelected(node) {
|
|
516
|
+
if (node) {
|
|
517
|
+
this.selectedStep = this.steps.find(s => s.ID === node.ID) ?? null;
|
|
518
|
+
this.selectedConnection = null;
|
|
519
|
+
this.selectedPathEntity = null;
|
|
520
|
+
this.showPropertiesPanel = true;
|
|
521
|
+
this.StepSelected.emit(this.selectedStep);
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
this.selectedStep = null;
|
|
525
|
+
// Only hide the panel if no connection is currently selected.
|
|
526
|
+
// When the user clicks a connection, Foblex fires NodeSelected(null) AND
|
|
527
|
+
// ConnectionSelected(conn) — we must not let the null-node event hide
|
|
528
|
+
// the panel that the connection event just opened.
|
|
529
|
+
if (!this.selectedConnection) {
|
|
530
|
+
this.showPropertiesPanel = false;
|
|
531
|
+
}
|
|
532
|
+
this.StepSelected.emit(null);
|
|
533
|
+
}
|
|
534
|
+
this.cdr.detectChanges();
|
|
535
|
+
}
|
|
536
|
+
onConnectionSelected(conn) {
|
|
537
|
+
if (conn) {
|
|
538
|
+
this.selectedConnection = conn;
|
|
539
|
+
this.selectedPathEntity = this.paths.find(p => p.ID === conn.ID) ?? null;
|
|
540
|
+
this.selectedStep = null;
|
|
541
|
+
this.showPropertiesPanel = true;
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
this.selectedConnection = null;
|
|
545
|
+
this.selectedPathEntity = null;
|
|
546
|
+
}
|
|
547
|
+
this.cdr.detectChanges();
|
|
548
|
+
}
|
|
549
|
+
onNodeRemoved(node) {
|
|
550
|
+
const step = this.steps.find(s => s.ID === node.ID);
|
|
551
|
+
if (step) {
|
|
552
|
+
// Track for deletion on save (only if it was previously saved)
|
|
553
|
+
if (step.IsSaved) {
|
|
554
|
+
this.deletedStepIDs.push(step.ID);
|
|
555
|
+
// Also mark paths connected to this step for deletion
|
|
556
|
+
const connectedPaths = this.paths.filter(p => p.OriginStepID === step.ID || p.DestinationStepID === step.ID);
|
|
557
|
+
for (const path of connectedPaths) {
|
|
558
|
+
if (path.IsSaved) {
|
|
559
|
+
this.deletedPathIDs.push(path.ID);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
this.steps = this.steps.filter(s => s.ID !== node.ID);
|
|
564
|
+
this.paths = this.paths.filter(p => p.OriginStepID !== node.ID && p.DestinationStepID !== node.ID);
|
|
565
|
+
this.markDirty();
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
onConnectionRemoved(conn) {
|
|
569
|
+
const path = this.paths.find(p => p.ID === conn.ID);
|
|
570
|
+
if (path) {
|
|
571
|
+
if (path.IsSaved) {
|
|
572
|
+
this.deletedPathIDs.push(path.ID);
|
|
573
|
+
}
|
|
574
|
+
this.paths = this.paths.filter(p => p.ID !== conn.ID);
|
|
575
|
+
this.markDirty();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
onConnectionReassigned(event) {
|
|
579
|
+
const path = this.paths.find(p => p.ID === event.ConnectionID);
|
|
580
|
+
if (!path)
|
|
581
|
+
return;
|
|
582
|
+
// Update the entity's origin/destination to match the new visual endpoints
|
|
583
|
+
path.OriginStepID = event.NewSourceNodeID;
|
|
584
|
+
path.DestinationStepID = event.NewTargetNodeID;
|
|
585
|
+
// Rebuild all connections so sibling-based visual logic recalculates
|
|
586
|
+
// (e.g., Default vs Duplicate Default labels depend on sibling analysis)
|
|
587
|
+
this.rebuildFlowModel();
|
|
588
|
+
this.markDirty();
|
|
589
|
+
this.cdr.detectChanges();
|
|
590
|
+
}
|
|
591
|
+
onNodesChanged(nodes) {
|
|
592
|
+
this.nodes = nodes;
|
|
593
|
+
// Sync canvas positions back to entities immediately so that
|
|
594
|
+
// any subsequent rebuildFlowModel() preserves drag changes.
|
|
595
|
+
this.syncPositionsToEntities();
|
|
596
|
+
this.markDirty();
|
|
597
|
+
}
|
|
598
|
+
onConnectionsChanged(connections) {
|
|
599
|
+
this.connections = connections;
|
|
600
|
+
this.markDirty();
|
|
601
|
+
}
|
|
602
|
+
// ── Properties Panel Events ─────────────────────────────────
|
|
603
|
+
onStepChanged(step) {
|
|
604
|
+
// Update the corresponding flow node in-place and push to generic editor
|
|
605
|
+
const node = this.nodes.find(n => n.ID === step.ID);
|
|
606
|
+
if (node) {
|
|
607
|
+
const newLabel = step.Name;
|
|
608
|
+
const newSubtitle = this.transformer.BuildStepSubtitle(step);
|
|
609
|
+
const baseStatus = this.transformer.MapStepStatus(step.Status);
|
|
610
|
+
const warningMessage = (baseStatus !== 'disabled') ? this.transformer.BuildConfigWarningMessage(step) : null;
|
|
611
|
+
const newStatus = warningMessage ? 'warning' : baseStatus;
|
|
612
|
+
const newIsStart = step.StartingStep === true;
|
|
613
|
+
node.Label = newLabel;
|
|
614
|
+
node.Subtitle = newSubtitle;
|
|
615
|
+
node.Status = newStatus;
|
|
616
|
+
node.StatusMessage = warningMessage ?? undefined;
|
|
617
|
+
node.IsStartNode = newIsStart;
|
|
618
|
+
// Update input port disabled state for starting steps
|
|
619
|
+
const inputPort = node.Ports.find(p => p.Direction === 'input');
|
|
620
|
+
if (inputPort) {
|
|
621
|
+
inputPort.Disabled = newIsStart;
|
|
622
|
+
}
|
|
623
|
+
// Re-resolve icon from picker data (handles action/agent assignment changes)
|
|
624
|
+
const resolved = this.transformer.ResolveStepIcon(step, this.availableActions, this.availableAgents);
|
|
625
|
+
node.Icon = resolved.Icon;
|
|
626
|
+
if (!node.Data)
|
|
627
|
+
node.Data = {};
|
|
628
|
+
node.Data['LogoURL'] = resolved.LogoURL ?? null;
|
|
629
|
+
// For loop nodes, rebuild the loop-specific Data properties so the
|
|
630
|
+
// inner body card updates immediately when the user changes body type / config
|
|
631
|
+
if (step.StepType === 'ForEach' || step.StepType === 'While') {
|
|
632
|
+
this.updateLoopNodeData(step, node);
|
|
633
|
+
}
|
|
634
|
+
// Push visual update to the generic flow editor (creates new object ref for OnPush)
|
|
635
|
+
this.flowEditor?.UpdateNode(step.ID, {
|
|
636
|
+
Label: newLabel,
|
|
637
|
+
Subtitle: newSubtitle,
|
|
638
|
+
Status: newStatus,
|
|
639
|
+
StatusMessage: warningMessage ?? undefined,
|
|
640
|
+
IsStartNode: newIsStart,
|
|
641
|
+
Icon: resolved.Icon,
|
|
642
|
+
Data: node.Data
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
this.markDirty();
|
|
646
|
+
this.cdr.detectChanges();
|
|
647
|
+
}
|
|
648
|
+
/** Update loop-specific data fields on a FlowNode from the step entity */
|
|
649
|
+
updateLoopNodeData(step, node) {
|
|
650
|
+
if (!node.Data)
|
|
651
|
+
node.Data = {};
|
|
652
|
+
// Delegate to the transformer's public methods for consistency
|
|
653
|
+
const bodyType = step.LoopBodyType;
|
|
654
|
+
node.Data['LoopBodyType'] = bodyType ?? null;
|
|
655
|
+
node.Data['LoopBodyName'] = this.resolveLoopBodyNameFromStep(step);
|
|
656
|
+
node.Data['LoopBodyIcon'] = this.getBodyTypeIcon(bodyType);
|
|
657
|
+
node.Data['LoopBodyColor'] = this.getBodyTypeColor(bodyType);
|
|
658
|
+
node.Data['LoopIterationSummary'] = this.transformer.BuildLoopIterationSummary(step);
|
|
659
|
+
}
|
|
660
|
+
resolveLoopBodyNameFromStep(step) {
|
|
661
|
+
switch (step.LoopBodyType) {
|
|
662
|
+
case 'Action': return step.Action ?? null;
|
|
663
|
+
case 'Prompt': return step.Prompt ?? null;
|
|
664
|
+
case 'Sub-Agent': return step.SubAgent ?? null;
|
|
665
|
+
default: return null;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
getBodyTypeIcon(bodyType) {
|
|
669
|
+
switch (bodyType) {
|
|
670
|
+
case 'Action': return 'fa-bolt';
|
|
671
|
+
case 'Prompt': return 'fa-comment-dots';
|
|
672
|
+
case 'Sub-Agent': return 'fa-robot';
|
|
673
|
+
default: return 'fa-circle-nodes';
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
getBodyTypeColor(bodyType) {
|
|
677
|
+
switch (bodyType) {
|
|
678
|
+
case 'Action': return '#3B82F6';
|
|
679
|
+
case 'Prompt': return '#8B5CF6';
|
|
680
|
+
case 'Sub-Agent': return '#10B981';
|
|
681
|
+
default: return '#6B7280';
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
onPathChanged(path) {
|
|
685
|
+
// Rebuild all connections from the same origin since always/conditional logic
|
|
686
|
+
// depends on sibling paths (e.g., "Default" label only appears when siblings exist)
|
|
687
|
+
this.rebuildFlowModel();
|
|
688
|
+
this.markDirty();
|
|
689
|
+
this.cdr.detectChanges();
|
|
690
|
+
}
|
|
691
|
+
onDeleteStepRequested(step) {
|
|
692
|
+
const node = this.nodes.find(n => n.ID === step.ID);
|
|
693
|
+
if (node) {
|
|
694
|
+
this.flowEditor?.SelectNode(step.ID);
|
|
695
|
+
this.flowEditor?.DeleteSelected();
|
|
696
|
+
}
|
|
697
|
+
this.showPropertiesPanel = false;
|
|
698
|
+
this.selectedStep = null;
|
|
699
|
+
this.cdr.detectChanges();
|
|
700
|
+
}
|
|
701
|
+
onDeletePathRequested(path) {
|
|
702
|
+
const conn = this.connections.find(c => c.ID === path.ID);
|
|
703
|
+
if (conn) {
|
|
704
|
+
if (path.IsSaved) {
|
|
705
|
+
this.deletedPathIDs.push(path.ID);
|
|
706
|
+
}
|
|
707
|
+
this.paths = this.paths.filter(p => p.ID !== path.ID);
|
|
708
|
+
this.rebuildFlowModel();
|
|
709
|
+
this.markDirty();
|
|
710
|
+
}
|
|
711
|
+
this.showPropertiesPanel = false;
|
|
712
|
+
this.selectedConnection = null;
|
|
713
|
+
this.selectedPathEntity = null;
|
|
714
|
+
this.cdr.detectChanges();
|
|
715
|
+
}
|
|
716
|
+
onCloseProperties() {
|
|
717
|
+
this.showPropertiesPanel = false;
|
|
718
|
+
this.flowEditor?.ClearSelection();
|
|
719
|
+
}
|
|
720
|
+
// ── View & UI Controls ──────────────────────────────────────
|
|
721
|
+
toggleViewMode() {
|
|
722
|
+
this.viewMode = this.viewMode === 'diagram' ? 'list' : 'diagram';
|
|
723
|
+
this.cdr.detectChanges();
|
|
724
|
+
}
|
|
725
|
+
/** Whether editing is currently allowed — combines parent EditMode + fullscreen self-contained edit */
|
|
726
|
+
get isEditingActive() {
|
|
727
|
+
return this.EditMode || this.fullscreenEditMode;
|
|
728
|
+
}
|
|
729
|
+
toggleFullscreenEditMode() {
|
|
730
|
+
this.fullscreenEditMode = !this.fullscreenEditMode;
|
|
731
|
+
this.cdr.detectChanges();
|
|
732
|
+
}
|
|
733
|
+
cancelFullscreenEdit() {
|
|
734
|
+
if (this.hasUnsavedChanges) {
|
|
735
|
+
// Reload to discard changes
|
|
736
|
+
this.fullscreenEditMode = false;
|
|
737
|
+
this.hasUnsavedChanges = false;
|
|
738
|
+
this.loadAll();
|
|
739
|
+
}
|
|
740
|
+
else {
|
|
741
|
+
this.fullscreenEditMode = false;
|
|
742
|
+
this.cdr.detectChanges();
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
toggleFullScreen() {
|
|
746
|
+
if (this.FullScreen && this.hasUnsavedChanges) {
|
|
747
|
+
this.showUnsavedDialog = true;
|
|
748
|
+
this.cdr.detectChanges();
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
this.performFullscreenToggle();
|
|
752
|
+
}
|
|
753
|
+
onUnsavedDialogSave() {
|
|
754
|
+
this.showUnsavedDialog = false;
|
|
755
|
+
this.Save().then(() => this.performFullscreenToggle());
|
|
756
|
+
}
|
|
757
|
+
onUnsavedDialogDiscard() {
|
|
758
|
+
this.showUnsavedDialog = false;
|
|
759
|
+
this.hasUnsavedChanges = false;
|
|
760
|
+
this.fullscreenEditMode = false;
|
|
761
|
+
this.performFullscreenToggle();
|
|
762
|
+
// Reload original data
|
|
763
|
+
this.loadAll();
|
|
764
|
+
}
|
|
765
|
+
onUnsavedDialogCancel() {
|
|
766
|
+
this.showUnsavedDialog = false;
|
|
767
|
+
this.cdr.detectChanges();
|
|
768
|
+
}
|
|
769
|
+
performFullscreenToggle() {
|
|
770
|
+
this.FullScreen = !this.FullScreen;
|
|
771
|
+
if (this.FullScreen) {
|
|
772
|
+
this.moveToBodyForFullscreen();
|
|
773
|
+
}
|
|
774
|
+
else {
|
|
775
|
+
this.fullscreenEditMode = false;
|
|
776
|
+
this.restoreFromFullscreen();
|
|
777
|
+
}
|
|
778
|
+
this.FullScreenToggled.emit(this.FullScreen);
|
|
779
|
+
this.cdr.detectChanges();
|
|
780
|
+
// Re-fit after layout change
|
|
781
|
+
setTimeout(() => this.flowEditor?.ZoomToFit(), 200);
|
|
782
|
+
}
|
|
783
|
+
moveToBodyForFullscreen() {
|
|
784
|
+
const hostEl = this.elRef.nativeElement;
|
|
785
|
+
this.originalParent = hostEl.parentElement;
|
|
786
|
+
this.originalNextSibling = hostEl.nextSibling;
|
|
787
|
+
// Create backdrop as a separate body-level element so it covers everything
|
|
788
|
+
this.backdropElement = this.renderer.createElement('div');
|
|
789
|
+
this.renderer.addClass(this.backdropElement, 'mj-agent-editor-backdrop');
|
|
790
|
+
this.renderer.listen(this.backdropElement, 'click', () => this.toggleFullScreen());
|
|
791
|
+
this.renderer.appendChild(document.body, this.backdropElement);
|
|
792
|
+
// Move the host element to body — @HostBinding applies the fixed-position class
|
|
793
|
+
this.renderer.appendChild(document.body, hostEl);
|
|
794
|
+
}
|
|
795
|
+
restoreFromFullscreen() {
|
|
796
|
+
// Remove backdrop
|
|
797
|
+
if (this.backdropElement) {
|
|
798
|
+
this.renderer.removeChild(document.body, this.backdropElement);
|
|
799
|
+
this.backdropElement = null;
|
|
800
|
+
}
|
|
801
|
+
// Restore host element to original position
|
|
802
|
+
if (!this.originalParent)
|
|
803
|
+
return;
|
|
804
|
+
const hostEl = this.elRef.nativeElement;
|
|
805
|
+
if (this.originalNextSibling) {
|
|
806
|
+
this.renderer.insertBefore(this.originalParent, hostEl, this.originalNextSibling);
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
this.renderer.appendChild(this.originalParent, hostEl);
|
|
810
|
+
}
|
|
811
|
+
this.originalParent = null;
|
|
812
|
+
this.originalNextSibling = null;
|
|
813
|
+
}
|
|
814
|
+
onStepClickedInList(step) {
|
|
815
|
+
this.selectedStep = step;
|
|
816
|
+
this.selectedConnection = null;
|
|
817
|
+
this.selectedPathEntity = null;
|
|
818
|
+
this.showPropertiesPanel = true;
|
|
819
|
+
this.StepSelected.emit(step);
|
|
820
|
+
this.cdr.detectChanges();
|
|
821
|
+
}
|
|
822
|
+
// ── Keyboard Shortcuts ─────────────────────────────────────
|
|
823
|
+
onEscapeKey() {
|
|
824
|
+
if (this.showUnsavedDialog) {
|
|
825
|
+
this.onUnsavedDialogCancel();
|
|
826
|
+
}
|
|
827
|
+
else if (this.FullScreen) {
|
|
828
|
+
this.toggleFullScreen();
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
// ── Permission Check ────────────────────────────────────────
|
|
832
|
+
checkUpdatePermission() {
|
|
833
|
+
const md = new Metadata();
|
|
834
|
+
const entity = md.EntityByName('AI Agents');
|
|
835
|
+
if (entity) {
|
|
836
|
+
const perms = entity.GetUserPermisions(md.CurrentUser);
|
|
837
|
+
this.userCanUpdate = perms?.CanUpdate === true;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
// ── View Preference Persistence ─────────────────────────────
|
|
841
|
+
loadViewPreferences() {
|
|
842
|
+
const raw = UserInfoEngine.Instance.GetSetting(FlowAgentEditorComponent.PREF_KEY);
|
|
843
|
+
if (raw) {
|
|
844
|
+
try {
|
|
845
|
+
const prefs = JSON.parse(raw);
|
|
846
|
+
if (prefs.grid != null)
|
|
847
|
+
this.prefShowGrid = prefs.grid;
|
|
848
|
+
if (prefs.minimap != null)
|
|
849
|
+
this.prefShowMinimap = prefs.minimap;
|
|
850
|
+
if (prefs.legend != null)
|
|
851
|
+
this.prefShowLegend = prefs.legend;
|
|
852
|
+
}
|
|
853
|
+
catch {
|
|
854
|
+
// Ignore malformed preference data
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
saveViewPreferences() {
|
|
859
|
+
const prefs = JSON.stringify({
|
|
860
|
+
grid: this.prefShowGrid,
|
|
861
|
+
minimap: this.prefShowMinimap,
|
|
862
|
+
legend: this.prefShowLegend
|
|
863
|
+
});
|
|
864
|
+
// Fire-and-forget — preference save errors are non-critical
|
|
865
|
+
UserInfoEngine.Instance.SetSetting(FlowAgentEditorComponent.PREF_KEY, prefs);
|
|
866
|
+
}
|
|
867
|
+
onGridPrefChanged(show) {
|
|
868
|
+
this.prefShowGrid = show;
|
|
869
|
+
this.saveViewPreferences();
|
|
870
|
+
}
|
|
871
|
+
onMinimapPrefChanged(show) {
|
|
872
|
+
this.prefShowMinimap = show;
|
|
873
|
+
this.saveViewPreferences();
|
|
874
|
+
}
|
|
875
|
+
onLegendPrefChanged(show) {
|
|
876
|
+
this.prefShowLegend = show;
|
|
877
|
+
this.saveViewPreferences();
|
|
878
|
+
}
|
|
879
|
+
// ── Helpers ─────────────────────────────────────────────────
|
|
880
|
+
markDirty() {
|
|
881
|
+
if (!this.hasUnsavedChanges) {
|
|
882
|
+
this.hasUnsavedChanges = true;
|
|
883
|
+
this.FlowChanged.emit(true);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
static ɵfac = function FlowAgentEditorComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FlowAgentEditorComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.AgentFlowTransformerService), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.Renderer2)); };
|
|
887
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FlowAgentEditorComponent, selectors: [["mj-flow-agent-editor"]], viewQuery: function FlowAgentEditorComponent_Query(rf, ctx) { if (rf & 1) {
|
|
888
|
+
i0.ɵɵviewQuery(_c0, 5);
|
|
889
|
+
} if (rf & 2) {
|
|
890
|
+
let _t;
|
|
891
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.flowEditor = _t.first);
|
|
892
|
+
} }, hostVars: 2, hostBindings: function FlowAgentEditorComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
893
|
+
i0.ɵɵlistener("keydown.escape", function FlowAgentEditorComponent_keydown_escape_HostBindingHandler() { return ctx.onEscapeKey(); }, i0.ɵɵresolveDocument);
|
|
894
|
+
} if (rf & 2) {
|
|
895
|
+
i0.ɵɵclassProp("mj-flow-agent-editor--fullscreen", ctx.HostFullScreen);
|
|
896
|
+
} }, inputs: { AgentID: "AgentID", EditMode: "EditMode", FullScreen: "FullScreen" }, outputs: { FlowSaved: "FlowSaved", FlowChanged: "FlowChanged", FullScreenToggled: "FullScreenToggled", StepSelected: "StepSelected" }, standalone: false, features: [i0.ɵɵProvidersFeature([AgentFlowTransformerService]), i0.ɵɵNgOnChangesFeature], decls: 30, vars: 21, consts: [["flowEditor", ""], [1, "mj-agent-editor"], [1, "mj-agent-editor-toolbar"], [1, "mj-agent-editor-toolbar-left"], ["title", "Undo (Ctrl+Z)", 1, "mj-agent-editor-btn", 3, "disabled"], ["title", "Redo (Ctrl+Y)", 1, "mj-agent-editor-btn", 3, "disabled"], [1, "mj-agent-editor-toolbar-center"], [1, "mj-agent-editor-title"], [1, "fa-solid", "fa-diagram-project"], [1, "mj-agent-editor-view-toggle"], [1, "mj-agent-editor-view-btn", 3, "click"], [1, "fa-solid", "fa-list"], [1, "mj-agent-editor-mode-badge", "mj-agent-editor-mode-badge--editing"], [1, "mj-agent-editor-mode-badge", "mj-agent-editor-mode-badge--readonly"], [1, "mj-agent-editor-toolbar-right"], [1, "mj-agent-editor-status", "mj-agent-editor-status--unsaved"], [1, "mj-agent-editor-status"], [1, "mj-agent-editor-btn", "mj-agent-editor-btn--primary", 3, "disabled"], ["title", "Cancel editing", 1, "mj-agent-editor-btn"], [1, "mj-agent-editor-btn-divider"], ["title", "Edit flow", 1, "mj-agent-editor-btn", "mj-agent-editor-btn--edit"], ["title", "Expand to full screen", 1, "mj-agent-editor-btn", "mj-agent-editor-btn--expand"], ["title", "Close full screen (Esc)", 1, "mj-agent-editor-btn", "mj-agent-editor-btn--close"], [1, "mj-agent-editor-loading"], [1, "mj-agent-editor-body"], [1, "mj-agent-editor-dialog-overlay"], ["title", "Undo (Ctrl+Z)", 1, "mj-agent-editor-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-rotate-left"], ["title", "Redo (Ctrl+Y)", 1, "mj-agent-editor-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-rotate-right"], [1, "fa-solid", "fa-pen"], [1, "fa-solid", "fa-lock"], [1, "fa-solid", "fa-circle"], [1, "mj-agent-editor-btn", "mj-agent-editor-btn--primary", 3, "click", "disabled"], [1, "fa-solid", 3, "ngClass"], ["title", "Cancel editing", 1, "mj-agent-editor-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], ["title", "Edit flow", 1, "mj-agent-editor-btn", "mj-agent-editor-btn--edit", 3, "click"], [1, "fa-solid", "fa-pen-to-square"], ["title", "Expand to full screen", 1, "mj-agent-editor-btn", "mj-agent-editor-btn--expand", 3, "click"], [1, "fa-solid", "fa-up-right-and-down-left-from-center"], ["title", "Close full screen (Esc)", 1, "mj-agent-editor-btn", "mj-agent-editor-btn--close", 3, "click"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "mj-agent-editor-diagram"], [1, "mj-agent-editor-list"], [3, "NodeSelected", "NodeAdded", "NodeRemoved", "ConnectionCreated", "ConnectionRemoved", "ConnectionReassigned", "ConnectionSelected", "NodesChanged", "ConnectionsChanged", "GridToggled", "MinimapToggled", "LegendToggled", "Nodes", "Connections", "NodeTypes", "ReadOnly", "ShowMinimap", "ShowPalette", "ShowGrid", "ShowLegend", "ShowStatusBar", "ShowToolbar", "AutoLayoutDirection"], [1, "mj-agent-editor-properties"], [3, "StepChanged", "PathChanged", "DeleteStepRequested", "DeletePathRequested", "CloseRequested", "Step", "SelectedConnection", "PathEntity", "ReadOnly", "Actions", "Prompts", "Agents", "AllSteps"], [3, "StepClicked", "Steps", "Paths", "SelectedStepID"], [1, "mj-agent-editor-dialog"], [1, "mj-agent-editor-dialog-icon"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "mj-agent-editor-dialog-title"], [1, "mj-agent-editor-dialog-message"], [1, "mj-agent-editor-dialog-actions"], [1, "mj-agent-editor-btn", "mj-agent-editor-btn--primary", 3, "click"], [1, "fa-solid", "fa-floppy-disk"], [1, "mj-agent-editor-btn", "mj-agent-editor-btn--danger-outline", 3, "click"], [1, "mj-agent-editor-btn", 3, "click"]], template: function FlowAgentEditorComponent_Template(rf, ctx) { if (rf & 1) {
|
|
897
|
+
i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3);
|
|
898
|
+
i0.ɵɵconditionalCreate(3, FlowAgentEditorComponent_Conditional_3_Template, 2, 1, "button", 4);
|
|
899
|
+
i0.ɵɵconditionalCreate(4, FlowAgentEditorComponent_Conditional_4_Template, 2, 1, "button", 5);
|
|
900
|
+
i0.ɵɵelementEnd();
|
|
901
|
+
i0.ɵɵelementStart(5, "div", 6)(6, "span", 7);
|
|
902
|
+
i0.ɵɵelement(7, "i", 8);
|
|
903
|
+
i0.ɵɵtext(8, " Flow Configuration ");
|
|
904
|
+
i0.ɵɵelementEnd();
|
|
905
|
+
i0.ɵɵelementStart(9, "div", 9)(10, "button", 10);
|
|
906
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Template_button_click_10_listener() { return ctx.viewMode = "diagram"; });
|
|
907
|
+
i0.ɵɵelement(11, "i", 8);
|
|
908
|
+
i0.ɵɵtext(12, " Diagram ");
|
|
909
|
+
i0.ɵɵelementEnd();
|
|
910
|
+
i0.ɵɵelementStart(13, "button", 10);
|
|
911
|
+
i0.ɵɵlistener("click", function FlowAgentEditorComponent_Template_button_click_13_listener() { return ctx.viewMode = "list"; });
|
|
912
|
+
i0.ɵɵelement(14, "i", 11);
|
|
913
|
+
i0.ɵɵtext(15, " List ");
|
|
914
|
+
i0.ɵɵelementEnd()();
|
|
915
|
+
i0.ɵɵconditionalCreate(16, FlowAgentEditorComponent_Conditional_16_Template, 3, 0, "span", 12);
|
|
916
|
+
i0.ɵɵconditionalCreate(17, FlowAgentEditorComponent_Conditional_17_Template, 3, 0, "span", 13);
|
|
917
|
+
i0.ɵɵelementEnd();
|
|
918
|
+
i0.ɵɵelementStart(18, "div", 14);
|
|
919
|
+
i0.ɵɵconditionalCreate(19, FlowAgentEditorComponent_Conditional_19_Template, 3, 0, "span", 15);
|
|
920
|
+
i0.ɵɵconditionalCreate(20, FlowAgentEditorComponent_Conditional_20_Template, 3, 4, "span", 16);
|
|
921
|
+
i0.ɵɵconditionalCreate(21, FlowAgentEditorComponent_Conditional_21_Template, 3, 3, "button", 17);
|
|
922
|
+
i0.ɵɵconditionalCreate(22, FlowAgentEditorComponent_Conditional_22_Template, 3, 0, "button", 18);
|
|
923
|
+
i0.ɵɵconditionalCreate(23, FlowAgentEditorComponent_Conditional_23_Template, 1, 0, "div", 19);
|
|
924
|
+
i0.ɵɵconditionalCreate(24, FlowAgentEditorComponent_Conditional_24_Template, 3, 0, "button", 20);
|
|
925
|
+
i0.ɵɵconditionalCreate(25, FlowAgentEditorComponent_Conditional_25_Template, 3, 0, "button", 21);
|
|
926
|
+
i0.ɵɵconditionalCreate(26, FlowAgentEditorComponent_Conditional_26_Template, 3, 0, "button", 22);
|
|
927
|
+
i0.ɵɵelementEnd()();
|
|
928
|
+
i0.ɵɵconditionalCreate(27, FlowAgentEditorComponent_Conditional_27_Template, 4, 0, "div", 23);
|
|
929
|
+
i0.ɵɵconditionalCreate(28, FlowAgentEditorComponent_Conditional_28_Template, 3, 2, "div", 24);
|
|
930
|
+
i0.ɵɵconditionalCreate(29, FlowAgentEditorComponent_Conditional_29_Template, 16, 0, "div", 25);
|
|
931
|
+
i0.ɵɵelementEnd();
|
|
932
|
+
} if (rf & 2) {
|
|
933
|
+
i0.ɵɵadvance();
|
|
934
|
+
i0.ɵɵclassProp("mj-agent-editor-toolbar--editing", ctx.isEditingActive);
|
|
935
|
+
i0.ɵɵadvance(2);
|
|
936
|
+
i0.ɵɵconditional(ctx.isEditingActive ? 3 : -1);
|
|
937
|
+
i0.ɵɵadvance();
|
|
938
|
+
i0.ɵɵconditional(ctx.isEditingActive ? 4 : -1);
|
|
939
|
+
i0.ɵɵadvance(6);
|
|
940
|
+
i0.ɵɵclassProp("mj-agent-editor-view-btn--active", ctx.viewMode === "diagram");
|
|
941
|
+
i0.ɵɵadvance(3);
|
|
942
|
+
i0.ɵɵclassProp("mj-agent-editor-view-btn--active", ctx.viewMode === "list");
|
|
943
|
+
i0.ɵɵadvance(3);
|
|
944
|
+
i0.ɵɵconditional(ctx.isEditingActive ? 16 : -1);
|
|
945
|
+
i0.ɵɵadvance();
|
|
946
|
+
i0.ɵɵconditional(!ctx.isEditingActive ? 17 : -1);
|
|
947
|
+
i0.ɵɵadvance(2);
|
|
948
|
+
i0.ɵɵconditional(ctx.hasUnsavedChanges ? 19 : -1);
|
|
949
|
+
i0.ɵɵadvance();
|
|
950
|
+
i0.ɵɵconditional(ctx.lastSaved ? 20 : -1);
|
|
951
|
+
i0.ɵɵadvance();
|
|
952
|
+
i0.ɵɵconditional(ctx.isEditingActive ? 21 : -1);
|
|
953
|
+
i0.ɵɵadvance();
|
|
954
|
+
i0.ɵɵconditional(ctx.fullscreenEditMode && !ctx.EditMode ? 22 : -1);
|
|
955
|
+
i0.ɵɵadvance();
|
|
956
|
+
i0.ɵɵconditional(ctx.isEditingActive ? 23 : -1);
|
|
957
|
+
i0.ɵɵadvance();
|
|
958
|
+
i0.ɵɵconditional(!ctx.EditMode && !ctx.fullscreenEditMode && ctx.userCanUpdate ? 24 : -1);
|
|
959
|
+
i0.ɵɵadvance();
|
|
960
|
+
i0.ɵɵconditional(!ctx.FullScreen ? 25 : -1);
|
|
961
|
+
i0.ɵɵadvance();
|
|
962
|
+
i0.ɵɵconditional(ctx.FullScreen ? 26 : -1);
|
|
963
|
+
i0.ɵɵadvance();
|
|
964
|
+
i0.ɵɵconditional(ctx.isLoading ? 27 : -1);
|
|
965
|
+
i0.ɵɵadvance();
|
|
966
|
+
i0.ɵɵconditional(!ctx.isLoading ? 28 : -1);
|
|
967
|
+
i0.ɵɵadvance();
|
|
968
|
+
i0.ɵɵconditional(ctx.showUnsavedDialog ? 29 : -1);
|
|
969
|
+
} }, dependencies: [i2.NgClass, i3.FlowEditorComponent, i4.AgentPropertiesPanelComponent, i5.AgentStepListComponent, i2.DatePipe], styles: ["/* ============================================================\n Flow Agent Editor \u2014 MJ-specific flow editor wrapper\n ============================================================ */\n\n/* \u2500\u2500 Host element fullscreen positioning \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nmj-flow-agent-editor.mj-flow-agent-editor--fullscreen {\n position: fixed;\n top: 12px;\n left: 12px;\n right: 12px;\n padding-right: 25px;\n bottom: 12px;\n z-index: 10000;\n border-radius: 10px;\n height: auto !important;\n min-height: unset !important;\n box-shadow: 0 25px 60px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(0, 0, 0, 0.08);\n}\n\nmj-flow-agent-editor.mj-flow-agent-editor--fullscreen .mj-agent-editor {\n height: 100%;\n min-height: unset;\n border-radius: 10px;\n}\n\n.mj-agent-editor {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 500px;\n background: #f8fafc;\n border-radius: 8px;\n overflow: hidden;\n position: relative;\n}\n\n/* \u2500\u2500 Backdrop overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9999;\n}\n\n/* \u2500\u2500 Toolbar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: #ffffff;\n border-bottom: 1px solid #e2e8f0;\n gap: 12px;\n flex-shrink: 0;\n transition: background 0.2s ease, border-color 0.2s ease;\n}\n\n.mj-agent-editor-toolbar--editing {\n background: linear-gradient(135deg, #f0fdf4 0%, #ecfdf5 50%, #f0fdf4 100%);\n border-bottom-color: #bbf7d0;\n}\n\n.mj-flow-agent-editor--fullscreen .mj-agent-editor-toolbar {\n padding: 10px 16px;\n border-bottom: 1px solid #e2e8f0;\n background: #ffffff;\n border-radius: 10px 10px 0 0;\n}\n\n.mj-flow-agent-editor--fullscreen .mj-agent-editor-toolbar--editing {\n background: linear-gradient(135deg, #f0fdf4 0%, #ecfdf5 50%, #f0fdf4 100%);\n border-bottom-color: #bbf7d0;\n}\n\n.mj-agent-editor-toolbar-left,\n.mj-agent-editor-toolbar-center,\n.mj-agent-editor-toolbar-right {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.mj-agent-editor-toolbar-right {\n gap: 10px;\n}\n\n.mj-agent-editor-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n background: #ffffff;\n color: #475569;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.mj-agent-editor-btn i { font-size: 12px; }\n\n.mj-agent-editor-btn:hover:not(:disabled) { background: #f1f5f9; border-color: #cbd5e1; }\n.mj-agent-editor-btn:disabled { opacity: 0.4; cursor: not-allowed; }\n\n.mj-agent-editor-btn--primary {\n background: #3b82f6;\n border-color: #3b82f6;\n color: #ffffff;\n}\n\n.mj-agent-editor-btn--primary:hover:not(:disabled) { background: #2563eb; border-color: #2563eb; }\n\n.mj-agent-editor-btn--expand {\n background: #f0f9ff;\n border-color: #bae6fd;\n color: #0284c7;\n}\n\n.mj-agent-editor-btn--expand:hover:not(:disabled) { background: #e0f2fe; border-color: #7dd3fc; color: #0369a1; }\n\n.mj-agent-editor-btn--close {\n background: #fef2f2;\n border-color: #fecaca;\n color: #dc2626;\n}\n\n.mj-agent-editor-btn--close:hover:not(:disabled) { background: #fee2e2; border-color: #fca5a5; color: #b91c1c; }\n\n.mj-agent-editor-btn-divider {\n width: 1px;\n height: 22px;\n background: #e2e8f0;\n margin: 0 2px;\n}\n\n/* \u2500\u2500 View Toggle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-view-toggle {\n display: flex;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n overflow: hidden;\n}\n\n.mj-agent-editor-view-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n border: none;\n background: #ffffff;\n color: #64748b;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.mj-agent-editor-view-btn i { font-size: 11px; }\n\n.mj-agent-editor-view-btn:not(:last-child) { border-right: 1px solid #e2e8f0; }\n\n.mj-agent-editor-view-btn--active {\n background: #eff6ff;\n color: #3b82f6;\n}\n\n.mj-agent-editor-view-btn:hover:not(.mj-agent-editor-view-btn--active) { background: #f8fafc; }\n\n/* \u2500\u2500 Fullscreen Title \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-title {\n font-size: 14px;\n font-weight: 600;\n color: #1e293b;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin-right: 12px;\n}\n\n.mj-agent-editor-title i {\n color: #3b82f6;\n font-size: 14px;\n}\n\n/* \u2500\u2500 Status Indicators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-status {\n font-size: 12px;\n color: #94a3b8;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.mj-agent-editor-status--unsaved {\n color: #f59e0b;\n}\n\n.mj-agent-editor-status--unsaved i { font-size: 6px; }\n\n/* \u2500\u2500 Inline Floating Controls (non-fullscreen) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-inline-controls {\n position: absolute;\n top: 8px;\n right: 8px;\n z-index: 100;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.mj-agent-editor-inline-expand {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n border: 1px solid rgba(0, 0, 0, 0.12);\n border-radius: 6px;\n background: rgba(255, 255, 255, 0.85);\n color: #475569;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s ease;\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);\n backdrop-filter: blur(4px);\n}\n\n.mj-agent-editor-inline-expand:hover {\n background: #ffffff;\n border-color: #94a3b8;\n color: #1e293b;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n transform: scale(1.05);\n}\n\n.mj-agent-editor-inline-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #f59e0b;\n box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9), 0 0 6px rgba(245, 158, 11, 0.4);\n animation: mj-inline-dot-pulse 2s ease-in-out infinite;\n}\n\n@keyframes mj-inline-dot-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n\n/* \u2500\u2500 Loading \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n flex: 1;\n font-size: 14px;\n color: #64748b;\n}\n\n.mj-agent-editor-loading i { font-size: 16px; }\n\n/* \u2500\u2500 Body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.mj-agent-editor-diagram {\n display: flex;\n flex: 1;\n overflow: hidden;\n position: relative;\n}\n\n.mj-agent-editor-diagram mj-flow-editor {\n flex: 1;\n display: flex;\n}\n\n.mj-agent-editor-list {\n display: flex;\n flex: 1;\n overflow: hidden;\n}\n\n.mj-agent-editor-list mj-agent-step-list {\n flex: 1;\n overflow-y: auto;\n}\n\n/* \u2500\u2500 Properties Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-properties {\n width: 320px;\n flex-shrink: 0;\n overflow: hidden;\n transform: translateX(320px);\n margin-right: -320px;\n transition: transform 0.2s ease, margin-right 0.2s ease;\n border-left: 1px solid #e2e8f0;\n}\n\n.mj-agent-editor-properties--visible {\n transform: translateX(0);\n margin-right: 0;\n}\n\n.mj-agent-editor-properties mj-agent-properties-panel {\n display: block;\n width: 320px;\n height: 100%;\n}\n\n/* \u2500\u2500 Mode Indicator Badge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-mode-badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 11px;\n font-weight: 600;\n padding: 3px 10px;\n border-radius: 12px;\n letter-spacing: 0.2px;\n}\n\n.mj-agent-editor-mode-badge i { font-size: 10px; }\n\n.mj-agent-editor-mode-badge--editing {\n background: #ecfdf5;\n color: #059669;\n}\n\n.mj-agent-editor-mode-badge--readonly {\n background: #f1f5f9;\n color: #64748b;\n}\n\n/* \u2500\u2500 Edit Button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-btn--edit {\n background: #ecfdf5;\n border-color: #a7f3d0;\n color: #059669;\n}\n\n.mj-agent-editor-btn--edit:hover:not(:disabled) {\n background: #d1fae5;\n border-color: #6ee7b7;\n color: #047857;\n}\n\n/* \u2500\u2500 Danger Outline Button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-btn--danger-outline {\n border-color: #fecaca;\n color: #dc2626;\n background: #ffffff;\n}\n\n.mj-agent-editor-btn--danger-outline:hover:not(:disabled) {\n background: #fef2f2;\n border-color: #fca5a5;\n}\n\n/* \u2500\u2500 Unsaved Changes Dialog \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-dialog-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10001;\n animation: mj-dialog-fade-in 0.15s ease-out;\n}\n\n@keyframes mj-dialog-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.mj-agent-editor-dialog {\n background: #ffffff;\n border-radius: 12px;\n padding: 28px 32px;\n max-width: 400px;\n width: 90%;\n box-shadow: 0 20px 50px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.05);\n text-align: center;\n animation: mj-dialog-scale-in 0.15s ease-out;\n}\n\n@keyframes mj-dialog-scale-in {\n from { transform: scale(0.95); opacity: 0; }\n to { transform: scale(1); opacity: 1; }\n}\n\n.mj-agent-editor-dialog-icon {\n font-size: 28px;\n color: #f59e0b;\n margin-bottom: 12px;\n}\n\n.mj-agent-editor-dialog-title {\n font-size: 16px;\n font-weight: 600;\n color: #1e293b;\n margin: 0 0 8px;\n}\n\n.mj-agent-editor-dialog-message {\n font-size: 13px;\n color: #64748b;\n margin: 0 0 20px;\n line-height: 1.5;\n}\n\n.mj-agent-editor-dialog-actions {\n display: flex;\n gap: 8px;\n justify-content: center;\n flex-wrap: wrap;\n}\n"], encapsulation: 2 });
|
|
970
|
+
}
|
|
971
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FlowAgentEditorComponent, [{
|
|
972
|
+
type: Component,
|
|
973
|
+
args: [{ standalone: false, selector: 'mj-flow-agent-editor', encapsulation: ViewEncapsulation.None, providers: [AgentFlowTransformerService], template: "<div class=\"mj-agent-editor\">\n\n <!-- \u2500\u2500 Toolbar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"mj-agent-editor-toolbar\" [class.mj-agent-editor-toolbar--editing]=\"isEditingActive\">\n <div class=\"mj-agent-editor-toolbar-left\">\n <!-- Undo / Redo (edit mode only) -->\n @if (isEditingActive) {\n <button class=\"mj-agent-editor-btn\"\n [disabled]=\"!flowEditor?.CanUndo\" (click)=\"flowEditor?.Undo()\" title=\"Undo (Ctrl+Z)\">\n <i class=\"fa-solid fa-rotate-left\"></i>\n </button>\n }\n @if (isEditingActive) {\n <button class=\"mj-agent-editor-btn\"\n [disabled]=\"!flowEditor?.CanRedo\" (click)=\"flowEditor?.Redo()\" title=\"Redo (Ctrl+Y)\">\n <i class=\"fa-solid fa-rotate-right\"></i>\n </button>\n }\n </div>\n\n <div class=\"mj-agent-editor-toolbar-center\">\n <!-- Fullscreen title -->\n <span class=\"mj-agent-editor-title\">\n <i class=\"fa-solid fa-diagram-project\"></i> Flow Configuration\n </span>\n\n <!-- View Mode Toggle -->\n <div class=\"mj-agent-editor-view-toggle\">\n <button class=\"mj-agent-editor-view-btn\"\n [class.mj-agent-editor-view-btn--active]=\"viewMode === 'diagram'\"\n (click)=\"viewMode = 'diagram'\">\n <i class=\"fa-solid fa-diagram-project\"></i> Diagram\n </button>\n <button class=\"mj-agent-editor-view-btn\"\n [class.mj-agent-editor-view-btn--active]=\"viewMode === 'list'\"\n (click)=\"viewMode = 'list'\">\n <i class=\"fa-solid fa-list\"></i> List\n </button>\n </div>\n\n <!-- Mode indicator badge -->\n @if (isEditingActive) {\n <span class=\"mj-agent-editor-mode-badge mj-agent-editor-mode-badge--editing\">\n <i class=\"fa-solid fa-pen\"></i> Editing\n </span>\n }\n @if (!isEditingActive) {\n <span class=\"mj-agent-editor-mode-badge mj-agent-editor-mode-badge--readonly\">\n <i class=\"fa-solid fa-lock\"></i> Read Only\n </span>\n }\n </div>\n\n <div class=\"mj-agent-editor-toolbar-right\">\n <!-- Status indicators -->\n @if (hasUnsavedChanges) {\n <span class=\"mj-agent-editor-status mj-agent-editor-status--unsaved\">\n <i class=\"fa-solid fa-circle\"></i> Unsaved\n </span>\n }\n @if (lastSaved) {\n <span class=\"mj-agent-editor-status\">\n Saved {{ lastSaved | date:'shortTime' }}\n </span>\n }\n\n <!-- Save + Cancel (when editing) -->\n @if (isEditingActive) {\n <button class=\"mj-agent-editor-btn mj-agent-editor-btn--primary\"\n [disabled]=\"isSaving || !hasUnsavedChanges\" (click)=\"Save()\">\n <i class=\"fa-solid\" [ngClass]=\"isSaving ? 'fa-spinner fa-spin' : 'fa-floppy-disk'\"></i>\n {{ isSaving ? 'Saving...' : 'Save' }}\n </button>\n }\n @if (fullscreenEditMode && !EditMode) {\n <button\n class=\"mj-agent-editor-btn\"\n (click)=\"cancelFullscreenEdit()\" title=\"Cancel editing\">\n <i class=\"fa-solid fa-xmark\"></i> Cancel\n </button>\n }\n\n @if (isEditingActive) {\n <div class=\"mj-agent-editor-btn-divider\"></div>\n }\n\n <!-- Fullscreen edit toggle (only when parent is NOT in edit mode) -->\n @if (!EditMode && !fullscreenEditMode && userCanUpdate) {\n <button\n class=\"mj-agent-editor-btn mj-agent-editor-btn--edit\"\n (click)=\"toggleFullscreenEditMode()\" title=\"Edit flow\">\n <i class=\"fa-solid fa-pen-to-square\"></i> Edit\n </button>\n }\n\n <!-- Expand / Close fullscreen -->\n @if (!FullScreen) {\n <button class=\"mj-agent-editor-btn mj-agent-editor-btn--expand\"\n (click)=\"toggleFullScreen()\" title=\"Expand to full screen\">\n <i class=\"fa-solid fa-up-right-and-down-left-from-center\"></i> Expand\n </button>\n }\n @if (FullScreen) {\n <button class=\"mj-agent-editor-btn mj-agent-editor-btn--close\"\n (click)=\"toggleFullScreen()\" title=\"Close full screen (Esc)\">\n <i class=\"fa-solid fa-xmark\"></i> Close\n </button>\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Loading State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (isLoading) {\n <div class=\"mj-agent-editor-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading flow...</span>\n </div>\n }\n\n <!-- \u2500\u2500 Main Content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (!isLoading) {\n <div class=\"mj-agent-editor-body\">\n <!-- Diagram View -->\n @if (viewMode === 'diagram') {\n <div class=\"mj-agent-editor-diagram\">\n <mj-flow-editor #flowEditor\n [Nodes]=\"nodes\"\n [Connections]=\"connections\"\n [NodeTypes]=\"nodeTypes\"\n [ReadOnly]=\"!isEditingActive\"\n [ShowMinimap]=\"prefShowMinimap\"\n [ShowPalette]=\"isEditingActive\"\n [ShowGrid]=\"prefShowGrid\"\n [ShowLegend]=\"prefShowLegend\"\n [ShowStatusBar]=\"true\"\n [ShowToolbar]=\"true\"\n [AutoLayoutDirection]=\"'vertical'\"\n (NodeSelected)=\"onNodeSelected($event)\"\n (NodeAdded)=\"onNodeAdded($event)\"\n (NodeRemoved)=\"onNodeRemoved($event)\"\n (ConnectionCreated)=\"onConnectionCreated($event)\"\n (ConnectionRemoved)=\"onConnectionRemoved($event)\"\n (ConnectionReassigned)=\"onConnectionReassigned($event)\"\n (ConnectionSelected)=\"onConnectionSelected($event)\"\n (NodesChanged)=\"onNodesChanged($event)\"\n (ConnectionsChanged)=\"onConnectionsChanged($event)\"\n (GridToggled)=\"onGridPrefChanged($event)\"\n (MinimapToggled)=\"onMinimapPrefChanged($event)\"\n (LegendToggled)=\"onLegendPrefChanged($event)\">\n </mj-flow-editor>\n <!-- Properties Panel -->\n <div class=\"mj-agent-editor-properties\"\n [class.mj-agent-editor-properties--visible]=\"showPropertiesPanel\">\n <mj-agent-properties-panel\n [Step]=\"selectedStep\"\n [SelectedConnection]=\"selectedConnection\"\n [PathEntity]=\"selectedPathEntity\"\n [ReadOnly]=\"!isEditingActive\"\n [Actions]=\"availableActions\"\n [Prompts]=\"availablePrompts\"\n [Agents]=\"availableAgents\"\n [AllSteps]=\"steps\"\n (StepChanged)=\"onStepChanged($event)\"\n (PathChanged)=\"onPathChanged($event)\"\n (DeleteStepRequested)=\"onDeleteStepRequested($event)\"\n (DeletePathRequested)=\"onDeletePathRequested($event)\"\n (CloseRequested)=\"onCloseProperties()\">\n </mj-agent-properties-panel>\n </div>\n </div>\n }\n <!-- List View -->\n @if (viewMode === 'list') {\n <div class=\"mj-agent-editor-list\">\n <mj-agent-step-list\n [Steps]=\"steps\"\n [Paths]=\"paths\"\n [SelectedStepID]=\"selectedStep?.ID || null\"\n (StepClicked)=\"onStepClickedInList($event)\">\n </mj-agent-step-list>\n <!-- Properties Panel in list mode too -->\n <div class=\"mj-agent-editor-properties\"\n [class.mj-agent-editor-properties--visible]=\"showPropertiesPanel\">\n <mj-agent-properties-panel\n [Step]=\"selectedStep\"\n [SelectedConnection]=\"selectedConnection\"\n [PathEntity]=\"selectedPathEntity\"\n [ReadOnly]=\"!isEditingActive\"\n [Actions]=\"availableActions\"\n [Prompts]=\"availablePrompts\"\n [Agents]=\"availableAgents\"\n [AllSteps]=\"steps\"\n (StepChanged)=\"onStepChanged($event)\"\n (PathChanged)=\"onPathChanged($event)\"\n (DeleteStepRequested)=\"onDeleteStepRequested($event)\"\n (DeletePathRequested)=\"onDeletePathRequested($event)\"\n (CloseRequested)=\"onCloseProperties()\">\n </mj-agent-properties-panel>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- \u2500\u2500 Unsaved Changes Dialog \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (showUnsavedDialog) {\n <div class=\"mj-agent-editor-dialog-overlay\">\n <div class=\"mj-agent-editor-dialog\">\n <div class=\"mj-agent-editor-dialog-icon\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n </div>\n <h3 class=\"mj-agent-editor-dialog-title\">Unsaved Changes</h3>\n <p class=\"mj-agent-editor-dialog-message\">\n You have unsaved changes to this flow. What would you like to do?\n </p>\n <div class=\"mj-agent-editor-dialog-actions\">\n <button class=\"mj-agent-editor-btn mj-agent-editor-btn--primary\" (click)=\"onUnsavedDialogSave()\">\n <i class=\"fa-solid fa-floppy-disk\"></i> Save & Close\n </button>\n <button class=\"mj-agent-editor-btn mj-agent-editor-btn--danger-outline\" (click)=\"onUnsavedDialogDiscard()\">\n Discard Changes\n </button>\n <button class=\"mj-agent-editor-btn\" (click)=\"onUnsavedDialogCancel()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: ["/* ============================================================\n Flow Agent Editor \u2014 MJ-specific flow editor wrapper\n ============================================================ */\n\n/* \u2500\u2500 Host element fullscreen positioning \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nmj-flow-agent-editor.mj-flow-agent-editor--fullscreen {\n position: fixed;\n top: 12px;\n left: 12px;\n right: 12px;\n padding-right: 25px;\n bottom: 12px;\n z-index: 10000;\n border-radius: 10px;\n height: auto !important;\n min-height: unset !important;\n box-shadow: 0 25px 60px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(0, 0, 0, 0.08);\n}\n\nmj-flow-agent-editor.mj-flow-agent-editor--fullscreen .mj-agent-editor {\n height: 100%;\n min-height: unset;\n border-radius: 10px;\n}\n\n.mj-agent-editor {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 500px;\n background: #f8fafc;\n border-radius: 8px;\n overflow: hidden;\n position: relative;\n}\n\n/* \u2500\u2500 Backdrop overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9999;\n}\n\n/* \u2500\u2500 Toolbar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: #ffffff;\n border-bottom: 1px solid #e2e8f0;\n gap: 12px;\n flex-shrink: 0;\n transition: background 0.2s ease, border-color 0.2s ease;\n}\n\n.mj-agent-editor-toolbar--editing {\n background: linear-gradient(135deg, #f0fdf4 0%, #ecfdf5 50%, #f0fdf4 100%);\n border-bottom-color: #bbf7d0;\n}\n\n.mj-flow-agent-editor--fullscreen .mj-agent-editor-toolbar {\n padding: 10px 16px;\n border-bottom: 1px solid #e2e8f0;\n background: #ffffff;\n border-radius: 10px 10px 0 0;\n}\n\n.mj-flow-agent-editor--fullscreen .mj-agent-editor-toolbar--editing {\n background: linear-gradient(135deg, #f0fdf4 0%, #ecfdf5 50%, #f0fdf4 100%);\n border-bottom-color: #bbf7d0;\n}\n\n.mj-agent-editor-toolbar-left,\n.mj-agent-editor-toolbar-center,\n.mj-agent-editor-toolbar-right {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.mj-agent-editor-toolbar-right {\n gap: 10px;\n}\n\n.mj-agent-editor-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n background: #ffffff;\n color: #475569;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.mj-agent-editor-btn i { font-size: 12px; }\n\n.mj-agent-editor-btn:hover:not(:disabled) { background: #f1f5f9; border-color: #cbd5e1; }\n.mj-agent-editor-btn:disabled { opacity: 0.4; cursor: not-allowed; }\n\n.mj-agent-editor-btn--primary {\n background: #3b82f6;\n border-color: #3b82f6;\n color: #ffffff;\n}\n\n.mj-agent-editor-btn--primary:hover:not(:disabled) { background: #2563eb; border-color: #2563eb; }\n\n.mj-agent-editor-btn--expand {\n background: #f0f9ff;\n border-color: #bae6fd;\n color: #0284c7;\n}\n\n.mj-agent-editor-btn--expand:hover:not(:disabled) { background: #e0f2fe; border-color: #7dd3fc; color: #0369a1; }\n\n.mj-agent-editor-btn--close {\n background: #fef2f2;\n border-color: #fecaca;\n color: #dc2626;\n}\n\n.mj-agent-editor-btn--close:hover:not(:disabled) { background: #fee2e2; border-color: #fca5a5; color: #b91c1c; }\n\n.mj-agent-editor-btn-divider {\n width: 1px;\n height: 22px;\n background: #e2e8f0;\n margin: 0 2px;\n}\n\n/* \u2500\u2500 View Toggle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-view-toggle {\n display: flex;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n overflow: hidden;\n}\n\n.mj-agent-editor-view-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n border: none;\n background: #ffffff;\n color: #64748b;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.mj-agent-editor-view-btn i { font-size: 11px; }\n\n.mj-agent-editor-view-btn:not(:last-child) { border-right: 1px solid #e2e8f0; }\n\n.mj-agent-editor-view-btn--active {\n background: #eff6ff;\n color: #3b82f6;\n}\n\n.mj-agent-editor-view-btn:hover:not(.mj-agent-editor-view-btn--active) { background: #f8fafc; }\n\n/* \u2500\u2500 Fullscreen Title \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-title {\n font-size: 14px;\n font-weight: 600;\n color: #1e293b;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin-right: 12px;\n}\n\n.mj-agent-editor-title i {\n color: #3b82f6;\n font-size: 14px;\n}\n\n/* \u2500\u2500 Status Indicators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-status {\n font-size: 12px;\n color: #94a3b8;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.mj-agent-editor-status--unsaved {\n color: #f59e0b;\n}\n\n.mj-agent-editor-status--unsaved i { font-size: 6px; }\n\n/* \u2500\u2500 Inline Floating Controls (non-fullscreen) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-inline-controls {\n position: absolute;\n top: 8px;\n right: 8px;\n z-index: 100;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.mj-agent-editor-inline-expand {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n border: 1px solid rgba(0, 0, 0, 0.12);\n border-radius: 6px;\n background: rgba(255, 255, 255, 0.85);\n color: #475569;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s ease;\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);\n backdrop-filter: blur(4px);\n}\n\n.mj-agent-editor-inline-expand:hover {\n background: #ffffff;\n border-color: #94a3b8;\n color: #1e293b;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n transform: scale(1.05);\n}\n\n.mj-agent-editor-inline-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #f59e0b;\n box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9), 0 0 6px rgba(245, 158, 11, 0.4);\n animation: mj-inline-dot-pulse 2s ease-in-out infinite;\n}\n\n@keyframes mj-inline-dot-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n\n/* \u2500\u2500 Loading \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n flex: 1;\n font-size: 14px;\n color: #64748b;\n}\n\n.mj-agent-editor-loading i { font-size: 16px; }\n\n/* \u2500\u2500 Body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.mj-agent-editor-diagram {\n display: flex;\n flex: 1;\n overflow: hidden;\n position: relative;\n}\n\n.mj-agent-editor-diagram mj-flow-editor {\n flex: 1;\n display: flex;\n}\n\n.mj-agent-editor-list {\n display: flex;\n flex: 1;\n overflow: hidden;\n}\n\n.mj-agent-editor-list mj-agent-step-list {\n flex: 1;\n overflow-y: auto;\n}\n\n/* \u2500\u2500 Properties Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-properties {\n width: 320px;\n flex-shrink: 0;\n overflow: hidden;\n transform: translateX(320px);\n margin-right: -320px;\n transition: transform 0.2s ease, margin-right 0.2s ease;\n border-left: 1px solid #e2e8f0;\n}\n\n.mj-agent-editor-properties--visible {\n transform: translateX(0);\n margin-right: 0;\n}\n\n.mj-agent-editor-properties mj-agent-properties-panel {\n display: block;\n width: 320px;\n height: 100%;\n}\n\n/* \u2500\u2500 Mode Indicator Badge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-mode-badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 11px;\n font-weight: 600;\n padding: 3px 10px;\n border-radius: 12px;\n letter-spacing: 0.2px;\n}\n\n.mj-agent-editor-mode-badge i { font-size: 10px; }\n\n.mj-agent-editor-mode-badge--editing {\n background: #ecfdf5;\n color: #059669;\n}\n\n.mj-agent-editor-mode-badge--readonly {\n background: #f1f5f9;\n color: #64748b;\n}\n\n/* \u2500\u2500 Edit Button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-btn--edit {\n background: #ecfdf5;\n border-color: #a7f3d0;\n color: #059669;\n}\n\n.mj-agent-editor-btn--edit:hover:not(:disabled) {\n background: #d1fae5;\n border-color: #6ee7b7;\n color: #047857;\n}\n\n/* \u2500\u2500 Danger Outline Button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-btn--danger-outline {\n border-color: #fecaca;\n color: #dc2626;\n background: #ffffff;\n}\n\n.mj-agent-editor-btn--danger-outline:hover:not(:disabled) {\n background: #fef2f2;\n border-color: #fca5a5;\n}\n\n/* \u2500\u2500 Unsaved Changes Dialog \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-agent-editor-dialog-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10001;\n animation: mj-dialog-fade-in 0.15s ease-out;\n}\n\n@keyframes mj-dialog-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.mj-agent-editor-dialog {\n background: #ffffff;\n border-radius: 12px;\n padding: 28px 32px;\n max-width: 400px;\n width: 90%;\n box-shadow: 0 20px 50px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.05);\n text-align: center;\n animation: mj-dialog-scale-in 0.15s ease-out;\n}\n\n@keyframes mj-dialog-scale-in {\n from { transform: scale(0.95); opacity: 0; }\n to { transform: scale(1); opacity: 1; }\n}\n\n.mj-agent-editor-dialog-icon {\n font-size: 28px;\n color: #f59e0b;\n margin-bottom: 12px;\n}\n\n.mj-agent-editor-dialog-title {\n font-size: 16px;\n font-weight: 600;\n color: #1e293b;\n margin: 0 0 8px;\n}\n\n.mj-agent-editor-dialog-message {\n font-size: 13px;\n color: #64748b;\n margin: 0 0 20px;\n line-height: 1.5;\n}\n\n.mj-agent-editor-dialog-actions {\n display: flex;\n gap: 8px;\n justify-content: center;\n flex-wrap: wrap;\n}\n"] }]
|
|
974
|
+
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.AgentFlowTransformerService }, { type: i0.ElementRef }, { type: i0.Renderer2 }], { HostFullScreen: [{
|
|
975
|
+
type: HostBinding,
|
|
976
|
+
args: ['class.mj-flow-agent-editor--fullscreen']
|
|
977
|
+
}], AgentID: [{
|
|
978
|
+
type: Input
|
|
979
|
+
}], EditMode: [{
|
|
980
|
+
type: Input
|
|
981
|
+
}], FullScreen: [{
|
|
982
|
+
type: Input
|
|
983
|
+
}], FlowSaved: [{
|
|
984
|
+
type: Output
|
|
985
|
+
}], FlowChanged: [{
|
|
986
|
+
type: Output
|
|
987
|
+
}], FullScreenToggled: [{
|
|
988
|
+
type: Output
|
|
989
|
+
}], StepSelected: [{
|
|
990
|
+
type: Output
|
|
991
|
+
}], flowEditor: [{
|
|
992
|
+
type: ViewChild,
|
|
993
|
+
args: ['flowEditor']
|
|
994
|
+
}], onEscapeKey: [{
|
|
995
|
+
type: HostListener,
|
|
996
|
+
args: ['document:keydown.escape']
|
|
997
|
+
}] }); })();
|
|
998
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FlowAgentEditorComponent, { className: "FlowAgentEditorComponent", filePath: "src/lib/agent-editor/flow-agent-editor.component.ts", lineNumber: 27 }); })();
|
|
999
|
+
//# sourceMappingURL=flow-agent-editor.component.js.map
|