@memberjunction/ng-dashboards 5.8.0 → 5.10.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.
Files changed (84) hide show
  1. package/dist/AI/components/models/model-management.component.d.ts +2 -0
  2. package/dist/AI/components/models/model-management.component.d.ts.map +1 -1
  3. package/dist/AI/components/models/model-management.component.js +44 -2
  4. package/dist/AI/components/models/model-management.component.js.map +1 -1
  5. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
  6. package/dist/DashboardBrowser/dashboard-browser-resource.component.js +15 -12
  7. package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
  8. package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +1 -1
  9. package/dist/DataExplorer/components/view-selector/view-selector.component.js +16 -22
  10. package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +1 -1
  11. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  12. package/dist/DataExplorer/data-explorer-dashboard.component.js +31 -11
  13. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  14. package/dist/Home/home-dashboard.component.d.ts.map +1 -1
  15. package/dist/Home/home-dashboard.component.js +10 -7
  16. package/dist/Home/home-dashboard.component.js.map +1 -1
  17. package/dist/Integration/components/activity/activity.component.d.ts +96 -0
  18. package/dist/Integration/components/activity/activity.component.d.ts.map +1 -0
  19. package/dist/Integration/components/activity/activity.component.js +961 -0
  20. package/dist/Integration/components/activity/activity.component.js.map +1 -0
  21. package/dist/Integration/components/connections/connections.component.d.ts +194 -0
  22. package/dist/Integration/components/connections/connections.component.d.ts.map +1 -0
  23. package/dist/Integration/components/connections/connections.component.js +2368 -0
  24. package/dist/Integration/components/connections/connections.component.js.map +1 -0
  25. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.d.ts +213 -15
  26. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.d.ts.map +1 -1
  27. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +2093 -187
  28. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
  29. package/dist/Integration/components/overview/overview.component.d.ts +60 -0
  30. package/dist/Integration/components/overview/overview.component.d.ts.map +1 -0
  31. package/dist/Integration/components/overview/overview.component.js +628 -0
  32. package/dist/Integration/components/overview/overview.component.js.map +1 -0
  33. package/dist/Integration/components/pipelines/pipelines.component.d.ts +203 -0
  34. package/dist/Integration/components/pipelines/pipelines.component.d.ts.map +1 -0
  35. package/dist/Integration/components/pipelines/pipelines.component.js +2057 -0
  36. package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -0
  37. package/dist/Integration/components/schedules/schedules.component.d.ts +110 -0
  38. package/dist/Integration/components/schedules/schedules.component.d.ts.map +1 -0
  39. package/dist/Integration/components/schedules/schedules.component.js +842 -0
  40. package/dist/Integration/components/schedules/schedules.component.js.map +1 -0
  41. package/dist/Integration/components/visual-editor/visual-editor.component.d.ts +141 -0
  42. package/dist/Integration/components/visual-editor/visual-editor.component.d.ts.map +1 -0
  43. package/dist/Integration/components/visual-editor/visual-editor.component.js +1538 -0
  44. package/dist/Integration/components/visual-editor/visual-editor.component.js.map +1 -0
  45. package/dist/Integration/components/widgets/run-history-panel.component.js +3 -2
  46. package/dist/Integration/components/widgets/run-history-panel.component.js.map +1 -1
  47. package/dist/Integration/index.d.ts +5 -3
  48. package/dist/Integration/index.d.ts.map +1 -1
  49. package/dist/Integration/index.js +11 -7
  50. package/dist/Integration/index.js.map +1 -1
  51. package/dist/Integration/integration.module.d.ts +20 -16
  52. package/dist/Integration/integration.module.d.ts.map +1 -1
  53. package/dist/Integration/integration.module.js +40 -21
  54. package/dist/Integration/integration.module.js.map +1 -1
  55. package/dist/Integration/services/integration-data.service.d.ts +123 -9
  56. package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
  57. package/dist/Integration/services/integration-data.service.js +385 -68
  58. package/dist/Integration/services/integration-data.service.js.map +1 -1
  59. package/dist/QueryBrowser/query-browser-resource.component.d.ts +27 -4
  60. package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
  61. package/dist/QueryBrowser/query-browser-resource.component.js +338 -144
  62. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  63. package/dist/__tests__/integration-data-service.test.js.map +1 -1
  64. package/dist/__tests__/mapping-validation.test.d.ts +2 -0
  65. package/dist/__tests__/mapping-validation.test.d.ts.map +1 -0
  66. package/dist/__tests__/mapping-validation.test.js +170 -0
  67. package/dist/__tests__/mapping-validation.test.js.map +1 -0
  68. package/package.json +40 -38
  69. package/dist/Integration/components/connection-studio/connection-studio.component.d.ts +0 -81
  70. package/dist/Integration/components/connection-studio/connection-studio.component.d.ts.map +0 -1
  71. package/dist/Integration/components/connection-studio/connection-studio.component.js +0 -960
  72. package/dist/Integration/components/connection-studio/connection-studio.component.js.map +0 -1
  73. package/dist/Integration/components/control-tower/control-tower.component.d.ts +0 -43
  74. package/dist/Integration/components/control-tower/control-tower.component.d.ts.map +0 -1
  75. package/dist/Integration/components/control-tower/control-tower.component.js +0 -446
  76. package/dist/Integration/components/control-tower/control-tower.component.js.map +0 -1
  77. package/dist/Integration/components/sync-activity/sync-activity.component.d.ts +0 -65
  78. package/dist/Integration/components/sync-activity/sync-activity.component.d.ts.map +0 -1
  79. package/dist/Integration/components/sync-activity/sync-activity.component.js +0 -671
  80. package/dist/Integration/components/sync-activity/sync-activity.component.js.map +0 -1
  81. package/dist/__tests__/connection-studio.test.d.ts +0 -2
  82. package/dist/__tests__/connection-studio.test.d.ts.map +0 -1
  83. package/dist/__tests__/connection-studio.test.js +0 -186
  84. package/dist/__tests__/connection-studio.test.js.map +0 -1
@@ -0,0 +1,2057 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { ChangeDetectorRef, Component, inject } from '@angular/core';
8
+ import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
9
+ import { RunView } from '@memberjunction/core';
10
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
11
+ import { IntegrationEngineBase } from '@memberjunction/integration-engine-base';
12
+ import { IntegrationDataService, ResolveIntegrationIcon } from '../../services/integration-data.service';
13
+ import * as i0 from "@angular/core";
14
+ import * as i1 from "@angular/common";
15
+ import * as i2 from "@angular/forms";
16
+ const _forTrack0 = ($index, $item) => $item.IntegrationID;
17
+ const _forTrack1 = ($index, $item) => $item.ID;
18
+ const _forTrack2 = ($index, $item) => $item.Name;
19
+ const _forTrack3 = ($index, $item) => $item.SourceFieldName + "-" + $item.DestFieldName;
20
+ const _forTrack4 = ($index, $item) => $item.Value;
21
+ function PipelinesComponent_Conditional_1_Conditional_21_Template(rf, ctx) { if (rf & 1) {
22
+ i0.ɵɵelementStart(0, "div", 20);
23
+ i0.ɵɵelement(1, "i", 23);
24
+ i0.ɵɵelementStart(2, "span");
25
+ i0.ɵɵtext(3, "Loading pipelines...");
26
+ i0.ɵɵelementEnd()();
27
+ } }
28
+ function PipelinesComponent_Conditional_1_Conditional_22_Template(rf, ctx) { if (rf & 1) {
29
+ i0.ɵɵelementStart(0, "div", 21);
30
+ i0.ɵɵelement(1, "i", 24);
31
+ i0.ɵɵelementStart(2, "h3");
32
+ i0.ɵɵtext(3, "No Integration Pipelines");
33
+ i0.ɵɵelementEnd();
34
+ i0.ɵɵelementStart(4, "p");
35
+ i0.ɵɵtext(5, "Configure integrations to see data flow pipelines here.");
36
+ i0.ɵɵelementEnd()();
37
+ } }
38
+ function PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_19_Template(rf, ctx) { if (rf & 1) {
39
+ i0.ɵɵelementStart(0, "span", 36);
40
+ i0.ɵɵtext(1);
41
+ i0.ɵɵelementEnd();
42
+ } if (rf & 2) {
43
+ const card_r4 = i0.ɵɵnextContext().$implicit;
44
+ i0.ɵɵadvance();
45
+ i0.ɵɵtextInterpolate(card_r4.LastSync);
46
+ } }
47
+ function PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_For_18_Conditional_13_Template(rf, ctx) { if (rf & 1) {
48
+ i0.ɵɵelementStart(0, "span", 64);
49
+ i0.ɵɵelement(1, "i", 67);
50
+ i0.ɵɵelementEnd();
51
+ } if (rf & 2) {
52
+ const em_r7 = i0.ɵɵnextContext().$implicit;
53
+ i0.ɵɵproperty("title", "Match: " + em_r7.MatchStrategy);
54
+ } }
55
+ function PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_For_18_Template(rf, ctx) { if (rf & 1) {
56
+ const _r6 = i0.ɵɵgetCurrentView();
57
+ i0.ɵɵelementStart(0, "div", 57);
58
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_For_18_Template_div_click_0_listener() { const em_r7 = i0.ɵɵrestoreView(_r6).$implicit; const card_r4 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnMapRowClick(card_r4, em_r7)); });
59
+ i0.ɵɵelementStart(1, "span", 58);
60
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_For_18_Template_span_click_1_listener($event) { i0.ɵɵrestoreView(_r6); return i0.ɵɵresetView($event.stopPropagation()); });
61
+ i0.ɵɵelementStart(2, "label", 59)(3, "input", 60);
62
+ i0.ɵɵlistener("change", function PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_For_18_Template_input_change_3_listener($event) { const em_r7 = i0.ɵɵrestoreView(_r6).$implicit; const card_r4 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnToggleSyncEnabled(card_r4, em_r7, $event)); });
63
+ i0.ɵɵelementEnd();
64
+ i0.ɵɵelement(4, "span", 61);
65
+ i0.ɵɵelementEnd()();
66
+ i0.ɵɵelementStart(5, "span", 62);
67
+ i0.ɵɵtext(6);
68
+ i0.ɵɵelementEnd();
69
+ i0.ɵɵelementStart(7, "span", 51)(8, "span");
70
+ i0.ɵɵtext(9);
71
+ i0.ɵɵelementEnd()();
72
+ i0.ɵɵelementStart(10, "span", 63);
73
+ i0.ɵɵtext(11);
74
+ i0.ɵɵelementEnd();
75
+ i0.ɵɵelementStart(12, "span", 53);
76
+ i0.ɵɵconditionalCreate(13, PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_For_18_Conditional_13_Template, 2, 1, "span", 64);
77
+ i0.ɵɵelementStart(14, "span", 64);
78
+ i0.ɵɵelement(15, "i", 18);
79
+ i0.ɵɵelementEnd();
80
+ i0.ɵɵelementStart(16, "span", 65);
81
+ i0.ɵɵelement(17, "i", 66);
82
+ i0.ɵɵelementEnd()()();
83
+ } if (rf & 2) {
84
+ const em_r7 = ctx.$implicit;
85
+ const ctx_r1 = i0.ɵɵnextContext(5);
86
+ i0.ɵɵclassProp("sync-disabled", !em_r7.SyncEnabled);
87
+ i0.ɵɵadvance(2);
88
+ i0.ɵɵproperty("title", em_r7.SyncEnabled ? "Sync enabled \u2014 click to disable" : "Sync disabled \u2014 click to enable");
89
+ i0.ɵɵadvance();
90
+ i0.ɵɵproperty("checked", em_r7.SyncEnabled);
91
+ i0.ɵɵadvance(2);
92
+ i0.ɵɵproperty("title", em_r7.ExternalObjectName);
93
+ i0.ɵɵadvance();
94
+ i0.ɵɵtextInterpolate1(" ", em_r7.ExternalObjectLabel ?? em_r7.ExternalObjectName, " ");
95
+ i0.ɵɵadvance(2);
96
+ i0.ɵɵclassMap(ctx_r1.DirectionBadgeClass(em_r7.SyncDirection));
97
+ i0.ɵɵadvance();
98
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.DirectionText(em_r7.SyncDirection), " ");
99
+ i0.ɵɵadvance();
100
+ i0.ɵɵproperty("title", em_r7.Entity);
101
+ i0.ɵɵadvance();
102
+ i0.ɵɵtextInterpolate1(" ", em_r7.Entity, " ");
103
+ i0.ɵɵadvance(2);
104
+ i0.ɵɵconditional(em_r7.MatchStrategy ? 13 : -1);
105
+ i0.ɵɵadvance();
106
+ i0.ɵɵproperty("title", "Conflict: " + em_r7.ConflictResolution);
107
+ } }
108
+ function PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_ForEmpty_19_Template(rf, ctx) { if (rf & 1) {
109
+ i0.ɵɵelementStart(0, "div", 56);
110
+ i0.ɵɵtext(1, " No entity maps match your filter. ");
111
+ i0.ɵɵelementEnd();
112
+ } }
113
+ function PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_Template(rf, ctx) { if (rf & 1) {
114
+ const _r5 = i0.ɵɵgetCurrentView();
115
+ i0.ɵɵelementStart(0, "div", 43)(1, "div", 44);
116
+ i0.ɵɵelement(2, "i", 45);
117
+ i0.ɵɵelementStart(3, "input", 46);
118
+ i0.ɵɵlistener("input", function PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_Template_input_input_3_listener($event) { i0.ɵɵrestoreView(_r5); const card_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnCardSearch(card_r4, $event)); });
119
+ i0.ɵɵelementEnd();
120
+ i0.ɵɵelementStart(4, "span", 47);
121
+ i0.ɵɵtext(5);
122
+ i0.ɵɵelementEnd()();
123
+ i0.ɵɵelementStart(6, "div", 48)(7, "span", 49);
124
+ i0.ɵɵtext(8, "Sync");
125
+ i0.ɵɵelementEnd();
126
+ i0.ɵɵelementStart(9, "span", 50);
127
+ i0.ɵɵtext(10, "External Object");
128
+ i0.ɵɵelementEnd();
129
+ i0.ɵɵelement(11, "span", 51);
130
+ i0.ɵɵelementStart(12, "span", 52);
131
+ i0.ɵɵtext(13, "MJ Entity");
132
+ i0.ɵɵelementEnd();
133
+ i0.ɵɵelementStart(14, "span", 53);
134
+ i0.ɵɵtext(15, "Config");
135
+ i0.ɵɵelementEnd()();
136
+ i0.ɵɵelementStart(16, "div", 54);
137
+ i0.ɵɵrepeaterCreate(17, PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_For_18_Template, 18, 13, "div", 55, _forTrack1, false, PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_ForEmpty_19_Template, 2, 0, "div", 56);
138
+ i0.ɵɵelementEnd()();
139
+ } if (rf & 2) {
140
+ const card_r4 = i0.ɵɵnextContext().$implicit;
141
+ i0.ɵɵadvance(3);
142
+ i0.ɵɵproperty("value", card_r4.SearchTerm);
143
+ i0.ɵɵadvance(2);
144
+ i0.ɵɵtextInterpolate2(" ", card_r4.FilteredMaps.length, " of ", card_r4.EntityMapCount, " ");
145
+ i0.ɵɵadvance(12);
146
+ i0.ɵɵrepeater(card_r4.FilteredMaps);
147
+ } }
148
+ function PipelinesComponent_Conditional_1_Conditional_23_For_2_Template(rf, ctx) { if (rf & 1) {
149
+ const _r3 = i0.ɵɵgetCurrentView();
150
+ i0.ɵɵelementStart(0, "div", 26)(1, "div", 27);
151
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_1_Conditional_23_For_2_Template_div_click_1_listener() { const card_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ToggleCard(card_r4)); });
152
+ i0.ɵɵelementStart(2, "div", 28);
153
+ i0.ɵɵelement(3, "div", 29)(4, "i");
154
+ i0.ɵɵelementStart(5, "div", 30)(6, "span", 31);
155
+ i0.ɵɵtext(7);
156
+ i0.ɵɵelementEnd();
157
+ i0.ɵɵelementStart(8, "span", 32);
158
+ i0.ɵɵtext(9);
159
+ i0.ɵɵelementStart(10, "span", 33);
160
+ i0.ɵɵtext(11, "\u00B7");
161
+ i0.ɵɵelementEnd();
162
+ i0.ɵɵtext(12);
163
+ i0.ɵɵelementStart(13, "span", 33);
164
+ i0.ɵɵtext(14, "\u00B7");
165
+ i0.ɵɵelementEnd();
166
+ i0.ɵɵtext(15);
167
+ i0.ɵɵelementEnd()()();
168
+ i0.ɵɵelementStart(16, "div", 34)(17, "span", 35);
169
+ i0.ɵɵtext(18);
170
+ i0.ɵɵelementEnd();
171
+ i0.ɵɵconditionalCreate(19, PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_19_Template, 2, 1, "span", 36);
172
+ i0.ɵɵelementStart(20, "div", 37);
173
+ i0.ɵɵelement(21, "span", 38)(22, "span", 39);
174
+ i0.ɵɵelementStart(23, "span", 40);
175
+ i0.ɵɵtext(24);
176
+ i0.ɵɵelementEnd();
177
+ i0.ɵɵelement(25, "span", 39)(26, "span", 41);
178
+ i0.ɵɵelementEnd();
179
+ i0.ɵɵelement(27, "i", 42);
180
+ i0.ɵɵelementEnd()();
181
+ i0.ɵɵconditionalCreate(28, PipelinesComponent_Conditional_1_Conditional_23_For_2_Conditional_28_Template, 20, 4, "div", 43);
182
+ i0.ɵɵelementEnd();
183
+ } if (rf & 2) {
184
+ const card_r4 = ctx.$implicit;
185
+ i0.ɵɵclassProp("expanded", card_r4.IsExpanded);
186
+ i0.ɵɵadvance(3);
187
+ i0.ɵɵstyleProp("background-color", card_r4.StatusColor);
188
+ i0.ɵɵadvance();
189
+ i0.ɵɵclassMap(card_r4.Icon + " card-icon");
190
+ i0.ɵɵadvance(3);
191
+ i0.ɵɵtextInterpolate(card_r4.IntegrationName);
192
+ i0.ɵɵadvance(2);
193
+ i0.ɵɵtextInterpolate1(" ", card_r4.EntityMapCount, " maps ");
194
+ i0.ɵɵadvance(3);
195
+ i0.ɵɵtextInterpolate1(" ", card_r4.ActiveMapCount, " active ");
196
+ i0.ɵɵadvance(3);
197
+ i0.ɵɵtextInterpolate1(" ", card_r4.UniqueEntityCount, " entities ");
198
+ i0.ɵɵadvance(2);
199
+ i0.ɵɵstyleProp("color", card_r4.StatusColor);
200
+ i0.ɵɵadvance();
201
+ i0.ɵɵtextInterpolate1(" ", card_r4.StatusLabel, " ");
202
+ i0.ɵɵadvance();
203
+ i0.ɵɵconditional(card_r4.LastSync ? 19 : -1);
204
+ i0.ɵɵadvance(5);
205
+ i0.ɵɵtextInterpolate(card_r4.EntityMapCount);
206
+ i0.ɵɵadvance(3);
207
+ i0.ɵɵclassProp("fa-chevron-down", !card_r4.IsExpanded)("fa-chevron-up", card_r4.IsExpanded);
208
+ i0.ɵɵadvance();
209
+ i0.ɵɵconditional(card_r4.IsExpanded ? 28 : -1);
210
+ } }
211
+ function PipelinesComponent_Conditional_1_Conditional_23_Template(rf, ctx) { if (rf & 1) {
212
+ i0.ɵɵelementStart(0, "div", 22);
213
+ i0.ɵɵrepeaterCreate(1, PipelinesComponent_Conditional_1_Conditional_23_For_2_Template, 29, 20, "div", 25, _forTrack0);
214
+ i0.ɵɵelementEnd();
215
+ } if (rf & 2) {
216
+ const ctx_r1 = i0.ɵɵnextContext(2);
217
+ i0.ɵɵadvance();
218
+ i0.ɵɵrepeater(ctx_r1.FilteredCards);
219
+ } }
220
+ function PipelinesComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
221
+ const _r1 = i0.ɵɵgetCurrentView();
222
+ i0.ɵɵelementStart(0, "div", 2)(1, "div", 3)(2, "h2", 4);
223
+ i0.ɵɵelement(3, "i", 5);
224
+ i0.ɵɵtext(4, " Pipelines ");
225
+ i0.ɵɵelementEnd();
226
+ i0.ɵɵelementStart(5, "span", 6);
227
+ i0.ɵɵtext(6);
228
+ i0.ɵɵelementEnd();
229
+ i0.ɵɵelementStart(7, "span", 7);
230
+ i0.ɵɵtext(8);
231
+ i0.ɵɵelementEnd()();
232
+ i0.ɵɵelementStart(9, "div", 8)(10, "div", 9);
233
+ i0.ɵɵelement(11, "i", 10);
234
+ i0.ɵɵelementStart(12, "input", 11);
235
+ i0.ɵɵlistener("input", function PipelinesComponent_Conditional_1_Template_input_input_12_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnGlobalSearchChange($event)); });
236
+ i0.ɵɵelementEnd()();
237
+ i0.ɵɵelementStart(13, "button", 12);
238
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_1_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ExpandAll()); });
239
+ i0.ɵɵelement(14, "i", 13);
240
+ i0.ɵɵelementEnd();
241
+ i0.ɵɵelementStart(15, "button", 14);
242
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_1_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CollapseAll()); });
243
+ i0.ɵɵelement(16, "i", 15);
244
+ i0.ɵɵelementEnd();
245
+ i0.ɵɵelement(17, "div", 16);
246
+ i0.ɵɵelementStart(18, "button", 17);
247
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_1_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.LoadData()); });
248
+ i0.ɵɵelement(19, "i", 18);
249
+ i0.ɵɵelementEnd()()();
250
+ i0.ɵɵelementStart(20, "div", 19);
251
+ i0.ɵɵconditionalCreate(21, PipelinesComponent_Conditional_1_Conditional_21_Template, 4, 0, "div", 20)(22, PipelinesComponent_Conditional_1_Conditional_22_Template, 6, 0, "div", 21)(23, PipelinesComponent_Conditional_1_Conditional_23_Template, 3, 0, "div", 22);
252
+ i0.ɵɵelementEnd();
253
+ } if (rf & 2) {
254
+ const ctx_r1 = i0.ɵɵnextContext();
255
+ i0.ɵɵadvance(6);
256
+ i0.ɵɵtextInterpolate(ctx_r1.IntegrationCount);
257
+ i0.ɵɵadvance(2);
258
+ i0.ɵɵtextInterpolate1("", ctx_r1.TotalMapCount, " entity maps");
259
+ i0.ɵɵadvance(4);
260
+ i0.ɵɵproperty("value", ctx_r1.GlobalSearch);
261
+ i0.ɵɵadvance(7);
262
+ i0.ɵɵclassProp("fa-spin", ctx_r1.IsLoading);
263
+ i0.ɵɵadvance(2);
264
+ i0.ɵɵconditional(ctx_r1.IsLoading && ctx_r1.PipelineCards.length === 0 ? 21 : ctx_r1.PipelineCards.length === 0 ? 22 : 23);
265
+ } }
266
+ function PipelinesComponent_Conditional_2_Conditional_12_Template(rf, ctx) { if (rf & 1) {
267
+ const _r9 = i0.ɵɵgetCurrentView();
268
+ i0.ɵɵelementStart(0, "label", 94)(1, "input", 60);
269
+ i0.ɵɵlistener("change", function PipelinesComponent_Conditional_2_Conditional_12_Template_input_change_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnToggleEditorSyncEnabled($event)); });
270
+ i0.ɵɵelementEnd();
271
+ i0.ɵɵelement(2, "span", 61);
272
+ i0.ɵɵelementEnd();
273
+ i0.ɵɵelementStart(3, "span", 95);
274
+ i0.ɵɵtext(4);
275
+ i0.ɵɵelementEnd();
276
+ } if (rf & 2) {
277
+ const ctx_r1 = i0.ɵɵnextContext(2);
278
+ i0.ɵɵproperty("title", ctx_r1.EditorEntityMap.SyncEnabled ? "Sync enabled" : "Sync disabled");
279
+ i0.ɵɵadvance();
280
+ i0.ɵɵproperty("checked", ctx_r1.EditorEntityMap.SyncEnabled);
281
+ i0.ɵɵadvance(3);
282
+ i0.ɵɵtextInterpolate(ctx_r1.EditorEntityMap.SyncEnabled ? "Sync On" : "Sync Off");
283
+ } }
284
+ function PipelinesComponent_Conditional_2_Conditional_40_Template(rf, ctx) { if (rf & 1) {
285
+ i0.ɵɵelement(0, "i", 23);
286
+ i0.ɵɵtext(1, " Saving... ");
287
+ } }
288
+ function PipelinesComponent_Conditional_2_Conditional_41_Template(rf, ctx) { if (rf & 1) {
289
+ i0.ɵɵelement(0, "i", 96);
290
+ i0.ɵɵtext(1, " Save ");
291
+ } }
292
+ function PipelinesComponent_Conditional_2_Conditional_42_Template(rf, ctx) { if (rf & 1) {
293
+ i0.ɵɵelementStart(0, "span", 89);
294
+ i0.ɵɵelement(1, "i", 97);
295
+ i0.ɵɵtext(2, " Saved ");
296
+ i0.ɵɵelementEnd();
297
+ } }
298
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_7_Template(rf, ctx) { if (rf & 1) {
299
+ i0.ɵɵelementStart(0, "div", 102);
300
+ i0.ɵɵelement(1, "i", 23);
301
+ i0.ɵɵtext(2, " Loading... ");
302
+ i0.ɵɵelementEnd();
303
+ } }
304
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_8_Template(rf, ctx) { if (rf & 1) {
305
+ i0.ɵɵelementStart(0, "div", 103);
306
+ i0.ɵɵtext(1, "No source data available");
307
+ i0.ɵɵelementEnd();
308
+ } }
309
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_9_For_5_Template(rf, ctx) { if (rf & 1) {
310
+ i0.ɵɵelementStart(0, "th");
311
+ i0.ɵɵtext(1);
312
+ i0.ɵɵelementEnd();
313
+ } if (rf & 2) {
314
+ const col_r11 = ctx.$implicit;
315
+ i0.ɵɵadvance();
316
+ i0.ɵɵtextInterpolate(col_r11);
317
+ } }
318
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_9_For_8_For_2_Template(rf, ctx) { if (rf & 1) {
319
+ i0.ɵɵelementStart(0, "td", 106);
320
+ i0.ɵɵtext(1);
321
+ i0.ɵɵelementEnd();
322
+ } if (rf & 2) {
323
+ const col_r12 = ctx.$implicit;
324
+ const row_r13 = i0.ɵɵnextContext().$implicit;
325
+ i0.ɵɵproperty("title", (row_r13[col_r12] == null ? null : row_r13[col_r12].toString()) ?? "");
326
+ i0.ɵɵadvance();
327
+ i0.ɵɵtextInterpolate(row_r13[col_r12] ?? "");
328
+ } }
329
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_9_For_8_Template(rf, ctx) { if (rf & 1) {
330
+ i0.ɵɵelementStart(0, "tr");
331
+ i0.ɵɵrepeaterCreate(1, PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_9_For_8_For_2_Template, 2, 2, "td", 106, i0.ɵɵrepeaterTrackByIdentity);
332
+ i0.ɵɵelementEnd();
333
+ } if (rf & 2) {
334
+ const ctx_r1 = i0.ɵɵnextContext(5);
335
+ i0.ɵɵadvance();
336
+ i0.ɵɵrepeater(ctx_r1.PreviewSourceColumns);
337
+ } }
338
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_9_Template(rf, ctx) { if (rf & 1) {
339
+ i0.ɵɵelementStart(0, "div", 104)(1, "table", 105)(2, "thead")(3, "tr");
340
+ i0.ɵɵrepeaterCreate(4, PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_9_For_5_Template, 2, 1, "th", null, i0.ɵɵrepeaterTrackByIdentity);
341
+ i0.ɵɵelementEnd()();
342
+ i0.ɵɵelementStart(6, "tbody");
343
+ i0.ɵɵrepeaterCreate(7, PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_9_For_8_Template, 3, 0, "tr", null, i0.ɵɵrepeaterTrackByIndex);
344
+ i0.ɵɵelementEnd()()();
345
+ } if (rf & 2) {
346
+ const ctx_r1 = i0.ɵɵnextContext(4);
347
+ i0.ɵɵadvance(4);
348
+ i0.ɵɵrepeater(ctx_r1.PreviewSourceColumns);
349
+ i0.ɵɵadvance(3);
350
+ i0.ɵɵrepeater(ctx_r1.PreviewSourceRows);
351
+ } }
352
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Template(rf, ctx) { if (rf & 1) {
353
+ const _r10 = i0.ɵɵgetCurrentView();
354
+ i0.ɵɵelementStart(0, "div", 98)(1, "div", 99);
355
+ i0.ɵɵelement(2, "i", 82);
356
+ i0.ɵɵelementStart(3, "span");
357
+ i0.ɵɵtext(4);
358
+ i0.ɵɵelementEnd();
359
+ i0.ɵɵelementStart(5, "button", 100);
360
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ShowSourcePreview = false); });
361
+ i0.ɵɵelement(6, "i", 101);
362
+ i0.ɵɵelementEnd()();
363
+ i0.ɵɵconditionalCreate(7, PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_7_Template, 3, 0, "div", 102)(8, PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_8_Template, 2, 0, "div", 103)(9, PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Conditional_9_Template, 9, 0, "div", 104);
364
+ i0.ɵɵelementEnd();
365
+ } if (rf & 2) {
366
+ const ctx_r1 = i0.ɵɵnextContext(3);
367
+ i0.ɵɵadvance(4);
368
+ i0.ɵɵtextInterpolate1("Source Preview: ", (ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.ExternalObjectLabel) ?? (ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.ExternalObjectName));
369
+ i0.ɵɵadvance(3);
370
+ i0.ɵɵconditional(ctx_r1.PreviewSourceLoading ? 7 : ctx_r1.PreviewSourceRows.length === 0 ? 8 : 9);
371
+ } }
372
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_7_Template(rf, ctx) { if (rf & 1) {
373
+ i0.ɵɵelementStart(0, "div", 102);
374
+ i0.ɵɵelement(1, "i", 23);
375
+ i0.ɵɵtext(2, " Loading... ");
376
+ i0.ɵɵelementEnd();
377
+ } }
378
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
379
+ i0.ɵɵelementStart(0, "div", 103);
380
+ i0.ɵɵtext(1, "No destination data available");
381
+ i0.ɵɵelementEnd();
382
+ } }
383
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_9_For_5_Template(rf, ctx) { if (rf & 1) {
384
+ i0.ɵɵelementStart(0, "th");
385
+ i0.ɵɵtext(1);
386
+ i0.ɵɵelementEnd();
387
+ } if (rf & 2) {
388
+ const col_r15 = ctx.$implicit;
389
+ i0.ɵɵadvance();
390
+ i0.ɵɵtextInterpolate(col_r15);
391
+ } }
392
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_9_For_8_For_2_Template(rf, ctx) { if (rf & 1) {
393
+ i0.ɵɵelementStart(0, "td", 106);
394
+ i0.ɵɵtext(1);
395
+ i0.ɵɵelementEnd();
396
+ } if (rf & 2) {
397
+ const col_r16 = ctx.$implicit;
398
+ const row_r17 = i0.ɵɵnextContext().$implicit;
399
+ i0.ɵɵproperty("title", (row_r17[col_r16] == null ? null : row_r17[col_r16].toString()) ?? "");
400
+ i0.ɵɵadvance();
401
+ i0.ɵɵtextInterpolate(row_r17[col_r16] ?? "");
402
+ } }
403
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_9_For_8_Template(rf, ctx) { if (rf & 1) {
404
+ i0.ɵɵelementStart(0, "tr");
405
+ i0.ɵɵrepeaterCreate(1, PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_9_For_8_For_2_Template, 2, 2, "td", 106, i0.ɵɵrepeaterTrackByIdentity);
406
+ i0.ɵɵelementEnd();
407
+ } if (rf & 2) {
408
+ const ctx_r1 = i0.ɵɵnextContext(5);
409
+ i0.ɵɵadvance();
410
+ i0.ɵɵrepeater(ctx_r1.PreviewDestColumns);
411
+ } }
412
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
413
+ i0.ɵɵelementStart(0, "div", 104)(1, "table", 105)(2, "thead")(3, "tr");
414
+ i0.ɵɵrepeaterCreate(4, PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_9_For_5_Template, 2, 1, "th", null, i0.ɵɵrepeaterTrackByIdentity);
415
+ i0.ɵɵelementEnd()();
416
+ i0.ɵɵelementStart(6, "tbody");
417
+ i0.ɵɵrepeaterCreate(7, PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_9_For_8_Template, 3, 0, "tr", null, i0.ɵɵrepeaterTrackByIndex);
418
+ i0.ɵɵelementEnd()()();
419
+ } if (rf & 2) {
420
+ const ctx_r1 = i0.ɵɵnextContext(4);
421
+ i0.ɵɵadvance(4);
422
+ i0.ɵɵrepeater(ctx_r1.PreviewDestColumns);
423
+ i0.ɵɵadvance(3);
424
+ i0.ɵɵrepeater(ctx_r1.PreviewDestRows);
425
+ } }
426
+ function PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Template(rf, ctx) { if (rf & 1) {
427
+ const _r14 = i0.ɵɵgetCurrentView();
428
+ i0.ɵɵelementStart(0, "div", 98)(1, "div", 99);
429
+ i0.ɵɵelement(2, "i", 84);
430
+ i0.ɵɵelementStart(3, "span");
431
+ i0.ɵɵtext(4);
432
+ i0.ɵɵelementEnd();
433
+ i0.ɵɵelementStart(5, "button", 100);
434
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ShowDestPreview = false); });
435
+ i0.ɵɵelement(6, "i", 101);
436
+ i0.ɵɵelementEnd()();
437
+ i0.ɵɵconditionalCreate(7, PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_7_Template, 3, 0, "div", 102)(8, PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_8_Template, 2, 0, "div", 103)(9, PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Conditional_9_Template, 9, 0, "div", 104);
438
+ i0.ɵɵelementEnd();
439
+ } if (rf & 2) {
440
+ const ctx_r1 = i0.ɵɵnextContext(3);
441
+ i0.ɵɵadvance(4);
442
+ i0.ɵɵtextInterpolate1("Dest Preview: ", ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.Entity);
443
+ i0.ɵɵadvance(3);
444
+ i0.ɵɵconditional(ctx_r1.PreviewDestLoading ? 7 : ctx_r1.PreviewDestRows.length === 0 ? 8 : 9);
445
+ } }
446
+ function PipelinesComponent_Conditional_2_Conditional_43_Template(rf, ctx) { if (rf & 1) {
447
+ i0.ɵɵelementStart(0, "div", 90);
448
+ i0.ɵɵconditionalCreate(1, PipelinesComponent_Conditional_2_Conditional_43_Conditional_1_Template, 10, 2, "div", 98);
449
+ i0.ɵɵconditionalCreate(2, PipelinesComponent_Conditional_2_Conditional_43_Conditional_2_Template, 10, 2, "div", 98);
450
+ i0.ɵɵelementEnd();
451
+ } if (rf & 2) {
452
+ const ctx_r1 = i0.ɵɵnextContext(2);
453
+ i0.ɵɵadvance();
454
+ i0.ɵɵconditional(ctx_r1.ShowSourcePreview ? 1 : -1);
455
+ i0.ɵɵadvance();
456
+ i0.ɵɵconditional(ctx_r1.ShowDestPreview ? 2 : -1);
457
+ } }
458
+ function PipelinesComponent_Conditional_2_Conditional_44_Template(rf, ctx) { if (rf & 1) {
459
+ const _r18 = i0.ɵɵgetCurrentView();
460
+ i0.ɵɵelementStart(0, "div", 91);
461
+ i0.ɵɵelement(1, "i", 67);
462
+ i0.ɵɵtext(2, " Click a destination field to map from ");
463
+ i0.ɵɵelementStart(3, "strong");
464
+ i0.ɵɵtext(4);
465
+ i0.ɵɵelementEnd();
466
+ i0.ɵɵelementStart(5, "button", 107);
467
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_44_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.CancelConnect()); });
468
+ i0.ɵɵtext(6, "Cancel");
469
+ i0.ɵɵelementEnd()();
470
+ } if (rf & 2) {
471
+ const ctx_r1 = i0.ɵɵnextContext(2);
472
+ i0.ɵɵadvance(4);
473
+ i0.ɵɵtextInterpolate(ctx_r1.ConnectingFromSource);
474
+ } }
475
+ function PipelinesComponent_Conditional_2_Conditional_46_Template(rf, ctx) { if (rf & 1) {
476
+ i0.ɵɵelementStart(0, "div", 93);
477
+ i0.ɵɵelement(1, "i", 23);
478
+ i0.ɵɵelementStart(2, "span");
479
+ i0.ɵɵtext(3, "Loading field mappings...");
480
+ i0.ɵɵelementEnd()();
481
+ } }
482
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_26_Conditional_6_Template(rf, ctx) { if (rf & 1) {
483
+ i0.ɵɵelementStart(0, "span", 141);
484
+ i0.ɵɵtext(1, "PK");
485
+ i0.ɵɵelementEnd();
486
+ } }
487
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_26_Conditional_7_Template(rf, ctx) { if (rf & 1) {
488
+ i0.ɵɵelementStart(0, "span", 142);
489
+ i0.ɵɵtext(1, "*");
490
+ i0.ɵɵelementEnd();
491
+ } }
492
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_26_Template(rf, ctx) { if (rf & 1) {
493
+ const _r21 = i0.ɵɵgetCurrentView();
494
+ i0.ɵɵelementStart(0, "div", 137);
495
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_26_Template_div_click_0_listener($event) { const sf_r22 = i0.ɵɵrestoreView(_r21).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.OnEditorSourceClick(sf_r22.Name); return i0.ɵɵresetView($event.stopPropagation()); });
496
+ i0.ɵɵelementStart(1, "span", 138);
497
+ i0.ɵɵtext(2);
498
+ i0.ɵɵelementEnd();
499
+ i0.ɵɵelementStart(3, "span", 139);
500
+ i0.ɵɵtext(4);
501
+ i0.ɵɵelementEnd();
502
+ i0.ɵɵelementStart(5, "span", 140);
503
+ i0.ɵɵconditionalCreate(6, PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_26_Conditional_6_Template, 2, 0, "span", 141);
504
+ i0.ɵɵconditionalCreate(7, PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_26_Conditional_7_Template, 2, 0, "span", 142);
505
+ i0.ɵɵelementEnd()();
506
+ } if (rf & 2) {
507
+ const sf_r22 = ctx.$implicit;
508
+ const ctx_r1 = i0.ɵɵnextContext(4);
509
+ i0.ɵɵstyleProp("height", ctx_r1.FIELD_HEIGHT, "px");
510
+ i0.ɵɵclassProp("mapped", ctx_r1.IsSourceFieldMapped(sf_r22.Name))("unmapped", !ctx_r1.IsSourceFieldMapped(sf_r22.Name))("connecting", ctx_r1.ConnectingFromSource === sf_r22.Name);
511
+ i0.ɵɵadvance();
512
+ i0.ɵɵproperty("title", sf_r22.Name);
513
+ i0.ɵɵadvance();
514
+ i0.ɵɵtextInterpolate(sf_r22.Label || sf_r22.Name);
515
+ i0.ɵɵadvance(2);
516
+ i0.ɵɵtextInterpolate(sf_r22.Type);
517
+ i0.ɵɵadvance(2);
518
+ i0.ɵɵconditional(sf_r22.IsPrimaryKey ? 6 : -1);
519
+ i0.ɵɵadvance();
520
+ i0.ɵɵconditional(sf_r22.IsRequired ? 7 : -1);
521
+ } }
522
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_Conditional_27_Template(rf, ctx) { if (rf & 1) {
523
+ i0.ɵɵelementStart(0, "div", 133);
524
+ i0.ɵɵtext(1, "No source fields found");
525
+ i0.ɵɵelementEnd();
526
+ } }
527
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_30_Template(rf, ctx) { if (rf & 1) {
528
+ const _r23 = i0.ɵɵgetCurrentView();
529
+ i0.ɵɵnamespaceSVG();
530
+ i0.ɵɵelementStart(0, "path", 143);
531
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_30_Template_path_click_0_listener($event) { const ɵ$index_483_r24 = i0.ɵɵrestoreView(_r23).$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SelectConnection(ɵ$index_483_r24, $event)); });
532
+ i0.ɵɵelementEnd();
533
+ i0.ɵɵelementStart(1, "foreignObject", 144);
534
+ i0.ɵɵnamespaceHTML();
535
+ i0.ɵɵelementStart(2, "div", 145);
536
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_30_Template_div_click_2_listener($event) { const ɵ$index_483_r24 = i0.ɵɵrestoreView(_r23).$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SelectConnection(ɵ$index_483_r24, $event)); });
537
+ i0.ɵɵelement(3, "i");
538
+ i0.ɵɵelementEnd()();
539
+ } if (rf & 2) {
540
+ const conn_r25 = ctx.$implicit;
541
+ const ɵ$index_483_r24 = ctx.$index;
542
+ const ctx_r1 = i0.ɵɵnextContext(4);
543
+ i0.ɵɵclassMap("ve-conn-line " + ctx_r1.GetConnectionLineClass(conn_r25));
544
+ i0.ɵɵclassProp("selected", ctx_r1.SelectedConnectionIdx === ɵ$index_483_r24);
545
+ i0.ɵɵattribute("d", ctx_r1.GetConnectionPath(conn_r25));
546
+ i0.ɵɵadvance();
547
+ i0.ɵɵattribute("x", ctx_r1.SVG_WIDTH / 2 - 14)("y", ctx_r1.GetConnectionMidY(conn_r25) - 14);
548
+ i0.ɵɵadvance();
549
+ i0.ɵɵclassMap("ve-conn-badge " + ctx_r1.GetConnectionBadgeClass(conn_r25));
550
+ i0.ɵɵclassProp("selected", ctx_r1.SelectedConnectionIdx === ɵ$index_483_r24);
551
+ i0.ɵɵadvance();
552
+ i0.ɵɵclassMap(ctx_r1.GetConnectionDirectionIcon(conn_r25));
553
+ } }
554
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_33_Conditional_6_Template(rf, ctx) { if (rf & 1) {
555
+ i0.ɵɵelementStart(0, "span", 142);
556
+ i0.ɵɵtext(1, "*");
557
+ i0.ɵɵelementEnd();
558
+ } }
559
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_33_Template(rf, ctx) { if (rf & 1) {
560
+ const _r26 = i0.ɵɵgetCurrentView();
561
+ i0.ɵɵelementStart(0, "div", 137);
562
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_33_Template_div_click_0_listener($event) { const df_r27 = i0.ɵɵrestoreView(_r26).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.OnEditorDestClick(df_r27.Name); return i0.ɵɵresetView($event.stopPropagation()); });
563
+ i0.ɵɵelementStart(1, "span", 138);
564
+ i0.ɵɵtext(2);
565
+ i0.ɵɵelementEnd();
566
+ i0.ɵɵelementStart(3, "span", 139);
567
+ i0.ɵɵtext(4);
568
+ i0.ɵɵelementEnd();
569
+ i0.ɵɵelementStart(5, "span", 140);
570
+ i0.ɵɵconditionalCreate(6, PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_33_Conditional_6_Template, 2, 0, "span", 142);
571
+ i0.ɵɵelementEnd()();
572
+ } if (rf & 2) {
573
+ const df_r27 = ctx.$implicit;
574
+ const ctx_r1 = i0.ɵɵnextContext(4);
575
+ i0.ɵɵstyleProp("height", ctx_r1.FIELD_HEIGHT, "px");
576
+ i0.ɵɵclassProp("mapped", ctx_r1.IsDestFieldMapped(df_r27.Name))("unmapped", !ctx_r1.IsDestFieldMapped(df_r27.Name))("connect-target", ctx_r1.ConnectingFromSource !== null);
577
+ i0.ɵɵadvance();
578
+ i0.ɵɵproperty("title", df_r27.Name);
579
+ i0.ɵɵadvance();
580
+ i0.ɵɵtextInterpolate(df_r27.Name);
581
+ i0.ɵɵadvance(2);
582
+ i0.ɵɵtextInterpolate(df_r27.Type);
583
+ i0.ɵɵadvance(2);
584
+ i0.ɵɵconditional(df_r27.IsRequired ? 6 : -1);
585
+ } }
586
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_Conditional_34_Template(rf, ctx) { if (rf & 1) {
587
+ i0.ɵɵelementStart(0, "div", 133);
588
+ i0.ɵɵtext(1, "No destination fields found");
589
+ i0.ɵɵelementEnd();
590
+ } }
591
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_Template(rf, ctx) { if (rf & 1) {
592
+ const _r20 = i0.ɵɵgetCurrentView();
593
+ i0.ɵɵelementStart(0, "div", 114)(1, "div", 117)(2, "div", 118)(3, "div", 119);
594
+ i0.ɵɵelement(4, "i", 82);
595
+ i0.ɵɵtext(5, " Source Fields ");
596
+ i0.ɵɵelementStart(6, "span", 120);
597
+ i0.ɵɵtext(7);
598
+ i0.ɵɵelementEnd()();
599
+ i0.ɵɵelement(8, "div", 121);
600
+ i0.ɵɵelementStart(9, "div", 122);
601
+ i0.ɵɵelement(10, "i", 84);
602
+ i0.ɵɵtext(11, " MJ Entity Fields ");
603
+ i0.ɵɵelementStart(12, "span", 120);
604
+ i0.ɵɵtext(13);
605
+ i0.ɵɵelementEnd()()();
606
+ i0.ɵɵelementStart(14, "div", 123)(15, "div", 124);
607
+ i0.ɵɵelement(16, "i", 125);
608
+ i0.ɵɵelementStart(17, "input", 126);
609
+ i0.ɵɵlistener("input", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_Template_input_input_17_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.EditorSearchSource = $event.target.value); });
610
+ i0.ɵɵelementEnd()();
611
+ i0.ɵɵelement(18, "div", 127);
612
+ i0.ɵɵelementStart(19, "div", 124);
613
+ i0.ɵɵelement(20, "i", 125);
614
+ i0.ɵɵelementStart(21, "input", 128);
615
+ i0.ɵɵlistener("input", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_Template_input_input_21_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.EditorSearchDest = $event.target.value); });
616
+ i0.ɵɵelementEnd()()();
617
+ i0.ɵɵelementStart(22, "div", 129);
618
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_Template_div_click_22_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.DeselectConnection()); });
619
+ i0.ɵɵelementStart(23, "div", 130)(24, "div", 131);
620
+ i0.ɵɵrepeaterCreate(25, PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_26_Template, 8, 13, "div", 132, _forTrack2);
621
+ i0.ɵɵconditionalCreate(27, PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_Conditional_27_Template, 2, 0, "div", 133);
622
+ i0.ɵɵelementEnd();
623
+ i0.ɵɵnamespaceSVG();
624
+ i0.ɵɵelementStart(28, "svg", 134);
625
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_Template_svg_click_28_listener($event) { i0.ɵɵrestoreView(_r20); return i0.ɵɵresetView($event.stopPropagation()); });
626
+ i0.ɵɵrepeaterCreate(29, PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_30_Template, 4, 13, null, null, _forTrack3);
627
+ i0.ɵɵelementEnd();
628
+ i0.ɵɵnamespaceHTML();
629
+ i0.ɵɵelementStart(31, "div", 135);
630
+ i0.ɵɵrepeaterCreate(32, PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_For_33_Template, 7, 12, "div", 136, _forTrack2);
631
+ i0.ɵɵconditionalCreate(34, PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_Conditional_34_Template, 2, 0, "div", 133);
632
+ i0.ɵɵelementEnd()()()()();
633
+ } if (rf & 2) {
634
+ const ctx_r1 = i0.ɵɵnextContext(3);
635
+ i0.ɵɵadvance(7);
636
+ i0.ɵɵtextInterpolate(ctx_r1.EditorSourceFields.length);
637
+ i0.ɵɵadvance(6);
638
+ i0.ɵɵtextInterpolate(ctx_r1.EditorDestFields.length);
639
+ i0.ɵɵadvance(4);
640
+ i0.ɵɵproperty("value", ctx_r1.EditorSearchSource);
641
+ i0.ɵɵadvance(4);
642
+ i0.ɵɵproperty("value", ctx_r1.EditorSearchDest);
643
+ i0.ɵɵadvance(2);
644
+ i0.ɵɵstyleProp("min-height", ctx_r1.EditorCanvasHeight, "px");
645
+ i0.ɵɵadvance(2);
646
+ i0.ɵɵrepeater(ctx_r1.FilteredEditorSourceFields);
647
+ i0.ɵɵadvance(2);
648
+ i0.ɵɵconditional(ctx_r1.FilteredEditorSourceFields.length === 0 ? 27 : -1);
649
+ i0.ɵɵadvance();
650
+ i0.ɵɵattribute("width", ctx_r1.SVG_WIDTH)("height", ctx_r1.EditorCanvasHeight)("viewBox", "0 0 " + ctx_r1.SVG_WIDTH + " " + ctx_r1.EditorCanvasHeight);
651
+ i0.ɵɵadvance();
652
+ i0.ɵɵrepeater(ctx_r1.VisibleConnections);
653
+ i0.ɵɵadvance(3);
654
+ i0.ɵɵrepeater(ctx_r1.FilteredEditorDestFields);
655
+ i0.ɵɵadvance(2);
656
+ i0.ɵɵconditional(ctx_r1.FilteredEditorDestFields.length === 0 ? 34 : -1);
657
+ } }
658
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_14_Conditional_1_Template(rf, ctx) { if (rf & 1) {
659
+ i0.ɵɵelementStart(0, "div", 146);
660
+ i0.ɵɵelement(1, "i", 23);
661
+ i0.ɵɵtext(2, " Loading stats... ");
662
+ i0.ɵɵelementEnd();
663
+ } }
664
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_14_Conditional_2_Conditional_25_Template(rf, ctx) { if (rf & 1) {
665
+ i0.ɵɵelementStart(0, "div", 148)(1, "div", 159);
666
+ i0.ɵɵelement(2, "i", 111);
667
+ i0.ɵɵelementEnd();
668
+ i0.ɵɵelementStart(3, "div", 150)(4, "span", 151);
669
+ i0.ɵɵtext(5);
670
+ i0.ɵɵelementEnd();
671
+ i0.ɵɵelementStart(6, "span", 152);
672
+ i0.ɵɵtext(7);
673
+ i0.ɵɵelementEnd()()();
674
+ } if (rf & 2) {
675
+ const ctx_r1 = i0.ɵɵnextContext(5);
676
+ i0.ɵɵadvance();
677
+ i0.ɵɵproperty("ngClass", ctx_r1.SyncStatusClass(ctx_r1.InfoLastSync.Status));
678
+ i0.ɵɵadvance();
679
+ i0.ɵɵclassProp("fa-circle-check", ctx_r1.InfoLastSync.Status === "Success")("fa-circle-xmark", ctx_r1.InfoLastSync.Status === "Failed")("fa-spinner", ctx_r1.InfoLastSync.Status === "In Progress")("fa-clock", ctx_r1.InfoLastSync.Status === "Pending");
680
+ i0.ɵɵadvance(3);
681
+ i0.ɵɵtextInterpolate(ctx_r1.InfoLastSync.Status);
682
+ i0.ɵɵadvance(2);
683
+ i0.ɵɵtextInterpolate1("", ctx_r1.InfoLastSync.TotalRecords, " records processed");
684
+ } }
685
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_14_Conditional_2_Conditional_47_Template(rf, ctx) { if (rf & 1) {
686
+ i0.ɵɵelementStart(0, "div", 156)(1, "span", 157);
687
+ i0.ɵɵtext(2, "Match Strategy");
688
+ i0.ɵɵelementEnd();
689
+ i0.ɵɵelementStart(3, "span", 158);
690
+ i0.ɵɵtext(4, "Configured");
691
+ i0.ɵɵelementEnd()();
692
+ } }
693
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_14_Conditional_2_Template(rf, ctx) { if (rf & 1) {
694
+ i0.ɵɵelementStart(0, "div", 147)(1, "div", 148)(2, "div", 149);
695
+ i0.ɵɵelement(3, "i", 84);
696
+ i0.ɵɵelementEnd();
697
+ i0.ɵɵelementStart(4, "div", 150)(5, "span", 151);
698
+ i0.ɵɵtext(6);
699
+ i0.ɵɵelementEnd();
700
+ i0.ɵɵelementStart(7, "span", 152);
701
+ i0.ɵɵtext(8, "MJ Records");
702
+ i0.ɵɵelementEnd()()();
703
+ i0.ɵɵelementStart(9, "div", 148)(10, "div", 153);
704
+ i0.ɵɵelement(11, "i", 82);
705
+ i0.ɵɵelementEnd();
706
+ i0.ɵɵelementStart(12, "div", 150)(13, "span", 151);
707
+ i0.ɵɵtext(14);
708
+ i0.ɵɵelementEnd();
709
+ i0.ɵɵelementStart(15, "span", 152);
710
+ i0.ɵɵtext(16, "Source Fields");
711
+ i0.ɵɵelementEnd()()();
712
+ i0.ɵɵelementStart(17, "div", 148)(18, "div", 154);
713
+ i0.ɵɵelement(19, "i", 18);
714
+ i0.ɵɵelementEnd();
715
+ i0.ɵɵelementStart(20, "div", 150)(21, "span", 151);
716
+ i0.ɵɵtext(22);
717
+ i0.ɵɵelementEnd();
718
+ i0.ɵɵelementStart(23, "span", 152);
719
+ i0.ɵɵtext(24, "Last Sync");
720
+ i0.ɵɵelementEnd()()();
721
+ i0.ɵɵconditionalCreate(25, PipelinesComponent_Conditional_2_Conditional_47_Conditional_14_Conditional_2_Conditional_25_Template, 8, 11, "div", 148);
722
+ i0.ɵɵelementEnd();
723
+ i0.ɵɵelementStart(26, "div", 155)(27, "div", 156)(28, "span", 157);
724
+ i0.ɵɵtext(29, "Sync Direction");
725
+ i0.ɵɵelementEnd();
726
+ i0.ɵɵelementStart(30, "span", 158);
727
+ i0.ɵɵtext(31);
728
+ i0.ɵɵelementEnd()();
729
+ i0.ɵɵelementStart(32, "div", 156)(33, "span", 157);
730
+ i0.ɵɵtext(34, "Conflict Resolution");
731
+ i0.ɵɵelementEnd();
732
+ i0.ɵɵelementStart(35, "span", 158);
733
+ i0.ɵɵtext(36);
734
+ i0.ɵɵelementEnd()();
735
+ i0.ɵɵelementStart(37, "div", 156)(38, "span", 157);
736
+ i0.ɵɵtext(39, "Delete Behavior");
737
+ i0.ɵɵelementEnd();
738
+ i0.ɵɵelementStart(40, "span", 158);
739
+ i0.ɵɵtext(41);
740
+ i0.ɵɵelementEnd()();
741
+ i0.ɵɵelementStart(42, "div", 156)(43, "span", 157);
742
+ i0.ɵɵtext(44, "Priority");
743
+ i0.ɵɵelementEnd();
744
+ i0.ɵɵelementStart(45, "span", 158);
745
+ i0.ɵɵtext(46);
746
+ i0.ɵɵelementEnd()();
747
+ i0.ɵɵconditionalCreate(47, PipelinesComponent_Conditional_2_Conditional_47_Conditional_14_Conditional_2_Conditional_47_Template, 5, 0, "div", 156);
748
+ i0.ɵɵelementEnd();
749
+ } if (rf & 2) {
750
+ const ctx_r1 = i0.ɵɵnextContext(4);
751
+ i0.ɵɵadvance(6);
752
+ i0.ɵɵtextInterpolate(ctx_r1.InfoDestRecordCount ?? "-");
753
+ i0.ɵɵadvance(8);
754
+ i0.ɵɵtextInterpolate(ctx_r1.EditorSourceFields.length);
755
+ i0.ɵɵadvance(8);
756
+ i0.ɵɵtextInterpolate(ctx_r1.FormatSyncDate((ctx_r1.InfoLastSync == null ? null : ctx_r1.InfoLastSync.StartedAt) ?? null));
757
+ i0.ɵɵadvance(3);
758
+ i0.ɵɵconditional(ctx_r1.InfoLastSync ? 25 : -1);
759
+ i0.ɵɵadvance(6);
760
+ i0.ɵɵtextInterpolate(ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.SyncDirection);
761
+ i0.ɵɵadvance(5);
762
+ i0.ɵɵtextInterpolate(ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.ConflictResolution);
763
+ i0.ɵɵadvance(5);
764
+ i0.ɵɵtextInterpolate(ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.DeleteBehavior);
765
+ i0.ɵɵadvance(5);
766
+ i0.ɵɵtextInterpolate(ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.Priority);
767
+ i0.ɵɵadvance();
768
+ i0.ɵɵconditional((ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.MatchStrategy) ? 47 : -1);
769
+ } }
770
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_14_Template(rf, ctx) { if (rf & 1) {
771
+ i0.ɵɵelementStart(0, "div", 115);
772
+ i0.ɵɵconditionalCreate(1, PipelinesComponent_Conditional_2_Conditional_47_Conditional_14_Conditional_1_Template, 3, 0, "div", 146)(2, PipelinesComponent_Conditional_2_Conditional_47_Conditional_14_Conditional_2_Template, 48, 9);
773
+ i0.ɵɵelementEnd();
774
+ } if (rf & 2) {
775
+ const ctx_r1 = i0.ɵɵnextContext(3);
776
+ i0.ɵɵadvance();
777
+ i0.ɵɵconditional(ctx_r1.InfoPanelLoading ? 1 : 2);
778
+ } }
779
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Conditional_16_Template(rf, ctx) { if (rf & 1) {
780
+ i0.ɵɵelement(0, "i", 96);
781
+ } }
782
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Conditional_21_Template(rf, ctx) { if (rf & 1) {
783
+ i0.ɵɵelement(0, "i", 96);
784
+ } }
785
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_For_6_Template(rf, ctx) { if (rf & 1) {
786
+ i0.ɵɵelementStart(0, "option", 187);
787
+ i0.ɵɵtext(1);
788
+ i0.ɵɵelementEnd();
789
+ } if (rf & 2) {
790
+ const tt_r31 = ctx.$implicit;
791
+ const step_r32 = i0.ɵɵnextContext().$implicit;
792
+ i0.ɵɵproperty("value", tt_r31.Value)("selected", tt_r31.Value === step_r32.Type);
793
+ i0.ɵɵadvance();
794
+ i0.ɵɵtextInterpolate(tt_r31.Label);
795
+ } }
796
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_Conditional_9_For_2_Template(rf, ctx) { if (rf & 1) {
797
+ const _r33 = i0.ɵɵgetCurrentView();
798
+ i0.ɵɵelementStart(0, "div", 195)(1, "label");
799
+ i0.ɵɵtext(2);
800
+ i0.ɵɵelementEnd();
801
+ i0.ɵɵelementStart(3, "input", 196);
802
+ i0.ɵɵlistener("input", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_Conditional_9_For_2_Template_input_input_3_listener($event) { const key_r34 = i0.ɵɵrestoreView(_r33).$implicit; const ɵ$index_708_r30 = i0.ɵɵnextContext(2).$index; const conn_r35 = i0.ɵɵnextContext(); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnTransformConfigChange(conn_r35, ɵ$index_708_r30, key_r34, $event.target.value)); });
803
+ i0.ɵɵelementEnd()();
804
+ } if (rf & 2) {
805
+ const key_r34 = ctx.$implicit;
806
+ const step_r32 = i0.ɵɵnextContext(2).$implicit;
807
+ const ctx_r1 = i0.ɵɵnextContext(4);
808
+ i0.ɵɵadvance(2);
809
+ i0.ɵɵtextInterpolate(key_r34);
810
+ i0.ɵɵadvance();
811
+ i0.ɵɵproperty("placeholder", i0.ɵɵinterpolate(key_r34))("value", ctx_r1.GetConfigValue(step_r32, key_r34));
812
+ } }
813
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_Conditional_9_Template(rf, ctx) { if (rf & 1) {
814
+ i0.ɵɵelementStart(0, "div", 189);
815
+ i0.ɵɵrepeaterCreate(1, PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_Conditional_9_For_2_Template, 4, 4, "div", 195, i0.ɵɵrepeaterTrackByIdentity);
816
+ i0.ɵɵelementEnd();
817
+ } if (rf & 2) {
818
+ const step_r32 = i0.ɵɵnextContext().$implicit;
819
+ const ctx_r1 = i0.ɵɵnextContext(4);
820
+ i0.ɵɵadvance();
821
+ i0.ɵɵrepeater(ctx_r1.GetConfigKeys(step_r32));
822
+ } }
823
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_Template(rf, ctx) { if (rf & 1) {
824
+ const _r29 = i0.ɵɵgetCurrentView();
825
+ i0.ɵɵelementStart(0, "div", 179)(1, "div", 184)(2, "span", 185);
826
+ i0.ɵɵtext(3);
827
+ i0.ɵɵelementEnd();
828
+ i0.ɵɵelementStart(4, "select", 186);
829
+ i0.ɵɵlistener("change", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_Template_select_change_4_listener($event) { const ɵ$index_708_r30 = i0.ɵɵrestoreView(_r29).$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnConnectionTransformChange(ɵ$index_708_r30, $event.target.value)); });
830
+ i0.ɵɵrepeaterCreate(5, PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_For_6_Template, 2, 3, "option", 187, _forTrack4);
831
+ i0.ɵɵelementEnd();
832
+ i0.ɵɵelementStart(7, "button", 188);
833
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_Template_button_click_7_listener() { const ɵ$index_708_r30 = i0.ɵɵrestoreView(_r29).$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.RemoveTransformStep(ɵ$index_708_r30)); });
834
+ i0.ɵɵelement(8, "i", 183);
835
+ i0.ɵɵelementEnd()();
836
+ i0.ɵɵconditionalCreate(9, PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_Conditional_9_Template, 3, 0, "div", 189);
837
+ i0.ɵɵelementStart(10, "div", 190)(11, "label");
838
+ i0.ɵɵtext(12, "On Error:");
839
+ i0.ɵɵelementEnd();
840
+ i0.ɵɵelementStart(13, "select", 191);
841
+ i0.ɵɵlistener("change", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_Template_select_change_13_listener($event) { const step_r32 = i0.ɵɵrestoreView(_r29).$implicit; const conn_r35 = i0.ɵɵnextContext(); step_r32.OnError = $event.target.value; return i0.ɵɵresetView(conn_r35.IsDirty = true); });
842
+ i0.ɵɵelementStart(14, "option", 192);
843
+ i0.ɵɵtext(15, "Fail");
844
+ i0.ɵɵelementEnd();
845
+ i0.ɵɵelementStart(16, "option", 193);
846
+ i0.ɵɵtext(17, "Skip");
847
+ i0.ɵɵelementEnd();
848
+ i0.ɵɵelementStart(18, "option", 194);
849
+ i0.ɵɵtext(19, "Null");
850
+ i0.ɵɵelementEnd()()()();
851
+ } if (rf & 2) {
852
+ const step_r32 = ctx.$implicit;
853
+ const ɵ$index_708_r30 = ctx.$index;
854
+ const ctx_r1 = i0.ɵɵnextContext(4);
855
+ i0.ɵɵadvance(3);
856
+ i0.ɵɵtextInterpolate(ɵ$index_708_r30 + 1);
857
+ i0.ɵɵadvance();
858
+ i0.ɵɵproperty("value", step_r32.Type);
859
+ i0.ɵɵadvance();
860
+ i0.ɵɵrepeater(ctx_r1.TRANSFORM_TYPES);
861
+ i0.ɵɵadvance(4);
862
+ i0.ɵɵconditional(step_r32.Type !== "direct" ? 9 : -1);
863
+ i0.ɵɵadvance(4);
864
+ i0.ɵɵproperty("value", step_r32.OnError);
865
+ } }
866
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Conditional_43_Template(rf, ctx) { if (rf & 1) {
867
+ i0.ɵɵelementStart(0, "div", 180);
868
+ i0.ɵɵtext(1, " No transform steps. Data passes through as-is. ");
869
+ i0.ɵɵelementEnd();
870
+ } }
871
+ function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template(rf, ctx) { if (rf & 1) {
872
+ const _r28 = i0.ɵɵgetCurrentView();
873
+ i0.ɵɵelementStart(0, "div", 160);
874
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r28); return i0.ɵɵresetView($event.stopPropagation()); });
875
+ i0.ɵɵelementStart(1, "div", 161)(2, "span", 162);
876
+ i0.ɵɵtext(3, "Mapping Details");
877
+ i0.ɵɵelementEnd();
878
+ i0.ɵɵelementStart(4, "button", 163);
879
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r28); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.DeselectConnection()); });
880
+ i0.ɵɵelement(5, "i", 101);
881
+ i0.ɵɵelementEnd()();
882
+ i0.ɵɵelementStart(6, "div", 164)(7, "div", 165)(8, "span", 166);
883
+ i0.ɵɵtext(9);
884
+ i0.ɵɵelementEnd();
885
+ i0.ɵɵelement(10, "i", 167);
886
+ i0.ɵɵelementStart(11, "span", 168);
887
+ i0.ɵɵtext(12);
888
+ i0.ɵɵelementEnd()()();
889
+ i0.ɵɵelementStart(13, "div", 169)(14, "label", 170);
890
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template_label_click_14_listener() { i0.ɵɵrestoreView(_r28); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ToggleConnectionKey()); });
891
+ i0.ɵɵelementStart(15, "span", 171);
892
+ i0.ɵɵconditionalCreate(16, PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Conditional_16_Template, 1, 0, "i", 96);
893
+ i0.ɵɵelementEnd();
894
+ i0.ɵɵelementStart(17, "span");
895
+ i0.ɵɵtext(18, "Key Field");
896
+ i0.ɵɵelementEnd()();
897
+ i0.ɵɵelementStart(19, "label", 170);
898
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template_label_click_19_listener() { i0.ɵɵrestoreView(_r28); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ToggleConnectionRequired()); });
899
+ i0.ɵɵelementStart(20, "span", 171);
900
+ i0.ɵɵconditionalCreate(21, PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Conditional_21_Template, 1, 0, "i", 96);
901
+ i0.ɵɵelementEnd();
902
+ i0.ɵɵelementStart(22, "span");
903
+ i0.ɵɵtext(23, "Required");
904
+ i0.ɵɵelementEnd()()();
905
+ i0.ɵɵelementStart(24, "div", 172)(25, "label", 173);
906
+ i0.ɵɵtext(26, "Direction");
907
+ i0.ɵɵelementEnd();
908
+ i0.ɵɵelementStart(27, "div", 174)(28, "button", 175);
909
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template_button_click_28_listener() { i0.ɵɵrestoreView(_r28); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnConnectionDirectionChange("SourceToDest")); });
910
+ i0.ɵɵtext(29, " Source \u2192 Dest ");
911
+ i0.ɵɵelementEnd();
912
+ i0.ɵɵelementStart(30, "button", 175);
913
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template_button_click_30_listener() { i0.ɵɵrestoreView(_r28); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnConnectionDirectionChange("DestToSource")); });
914
+ i0.ɵɵtext(31, " Dest \u2192 Source ");
915
+ i0.ɵɵelementEnd();
916
+ i0.ɵɵelementStart(32, "button", 175);
917
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template_button_click_32_listener() { i0.ɵɵrestoreView(_r28); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnConnectionDirectionChange("Both")); });
918
+ i0.ɵɵtext(33, " Both ");
919
+ i0.ɵɵelementEnd()()();
920
+ i0.ɵɵelementStart(34, "div", 172)(35, "div", 176)(36, "label", 173);
921
+ i0.ɵɵtext(37, "Transform Pipeline");
922
+ i0.ɵɵelementEnd();
923
+ i0.ɵɵelementStart(38, "button", 177);
924
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template_button_click_38_listener() { i0.ɵɵrestoreView(_r28); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.AddTransformStep()); });
925
+ i0.ɵɵelement(39, "i", 178);
926
+ i0.ɵɵtext(40, " Add Step ");
927
+ i0.ɵɵelementEnd()();
928
+ i0.ɵɵrepeaterCreate(41, PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_For_42_Template, 20, 4, "div", 179, i0.ɵɵrepeaterTrackByIndex);
929
+ i0.ɵɵconditionalCreate(43, PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Conditional_43_Template, 2, 0, "div", 180);
930
+ i0.ɵɵelementEnd();
931
+ i0.ɵɵelementStart(44, "div", 181)(45, "button", 182);
932
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template_button_click_45_listener() { i0.ɵɵrestoreView(_r28); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.RemoveSelectedConnection()); });
933
+ i0.ɵɵelement(46, "i", 183);
934
+ i0.ɵɵtext(47, " Remove Mapping ");
935
+ i0.ɵɵelementEnd()()();
936
+ } if (rf & 2) {
937
+ const conn_r35 = ctx;
938
+ i0.ɵɵadvance(9);
939
+ i0.ɵɵtextInterpolate(conn_r35.SourceFieldName);
940
+ i0.ɵɵadvance();
941
+ i0.ɵɵclassProp("fa-arrow-right", conn_r35.Direction === "SourceToDest")("fa-arrow-left", conn_r35.Direction === "DestToSource")("fa-right-left", conn_r35.Direction === "Both");
942
+ i0.ɵɵadvance(2);
943
+ i0.ɵɵtextInterpolate(conn_r35.DestFieldName);
944
+ i0.ɵɵadvance(3);
945
+ i0.ɵɵclassProp("active", conn_r35.IsKeyField);
946
+ i0.ɵɵadvance();
947
+ i0.ɵɵconditional(conn_r35.IsKeyField ? 16 : -1);
948
+ i0.ɵɵadvance(4);
949
+ i0.ɵɵclassProp("active", conn_r35.IsRequired);
950
+ i0.ɵɵadvance();
951
+ i0.ɵɵconditional(conn_r35.IsRequired ? 21 : -1);
952
+ i0.ɵɵadvance(7);
953
+ i0.ɵɵclassProp("active", conn_r35.Direction === "SourceToDest");
954
+ i0.ɵɵadvance(2);
955
+ i0.ɵɵclassProp("active", conn_r35.Direction === "DestToSource");
956
+ i0.ɵɵadvance(2);
957
+ i0.ɵɵclassProp("active", conn_r35.Direction === "Both");
958
+ i0.ɵɵadvance(9);
959
+ i0.ɵɵrepeater(conn_r35.TransformSteps);
960
+ i0.ɵɵadvance(2);
961
+ i0.ɵɵconditional(conn_r35.TransformSteps.length === 0 ? 43 : -1);
962
+ } }
963
+ function PipelinesComponent_Conditional_2_Conditional_47_Template(rf, ctx) { if (rf & 1) {
964
+ const _r19 = i0.ɵɵgetCurrentView();
965
+ i0.ɵɵelementStart(0, "div", 108)(1, "div", 109)(2, "div", 110);
966
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleFieldMaps()); });
967
+ i0.ɵɵelement(3, "i", 111);
968
+ i0.ɵɵelementStart(4, "span", 112);
969
+ i0.ɵɵtext(5, "Field Mappings");
970
+ i0.ɵɵelementEnd();
971
+ i0.ɵɵelementStart(6, "span", 113);
972
+ i0.ɵɵtext(7);
973
+ i0.ɵɵelementEnd()();
974
+ i0.ɵɵconditionalCreate(8, PipelinesComponent_Conditional_2_Conditional_47_Conditional_8_Template, 35, 11, "div", 114);
975
+ i0.ɵɵelementEnd();
976
+ i0.ɵɵelementStart(9, "div", 109)(10, "div", 110);
977
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Conditional_47_Template_div_click_10_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleInfoPanel()); });
978
+ i0.ɵɵelement(11, "i", 111);
979
+ i0.ɵɵelementStart(12, "span", 112);
980
+ i0.ɵɵtext(13, "Sync Info");
981
+ i0.ɵɵelementEnd()();
982
+ i0.ɵɵconditionalCreate(14, PipelinesComponent_Conditional_2_Conditional_47_Conditional_14_Template, 3, 1, "div", 115);
983
+ i0.ɵɵelementEnd()();
984
+ i0.ɵɵconditionalCreate(15, PipelinesComponent_Conditional_2_Conditional_47_Conditional_15_Template, 48, 21, "div", 116);
985
+ } if (rf & 2) {
986
+ let tmp_11_0;
987
+ const ctx_r1 = i0.ɵɵnextContext(2);
988
+ i0.ɵɵadvance();
989
+ i0.ɵɵclassProp("collapsed", !ctx_r1.FieldMapsExpanded);
990
+ i0.ɵɵadvance(2);
991
+ i0.ɵɵclassProp("fa-chevron-down", ctx_r1.FieldMapsExpanded)("fa-chevron-right", !ctx_r1.FieldMapsExpanded);
992
+ i0.ɵɵadvance(4);
993
+ i0.ɵɵtextInterpolate1("", ctx_r1.EditorMappedCount, " mapped");
994
+ i0.ɵɵadvance();
995
+ i0.ɵɵconditional(ctx_r1.FieldMapsExpanded ? 8 : -1);
996
+ i0.ɵɵadvance();
997
+ i0.ɵɵclassProp("collapsed", !ctx_r1.InfoPanelExpanded);
998
+ i0.ɵɵadvance(2);
999
+ i0.ɵɵclassProp("fa-chevron-down", ctx_r1.InfoPanelExpanded)("fa-chevron-right", !ctx_r1.InfoPanelExpanded);
1000
+ i0.ɵɵadvance(3);
1001
+ i0.ɵɵconditional(ctx_r1.InfoPanelExpanded ? 14 : -1);
1002
+ i0.ɵɵadvance();
1003
+ i0.ɵɵconditional((tmp_11_0 = ctx_r1.SelectedConnection) ? 15 : -1, tmp_11_0);
1004
+ } }
1005
+ function PipelinesComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
1006
+ const _r8 = i0.ɵɵgetCurrentView();
1007
+ i0.ɵɵelementStart(0, "div", 1)(1, "div", 68)(2, "div", 69)(3, "button", 70);
1008
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseVisualEditor()); });
1009
+ i0.ɵɵelement(4, "i", 71);
1010
+ i0.ɵɵelementEnd();
1011
+ i0.ɵɵelementStart(5, "div", 72)(6, "span", 73);
1012
+ i0.ɵɵtext(7);
1013
+ i0.ɵɵelementEnd();
1014
+ i0.ɵɵelementStart(8, "span", 74);
1015
+ i0.ɵɵelement(9, "i", 75);
1016
+ i0.ɵɵelementEnd();
1017
+ i0.ɵɵelementStart(10, "span", 76);
1018
+ i0.ɵɵtext(11);
1019
+ i0.ɵɵelementEnd()();
1020
+ i0.ɵɵconditionalCreate(12, PipelinesComponent_Conditional_2_Conditional_12_Template, 5, 3);
1021
+ i0.ɵɵelementEnd();
1022
+ i0.ɵɵelementStart(13, "div", 77)(14, "span", 78)(15, "strong");
1023
+ i0.ɵɵtext(16);
1024
+ i0.ɵɵelementEnd();
1025
+ i0.ɵɵtext(17, " mapped ");
1026
+ i0.ɵɵelementEnd();
1027
+ i0.ɵɵelement(18, "span", 79);
1028
+ i0.ɵɵelementStart(19, "span", 78)(20, "strong");
1029
+ i0.ɵɵtext(21);
1030
+ i0.ɵɵelementEnd();
1031
+ i0.ɵɵtext(22, " key ");
1032
+ i0.ɵɵelementEnd();
1033
+ i0.ɵɵelement(23, "span", 79);
1034
+ i0.ɵɵelementStart(24, "span", 78)(25, "strong");
1035
+ i0.ɵɵtext(26);
1036
+ i0.ɵɵelementEnd();
1037
+ i0.ɵɵtext(27, " required ");
1038
+ i0.ɵɵelementEnd()();
1039
+ i0.ɵɵelementStart(28, "div", 80)(29, "button", 81);
1040
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Template_button_click_29_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleSourcePreview()); });
1041
+ i0.ɵɵelement(30, "i", 82);
1042
+ i0.ɵɵtext(31, " Source Data ");
1043
+ i0.ɵɵelementEnd();
1044
+ i0.ɵɵelementStart(32, "button", 83);
1045
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Template_button_click_32_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ToggleDestPreview()); });
1046
+ i0.ɵɵelement(33, "i", 84);
1047
+ i0.ɵɵtext(34, " MJ Data ");
1048
+ i0.ɵɵelementEnd();
1049
+ i0.ɵɵelement(35, "div", 85);
1050
+ i0.ɵɵelementStart(36, "button", 86);
1051
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Template_button_click_36_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.AutoMapEditorFields()); });
1052
+ i0.ɵɵelement(37, "i", 87);
1053
+ i0.ɵɵtext(38, " Auto-Map ");
1054
+ i0.ɵɵelementEnd();
1055
+ i0.ɵɵelementStart(39, "button", 88);
1056
+ i0.ɵɵlistener("click", function PipelinesComponent_Conditional_2_Template_button_click_39_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SaveVisualEditor()); });
1057
+ i0.ɵɵconditionalCreate(40, PipelinesComponent_Conditional_2_Conditional_40_Template, 2, 0)(41, PipelinesComponent_Conditional_2_Conditional_41_Template, 2, 0);
1058
+ i0.ɵɵelementEnd();
1059
+ i0.ɵɵconditionalCreate(42, PipelinesComponent_Conditional_2_Conditional_42_Template, 3, 0, "span", 89);
1060
+ i0.ɵɵelementEnd()();
1061
+ i0.ɵɵconditionalCreate(43, PipelinesComponent_Conditional_2_Conditional_43_Template, 3, 2, "div", 90);
1062
+ i0.ɵɵconditionalCreate(44, PipelinesComponent_Conditional_2_Conditional_44_Template, 7, 1, "div", 91);
1063
+ i0.ɵɵelementStart(45, "div", 92);
1064
+ i0.ɵɵconditionalCreate(46, PipelinesComponent_Conditional_2_Conditional_46_Template, 4, 0, "div", 93)(47, PipelinesComponent_Conditional_2_Conditional_47_Template, 16, 16);
1065
+ i0.ɵɵelementEnd()();
1066
+ } if (rf & 2) {
1067
+ const ctx_r1 = i0.ɵɵnextContext();
1068
+ i0.ɵɵadvance(7);
1069
+ i0.ɵɵtextInterpolate((ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.ExternalObjectLabel) ?? (ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.ExternalObjectName));
1070
+ i0.ɵɵadvance(4);
1071
+ i0.ɵɵtextInterpolate(ctx_r1.EditorEntityMap == null ? null : ctx_r1.EditorEntityMap.Entity);
1072
+ i0.ɵɵadvance();
1073
+ i0.ɵɵconditional(ctx_r1.EditorEntityMap ? 12 : -1);
1074
+ i0.ɵɵadvance(4);
1075
+ i0.ɵɵtextInterpolate(ctx_r1.EditorMappedCount);
1076
+ i0.ɵɵadvance(5);
1077
+ i0.ɵɵtextInterpolate(ctx_r1.EditorKeyFieldCount);
1078
+ i0.ɵɵadvance(5);
1079
+ i0.ɵɵtextInterpolate(ctx_r1.EditorRequiredCount);
1080
+ i0.ɵɵadvance(3);
1081
+ i0.ɵɵclassProp("active", ctx_r1.ShowSourcePreview);
1082
+ i0.ɵɵadvance(3);
1083
+ i0.ɵɵclassProp("active", ctx_r1.ShowDestPreview);
1084
+ i0.ɵɵadvance(7);
1085
+ i0.ɵɵproperty("disabled", !ctx_r1.HasEditorChanges || ctx_r1.EditorSaving);
1086
+ i0.ɵɵadvance();
1087
+ i0.ɵɵconditional(ctx_r1.EditorSaving ? 40 : 41);
1088
+ i0.ɵɵadvance(2);
1089
+ i0.ɵɵconditional(ctx_r1.EditorSaveSuccess && !ctx_r1.HasEditorChanges ? 42 : -1);
1090
+ i0.ɵɵadvance();
1091
+ i0.ɵɵconditional(ctx_r1.ShowSourcePreview || ctx_r1.ShowDestPreview ? 43 : -1);
1092
+ i0.ɵɵadvance();
1093
+ i0.ɵɵconditional(ctx_r1.ConnectingFromSource ? 44 : -1);
1094
+ i0.ɵɵadvance();
1095
+ i0.ɵɵclassProp("has-transform-panel", ctx_r1.SelectedConnectionIdx !== null);
1096
+ i0.ɵɵadvance();
1097
+ i0.ɵɵconditional(ctx_r1.EditorLoading ? 46 : 47);
1098
+ } }
1099
+ let PipelinesComponent = class PipelinesComponent extends BaseResourceComponent {
1100
+ // ---------------------------------------------------------------------------
1101
+ // Public state — Card list
1102
+ // ---------------------------------------------------------------------------
1103
+ PipelineCards = [];
1104
+ IsLoading = false;
1105
+ GlobalSearch = '';
1106
+ // ---------------------------------------------------------------------------
1107
+ // Visual Editor state
1108
+ // ---------------------------------------------------------------------------
1109
+ VisualEditorOpen = false;
1110
+ EditorEntityMap = null;
1111
+ EditorCard = null;
1112
+ EditorSourceFields = [];
1113
+ EditorDestFields = [];
1114
+ EditorConnections = [];
1115
+ EditorLoading = false;
1116
+ EditorSaving = false;
1117
+ EditorSaveSuccess = false;
1118
+ /** Currently selected connection index (opens transform panel) */
1119
+ SelectedConnectionIdx = null;
1120
+ /** When non-null, user is in "connect mode" — next dest click creates a mapping */
1121
+ ConnectingFromSource = null;
1122
+ /** Search/filter within the visual editor columns */
1123
+ EditorSearchSource = '';
1124
+ EditorSearchDest = '';
1125
+ /** Data preview state */
1126
+ ShowSourcePreview = false;
1127
+ ShowDestPreview = false;
1128
+ PreviewSourceLoading = false;
1129
+ PreviewDestLoading = false;
1130
+ PreviewSourceRows = [];
1131
+ PreviewDestRows = [];
1132
+ PreviewSourceColumns = [];
1133
+ PreviewDestColumns = [];
1134
+ /** Collapsible section state */
1135
+ FieldMapsExpanded = true;
1136
+ InfoPanelExpanded = false;
1137
+ /** Info panel data */
1138
+ InfoPanelLoading = false;
1139
+ InfoDestRecordCount = null;
1140
+ InfoLastSync = null;
1141
+ /** SVG layout constants */
1142
+ FIELD_HEIGHT = 40;
1143
+ SVG_WIDTH = 200;
1144
+ /** Transform type metadata */
1145
+ TRANSFORM_TYPES = [
1146
+ { Value: 'direct', Label: 'Direct', Icon: 'fa-solid fa-arrow-right' },
1147
+ { Value: 'regex', Label: 'Regex', Icon: 'fa-solid fa-code' },
1148
+ { Value: 'split', Label: 'Split', Icon: 'fa-solid fa-scissors' },
1149
+ { Value: 'combine', Label: 'Combine', Icon: 'fa-solid fa-object-group' },
1150
+ { Value: 'lookup', Label: 'Lookup', Icon: 'fa-solid fa-book' },
1151
+ { Value: 'format', Label: 'Format', Icon: 'fa-solid fa-font' },
1152
+ { Value: 'coerce', Label: 'Coerce', Icon: 'fa-solid fa-exchange-alt' },
1153
+ { Value: 'substring', Label: 'Substring', Icon: 'fa-solid fa-text-width' },
1154
+ { Value: 'custom', Label: 'Custom', Icon: 'fa-solid fa-wand-magic-sparkles' }
1155
+ ];
1156
+ // ---------------------------------------------------------------------------
1157
+ // Private
1158
+ // ---------------------------------------------------------------------------
1159
+ dataService = inject(IntegrationDataService);
1160
+ cdr = inject(ChangeDetectorRef);
1161
+ // ---------------------------------------------------------------------------
1162
+ // Lifecycle
1163
+ // ---------------------------------------------------------------------------
1164
+ async ngOnInit() {
1165
+ await this.LoadData();
1166
+ }
1167
+ ngOnDestroy() {
1168
+ // Clean up if needed
1169
+ }
1170
+ // ---------------------------------------------------------------------------
1171
+ // Resource overrides
1172
+ // ---------------------------------------------------------------------------
1173
+ async GetResourceDisplayName(_data) {
1174
+ return 'Pipelines';
1175
+ }
1176
+ async GetResourceIconClass(_data) {
1177
+ return 'fa-solid fa-diagram-project';
1178
+ }
1179
+ // ---------------------------------------------------------------------------
1180
+ // Data loading
1181
+ // ---------------------------------------------------------------------------
1182
+ async LoadData() {
1183
+ this.IsLoading = true;
1184
+ this.cdr.detectChanges();
1185
+ try {
1186
+ const provider = this.RunViewToUse;
1187
+ const [summaries, allEntityMaps] = await Promise.all([
1188
+ this.dataService.LoadIntegrationSummaries(provider),
1189
+ this.loadAllEntityMaps(provider)
1190
+ ]);
1191
+ this.BuildCards(summaries, allEntityMaps);
1192
+ }
1193
+ catch (err) {
1194
+ console.error('[PipelinesComponent] Failed to load data:', err);
1195
+ }
1196
+ finally {
1197
+ this.IsLoading = false;
1198
+ this.cdr.detectChanges();
1199
+ }
1200
+ }
1201
+ // ---------------------------------------------------------------------------
1202
+ // Card building
1203
+ // ---------------------------------------------------------------------------
1204
+ BuildCards(summaries, allEntityMaps) {
1205
+ this.PipelineCards = summaries.map(summary => {
1206
+ const maps = allEntityMaps.filter(m => UUIDsEqual(m.CompanyIntegrationID, summary.Integration.ID));
1207
+ const activeMaps = maps.filter(m => m.SyncEnabled);
1208
+ const uniqueEntities = new Set(maps.map(m => m.EntityID)).size;
1209
+ return {
1210
+ IntegrationID: summary.Integration.ID,
1211
+ IntegrationName: summary.Integration.Integration ?? summary.Integration.Name,
1212
+ Icon: this.resolveIcon(summary),
1213
+ StatusColor: this.statusToColor(summary.StatusColor),
1214
+ StatusLabel: this.statusToLabel(summary.StatusColor),
1215
+ EntityMapCount: maps.length,
1216
+ ActiveMapCount: activeMaps.length,
1217
+ UniqueEntityCount: uniqueEntities,
1218
+ LastSync: summary.RelativeTime,
1219
+ IsExpanded: false,
1220
+ EntityMaps: maps,
1221
+ FilteredMaps: maps,
1222
+ SearchTerm: ''
1223
+ };
1224
+ });
1225
+ }
1226
+ // ---------------------------------------------------------------------------
1227
+ // Card expand / collapse
1228
+ // ---------------------------------------------------------------------------
1229
+ ToggleCard(card) {
1230
+ card.IsExpanded = !card.IsExpanded;
1231
+ if (card.IsExpanded) {
1232
+ card.FilteredMaps = this.applyMapFilter(card);
1233
+ }
1234
+ }
1235
+ ExpandAll() {
1236
+ for (const card of this.PipelineCards) {
1237
+ card.IsExpanded = true;
1238
+ card.FilteredMaps = this.applyMapFilter(card);
1239
+ }
1240
+ }
1241
+ CollapseAll() {
1242
+ for (const card of this.PipelineCards) {
1243
+ card.IsExpanded = false;
1244
+ }
1245
+ }
1246
+ // ---------------------------------------------------------------------------
1247
+ // Search / filter
1248
+ // ---------------------------------------------------------------------------
1249
+ OnCardSearch(card, event) {
1250
+ const input = event.target;
1251
+ card.SearchTerm = input.value;
1252
+ card.FilteredMaps = this.applyMapFilter(card);
1253
+ this.cdr.detectChanges();
1254
+ }
1255
+ OnGlobalSearchChange(event) {
1256
+ const input = event.target;
1257
+ this.GlobalSearch = input.value;
1258
+ this.cdr.detectChanges();
1259
+ }
1260
+ get FilteredCards() {
1261
+ if (!this.GlobalSearch.trim())
1262
+ return this.PipelineCards;
1263
+ const term = this.GlobalSearch.toLowerCase();
1264
+ return this.PipelineCards.filter(card => card.IntegrationName.toLowerCase().includes(term) ||
1265
+ card.EntityMaps.some(m => (m.ExternalObjectLabel ?? m.ExternalObjectName).toLowerCase().includes(term) ||
1266
+ m.Entity.toLowerCase().includes(term)));
1267
+ }
1268
+ // ---------------------------------------------------------------------------
1269
+ // Entity map row click → Open Visual Editor
1270
+ // ---------------------------------------------------------------------------
1271
+ OnMapRowClick(card, entityMap) {
1272
+ this.OpenVisualEditor(card, entityMap);
1273
+ }
1274
+ // ---------------------------------------------------------------------------
1275
+ // SyncEnabled toggle
1276
+ // ---------------------------------------------------------------------------
1277
+ async OnToggleSyncEnabled(card, em, event) {
1278
+ const checkbox = event.target;
1279
+ const newValue = checkbox.checked;
1280
+ em.SyncEnabled = newValue;
1281
+ card.ActiveMapCount = card.EntityMaps.filter(m => m.SyncEnabled).length;
1282
+ this.cdr.detectChanges();
1283
+ try {
1284
+ await this.dataService.ToggleEntityMapEnabled(em.ID, newValue);
1285
+ }
1286
+ catch (err) {
1287
+ // Revert on failure
1288
+ em.SyncEnabled = !newValue;
1289
+ card.ActiveMapCount = card.EntityMaps.filter(m => m.SyncEnabled).length;
1290
+ checkbox.checked = !newValue;
1291
+ console.error('[PipelinesComponent] Failed to toggle SyncEnabled:', err);
1292
+ this.cdr.detectChanges();
1293
+ }
1294
+ }
1295
+ async OnToggleEditorSyncEnabled(event) {
1296
+ if (!this.EditorEntityMap || !this.EditorCard)
1297
+ return;
1298
+ const checkbox = event.target;
1299
+ const newValue = checkbox.checked;
1300
+ this.EditorEntityMap.SyncEnabled = newValue;
1301
+ this.EditorCard.ActiveMapCount = this.EditorCard.EntityMaps.filter(m => m.SyncEnabled).length;
1302
+ this.cdr.detectChanges();
1303
+ try {
1304
+ await this.dataService.ToggleEntityMapEnabled(this.EditorEntityMap.ID, newValue);
1305
+ }
1306
+ catch (err) {
1307
+ this.EditorEntityMap.SyncEnabled = !newValue;
1308
+ this.EditorCard.ActiveMapCount = this.EditorCard.EntityMaps.filter(m => m.SyncEnabled).length;
1309
+ checkbox.checked = !newValue;
1310
+ console.error('[PipelinesComponent] Failed to toggle SyncEnabled:', err);
1311
+ this.cdr.detectChanges();
1312
+ }
1313
+ }
1314
+ // ---------------------------------------------------------------------------
1315
+ // Data preview
1316
+ // ---------------------------------------------------------------------------
1317
+ async ToggleSourcePreview() {
1318
+ this.ShowSourcePreview = !this.ShowSourcePreview;
1319
+ if (this.ShowSourcePreview && this.PreviewSourceRows.length === 0) {
1320
+ await this.loadSourcePreview();
1321
+ }
1322
+ this.cdr.detectChanges();
1323
+ }
1324
+ async ToggleDestPreview() {
1325
+ this.ShowDestPreview = !this.ShowDestPreview;
1326
+ if (this.ShowDestPreview && this.PreviewDestRows.length === 0) {
1327
+ await this.loadDestPreview();
1328
+ }
1329
+ this.cdr.detectChanges();
1330
+ }
1331
+ async loadSourcePreview() {
1332
+ if (!this.EditorEntityMap || !this.EditorCard)
1333
+ return;
1334
+ this.PreviewSourceLoading = true;
1335
+ this.cdr.detectChanges();
1336
+ try {
1337
+ const rows = await this.dataService.PreviewSourceData(this.EditorCard.IntegrationID, this.EditorEntityMap.ExternalObjectName, 5);
1338
+ this.PreviewSourceRows = rows;
1339
+ this.PreviewSourceColumns = rows.length > 0 ? Object.keys(rows[0]) : [];
1340
+ }
1341
+ catch (err) {
1342
+ console.error('[PipelinesComponent] Failed to load source preview:', err);
1343
+ this.PreviewSourceRows = [];
1344
+ this.PreviewSourceColumns = [];
1345
+ }
1346
+ finally {
1347
+ this.PreviewSourceLoading = false;
1348
+ this.cdr.detectChanges();
1349
+ }
1350
+ }
1351
+ async loadDestPreview() {
1352
+ if (!this.EditorEntityMap)
1353
+ return;
1354
+ this.PreviewDestLoading = true;
1355
+ this.cdr.detectChanges();
1356
+ try {
1357
+ const rows = await this.dataService.PreviewDestinationData(this.EditorEntityMap.EntityID, 5, this.RunViewToUse);
1358
+ this.PreviewDestRows = rows;
1359
+ this.PreviewDestColumns = rows.length > 0 ? Object.keys(rows[0]) : [];
1360
+ }
1361
+ catch (err) {
1362
+ console.error('[PipelinesComponent] Failed to load dest preview:', err);
1363
+ this.PreviewDestRows = [];
1364
+ this.PreviewDestColumns = [];
1365
+ }
1366
+ finally {
1367
+ this.PreviewDestLoading = false;
1368
+ this.cdr.detectChanges();
1369
+ }
1370
+ }
1371
+ // ---------------------------------------------------------------------------
1372
+ // Collapsible sections
1373
+ // ---------------------------------------------------------------------------
1374
+ ToggleFieldMaps() {
1375
+ this.FieldMapsExpanded = !this.FieldMapsExpanded;
1376
+ this.cdr.detectChanges();
1377
+ }
1378
+ ToggleInfoPanel() {
1379
+ this.InfoPanelExpanded = !this.InfoPanelExpanded;
1380
+ if (this.InfoPanelExpanded && this.InfoDestRecordCount === null) {
1381
+ this.loadInfoPanelData();
1382
+ }
1383
+ this.cdr.detectChanges();
1384
+ }
1385
+ async loadInfoPanelData() {
1386
+ if (!this.EditorEntityMap || !this.EditorCard)
1387
+ return;
1388
+ this.InfoPanelLoading = true;
1389
+ this.cdr.detectChanges();
1390
+ try {
1391
+ const [destCount, lastSync] = await Promise.all([
1392
+ this.dataService.GetDestinationRecordCount(this.EditorEntityMap.EntityID, this.RunViewToUse),
1393
+ this.dataService.GetLastSyncForEntity(this.EditorCard.IntegrationID, this.EditorEntityMap.EntityID, this.RunViewToUse)
1394
+ ]);
1395
+ this.InfoDestRecordCount = destCount;
1396
+ this.InfoLastSync = lastSync;
1397
+ }
1398
+ catch (err) {
1399
+ console.error('[PipelinesComponent] Failed to load info panel data:', err);
1400
+ }
1401
+ finally {
1402
+ this.InfoPanelLoading = false;
1403
+ this.cdr.detectChanges();
1404
+ }
1405
+ }
1406
+ FormatSyncDate(dateStr) {
1407
+ if (!dateStr)
1408
+ return 'Never';
1409
+ const d = new Date(dateStr);
1410
+ const now = new Date();
1411
+ const diffMs = now.getTime() - d.getTime();
1412
+ const diffMins = Math.floor(diffMs / 60000);
1413
+ if (diffMins < 1)
1414
+ return 'Just now';
1415
+ if (diffMins < 60)
1416
+ return `${diffMins}m ago`;
1417
+ const diffHours = Math.floor(diffMins / 60);
1418
+ if (diffHours < 24)
1419
+ return `${diffHours}h ago`;
1420
+ const diffDays = Math.floor(diffHours / 24);
1421
+ if (diffDays < 7)
1422
+ return `${diffDays}d ago`;
1423
+ return d.toLocaleDateString();
1424
+ }
1425
+ SyncStatusClass(status) {
1426
+ switch (status) {
1427
+ case 'Success': return 'info-status-success';
1428
+ case 'Failed': return 'info-status-error';
1429
+ case 'In Progress': return 'info-status-running';
1430
+ default: return 'info-status-pending';
1431
+ }
1432
+ }
1433
+ // ---------------------------------------------------------------------------
1434
+ // Template helpers
1435
+ // ---------------------------------------------------------------------------
1436
+ /**
1437
+ * Direction arrows for entity-level sync direction.
1438
+ * Pull = data flows FROM external source INTO MJ = right arrow (→)
1439
+ * Push = data flows FROM MJ OUT to external = left arrow (←)
1440
+ */
1441
+ DirectionLabel(direction) {
1442
+ if (direction === 'Pull')
1443
+ return '\u2192';
1444
+ if (direction === 'Push')
1445
+ return '\u2190';
1446
+ if (direction === 'Bidirectional')
1447
+ return '\u2194';
1448
+ return '\u2192';
1449
+ }
1450
+ DirectionBadgeClass(direction) {
1451
+ if (direction === 'Pull')
1452
+ return 'direction-badge pull';
1453
+ if (direction === 'Push')
1454
+ return 'direction-badge push';
1455
+ if (direction === 'Bidirectional')
1456
+ return 'direction-badge bidirectional';
1457
+ return 'direction-badge';
1458
+ }
1459
+ DirectionText(direction) {
1460
+ if (direction === 'Pull')
1461
+ return 'Pull \u2192';
1462
+ if (direction === 'Push')
1463
+ return '\u2190 Push';
1464
+ if (direction === 'Bidirectional')
1465
+ return '\u2194 Bi';
1466
+ return 'Pull \u2192';
1467
+ }
1468
+ get IntegrationCount() {
1469
+ return this.PipelineCards.length;
1470
+ }
1471
+ get TotalMapCount() {
1472
+ return this.PipelineCards.reduce((sum, c) => sum + c.EntityMapCount, 0);
1473
+ }
1474
+ // ===========================================================================
1475
+ // VISUAL FIELD MAPPING EDITOR
1476
+ // ===========================================================================
1477
+ // ---------------------------------------------------------------------------
1478
+ // Open / Close
1479
+ // ---------------------------------------------------------------------------
1480
+ OpenVisualEditor(card, entityMap) {
1481
+ this.EditorCard = card;
1482
+ this.EditorEntityMap = entityMap;
1483
+ this.VisualEditorOpen = true;
1484
+ this.SelectedConnectionIdx = null;
1485
+ this.ConnectingFromSource = null;
1486
+ this.EditorSearchSource = '';
1487
+ this.EditorSearchDest = '';
1488
+ this.EditorSaveSuccess = false;
1489
+ this.ShowSourcePreview = false;
1490
+ this.ShowDestPreview = false;
1491
+ this.PreviewSourceRows = [];
1492
+ this.PreviewDestRows = [];
1493
+ this.PreviewSourceColumns = [];
1494
+ this.PreviewDestColumns = [];
1495
+ this.FieldMapsExpanded = true;
1496
+ this.InfoPanelExpanded = false;
1497
+ this.InfoDestRecordCount = null;
1498
+ this.InfoLastSync = null;
1499
+ this.cdr.detectChanges();
1500
+ this.LoadVisualEditorData();
1501
+ }
1502
+ CloseVisualEditor() {
1503
+ this.VisualEditorOpen = false;
1504
+ this.EditorEntityMap = null;
1505
+ this.EditorCard = null;
1506
+ this.EditorSourceFields = [];
1507
+ this.EditorDestFields = [];
1508
+ this.EditorConnections = [];
1509
+ this.SelectedConnectionIdx = null;
1510
+ this.ConnectingFromSource = null;
1511
+ this.cdr.detectChanges();
1512
+ }
1513
+ async LoadVisualEditorData() {
1514
+ if (!this.EditorEntityMap || !this.EditorCard)
1515
+ return;
1516
+ this.EditorLoading = true;
1517
+ this.cdr.detectChanges();
1518
+ const entityMap = this.EditorEntityMap;
1519
+ try {
1520
+ // Load field maps and dest fields in parallel
1521
+ const [fieldMaps, destFields] = await Promise.all([
1522
+ this.dataService.LoadFieldMaps(entityMap.ID, this.RunViewToUse),
1523
+ this.dataService.LoadEntityFields(entityMap.EntityID, this.RunViewToUse)
1524
+ ]);
1525
+ // Build source fields from IntegrationObjectField metadata
1526
+ const sourceFields = this.resolveSourceFieldsFromMetadata(this.EditorCard.IntegrationID, entityMap.ExternalObjectName);
1527
+ if (sourceFields.length > 0) {
1528
+ this.EditorSourceFields = sourceFields;
1529
+ }
1530
+ else {
1531
+ // Fallback: derive source fields from existing field maps
1532
+ this.EditorSourceFields = fieldMaps.map(fm => ({
1533
+ Name: fm.SourceFieldName,
1534
+ Label: fm.SourceFieldLabel ?? fm.SourceFieldName,
1535
+ Type: '',
1536
+ IsRequired: fm.IsRequired,
1537
+ IsPrimaryKey: fm.IsKeyField
1538
+ }));
1539
+ }
1540
+ // Build dest fields (exclude __mj system fields — they are read-only)
1541
+ this.EditorDestFields = destFields
1542
+ .filter(f => !f.Name.startsWith('__mj'))
1543
+ .map(f => ({
1544
+ Name: f.Name,
1545
+ Type: f.Type,
1546
+ IsRequired: f.IsRequired
1547
+ }));
1548
+ // Build connections
1549
+ this.EditorConnections = fieldMaps
1550
+ .filter(fm => fm.Status === 'Active')
1551
+ .map(fm => ({
1552
+ ID: fm.ID,
1553
+ SourceFieldName: fm.SourceFieldName,
1554
+ DestFieldName: fm.DestinationFieldName,
1555
+ IsKeyField: fm.IsKeyField,
1556
+ IsRequired: fm.IsRequired,
1557
+ Direction: fm.Direction,
1558
+ TransformSteps: this.parseTransformPipeline(fm.TransformPipeline),
1559
+ IsDirty: false,
1560
+ IsNew: false,
1561
+ MarkedForDelete: false
1562
+ }));
1563
+ }
1564
+ catch (err) {
1565
+ console.error('[PipelinesComponent] Failed to load editor data:', err);
1566
+ }
1567
+ finally {
1568
+ this.EditorLoading = false;
1569
+ this.cdr.detectChanges();
1570
+ }
1571
+ }
1572
+ // ---------------------------------------------------------------------------
1573
+ // Filtered field lists
1574
+ // ---------------------------------------------------------------------------
1575
+ get FilteredEditorSourceFields() {
1576
+ if (!this.EditorSearchSource.trim())
1577
+ return this.EditorSourceFields;
1578
+ const term = this.EditorSearchSource.toLowerCase();
1579
+ return this.EditorSourceFields.filter(f => f.Name.toLowerCase().includes(term) || f.Label.toLowerCase().includes(term));
1580
+ }
1581
+ get FilteredEditorDestFields() {
1582
+ if (!this.EditorSearchDest.trim())
1583
+ return this.EditorDestFields;
1584
+ const term = this.EditorSearchDest.toLowerCase();
1585
+ return this.EditorDestFields.filter(f => f.Name.toLowerCase().includes(term));
1586
+ }
1587
+ /** Only show connections where both source and dest are visible */
1588
+ get VisibleConnections() {
1589
+ return this.EditorConnections.filter(c => !c.MarkedForDelete &&
1590
+ this.getSourceFieldIndex(c.SourceFieldName) >= 0 &&
1591
+ this.getDestFieldIndex(c.DestFieldName) >= 0);
1592
+ }
1593
+ // ---------------------------------------------------------------------------
1594
+ // SVG Calculations
1595
+ // ---------------------------------------------------------------------------
1596
+ get EditorCanvasHeight() {
1597
+ const sourceHeight = this.FilteredEditorSourceFields.length * this.FIELD_HEIGHT;
1598
+ const destHeight = this.FilteredEditorDestFields.length * this.FIELD_HEIGHT;
1599
+ return Math.max(sourceHeight, destHeight, 200);
1600
+ }
1601
+ GetConnectionPath(conn) {
1602
+ const sourceY = this.getSourceFieldY(conn.SourceFieldName);
1603
+ const destY = this.getDestFieldY(conn.DestFieldName);
1604
+ if (sourceY < 0 || destY < 0)
1605
+ return '';
1606
+ const cp1x = this.SVG_WIDTH * 0.35;
1607
+ const cp2x = this.SVG_WIDTH * 0.65;
1608
+ return `M 0 ${sourceY} C ${cp1x} ${sourceY}, ${cp2x} ${destY}, ${this.SVG_WIDTH} ${destY}`;
1609
+ }
1610
+ GetConnectionMidY(conn) {
1611
+ const sourceY = this.getSourceFieldY(conn.SourceFieldName);
1612
+ const destY = this.getDestFieldY(conn.DestFieldName);
1613
+ return (sourceY + destY) / 2;
1614
+ }
1615
+ GetConnectionLineClass(conn) {
1616
+ const type = this.getPrimaryTransformType(conn);
1617
+ return `conn-${type}`;
1618
+ }
1619
+ GetConnectionBadgeClass(conn) {
1620
+ const type = this.getPrimaryTransformType(conn);
1621
+ return `badge-${type}`;
1622
+ }
1623
+ GetConnectionTransformIcon(conn) {
1624
+ const type = this.getPrimaryTransformType(conn);
1625
+ return this.TRANSFORM_TYPES.find(t => t.Value === type)?.Icon ?? 'fa-solid fa-arrow-right';
1626
+ }
1627
+ /** Direction-aware icon for the SVG connection badge */
1628
+ GetConnectionDirectionIcon(conn) {
1629
+ switch (conn.Direction) {
1630
+ case 'DestToSource': return 'fa-solid fa-arrow-left';
1631
+ case 'Both': return 'fa-solid fa-right-left';
1632
+ default: return 'fa-solid fa-arrow-right';
1633
+ }
1634
+ }
1635
+ GetTransformTypeLabel(type) {
1636
+ return this.TRANSFORM_TYPES.find(t => t.Value === type)?.Label ?? type;
1637
+ }
1638
+ // ---------------------------------------------------------------------------
1639
+ // Field mapped state
1640
+ // ---------------------------------------------------------------------------
1641
+ IsSourceFieldMapped(fieldName) {
1642
+ return this.EditorConnections.some(c => !c.MarkedForDelete && c.SourceFieldName === fieldName);
1643
+ }
1644
+ IsDestFieldMapped(fieldName) {
1645
+ return this.EditorConnections.some(c => !c.MarkedForDelete && c.DestFieldName === fieldName);
1646
+ }
1647
+ // ---------------------------------------------------------------------------
1648
+ // Creating connections (click source → click dest)
1649
+ // ---------------------------------------------------------------------------
1650
+ OnEditorSourceClick(fieldName) {
1651
+ // Don't allow starting a new connection from an already-mapped field
1652
+ if (this.IsSourceFieldMapped(fieldName))
1653
+ return;
1654
+ if (this.ConnectingFromSource === fieldName) {
1655
+ this.ConnectingFromSource = null;
1656
+ }
1657
+ else {
1658
+ this.ConnectingFromSource = fieldName;
1659
+ this.SelectedConnectionIdx = null;
1660
+ }
1661
+ this.cdr.detectChanges();
1662
+ }
1663
+ OnEditorDestClick(fieldName) {
1664
+ if (!this.ConnectingFromSource)
1665
+ return;
1666
+ // Don't allow mapping to an already-mapped dest field
1667
+ if (this.IsDestFieldMapped(fieldName))
1668
+ return;
1669
+ // Check if this mapping already exists
1670
+ const existing = this.EditorConnections.find(c => !c.MarkedForDelete && c.SourceFieldName === this.ConnectingFromSource && c.DestFieldName === fieldName);
1671
+ if (existing) {
1672
+ this.ConnectingFromSource = null;
1673
+ return;
1674
+ }
1675
+ // Create new connection
1676
+ this.EditorConnections.push({
1677
+ ID: null,
1678
+ SourceFieldName: this.ConnectingFromSource,
1679
+ DestFieldName: fieldName,
1680
+ IsKeyField: false,
1681
+ IsRequired: false,
1682
+ Direction: 'SourceToDest',
1683
+ TransformSteps: [{ Type: 'direct', Config: {}, OnError: 'Fail' }],
1684
+ IsDirty: true,
1685
+ IsNew: true,
1686
+ MarkedForDelete: false
1687
+ });
1688
+ this.ConnectingFromSource = null;
1689
+ this.SelectedConnectionIdx = this.EditorConnections.length - 1;
1690
+ this.cdr.detectChanges();
1691
+ }
1692
+ CancelConnect() {
1693
+ this.ConnectingFromSource = null;
1694
+ this.cdr.detectChanges();
1695
+ }
1696
+ // ---------------------------------------------------------------------------
1697
+ // Connection selection / editing
1698
+ // ---------------------------------------------------------------------------
1699
+ SelectConnection(index, event) {
1700
+ event.stopPropagation();
1701
+ this.SelectedConnectionIdx = this.SelectedConnectionIdx === index ? null : index;
1702
+ this.ConnectingFromSource = null;
1703
+ this.cdr.detectChanges();
1704
+ }
1705
+ DeselectConnection() {
1706
+ this.SelectedConnectionIdx = null;
1707
+ this.cdr.detectChanges();
1708
+ }
1709
+ get SelectedConnection() {
1710
+ if (this.SelectedConnectionIdx == null)
1711
+ return null;
1712
+ return this.EditorConnections[this.SelectedConnectionIdx] ?? null;
1713
+ }
1714
+ RemoveSelectedConnection() {
1715
+ if (this.SelectedConnectionIdx == null)
1716
+ return;
1717
+ const conn = this.EditorConnections[this.SelectedConnectionIdx];
1718
+ if (conn.IsNew) {
1719
+ this.EditorConnections.splice(this.SelectedConnectionIdx, 1);
1720
+ }
1721
+ else {
1722
+ conn.MarkedForDelete = true;
1723
+ conn.IsDirty = true;
1724
+ }
1725
+ this.SelectedConnectionIdx = null;
1726
+ this.cdr.detectChanges();
1727
+ }
1728
+ ToggleConnectionKey() {
1729
+ const conn = this.SelectedConnection;
1730
+ if (!conn)
1731
+ return;
1732
+ conn.IsKeyField = !conn.IsKeyField;
1733
+ conn.IsDirty = true;
1734
+ this.cdr.detectChanges();
1735
+ }
1736
+ ToggleConnectionRequired() {
1737
+ const conn = this.SelectedConnection;
1738
+ if (!conn)
1739
+ return;
1740
+ conn.IsRequired = !conn.IsRequired;
1741
+ conn.IsDirty = true;
1742
+ this.cdr.detectChanges();
1743
+ }
1744
+ GetDirectionArrowClass(direction) {
1745
+ switch (direction) {
1746
+ case 'DestToSource': return 'fa-arrow-left';
1747
+ case 'Both': return 'fa-right-left';
1748
+ default: return 'fa-arrow-right';
1749
+ }
1750
+ }
1751
+ OnConnectionDirectionChange(direction) {
1752
+ const conn = this.SelectedConnection;
1753
+ if (!conn)
1754
+ return;
1755
+ conn.Direction = direction;
1756
+ conn.IsDirty = true;
1757
+ this.cdr.detectChanges();
1758
+ }
1759
+ OnConnectionTransformChange(stepIndex, type) {
1760
+ const conn = this.SelectedConnection;
1761
+ if (!conn || !conn.TransformSteps[stepIndex])
1762
+ return;
1763
+ conn.TransformSteps[stepIndex].Type = type;
1764
+ conn.TransformSteps[stepIndex].Config = this.getDefaultConfigForType(type);
1765
+ conn.IsDirty = true;
1766
+ this.cdr.detectChanges();
1767
+ }
1768
+ OnTransformConfigChange(conn, stepIndex, key, value) {
1769
+ if (!conn.TransformSteps[stepIndex])
1770
+ return;
1771
+ conn.TransformSteps[stepIndex].Config[key] = value;
1772
+ conn.IsDirty = true;
1773
+ }
1774
+ AddTransformStep() {
1775
+ const conn = this.SelectedConnection;
1776
+ if (!conn)
1777
+ return;
1778
+ conn.TransformSteps.push({ Type: 'direct', Config: {}, OnError: 'Fail' });
1779
+ conn.IsDirty = true;
1780
+ this.cdr.detectChanges();
1781
+ }
1782
+ RemoveTransformStep(stepIndex) {
1783
+ const conn = this.SelectedConnection;
1784
+ if (!conn)
1785
+ return;
1786
+ conn.TransformSteps.splice(stepIndex, 1);
1787
+ conn.IsDirty = true;
1788
+ this.cdr.detectChanges();
1789
+ }
1790
+ // ---------------------------------------------------------------------------
1791
+ // Save / Auto-map
1792
+ // ---------------------------------------------------------------------------
1793
+ get HasEditorChanges() {
1794
+ return this.EditorConnections.some(c => c.IsDirty);
1795
+ }
1796
+ async SaveVisualEditor() {
1797
+ if (!this.EditorEntityMap)
1798
+ return;
1799
+ this.EditorSaving = true;
1800
+ this.EditorSaveSuccess = false;
1801
+ this.cdr.detectChanges();
1802
+ try {
1803
+ for (const conn of this.EditorConnections) {
1804
+ if (!conn.IsDirty)
1805
+ continue;
1806
+ if (conn.MarkedForDelete && conn.ID) {
1807
+ await this.dataService.DeleteFieldMap(conn.ID);
1808
+ }
1809
+ else if (conn.IsNew && !conn.MarkedForDelete) {
1810
+ await this.dataService.CreateFieldMap({
1811
+ EntityMapID: this.EditorEntityMap.ID,
1812
+ SourceFieldName: conn.SourceFieldName,
1813
+ DestinationFieldName: conn.DestFieldName,
1814
+ IsKeyField: conn.IsKeyField,
1815
+ IsRequired: conn.IsRequired,
1816
+ Direction: conn.Direction,
1817
+ TransformPipeline: this.serializeTransformPipeline(conn.TransformSteps)
1818
+ });
1819
+ }
1820
+ else if (conn.ID && !conn.MarkedForDelete) {
1821
+ await this.dataService.UpdateFieldMap(conn.ID, {
1822
+ SourceFieldName: conn.SourceFieldName,
1823
+ DestinationFieldName: conn.DestFieldName,
1824
+ IsKeyField: conn.IsKeyField,
1825
+ IsRequired: conn.IsRequired,
1826
+ Direction: conn.Direction,
1827
+ TransformPipeline: this.serializeTransformPipeline(conn.TransformSteps)
1828
+ });
1829
+ }
1830
+ }
1831
+ // Reload to get clean state
1832
+ await this.LoadVisualEditorData();
1833
+ this.EditorSaveSuccess = true;
1834
+ this.SelectedConnectionIdx = null;
1835
+ }
1836
+ catch (err) {
1837
+ console.error('[PipelinesComponent] Failed to save field mappings:', err);
1838
+ }
1839
+ finally {
1840
+ this.EditorSaving = false;
1841
+ this.cdr.detectChanges();
1842
+ }
1843
+ }
1844
+ async AutoMapEditorFields() {
1845
+ if (!this.EditorEntityMap || !this.EditorCard)
1846
+ return;
1847
+ // Match source to dest by name (case-insensitive)
1848
+ const destMap = new Map();
1849
+ for (const df of this.EditorDestFields) {
1850
+ destMap.set(df.Name.toLowerCase(), df);
1851
+ }
1852
+ let addedCount = 0;
1853
+ for (const sf of this.EditorSourceFields) {
1854
+ // Skip if already mapped
1855
+ if (this.IsSourceFieldMapped(sf.Name))
1856
+ continue;
1857
+ const destMatch = destMap.get(sf.Name.toLowerCase());
1858
+ if (!destMatch)
1859
+ continue;
1860
+ if (this.IsDestFieldMapped(destMatch.Name))
1861
+ continue;
1862
+ this.EditorConnections.push({
1863
+ ID: null,
1864
+ SourceFieldName: sf.Name,
1865
+ DestFieldName: destMatch.Name,
1866
+ IsKeyField: sf.IsPrimaryKey,
1867
+ IsRequired: sf.IsRequired || destMatch.IsRequired,
1868
+ Direction: 'SourceToDest',
1869
+ TransformSteps: [{ Type: 'direct', Config: {}, OnError: 'Fail' }],
1870
+ IsDirty: true,
1871
+ IsNew: true,
1872
+ MarkedForDelete: false
1873
+ });
1874
+ addedCount++;
1875
+ }
1876
+ if (addedCount > 0) {
1877
+ this.cdr.detectChanges();
1878
+ }
1879
+ }
1880
+ // ---------------------------------------------------------------------------
1881
+ // Editor computed props
1882
+ // ---------------------------------------------------------------------------
1883
+ get EditorMappedCount() {
1884
+ return this.EditorConnections.filter(c => !c.MarkedForDelete).length;
1885
+ }
1886
+ get EditorKeyFieldCount() {
1887
+ return this.EditorConnections.filter(c => !c.MarkedForDelete && c.IsKeyField).length;
1888
+ }
1889
+ get EditorRequiredCount() {
1890
+ return this.EditorConnections.filter(c => !c.MarkedForDelete && c.IsRequired).length;
1891
+ }
1892
+ /** Get transform config keys for inline editing */
1893
+ GetConfigKeys(step) {
1894
+ return Object.keys(step.Config);
1895
+ }
1896
+ GetConfigValue(step, key) {
1897
+ const val = step.Config[key];
1898
+ if (val == null)
1899
+ return '';
1900
+ if (typeof val === 'object')
1901
+ return JSON.stringify(val);
1902
+ return String(val);
1903
+ }
1904
+ // ---------------------------------------------------------------------------
1905
+ // Private helpers
1906
+ // ---------------------------------------------------------------------------
1907
+ getSourceFieldIndex(fieldName) {
1908
+ return this.FilteredEditorSourceFields.findIndex(f => f.Name === fieldName);
1909
+ }
1910
+ getDestFieldIndex(fieldName) {
1911
+ return this.FilteredEditorDestFields.findIndex(f => f.Name === fieldName);
1912
+ }
1913
+ getSourceFieldY(fieldName) {
1914
+ const idx = this.getSourceFieldIndex(fieldName);
1915
+ if (idx < 0)
1916
+ return -1;
1917
+ return idx * this.FIELD_HEIGHT + this.FIELD_HEIGHT / 2;
1918
+ }
1919
+ getDestFieldY(fieldName) {
1920
+ const idx = this.getDestFieldIndex(fieldName);
1921
+ if (idx < 0)
1922
+ return -1;
1923
+ return idx * this.FIELD_HEIGHT + this.FIELD_HEIGHT / 2;
1924
+ }
1925
+ getPrimaryTransformType(conn) {
1926
+ if (conn.TransformSteps.length === 0)
1927
+ return 'direct';
1928
+ return conn.TransformSteps[0].Type;
1929
+ }
1930
+ parseTransformPipeline(json) {
1931
+ if (!json || json.trim() === '')
1932
+ return [];
1933
+ try {
1934
+ const parsed = JSON.parse(json);
1935
+ if (!Array.isArray(parsed))
1936
+ return [];
1937
+ return parsed.map(step => ({
1938
+ Type: step.Type ?? 'direct',
1939
+ Config: step.Config ?? {},
1940
+ OnError: step.OnError ?? 'Fail'
1941
+ }));
1942
+ }
1943
+ catch {
1944
+ return [];
1945
+ }
1946
+ }
1947
+ serializeTransformPipeline(steps) {
1948
+ if (steps.length === 0)
1949
+ return null;
1950
+ return JSON.stringify(steps.map(s => ({ Type: s.Type, Config: s.Config, OnError: s.OnError })));
1951
+ }
1952
+ getDefaultConfigForType(type) {
1953
+ switch (type) {
1954
+ case 'direct': return {};
1955
+ case 'regex': return { Pattern: '', Replacement: '', Flags: 'g' };
1956
+ case 'split': return { Delimiter: ',', Index: 0 };
1957
+ case 'combine': return { SourceFields: [], Separator: ' ' };
1958
+ case 'lookup': return { Map: {}, Default: '' };
1959
+ case 'format': return { FormatString: '', FormatType: 'date' };
1960
+ case 'coerce': return { TargetType: 'string' };
1961
+ case 'substring': return { Start: 0, Length: 10 };
1962
+ case 'custom': return { Expression: 'value' };
1963
+ }
1964
+ }
1965
+ /**
1966
+ * Resolve source fields from IntegrationObjectField metadata via IntegrationEngineBase.
1967
+ * CompanyIntegrationID → Integration → IntegrationObject → IntegrationObjectFields.
1968
+ */
1969
+ resolveSourceFieldsFromMetadata(companyIntegrationID, externalObjectName) {
1970
+ const engine = IntegrationEngineBase.Instance;
1971
+ const integration = engine.GetIntegrationForCompanyIntegration(companyIntegrationID);
1972
+ if (!integration)
1973
+ return [];
1974
+ const obj = engine.GetIntegrationObject(integration.ID, externalObjectName);
1975
+ if (!obj)
1976
+ return [];
1977
+ const fields = engine.GetIntegrationObjectFields(obj.ID);
1978
+ return fields
1979
+ .filter(f => f.Status === 'Active')
1980
+ .sort((a, b) => a.Sequence - b.Sequence)
1981
+ .map(f => ({
1982
+ Name: f.Name,
1983
+ Label: f.DisplayName || f.Name,
1984
+ Type: f.Type,
1985
+ IsRequired: f.IsRequired,
1986
+ IsPrimaryKey: f.IsPrimaryKey
1987
+ }));
1988
+ }
1989
+ applyMapFilter(card) {
1990
+ if (!card.SearchTerm.trim())
1991
+ return card.EntityMaps;
1992
+ const term = card.SearchTerm.toLowerCase();
1993
+ return card.EntityMaps.filter(m => (m.ExternalObjectLabel ?? m.ExternalObjectName).toLowerCase().includes(term) ||
1994
+ m.Entity.toLowerCase().includes(term));
1995
+ }
1996
+ async loadAllEntityMaps(provider) {
1997
+ const rv = new RunView(provider ?? null);
1998
+ const result = await rv.RunView({
1999
+ EntityName: 'MJ: Company Integration Entity Maps',
2000
+ ExtraFilter: '',
2001
+ OrderBy: 'CompanyIntegrationID, Priority, ExternalObjectName',
2002
+ Fields: ['ID', 'CompanyIntegrationID', 'ExternalObjectName', 'ExternalObjectLabel',
2003
+ 'EntityID', 'SyncDirection', 'SyncEnabled', 'MatchStrategy',
2004
+ 'ConflictResolution', 'Priority', 'DeleteBehavior', 'Status', 'Entity'],
2005
+ ResultType: 'simple'
2006
+ });
2007
+ return result.Results;
2008
+ }
2009
+ resolveIcon(summary) {
2010
+ if (summary.SourceType?.IconClass) {
2011
+ return summary.SourceType.IconClass;
2012
+ }
2013
+ const name = summary.Integration.Integration ?? summary.Integration.Name;
2014
+ return ResolveIntegrationIcon(name);
2015
+ }
2016
+ statusToColor(color) {
2017
+ if (color === 'green')
2018
+ return '#059669';
2019
+ if (color === 'amber')
2020
+ return '#d97706';
2021
+ if (color === 'red')
2022
+ return '#dc2626';
2023
+ return '#9ca3af';
2024
+ }
2025
+ statusToLabel(color) {
2026
+ if (color === 'green')
2027
+ return 'Healthy';
2028
+ if (color === 'amber')
2029
+ return 'Warning';
2030
+ if (color === 'red')
2031
+ return 'Error';
2032
+ return 'Inactive';
2033
+ }
2034
+ static ɵfac = /*@__PURE__*/ (() => { let ɵPipelinesComponent_BaseFactory; return function PipelinesComponent_Factory(__ngFactoryType__) { return (ɵPipelinesComponent_BaseFactory || (ɵPipelinesComponent_BaseFactory = i0.ɵɵgetInheritedFactory(PipelinesComponent)))(__ngFactoryType__ || PipelinesComponent); }; })();
2035
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PipelinesComponent, selectors: [["app-integration-pipelines"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 3, vars: 1, consts: [[1, "pipelines-container"], [1, "ve-container"], [1, "pipelines-toolbar"], [1, "toolbar-left"], [1, "toolbar-title"], [1, "fa-solid", "fa-diagram-project"], [1, "toolbar-count-badge"], [1, "toolbar-map-count"], [1, "toolbar-right"], [1, "global-search"], [1, "fa-solid", "fa-search", "search-icon"], ["type", "text", "placeholder", "Search integrations or entities...", 1, "search-input", 3, "input", "value"], ["title", "Expand All", 1, "toolbar-btn", 3, "click"], [1, "fa-solid", "fa-angles-down"], ["title", "Collapse All", 1, "toolbar-btn", 3, "click"], [1, "fa-solid", "fa-angles-up"], [1, "toolbar-divider"], ["title", "Refresh", 1, "toolbar-btn", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "pipelines-content"], [1, "content-loading"], [1, "content-empty"], [1, "cards-list"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-diagram-project", "empty-icon"], [1, "pipeline-card", 3, "expanded"], [1, "pipeline-card"], [1, "card-header", 3, "click"], [1, "card-header-left"], [1, "card-status-dot"], [1, "card-info"], [1, "card-name"], [1, "card-meta"], [1, "meta-sep"], [1, "card-header-right"], [1, "card-status-label"], [1, "card-last-sync"], [1, "mini-flow"], [1, "mini-flow-dot", "source"], [1, "mini-flow-line"], [1, "mini-flow-count"], [1, "mini-flow-dot", "dest"], [1, "fa-solid", "card-chevron"], [1, "card-body"], [1, "card-search-bar"], [1, "fa-solid", "fa-filter", "card-search-icon"], ["type", "text", "placeholder", "Filter entity maps...", 1, "card-search-input", 3, "input", "value"], [1, "card-search-count"], [1, "map-table-head"], [1, "map-col-toggle"], [1, "map-col-source"], [1, "map-col-direction"], [1, "map-col-dest"], [1, "map-col-meta"], [1, "map-table-body"], [1, "map-row", 3, "sync-disabled"], [1, "map-table-empty"], [1, "map-row", 3, "click"], [1, "map-col-toggle", 3, "click"], [1, "sync-toggle", 3, "title"], ["type", "checkbox", 3, "change", "checked"], [1, "sync-toggle-track"], [1, "map-col-source", 3, "title"], [1, "map-col-dest", 3, "title"], [1, "map-config-badge", 3, "title"], [1, "map-edit-hint"], [1, "fa-solid", "fa-chevron-right"], [1, "fa-solid", "fa-link"], [1, "ve-header"], [1, "ve-header-left"], ["title", "Back to Pipelines", 1, "ve-back-btn", 3, "click"], [1, "fa-solid", "fa-arrow-left"], [1, "ve-header-title"], [1, "ve-source-label"], [1, "ve-direction-arrow"], [1, "fa-solid", "fa-arrow-right-arrow-left"], [1, "ve-dest-label"], [1, "ve-header-stats"], [1, "ve-stat"], [1, "ve-stat-sep"], [1, "ve-header-actions"], ["title", "Preview source data", 1, "ve-btn", "ve-btn-ghost", 3, "click"], [1, "fa-solid", "fa-cloud"], ["title", "Preview MJ data", 1, "ve-btn", "ve-btn-ghost", 3, "click"], [1, "fa-solid", "fa-database"], [1, "ve-action-sep"], ["title", "Auto-map fields by name", 1, "ve-btn", "ve-btn-ghost", 3, "click"], [1, "fa-solid", "fa-wand-magic-sparkles"], [1, "ve-btn", "ve-btn-primary", 3, "click", "disabled"], [1, "ve-save-success"], [1, "ve-preview-strip"], [1, "ve-connect-banner"], [1, "ve-body"], [1, "ve-loading"], [1, "sync-toggle", "ve-sync-toggle", 3, "title"], [1, "ve-sync-label"], [1, "fa-solid", "fa-check"], [1, "fa-solid", "fa-circle-check"], [1, "ve-preview-panel"], [1, "ve-preview-header"], [1, "ve-preview-close", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "ve-preview-loading"], [1, "ve-preview-empty"], [1, "ve-preview-table-wrap"], [1, "ve-preview-table"], [3, "title"], [1, "ve-connect-cancel", 3, "click"], [1, "ve-sections-wrapper"], [1, "ve-section"], [1, "ve-section-header", 3, "click"], [1, "fa-solid"], [1, "ve-section-title"], [1, "ve-section-badge"], [1, "ve-section-body"], [1, "ve-section-body", "ve-info-body"], [1, "ve-transform-panel"], [1, "ve-canvas-wrapper"], [1, "ve-col-headers"], [1, "ve-col-header", "source"], [1, "ve-col-count"], [1, "ve-col-header-spacer"], [1, "ve-col-header", "dest"], [1, "ve-col-searches"], [1, "ve-col-search"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Filter source fields...", 3, "input", "value"], [1, "ve-col-search-spacer"], ["type", "text", "placeholder", "Filter destination fields...", 3, "input", "value"], [1, "ve-canvas-scroll", 3, "click"], [1, "ve-canvas-grid"], [1, "ve-field-col", "source"], [1, "ve-field-item", 3, "mapped", "unmapped", "connecting", "height"], [1, "ve-field-empty"], [1, "ve-svg", 3, "click"], [1, "ve-field-col", "dest"], [1, "ve-field-item", 3, "mapped", "unmapped", "connect-target", "height"], [1, "ve-field-item", 3, "click"], [1, "ve-field-name", 3, "title"], [1, "ve-field-type"], [1, "ve-field-badges"], ["title", "Primary Key", 1, "ve-fbadge", "pk"], ["title", "Required", 1, "ve-fbadge", "req"], [1, "ve-conn-line", 3, "click"], ["width", "28", "height", "28", 1, "ve-badge-fo"], ["xmlns", "http://www.w3.org/1999/xhtml", 1, "ve-conn-badge", 3, "click"], [1, "ve-info-loading"], [1, "ve-info-grid"], [1, "ve-info-card"], [1, "ve-info-card-icon"], [1, "ve-info-card-content"], [1, "ve-info-card-value"], [1, "ve-info-card-label"], [1, "ve-info-card-icon", "source"], [1, "ve-info-card-icon", "sync"], [1, "ve-info-details"], [1, "ve-info-detail-row"], [1, "ve-info-detail-label"], [1, "ve-info-detail-value"], [1, "ve-info-card-icon", 3, "ngClass"], [1, "ve-transform-panel", 3, "click"], [1, "ve-tp-header"], [1, "ve-tp-title"], [1, "ve-tp-close", 3, "click"], [1, "ve-tp-mapping-info"], [1, "ve-tp-field-pair"], [1, "ve-tp-field", "source"], [1, "fa-solid", "ve-tp-arrow"], [1, "ve-tp-field", "dest"], [1, "ve-tp-toggles"], [1, "ve-tp-toggle", 3, "click"], [1, "ve-tp-toggle-box"], [1, "ve-tp-section"], [1, "ve-tp-section-label"], [1, "ve-tp-direction-btns"], [3, "click"], [1, "ve-tp-section-header"], [1, "ve-tp-add-step", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "ve-tp-step"], [1, "ve-tp-no-steps"], [1, "ve-tp-footer"], [1, "ve-btn", "ve-btn-danger", 3, "click"], [1, "fa-solid", "fa-trash-can"], [1, "ve-tp-step-header"], [1, "ve-tp-step-num"], [1, "ve-tp-type-select", 3, "change", "value"], [3, "value", "selected"], ["title", "Remove step", 1, "ve-tp-remove-step", 3, "click"], [1, "ve-tp-step-config"], [1, "ve-tp-step-onerror"], [3, "change", "value"], ["value", "Fail"], ["value", "Skip"], ["value", "Null"], [1, "ve-tp-config-row"], ["type", "text", 3, "input", "value", "placeholder"]], template: function PipelinesComponent_Template(rf, ctx) { if (rf & 1) {
2036
+ i0.ɵɵelementStart(0, "div", 0);
2037
+ i0.ɵɵconditionalCreate(1, PipelinesComponent_Conditional_1_Template, 24, 6)(2, PipelinesComponent_Conditional_2_Template, 48, 18, "div", 1);
2038
+ i0.ɵɵelementEnd();
2039
+ } if (rf & 2) {
2040
+ i0.ɵɵadvance();
2041
+ i0.ɵɵconditional(!ctx.VisualEditorOpen ? 1 : 2);
2042
+ } }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption], styles: ["\n\n\n\n\n[_nghost-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n\n\n\n\n\n.pipelines-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-page);\n position: relative;\n overflow: hidden;\n}\n\n\n\n\n\n\n.pipelines-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 20px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n z-index: 10;\n}\n\n.toolbar-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.toolbar-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.toolbar-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-color-indigo-500); }\n\n.toolbar-count-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 6px;\n border-radius: 11px;\n background: var(--mj-color-indigo-500);\n color: var(--mj-bg-surface);\n font-size: 11px;\n font-weight: 600;\n}\n\n.toolbar-map-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n.toolbar-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.global-search[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.search-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 10px;\n font-size: 12px;\n color: var(--mj-text-disabled);\n pointer-events: none;\n}\n\n.search-input[_ngcontent-%COMP%] {\n width: 240px;\n height: 32px;\n padding: 0 12px 0 30px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-page);\n outline: none;\n transition: border-color 150ms ease, background 150ms ease;\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-color-indigo-500);\n background: var(--mj-bg-surface);\n}\n\n.search-input[_ngcontent-%COMP%]::placeholder { color: var(--mj-color-neutral-300); }\n\n.toolbar-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 150ms ease;\n font-size: 13px;\n}\n\n.toolbar-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-color-neutral-300);\n color: var(--mj-text-primary);\n}\n\n.toolbar-btn[_ngcontent-%COMP%]:active { background: var(--mj-bg-surface-active); }\n\n.toolbar-divider[_ngcontent-%COMP%] {\n width: 1px;\n height: 20px;\n background: var(--mj-border-default);\n margin: 0 4px;\n}\n\n\n\n\n\n\n.pipelines-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n position: relative;\n overflow: hidden;\n min-height: 0;\n}\n\n.content-loading[_ngcontent-%COMP%], \n.content-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 12px;\n color: var(--mj-text-disabled);\n}\n\n.content-loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 28px; color: var(--mj-color-indigo-500); }\n.content-loading[_ngcontent-%COMP%] span[_ngcontent-%COMP%] { font-size: 14px; }\n.content-empty[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] { font-size: 48px; color: var(--mj-color-neutral-300); }\n.content-empty[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] { margin: 0; font-size: 18px; font-weight: 600; color: var(--mj-text-muted); }\n.content-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] { margin: 0; font-size: 13px; color: var(--mj-text-disabled); }\n\n\n\n\n\n\n.cards-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 20px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 1200px;\n margin: 0 auto;\n width: 100%;\n box-sizing: border-box;\n min-height: 0;\n}\n\n\n\n\n\n\n.pipeline-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n overflow: hidden;\n transition: box-shadow 200ms ease, border-color 200ms ease;\n}\n\n.pipeline-card[_ngcontent-%COMP%]:hover { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); }\n\n.pipeline-card.expanded[_ngcontent-%COMP%] {\n border-color: var(--mj-color-indigo-100);\n box-shadow: 0 2px 12px rgba(99, 102, 241, 0.08);\n}\n\n\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n cursor: pointer;\n user-select: none;\n transition: background 150ms ease;\n}\n\n.card-header[_ngcontent-%COMP%]:hover { background: var(--mj-bg-page); }\n\n.card-header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n flex: 1;\n}\n\n.card-status-dot[_ngcontent-%COMP%] { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }\n\n.card-icon[_ngcontent-%COMP%] {\n font-size: 18px;\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n width: 24px;\n text-align: center;\n}\n\n.card-info[_ngcontent-%COMP%] { display: flex; flex-direction: column; gap: 2px; min-width: 0; }\n\n.card-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card-meta[_ngcontent-%COMP%] { font-size: 12px; color: var(--mj-text-disabled); }\n.meta-sep[_ngcontent-%COMP%] { color: var(--mj-color-neutral-300); margin: 0 2px; }\n\n.card-header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n flex-shrink: 0;\n}\n\n.card-status-label[_ngcontent-%COMP%] { font-size: 12px; font-weight: 600; }\n.card-last-sync[_ngcontent-%COMP%] { font-size: 11px; color: var(--mj-text-disabled); }\n\n\n\n.mini-flow[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 4px; }\n.mini-flow-dot[_ngcontent-%COMP%] { width: 8px; height: 8px; border-radius: 50%; }\n.mini-flow-dot.source[_ngcontent-%COMP%] { background: var(--mj-brand-primary); }\n.mini-flow-dot.dest[_ngcontent-%COMP%] { background: var(--mj-color-success-600); }\n.mini-flow-line[_ngcontent-%COMP%] { width: 16px; height: 2px; background: var(--mj-border-default); border-radius: 1px; }\n.mini-flow-count[_ngcontent-%COMP%] {\n font-size: 10px; font-weight: 700; color: var(--mj-color-indigo-500);\n background: var(--mj-color-indigo-50); padding: 1px 5px; border-radius: 4px;\n}\n\n.card-chevron[_ngcontent-%COMP%] { font-size: 12px; color: var(--mj-text-disabled); transition: transform 200ms ease; }\n\n\n\n\n\n\n.card-body[_ngcontent-%COMP%] {\n border-top: 1px solid var(--mj-border-subtle);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n \n\n\n max-height: 60vh;\n}\n\n\n\n.card-search-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 18px;\n border-bottom: 1px solid var(--mj-border-subtle);\n flex-shrink: 0;\n}\n\n.card-search-icon[_ngcontent-%COMP%] { font-size: 11px; color: var(--mj-text-disabled); flex-shrink: 0; }\n\n.card-search-input[_ngcontent-%COMP%] {\n flex: 1;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n font-size: 12px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-page);\n outline: none;\n transition: border-color 150ms ease;\n}\n\n.card-search-input[_ngcontent-%COMP%]:focus { border-color: var(--mj-color-indigo-500); background: var(--mj-bg-surface); }\n.card-search-input[_ngcontent-%COMP%]::placeholder { color: var(--mj-color-neutral-300); }\n.card-search-count[_ngcontent-%COMP%] { font-size: 11px; color: var(--mj-text-disabled); white-space: nowrap; flex-shrink: 0; }\n\n\n\n.map-table-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 6px 18px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n border-bottom: 1px solid var(--mj-border-subtle);\n background: var(--mj-bg-page);\n flex-shrink: 0;\n}\n\n\n\n.map-table-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n}\n\n.map-table-empty[_ngcontent-%COMP%] {\n padding: 24px 18px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n}\n\n\n\n\n\n.map-col-source[_ngcontent-%COMP%] { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.map-col-direction[_ngcontent-%COMP%] { width: 52px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }\n.map-col-dest[_ngcontent-%COMP%] { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.map-col-meta[_ngcontent-%COMP%] { width: 80px; flex-shrink: 0; display: flex; align-items: center; justify-content: flex-end; gap: 4px; }\n\n\n\n.map-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 8px 18px;\n font-size: 13px;\n color: var(--mj-color-neutral-700);\n cursor: pointer;\n transition: background 150ms ease;\n border-bottom: 1px solid var(--mj-bg-page);\n}\n\n.map-row[_ngcontent-%COMP%]:hover { background: var(--mj-color-indigo-50); }\n.map-row.sync-disabled[_ngcontent-%COMP%] { opacity: 0.55; }\n.map-row.sync-disabled[_ngcontent-%COMP%]:hover { opacity: 0.8; }\n\n\n\n\n.map-config-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 4px;\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-disabled);\n font-size: 10px;\n}\n\n.map-edit-hint[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 4px;\n color: var(--mj-color-neutral-300);\n font-size: 11px;\n transition: color 150ms ease;\n}\n\n.map-row[_ngcontent-%COMP%]:hover .map-edit-hint[_ngcontent-%COMP%] { color: var(--mj-color-indigo-500); }\n\n\n\n\n\n\n.map-col-toggle[_ngcontent-%COMP%] {\n width: 50px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sync-toggle[_ngcontent-%COMP%] {\n position: relative;\n display: inline-flex;\n align-items: center;\n cursor: pointer;\n}\n\n.sync-toggle[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n}\n\n.sync-toggle-track[_ngcontent-%COMP%] {\n width: 30px;\n height: 16px;\n border-radius: 8px;\n background: var(--mj-color-neutral-300);\n position: relative;\n transition: background 200ms ease;\n}\n\n.sync-toggle-track[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);\n transition: transform 200ms ease;\n}\n\n.sync-toggle[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:checked + .sync-toggle-track[_ngcontent-%COMP%] {\n background: var(--mj-color-success-600);\n}\n\n.sync-toggle[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:checked + .sync-toggle-track[_ngcontent-%COMP%]::after {\n transform: translateX(14px);\n}\n\n\n\n\n\n\n.direction-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 36px;\n height: 20px;\n padding: 0 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n flex-shrink: 0;\n}\n\n.direction-badge.pull[_ngcontent-%COMP%] { background: var(--mj-color-info-100); color: var(--mj-brand-primary); }\n.direction-badge.push[_ngcontent-%COMP%] { background: var(--mj-color-success-100); color: var(--mj-color-success-600); }\n.direction-badge.bidirectional[_ngcontent-%COMP%] { background: var(--mj-color-warning-100); color: var(--mj-color-warning-600); }\n\n\n\n\n\n\n.ve-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n background: var(--mj-bg-surface);\n animation: _ngcontent-%COMP%_slideIn 250ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes _ngcontent-%COMP%_slideIn {\n from { opacity: 0; transform: translateX(30px); }\n to { opacity: 1; transform: translateX(0); }\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n\n\n\n\n\n.ve-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 16px;\n}\n\n.ve-header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.ve-back-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 14px;\n flex-shrink: 0;\n transition: all 150ms ease;\n}\n\n.ve-back-btn[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n\n.ve-header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 15px;\n font-weight: 600;\n min-width: 0;\n}\n\n.ve-source-label[_ngcontent-%COMP%] {\n color: var(--mj-color-indigo-500);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 200px;\n}\n\n.ve-direction-arrow[_ngcontent-%COMP%] { color: var(--mj-text-disabled); font-size: 13px; flex-shrink: 0; }\n\n.ve-dest-label[_ngcontent-%COMP%] {\n color: var(--mj-color-success-600);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 200px;\n}\n\n.ve-header-stats[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n}\n\n.ve-stat[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.ve-stat[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n font-weight: 700;\n}\n\n.ve-stat-sep[_ngcontent-%COMP%] {\n width: 1px;\n height: 14px;\n background: var(--mj-border-default);\n}\n\n.ve-header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.ve-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 14px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n border: none;\n white-space: nowrap;\n}\n\n.ve-btn-ghost[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n.ve-btn-ghost[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-active); color: var(--mj-text-primary); }\n\n.ve-btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-color-indigo-500);\n color: var(--mj-bg-surface);\n}\n\n.ve-btn-primary[_ngcontent-%COMP%]:hover { background: var(--mj-color-indigo-600); }\n.ve-btn-primary[_ngcontent-%COMP%]:disabled { opacity: 0.5; cursor: default; }\n\n.ve-btn-danger[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-color-error-600);\n border: 1px solid var(--mj-color-error-200);\n}\n\n.ve-btn-danger[_ngcontent-%COMP%]:hover { background: var(--mj-color-error-100); }\n\n.ve-save-success[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-color-success-600);\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 4px;\n animation: _ngcontent-%COMP%_fadeIn 300ms ease;\n}\n\n\n\n.ve-sync-toggle[_ngcontent-%COMP%] { flex-shrink: 0; margin-left: 8px; }\n.ve-sync-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n\n\n.ve-action-sep[_ngcontent-%COMP%] {\n width: 1px;\n height: 20px;\n background: var(--mj-border-default);\n flex-shrink: 0;\n}\n\n\n\n.ve-btn-ghost.active[_ngcontent-%COMP%] {\n background: var(--mj-color-indigo-50);\n color: var(--mj-color-indigo-600);\n border-color: var(--mj-color-indigo-200);\n}\n\n\n\n\n\n\n.ve-preview-strip[_ngcontent-%COMP%] {\n display: flex;\n gap: 1px;\n background: var(--mj-border-default);\n border-bottom: 1px solid var(--mj-border-default);\n max-height: 220px;\n flex-shrink: 0;\n overflow: hidden;\n}\n\n.ve-preview-panel[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n overflow: hidden;\n}\n\n.ve-preview-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 1px solid var(--mj-border-subtle);\n flex-shrink: 0;\n}\n\n.ve-preview-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 11px; color: var(--mj-color-indigo-500); }\n.ve-preview-header[_ngcontent-%COMP%] span[_ngcontent-%COMP%] { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n.ve-preview-close[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n font-size: 11px;\n flex-shrink: 0;\n}\n\n.ve-preview-close[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-active); color: var(--mj-text-secondary); }\n\n.ve-preview-loading[_ngcontent-%COMP%], \n.ve-preview-empty[_ngcontent-%COMP%] {\n padding: 20px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.ve-preview-loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { margin-right: 6px; color: var(--mj-color-indigo-500); }\n\n.ve-preview-table-wrap[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n}\n\n.ve-preview-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 11px;\n}\n\n.ve-preview-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n position: sticky;\n top: 0;\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-muted);\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n font-size: 10px;\n padding: 5px 10px;\n text-align: left;\n white-space: nowrap;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.ve-preview-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 4px 10px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-subtle);\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.ve-preview-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover td[_ngcontent-%COMP%] {\n background: var(--mj-color-indigo-50);\n}\n\n\n\n\n\n\n.ve-connect-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 20px;\n background: var(--mj-color-indigo-50);\n color: var(--mj-color-indigo-700);\n font-size: 13px;\n border-bottom: 1px solid var(--mj-color-indigo-100);\n flex-shrink: 0;\n}\n\n.ve-connect-banner[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] { font-weight: 700; }\n\n.ve-connect-cancel[_ngcontent-%COMP%] {\n margin-left: auto;\n padding: 3px 10px;\n border: 1px solid var(--mj-color-indigo-100);\n border-radius: 5px;\n background: var(--mj-bg-surface);\n color: var(--mj-color-indigo-700);\n font-size: 12px;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.ve-connect-cancel[_ngcontent-%COMP%]:hover { background: var(--mj-color-indigo-100); }\n\n\n\n\n\n\n.ve-body[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n.ve-loading[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 100%;\n gap: 12px;\n color: var(--mj-text-disabled);\n font-size: 14px;\n}\n\n.ve-loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 24px; color: var(--mj-color-indigo-500); }\n\n\n\n.ve-sections-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-width: 0;\n}\n\n\n\n.ve-section[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.ve-section[_ngcontent-%COMP%]:not(.collapsed) {\n flex: 1;\n min-height: 0;\n}\n\n.ve-section.collapsed[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n.ve-section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n cursor: pointer;\n user-select: none;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-subtle);\n flex-shrink: 0;\n transition: background 150ms ease;\n}\n\n.ve-section-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.ve-section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-disabled);\n width: 12px;\n flex-shrink: 0;\n transition: transform 200ms ease;\n}\n\n.ve-section-title[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n color: var(--mj-text-muted);\n}\n\n.ve-section-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 600;\n background: var(--mj-color-indigo-50);\n color: var(--mj-color-indigo-600);\n padding: 1px 8px;\n border-radius: 4px;\n margin-left: auto;\n}\n\n.ve-section-body[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n animation: _ngcontent-%COMP%_fadeIn 200ms ease;\n}\n\n\n\n.ve-canvas-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-width: 0;\n}\n\n\n\n\n\n\n.ve-col-headers[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 200px 1fr;\n flex-shrink: 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-col-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n}\n\n.ve-col-header.source[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-color-indigo-500); }\n.ve-col-header.dest[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-color-success-600); }\n.ve-col-header-spacer[_ngcontent-%COMP%] { \n }\n\n.ve-col-count[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 600;\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-disabled);\n padding: 1px 6px;\n border-radius: 4px;\n}\n\n\n\n\n\n\n.ve-col-searches[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 200px 1fr;\n flex-shrink: 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n padding: 6px 0;\n}\n\n.ve-col-search[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 0 12px;\n}\n\n.ve-col-search[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n}\n\n.ve-col-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n font-size: 12px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-page);\n outline: none;\n transition: border-color 150ms ease;\n}\n\n.ve-col-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus { border-color: var(--mj-color-indigo-500); background: var(--mj-bg-surface); }\n.ve-col-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder { color: var(--mj-color-neutral-300); }\n.ve-col-search-spacer[_ngcontent-%COMP%] { \n }\n\n\n\n\n\n\n.ve-canvas-scroll[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.ve-canvas-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 200px 1fr;\n position: relative;\n}\n\n\n\n\n\n\n.ve-field-col[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n}\n\n.ve-field-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 14px;\n font-size: 13px;\n cursor: pointer;\n transition: background 150ms ease, opacity 150ms ease;\n border-bottom: 1px solid var(--mj-bg-page);\n box-sizing: border-box;\n}\n\n.ve-field-item.mapped[_ngcontent-%COMP%] { background: var(--mj-bg-surface); }\n\n.ve-field-item.unmapped[_ngcontent-%COMP%] {\n opacity: 0.5;\n background: var(--mj-bg-page);\n}\n\n.ve-field-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-color-indigo-50);\n opacity: 1;\n}\n\n.ve-field-item.connecting[_ngcontent-%COMP%] {\n background: var(--mj-color-indigo-100);\n opacity: 1;\n box-shadow: inset 0 0 0 2px var(--mj-color-indigo-500);\n}\n\n.ve-field-item.connect-target[_ngcontent-%COMP%]:hover {\n background: var(--mj-color-success-100);\n box-shadow: inset 0 0 0 2px var(--mj-color-success-600);\n}\n\n.ve-field-name[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--mj-color-neutral-700);\n font-weight: 500;\n}\n\n.ve-field-type[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n font-family: 'SF Mono', 'Fira Code', monospace;\n}\n\n.ve-field-badges[_ngcontent-%COMP%] {\n display: flex;\n gap: 3px;\n flex-shrink: 0;\n}\n\n.ve-fbadge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 3px;\n border-radius: 4px;\n font-size: 9px;\n font-weight: 700;\n}\n\n.ve-fbadge.pk[_ngcontent-%COMP%] { background: var(--mj-color-warning-100); color: var(--mj-color-warning-700); }\n.ve-fbadge.req[_ngcontent-%COMP%] { background: var(--mj-color-error-100); color: var(--mj-color-error-600); }\n\n.ve-field-empty[_ngcontent-%COMP%] {\n padding: 32px 16px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n}\n\n\n\n\n\n\n.ve-svg[_ngcontent-%COMP%] {\n display: block;\n}\n\n.ve-conn-line[_ngcontent-%COMP%] {\n fill: none;\n stroke-width: 2;\n cursor: pointer;\n transition: stroke 200ms ease, stroke-width 200ms ease;\n}\n\n\n\n.ve-conn-line.conn-direct[_ngcontent-%COMP%] { stroke: #6366f1; stroke-dasharray: none; }\n.ve-conn-line.conn-regex[_ngcontent-%COMP%] { stroke: #8b5cf6; stroke-dasharray: 6 3; }\n.ve-conn-line.conn-split[_ngcontent-%COMP%] { stroke: #f59e0b; stroke-dasharray: 8 4; }\n.ve-conn-line.conn-combine[_ngcontent-%COMP%] { stroke: #10b981; stroke-dasharray: 8 4; }\n.ve-conn-line.conn-lookup[_ngcontent-%COMP%] { stroke: #0ea5e9; stroke-dasharray: 4 4; }\n.ve-conn-line.conn-format[_ngcontent-%COMP%] { stroke: #ec4899; stroke-dasharray: 4 4; }\n.ve-conn-line.conn-coerce[_ngcontent-%COMP%] { stroke: #f97316; stroke-dasharray: 4 4; }\n.ve-conn-line.conn-substring[_ngcontent-%COMP%] { stroke: #14b8a6; stroke-dasharray: 4 4; }\n.ve-conn-line.conn-custom[_ngcontent-%COMP%] { stroke: #a855f7; stroke-dasharray: 2 3; }\n\n.ve-conn-line[_ngcontent-%COMP%]:hover { stroke-width: 3.5; }\n.ve-conn-line.selected[_ngcontent-%COMP%] { stroke-width: 3.5; filter: drop-shadow(0 0 4px rgba(99, 102, 241, 0.4)); }\n\n\n\n.ve-badge-fo[_ngcontent-%COMP%] { overflow: visible; }\n\n.ve-conn-badge[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n cursor: pointer;\n transition: all 150ms ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n}\n\n.ve-conn-badge.badge-direct[_ngcontent-%COMP%] { background: #eef2ff; color: #6366f1; border: 2px solid #6366f1; }\n.ve-conn-badge.badge-regex[_ngcontent-%COMP%] { background: #f5f3ff; color: #8b5cf6; border: 2px solid #8b5cf6; }\n.ve-conn-badge.badge-split[_ngcontent-%COMP%] { background: #fffbeb; color: #f59e0b; border: 2px solid #f59e0b; }\n.ve-conn-badge.badge-combine[_ngcontent-%COMP%] { background: #ecfdf5; color: #10b981; border: 2px solid #10b981; }\n.ve-conn-badge.badge-lookup[_ngcontent-%COMP%] { background: #f0f9ff; color: #0ea5e9; border: 2px solid #0ea5e9; }\n.ve-conn-badge.badge-format[_ngcontent-%COMP%] { background: #fdf2f8; color: #ec4899; border: 2px solid #ec4899; }\n.ve-conn-badge.badge-coerce[_ngcontent-%COMP%] { background: #fff7ed; color: #f97316; border: 2px solid #f97316; }\n.ve-conn-badge.badge-substring[_ngcontent-%COMP%] { background: #f0fdfa; color: #14b8a6; border: 2px solid #14b8a6; }\n.ve-conn-badge.badge-custom[_ngcontent-%COMP%] { background: #faf5ff; color: #a855f7; border: 2px solid #a855f7; }\n\n.ve-conn-badge[_ngcontent-%COMP%]:hover { transform: scale(1.2); }\n.ve-conn-badge.selected[_ngcontent-%COMP%] { transform: scale(1.25); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.3); }\n\n\n\n\n\n\n.ve-transform-panel[_ngcontent-%COMP%] {\n width: 320px;\n flex-shrink: 0;\n border-left: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n background: var(--mj-bg-page);\n animation: _ngcontent-%COMP%_slideInRight 200ms ease;\n}\n\n@keyframes _ngcontent-%COMP%_slideInRight {\n from { opacity: 0; transform: translateX(20px); }\n to { opacity: 1; transform: translateX(0); }\n}\n\n.ve-tp-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.ve-tp-title[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.ve-tp-close[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n font-size: 13px;\n transition: all 150ms ease;\n}\n\n.ve-tp-close[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-active); color: var(--mj-text-secondary); }\n\n\n\n.ve-tp-mapping-info[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-tp-field-pair[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.ve-tp-field[_ngcontent-%COMP%] {\n padding: 4px 10px;\n border-radius: 6px;\n font-weight: 600;\n font-size: 12px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 110px;\n}\n\n.ve-tp-field.source[_ngcontent-%COMP%] { background: var(--mj-color-indigo-50); color: var(--mj-color-indigo-700); }\n.ve-tp-field.dest[_ngcontent-%COMP%] { background: var(--mj-status-success-bg); color: var(--mj-color-success-700); }\n.ve-tp-arrow[_ngcontent-%COMP%] { color: var(--mj-text-disabled); font-size: 11px; flex-shrink: 0; }\n\n\n\n.ve-tp-toggles[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-tp-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.ve-tp-toggle-box[_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n border: 2px solid var(--mj-color-neutral-300);\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n color: var(--mj-bg-surface);\n transition: all 150ms ease;\n}\n\n.ve-tp-toggle-box.active[_ngcontent-%COMP%] {\n background: var(--mj-color-indigo-500);\n border-color: var(--mj-color-indigo-500);\n}\n\n\n\n.ve-tp-section[_ngcontent-%COMP%] {\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-tp-section-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 10px;\n font-weight: 700;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n margin-bottom: 8px;\n}\n\n.ve-tp-section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n\n\n.ve-tp-direction-btns[_ngcontent-%COMP%] {\n display: flex;\n gap: 0;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.ve-tp-direction-btns[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n flex: 1;\n padding: 6px 8px;\n border: none;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n border-right: 1px solid var(--mj-border-default);\n}\n\n.ve-tp-direction-btns[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:last-child { border-right: none; }\n.ve-tp-direction-btns[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); }\n.ve-tp-direction-btns[_ngcontent-%COMP%] button.active[_ngcontent-%COMP%] { background: var(--mj-color-indigo-500); color: var(--mj-bg-surface); }\n\n\n\n.ve-tp-add-step[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n font-size: 11px;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.ve-tp-add-step[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n\n.ve-tp-step[_ngcontent-%COMP%] {\n margin-top: 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n overflow: hidden;\n}\n\n.ve-tp-step-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-tp-step-num[_ngcontent-%COMP%] {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: var(--mj-color-indigo-500);\n color: var(--mj-bg-surface);\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.ve-tp-type-select[_ngcontent-%COMP%] {\n flex: 1;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n font-size: 12px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-surface);\n outline: none;\n cursor: pointer;\n}\n\n.ve-tp-type-select[_ngcontent-%COMP%]:focus { border-color: var(--mj-color-indigo-500); }\n\n.ve-tp-remove-step[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 5px;\n background: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n font-size: 11px;\n transition: all 150ms ease;\n flex-shrink: 0;\n}\n\n.ve-tp-remove-step[_ngcontent-%COMP%]:hover { background: var(--mj-color-error-100); color: var(--mj-color-error-600); }\n\n.ve-tp-step-config[_ngcontent-%COMP%] {\n padding: 8px 10px;\n}\n\n.ve-tp-config-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n}\n\n.ve-tp-config-row[_ngcontent-%COMP%]:last-child { margin-bottom: 0; }\n\n.ve-tp-config-row[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n width: 80px;\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.ve-tp-config-row[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n font-size: 12px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-page);\n outline: none;\n font-family: 'SF Mono', 'Fira Code', monospace;\n}\n\n.ve-tp-config-row[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus { border-color: var(--mj-color-indigo-500); background: var(--mj-bg-surface); }\n\n.ve-tp-step-onerror[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n border-top: 1px solid var(--mj-border-subtle);\n background: var(--mj-bg-page);\n}\n\n.ve-tp-step-onerror[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n}\n\n.ve-tp-step-onerror[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n height: 24px;\n padding: 0 6px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 11px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-surface);\n outline: none;\n cursor: pointer;\n}\n\n.ve-tp-no-steps[_ngcontent-%COMP%] {\n padding: 16px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 12px;\n font-style: italic;\n}\n\n\n\n.ve-tp-footer[_ngcontent-%COMP%] {\n padding: 14px 16px;\n margin-top: auto;\n flex-shrink: 0;\n}\n\n\n\n\n\n\n.cards-list[_ngcontent-%COMP%]::-webkit-scrollbar, \n.map-table-body[_ngcontent-%COMP%]::-webkit-scrollbar, \n.ve-canvas-scroll[_ngcontent-%COMP%]::-webkit-scrollbar, \n.ve-transform-panel[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 6px;\n height: 6px;\n}\n\n.cards-list[_ngcontent-%COMP%]::-webkit-scrollbar-track, \n.map-table-body[_ngcontent-%COMP%]::-webkit-scrollbar-track, \n.ve-canvas-scroll[_ngcontent-%COMP%]::-webkit-scrollbar-track, \n.ve-transform-panel[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.cards-list[_ngcontent-%COMP%]::-webkit-scrollbar-thumb, \n.map-table-body[_ngcontent-%COMP%]::-webkit-scrollbar-thumb, \n.ve-canvas-scroll[_ngcontent-%COMP%]::-webkit-scrollbar-thumb, \n.ve-transform-panel[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: var(--mj-color-neutral-300);\n border-radius: 3px;\n}\n\n.cards-list[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover, \n.map-table-body[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover, \n.ve-canvas-scroll[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover, \n.ve-transform-panel[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n\n\n\n\n\n.ve-info-body[_ngcontent-%COMP%] {\n padding: 16px;\n overflow-y: auto;\n}\n\n.ve-info-loading[_ngcontent-%COMP%] {\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n padding: 20px;\n}\n\n.ve-info-loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-indigo-500);\n margin-right: 6px;\n}\n\n.ve-info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n gap: 12px;\n margin-bottom: 16px;\n}\n\n.ve-info-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 14px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n}\n\n.ve-info-card-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n flex-shrink: 0;\n background: var(--mj-color-indigo-50);\n color: var(--mj-color-indigo-500);\n}\n\n.ve-info-card-icon.source[_ngcontent-%COMP%] {\n background: var(--mj-color-info-100);\n color: var(--mj-brand-primary);\n}\n\n.ve-info-card-icon.sync[_ngcontent-%COMP%] {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-600);\n}\n\n.ve-info-card-icon.info-status-success[_ngcontent-%COMP%] {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-600);\n}\n\n.ve-info-card-icon.info-status-error[_ngcontent-%COMP%] {\n background: var(--mj-color-error-100);\n color: var(--mj-color-error-600);\n}\n\n.ve-info-card-icon.info-status-running[_ngcontent-%COMP%] {\n background: var(--mj-color-info-100);\n color: var(--mj-brand-primary);\n}\n\n.ve-info-card-icon.info-status-pending[_ngcontent-%COMP%] {\n background: var(--mj-color-warning-100);\n color: var(--mj-color-warning-600);\n}\n\n.ve-info-card-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.ve-info-card-value[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.ve-info-card-label[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n.ve-info-details[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.ve-info-detail-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px;\n font-size: 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-info-detail-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.ve-info-detail-label[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-weight: 500;\n}\n\n.ve-info-detail-value[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n font-weight: 600;\n}"] });
2043
+ };
2044
+ PipelinesComponent = __decorate([
2045
+ RegisterClass(BaseResourceComponent, 'IntegrationPipelines')
2046
+ ], PipelinesComponent);
2047
+ export { PipelinesComponent };
2048
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PipelinesComponent, [{
2049
+ type: Component,
2050
+ args: [{ standalone: false, selector: 'app-integration-pipelines', template: "<div class=\"pipelines-container\">\n\n <!-- ===================================================================== -->\n <!-- MAP LIST VIEW (hidden when editor is open) -->\n <!-- ===================================================================== -->\n @if (!VisualEditorOpen) {\n\n <!-- Toolbar -->\n <div class=\"pipelines-toolbar\">\n <div class=\"toolbar-left\">\n <h2 class=\"toolbar-title\">\n <i class=\"fa-solid fa-diagram-project\"></i>\n Pipelines\n </h2>\n <span class=\"toolbar-count-badge\">{{ IntegrationCount }}</span>\n <span class=\"toolbar-map-count\">{{ TotalMapCount }} entity maps</span>\n </div>\n <div class=\"toolbar-right\">\n <div class=\"global-search\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input type=\"text\"\n class=\"search-input\"\n placeholder=\"Search integrations or entities...\"\n [value]=\"GlobalSearch\"\n (input)=\"OnGlobalSearchChange($event)\" />\n </div>\n <button class=\"toolbar-btn\" (click)=\"ExpandAll()\" title=\"Expand All\">\n <i class=\"fa-solid fa-angles-down\"></i>\n </button>\n <button class=\"toolbar-btn\" (click)=\"CollapseAll()\" title=\"Collapse All\">\n <i class=\"fa-solid fa-angles-up\"></i>\n </button>\n <div class=\"toolbar-divider\"></div>\n <button class=\"toolbar-btn\" (click)=\"LoadData()\" title=\"Refresh\">\n <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"IsLoading\"></i>\n </button>\n </div>\n </div>\n\n <!-- Main content area -->\n <div class=\"pipelines-content\">\n @if (IsLoading && PipelineCards.length === 0) {\n <div class=\"content-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading pipelines...</span>\n </div>\n } @else if (PipelineCards.length === 0) {\n <div class=\"content-empty\">\n <i class=\"fa-solid fa-diagram-project empty-icon\"></i>\n <h3>No Integration Pipelines</h3>\n <p>Configure integrations to see data flow pipelines here.</p>\n </div>\n } @else {\n <div class=\"cards-list\">\n @for (card of FilteredCards; track card.IntegrationID) {\n <!-- Pipeline card -->\n <div class=\"pipeline-card\" [class.expanded]=\"card.IsExpanded\">\n\n <!-- Card header (always visible) -->\n <div class=\"card-header\" (click)=\"ToggleCard(card)\">\n <div class=\"card-header-left\">\n <div class=\"card-status-dot\" [style.backgroundColor]=\"card.StatusColor\"></div>\n <i [class]=\"card.Icon + ' card-icon'\"></i>\n <div class=\"card-info\">\n <span class=\"card-name\">{{ card.IntegrationName }}</span>\n <span class=\"card-meta\">\n {{ card.EntityMapCount }} maps\n <span class=\"meta-sep\">&middot;</span>\n {{ card.ActiveMapCount }} active\n <span class=\"meta-sep\">&middot;</span>\n {{ card.UniqueEntityCount }} entities\n </span>\n </div>\n </div>\n <div class=\"card-header-right\">\n <span class=\"card-status-label\" [style.color]=\"card.StatusColor\">\n {{ card.StatusLabel }}\n </span>\n @if (card.LastSync) {\n <span class=\"card-last-sync\">{{ card.LastSync }}</span>\n }\n <!-- Mini flow indicator -->\n <div class=\"mini-flow\">\n <span class=\"mini-flow-dot source\"></span>\n <span class=\"mini-flow-line\"></span>\n <span class=\"mini-flow-count\">{{ card.EntityMapCount }}</span>\n <span class=\"mini-flow-line\"></span>\n <span class=\"mini-flow-dot dest\"></span>\n </div>\n <i class=\"fa-solid card-chevron\"\n [class.fa-chevron-down]=\"!card.IsExpanded\"\n [class.fa-chevron-up]=\"card.IsExpanded\"></i>\n </div>\n </div>\n\n <!-- Expanded entity map table -->\n @if (card.IsExpanded) {\n <div class=\"card-body\">\n <!-- Search within this integration -->\n <div class=\"card-search-bar\">\n <i class=\"fa-solid fa-filter card-search-icon\"></i>\n <input type=\"text\"\n class=\"card-search-input\"\n placeholder=\"Filter entity maps...\"\n [value]=\"card.SearchTerm\"\n (input)=\"OnCardSearch(card, $event)\" />\n <span class=\"card-search-count\">\n {{ card.FilteredMaps.length }} of {{ card.EntityMapCount }}\n </span>\n </div>\n\n <!-- Table header -->\n <div class=\"map-table-head\">\n <span class=\"map-col-toggle\">Sync</span>\n <span class=\"map-col-source\">External Object</span>\n <span class=\"map-col-direction\"></span>\n <span class=\"map-col-dest\">MJ Entity</span>\n <span class=\"map-col-meta\">Config</span>\n </div>\n\n <!-- Table body -->\n <div class=\"map-table-body\">\n @for (em of card.FilteredMaps; track em.ID) {\n <div class=\"map-row\"\n [class.sync-disabled]=\"!em.SyncEnabled\"\n (click)=\"OnMapRowClick(card, em)\">\n <span class=\"map-col-toggle\" (click)=\"$event.stopPropagation()\">\n <label class=\"sync-toggle\" [title]=\"em.SyncEnabled ? 'Sync enabled \u2014 click to disable' : 'Sync disabled \u2014 click to enable'\">\n <input type=\"checkbox\"\n [checked]=\"em.SyncEnabled\"\n (change)=\"OnToggleSyncEnabled(card, em, $event)\" />\n <span class=\"sync-toggle-track\"></span>\n </label>\n </span>\n <span class=\"map-col-source\" [title]=\"em.ExternalObjectName\">\n {{ em.ExternalObjectLabel ?? em.ExternalObjectName }}\n </span>\n <span class=\"map-col-direction\">\n <span [class]=\"DirectionBadgeClass(em.SyncDirection)\">\n {{ DirectionText(em.SyncDirection) }}\n </span>\n </span>\n <span class=\"map-col-dest\" [title]=\"em.Entity\">\n {{ em.Entity }}\n </span>\n <span class=\"map-col-meta\">\n @if (em.MatchStrategy) {\n <span class=\"map-config-badge\" [title]=\"'Match: ' + em.MatchStrategy\">\n <i class=\"fa-solid fa-link\"></i>\n </span>\n }\n <span class=\"map-config-badge\" [title]=\"'Conflict: ' + em.ConflictResolution\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n </span>\n <span class=\"map-edit-hint\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </span>\n </span>\n </div>\n } @empty {\n <div class=\"map-table-empty\">\n No entity maps match your filter.\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n } @else {\n\n <!-- ===================================================================== -->\n <!-- VISUAL FIELD MAPPING EDITOR (inline, replaces map list) -->\n <!-- ===================================================================== -->\n\n <div class=\"ve-container\">\n\n <!-- Header -->\n <div class=\"ve-header\">\n <div class=\"ve-header-left\">\n <button class=\"ve-back-btn\" (click)=\"CloseVisualEditor()\" title=\"Back to Pipelines\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n </button>\n <div class=\"ve-header-title\">\n <span class=\"ve-source-label\">{{ EditorEntityMap?.ExternalObjectLabel ?? EditorEntityMap?.ExternalObjectName }}</span>\n <span class=\"ve-direction-arrow\">\n <i class=\"fa-solid fa-arrow-right-arrow-left\"></i>\n </span>\n <span class=\"ve-dest-label\">{{ EditorEntityMap?.Entity }}</span>\n </div>\n <!-- SyncEnabled toggle in editor header -->\n @if (EditorEntityMap) {\n <label class=\"sync-toggle ve-sync-toggle\"\n [title]=\"EditorEntityMap.SyncEnabled ? 'Sync enabled' : 'Sync disabled'\">\n <input type=\"checkbox\"\n [checked]=\"EditorEntityMap.SyncEnabled\"\n (change)=\"OnToggleEditorSyncEnabled($event)\" />\n <span class=\"sync-toggle-track\"></span>\n </label>\n <span class=\"ve-sync-label\">{{ EditorEntityMap.SyncEnabled ? 'Sync On' : 'Sync Off' }}</span>\n }\n </div>\n <div class=\"ve-header-stats\">\n <span class=\"ve-stat\">\n <strong>{{ EditorMappedCount }}</strong> mapped\n </span>\n <span class=\"ve-stat-sep\"></span>\n <span class=\"ve-stat\">\n <strong>{{ EditorKeyFieldCount }}</strong> key\n </span>\n <span class=\"ve-stat-sep\"></span>\n <span class=\"ve-stat\">\n <strong>{{ EditorRequiredCount }}</strong> required\n </span>\n </div>\n <div class=\"ve-header-actions\">\n <!-- Data preview buttons -->\n <button class=\"ve-btn ve-btn-ghost\"\n (click)=\"ToggleSourcePreview()\"\n [class.active]=\"ShowSourcePreview\"\n title=\"Preview source data\">\n <i class=\"fa-solid fa-cloud\"></i> Source Data\n </button>\n <button class=\"ve-btn ve-btn-ghost\"\n (click)=\"ToggleDestPreview()\"\n [class.active]=\"ShowDestPreview\"\n title=\"Preview MJ data\">\n <i class=\"fa-solid fa-database\"></i> MJ Data\n </button>\n <div class=\"ve-action-sep\"></div>\n <button class=\"ve-btn ve-btn-ghost\" (click)=\"AutoMapEditorFields()\" title=\"Auto-map fields by name\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i> Auto-Map\n </button>\n <button class=\"ve-btn ve-btn-primary\"\n [disabled]=\"!HasEditorChanges || EditorSaving\"\n (click)=\"SaveVisualEditor()\">\n @if (EditorSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-check\"></i> Save\n }\n </button>\n @if (EditorSaveSuccess && !HasEditorChanges) {\n <span class=\"ve-save-success\">\n <i class=\"fa-solid fa-circle-check\"></i> Saved\n </span>\n }\n </div>\n </div>\n\n <!-- Data preview panels (collapsible) -->\n @if (ShowSourcePreview || ShowDestPreview) {\n <div class=\"ve-preview-strip\">\n @if (ShowSourcePreview) {\n <div class=\"ve-preview-panel\">\n <div class=\"ve-preview-header\">\n <i class=\"fa-solid fa-cloud\"></i>\n <span>Source Preview: {{ EditorEntityMap?.ExternalObjectLabel ?? EditorEntityMap?.ExternalObjectName }}</span>\n <button class=\"ve-preview-close\" (click)=\"ShowSourcePreview = false\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n @if (PreviewSourceLoading) {\n <div class=\"ve-preview-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading...\n </div>\n } @else if (PreviewSourceRows.length === 0) {\n <div class=\"ve-preview-empty\">No source data available</div>\n } @else {\n <div class=\"ve-preview-table-wrap\">\n <table class=\"ve-preview-table\">\n <thead>\n <tr>\n @for (col of PreviewSourceColumns; track col) {\n <th>{{ col }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of PreviewSourceRows; track $index) {\n <tr>\n @for (col of PreviewSourceColumns; track col) {\n <td [title]=\"row[col]?.toString() ?? ''\">{{ row[col] ?? '' }}</td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n }\n @if (ShowDestPreview) {\n <div class=\"ve-preview-panel\">\n <div class=\"ve-preview-header\">\n <i class=\"fa-solid fa-database\"></i>\n <span>Dest Preview: {{ EditorEntityMap?.Entity }}</span>\n <button class=\"ve-preview-close\" (click)=\"ShowDestPreview = false\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n @if (PreviewDestLoading) {\n <div class=\"ve-preview-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading...\n </div>\n } @else if (PreviewDestRows.length === 0) {\n <div class=\"ve-preview-empty\">No destination data available</div>\n } @else {\n <div class=\"ve-preview-table-wrap\">\n <table class=\"ve-preview-table\">\n <thead>\n <tr>\n @for (col of PreviewDestColumns; track col) {\n <th>{{ col }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of PreviewDestRows; track $index) {\n <tr>\n @for (col of PreviewDestColumns; track col) {\n <td [title]=\"row[col]?.toString() ?? ''\">{{ row[col] ?? '' }}</td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Connect mode banner -->\n @if (ConnectingFromSource) {\n <div class=\"ve-connect-banner\">\n <i class=\"fa-solid fa-link\"></i>\n Click a destination field to map from\n <strong>{{ ConnectingFromSource }}</strong>\n <button class=\"ve-connect-cancel\" (click)=\"CancelConnect()\">Cancel</button>\n </div>\n }\n\n <!-- Main content: sections + transform panel -->\n <div class=\"ve-body\" [class.has-transform-panel]=\"SelectedConnectionIdx !== null\">\n\n <!-- Loading state -->\n @if (EditorLoading) {\n <div class=\"ve-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading field mappings...</span>\n </div>\n } @else {\n\n <!-- Left content area (sections stacked vertically) -->\n <div class=\"ve-sections-wrapper\">\n\n <!-- ============================================================= -->\n <!-- FIELD MAPPINGS SECTION (collapsible) -->\n <!-- ============================================================= -->\n <div class=\"ve-section\" [class.collapsed]=\"!FieldMapsExpanded\">\n <div class=\"ve-section-header\" (click)=\"ToggleFieldMaps()\">\n <i class=\"fa-solid\"\n [class.fa-chevron-down]=\"FieldMapsExpanded\"\n [class.fa-chevron-right]=\"!FieldMapsExpanded\"></i>\n <span class=\"ve-section-title\">Field Mappings</span>\n <span class=\"ve-section-badge\">{{ EditorMappedCount }} mapped</span>\n </div>\n\n @if (FieldMapsExpanded) {\n <div class=\"ve-section-body\">\n <!-- Canvas area (scrollable) -->\n <div class=\"ve-canvas-wrapper\">\n\n <!-- Column headers -->\n <div class=\"ve-col-headers\">\n <div class=\"ve-col-header source\">\n <i class=\"fa-solid fa-cloud\"></i>\n Source Fields\n <span class=\"ve-col-count\">{{ EditorSourceFields.length }}</span>\n </div>\n <div class=\"ve-col-header-spacer\"></div>\n <div class=\"ve-col-header dest\">\n <i class=\"fa-solid fa-database\"></i>\n MJ Entity Fields\n <span class=\"ve-col-count\">{{ EditorDestFields.length }}</span>\n </div>\n </div>\n\n <!-- Search bars -->\n <div class=\"ve-col-searches\">\n <div class=\"ve-col-search\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Filter source fields...\"\n [value]=\"EditorSearchSource\"\n (input)=\"EditorSearchSource = $any($event.target).value\" />\n </div>\n <div class=\"ve-col-search-spacer\"></div>\n <div class=\"ve-col-search\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Filter destination fields...\"\n [value]=\"EditorSearchDest\"\n (input)=\"EditorSearchDest = $any($event.target).value\" />\n </div>\n </div>\n\n <!-- Canvas grid (source + SVG + dest) -->\n <div class=\"ve-canvas-scroll\" (click)=\"DeselectConnection()\">\n <div class=\"ve-canvas-grid\" [style.min-height.px]=\"EditorCanvasHeight\">\n\n <!-- Source column -->\n <div class=\"ve-field-col source\">\n @for (sf of FilteredEditorSourceFields; track sf.Name) {\n <div class=\"ve-field-item\"\n [class.mapped]=\"IsSourceFieldMapped(sf.Name)\"\n [class.unmapped]=\"!IsSourceFieldMapped(sf.Name)\"\n [class.connecting]=\"ConnectingFromSource === sf.Name\"\n [style.height.px]=\"FIELD_HEIGHT\"\n (click)=\"OnEditorSourceClick(sf.Name); $event.stopPropagation()\">\n <span class=\"ve-field-name\" [title]=\"sf.Name\">{{ sf.Label || sf.Name }}</span>\n <span class=\"ve-field-type\">{{ sf.Type }}</span>\n <span class=\"ve-field-badges\">\n @if (sf.IsPrimaryKey) {\n <span class=\"ve-fbadge pk\" title=\"Primary Key\">PK</span>\n }\n @if (sf.IsRequired) {\n <span class=\"ve-fbadge req\" title=\"Required\">*</span>\n }\n </span>\n </div>\n }\n @if (FilteredEditorSourceFields.length === 0) {\n <div class=\"ve-field-empty\">No source fields found</div>\n }\n </div>\n\n <!-- SVG connection lines -->\n <svg class=\"ve-svg\"\n [attr.width]=\"SVG_WIDTH\"\n [attr.height]=\"EditorCanvasHeight\"\n [attr.viewBox]=\"'0 0 ' + SVG_WIDTH + ' ' + EditorCanvasHeight\"\n (click)=\"$event.stopPropagation()\">\n @for (conn of VisibleConnections; track conn.SourceFieldName + '-' + conn.DestFieldName; let i = $index) {\n <!-- Connection line -->\n <path [attr.d]=\"GetConnectionPath(conn)\"\n class=\"ve-conn-line\"\n [class]=\"'ve-conn-line ' + GetConnectionLineClass(conn)\"\n [class.selected]=\"SelectedConnectionIdx === i\"\n (click)=\"SelectConnection(i, $event)\" />\n <!-- Transform badge at midpoint -->\n <foreignObject\n [attr.x]=\"SVG_WIDTH / 2 - 14\"\n [attr.y]=\"GetConnectionMidY(conn) - 14\"\n width=\"28\" height=\"28\"\n class=\"ve-badge-fo\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\"\n class=\"ve-conn-badge\"\n [class]=\"'ve-conn-badge ' + GetConnectionBadgeClass(conn)\"\n [class.selected]=\"SelectedConnectionIdx === i\"\n (click)=\"SelectConnection(i, $event)\">\n <i [class]=\"GetConnectionDirectionIcon(conn)\"></i>\n </div>\n </foreignObject>\n }\n </svg>\n\n <!-- Dest column -->\n <div class=\"ve-field-col dest\">\n @for (df of FilteredEditorDestFields; track df.Name) {\n <div class=\"ve-field-item\"\n [class.mapped]=\"IsDestFieldMapped(df.Name)\"\n [class.unmapped]=\"!IsDestFieldMapped(df.Name)\"\n [class.connect-target]=\"ConnectingFromSource !== null\"\n [style.height.px]=\"FIELD_HEIGHT\"\n (click)=\"OnEditorDestClick(df.Name); $event.stopPropagation()\">\n <span class=\"ve-field-name\" [title]=\"df.Name\">{{ df.Name }}</span>\n <span class=\"ve-field-type\">{{ df.Type }}</span>\n <span class=\"ve-field-badges\">\n @if (df.IsRequired) {\n <span class=\"ve-fbadge req\" title=\"Required\">*</span>\n }\n </span>\n </div>\n }\n @if (FilteredEditorDestFields.length === 0) {\n <div class=\"ve-field-empty\">No destination fields found</div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- ============================================================= -->\n <!-- INFO PANEL SECTION (collapsible) -->\n <!-- ============================================================= -->\n <div class=\"ve-section\" [class.collapsed]=\"!InfoPanelExpanded\">\n <div class=\"ve-section-header\" (click)=\"ToggleInfoPanel()\">\n <i class=\"fa-solid\"\n [class.fa-chevron-down]=\"InfoPanelExpanded\"\n [class.fa-chevron-right]=\"!InfoPanelExpanded\"></i>\n <span class=\"ve-section-title\">Sync Info</span>\n </div>\n\n @if (InfoPanelExpanded) {\n <div class=\"ve-section-body ve-info-body\">\n @if (InfoPanelLoading) {\n <div class=\"ve-info-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading stats...\n </div>\n } @else {\n <div class=\"ve-info-grid\">\n <!-- Destination record count -->\n <div class=\"ve-info-card\">\n <div class=\"ve-info-card-icon\">\n <i class=\"fa-solid fa-database\"></i>\n </div>\n <div class=\"ve-info-card-content\">\n <span class=\"ve-info-card-value\">{{ InfoDestRecordCount ?? '-' }}</span>\n <span class=\"ve-info-card-label\">MJ Records</span>\n </div>\n </div>\n <!-- Source fields count -->\n <div class=\"ve-info-card\">\n <div class=\"ve-info-card-icon source\">\n <i class=\"fa-solid fa-cloud\"></i>\n </div>\n <div class=\"ve-info-card-content\">\n <span class=\"ve-info-card-value\">{{ EditorSourceFields.length }}</span>\n <span class=\"ve-info-card-label\">Source Fields</span>\n </div>\n </div>\n <!-- Last sync -->\n <div class=\"ve-info-card\">\n <div class=\"ve-info-card-icon sync\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n </div>\n <div class=\"ve-info-card-content\">\n <span class=\"ve-info-card-value\">{{ FormatSyncDate(InfoLastSync?.StartedAt ?? null) }}</span>\n <span class=\"ve-info-card-label\">Last Sync</span>\n </div>\n </div>\n <!-- Sync status -->\n @if (InfoLastSync) {\n <div class=\"ve-info-card\">\n <div class=\"ve-info-card-icon\" [ngClass]=\"SyncStatusClass(InfoLastSync.Status)\">\n <i class=\"fa-solid\"\n [class.fa-circle-check]=\"InfoLastSync.Status === 'Success'\"\n [class.fa-circle-xmark]=\"InfoLastSync.Status === 'Failed'\"\n [class.fa-spinner]=\"InfoLastSync.Status === 'In Progress'\"\n [class.fa-clock]=\"InfoLastSync.Status === 'Pending'\"></i>\n </div>\n <div class=\"ve-info-card-content\">\n <span class=\"ve-info-card-value\">{{ InfoLastSync.Status }}</span>\n <span class=\"ve-info-card-label\">{{ InfoLastSync.TotalRecords }} records processed</span>\n </div>\n </div>\n }\n </div>\n\n <!-- Configuration details -->\n <div class=\"ve-info-details\">\n <div class=\"ve-info-detail-row\">\n <span class=\"ve-info-detail-label\">Sync Direction</span>\n <span class=\"ve-info-detail-value\">{{ EditorEntityMap?.SyncDirection }}</span>\n </div>\n <div class=\"ve-info-detail-row\">\n <span class=\"ve-info-detail-label\">Conflict Resolution</span>\n <span class=\"ve-info-detail-value\">{{ EditorEntityMap?.ConflictResolution }}</span>\n </div>\n <div class=\"ve-info-detail-row\">\n <span class=\"ve-info-detail-label\">Delete Behavior</span>\n <span class=\"ve-info-detail-value\">{{ EditorEntityMap?.DeleteBehavior }}</span>\n </div>\n <div class=\"ve-info-detail-row\">\n <span class=\"ve-info-detail-label\">Priority</span>\n <span class=\"ve-info-detail-value\">{{ EditorEntityMap?.Priority }}</span>\n </div>\n @if (EditorEntityMap?.MatchStrategy) {\n <div class=\"ve-info-detail-row\">\n <span class=\"ve-info-detail-label\">Match Strategy</span>\n <span class=\"ve-info-detail-value\">Configured</span>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Transform editor panel (right side, appears when connection selected) -->\n @if (SelectedConnection; as conn) {\n <div class=\"ve-transform-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"ve-tp-header\">\n <span class=\"ve-tp-title\">Mapping Details</span>\n <button class=\"ve-tp-close\" (click)=\"DeselectConnection()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <!-- Source \u2192 Dest -->\n <div class=\"ve-tp-mapping-info\">\n <div class=\"ve-tp-field-pair\">\n <span class=\"ve-tp-field source\">{{ conn.SourceFieldName }}</span>\n <i class=\"fa-solid ve-tp-arrow\"\n [class.fa-arrow-right]=\"conn.Direction === 'SourceToDest'\"\n [class.fa-arrow-left]=\"conn.Direction === 'DestToSource'\"\n [class.fa-right-left]=\"conn.Direction === 'Both'\"></i>\n <span class=\"ve-tp-field dest\">{{ conn.DestFieldName }}</span>\n </div>\n </div>\n\n <!-- Toggles -->\n <div class=\"ve-tp-toggles\">\n <label class=\"ve-tp-toggle\" (click)=\"ToggleConnectionKey()\">\n <span class=\"ve-tp-toggle-box\" [class.active]=\"conn.IsKeyField\">\n @if (conn.IsKeyField) { <i class=\"fa-solid fa-check\"></i> }\n </span>\n <span>Key Field</span>\n </label>\n <label class=\"ve-tp-toggle\" (click)=\"ToggleConnectionRequired()\">\n <span class=\"ve-tp-toggle-box\" [class.active]=\"conn.IsRequired\">\n @if (conn.IsRequired) { <i class=\"fa-solid fa-check\"></i> }\n </span>\n <span>Required</span>\n </label>\n </div>\n\n <!-- Direction -->\n <div class=\"ve-tp-section\">\n <label class=\"ve-tp-section-label\">Direction</label>\n <div class=\"ve-tp-direction-btns\">\n <button [class.active]=\"conn.Direction === 'SourceToDest'\"\n (click)=\"OnConnectionDirectionChange('SourceToDest')\">\n Source &rarr; Dest\n </button>\n <button [class.active]=\"conn.Direction === 'DestToSource'\"\n (click)=\"OnConnectionDirectionChange('DestToSource')\">\n Dest &rarr; Source\n </button>\n <button [class.active]=\"conn.Direction === 'Both'\"\n (click)=\"OnConnectionDirectionChange('Both')\">\n Both\n </button>\n </div>\n </div>\n\n <!-- Transform pipeline -->\n <div class=\"ve-tp-section\">\n <div class=\"ve-tp-section-header\">\n <label class=\"ve-tp-section-label\">Transform Pipeline</label>\n <button class=\"ve-tp-add-step\" (click)=\"AddTransformStep()\">\n <i class=\"fa-solid fa-plus\"></i> Add Step\n </button>\n </div>\n\n @for (step of conn.TransformSteps; track $index; let si = $index) {\n <div class=\"ve-tp-step\">\n <div class=\"ve-tp-step-header\">\n <span class=\"ve-tp-step-num\">{{ si + 1 }}</span>\n <select class=\"ve-tp-type-select\"\n [value]=\"step.Type\"\n (change)=\"OnConnectionTransformChange(si, $any($event.target).value)\">\n @for (tt of TRANSFORM_TYPES; track tt.Value) {\n <option [value]=\"tt.Value\" [selected]=\"tt.Value === step.Type\">{{ tt.Label }}</option>\n }\n </select>\n <button class=\"ve-tp-remove-step\" (click)=\"RemoveTransformStep(si)\" title=\"Remove step\">\n <i class=\"fa-solid fa-trash-can\"></i>\n </button>\n </div>\n\n <!-- Config fields based on transform type -->\n @if (step.Type !== 'direct') {\n <div class=\"ve-tp-step-config\">\n @for (key of GetConfigKeys(step); track key) {\n <div class=\"ve-tp-config-row\">\n <label>{{ key }}</label>\n <input type=\"text\"\n [value]=\"GetConfigValue(step, key)\"\n (input)=\"OnTransformConfigChange(conn, si, key, $any($event.target).value)\"\n placeholder=\"{{ key }}\" />\n </div>\n }\n </div>\n }\n\n <!-- On error -->\n <div class=\"ve-tp-step-onerror\">\n <label>On Error:</label>\n <select [value]=\"step.OnError\"\n (change)=\"step.OnError = $any($event.target).value; conn.IsDirty = true\">\n <option value=\"Fail\">Fail</option>\n <option value=\"Skip\">Skip</option>\n <option value=\"Null\">Null</option>\n </select>\n </div>\n </div>\n }\n\n @if (conn.TransformSteps.length === 0) {\n <div class=\"ve-tp-no-steps\">\n No transform steps. Data passes through as-is.\n </div>\n }\n </div>\n\n <!-- Delete mapping button -->\n <div class=\"ve-tp-footer\">\n <button class=\"ve-btn ve-btn-danger\" (click)=\"RemoveSelectedConnection()\">\n <i class=\"fa-solid fa-trash-can\"></i> Remove Mapping\n </button>\n </div>\n </div>\n }\n }\n </div>\n </div>\n }\n</div>\n", styles: ["/* =========================================================================\n Integration Pipelines - Card Layout + Visual Editor\n ========================================================================= */\n\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n/* ---------------------------------------------------------------------------\n Container\n --------------------------------------------------------------------------- */\n\n.pipelines-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-page);\n position: relative;\n overflow: hidden;\n}\n\n/* ---------------------------------------------------------------------------\n Toolbar\n --------------------------------------------------------------------------- */\n\n.pipelines-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 20px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n z-index: 10;\n}\n\n.toolbar-left {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.toolbar-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.toolbar-title i { color: var(--mj-color-indigo-500); }\n\n.toolbar-count-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 6px;\n border-radius: 11px;\n background: var(--mj-color-indigo-500);\n color: var(--mj-bg-surface);\n font-size: 11px;\n font-weight: 600;\n}\n\n.toolbar-map-count {\n font-size: 12px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n.toolbar-right {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.global-search {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.search-icon {\n position: absolute;\n left: 10px;\n font-size: 12px;\n color: var(--mj-text-disabled);\n pointer-events: none;\n}\n\n.search-input {\n width: 240px;\n height: 32px;\n padding: 0 12px 0 30px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-page);\n outline: none;\n transition: border-color 150ms ease, background 150ms ease;\n}\n\n.search-input:focus {\n border-color: var(--mj-color-indigo-500);\n background: var(--mj-bg-surface);\n}\n\n.search-input::placeholder { color: var(--mj-color-neutral-300); }\n\n.toolbar-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 150ms ease;\n font-size: 13px;\n}\n\n.toolbar-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-color-neutral-300);\n color: var(--mj-text-primary);\n}\n\n.toolbar-btn:active { background: var(--mj-bg-surface-active); }\n\n.toolbar-divider {\n width: 1px;\n height: 20px;\n background: var(--mj-border-default);\n margin: 0 4px;\n}\n\n/* ---------------------------------------------------------------------------\n Content area\n --------------------------------------------------------------------------- */\n\n.pipelines-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n position: relative;\n overflow: hidden;\n min-height: 0;\n}\n\n.content-loading,\n.content-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 12px;\n color: var(--mj-text-disabled);\n}\n\n.content-loading i { font-size: 28px; color: var(--mj-color-indigo-500); }\n.content-loading span { font-size: 14px; }\n.content-empty .empty-icon { font-size: 48px; color: var(--mj-color-neutral-300); }\n.content-empty h3 { margin: 0; font-size: 18px; font-weight: 600; color: var(--mj-text-muted); }\n.content-empty p { margin: 0; font-size: 13px; color: var(--mj-text-disabled); }\n\n/* ---------------------------------------------------------------------------\n Cards list\n --------------------------------------------------------------------------- */\n\n.cards-list {\n flex: 1;\n overflow-y: auto;\n padding: 16px 20px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 1200px;\n margin: 0 auto;\n width: 100%;\n box-sizing: border-box;\n min-height: 0;\n}\n\n/* ---------------------------------------------------------------------------\n Pipeline card\n --------------------------------------------------------------------------- */\n\n.pipeline-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n overflow: hidden;\n transition: box-shadow 200ms ease, border-color 200ms ease;\n}\n\n.pipeline-card:hover { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); }\n\n.pipeline-card.expanded {\n border-color: var(--mj-color-indigo-100);\n box-shadow: 0 2px 12px rgba(99, 102, 241, 0.08);\n}\n\n/* Card header */\n.card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n cursor: pointer;\n user-select: none;\n transition: background 150ms ease;\n}\n\n.card-header:hover { background: var(--mj-bg-page); }\n\n.card-header-left {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n flex: 1;\n}\n\n.card-status-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }\n\n.card-icon {\n font-size: 18px;\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n width: 24px;\n text-align: center;\n}\n\n.card-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }\n\n.card-name {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card-meta { font-size: 12px; color: var(--mj-text-disabled); }\n.meta-sep { color: var(--mj-color-neutral-300); margin: 0 2px; }\n\n.card-header-right {\n display: flex;\n align-items: center;\n gap: 14px;\n flex-shrink: 0;\n}\n\n.card-status-label { font-size: 12px; font-weight: 600; }\n.card-last-sync { font-size: 11px; color: var(--mj-text-disabled); }\n\n/* Mini flow indicator */\n.mini-flow { display: flex; align-items: center; gap: 4px; }\n.mini-flow-dot { width: 8px; height: 8px; border-radius: 50%; }\n.mini-flow-dot.source { background: var(--mj-brand-primary); }\n.mini-flow-dot.dest { background: var(--mj-color-success-600); }\n.mini-flow-line { width: 16px; height: 2px; background: var(--mj-border-default); border-radius: 1px; }\n.mini-flow-count {\n font-size: 10px; font-weight: 700; color: var(--mj-color-indigo-500);\n background: var(--mj-color-indigo-50); padding: 1px 5px; border-radius: 4px;\n}\n\n.card-chevron { font-size: 12px; color: var(--mj-text-disabled); transition: transform 200ms ease; }\n\n/* ---------------------------------------------------------------------------\n Card body (expanded entity maps)\n --------------------------------------------------------------------------- */\n\n.card-body {\n border-top: 1px solid var(--mj-border-subtle);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n /* When card is expanded, card-body takes remaining space in the cards-list scroll area.\n Limit to ~60vh so the table body scrolls internally while headers stay pinned. */\n max-height: 60vh;\n}\n\n/* Search bar within card */\n.card-search-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 18px;\n border-bottom: 1px solid var(--mj-border-subtle);\n flex-shrink: 0;\n}\n\n.card-search-icon { font-size: 11px; color: var(--mj-text-disabled); flex-shrink: 0; }\n\n.card-search-input {\n flex: 1;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n font-size: 12px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-page);\n outline: none;\n transition: border-color 150ms ease;\n}\n\n.card-search-input:focus { border-color: var(--mj-color-indigo-500); background: var(--mj-bg-surface); }\n.card-search-input::placeholder { color: var(--mj-color-neutral-300); }\n.card-search-count { font-size: 11px; color: var(--mj-text-disabled); white-space: nowrap; flex-shrink: 0; }\n\n/* Map table header */\n.map-table-head {\n display: flex;\n align-items: center;\n padding: 6px 18px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n border-bottom: 1px solid var(--mj-border-subtle);\n background: var(--mj-bg-page);\n flex-shrink: 0;\n}\n\n/* Map table body \u2014 scrolls within the constrained card-body */\n.map-table-body {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n}\n\n.map-table-empty {\n padding: 24px 18px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n}\n\n/* Map table columns */\n/* map-col-toggle width is set in the sync toggle section above */\n.map-col-source { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.map-col-direction { width: 52px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }\n.map-col-dest { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.map-col-meta { width: 80px; flex-shrink: 0; display: flex; align-items: center; justify-content: flex-end; gap: 4px; }\n\n/* Map row */\n.map-row {\n display: flex;\n align-items: center;\n padding: 8px 18px;\n font-size: 13px;\n color: var(--mj-color-neutral-700);\n cursor: pointer;\n transition: background 150ms ease;\n border-bottom: 1px solid var(--mj-bg-page);\n}\n\n.map-row:hover { background: var(--mj-color-indigo-50); }\n.map-row.sync-disabled { opacity: 0.55; }\n.map-row.sync-disabled:hover { opacity: 0.8; }\n\n/* map-status-dot removed \u2014 replaced by sync-toggle */\n\n.map-config-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 4px;\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-disabled);\n font-size: 10px;\n}\n\n.map-edit-hint {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 4px;\n color: var(--mj-color-neutral-300);\n font-size: 11px;\n transition: color 150ms ease;\n}\n\n.map-row:hover .map-edit-hint { color: var(--mj-color-indigo-500); }\n\n/* ---------------------------------------------------------------------------\n Sync toggle column\n --------------------------------------------------------------------------- */\n\n.map-col-toggle {\n width: 50px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sync-toggle {\n position: relative;\n display: inline-flex;\n align-items: center;\n cursor: pointer;\n}\n\n.sync-toggle input {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n}\n\n.sync-toggle-track {\n width: 30px;\n height: 16px;\n border-radius: 8px;\n background: var(--mj-color-neutral-300);\n position: relative;\n transition: background 200ms ease;\n}\n\n.sync-toggle-track::after {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);\n transition: transform 200ms ease;\n}\n\n.sync-toggle input:checked + .sync-toggle-track {\n background: var(--mj-color-success-600);\n}\n\n.sync-toggle input:checked + .sync-toggle-track::after {\n transform: translateX(14px);\n}\n\n/* ---------------------------------------------------------------------------\n Direction Badges\n --------------------------------------------------------------------------- */\n\n.direction-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 36px;\n height: 20px;\n padding: 0 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n flex-shrink: 0;\n}\n\n.direction-badge.pull { background: var(--mj-color-info-100); color: var(--mj-brand-primary); }\n.direction-badge.push { background: var(--mj-color-success-100); color: var(--mj-color-success-600); }\n.direction-badge.bidirectional { background: var(--mj-color-warning-100); color: var(--mj-color-warning-600); }\n\n/* =========================================================================\n VISUAL EDITOR (inline panel, replaces map list)\n ========================================================================= */\n\n.ve-container {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n background: var(--mj-bg-surface);\n animation: slideIn 250ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes slideIn {\n from { opacity: 0; transform: translateX(30px); }\n to { opacity: 1; transform: translateX(0); }\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* ---------------------------------------------------------------------------\n VE Header\n --------------------------------------------------------------------------- */\n\n.ve-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 16px;\n}\n\n.ve-header-left {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.ve-back-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 14px;\n flex-shrink: 0;\n transition: all 150ms ease;\n}\n\n.ve-back-btn:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n\n.ve-header-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 15px;\n font-weight: 600;\n min-width: 0;\n}\n\n.ve-source-label {\n color: var(--mj-color-indigo-500);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 200px;\n}\n\n.ve-direction-arrow { color: var(--mj-text-disabled); font-size: 13px; flex-shrink: 0; }\n\n.ve-dest-label {\n color: var(--mj-color-success-600);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 200px;\n}\n\n.ve-header-stats {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n}\n\n.ve-stat {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.ve-stat strong {\n color: var(--mj-text-primary);\n font-weight: 700;\n}\n\n.ve-stat-sep {\n width: 1px;\n height: 14px;\n background: var(--mj-border-default);\n}\n\n.ve-header-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.ve-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 14px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n border: none;\n white-space: nowrap;\n}\n\n.ve-btn-ghost {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n.ve-btn-ghost:hover { background: var(--mj-bg-surface-active); color: var(--mj-text-primary); }\n\n.ve-btn-primary {\n background: var(--mj-color-indigo-500);\n color: var(--mj-bg-surface);\n}\n\n.ve-btn-primary:hover { background: var(--mj-color-indigo-600); }\n.ve-btn-primary:disabled { opacity: 0.5; cursor: default; }\n\n.ve-btn-danger {\n background: var(--mj-status-error-bg);\n color: var(--mj-color-error-600);\n border: 1px solid var(--mj-color-error-200);\n}\n\n.ve-btn-danger:hover { background: var(--mj-color-error-100); }\n\n.ve-save-success {\n font-size: 12px;\n color: var(--mj-color-success-600);\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 4px;\n animation: fadeIn 300ms ease;\n}\n\n/* Sync toggle in editor header */\n.ve-sync-toggle { flex-shrink: 0; margin-left: 8px; }\n.ve-sync-label {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n/* Action separator */\n.ve-action-sep {\n width: 1px;\n height: 20px;\n background: var(--mj-border-default);\n flex-shrink: 0;\n}\n\n/* Active state for preview toggle buttons */\n.ve-btn-ghost.active {\n background: var(--mj-color-indigo-50);\n color: var(--mj-color-indigo-600);\n border-color: var(--mj-color-indigo-200);\n}\n\n/* ---------------------------------------------------------------------------\n Data Preview Strip\n --------------------------------------------------------------------------- */\n\n.ve-preview-strip {\n display: flex;\n gap: 1px;\n background: var(--mj-border-default);\n border-bottom: 1px solid var(--mj-border-default);\n max-height: 220px;\n flex-shrink: 0;\n overflow: hidden;\n}\n\n.ve-preview-panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n overflow: hidden;\n}\n\n.ve-preview-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 1px solid var(--mj-border-subtle);\n flex-shrink: 0;\n}\n\n.ve-preview-header i { font-size: 11px; color: var(--mj-color-indigo-500); }\n.ve-preview-header span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n.ve-preview-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n font-size: 11px;\n flex-shrink: 0;\n}\n\n.ve-preview-close:hover { background: var(--mj-bg-surface-active); color: var(--mj-text-secondary); }\n\n.ve-preview-loading,\n.ve-preview-empty {\n padding: 20px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.ve-preview-loading i { margin-right: 6px; color: var(--mj-color-indigo-500); }\n\n.ve-preview-table-wrap {\n flex: 1;\n overflow: auto;\n}\n\n.ve-preview-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 11px;\n}\n\n.ve-preview-table th {\n position: sticky;\n top: 0;\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-muted);\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n font-size: 10px;\n padding: 5px 10px;\n text-align: left;\n white-space: nowrap;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.ve-preview-table td {\n padding: 4px 10px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-subtle);\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.ve-preview-table tbody tr:hover td {\n background: var(--mj-color-indigo-50);\n}\n\n/* ---------------------------------------------------------------------------\n Connect mode banner\n --------------------------------------------------------------------------- */\n\n.ve-connect-banner {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 20px;\n background: var(--mj-color-indigo-50);\n color: var(--mj-color-indigo-700);\n font-size: 13px;\n border-bottom: 1px solid var(--mj-color-indigo-100);\n flex-shrink: 0;\n}\n\n.ve-connect-banner strong { font-weight: 700; }\n\n.ve-connect-cancel {\n margin-left: auto;\n padding: 3px 10px;\n border: 1px solid var(--mj-color-indigo-100);\n border-radius: 5px;\n background: var(--mj-bg-surface);\n color: var(--mj-color-indigo-700);\n font-size: 12px;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.ve-connect-cancel:hover { background: var(--mj-color-indigo-100); }\n\n/* ---------------------------------------------------------------------------\n VE Body\n --------------------------------------------------------------------------- */\n\n.ve-body {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n.ve-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 100%;\n gap: 12px;\n color: var(--mj-text-disabled);\n font-size: 14px;\n}\n\n.ve-loading i { font-size: 24px; color: var(--mj-color-indigo-500); }\n\n/* Sections wrapper (replaces ve-canvas-wrapper as the main left area) */\n.ve-sections-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-width: 0;\n}\n\n/* Collapsible section */\n.ve-section {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.ve-section:not(.collapsed) {\n flex: 1;\n min-height: 0;\n}\n\n.ve-section.collapsed {\n flex-shrink: 0;\n}\n\n.ve-section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n cursor: pointer;\n user-select: none;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-subtle);\n flex-shrink: 0;\n transition: background 150ms ease;\n}\n\n.ve-section-header:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.ve-section-header i {\n font-size: 10px;\n color: var(--mj-text-disabled);\n width: 12px;\n flex-shrink: 0;\n transition: transform 200ms ease;\n}\n\n.ve-section-title {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n color: var(--mj-text-muted);\n}\n\n.ve-section-badge {\n font-size: 10px;\n font-weight: 600;\n background: var(--mj-color-indigo-50);\n color: var(--mj-color-indigo-600);\n padding: 1px 8px;\n border-radius: 4px;\n margin-left: auto;\n}\n\n.ve-section-body {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n animation: fadeIn 200ms ease;\n}\n\n/* Canvas wrapper (takes available space, pushes transform panel right) */\n.ve-canvas-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-width: 0;\n}\n\n/* ---------------------------------------------------------------------------\n Column headers\n --------------------------------------------------------------------------- */\n\n.ve-col-headers {\n display: grid;\n grid-template-columns: 1fr 200px 1fr;\n flex-shrink: 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-col-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n}\n\n.ve-col-header.source i { color: var(--mj-color-indigo-500); }\n.ve-col-header.dest i { color: var(--mj-color-success-600); }\n.ve-col-header-spacer { /* SVG gap */ }\n\n.ve-col-count {\n font-size: 10px;\n font-weight: 600;\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-disabled);\n padding: 1px 6px;\n border-radius: 4px;\n}\n\n/* ---------------------------------------------------------------------------\n Column search bars\n --------------------------------------------------------------------------- */\n\n.ve-col-searches {\n display: grid;\n grid-template-columns: 1fr 200px 1fr;\n flex-shrink: 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n padding: 6px 0;\n}\n\n.ve-col-search {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 0 12px;\n}\n\n.ve-col-search i {\n font-size: 11px;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n}\n\n.ve-col-search input {\n flex: 1;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n font-size: 12px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-page);\n outline: none;\n transition: border-color 150ms ease;\n}\n\n.ve-col-search input:focus { border-color: var(--mj-color-indigo-500); background: var(--mj-bg-surface); }\n.ve-col-search input::placeholder { color: var(--mj-color-neutral-300); }\n.ve-col-search-spacer { /* SVG gap */ }\n\n/* ---------------------------------------------------------------------------\n Canvas scroll + grid\n --------------------------------------------------------------------------- */\n\n.ve-canvas-scroll {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.ve-canvas-grid {\n display: grid;\n grid-template-columns: 1fr 200px 1fr;\n position: relative;\n}\n\n/* ---------------------------------------------------------------------------\n Field columns\n --------------------------------------------------------------------------- */\n\n.ve-field-col {\n display: flex;\n flex-direction: column;\n}\n\n.ve-field-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 14px;\n font-size: 13px;\n cursor: pointer;\n transition: background 150ms ease, opacity 150ms ease;\n border-bottom: 1px solid var(--mj-bg-page);\n box-sizing: border-box;\n}\n\n.ve-field-item.mapped { background: var(--mj-bg-surface); }\n\n.ve-field-item.unmapped {\n opacity: 0.5;\n background: var(--mj-bg-page);\n}\n\n.ve-field-item:hover {\n background: var(--mj-color-indigo-50);\n opacity: 1;\n}\n\n.ve-field-item.connecting {\n background: var(--mj-color-indigo-100);\n opacity: 1;\n box-shadow: inset 0 0 0 2px var(--mj-color-indigo-500);\n}\n\n.ve-field-item.connect-target:hover {\n background: var(--mj-color-success-100);\n box-shadow: inset 0 0 0 2px var(--mj-color-success-600);\n}\n\n.ve-field-name {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--mj-color-neutral-700);\n font-weight: 500;\n}\n\n.ve-field-type {\n font-size: 10px;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n font-family: 'SF Mono', 'Fira Code', monospace;\n}\n\n.ve-field-badges {\n display: flex;\n gap: 3px;\n flex-shrink: 0;\n}\n\n.ve-fbadge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 3px;\n border-radius: 4px;\n font-size: 9px;\n font-weight: 700;\n}\n\n.ve-fbadge.pk { background: var(--mj-color-warning-100); color: var(--mj-color-warning-700); }\n.ve-fbadge.req { background: var(--mj-color-error-100); color: var(--mj-color-error-600); }\n\n.ve-field-empty {\n padding: 32px 16px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n}\n\n/* ---------------------------------------------------------------------------\n SVG connections\n --------------------------------------------------------------------------- */\n\n.ve-svg {\n display: block;\n}\n\n.ve-conn-line {\n fill: none;\n stroke-width: 2;\n cursor: pointer;\n transition: stroke 200ms ease, stroke-width 200ms ease;\n}\n\n/* Transform-based line styles */\n.ve-conn-line.conn-direct { stroke: #6366f1; stroke-dasharray: none; }\n.ve-conn-line.conn-regex { stroke: #8b5cf6; stroke-dasharray: 6 3; }\n.ve-conn-line.conn-split { stroke: #f59e0b; stroke-dasharray: 8 4; }\n.ve-conn-line.conn-combine { stroke: #10b981; stroke-dasharray: 8 4; }\n.ve-conn-line.conn-lookup { stroke: #0ea5e9; stroke-dasharray: 4 4; }\n.ve-conn-line.conn-format { stroke: #ec4899; stroke-dasharray: 4 4; }\n.ve-conn-line.conn-coerce { stroke: #f97316; stroke-dasharray: 4 4; }\n.ve-conn-line.conn-substring { stroke: #14b8a6; stroke-dasharray: 4 4; }\n.ve-conn-line.conn-custom { stroke: #a855f7; stroke-dasharray: 2 3; }\n\n.ve-conn-line:hover { stroke-width: 3.5; }\n.ve-conn-line.selected { stroke-width: 3.5; filter: drop-shadow(0 0 4px rgba(99, 102, 241, 0.4)); }\n\n/* Connection badge at midpoint */\n.ve-badge-fo { overflow: visible; }\n\n.ve-conn-badge {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n cursor: pointer;\n transition: all 150ms ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n}\n\n.ve-conn-badge.badge-direct { background: #eef2ff; color: #6366f1; border: 2px solid #6366f1; }\n.ve-conn-badge.badge-regex { background: #f5f3ff; color: #8b5cf6; border: 2px solid #8b5cf6; }\n.ve-conn-badge.badge-split { background: #fffbeb; color: #f59e0b; border: 2px solid #f59e0b; }\n.ve-conn-badge.badge-combine { background: #ecfdf5; color: #10b981; border: 2px solid #10b981; }\n.ve-conn-badge.badge-lookup { background: #f0f9ff; color: #0ea5e9; border: 2px solid #0ea5e9; }\n.ve-conn-badge.badge-format { background: #fdf2f8; color: #ec4899; border: 2px solid #ec4899; }\n.ve-conn-badge.badge-coerce { background: #fff7ed; color: #f97316; border: 2px solid #f97316; }\n.ve-conn-badge.badge-substring { background: #f0fdfa; color: #14b8a6; border: 2px solid #14b8a6; }\n.ve-conn-badge.badge-custom { background: #faf5ff; color: #a855f7; border: 2px solid #a855f7; }\n\n.ve-conn-badge:hover { transform: scale(1.2); }\n.ve-conn-badge.selected { transform: scale(1.25); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.3); }\n\n/* ---------------------------------------------------------------------------\n Transform Panel (right side)\n --------------------------------------------------------------------------- */\n\n.ve-transform-panel {\n width: 320px;\n flex-shrink: 0;\n border-left: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n background: var(--mj-bg-page);\n animation: slideInRight 200ms ease;\n}\n\n@keyframes slideInRight {\n from { opacity: 0; transform: translateX(20px); }\n to { opacity: 1; transform: translateX(0); }\n}\n\n.ve-tp-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.ve-tp-title {\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.ve-tp-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n font-size: 13px;\n transition: all 150ms ease;\n}\n\n.ve-tp-close:hover { background: var(--mj-bg-surface-active); color: var(--mj-text-secondary); }\n\n/* Mapping info */\n.ve-tp-mapping-info {\n padding: 14px 16px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-tp-field-pair {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.ve-tp-field {\n padding: 4px 10px;\n border-radius: 6px;\n font-weight: 600;\n font-size: 12px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 110px;\n}\n\n.ve-tp-field.source { background: var(--mj-color-indigo-50); color: var(--mj-color-indigo-700); }\n.ve-tp-field.dest { background: var(--mj-status-success-bg); color: var(--mj-color-success-700); }\n.ve-tp-arrow { color: var(--mj-text-disabled); font-size: 11px; flex-shrink: 0; }\n\n/* Toggles */\n.ve-tp-toggles {\n display: flex;\n gap: 16px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-tp-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.ve-tp-toggle-box {\n width: 18px;\n height: 18px;\n border: 2px solid var(--mj-color-neutral-300);\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n color: var(--mj-bg-surface);\n transition: all 150ms ease;\n}\n\n.ve-tp-toggle-box.active {\n background: var(--mj-color-indigo-500);\n border-color: var(--mj-color-indigo-500);\n}\n\n/* Sections */\n.ve-tp-section {\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-tp-section-label {\n display: block;\n font-size: 10px;\n font-weight: 700;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n margin-bottom: 8px;\n}\n\n.ve-tp-section-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n/* Direction buttons */\n.ve-tp-direction-btns {\n display: flex;\n gap: 0;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.ve-tp-direction-btns button {\n flex: 1;\n padding: 6px 8px;\n border: none;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n border-right: 1px solid var(--mj-border-default);\n}\n\n.ve-tp-direction-btns button:last-child { border-right: none; }\n.ve-tp-direction-btns button:hover { background: var(--mj-bg-surface-hover); }\n.ve-tp-direction-btns button.active { background: var(--mj-color-indigo-500); color: var(--mj-bg-surface); }\n\n/* Transform steps */\n.ve-tp-add-step {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n font-size: 11px;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.ve-tp-add-step:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n\n.ve-tp-step {\n margin-top: 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n overflow: hidden;\n}\n\n.ve-tp-step-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-tp-step-num {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: var(--mj-color-indigo-500);\n color: var(--mj-bg-surface);\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.ve-tp-type-select {\n flex: 1;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n font-size: 12px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-surface);\n outline: none;\n cursor: pointer;\n}\n\n.ve-tp-type-select:focus { border-color: var(--mj-color-indigo-500); }\n\n.ve-tp-remove-step {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 5px;\n background: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n font-size: 11px;\n transition: all 150ms ease;\n flex-shrink: 0;\n}\n\n.ve-tp-remove-step:hover { background: var(--mj-color-error-100); color: var(--mj-color-error-600); }\n\n.ve-tp-step-config {\n padding: 8px 10px;\n}\n\n.ve-tp-config-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n}\n\n.ve-tp-config-row:last-child { margin-bottom: 0; }\n\n.ve-tp-config-row label {\n width: 80px;\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.ve-tp-config-row input {\n flex: 1;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n font-size: 12px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-page);\n outline: none;\n font-family: 'SF Mono', 'Fira Code', monospace;\n}\n\n.ve-tp-config-row input:focus { border-color: var(--mj-color-indigo-500); background: var(--mj-bg-surface); }\n\n.ve-tp-step-onerror {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n border-top: 1px solid var(--mj-border-subtle);\n background: var(--mj-bg-page);\n}\n\n.ve-tp-step-onerror label {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n}\n\n.ve-tp-step-onerror select {\n height: 24px;\n padding: 0 6px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 11px;\n color: var(--mj-color-neutral-700);\n background: var(--mj-bg-surface);\n outline: none;\n cursor: pointer;\n}\n\n.ve-tp-no-steps {\n padding: 16px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 12px;\n font-style: italic;\n}\n\n/* Footer */\n.ve-tp-footer {\n padding: 14px 16px;\n margin-top: auto;\n flex-shrink: 0;\n}\n\n/* ---------------------------------------------------------------------------\n Scrollbar styling\n --------------------------------------------------------------------------- */\n\n.cards-list::-webkit-scrollbar,\n.map-table-body::-webkit-scrollbar,\n.ve-canvas-scroll::-webkit-scrollbar,\n.ve-transform-panel::-webkit-scrollbar {\n width: 6px;\n height: 6px;\n}\n\n.cards-list::-webkit-scrollbar-track,\n.map-table-body::-webkit-scrollbar-track,\n.ve-canvas-scroll::-webkit-scrollbar-track,\n.ve-transform-panel::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.cards-list::-webkit-scrollbar-thumb,\n.map-table-body::-webkit-scrollbar-thumb,\n.ve-canvas-scroll::-webkit-scrollbar-thumb,\n.ve-transform-panel::-webkit-scrollbar-thumb {\n background: var(--mj-color-neutral-300);\n border-radius: 3px;\n}\n\n.cards-list::-webkit-scrollbar-thumb:hover,\n.map-table-body::-webkit-scrollbar-thumb:hover,\n.ve-canvas-scroll::-webkit-scrollbar-thumb:hover,\n.ve-transform-panel::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n/* ---------------------------------------------------------------------------\n Info Panel\n --------------------------------------------------------------------------- */\n\n.ve-info-body {\n padding: 16px;\n overflow-y: auto;\n}\n\n.ve-info-loading {\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n padding: 20px;\n}\n\n.ve-info-loading i {\n color: var(--mj-color-indigo-500);\n margin-right: 6px;\n}\n\n.ve-info-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n gap: 12px;\n margin-bottom: 16px;\n}\n\n.ve-info-card {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 14px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n}\n\n.ve-info-card-icon {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n flex-shrink: 0;\n background: var(--mj-color-indigo-50);\n color: var(--mj-color-indigo-500);\n}\n\n.ve-info-card-icon.source {\n background: var(--mj-color-info-100);\n color: var(--mj-brand-primary);\n}\n\n.ve-info-card-icon.sync {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-600);\n}\n\n.ve-info-card-icon.info-status-success {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-600);\n}\n\n.ve-info-card-icon.info-status-error {\n background: var(--mj-color-error-100);\n color: var(--mj-color-error-600);\n}\n\n.ve-info-card-icon.info-status-running {\n background: var(--mj-color-info-100);\n color: var(--mj-brand-primary);\n}\n\n.ve-info-card-icon.info-status-pending {\n background: var(--mj-color-warning-100);\n color: var(--mj-color-warning-600);\n}\n\n.ve-info-card-content {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.ve-info-card-value {\n font-size: 16px;\n font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.ve-info-card-label {\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n.ve-info-details {\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.ve-info-detail-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px;\n font-size: 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.ve-info-detail-row:last-child {\n border-bottom: none;\n}\n\n.ve-info-detail-label {\n color: var(--mj-text-muted);\n font-weight: 500;\n}\n\n.ve-info-detail-value {\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n"] }]
2051
+ }], null, null); })();
2052
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PipelinesComponent, { className: "PipelinesComponent", filePath: "src/Integration/components/pipelines/pipelines.component.ts", lineNumber: 80 }); })();
2053
+ export function LoadPipelinesComponent() {
2054
+ // Tree-shaking prevention: importing this module causes
2055
+ // @RegisterClass decorators to fire, registering components.
2056
+ }
2057
+ //# sourceMappingURL=pipelines.component.js.map