@memberjunction/ng-dashboards 2.88.0 → 2.89.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.
@@ -4,230 +4,291 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
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
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Component } from '@angular/core';
7
+ import { Component, ViewChild } from '@angular/core';
8
8
  import { BaseDashboard } from '../generic/base-dashboard';
9
9
  import { RegisterClass } from '@memberjunction/global';
10
10
  import { RunView } from '@memberjunction/core';
11
11
  import { Subject } from 'rxjs';
12
12
  import { SharedService } from '@memberjunction/ng-shared';
13
+ import { ParseJSONRecursive } from '@memberjunction/global';
13
14
  import * as i0 from "@angular/core";
14
15
  import * as i1 from "@angular/common";
15
- import * as i2 from "@progress/kendo-angular-inputs";
16
- import * as i3 from "@progress/kendo-angular-layout";
17
- import * as i4 from "@progress/kendo-angular-buttons";
18
- import * as i5 from "@memberjunction/ng-react";
19
- const _forTrack0 = ($index, $item) => $item.ID;
20
- function ComponentStudioDashboardComponent_ng_template_20_Template(rf, ctx) { if (rf & 1) {
21
- i0.ɵɵelement(0, "i", 20);
22
- } }
23
- function ComponentStudioDashboardComponent_Conditional_22_Template(rf, ctx) { if (rf & 1) {
24
- i0.ɵɵelementStart(0, "div", 15);
25
- i0.ɵɵelement(1, "i", 21);
16
+ import * as i2 from "@angular/forms";
17
+ import * as i3 from "@progress/kendo-angular-inputs";
18
+ import * as i4 from "@progress/kendo-angular-layout";
19
+ import * as i5 from "@memberjunction/ng-code-editor";
20
+ import * as i6 from "@progress/kendo-angular-buttons";
21
+ import * as i7 from "@memberjunction/ng-react";
22
+ const _c0 = ["fileInput"];
23
+ function _forTrack0($index, $item) { return this.getComponentId($item); }
24
+ const _forTrack1 = ($index, $item) => $item.title;
25
+ function ComponentStudioDashboardComponent_Conditional_10_Conditional_1_Template(rf, ctx) { if (rf & 1) {
26
+ i0.ɵɵelement(0, "span", 27);
27
+ i0.ɵɵtext(1, " Show Details ");
28
+ } }
29
+ function ComponentStudioDashboardComponent_Conditional_10_Conditional_2_Template(rf, ctx) { if (rf & 1) {
30
+ i0.ɵɵelement(0, "span", 28);
31
+ i0.ɵɵtext(1, " Hide Details ");
32
+ } }
33
+ function ComponentStudioDashboardComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
34
+ const _r2 = i0.ɵɵgetCurrentView();
35
+ i0.ɵɵelementStart(0, "button", 8);
36
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleDetailsPane()); });
37
+ i0.ɵɵtemplate(1, ComponentStudioDashboardComponent_Conditional_10_Conditional_1_Template, 2, 0)(2, ComponentStudioDashboardComponent_Conditional_10_Conditional_2_Template, 2, 0);
38
+ i0.ɵɵelementEnd();
39
+ } if (rf & 2) {
40
+ const ctx_r2 = i0.ɵɵnextContext();
41
+ i0.ɵɵproperty("themeColor", "base");
42
+ i0.ɵɵadvance();
43
+ i0.ɵɵconditional(ctx_r2.isDetailsPaneCollapsed ? 1 : 2);
44
+ } }
45
+ function ComponentStudioDashboardComponent_ng_template_27_Template(rf, ctx) { if (rf & 1) {
46
+ i0.ɵɵelement(0, "i", 29);
47
+ } }
48
+ function ComponentStudioDashboardComponent_Conditional_29_Template(rf, ctx) { if (rf & 1) {
49
+ i0.ɵɵelementStart(0, "div", 21);
50
+ i0.ɵɵelement(1, "i", 30);
26
51
  i0.ɵɵtext(2, " Loading components... ");
27
52
  i0.ɵɵelementEnd();
28
53
  } }
29
- function ComponentStudioDashboardComponent_Conditional_23_Template(rf, ctx) { if (rf & 1) {
30
- i0.ɵɵelementStart(0, "div", 16);
31
- i0.ɵɵelement(1, "i", 22);
54
+ function ComponentStudioDashboardComponent_Conditional_30_Template(rf, ctx) { if (rf & 1) {
55
+ i0.ɵɵelementStart(0, "div", 22);
56
+ i0.ɵɵelement(1, "i", 31);
32
57
  i0.ɵɵtext(2, " No components found without custom properties. ");
33
58
  i0.ɵɵelement(3, "br");
34
59
  i0.ɵɵelementStart(4, "small");
35
60
  i0.ɵɵtext(5, "Only components that don't require custom props can be tested here.");
36
61
  i0.ɵɵelementEnd()();
37
62
  } }
38
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_12_Template(rf, ctx) { if (rf & 1) {
39
- i0.ɵɵelementStart(0, "span", 33);
63
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_7_Template(rf, ctx) { if (rf & 1) {
64
+ i0.ɵɵelementStart(0, "span", 39);
65
+ i0.ɵɵelement(1, "i", 50);
66
+ i0.ɵɵtext(2);
67
+ i0.ɵɵelementEnd();
68
+ } if (rf & 2) {
69
+ const component_r5 = i0.ɵɵnextContext().$implicit;
70
+ const ctx_r2 = i0.ɵɵnextContext(2);
71
+ i0.ɵɵpropertyInterpolate1("title", "Loaded from ", ctx_r2.getComponentFilename(component_r5), "");
72
+ i0.ɵɵadvance(2);
73
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.getComponentFilename(component_r5), " ");
74
+ } }
75
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_13_Template(rf, ctx) { if (rf & 1) {
76
+ i0.ɵɵelementStart(0, "span", 43);
77
+ i0.ɵɵtext(1, "File");
78
+ i0.ɵɵelementEnd();
79
+ } }
80
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_14_Template(rf, ctx) { if (rf & 1) {
81
+ i0.ɵɵelementStart(0, "span", 44);
40
82
  i0.ɵɵtext(1, "Published");
41
83
  i0.ɵɵelementEnd();
42
84
  } }
43
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_13_Template(rf, ctx) { if (rf & 1) {
44
- i0.ɵɵelementStart(0, "span", 34);
85
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_15_Template(rf, ctx) { if (rf & 1) {
86
+ i0.ɵɵelementStart(0, "span", 45);
45
87
  i0.ɵɵtext(1, "Draft");
46
88
  i0.ɵɵelementEnd();
47
89
  } }
48
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_15_Template(rf, ctx) { if (rf & 1) {
49
- i0.ɵɵelement(0, "i", 36);
90
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_17_Template(rf, ctx) { if (rf & 1) {
91
+ i0.ɵɵelement(0, "i", 47);
50
92
  } }
51
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_16_Template(rf, ctx) { if (rf & 1) {
52
- i0.ɵɵelement(0, "i", 37);
93
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_18_Template(rf, ctx) { if (rf & 1) {
94
+ i0.ɵɵelement(0, "i", 48);
53
95
  } }
54
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_1_Template(rf, ctx) { if (rf & 1) {
55
- i0.ɵɵelementStart(0, "div", 39)(1, "label");
96
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
97
+ i0.ɵɵelementStart(0, "div", 51)(1, "label");
56
98
  i0.ɵɵtext(2, "Description");
57
99
  i0.ɵɵelementEnd();
58
100
  i0.ɵɵelementStart(3, "p");
59
101
  i0.ɵɵtext(4);
60
102
  i0.ɵɵelementEnd()();
61
103
  } if (rf & 2) {
62
- const component_r2 = i0.ɵɵnextContext(2).$implicit;
104
+ const component_r5 = i0.ɵɵnextContext(2).$implicit;
105
+ const ctx_r2 = i0.ɵɵnextContext(2);
106
+ i0.ɵɵadvance(4);
107
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentDescription(component_r5));
108
+ } }
109
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_21_Template(rf, ctx) { if (rf & 1) {
110
+ i0.ɵɵelementStart(0, "div", 53)(1, "span", 54);
111
+ i0.ɵɵtext(2, "Loaded:");
112
+ i0.ɵɵelementEnd();
113
+ i0.ɵɵelementStart(3, "span", 55);
114
+ i0.ɵɵtext(4);
115
+ i0.ɵɵpipe(5, "date");
116
+ i0.ɵɵelementEnd()();
117
+ } if (rf & 2) {
118
+ const component_r5 = i0.ɵɵnextContext(2).$implicit;
119
+ const ctx_r2 = i0.ɵɵnextContext(2);
63
120
  i0.ɵɵadvance(4);
64
- i0.ɵɵtextInterpolate(component_r2.Description);
121
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 1, ctx_r2.getComponentLoadedAt(component_r5), "short"));
65
122
  } }
66
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_21_Template(rf, ctx) { if (rf & 1) {
67
- i0.ɵɵelementStart(0, "div", 41)(1, "span", 42);
123
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_22_Template(rf, ctx) { if (rf & 1) {
124
+ i0.ɵɵelementStart(0, "div", 53)(1, "span", 54);
68
125
  i0.ɵɵtext(2, "Updated:");
69
126
  i0.ɵɵelementEnd();
70
- i0.ɵɵelementStart(3, "span", 43);
127
+ i0.ɵɵelementStart(3, "span", 55);
71
128
  i0.ɵɵtext(4);
72
129
  i0.ɵɵpipe(5, "date");
73
130
  i0.ɵɵelementEnd()();
74
131
  } if (rf & 2) {
75
- const component_r2 = i0.ɵɵnextContext(2).$implicit;
132
+ const component_r5 = i0.ɵɵnextContext(2).$implicit;
133
+ const ctx_r2 = i0.ɵɵnextContext(2);
76
134
  i0.ɵɵadvance(4);
77
- i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 1, component_r2.__mj_UpdatedAt, "short"));
135
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 1, ctx_r2.getComponentUpdatedAt(component_r5), "short"));
78
136
  } }
79
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_23_Template(rf, ctx) { if (rf & 1) {
80
- const _r4 = i0.ɵɵgetCurrentView();
81
- i0.ɵɵelementStart(0, "button", 47);
82
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_23_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(4); ctx_r2.stopComponent(); return i0.ɵɵresetView($event.stopPropagation()); });
83
- i0.ɵɵelement(1, "span", 48);
137
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_24_Template(rf, ctx) { if (rf & 1) {
138
+ const _r6 = i0.ɵɵgetCurrentView();
139
+ i0.ɵɵelementStart(0, "button", 8);
140
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_24_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(4); ctx_r2.stopComponent(); return i0.ɵɵresetView($event.stopPropagation()); });
141
+ i0.ɵɵelement(1, "span", 58);
84
142
  i0.ɵɵtext(2, " Stop Component ");
85
143
  i0.ɵɵelementEnd();
86
144
  } if (rf & 2) {
87
145
  i0.ɵɵproperty("themeColor", "error");
88
146
  } }
89
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_24_Template(rf, ctx) { if (rf & 1) {
90
- const _r5 = i0.ɵɵgetCurrentView();
91
- i0.ɵɵelementStart(0, "button", 49);
92
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_24_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r5); const component_r2 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.runComponent(component_r2); return i0.ɵɵresetView($event.stopPropagation()); });
93
- i0.ɵɵelement(1, "span", 50);
147
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_25_Template(rf, ctx) { if (rf & 1) {
148
+ const _r7 = i0.ɵɵgetCurrentView();
149
+ i0.ɵɵelementStart(0, "button", 59);
150
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_25_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r7); const component_r5 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.runComponent(component_r5); return i0.ɵɵresetView($event.stopPropagation()); });
151
+ i0.ɵɵelement(1, "span", 60);
94
152
  i0.ɵɵtext(2, " Switch to This Component ");
95
153
  i0.ɵɵelementEnd();
96
154
  } if (rf & 2) {
97
155
  i0.ɵɵproperty("themeColor", "base");
98
156
  } }
99
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_25_Template(rf, ctx) { if (rf & 1) {
100
- const _r6 = i0.ɵɵgetCurrentView();
101
- i0.ɵɵelementStart(0, "button", 47);
102
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_25_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r6); const component_r2 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.runComponent(component_r2); return i0.ɵɵresetView($event.stopPropagation()); });
103
- i0.ɵɵelement(1, "span", 50);
157
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_26_Template(rf, ctx) { if (rf & 1) {
158
+ const _r8 = i0.ɵɵgetCurrentView();
159
+ i0.ɵɵelementStart(0, "button", 8);
160
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_26_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r8); const component_r5 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.runComponent(component_r5); return i0.ɵɵresetView($event.stopPropagation()); });
161
+ i0.ɵɵelement(1, "span", 60);
104
162
  i0.ɵɵtext(2, " Run Component ");
105
163
  i0.ɵɵelementEnd();
106
164
  } if (rf & 2) {
107
165
  i0.ɵɵproperty("themeColor", "primary");
108
166
  } }
109
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Template(rf, ctx) { if (rf & 1) {
110
- i0.ɵɵelementStart(0, "div", 38);
111
- i0.ɵɵtemplate(1, ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_1_Template, 5, 1, "div", 39);
112
- i0.ɵɵelementStart(2, "div", 39)(3, "label");
167
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Template(rf, ctx) { if (rf & 1) {
168
+ i0.ɵɵelementStart(0, "div", 49);
169
+ i0.ɵɵtemplate(1, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_1_Template, 5, 1, "div", 51);
170
+ i0.ɵɵelementStart(2, "div", 51)(3, "label");
113
171
  i0.ɵɵtext(4, "Component Info");
114
172
  i0.ɵɵelementEnd();
115
- i0.ɵɵelementStart(5, "div", 40)(6, "div", 41)(7, "span", 42);
173
+ i0.ɵɵelementStart(5, "div", 52)(6, "div", 53)(7, "span", 54);
116
174
  i0.ɵɵtext(8, "Type:");
117
175
  i0.ɵɵelementEnd();
118
- i0.ɵɵelementStart(9, "span", 43);
176
+ i0.ɵɵelementStart(9, "span", 55);
119
177
  i0.ɵɵtext(10);
120
178
  i0.ɵɵelementEnd()();
121
- i0.ɵɵelementStart(11, "div", 41)(12, "span", 42);
179
+ i0.ɵɵelementStart(11, "div", 53)(12, "span", 54);
122
180
  i0.ɵɵtext(13, "Version:");
123
181
  i0.ɵɵelementEnd();
124
- i0.ɵɵelementStart(14, "span", 43);
182
+ i0.ɵɵelementStart(14, "span", 55);
125
183
  i0.ɵɵtext(15);
126
184
  i0.ɵɵelementEnd()();
127
- i0.ɵɵelementStart(16, "div", 41)(17, "span", 42);
185
+ i0.ɵɵelementStart(16, "div", 53)(17, "span", 54);
128
186
  i0.ɵɵtext(18, "Status:");
129
187
  i0.ɵɵelementEnd();
130
- i0.ɵɵelementStart(19, "span", 43);
188
+ i0.ɵɵelementStart(19, "span", 55);
131
189
  i0.ɵɵtext(20);
132
190
  i0.ɵɵelementEnd()();
133
- i0.ɵɵtemplate(21, ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_21_Template, 6, 4, "div", 41);
191
+ i0.ɵɵtemplate(21, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_21_Template, 6, 4, "div", 53)(22, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_22_Template, 6, 4, "div", 53);
134
192
  i0.ɵɵelementEnd()();
135
- i0.ɵɵelementStart(22, "div", 44);
136
- i0.ɵɵtemplate(23, ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_23_Template, 3, 1, "button", 45)(24, ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_24_Template, 3, 1, "button", 46)(25, ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Conditional_25_Template, 3, 1, "button", 45);
193
+ i0.ɵɵelementStart(23, "div", 56);
194
+ i0.ɵɵtemplate(24, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_24_Template, 3, 1, "button", 7)(25, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_25_Template, 3, 1, "button", 57)(26, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_26_Template, 3, 1, "button", 7);
137
195
  i0.ɵɵelementEnd()();
138
196
  } if (rf & 2) {
139
- const component_r2 = i0.ɵɵnextContext().$implicit;
197
+ const component_r5 = i0.ɵɵnextContext().$implicit;
140
198
  const ctx_r2 = i0.ɵɵnextContext(2);
141
199
  i0.ɵɵadvance();
142
- i0.ɵɵconditional(component_r2.Description ? 1 : -1);
200
+ i0.ɵɵconditional(ctx_r2.getComponentDescription(component_r5) ? 1 : -1);
143
201
  i0.ɵɵadvance(9);
144
- i0.ɵɵtextInterpolate(component_r2.Type || "Unknown");
202
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentType(component_r5) || "Unknown");
145
203
  i0.ɵɵadvance(5);
146
- i0.ɵɵtextInterpolate(component_r2.Version || "1.0.0");
204
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentVersion(component_r5));
147
205
  i0.ɵɵadvance(5);
148
- i0.ɵɵtextInterpolate(component_r2.Status || "Draft");
206
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentStatus(component_r5) || "Draft");
149
207
  i0.ɵɵadvance();
150
- i0.ɵɵconditional(component_r2.__mj_UpdatedAt ? 21 : -1);
151
- i0.ɵɵadvance(2);
152
- i0.ɵɵconditional((ctx_r2.selectedComponent == null ? null : ctx_r2.selectedComponent.ID) === component_r2.ID && ctx_r2.isRunning ? 23 : ctx_r2.isRunning && (ctx_r2.selectedComponent == null ? null : ctx_r2.selectedComponent.ID) !== component_r2.ID ? 24 : 25);
208
+ i0.ɵɵconditional(ctx_r2.isFileLoadedComponent(component_r5) ? 21 : !ctx_r2.isFileLoadedComponent(component_r5) && ctx_r2.getComponentUpdatedAt(component_r5) ? 22 : -1);
209
+ i0.ɵɵadvance(3);
210
+ i0.ɵɵconditional(ctx_r2.selectedComponent && ctx_r2.getComponentId(ctx_r2.selectedComponent) === ctx_r2.getComponentId(component_r5) && ctx_r2.isRunning ? 24 : ctx_r2.isRunning && ctx_r2.selectedComponent && ctx_r2.getComponentId(ctx_r2.selectedComponent) !== ctx_r2.getComponentId(component_r5) ? 25 : 26);
153
211
  } }
154
- function ComponentStudioDashboardComponent_Conditional_24_For_1_Template(rf, ctx) { if (rf & 1) {
155
- const _r1 = i0.ɵɵgetCurrentView();
156
- i0.ɵɵelementStart(0, "div", 24)(1, "div", 25);
157
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_24_For_1_Template_div_click_1_listener() { const component_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.toggleComponentExpansion(component_r2)); });
158
- i0.ɵɵelementStart(2, "div", 26);
159
- i0.ɵɵelement(3, "i", 27);
212
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Template(rf, ctx) { if (rf & 1) {
213
+ const _r4 = i0.ɵɵgetCurrentView();
214
+ i0.ɵɵelementStart(0, "div", 33)(1, "div", 34);
215
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_31_For_1_Template_div_click_1_listener() { const component_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.toggleComponentExpansion(component_r5)); });
216
+ i0.ɵɵelementStart(2, "div", 35);
217
+ i0.ɵɵelement(3, "i", 36);
160
218
  i0.ɵɵelementEnd();
161
- i0.ɵɵelementStart(4, "div", 28)(5, "div", 29);
219
+ i0.ɵɵelementStart(4, "div", 37)(5, "div", 38);
162
220
  i0.ɵɵtext(6);
221
+ i0.ɵɵtemplate(7, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_7_Template, 3, 3, "span", 39);
163
222
  i0.ɵɵelementEnd();
164
- i0.ɵɵelementStart(7, "div", 30)(8, "span", 31);
165
- i0.ɵɵtext(9);
223
+ i0.ɵɵelementStart(8, "div", 40)(9, "span", 41);
224
+ i0.ɵɵtext(10);
166
225
  i0.ɵɵelementEnd();
167
- i0.ɵɵelementStart(10, "span", 32);
168
- i0.ɵɵtext(11);
226
+ i0.ɵɵelementStart(11, "span", 42);
227
+ i0.ɵɵtext(12);
169
228
  i0.ɵɵelementEnd();
170
- i0.ɵɵtemplate(12, ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_12_Template, 2, 0, "span", 33)(13, ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_13_Template, 2, 0, "span", 34);
229
+ i0.ɵɵtemplate(13, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_13_Template, 2, 0, "span", 43)(14, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_14_Template, 2, 0, "span", 44)(15, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_15_Template, 2, 0, "span", 45);
171
230
  i0.ɵɵelementEnd()();
172
- i0.ɵɵelementStart(14, "div", 35);
173
- i0.ɵɵtemplate(15, ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_15_Template, 1, 0, "i", 36)(16, ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_16_Template, 1, 0, "i", 37);
231
+ i0.ɵɵelementStart(16, "div", 46);
232
+ i0.ɵɵtemplate(17, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_17_Template, 1, 0, "i", 47)(18, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_18_Template, 1, 0, "i", 48);
174
233
  i0.ɵɵelementEnd()();
175
- i0.ɵɵtemplate(17, ComponentStudioDashboardComponent_Conditional_24_For_1_Conditional_17_Template, 26, 6, "div", 38);
234
+ i0.ɵɵtemplate(19, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Template, 27, 6, "div", 49);
176
235
  i0.ɵɵelementEnd();
177
236
  } if (rf & 2) {
178
- const component_r2 = ctx.$implicit;
237
+ const component_r5 = ctx.$implicit;
179
238
  const ctx_r2 = i0.ɵɵnextContext(2);
180
- i0.ɵɵclassProp("expanded", (ctx_r2.expandedComponent == null ? null : ctx_r2.expandedComponent.ID) === component_r2.ID)("running", (ctx_r2.selectedComponent == null ? null : ctx_r2.selectedComponent.ID) === component_r2.ID && ctx_r2.isRunning);
239
+ i0.ɵɵclassProp("expanded", ctx_r2.expandedComponent && ctx_r2.getComponentId(ctx_r2.expandedComponent) === ctx_r2.getComponentId(component_r5))("running", ctx_r2.selectedComponent && ctx_r2.getComponentId(ctx_r2.selectedComponent) === ctx_r2.getComponentId(component_r5) && ctx_r2.isRunning)("file-loaded", ctx_r2.isFileLoadedComponent(component_r5));
181
240
  i0.ɵɵadvance(2);
182
- i0.ɵɵstyleProp("color", ctx_r2.getComponentTypeColor(component_r2.Type));
241
+ i0.ɵɵstyleProp("color", ctx_r2.getComponentTypeColor(ctx_r2.getComponentType(component_r5)));
183
242
  i0.ɵɵadvance();
184
- i0.ɵɵproperty("ngClass", ctx_r2.getComponentTypeIcon(component_r2.Type));
243
+ i0.ɵɵproperty("ngClass", ctx_r2.getComponentTypeIcon(ctx_r2.getComponentType(component_r5)));
185
244
  i0.ɵɵadvance(3);
186
- i0.ɵɵtextInterpolate(component_r2.Name);
245
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.getComponentName(component_r5), " ");
246
+ i0.ɵɵadvance();
247
+ i0.ɵɵconditional(ctx_r2.isFileLoadedComponent(component_r5) ? 7 : -1);
187
248
  i0.ɵɵadvance(3);
188
- i0.ɵɵtextInterpolate(component_r2.Type || "Component");
249
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentType(component_r5) || "Component");
189
250
  i0.ɵɵadvance(2);
190
- i0.ɵɵtextInterpolate1("v", component_r2.Version || "1.0.0", "");
251
+ i0.ɵɵtextInterpolate1("v", ctx_r2.getComponentVersion(component_r5), "");
191
252
  i0.ɵɵadvance();
192
- i0.ɵɵconditional(component_r2.Status === "Published" ? 12 : 13);
193
- i0.ɵɵadvance(3);
194
- i0.ɵɵconditional((ctx_r2.expandedComponent == null ? null : ctx_r2.expandedComponent.ID) === component_r2.ID ? 15 : 16);
253
+ i0.ɵɵconditional(ctx_r2.isFileLoadedComponent(component_r5) ? 13 : ctx_r2.getComponentStatus(component_r5) === "Published" ? 14 : 15);
254
+ i0.ɵɵadvance(4);
255
+ i0.ɵɵconditional(ctx_r2.expandedComponent && ctx_r2.getComponentId(ctx_r2.expandedComponent) === ctx_r2.getComponentId(component_r5) ? 17 : 18);
195
256
  i0.ɵɵadvance(2);
196
- i0.ɵɵconditional((ctx_r2.expandedComponent == null ? null : ctx_r2.expandedComponent.ID) === component_r2.ID ? 17 : -1);
257
+ i0.ɵɵconditional(ctx_r2.expandedComponent && ctx_r2.getComponentId(ctx_r2.expandedComponent) === ctx_r2.getComponentId(component_r5) ? 19 : -1);
197
258
  } }
198
- function ComponentStudioDashboardComponent_Conditional_24_Template(rf, ctx) { if (rf & 1) {
199
- i0.ɵɵrepeaterCreate(0, ComponentStudioDashboardComponent_Conditional_24_For_1_Template, 18, 13, "div", 23, _forTrack0);
259
+ function ComponentStudioDashboardComponent_Conditional_31_Template(rf, ctx) { if (rf & 1) {
260
+ i0.ɵɵrepeaterCreate(0, ComponentStudioDashboardComponent_Conditional_31_For_1_Template, 20, 16, "div", 32, _forTrack0, true);
200
261
  } if (rf & 2) {
201
262
  const ctx_r2 = i0.ɵɵnextContext();
202
263
  i0.ɵɵrepeater(ctx_r2.filteredComponents);
203
264
  } }
204
- function ComponentStudioDashboardComponent_Conditional_27_Conditional_0_Conditional_18_Template(rf, ctx) { if (rf & 1) {
205
- i0.ɵɵelementStart(0, "details", 60)(1, "summary");
265
+ function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Conditional_18_Template(rf, ctx) { if (rf & 1) {
266
+ i0.ɵɵelementStart(0, "details", 77)(1, "summary");
206
267
  i0.ɵɵtext(2, "Technical Details (click to expand)");
207
268
  i0.ɵɵelementEnd();
208
269
  i0.ɵɵelementStart(3, "pre");
209
270
  i0.ɵɵtext(4);
210
271
  i0.ɵɵelementEnd()();
211
272
  } if (rf & 2) {
212
- const ctx_r2 = i0.ɵɵnextContext(3);
273
+ const ctx_r2 = i0.ɵɵnextContext(4);
213
274
  i0.ɵɵadvance(4);
214
275
  i0.ɵɵtextInterpolate(ctx_r2.formatTechnicalDetails(ctx_r2.currentError.technicalDetails));
215
276
  } }
216
- function ComponentStudioDashboardComponent_Conditional_27_Conditional_0_Template(rf, ctx) { if (rf & 1) {
217
- const _r7 = i0.ɵɵgetCurrentView();
218
- i0.ɵɵelementStart(0, "div", 51)(1, "div", 53)(2, "div", 54);
219
- i0.ɵɵelement(3, "i", 55);
277
+ function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
278
+ const _r10 = i0.ɵɵgetCurrentView();
279
+ i0.ɵɵelementStart(0, "div", 68)(1, "div", 70)(2, "div", 71);
280
+ i0.ɵɵelement(3, "i", 72);
220
281
  i0.ɵɵelementStart(4, "h3");
221
282
  i0.ɵɵtext(5, "Component Error");
222
283
  i0.ɵɵelementEnd();
223
- i0.ɵɵelementStart(6, "button", 56);
224
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_27_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.copyErrorToClipboard()); });
225
- i0.ɵɵelement(7, "i", 57);
284
+ i0.ɵɵelementStart(6, "button", 73);
285
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.copyErrorToClipboard()); });
286
+ i0.ɵɵelement(7, "i", 74);
226
287
  i0.ɵɵelementEnd()();
227
- i0.ɵɵelementStart(8, "p", 58);
288
+ i0.ɵɵelementStart(8, "p", 75);
228
289
  i0.ɵɵtext(9, " The component could not be rendered due to the following error: ");
229
290
  i0.ɵɵelementEnd();
230
- i0.ɵɵelementStart(10, "div", 59)(11, "strong");
291
+ i0.ɵɵelementStart(10, "div", 76)(11, "strong");
231
292
  i0.ɵɵtext(12, "Error Type:");
232
293
  i0.ɵɵelementEnd();
233
294
  i0.ɵɵtext(13);
@@ -236,9 +297,9 @@ function ComponentStudioDashboardComponent_Conditional_27_Conditional_0_Template
236
297
  i0.ɵɵtext(16, "Message:");
237
298
  i0.ɵɵelementEnd();
238
299
  i0.ɵɵtext(17);
239
- i0.ɵɵtemplate(18, ComponentStudioDashboardComponent_Conditional_27_Conditional_0_Conditional_18_Template, 5, 1, "details", 60);
300
+ i0.ɵɵtemplate(18, ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Conditional_18_Template, 5, 1, "details", 77);
240
301
  i0.ɵɵelementEnd();
241
- i0.ɵɵelementStart(19, "div", 61)(20, "strong");
302
+ i0.ɵɵelementStart(19, "div", 78)(20, "strong");
242
303
  i0.ɵɵtext(21, "What to do:");
243
304
  i0.ɵɵelementEnd();
244
305
  i0.ɵɵelementStart(22, "ol")(23, "li");
@@ -253,18 +314,18 @@ function ComponentStudioDashboardComponent_Conditional_27_Conditional_0_Template
253
314
  i0.ɵɵelementStart(29, "li");
254
315
  i0.ɵɵtext(30, "Contact your system administrator if the issue persists");
255
316
  i0.ɵɵelementEnd()()();
256
- i0.ɵɵelementStart(31, "div", 62)(32, "button", 63);
257
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_27_Conditional_0_Template_button_click_32_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.retryComponent()); });
258
- i0.ɵɵelement(33, "span", 64);
317
+ i0.ɵɵelementStart(31, "div", 79)(32, "button", 80);
318
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Template_button_click_32_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.retryComponent()); });
319
+ i0.ɵɵelement(33, "span", 81);
259
320
  i0.ɵɵtext(34, " Retry ");
260
321
  i0.ɵɵelementEnd();
261
- i0.ɵɵelementStart(35, "button", 47);
262
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_27_Conditional_0_Template_button_click_35_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.stopComponent()); });
263
- i0.ɵɵelement(36, "span", 48);
322
+ i0.ɵɵelementStart(35, "button", 8);
323
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Template_button_click_35_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.stopComponent()); });
324
+ i0.ɵɵelement(36, "span", 58);
264
325
  i0.ɵɵtext(37, " Stop ");
265
326
  i0.ɵɵelementEnd()()()();
266
327
  } if (rf & 2) {
267
- const ctx_r2 = i0.ɵɵnextContext(2);
328
+ const ctx_r2 = i0.ɵɵnextContext(3);
268
329
  i0.ɵɵadvance(13);
269
330
  i0.ɵɵtextInterpolate1(" ", ctx_r2.currentError.type, "");
270
331
  i0.ɵɵadvance(4);
@@ -274,35 +335,197 @@ function ComponentStudioDashboardComponent_Conditional_27_Conditional_0_Template
274
335
  i0.ɵɵadvance(17);
275
336
  i0.ɵɵproperty("themeColor", "error");
276
337
  } }
277
- function ComponentStudioDashboardComponent_Conditional_27_Conditional_1_Template(rf, ctx) { if (rf & 1) {
278
- const _r8 = i0.ɵɵgetCurrentView();
279
- i0.ɵɵelementStart(0, "mj-react-component", 65);
280
- i0.ɵɵlistener("componentEvent", function ComponentStudioDashboardComponent_Conditional_27_Conditional_1_Template_mj_react_component_componentEvent_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onComponentEvent($event)); })("openEntityRecord", function ComponentStudioDashboardComponent_Conditional_27_Conditional_1_Template_mj_react_component_openEntityRecord_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onOpenEntityRecord($event)); });
338
+ function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
339
+ const _r11 = i0.ɵɵgetCurrentView();
340
+ i0.ɵɵelementStart(0, "mj-react-component", 82);
341
+ i0.ɵɵlistener("componentEvent", function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_1_Template_mj_react_component_componentEvent_0_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onComponentEvent($event)); })("openEntityRecord", function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_1_Template_mj_react_component_openEntityRecord_0_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onOpenEntityRecord($event)); });
281
342
  i0.ɵɵelementEnd();
282
343
  } if (rf & 2) {
283
- const ctx_r2 = i0.ɵɵnextContext(2);
344
+ const ctx_r2 = i0.ɵɵnextContext(3);
284
345
  i0.ɵɵproperty("component", ctx_r2.componentSpec);
285
346
  } }
286
- function ComponentStudioDashboardComponent_Conditional_27_Template(rf, ctx) { if (rf & 1) {
287
- i0.ɵɵtemplate(0, ComponentStudioDashboardComponent_Conditional_27_Conditional_0_Template, 38, 4, "div", 51)(1, ComponentStudioDashboardComponent_Conditional_27_Conditional_1_Template, 1, 1, "mj-react-component", 52);
347
+ function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Template(rf, ctx) { if (rf & 1) {
348
+ i0.ɵɵtemplate(0, ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Template, 38, 4, "div", 68)(1, ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_1_Template, 1, 1, "mj-react-component", 69);
288
349
  } if (rf & 2) {
289
- const ctx_r2 = i0.ɵɵnextContext();
350
+ const ctx_r2 = i0.ɵɵnextContext(2);
290
351
  i0.ɵɵconditional(ctx_r2.currentError ? 0 : 1);
291
352
  } }
292
- function ComponentStudioDashboardComponent_Conditional_28_Template(rf, ctx) { if (rf & 1) {
293
- i0.ɵɵelementStart(0, "div", 19);
294
- i0.ɵɵelement(1, "i", 66);
353
+ function ComponentStudioDashboardComponent_Conditional_34_Conditional_4_Template(rf, ctx) { if (rf & 1) {
354
+ const _r12 = i0.ɵɵgetCurrentView();
355
+ i0.ɵɵelementStart(0, "div", 63);
356
+ i0.ɵɵelement(1, "i", 83);
357
+ i0.ɵɵelementStart(2, "h3");
358
+ i0.ɵɵtext(3);
359
+ i0.ɵɵelementEnd();
360
+ i0.ɵɵelementStart(4, "p");
361
+ i0.ɵɵtext(5);
362
+ i0.ɵɵelementEnd();
363
+ i0.ɵɵelementStart(6, "button", 84);
364
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_Conditional_4_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.runComponent(ctx_r2.selectedComponent)); });
365
+ i0.ɵɵelement(7, "span", 60);
366
+ i0.ɵɵtext(8, " Run Component ");
367
+ i0.ɵɵelementEnd()();
368
+ } if (rf & 2) {
369
+ const ctx_r2 = i0.ɵɵnextContext(2);
370
+ i0.ɵɵadvance(3);
371
+ i0.ɵɵtextInterpolate1("Component: ", ctx_r2.getComponentName(ctx_r2.selectedComponent), "");
372
+ i0.ɵɵadvance(2);
373
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentDescription(ctx_r2.selectedComponent) || "No description available");
374
+ i0.ɵɵadvance();
375
+ i0.ɵɵproperty("themeColor", "primary")("size", "large");
376
+ } }
377
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_6_Template(rf, ctx) { if (rf & 1) {
378
+ const _r14 = i0.ɵɵgetCurrentView();
379
+ i0.ɵɵelementStart(0, "button", 8);
380
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.applySpecChanges()); });
381
+ i0.ɵɵelement(1, "span", 91);
382
+ i0.ɵɵtext(2, " Apply Changes ");
383
+ i0.ɵɵelementEnd();
384
+ i0.ɵɵelementStart(3, "button", 80);
385
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_6_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.initializeEditors()); });
386
+ i0.ɵɵelement(4, "span", 92);
387
+ i0.ɵɵtext(5, " Cancel ");
388
+ i0.ɵɵelementEnd();
389
+ } if (rf & 2) {
390
+ i0.ɵɵproperty("themeColor", "primary");
391
+ } }
392
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_7_Template(rf, ctx) { if (rf & 1) {
393
+ const _r15 = i0.ɵɵgetCurrentView();
394
+ i0.ɵɵelementStart(0, "button", 8);
395
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.refreshComponent()); });
396
+ i0.ɵɵelement(1, "span", 11);
397
+ i0.ɵɵtext(2, " Refresh Component ");
398
+ i0.ɵɵelementEnd();
399
+ } if (rf & 2) {
400
+ i0.ɵɵproperty("themeColor", "info");
401
+ } }
402
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Template(rf, ctx) { if (rf & 1) {
403
+ const _r13 = i0.ɵɵgetCurrentView();
404
+ i0.ɵɵelementStart(0, "div", 85)(1, "div", 86)(2, "h4");
405
+ i0.ɵɵelement(3, "i", 87);
406
+ i0.ɵɵtext(4, " Component Specification (JSON)");
407
+ i0.ɵɵelementEnd();
408
+ i0.ɵɵelementStart(5, "div", 88);
409
+ i0.ɵɵtemplate(6, ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_6_Template, 6, 1)(7, ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_7_Template, 3, 1, "button", 7);
410
+ i0.ɵɵelementEnd()();
411
+ i0.ɵɵelementStart(8, "div", 89)(9, "mj-code-editor", 90);
412
+ i0.ɵɵtwoWayListener("ngModelChange", function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Template_mj_code_editor_ngModelChange_9_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r2 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r2.editableSpec, $event) || (ctx_r2.editableSpec = $event); return i0.ɵɵresetView($event); });
413
+ i0.ɵɵlistener("ngModelChange", function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Template_mj_code_editor_ngModelChange_9_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onSpecChange($event)); });
414
+ i0.ɵɵelementEnd()()();
415
+ } if (rf & 2) {
416
+ const ctx_r2 = i0.ɵɵnextContext(2);
417
+ i0.ɵɵadvance(6);
418
+ i0.ɵɵconditional(ctx_r2.isEditingSpec ? 6 : -1);
419
+ i0.ɵɵadvance();
420
+ i0.ɵɵconditional(ctx_r2.isRunning ? 7 : -1);
421
+ i0.ɵɵadvance(2);
422
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.editableSpec);
423
+ i0.ɵɵproperty("language", "json")("readonly", false);
424
+ } }
425
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_6_Template(rf, ctx) { if (rf & 1) {
426
+ const _r16 = i0.ɵɵgetCurrentView();
427
+ i0.ɵɵelementStart(0, "button", 8);
428
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r16); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.applyCodeChanges()); });
429
+ i0.ɵɵelement(1, "span", 91);
430
+ i0.ɵɵtext(2, " Apply Changes ");
431
+ i0.ɵɵelementEnd();
432
+ i0.ɵɵelementStart(3, "button", 80);
433
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_6_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r16); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.initializeEditors()); });
434
+ i0.ɵɵelement(4, "span", 92);
435
+ i0.ɵɵtext(5, " Cancel ");
436
+ i0.ɵɵelementEnd();
437
+ } if (rf & 2) {
438
+ i0.ɵɵproperty("themeColor", "primary");
439
+ } }
440
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_7_Template(rf, ctx) { if (rf & 1) {
441
+ const _r17 = i0.ɵɵgetCurrentView();
442
+ i0.ɵɵelementStart(0, "button", 8);
443
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r17); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.refreshComponent()); });
444
+ i0.ɵɵelement(1, "span", 11);
445
+ i0.ɵɵtext(2, " Refresh Component ");
446
+ i0.ɵɵelementEnd();
447
+ } if (rf & 2) {
448
+ i0.ɵɵproperty("themeColor", "info");
449
+ } }
450
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_For_11_ng_template_1_Template(rf, ctx) { if (rf & 1) {
451
+ const _r18 = i0.ɵɵgetCurrentView();
452
+ i0.ɵɵelementStart(0, "mj-code-editor", 98);
453
+ i0.ɵɵlistener("ngModelChange", function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_For_11_ng_template_1_Template_mj_code_editor_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r18); const ɵ$index_390_r19 = i0.ɵɵnextContext().$index; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onCodeSectionChange($event, ɵ$index_390_r19)); });
454
+ i0.ɵɵelementEnd();
455
+ } if (rf & 2) {
456
+ const section_r20 = i0.ɵɵnextContext().$implicit;
457
+ i0.ɵɵproperty("ngModel", section_r20.code)("language", "javascript")("readonly", false);
458
+ } }
459
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_For_11_Template(rf, ctx) { if (rf & 1) {
460
+ i0.ɵɵelementStart(0, "kendo-panelbar-item", 96);
461
+ i0.ɵɵtemplate(1, ComponentStudioDashboardComponent_Conditional_34_ng_template_10_For_11_ng_template_1_Template, 1, 3, "ng-template", 97);
462
+ i0.ɵɵelementEnd();
463
+ } if (rf & 2) {
464
+ const section_r20 = ctx.$implicit;
465
+ i0.ɵɵproperty("title", section_r20.title)("expanded", section_r20.expanded);
466
+ } }
467
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Template(rf, ctx) { if (rf & 1) {
468
+ i0.ɵɵelementStart(0, "div", 93)(1, "div", 86)(2, "h4");
469
+ i0.ɵɵelement(3, "i", 94);
470
+ i0.ɵɵtext(4, " Component Code (JavaScript/React)");
471
+ i0.ɵɵelementEnd();
472
+ i0.ɵɵelementStart(5, "div", 88);
473
+ i0.ɵɵtemplate(6, ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_6_Template, 6, 1)(7, ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_7_Template, 3, 1, "button", 7);
474
+ i0.ɵɵelementEnd()();
475
+ i0.ɵɵelementStart(8, "div", 89)(9, "kendo-panelbar", 95);
476
+ i0.ɵɵrepeaterCreate(10, ComponentStudioDashboardComponent_Conditional_34_ng_template_10_For_11_Template, 2, 2, "kendo-panelbar-item", 96, _forTrack1);
477
+ i0.ɵɵelementEnd()()();
478
+ } if (rf & 2) {
479
+ const ctx_r2 = i0.ɵɵnextContext(2);
480
+ i0.ɵɵadvance(6);
481
+ i0.ɵɵconditional(ctx_r2.isEditingCode ? 6 : -1);
482
+ i0.ɵɵadvance();
483
+ i0.ɵɵconditional(ctx_r2.isRunning ? 7 : -1);
484
+ i0.ɵɵadvance(3);
485
+ i0.ɵɵrepeater(ctx_r2.getComponentCodeSections());
486
+ } }
487
+ function ComponentStudioDashboardComponent_Conditional_34_Template(rf, ctx) { if (rf & 1) {
488
+ const _r9 = i0.ɵɵgetCurrentView();
489
+ i0.ɵɵelementStart(0, "kendo-splitter", 25)(1, "kendo-splitter-pane", 61)(2, "div", 62);
490
+ i0.ɵɵtemplate(3, ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Template, 2, 1)(4, ComponentStudioDashboardComponent_Conditional_34_Conditional_4_Template, 9, 4, "div", 63);
491
+ i0.ɵɵelementEnd()();
492
+ i0.ɵɵelementStart(5, "kendo-splitter-pane", 64)(6, "kendo-tabstrip", 65);
493
+ i0.ɵɵlistener("tabSelect", function ComponentStudioDashboardComponent_Conditional_34_Template_kendo_tabstrip_tabSelect_6_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onTabSelect($event)); });
494
+ i0.ɵɵelementStart(7, "kendo-tabstrip-tab", 66);
495
+ i0.ɵɵtemplate(8, ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Template, 10, 5, "ng-template", 67);
496
+ i0.ɵɵelementEnd();
497
+ i0.ɵɵelementStart(9, "kendo-tabstrip-tab", 66);
498
+ i0.ɵɵtemplate(10, ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Template, 12, 2, "ng-template", 67);
499
+ i0.ɵɵelementEnd()()()();
500
+ } if (rf & 2) {
501
+ const ctx_r2 = i0.ɵɵnextContext();
502
+ i0.ɵɵadvance();
503
+ i0.ɵɵproperty("min", "300px")("collapsible", false)("size", ctx_r2.isDetailsPaneCollapsed ? "100%" : "50%");
504
+ i0.ɵɵadvance(2);
505
+ i0.ɵɵconditional(ctx_r2.isRunning && ctx_r2.componentSpec ? 3 : 4);
506
+ i0.ɵɵadvance(2);
507
+ i0.ɵɵproperty("min", "400px")("collapsible", true)("collapsed", ctx_r2.isDetailsPaneCollapsed);
508
+ i0.ɵɵadvance(2);
509
+ i0.ɵɵproperty("title", "Spec")("selected", ctx_r2.activeTab === 0);
510
+ i0.ɵɵadvance(2);
511
+ i0.ɵɵproperty("title", "Code")("selected", ctx_r2.activeTab === 1);
512
+ } }
513
+ function ComponentStudioDashboardComponent_Conditional_35_Template(rf, ctx) { if (rf & 1) {
514
+ i0.ɵɵelementStart(0, "div", 26);
515
+ i0.ɵɵelement(1, "i", 99);
295
516
  i0.ɵɵelementStart(2, "h2");
296
517
  i0.ɵɵtext(3, "Ready to Test Components");
297
518
  i0.ɵɵelementEnd();
298
519
  i0.ɵɵelementStart(4, "p");
299
- i0.ɵɵtext(5, "Select a component from the list and click \"Run Component\" to see it in action");
520
+ i0.ɵɵtext(5, "Select a component from the list to view its details and run it");
300
521
  i0.ɵɵelementEnd()();
301
522
  } }
302
523
  let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent extends BaseDashboard {
303
524
  cdr;
304
525
  // Component data
305
526
  components = [];
527
+ fileLoadedComponents = []; // Components loaded from files
528
+ allComponents = []; // Combined list
306
529
  filteredComponents = [];
307
530
  selectedComponent = null;
308
531
  expandedComponent = null; // Track which card is expanded
@@ -312,6 +535,19 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
312
535
  isRunning = false; // Track if component is currently running
313
536
  // Error handling
314
537
  currentError = null;
538
+ // Tab management
539
+ activeTab = 0; // 0 = Spec, 1 = Code
540
+ // Splitter state
541
+ isDetailsPaneCollapsed = true; // Start with details collapsed
542
+ // Editor content
543
+ editableSpec = ''; // JSON string for spec editor
544
+ editableCode = ''; // JavaScript code for code editor
545
+ codeSections = [];
546
+ isEditingSpec = false;
547
+ isEditingCode = false;
548
+ lastEditSource = null;
549
+ // File input element reference
550
+ fileInput;
315
551
  destroy$ = new Subject();
316
552
  constructor(cdr) {
317
553
  super();
@@ -341,7 +577,7 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
341
577
  });
342
578
  if (result.Success) {
343
579
  this.components = result.Results || [];
344
- this.filterComponents();
580
+ this.combineAndFilterComponents();
345
581
  }
346
582
  else {
347
583
  console.error('Failed to load components:', result.ErrorMessage);
@@ -356,23 +592,67 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
356
592
  }
357
593
  onSearchChange(query) {
358
594
  this.searchQuery = query;
359
- this.filterComponents();
595
+ this.combineAndFilterComponents();
360
596
  }
361
- filterComponents() {
362
- // Note: this.components already filtered to HasCustomProps = 0 in loadData
597
+ combineAndFilterComponents() {
598
+ // Combine database components with file-loaded components
599
+ this.allComponents = [
600
+ ...this.fileLoadedComponents,
601
+ ...this.components
602
+ ];
603
+ // Apply search filter
363
604
  if (!this.searchQuery) {
364
- this.filteredComponents = [...this.components];
605
+ this.filteredComponents = [...this.allComponents];
365
606
  }
366
607
  else {
367
608
  const query = this.searchQuery.toLowerCase();
368
- this.filteredComponents = this.components.filter(c => c.Name?.toLowerCase().includes(query) ||
369
- c.Description?.toLowerCase().includes(query) ||
370
- c.Type?.toLowerCase().includes(query));
609
+ this.filteredComponents = this.allComponents.filter(c => {
610
+ const name = this.getComponentName(c)?.toLowerCase() || '';
611
+ const description = this.getComponentDescription(c)?.toLowerCase() || '';
612
+ const type = this.getComponentType(c)?.toLowerCase() || '';
613
+ return name.includes(query) || description.includes(query) || type.includes(query);
614
+ });
371
615
  }
372
616
  }
617
+ // Helper methods to get properties from union type
618
+ getComponentName(component) {
619
+ return component.isFileLoaded ? component.name : component.Name;
620
+ }
621
+ getComponentDescription(component) {
622
+ return component.isFileLoaded ? component.description : (component.Description || undefined);
623
+ }
624
+ getComponentType(component) {
625
+ return component.isFileLoaded ? component.type : (component.Type || undefined);
626
+ }
627
+ getComponentStatus(component) {
628
+ return component.isFileLoaded ? component.status : (component.Status || undefined);
629
+ }
630
+ getComponentVersion(component) {
631
+ return component.isFileLoaded ? '1.0.0' : (component.Version || '1.0.0');
632
+ }
633
+ getComponentSpec(component) {
634
+ return component.isFileLoaded ? component.specification : JSON.parse(component.Specification);
635
+ }
636
+ getComponentId(component) {
637
+ return component.isFileLoaded ? component.id : component.ID;
638
+ }
639
+ isFileLoadedComponent(component) {
640
+ return component.isFileLoaded === true;
641
+ }
642
+ getComponentFilename(component) {
643
+ return component.isFileLoaded ? component.filename : undefined;
644
+ }
645
+ getComponentLoadedAt(component) {
646
+ return component.isFileLoaded ? component.loadedAt : undefined;
647
+ }
648
+ getComponentUpdatedAt(component) {
649
+ return !component.isFileLoaded && component.__mj_UpdatedAt ? component.__mj_UpdatedAt : undefined;
650
+ }
373
651
  toggleComponentExpansion(component) {
374
652
  // Toggle expansion - if clicking the same component, collapse it
375
- if (this.expandedComponent?.ID === component.ID) {
653
+ const componentId = this.getComponentId(component);
654
+ const expandedId = this.expandedComponent ? this.getComponentId(this.expandedComponent) : null;
655
+ if (expandedId === componentId) {
376
656
  this.expandedComponent = null;
377
657
  }
378
658
  else {
@@ -382,7 +662,9 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
382
662
  }
383
663
  runComponent(component) {
384
664
  // If another component is running, stop it first then start the new one
385
- if (this.isRunning && this.selectedComponent?.ID !== component.ID) {
665
+ const componentId = this.getComponentId(component);
666
+ const selectedId = this.selectedComponent ? this.getComponentId(this.selectedComponent) : null;
667
+ if (this.isRunning && selectedId !== componentId) {
386
668
  this.stopComponent();
387
669
  this.startComponent(component);
388
670
  }
@@ -392,10 +674,12 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
392
674
  }
393
675
  startComponent(component) {
394
676
  this.selectedComponent = component;
395
- this.componentSpec = JSON.parse(component.Specification);
677
+ this.componentSpec = this.getComponentSpec(component);
396
678
  this.isRunning = true;
397
679
  this.currentError = null; // Clear any previous errors
398
- console.log('Running component:', component.Name);
680
+ this.isDetailsPaneCollapsed = true; // Start with details collapsed
681
+ this.initializeEditors(); // Initialize spec and code editors
682
+ console.log('Running component:', this.getComponentName(component));
399
683
  try {
400
684
  this.cdr.detectChanges();
401
685
  }
@@ -458,7 +742,7 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
458
742
  const errorText = `
459
743
  Component Error Report
460
744
  ${'='.repeat(50)}
461
- Component: ${this.selectedComponent?.Name}
745
+ Component: ${this.selectedComponent ? this.getComponentName(this.selectedComponent) : 'Unknown'}
462
746
  Error Type: ${this.currentError.type}
463
747
  Message: ${this.currentError.message}
464
748
  ${this.currentError.technicalDetails ? '\nTechnical Details:\n' + JSON.stringify(this.currentError.technicalDetails, null, 2) : ''}
@@ -483,6 +767,81 @@ ${this.currentError.technicalDetails ? '\nTechnical Details:\n' + JSON.stringify
483
767
  async refreshData() {
484
768
  await this.loadData();
485
769
  }
770
+ // File upload handling methods
771
+ triggerFileInput() {
772
+ this.fileInput?.nativeElement.click();
773
+ }
774
+ async handleFileSelect(event) {
775
+ const input = event.target;
776
+ const file = input.files?.[0];
777
+ if (!file)
778
+ return;
779
+ // Only accept JSON files
780
+ if (!file.name.endsWith('.json')) {
781
+ console.error('Please select a JSON file');
782
+ // Could add a toast notification here
783
+ return;
784
+ }
785
+ try {
786
+ const fileContent = await this.readFile(file);
787
+ const spec = JSON.parse(fileContent);
788
+ // Validate the spec has required fields
789
+ if (!spec.name || !spec.code) {
790
+ console.error('Invalid component specification: missing required fields (name, code)');
791
+ return;
792
+ }
793
+ // Create a file-loaded component
794
+ const fileComponent = {
795
+ id: this.generateId(),
796
+ name: spec.name,
797
+ description: spec.description,
798
+ specification: spec,
799
+ filename: file.name,
800
+ loadedAt: new Date(),
801
+ isFileLoaded: true,
802
+ type: spec.type || 'Component',
803
+ status: 'File'
804
+ };
805
+ // Add to the list and refresh
806
+ this.fileLoadedComponents.push(fileComponent);
807
+ this.combineAndFilterComponents();
808
+ console.log(`Loaded component "${spec.name}" from ${file.name}`);
809
+ // Automatically select and run the newly loaded component
810
+ this.expandedComponent = fileComponent;
811
+ this.runComponent(fileComponent);
812
+ // Clear the input for future uploads
813
+ input.value = '';
814
+ }
815
+ catch (error) {
816
+ console.error('Error loading component file:', error);
817
+ }
818
+ }
819
+ readFile(file) {
820
+ return new Promise((resolve, reject) => {
821
+ const reader = new FileReader();
822
+ reader.onload = (e) => resolve(e.target?.result);
823
+ reader.onerror = reject;
824
+ reader.readAsText(file);
825
+ });
826
+ }
827
+ generateId() {
828
+ return 'file-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
829
+ }
830
+ removeFileComponent(component) {
831
+ const index = this.fileLoadedComponents.indexOf(component);
832
+ if (index > -1) {
833
+ this.fileLoadedComponents.splice(index, 1);
834
+ // If this was the selected component, clear it
835
+ if (this.selectedComponent === component) {
836
+ this.stopComponent();
837
+ }
838
+ // If this was the expanded component, clear it
839
+ if (this.expandedComponent === component) {
840
+ this.expandedComponent = null;
841
+ }
842
+ this.combineAndFilterComponents();
843
+ }
844
+ }
486
845
  getComponentTypeIcon(type) {
487
846
  const icons = {
488
847
  'Report': 'fa-file-alt',
@@ -511,47 +870,286 @@ ${this.currentError.technicalDetails ? '\nTechnical Details:\n' + JSON.stringify
511
870
  };
512
871
  return colors[type || ''] || '#9CA3AF';
513
872
  }
873
+ /**
874
+ * Initialize the spec and code editors when a component is selected
875
+ */
876
+ initializeEditors() {
877
+ if (this.selectedComponent) {
878
+ const spec = this.getComponentSpec(this.selectedComponent);
879
+ // Deep parse the spec for better readability
880
+ const parseOptions = {
881
+ extractInlineJson: true,
882
+ maxDepth: 100,
883
+ debug: false
884
+ };
885
+ const parsed = ParseJSONRecursive(spec, parseOptions);
886
+ this.editableSpec = JSON.stringify(parsed, null, 2);
887
+ // Extract code from spec
888
+ this.editableCode = spec.code || '// No code available';
889
+ // Build code sections array
890
+ this.buildCodeSections();
891
+ // Reset editing flags
892
+ this.isEditingSpec = false;
893
+ this.isEditingCode = false;
894
+ this.lastEditSource = null;
895
+ }
896
+ }
897
+ /**
898
+ * Handle spec editor changes
899
+ */
900
+ onSpecChange(newSpec) {
901
+ this.editableSpec = newSpec;
902
+ this.isEditingSpec = true;
903
+ this.lastEditSource = 'spec';
904
+ }
905
+ /**
906
+ * Handle code editor changes
907
+ */
908
+ onCodeChange(newCode) {
909
+ this.editableCode = newCode;
910
+ this.isEditingCode = true;
911
+ this.lastEditSource = 'code';
912
+ }
913
+ /**
914
+ * Apply spec changes and update the code tab
915
+ */
916
+ applySpecChanges() {
917
+ try {
918
+ const parsed = JSON.parse(this.editableSpec);
919
+ // Update the component spec
920
+ if (this.selectedComponent) {
921
+ if (this.isFileLoadedComponent(this.selectedComponent)) {
922
+ // Update file-loaded component
923
+ this.selectedComponent.specification = parsed;
924
+ }
925
+ else {
926
+ // Update database component's Specification field in memory only
927
+ this.selectedComponent.Specification = JSON.stringify(parsed);
928
+ }
929
+ // Update the runtime spec
930
+ this.componentSpec = parsed;
931
+ // Update the code editor with new code from spec
932
+ this.editableCode = parsed.code || '// No code available';
933
+ // Rebuild code sections from updated spec
934
+ this.buildCodeSections();
935
+ // If component is running, update it without full refresh
936
+ if (this.isRunning) {
937
+ this.updateRunningComponent();
938
+ }
939
+ this.isEditingSpec = false;
940
+ }
941
+ }
942
+ catch (error) {
943
+ console.error('Invalid JSON in spec editor:', error);
944
+ // Could show a toast notification here
945
+ }
946
+ }
947
+ /**
948
+ * Apply code changes and update the spec
949
+ */
950
+ applyCodeChanges() {
951
+ if (this.selectedComponent) {
952
+ try {
953
+ // Parse the current spec
954
+ const spec = JSON.parse(this.editableSpec);
955
+ // Update main code and dependencies from code sections
956
+ if (this.codeSections.length > 0) {
957
+ // First section is always the main component
958
+ spec.code = this.codeSections[0].code;
959
+ // Update dependencies if any
960
+ if (this.codeSections.length > 1 && spec.dependencies) {
961
+ for (let i = 1; i < this.codeSections.length; i++) {
962
+ const section = this.codeSections[i];
963
+ if (section.index !== undefined && spec.dependencies[section.index]) {
964
+ spec.dependencies[section.index].code = section.code;
965
+ }
966
+ }
967
+ }
968
+ }
969
+ // Update the spec editor
970
+ const parseOptions = {
971
+ extractInlineJson: true,
972
+ maxDepth: 100,
973
+ debug: false
974
+ };
975
+ const parsed = ParseJSONRecursive(spec, parseOptions);
976
+ this.editableSpec = JSON.stringify(parsed, null, 2);
977
+ // Update the component entity in memory
978
+ if (this.isFileLoadedComponent(this.selectedComponent)) {
979
+ this.selectedComponent.specification = spec;
980
+ }
981
+ else {
982
+ // Update database component's Specification field in memory only
983
+ this.selectedComponent.Specification = JSON.stringify(spec);
984
+ }
985
+ // Update the runtime spec
986
+ this.componentSpec = spec;
987
+ // If component is running, update it without full refresh
988
+ if (this.isRunning) {
989
+ this.updateRunningComponent();
990
+ }
991
+ this.isEditingCode = false;
992
+ }
993
+ catch (error) {
994
+ console.error('Error applying code changes:', error);
995
+ }
996
+ }
997
+ }
998
+ /**
999
+ * Refresh the running component with new spec/code (in-place update)
1000
+ */
1001
+ refreshComponent() {
1002
+ if (this.selectedComponent && this.isRunning) {
1003
+ // Use the same in-place update logic as Apply Changes
1004
+ this.updateRunningComponent();
1005
+ }
1006
+ }
1007
+ /**
1008
+ * Update the running component without full refresh
1009
+ */
1010
+ updateRunningComponent() {
1011
+ if (this.selectedComponent && this.isRunning) {
1012
+ // Get the updated spec
1013
+ const spec = this.getComponentSpec(this.selectedComponent);
1014
+ // Temporarily set to null to force React to re-render
1015
+ this.componentSpec = null;
1016
+ this.cdr.detectChanges();
1017
+ // Then set the new spec
1018
+ setTimeout(() => {
1019
+ this.componentSpec = spec;
1020
+ try {
1021
+ this.cdr.detectChanges();
1022
+ }
1023
+ catch (error) {
1024
+ console.error('Error with cdr.detectChanges():', error);
1025
+ }
1026
+ }, 10);
1027
+ }
1028
+ }
1029
+ /**
1030
+ * Build code sections array from spec
1031
+ */
1032
+ buildCodeSections() {
1033
+ if (!this.selectedComponent) {
1034
+ this.codeSections = [];
1035
+ return;
1036
+ }
1037
+ const spec = this.getComponentSpec(this.selectedComponent);
1038
+ const sections = [];
1039
+ // Main component code
1040
+ sections.push({
1041
+ title: spec.name || 'Main Component',
1042
+ code: spec.code || '// No code available',
1043
+ expanded: true,
1044
+ isDependency: false
1045
+ });
1046
+ // Add dependent components if any
1047
+ if (spec.dependencies && Array.isArray(spec.dependencies)) {
1048
+ spec.dependencies.forEach((dep, index) => {
1049
+ sections.push({
1050
+ title: dep.name || `Dependency ${index + 1}`,
1051
+ code: dep.code || '// No code available',
1052
+ expanded: false,
1053
+ isDependency: true,
1054
+ index: index
1055
+ });
1056
+ });
1057
+ }
1058
+ this.codeSections = sections;
1059
+ }
1060
+ /**
1061
+ * Get component code sections for panel bar
1062
+ */
1063
+ getComponentCodeSections() {
1064
+ return this.codeSections;
1065
+ }
1066
+ /**
1067
+ * Handle code section changes
1068
+ */
1069
+ onCodeSectionChange(newCode, sectionIndex) {
1070
+ if (this.codeSections[sectionIndex]) {
1071
+ this.codeSections[sectionIndex].code = newCode;
1072
+ this.isEditingCode = true;
1073
+ this.lastEditSource = 'code';
1074
+ }
1075
+ }
1076
+ /**
1077
+ * Toggle the details pane (spec/code editors)
1078
+ */
1079
+ toggleDetailsPane() {
1080
+ this.isDetailsPaneCollapsed = !this.isDetailsPaneCollapsed;
1081
+ this.cdr.detectChanges();
1082
+ }
1083
+ /**
1084
+ * Handle tab selection
1085
+ */
1086
+ onTabSelect(event) {
1087
+ this.activeTab = event.index;
1088
+ // Initialize editors when switching to spec or code tabs
1089
+ // Both tabs now need initialization since there's no separate Run tab
1090
+ this.initializeEditors();
1091
+ }
514
1092
  static ɵfac = function ComponentStudioDashboardComponent_Factory(t) { return new (t || ComponentStudioDashboardComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
515
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ComponentStudioDashboardComponent, selectors: [["mj-component-studio-dashboard"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 29, vars: 9, consts: [[1, "component-studio"], [1, "dashboard-header"], [1, "header-content"], [1, "fa-solid", "fa-puzzle-piece"], [1, "header-subtitle"], ["kendoButton", "", 3, "click", "disabled"], [1, "fa-solid", "fa-sync"], ["orientation", "horizontal", 2, "flex", "1", "height", "auto"], [3, "min", "max", "size"], [1, "components-panel"], [1, "panel-header"], [1, "search-box"], ["placeholder", "Search components...", 3, "valueChange", "value", "clearButton"], ["kendoTextBoxPrefixTemplate", ""], [1, "components-list"], [1, "loading-message"], [1, "empty-message"], [3, "min"], [1, "component-display"], [1, "empty-state"], [1, "fa-solid", "fa-search"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-info-circle"], [1, "component-card", 3, "expanded", "running"], [1, "component-card"], [1, "card-header", 3, "click"], [1, "card-icon"], [1, "fa-solid", 3, "ngClass"], [1, "card-info"], [1, "card-name"], [1, "card-meta"], [1, "card-type"], [1, "card-version"], [1, "status-badge", "published"], [1, "status-badge", "draft"], [1, "card-chevron"], [1, "fa-solid", "fa-chevron-up"], [1, "fa-solid", "fa-chevron-down"], [1, "card-details"], [1, "detail-section"], [1, "info-grid"], [1, "info-item"], [1, "info-label"], [1, "info-value"], [1, "card-actions"], ["kendoButton", "", 3, "themeColor"], ["kendoButton", "", "title", "Stop current component and run this one", 3, "themeColor"], ["kendoButton", "", 3, "click", "themeColor"], [1, "fa-solid", "fa-stop"], ["kendoButton", "", "title", "Stop current component and run this one", 3, "click", "themeColor"], [1, "fa-solid", "fa-play"], [1, "error-display"], [3, "component"], [1, "error-container"], [1, "error-header"], [1, "fa-solid", "fa-exclamation-triangle"], ["title", "Copy error details", 1, "copy-button", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "error-intro"], [1, "error-details"], [1, "technical-details"], [1, "error-help"], [1, "error-actions"], ["kendoButton", "", 3, "click"], [1, "fa-solid", "fa-rotate"], [3, "componentEvent", "openEntityRecord", "component"], [1, "fa-solid", "fa-rocket", "fa-3x"]], template: function ComponentStudioDashboardComponent_Template(rf, ctx) { if (rf & 1) {
516
- i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "div")(4, "h1");
517
- i0.ɵɵelement(5, "i", 3);
1093
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ComponentStudioDashboardComponent, selectors: [["mj-component-studio-dashboard"]], viewQuery: function ComponentStudioDashboardComponent_Query(rf, ctx) { if (rf & 1) {
1094
+ i0.ɵɵviewQuery(_c0, 5);
1095
+ } if (rf & 2) {
1096
+ let _t;
1097
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.fileInput = _t.first);
1098
+ } }, features: [i0.ɵɵInheritDefinitionFeature], decls: 36, vars: 11, consts: [["fileInput", ""], [1, "component-studio"], [1, "dashboard-header"], [1, "header-content"], [1, "fa-solid", "fa-puzzle-piece"], [1, "header-subtitle"], [1, "header-buttons"], ["kendoButton", "", 3, "themeColor"], ["kendoButton", "", 3, "click", "themeColor"], [1, "fa-solid", "fa-file-import"], ["kendoButton", "", 3, "click", "disabled"], [1, "fa-solid", "fa-sync"], ["type", "file", "accept", ".json", 2, "display", "none", 3, "change"], ["orientation", "horizontal", 2, "flex", "1", "height", "auto"], [3, "min", "max", "size"], [1, "components-panel"], [1, "panel-header"], [1, "search-box"], ["placeholder", "Search components...", 3, "valueChange", "value", "clearButton"], ["kendoTextBoxPrefixTemplate", ""], [1, "components-list"], [1, "loading-message"], [1, "empty-message"], [3, "min"], [1, "component-display"], ["orientation", "horizontal", 1, "component-editor-splitter"], [1, "empty-state"], [1, "fa-solid", "fa-eye"], [1, "fa-solid", "fa-eye-slash"], [1, "fa-solid", "fa-search"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-info-circle"], [1, "component-card", 3, "expanded", "running", "file-loaded"], [1, "component-card"], [1, "card-header", 3, "click"], [1, "card-icon"], [1, "fa-solid", 3, "ngClass"], [1, "card-info"], [1, "card-name"], [1, "file-badge", 3, "title"], [1, "card-meta"], [1, "card-type"], [1, "card-version"], [1, "status-badge", "file"], [1, "status-badge", "published"], [1, "status-badge", "draft"], [1, "card-chevron"], [1, "fa-solid", "fa-chevron-up"], [1, "fa-solid", "fa-chevron-down"], [1, "card-details"], [1, "fa-solid", "fa-file"], [1, "detail-section"], [1, "info-grid"], [1, "info-item"], [1, "info-label"], [1, "info-value"], [1, "card-actions"], ["kendoButton", "", "title", "Stop current component and run this one", 3, "themeColor"], [1, "fa-solid", "fa-stop"], ["kendoButton", "", "title", "Stop current component and run this one", 3, "click", "themeColor"], [1, "fa-solid", "fa-play"], [3, "min", "collapsible", "size"], [1, "component-runtime"], [1, "run-empty-state"], [3, "min", "collapsible", "collapsed"], [1, "editor-tabs", 3, "tabSelect"], [3, "title", "selected"], ["kendoTabContent", ""], [1, "error-display"], [3, "component"], [1, "error-container"], [1, "error-header"], [1, "fa-solid", "fa-exclamation-triangle"], ["title", "Copy error details", 1, "copy-button", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "error-intro"], [1, "error-details"], [1, "technical-details"], [1, "error-help"], [1, "error-actions"], ["kendoButton", "", 3, "click"], [1, "fa-solid", "fa-rotate"], [3, "componentEvent", "openEntityRecord", "component"], [1, "fa-solid", "fa-play-circle", "fa-3x"], ["kendoButton", "", 3, "click", "themeColor", "size"], [1, "tab-content", "spec-tab"], [1, "editor-header"], [1, "fa-solid", "fa-code"], [1, "editor-actions"], [1, "editor-wrapper"], [2, "height", "100%", "width", "100%", 3, "ngModelChange", "ngModel", "language", "readonly"], [1, "fa-solid", "fa-check"], [1, "fa-solid", "fa-times"], [1, "tab-content", "code-tab"], [1, "fa-solid", "fa-file-code"], [1, "code-sections"], [3, "title", "expanded"], ["kendoPanelBarContent", ""], [2, "height", "400px", "width", "100%", 3, "ngModelChange", "ngModel", "language", "readonly"], [1, "fa-solid", "fa-rocket", "fa-3x"]], template: function ComponentStudioDashboardComponent_Template(rf, ctx) { if (rf & 1) {
1099
+ const _r1 = i0.ɵɵgetCurrentView();
1100
+ i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3)(3, "div")(4, "h1");
1101
+ i0.ɵɵelement(5, "i", 4);
518
1102
  i0.ɵɵtext(6, " Component Studio");
519
1103
  i0.ɵɵelementEnd();
520
- i0.ɵɵelementStart(7, "p", 4);
1104
+ i0.ɵɵelementStart(7, "p", 5);
521
1105
  i0.ɵɵtext(8, "Testing components without custom properties");
522
1106
  i0.ɵɵelementEnd()();
523
- i0.ɵɵelementStart(9, "button", 5);
524
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Template_button_click_9_listener() { return ctx.refreshData(); });
525
- i0.ɵɵelement(10, "span", 6);
526
- i0.ɵɵtext(11, " Refresh ");
1107
+ i0.ɵɵelementStart(9, "div", 6);
1108
+ i0.ɵɵtemplate(10, ComponentStudioDashboardComponent_Conditional_10_Template, 3, 2, "button", 7);
1109
+ i0.ɵɵelementStart(11, "button", 8);
1110
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.triggerFileInput()); });
1111
+ i0.ɵɵelement(12, "span", 9);
1112
+ i0.ɵɵtext(13, " Import from File ");
1113
+ i0.ɵɵelementEnd();
1114
+ i0.ɵɵelementStart(14, "button", 10);
1115
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.refreshData()); });
1116
+ i0.ɵɵelement(15, "span", 11);
1117
+ i0.ɵɵtext(16, " Refresh ");
1118
+ i0.ɵɵelementEnd()();
1119
+ i0.ɵɵelementStart(17, "input", 12, 0);
1120
+ i0.ɵɵlistener("change", function ComponentStudioDashboardComponent_Template_input_change_17_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.handleFileSelect($event)); });
527
1121
  i0.ɵɵelementEnd()()();
528
- i0.ɵɵelementStart(12, "kendo-splitter", 7)(13, "kendo-splitter-pane", 8)(14, "div", 9)(15, "div", 10)(16, "h3");
529
- i0.ɵɵtext(17, "Components");
1122
+ i0.ɵɵelementStart(19, "kendo-splitter", 13)(20, "kendo-splitter-pane", 14)(21, "div", 15)(22, "div", 16)(23, "h3");
1123
+ i0.ɵɵtext(24, "Components");
530
1124
  i0.ɵɵelementEnd();
531
- i0.ɵɵelementStart(18, "div", 11)(19, "kendo-textbox", 12);
532
- i0.ɵɵlistener("valueChange", function ComponentStudioDashboardComponent_Template_kendo_textbox_valueChange_19_listener($event) { return ctx.onSearchChange($event); });
533
- i0.ɵɵtemplate(20, ComponentStudioDashboardComponent_ng_template_20_Template, 1, 0, "ng-template", 13);
1125
+ i0.ɵɵelementStart(25, "div", 17)(26, "kendo-textbox", 18);
1126
+ i0.ɵɵlistener("valueChange", function ComponentStudioDashboardComponent_Template_kendo_textbox_valueChange_26_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSearchChange($event)); });
1127
+ i0.ɵɵtemplate(27, ComponentStudioDashboardComponent_ng_template_27_Template, 1, 0, "ng-template", 19);
534
1128
  i0.ɵɵelementEnd()()();
535
- i0.ɵɵelementStart(21, "div", 14);
536
- i0.ɵɵtemplate(22, ComponentStudioDashboardComponent_Conditional_22_Template, 3, 0, "div", 15)(23, ComponentStudioDashboardComponent_Conditional_23_Template, 6, 0, "div", 16)(24, ComponentStudioDashboardComponent_Conditional_24_Template, 2, 0);
1129
+ i0.ɵɵelementStart(28, "div", 20);
1130
+ i0.ɵɵtemplate(29, ComponentStudioDashboardComponent_Conditional_29_Template, 3, 0, "div", 21)(30, ComponentStudioDashboardComponent_Conditional_30_Template, 6, 0, "div", 22)(31, ComponentStudioDashboardComponent_Conditional_31_Template, 2, 0);
537
1131
  i0.ɵɵelementEnd()()();
538
- i0.ɵɵelementStart(25, "kendo-splitter-pane", 17)(26, "div", 18);
539
- i0.ɵɵtemplate(27, ComponentStudioDashboardComponent_Conditional_27_Template, 2, 1)(28, ComponentStudioDashboardComponent_Conditional_28_Template, 6, 0, "div", 19);
1132
+ i0.ɵɵelementStart(32, "kendo-splitter-pane", 23)(33, "div", 24);
1133
+ i0.ɵɵtemplate(34, ComponentStudioDashboardComponent_Conditional_34_Template, 11, 11, "kendo-splitter", 25)(35, ComponentStudioDashboardComponent_Conditional_35_Template, 6, 0, "div", 26);
540
1134
  i0.ɵɵelementEnd()()()();
541
1135
  } if (rf & 2) {
542
- i0.ɵɵadvance(9);
1136
+ i0.ɵɵadvance(10);
1137
+ i0.ɵɵconditional(ctx.selectedComponent && ctx.isRunning ? 10 : -1);
1138
+ i0.ɵɵadvance();
1139
+ i0.ɵɵproperty("themeColor", "info");
1140
+ i0.ɵɵadvance(3);
543
1141
  i0.ɵɵproperty("disabled", ctx.isLoading);
544
- i0.ɵɵadvance(4);
1142
+ i0.ɵɵadvance(6);
545
1143
  i0.ɵɵproperty("min", "350px")("max", "600px")("size", "400px");
546
1144
  i0.ɵɵadvance(6);
547
1145
  i0.ɵɵproperty("value", ctx.searchQuery)("clearButton", true);
548
1146
  i0.ɵɵadvance(3);
549
- i0.ɵɵconditional(ctx.isLoading ? 22 : ctx.filteredComponents.length === 0 ? 23 : 24);
1147
+ i0.ɵɵconditional(ctx.isLoading ? 29 : ctx.filteredComponents.length === 0 ? 30 : 31);
550
1148
  i0.ɵɵadvance(3);
551
1149
  i0.ɵɵproperty("min", "400px");
552
1150
  i0.ɵɵadvance(2);
553
- i0.ɵɵconditional(ctx.isRunning && ctx.selectedComponent && ctx.componentSpec ? 27 : 28);
554
- } }, dependencies: [i1.NgClass, i2.TextBoxComponent, i2.TextBoxPrefixTemplateDirective, i3.SplitterComponent, i3.SplitterPaneComponent, i4.ButtonComponent, i5.MJReactComponent, i1.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f8f9fa;\n overflow: hidden;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n \n .header-subtitle {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: #6c757d;\n font-weight: normal;\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #212529;\n }\n \n .search-box {\n kendo-textbox {\n width: 100%;\n }\n }\n }\n \n .components-list {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n background: linear-gradient(to right, rgba(16, 185, 129, 0.03) 0%, white 100%);\n \n .card-header {\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n background: #10b981;\n }\n }\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n position: relative;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: _ngcontent-%COMP%_slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n }\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}"] });
1151
+ i0.ɵɵconditional(ctx.selectedComponent ? 34 : 35);
1152
+ } }, dependencies: [i1.NgClass, i2.NgControlStatus, i2.NgModel, i3.TextBoxComponent, i3.TextBoxPrefixTemplateDirective, i4.PanelBarComponent, i4.PanelBarItemComponent, i4.PanelBarContentDirective, i4.SplitterComponent, i4.SplitterPaneComponent, i4.TabStripComponent, i4.TabStripTabComponent, i4.TabContentDirective, i5.CodeEditorComponent, i6.ButtonComponent, i7.MJReactComponent, i1.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100vh;\n background: #f8f9fa;\n overflow: hidden;\n position: relative;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n .header-buttons {\n display: flex;\n gap: 8px;\n }\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n \n .header-subtitle {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: #6c757d;\n font-weight: normal;\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n \n ::ng-deep .k-pane {\n overflow: hidden;\n height: 100%;\n }\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #212529;\n }\n \n .search-box {\n kendo-textbox {\n width: 100%;\n }\n }\n }\n \n .components-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n background: linear-gradient(to right, rgba(16, 185, 129, 0.03) 0%, white 100%);\n \n .card-header {\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n background: #10b981;\n }\n }\n }\n \n &.file-loaded {\n background: linear-gradient(135deg, #f0f8ff 0%, white 100%);\n border-style: dashed;\n border-color: #3b82f6;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n \n &.expanded {\n border-style: solid;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n }\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n position: relative;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 8px;\n \n .file-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n background: #e0f2fe;\n color: #0369a1;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n flex-shrink: 0;\n \n i {\n font-size: 10px;\n }\n }\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n \n &.file {\n background: #e0f2fe;\n color: #0369a1;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: _ngcontent-%COMP%_slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow: hidden;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n display: block;\n overflow-y: auto;\n overflow-x: hidden;\n }\n \n // Component and editor splitter\n .component-editor-splitter {\n height: 100%;\n overflow: hidden;\n \n ::ng-deep .k-splitter-bar {\n background: #6366f1; // Same blue as Import button\n width: 6px; // Make it slightly wider for visibility\n \n &:hover {\n background: #4f52d9; // Darker blue on hover\n }\n \n .k-resize-handle {\n background-color: rgba(255, 255, 255, 0.3);\n }\n }\n \n ::ng-deep .k-pane {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n }\n \n // Component runtime area\n .component-runtime {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow-y: auto;\n overflow-x: hidden;\n \n .run-empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px;\n text-align: center;\n \n i {\n color: #10b981;\n margin-bottom: 24px;\n }\n \n h3 {\n margin: 0 0 12px 0;\n font-size: 20px;\n font-weight: 600;\n color: #212529;\n }\n \n p {\n margin: 0 0 24px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n }\n }\n }\n \n // Editor tabs on the right\n .editor-tabs {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n ::ng-deep .k-tabstrip-items-wrapper {\n background: #f8f9fa;\n border-bottom: 2px solid #dee2e6;\n flex-shrink: 0;\n }\n \n ::ng-deep .k-tabstrip-content {\n flex: 1;\n padding: 0;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n \n ::ng-deep .k-item.k-tabstrip-item {\n font-weight: 500;\n \n &.k-active {\n background: white;\n border-bottom-color: white;\n }\n }\n }\n \n .tab-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n &.spec-tab, &.code-tab {\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n \n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\n flex-shrink: 0;\n min-width: 0; // Fix width issue\n \n h4 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 1; // Allow title to shrink\n min-width: 0; // Prevent overflow\n \n i {\n color: #6366f1;\n flex-shrink: 0; // Keep icon from shrinking\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0; // Prevent buttons from shrinking\n \n button {\n min-width: auto;\n padding: 4px 12px;\n font-size: 13px;\n white-space: nowrap; // Prevent button text wrapping\n }\n }\n }\n \n .editor-wrapper {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n }\n \n ::ng-deep .monaco-editor {\n border: 1px solid #dee2e6;\n }\n }\n \n .code-sections {\n height: 100%;\n \n ::ng-deep .k-panelbar-item-header {\n background: #f8f9fa;\n font-weight: 500;\n font-size: 14px;\n }\n \n ::ng-deep .k-panelbar-content {\n padding: 0;\n }\n }\n }\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}"] });
555
1153
  };
556
1154
  ComponentStudioDashboardComponent = __decorate([
557
1155
  RegisterClass(BaseDashboard, 'ComponentStudioDashboard')
@@ -559,9 +1157,12 @@ ComponentStudioDashboardComponent = __decorate([
559
1157
  export { ComponentStudioDashboardComponent };
560
1158
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ComponentStudioDashboardComponent, [{
561
1159
  type: Component,
562
- args: [{ selector: 'mj-component-studio-dashboard', template: "<div class=\"component-studio\">\n <!-- Header -->\n <div class=\"dashboard-header\">\n <div class=\"header-content\">\n <div>\n <h1><i class=\"fa-solid fa-puzzle-piece\"></i> Component Studio</h1>\n <p class=\"header-subtitle\">Testing components without custom properties</p>\n </div>\n <button kendoButton (click)=\"refreshData()\" [disabled]=\"isLoading\">\n <span class=\"fa-solid fa-sync\"></span> Refresh\n </button>\n </div>\n </div>\n\n <!-- Main Content with Splitter -->\n <kendo-splitter orientation=\"horizontal\" style=\"flex: 1; height: auto;\">\n <!-- Left Panel - Component List -->\n <kendo-splitter-pane [min]=\"'350px'\" [max]=\"'600px'\" [size]=\"'400px'\">\n <div class=\"components-panel\">\n <div class=\"panel-header\">\n <h3>Components</h3>\n <div class=\"search-box\">\n <kendo-textbox \n [value]=\"searchQuery\"\n (valueChange)=\"onSearchChange($event)\"\n placeholder=\"Search components...\"\n [clearButton]=\"true\">\n <ng-template kendoTextBoxPrefixTemplate>\n <i class=\"fa-solid fa-search\"></i>\n </ng-template>\n </kendo-textbox>\n </div>\n </div>\n \n <div class=\"components-list\">\n @if (isLoading) {\n <div class=\"loading-message\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading components...\n </div>\n } @else if (filteredComponents.length === 0) {\n <div class=\"empty-message\">\n <i class=\"fa-solid fa-info-circle\"></i> No components found without custom properties.\n <br>\n <small>Only components that don't require custom props can be tested here.</small>\n </div>\n } @else {\n @for (component of filteredComponents; track component.ID) {\n <div class=\"component-card\" \n [class.expanded]=\"expandedComponent?.ID === component.ID\"\n [class.running]=\"selectedComponent?.ID === component.ID && isRunning\">\n \n <!-- Card Header - Always visible -->\n <div class=\"card-header\" (click)=\"toggleComponentExpansion(component)\">\n <div class=\"card-icon\" [style.color]=\"getComponentTypeColor(component.Type)\">\n <i class=\"fa-solid\" [ngClass]=\"getComponentTypeIcon(component.Type)\"></i>\n </div>\n <div class=\"card-info\">\n <div class=\"card-name\">{{ component.Name }}</div>\n <div class=\"card-meta\">\n <span class=\"card-type\">{{ component.Type || 'Component' }}</span>\n <span class=\"card-version\">v{{ component.Version || '1.0.0' }}</span>\n @if (component.Status === 'Published') {\n <span class=\"status-badge published\">Published</span>\n } @else {\n <span class=\"status-badge draft\">Draft</span>\n }\n </div>\n </div>\n <div class=\"card-chevron\">\n @if (expandedComponent?.ID === component.ID) {\n <i class=\"fa-solid fa-chevron-up\"></i>\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i>\n }\n </div>\n </div>\n \n <!-- Card Details - Only visible when expanded -->\n @if (expandedComponent?.ID === component.ID) {\n <div class=\"card-details\">\n @if (component.Description) {\n <div class=\"detail-section\">\n <label>Description</label>\n <p>{{ component.Description }}</p>\n </div>\n }\n \n <div class=\"detail-section\">\n <label>Component Info</label>\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Type:</span>\n <span class=\"info-value\">{{ component.Type || 'Unknown' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Version:</span>\n <span class=\"info-value\">{{ component.Version || '1.0.0' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Status:</span>\n <span class=\"info-value\">{{ component.Status || 'Draft' }}</span>\n </div>\n @if (component.__mj_UpdatedAt) {\n <div class=\"info-item\">\n <span class=\"info-label\">Updated:</span>\n <span class=\"info-value\">{{ component.__mj_UpdatedAt | date:'short' }}</span>\n </div>\n }\n </div>\n </div>\n \n <div class=\"card-actions\">\n @if (selectedComponent?.ID === component.ID && isRunning) {\n <button kendoButton \n [themeColor]=\"'error'\"\n (click)=\"stopComponent(); $event.stopPropagation()\">\n <span class=\"fa-solid fa-stop\"></span> Stop Component\n </button>\n } @else if (isRunning && selectedComponent?.ID !== component.ID) {\n <button kendoButton \n [themeColor]=\"'base'\"\n title=\"Stop current component and run this one\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n <span class=\"fa-solid fa-play\"></span> Switch to This Component\n </button>\n } @else {\n <button kendoButton \n [themeColor]=\"'primary'\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n <span class=\"fa-solid fa-play\"></span> Run Component\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </kendo-splitter-pane>\n\n <!-- Right Panel - Component Display -->\n <kendo-splitter-pane [min]=\"'400px'\">\n <div class=\"component-display\">\n @if (isRunning && selectedComponent && componentSpec) {\n @if (currentError) {\n <!-- Error Display -->\n <div class=\"error-display\">\n <div class=\"error-container\">\n <div class=\"error-header\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <h3>Component Error</h3>\n <button class=\"copy-button\" (click)=\"copyErrorToClipboard()\" title=\"Copy error details\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n \n <p class=\"error-intro\">\n The component could not be rendered due to the following error:\n </p>\n \n <div class=\"error-details\">\n <strong>Error Type:</strong> {{ currentError.type }}<br>\n <strong>Message:</strong> {{ currentError.message }}\n @if (currentError.technicalDetails) {\n <details class=\"technical-details\">\n <summary>Technical Details (click to expand)</summary>\n <pre>{{ formatTechnicalDetails(currentError.technicalDetails) }}</pre>\n </details>\n }\n </div>\n \n <div class=\"error-help\">\n <strong>What to do:</strong>\n <ol>\n <li>Check that the component code is valid JavaScript/React</li>\n <li>Ensure all required dependencies are available</li>\n <li>Review the technical details for specific error information</li>\n <li>Contact your system administrator if the issue persists</li>\n </ol>\n </div>\n \n <div class=\"error-actions\">\n <button kendoButton (click)=\"retryComponent()\">\n <span class=\"fa-solid fa-rotate\"></span> Retry\n </button>\n <button kendoButton (click)=\"stopComponent()\" [themeColor]=\"'error'\">\n <span class=\"fa-solid fa-stop\"></span> Stop\n </button>\n </div>\n </div>\n </div>\n } @else {\n <!-- React Component -->\n <mj-react-component \n [component]=\"componentSpec\"\n (componentEvent)=\"onComponentEvent($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-react-component>\n }\n } @else {\n <!-- Empty State -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-rocket fa-3x\"></i>\n <h2>Ready to Test Components</h2>\n <p>Select a component from the list and click \"Run Component\" to see it in action</p>\n </div>\n }\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n</div>", styles: [":host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f8f9fa;\n overflow: hidden;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n \n .header-subtitle {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: #6c757d;\n font-weight: normal;\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #212529;\n }\n \n .search-box {\n kendo-textbox {\n width: 100%;\n }\n }\n }\n \n .components-list {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n background: linear-gradient(to right, rgba(16, 185, 129, 0.03) 0%, white 100%);\n \n .card-header {\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n background: #10b981;\n }\n }\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n position: relative;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n }\n }\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}"] }]
563
- }], () => [{ type: i0.ChangeDetectorRef }], null); })();
564
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ComponentStudioDashboardComponent, { className: "ComponentStudioDashboardComponent", filePath: "src/ComponentStudio/component-studio-dashboard.component.ts", lineNumber: 18 }); })();
1160
+ args: [{ selector: 'mj-component-studio-dashboard', template: "<div class=\"component-studio\">\n <!-- Header -->\n <div class=\"dashboard-header\">\n <div class=\"header-content\">\n <div>\n <h1><i class=\"fa-solid fa-puzzle-piece\"></i> Component Studio</h1>\n <p class=\"header-subtitle\">Testing components without custom properties</p>\n </div>\n <div class=\"header-buttons\">\n @if (selectedComponent && isRunning) {\n <button kendoButton (click)=\"toggleDetailsPane()\" [themeColor]=\"'base'\">\n @if (isDetailsPaneCollapsed) {\n <span class=\"fa-solid fa-eye\"></span> Show Details\n } @else {\n <span class=\"fa-solid fa-eye-slash\"></span> Hide Details\n }\n </button>\n }\n <button kendoButton (click)=\"triggerFileInput()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-file-import\"></span> Import from File\n </button>\n <button kendoButton (click)=\"refreshData()\" [disabled]=\"isLoading\">\n <span class=\"fa-solid fa-sync\"></span> Refresh\n </button>\n </div>\n <!-- Hidden file input -->\n <input #fileInput type=\"file\" accept=\".json\" (change)=\"handleFileSelect($event)\" style=\"display: none;\" />\n </div>\n </div>\n\n <!-- Main Content with Splitter -->\n <kendo-splitter orientation=\"horizontal\" style=\"flex: 1; height: auto;\">\n <!-- Left Panel - Component List -->\n <kendo-splitter-pane [min]=\"'350px'\" [max]=\"'600px'\" [size]=\"'400px'\">\n <div class=\"components-panel\">\n <div class=\"panel-header\">\n <h3>Components</h3>\n <div class=\"search-box\">\n <kendo-textbox \n [value]=\"searchQuery\"\n (valueChange)=\"onSearchChange($event)\"\n placeholder=\"Search components...\"\n [clearButton]=\"true\">\n <ng-template kendoTextBoxPrefixTemplate>\n <i class=\"fa-solid fa-search\"></i>\n </ng-template>\n </kendo-textbox>\n </div>\n </div>\n \n <div class=\"components-list\">\n @if (isLoading) {\n <div class=\"loading-message\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading components...\n </div>\n } @else if (filteredComponents.length === 0) {\n <div class=\"empty-message\">\n <i class=\"fa-solid fa-info-circle\"></i> No components found without custom properties.\n <br>\n <small>Only components that don't require custom props can be tested here.</small>\n </div>\n } @else {\n @for (component of filteredComponents; track getComponentId(component)) {\n <div class=\"component-card\" \n [class.expanded]=\"expandedComponent && getComponentId(expandedComponent) === getComponentId(component)\"\n [class.running]=\"selectedComponent && getComponentId(selectedComponent) === getComponentId(component) && isRunning\"\n [class.file-loaded]=\"isFileLoadedComponent(component)\">\n \n <!-- Card Header - Always visible -->\n <div class=\"card-header\" (click)=\"toggleComponentExpansion(component)\">\n <div class=\"card-icon\" [style.color]=\"getComponentTypeColor(getComponentType(component))\">\n <i class=\"fa-solid\" [ngClass]=\"getComponentTypeIcon(getComponentType(component))\"></i>\n </div>\n <div class=\"card-info\">\n <div class=\"card-name\">\n {{ getComponentName(component) }}\n @if (isFileLoadedComponent(component)) {\n <span class=\"file-badge\" title=\"Loaded from {{ getComponentFilename(component) }}\">\n <i class=\"fa-solid fa-file\"></i> {{ getComponentFilename(component) }}\n </span>\n }\n </div>\n <div class=\"card-meta\">\n <span class=\"card-type\">{{ getComponentType(component) || 'Component' }}</span>\n <span class=\"card-version\">v{{ getComponentVersion(component) }}</span>\n @if (isFileLoadedComponent(component)) {\n <span class=\"status-badge file\">File</span>\n } @else if (getComponentStatus(component) === 'Published') {\n <span class=\"status-badge published\">Published</span>\n } @else {\n <span class=\"status-badge draft\">Draft</span>\n }\n </div>\n </div>\n <div class=\"card-chevron\">\n @if (expandedComponent && getComponentId(expandedComponent) === getComponentId(component)) {\n <i class=\"fa-solid fa-chevron-up\"></i>\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i>\n }\n </div>\n </div>\n \n <!-- Card Details - Only visible when expanded -->\n @if (expandedComponent && getComponentId(expandedComponent) === getComponentId(component)) {\n <div class=\"card-details\">\n @if (getComponentDescription(component)) {\n <div class=\"detail-section\">\n <label>Description</label>\n <p>{{ getComponentDescription(component) }}</p>\n </div>\n }\n \n <div class=\"detail-section\">\n <label>Component Info</label>\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Type:</span>\n <span class=\"info-value\">{{ getComponentType(component) || 'Unknown' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Version:</span>\n <span class=\"info-value\">{{ getComponentVersion(component) }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Status:</span>\n <span class=\"info-value\">{{ getComponentStatus(component) || 'Draft' }}</span>\n </div>\n @if (isFileLoadedComponent(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Loaded:</span>\n <span class=\"info-value\">{{ getComponentLoadedAt(component) | date:'short' }}</span>\n </div>\n } @else if (!isFileLoadedComponent(component) && getComponentUpdatedAt(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Updated:</span>\n <span class=\"info-value\">{{ getComponentUpdatedAt(component) | date:'short' }}</span>\n </div>\n }\n </div>\n </div>\n \n <div class=\"card-actions\">\n @if (selectedComponent && getComponentId(selectedComponent) === getComponentId(component) && isRunning) {\n <button kendoButton \n [themeColor]=\"'error'\"\n (click)=\"stopComponent(); $event.stopPropagation()\">\n <span class=\"fa-solid fa-stop\"></span> Stop Component\n </button>\n } @else if (isRunning && selectedComponent && getComponentId(selectedComponent) !== getComponentId(component)) {\n <button kendoButton \n [themeColor]=\"'base'\"\n title=\"Stop current component and run this one\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n <span class=\"fa-solid fa-play\"></span> Switch to This Component\n </button>\n } @else {\n <button kendoButton \n [themeColor]=\"'primary'\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n <span class=\"fa-solid fa-play\"></span> Run Component\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </kendo-splitter-pane>\n\n <!-- Right Panel - Component Display with Editor Splitter -->\n <kendo-splitter-pane [min]=\"'400px'\">\n <div class=\"component-display\">\n @if (selectedComponent) {\n <!-- Splitter for component and editors -->\n <kendo-splitter orientation=\"horizontal\" class=\"component-editor-splitter\">\n <!-- Left side - Running Component -->\n <kendo-splitter-pane [min]=\"'300px'\" [collapsible]=\"false\" [size]=\"isDetailsPaneCollapsed ? '100%' : '50%'\">\n <div class=\"component-runtime\">\n @if (isRunning && componentSpec) {\n @if (currentError) {\n <!-- Error Display -->\n <div class=\"error-display\">\n <div class=\"error-container\">\n <div class=\"error-header\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <h3>Component Error</h3>\n <button class=\"copy-button\" (click)=\"copyErrorToClipboard()\" title=\"Copy error details\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n \n <p class=\"error-intro\">\n The component could not be rendered due to the following error:\n </p>\n \n <div class=\"error-details\">\n <strong>Error Type:</strong> {{ currentError.type }}<br>\n <strong>Message:</strong> {{ currentError.message }}\n @if (currentError.technicalDetails) {\n <details class=\"technical-details\">\n <summary>Technical Details (click to expand)</summary>\n <pre>{{ formatTechnicalDetails(currentError.technicalDetails) }}</pre>\n </details>\n }\n </div>\n \n <div class=\"error-help\">\n <strong>What to do:</strong>\n <ol>\n <li>Check that the component code is valid JavaScript/React</li>\n <li>Ensure all required dependencies are available</li>\n <li>Review the technical details for specific error information</li>\n <li>Contact your system administrator if the issue persists</li>\n </ol>\n </div>\n \n <div class=\"error-actions\">\n <button kendoButton (click)=\"retryComponent()\">\n <span class=\"fa-solid fa-rotate\"></span> Retry\n </button>\n <button kendoButton (click)=\"stopComponent()\" [themeColor]=\"'error'\">\n <span class=\"fa-solid fa-stop\"></span> Stop\n </button>\n </div>\n </div>\n </div>\n } @else {\n <!-- React Component -->\n <mj-react-component \n [component]=\"componentSpec\"\n (componentEvent)=\"onComponentEvent($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-react-component>\n }\n } @else {\n <!-- Component Not Running State -->\n <div class=\"run-empty-state\">\n <i class=\"fa-solid fa-play-circle fa-3x\"></i>\n <h3>Component: {{ getComponentName(selectedComponent) }}</h3>\n <p>{{ getComponentDescription(selectedComponent) || 'No description available' }}</p>\n <button kendoButton [themeColor]=\"'primary'\" [size]=\"'large'\" (click)=\"runComponent(selectedComponent)\">\n <span class=\"fa-solid fa-play\"></span> Run Component\n </button>\n </div>\n }\n </div>\n </kendo-splitter-pane>\n \n <!-- Right side - Spec and Code Editors -->\n <kendo-splitter-pane [min]=\"'400px'\" [collapsible]=\"true\" [collapsed]=\"isDetailsPaneCollapsed\">\n <kendo-tabstrip (tabSelect)=\"onTabSelect($event)\" class=\"editor-tabs\">\n <!-- Spec Tab -->\n <kendo-tabstrip-tab [title]=\"'Spec'\" [selected]=\"activeTab === 0\">\n <ng-template kendoTabContent>\n <div class=\"tab-content spec-tab\">\n <div class=\"editor-header\">\n <h4><i class=\"fa-solid fa-code\"></i> Component Specification (JSON)</h4>\n <div class=\"editor-actions\">\n @if (isEditingSpec) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"applySpecChanges()\">\n <span class=\"fa-solid fa-check\"></span> Apply Changes\n </button>\n <button kendoButton (click)=\"initializeEditors()\">\n <span class=\"fa-solid fa-times\"></span> Cancel\n </button>\n }\n @if (isRunning) {\n <button kendoButton (click)=\"refreshComponent()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-sync\"></span> Refresh Component\n </button>\n }\n </div>\n </div>\n <div class=\"editor-wrapper\">\n <mj-code-editor\n [(ngModel)]=\"editableSpec\"\n (ngModelChange)=\"onSpecChange($event)\"\n [language]=\"'json'\"\n [readonly]=\"false\"\n style=\"height: 100%; width: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n </ng-template>\n </kendo-tabstrip-tab>\n \n <!-- Code Tab -->\n <kendo-tabstrip-tab [title]=\"'Code'\" [selected]=\"activeTab === 1\">\n <ng-template kendoTabContent>\n <div class=\"tab-content code-tab\">\n <div class=\"editor-header\">\n <h4><i class=\"fa-solid fa-file-code\"></i> Component Code (JavaScript/React)</h4>\n <div class=\"editor-actions\">\n @if (isEditingCode) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"applyCodeChanges()\">\n <span class=\"fa-solid fa-check\"></span> Apply Changes\n </button>\n <button kendoButton (click)=\"initializeEditors()\">\n <span class=\"fa-solid fa-times\"></span> Cancel\n </button>\n }\n @if (isRunning) {\n <button kendoButton (click)=\"refreshComponent()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-sync\"></span> Refresh Component\n </button>\n }\n </div>\n </div>\n \n <!-- Always use panel bar for consistency and to show all components -->\n <div class=\"editor-wrapper\">\n <kendo-panelbar class=\"code-sections\">\n @for (section of getComponentCodeSections(); track section.title; let i = $index) {\n <kendo-panelbar-item [title]=\"section.title\" [expanded]=\"section.expanded\">\n <ng-template kendoPanelBarContent>\n <mj-code-editor\n [ngModel]=\"section.code\"\n (ngModelChange)=\"onCodeSectionChange($event, i)\"\n [language]=\"'javascript'\"\n [readonly]=\"false\"\n style=\"height: 400px; width: 100%;\">\n </mj-code-editor>\n </ng-template>\n </kendo-panelbar-item>\n }\n </kendo-panelbar>\n </div>\n </div>\n </ng-template>\n </kendo-tabstrip-tab>\n </kendo-tabstrip>\n </kendo-splitter-pane>\n </kendo-splitter>\n } @else {\n <!-- Empty State when no component selected -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-rocket fa-3x\"></i>\n <h2>Ready to Test Components</h2>\n <p>Select a component from the list to view its details and run it</p>\n </div>\n }\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n</div>", styles: [":host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio {\n display: flex;\n flex-direction: column;\n height: 100vh;\n background: #f8f9fa;\n overflow: hidden;\n position: relative;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n .header-buttons {\n display: flex;\n gap: 8px;\n }\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n \n .header-subtitle {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: #6c757d;\n font-weight: normal;\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n \n ::ng-deep .k-pane {\n overflow: hidden;\n height: 100%;\n }\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #212529;\n }\n \n .search-box {\n kendo-textbox {\n width: 100%;\n }\n }\n }\n \n .components-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n background: linear-gradient(to right, rgba(16, 185, 129, 0.03) 0%, white 100%);\n \n .card-header {\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n background: #10b981;\n }\n }\n }\n \n &.file-loaded {\n background: linear-gradient(135deg, #f0f8ff 0%, white 100%);\n border-style: dashed;\n border-color: #3b82f6;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n \n &.expanded {\n border-style: solid;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n }\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n position: relative;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 8px;\n \n .file-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n background: #e0f2fe;\n color: #0369a1;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n flex-shrink: 0;\n \n i {\n font-size: 10px;\n }\n }\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n \n &.file {\n background: #e0f2fe;\n color: #0369a1;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow: hidden;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n display: block;\n overflow-y: auto;\n overflow-x: hidden;\n }\n \n // Component and editor splitter\n .component-editor-splitter {\n height: 100%;\n overflow: hidden;\n \n ::ng-deep .k-splitter-bar {\n background: #6366f1; // Same blue as Import button\n width: 6px; // Make it slightly wider for visibility\n \n &:hover {\n background: #4f52d9; // Darker blue on hover\n }\n \n .k-resize-handle {\n background-color: rgba(255, 255, 255, 0.3);\n }\n }\n \n ::ng-deep .k-pane {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n }\n \n // Component runtime area\n .component-runtime {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow-y: auto;\n overflow-x: hidden;\n \n .run-empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px;\n text-align: center;\n \n i {\n color: #10b981;\n margin-bottom: 24px;\n }\n \n h3 {\n margin: 0 0 12px 0;\n font-size: 20px;\n font-weight: 600;\n color: #212529;\n }\n \n p {\n margin: 0 0 24px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n }\n }\n }\n \n // Editor tabs on the right\n .editor-tabs {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n ::ng-deep .k-tabstrip-items-wrapper {\n background: #f8f9fa;\n border-bottom: 2px solid #dee2e6;\n flex-shrink: 0;\n }\n \n ::ng-deep .k-tabstrip-content {\n flex: 1;\n padding: 0;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n \n ::ng-deep .k-item.k-tabstrip-item {\n font-weight: 500;\n \n &.k-active {\n background: white;\n border-bottom-color: white;\n }\n }\n }\n \n .tab-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n &.spec-tab, &.code-tab {\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n \n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\n flex-shrink: 0;\n min-width: 0; // Fix width issue\n \n h4 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 1; // Allow title to shrink\n min-width: 0; // Prevent overflow\n \n i {\n color: #6366f1;\n flex-shrink: 0; // Keep icon from shrinking\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0; // Prevent buttons from shrinking\n \n button {\n min-width: auto;\n padding: 4px 12px;\n font-size: 13px;\n white-space: nowrap; // Prevent button text wrapping\n }\n }\n }\n \n .editor-wrapper {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n }\n \n ::ng-deep .monaco-editor {\n border: 1px solid #dee2e6;\n }\n }\n \n .code-sections {\n height: 100%;\n \n ::ng-deep .k-panelbar-item-header {\n background: #f8f9fa;\n font-weight: 500;\n font-size: 14px;\n }\n \n ::ng-deep .k-panelbar-content {\n padding: 0;\n }\n }\n }\n }\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}"] }]
1161
+ }], () => [{ type: i0.ChangeDetectorRef }], { fileInput: [{
1162
+ type: ViewChild,
1163
+ args: ['fileInput', { static: false }]
1164
+ }] }); })();
1165
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ComponentStudioDashboardComponent, { className: "ComponentStudioDashboardComponent", filePath: "src/ComponentStudio/component-studio-dashboard.component.ts", lineNumber: 35 }); })();
565
1166
  /**
566
1167
  * Function to prevent tree shaking of the ComponentStudioDashboardComponent.
567
1168
  */