@memberjunction/ng-skip-chat 2.43.0 → 2.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +99 -7
  2. package/dist/lib/artifacts/skip-artifact-viewer.component.d.ts +33 -1
  3. package/dist/lib/artifacts/skip-artifact-viewer.component.d.ts.map +1 -1
  4. package/dist/lib/artifacts/skip-artifact-viewer.component.js +82 -86
  5. package/dist/lib/artifacts/skip-artifact-viewer.component.js.map +1 -1
  6. package/dist/lib/dynamic-report/base-report.d.ts.map +1 -1
  7. package/dist/lib/dynamic-report/base-report.js +2 -1
  8. package/dist/lib/dynamic-report/base-report.js.map +1 -1
  9. package/dist/lib/dynamic-report/dynamic-chart.d.ts.map +1 -1
  10. package/dist/lib/dynamic-report/dynamic-chart.js +5 -2
  11. package/dist/lib/dynamic-report/dynamic-chart.js.map +1 -1
  12. package/dist/lib/dynamic-report/dynamic-grid.d.ts.map +1 -1
  13. package/dist/lib/dynamic-report/dynamic-grid.js +6 -3
  14. package/dist/lib/dynamic-report/dynamic-grid.js.map +1 -1
  15. package/dist/lib/dynamic-report/dynamic-html-report.d.ts +90 -11
  16. package/dist/lib/dynamic-report/dynamic-html-report.d.ts.map +1 -1
  17. package/dist/lib/dynamic-report/dynamic-html-report.js +1001 -163
  18. package/dist/lib/dynamic-report/dynamic-html-report.js.map +1 -1
  19. package/dist/lib/dynamic-report/linear-report.d.ts +4 -0
  20. package/dist/lib/dynamic-report/linear-report.d.ts.map +1 -1
  21. package/dist/lib/dynamic-report/linear-report.js +78 -76
  22. package/dist/lib/dynamic-report/linear-report.js.map +1 -1
  23. package/dist/lib/dynamic-report/skip-react-component-host.d.ts +106 -0
  24. package/dist/lib/dynamic-report/skip-react-component-host.d.ts.map +1 -0
  25. package/dist/lib/dynamic-report/skip-react-component-host.js +450 -0
  26. package/dist/lib/dynamic-report/skip-react-component-host.js.map +1 -0
  27. package/dist/lib/skip-chat/skip-chat.component.d.ts +54 -0
  28. package/dist/lib/skip-chat/skip-chat.component.d.ts.map +1 -1
  29. package/dist/lib/skip-chat/skip-chat.component.js +107 -6
  30. package/dist/lib/skip-chat/skip-chat.component.js.map +1 -1
  31. package/dist/lib/split-panel/skip-split-panel.component.d.ts +18 -1
  32. package/dist/lib/split-panel/skip-split-panel.component.d.ts.map +1 -1
  33. package/dist/lib/split-panel/skip-split-panel.component.js +135 -8
  34. package/dist/lib/split-panel/skip-split-panel.component.js.map +1 -1
  35. package/package.json +17 -13
@@ -7,45 +7,459 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
11
- import { CompositeKey, LogError, Metadata } from '@memberjunction/core';
10
+ import { Component, EventEmitter, Input, Output, ViewChildren } from '@angular/core';
11
+ import { CompositeKey, LogError, Metadata, RunQuery, RunView } from '@memberjunction/core';
12
+ import { SkipReactComponentHost } from './skip-react-component-host';
13
+ import { MapEntityInfoToSkipEntityInfo, BuildSkipComponentCompleteCode } from '@memberjunction/skip-types';
12
14
  import { DrillDownInfo } from '../drill-down-info';
13
15
  import * as i0 from "@angular/core";
14
16
  import * as i1 from "@angular/common";
15
- import * as i2 from "@memberjunction/ng-container-directives";
17
+ import * as i2 from "@progress/kendo-angular-layout";
16
18
  import * as i3 from "@progress/kendo-angular-buttons";
17
19
  const _c0 = ["htmlContainer"];
18
- function SkipDynamicHTMLReportComponent_button_0_Template(rf, ctx) { if (rf & 1) {
20
+ function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
21
+ i0.ɵɵelement(0, "i", 7);
22
+ } }
23
+ function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_1_Template(rf, ctx) { if (rf & 1) {
24
+ i0.ɵɵtemplate(0, SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_1_Conditional_0_Template, 1, 0, "i", 7);
25
+ i0.ɵɵtext(1);
26
+ } if (rf & 2) {
27
+ const ɵ$index_4_r3 = i0.ɵɵnextContext().$index;
28
+ const ctx_r1 = i0.ɵɵnextContext(2);
29
+ i0.ɵɵconditional(ctx_r1.isTopRanked(ɵ$index_4_r3) ? 0 : -1);
30
+ i0.ɵɵadvance();
31
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.getTabTitle(ɵ$index_4_r3), " ");
32
+ } }
33
+ function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_button_4_Template(rf, ctx) { if (rf & 1) {
34
+ const _r4 = i0.ɵɵgetCurrentView();
35
+ i0.ɵɵelementStart(0, "button", 15);
36
+ i0.ɵɵlistener("click", function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_button_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ɵ$index_4_r3 = i0.ɵɵnextContext(2).$index; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.createReportForOption(ɵ$index_4_r3)); });
37
+ i0.ɵɵelement(1, "i", 16);
38
+ i0.ɵɵelementStart(2, "span");
39
+ i0.ɵɵtext(3, "Create Report");
40
+ i0.ɵɵelementEnd()();
41
+ } if (rf & 2) {
42
+ const ctx_r1 = i0.ɵɵnextContext(4);
43
+ i0.ɵɵproperty("disabled", ctx_r1.isCreatingReport);
44
+ } }
45
+ function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_button_5_Template(rf, ctx) { if (rf & 1) {
46
+ const _r5 = i0.ɵɵgetCurrentView();
47
+ i0.ɵɵelementStart(0, "button", 17);
48
+ i0.ɵɵlistener("click", function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_button_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.PrintReport()); });
49
+ i0.ɵɵelement(1, "i", 18);
50
+ i0.ɵɵelementStart(2, "span");
51
+ i0.ɵɵtext(3, "Print Report");
52
+ i0.ɵɵelementEnd()();
53
+ } }
54
+ function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_Conditional_8_Conditional_19_Template(rf, ctx) { if (rf & 1) {
55
+ i0.ɵɵelementStart(0, "details", 27)(1, "summary", 33);
56
+ i0.ɵɵtext(2, "Technical Details (click to expand)");
57
+ i0.ɵɵelementEnd();
58
+ i0.ɵɵelementStart(3, "pre", 34);
59
+ i0.ɵɵtext(4);
60
+ i0.ɵɵelementEnd()();
61
+ } if (rf & 2) {
62
+ const ctx_r1 = i0.ɵɵnextContext(5);
63
+ i0.ɵɵadvance(4);
64
+ i0.ɵɵtextInterpolate(ctx_r1.currentError.technicalDetails);
65
+ } }
66
+ function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
67
+ const _r6 = i0.ɵɵgetCurrentView();
68
+ i0.ɵɵelementStart(0, "div", 14)(1, "div", 19)(2, "div", 20)(3, "button", 21);
69
+ i0.ɵɵlistener("click", function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_Conditional_8_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.copyErrorToClipboard()); });
70
+ i0.ɵɵelement(4, "span", 22);
71
+ i0.ɵɵtext(5, " Copy Error Details ");
72
+ i0.ɵɵelementEnd();
73
+ i0.ɵɵelementStart(6, "h3", 23);
74
+ i0.ɵɵelement(7, "span", 24);
75
+ i0.ɵɵtext(8, " Component Rendering Error ");
76
+ i0.ɵɵelementEnd()();
77
+ i0.ɵɵelementStart(9, "p", 25);
78
+ i0.ɵɵtext(10, " The selected component option could not be rendered due to the following error: ");
79
+ i0.ɵɵelementEnd();
80
+ i0.ɵɵelementStart(11, "div", 26)(12, "strong");
81
+ i0.ɵɵtext(13, "Error Type:");
82
+ i0.ɵɵelementEnd();
83
+ i0.ɵɵtext(14);
84
+ i0.ɵɵelement(15, "br");
85
+ i0.ɵɵelementStart(16, "strong");
86
+ i0.ɵɵtext(17, "Details:");
87
+ i0.ɵɵelementEnd();
88
+ i0.ɵɵtext(18);
89
+ i0.ɵɵtemplate(19, SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_Conditional_8_Conditional_19_Template, 5, 1, "details", 27);
90
+ i0.ɵɵelementEnd();
91
+ i0.ɵɵelementStart(20, "div", 28)(21, "strong", 29);
92
+ i0.ɵɵtext(22, "What to do:");
93
+ i0.ɵɵelementEnd();
94
+ i0.ɵɵelementStart(23, "ol", 30)(24, "li");
95
+ i0.ɵɵtext(25, "Try selecting a different report option from the tabs above");
96
+ i0.ɵɵelementEnd();
97
+ i0.ɵɵelementStart(26, "li");
98
+ i0.ɵɵtext(27, "Copy the error details and send them back to Skip in the chat to get a corrected version");
99
+ i0.ɵɵelementEnd();
100
+ i0.ɵɵelementStart(28, "li");
101
+ i0.ɵɵtext(29, "Contact your IT department if the issue persists");
102
+ i0.ɵɵelementEnd()()();
103
+ i0.ɵɵelementStart(30, "button", 31);
104
+ i0.ɵɵlistener("click", function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_Conditional_8_Template_button_click_30_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.retryCurrentOption()); });
105
+ i0.ɵɵelement(31, "span", 32);
106
+ i0.ɵɵtext(32, " Retry ");
107
+ i0.ɵɵelementEnd()()();
108
+ } if (rf & 2) {
109
+ const ctx_r1 = i0.ɵɵnextContext(4);
110
+ i0.ɵɵadvance(14);
111
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.currentError.type, "");
112
+ i0.ɵɵadvance(4);
113
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.currentError.message, " ");
114
+ i0.ɵɵadvance();
115
+ i0.ɵɵconditional(ctx_r1.currentError.technicalDetails ? 19 : -1);
116
+ } }
117
+ function SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_Template(rf, ctx) { if (rf & 1) {
118
+ i0.ɵɵelementStart(0, "div", 2)(1, "div", 8);
119
+ i0.ɵɵelement(2, "div", 9);
120
+ i0.ɵɵelementStart(3, "div", 10);
121
+ i0.ɵɵtemplate(4, SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_button_4_Template, 4, 1, "button", 11)(5, SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_button_5_Template, 4, 0, "button", 12);
122
+ i0.ɵɵelementEnd()();
123
+ i0.ɵɵelementStart(6, "div", 13, 0);
124
+ i0.ɵɵtemplate(8, SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_Conditional_8_Template, 33, 3, "div", 14);
125
+ i0.ɵɵelementEnd()();
126
+ } if (rf & 2) {
127
+ const ɵ$index_4_r3 = i0.ɵɵnextContext().$index;
128
+ const ctx_r1 = i0.ɵɵnextContext(2);
129
+ i0.ɵɵadvance(4);
130
+ i0.ɵɵproperty("ngIf", ctx_r1.ShowCreateReportButton && !ctx_r1.matchingReportID);
131
+ i0.ɵɵadvance();
132
+ i0.ɵɵproperty("ngIf", ctx_r1.ShowPrintReport);
133
+ i0.ɵɵadvance();
134
+ i0.ɵɵattribute("data-tab-index", ɵ$index_4_r3);
135
+ i0.ɵɵadvance(2);
136
+ i0.ɵɵconditional(ctx_r1.currentError && ctx_r1.selectedReportOptionIndex === ɵ$index_4_r3 ? 8 : -1);
137
+ } }
138
+ function SkipDynamicHTMLReportComponent_Conditional_0_For_2_Template(rf, ctx) { if (rf & 1) {
139
+ i0.ɵɵelementStart(0, "kendo-tabstrip-tab", 4);
140
+ i0.ɵɵtemplate(1, SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_1_Template, 2, 2, "ng-template", 5)(2, SkipDynamicHTMLReportComponent_Conditional_0_For_2_ng_template_2_Template, 9, 4, "ng-template", 6);
141
+ i0.ɵɵelementEnd();
142
+ } if (rf & 2) {
143
+ const ɵ$index_4_r3 = ctx.$index;
144
+ const ctx_r1 = i0.ɵɵnextContext(2);
145
+ i0.ɵɵproperty("selected", ɵ$index_4_r3 === ctx_r1.selectedReportOptionIndex);
146
+ } }
147
+ function SkipDynamicHTMLReportComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
19
148
  const _r1 = i0.ɵɵgetCurrentView();
20
- i0.ɵɵelementStart(0, "button", 3);
21
- i0.ɵɵlistener("click", function SkipDynamicHTMLReportComponent_button_0_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.PrintReport()); });
22
- i0.ɵɵelement(1, "span", 4);
23
- i0.ɵɵtext(2, " Print ");
149
+ i0.ɵɵelementStart(0, "kendo-tabstrip", 3);
150
+ i0.ɵɵlistener("tabSelect", function SkipDynamicHTMLReportComponent_Conditional_0_Template_kendo_tabstrip_tabSelect_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onTabSelect($event)); });
151
+ i0.ɵɵrepeaterCreate(1, SkipDynamicHTMLReportComponent_Conditional_0_For_2_Template, 3, 1, "kendo-tabstrip-tab", 4, i0.ɵɵrepeaterTrackByIdentity);
152
+ i0.ɵɵelementEnd();
153
+ } if (rf & 2) {
154
+ const ctx_r1 = i0.ɵɵnextContext();
155
+ i0.ɵɵproperty("keepTabContent", true);
156
+ i0.ɵɵadvance();
157
+ i0.ɵɵrepeater(ctx_r1.reportOptions);
158
+ } }
159
+ function SkipDynamicHTMLReportComponent_Conditional_1_button_4_Template(rf, ctx) { if (rf & 1) {
160
+ const _r7 = i0.ɵɵgetCurrentView();
161
+ i0.ɵɵelementStart(0, "button", 15);
162
+ i0.ɵɵlistener("click", function SkipDynamicHTMLReportComponent_Conditional_1_button_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.createReportForOption(0)); });
163
+ i0.ɵɵelement(1, "i", 16);
164
+ i0.ɵɵelementStart(2, "span");
165
+ i0.ɵɵtext(3, "Create Report");
166
+ i0.ɵɵelementEnd()();
167
+ } if (rf & 2) {
168
+ const ctx_r1 = i0.ɵɵnextContext(2);
169
+ i0.ɵɵproperty("disabled", ctx_r1.isCreatingReport);
170
+ } }
171
+ function SkipDynamicHTMLReportComponent_Conditional_1_button_5_Template(rf, ctx) { if (rf & 1) {
172
+ const _r8 = i0.ɵɵgetCurrentView();
173
+ i0.ɵɵelementStart(0, "button", 17);
174
+ i0.ɵɵlistener("click", function SkipDynamicHTMLReportComponent_Conditional_1_button_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.PrintReport()); });
175
+ i0.ɵɵelement(1, "i", 18);
176
+ i0.ɵɵelementStart(2, "span");
177
+ i0.ɵɵtext(3, "Print Report");
178
+ i0.ɵɵelementEnd()();
179
+ } }
180
+ function SkipDynamicHTMLReportComponent_Conditional_1_Conditional_8_Conditional_19_Template(rf, ctx) { if (rf & 1) {
181
+ i0.ɵɵelementStart(0, "details", 27)(1, "summary", 33);
182
+ i0.ɵɵtext(2, "Technical Details (click to expand)");
183
+ i0.ɵɵelementEnd();
184
+ i0.ɵɵelementStart(3, "pre", 34);
185
+ i0.ɵɵtext(4);
186
+ i0.ɵɵelementEnd()();
187
+ } if (rf & 2) {
188
+ const ctx_r1 = i0.ɵɵnextContext(3);
189
+ i0.ɵɵadvance(4);
190
+ i0.ɵɵtextInterpolate(ctx_r1.currentError.technicalDetails);
191
+ } }
192
+ function SkipDynamicHTMLReportComponent_Conditional_1_Conditional_8_Template(rf, ctx) { if (rf & 1) {
193
+ const _r9 = i0.ɵɵgetCurrentView();
194
+ i0.ɵɵelementStart(0, "div", 35)(1, "div", 19)(2, "div", 20)(3, "button", 21);
195
+ i0.ɵɵlistener("click", function SkipDynamicHTMLReportComponent_Conditional_1_Conditional_8_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.copyErrorToClipboard()); });
196
+ i0.ɵɵelement(4, "span", 22);
197
+ i0.ɵɵtext(5, " Copy Error Details ");
198
+ i0.ɵɵelementEnd();
199
+ i0.ɵɵelementStart(6, "h3", 23);
200
+ i0.ɵɵelement(7, "span", 24);
201
+ i0.ɵɵtext(8, " Component Rendering Error ");
202
+ i0.ɵɵelementEnd()();
203
+ i0.ɵɵelementStart(9, "p", 25);
204
+ i0.ɵɵtext(10, " The selected component option could not be rendered due to the following error: ");
205
+ i0.ɵɵelementEnd();
206
+ i0.ɵɵelementStart(11, "div", 26)(12, "strong");
207
+ i0.ɵɵtext(13, "Error Type:");
208
+ i0.ɵɵelementEnd();
209
+ i0.ɵɵtext(14);
210
+ i0.ɵɵelement(15, "br");
211
+ i0.ɵɵelementStart(16, "strong");
212
+ i0.ɵɵtext(17, "Details:");
213
+ i0.ɵɵelementEnd();
214
+ i0.ɵɵtext(18);
215
+ i0.ɵɵtemplate(19, SkipDynamicHTMLReportComponent_Conditional_1_Conditional_8_Conditional_19_Template, 5, 1, "details", 27);
216
+ i0.ɵɵelementEnd();
217
+ i0.ɵɵelementStart(20, "div", 28)(21, "strong", 29);
218
+ i0.ɵɵtext(22, "What to do:");
219
+ i0.ɵɵelementEnd();
220
+ i0.ɵɵelementStart(23, "ol", 30)(24, "li");
221
+ i0.ɵɵtext(25, "Copy the error details and send them back to Skip in the chat to get a corrected version");
24
222
  i0.ɵɵelementEnd();
223
+ i0.ɵɵelementStart(26, "li");
224
+ i0.ɵɵtext(27, "Contact your IT department if the issue persists");
225
+ i0.ɵɵelementEnd()()();
226
+ i0.ɵɵelementStart(28, "button", 31);
227
+ i0.ɵɵlistener("click", function SkipDynamicHTMLReportComponent_Conditional_1_Conditional_8_Template_button_click_28_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.retryCurrentOption()); });
228
+ i0.ɵɵelement(29, "span", 32);
229
+ i0.ɵɵtext(30, " Retry ");
230
+ i0.ɵɵelementEnd()()();
231
+ } if (rf & 2) {
232
+ const ctx_r1 = i0.ɵɵnextContext(2);
233
+ i0.ɵɵadvance(14);
234
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.currentError.type, "");
235
+ i0.ɵɵadvance(4);
236
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.currentError.message, " ");
237
+ i0.ɵɵadvance();
238
+ i0.ɵɵconditional(ctx_r1.currentError.technicalDetails ? 19 : -1);
239
+ } }
240
+ function SkipDynamicHTMLReportComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
241
+ i0.ɵɵelementStart(0, "div", 2)(1, "div", 8);
242
+ i0.ɵɵelement(2, "div", 9);
243
+ i0.ɵɵelementStart(3, "div", 10);
244
+ i0.ɵɵtemplate(4, SkipDynamicHTMLReportComponent_Conditional_1_button_4_Template, 4, 1, "button", 11)(5, SkipDynamicHTMLReportComponent_Conditional_1_button_5_Template, 4, 0, "button", 12);
245
+ i0.ɵɵelementEnd()();
246
+ i0.ɵɵelementStart(6, "div", 13, 0);
247
+ i0.ɵɵtemplate(8, SkipDynamicHTMLReportComponent_Conditional_1_Conditional_8_Template, 31, 3, "div", 35);
248
+ i0.ɵɵelementEnd()();
249
+ } if (rf & 2) {
250
+ const ctx_r1 = i0.ɵɵnextContext();
251
+ i0.ɵɵadvance(4);
252
+ i0.ɵɵproperty("ngIf", ctx_r1.ShowCreateReportButton && !ctx_r1.matchingReportID);
253
+ i0.ɵɵadvance();
254
+ i0.ɵɵproperty("ngIf", ctx_r1.ShowPrintReport);
255
+ i0.ɵɵadvance(3);
256
+ i0.ɵɵconditional(ctx_r1.currentError ? 8 : -1);
25
257
  } }
26
258
  export class SkipDynamicHTMLReportComponent {
27
- constructor(cdr) {
28
- this.cdr = cdr;
259
+ constructor() {
29
260
  this.HTMLReport = null;
30
- this.HTMLReportObjectName = null;
261
+ this.ComponentObjectName = null;
31
262
  this.ShowPrintReport = true;
263
+ this.ShowReportOptionsToggle = true;
264
+ this.ShowCreateReportButton = false;
265
+ this.matchingReportID = null;
32
266
  this.DrillDownEvent = new EventEmitter();
267
+ this.CreateReportRequested = new EventEmitter();
268
+ // Properties for handling multiple report options
269
+ this.reportOptions = [];
270
+ this.selectedReportOptionIndex = 0;
271
+ this.currentError = null;
272
+ this.isCreatingReport = false;
273
+ // Cache for React component hosts - lazy loaded per option
274
+ this.reactHostCache = new Map();
275
+ this.currentHostIndex = null;
276
+ this.callbacks = {
277
+ RefreshData: () => this.handleRefreshData(),
278
+ OpenEntityRecord: (entityName, key) => this.handleOpenEntityRecord(entityName, key),
279
+ UpdateUserState: (userState) => this.handleUpdateUserState(userState),
280
+ NotifyEvent: (eventName, eventData) => this.handleNotifyEvent(eventName, eventData)
281
+ };
282
+ }
283
+ /**
284
+ * Gets the currently selected report option
285
+ */
286
+ get selectedReportOption() {
287
+ return this.reportOptions.length > this.selectedReportOptionIndex
288
+ ? this.reportOptions[this.selectedReportOptionIndex]
289
+ : null;
290
+ }
291
+ /**
292
+ * Get tab title for a specific option index
293
+ */
294
+ getTabTitle(index) {
295
+ const option = this.reportOptions[index];
296
+ if (!option)
297
+ return `report ${index + 1}`;
298
+ const componentType = option.option.componentType || 'report';
299
+ return `${componentType} ${index + 1}`;
300
+ }
301
+ /**
302
+ * Check if this option is the AI's top recommendation
303
+ */
304
+ isTopRanked(index) {
305
+ const option = this.reportOptions[index];
306
+ return (option === null || option === void 0 ? void 0 : option.AIRank) === 1;
307
+ }
308
+ /**
309
+ * Handles when the user selects a tab
310
+ */
311
+ onTabSelect(event) {
312
+ const selectedIndex = event.index;
313
+ this.onReportOptionChange(selectedIndex);
314
+ }
315
+ /**
316
+ * Handles when the user changes the selected report option
317
+ */
318
+ onReportOptionChange(selectedIndex) {
319
+ if (selectedIndex >= 0 && selectedIndex < this.reportOptions.length) {
320
+ this.selectedReportOptionIndex = selectedIndex;
321
+ this.updateCurrentReport();
322
+ }
323
+ }
324
+ /**
325
+ * Updates the current report display based on the selected option
326
+ */
327
+ updateCurrentReport() {
328
+ const selectedOption = this.selectedReportOption;
329
+ if (!selectedOption)
330
+ return;
331
+ // Clear any previous error
332
+ this.currentError = null;
333
+ // Update the component info
334
+ this.HTMLReport = BuildSkipComponentCompleteCode(selectedOption.option);
335
+ this.ComponentObjectName = selectedOption.option.componentName;
336
+ // Simply create or reuse the React host for this option
337
+ // The tab component handles visibility automatically
338
+ if (!this.reactHostCache.has(this.selectedReportOptionIndex)) {
339
+ // Create a new host for this option
340
+ this.createReactHostForOption(this.selectedReportOptionIndex);
341
+ }
342
+ this.currentHostIndex = this.selectedReportOptionIndex;
33
343
  }
34
344
  PrintReport() {
35
345
  return __awaiter(this, void 0, void 0, function* () {
36
- // Implement printing of the HTML element only here
346
+ const currentHost = this.getCurrentReactHost();
347
+ if (currentHost) {
348
+ currentHost.print();
349
+ }
350
+ else {
351
+ window.print();
352
+ }
37
353
  });
38
354
  }
39
- ngAfterViewInit() {
355
+ /**
356
+ * Copy error details to clipboard for user to send back to Skip
357
+ */
358
+ copyErrorToClipboard() {
359
+ if (!this.currentError)
360
+ return;
361
+ const errorText = `Skip Component Error:
362
+ Type: ${this.currentError.type}
363
+ Message: ${this.currentError.message}
364
+ ${this.currentError.technicalDetails ? `\nTechnical Details:\n${this.currentError.technicalDetails}` : ''}
365
+
366
+ Component Option: ${this.selectedReportOptionIndex + 1}
367
+ Component Name: ${this.ComponentObjectName || 'Unknown'}`;
368
+ navigator.clipboard.writeText(errorText).then(() => {
369
+ alert('Error details copied to clipboard. You can paste this in the Skip chat to get help.');
370
+ }).catch(err => {
371
+ console.error('Failed to copy to clipboard:', err);
372
+ });
373
+ }
374
+ /**
375
+ * Get the container element for a specific option index
376
+ */
377
+ getContainerForOption(optionIndex) {
40
378
  var _a;
41
- if (this.HTMLReport) {
42
- const container = (_a = this.htmlContainer) === null || _a === void 0 ? void 0 : _a.nativeElement;
43
- if (container) {
44
- if (this.HTMLReportObjectName && this.SkipData) {
45
- this.invokeHTMLInitFunction();
46
- }
379
+ if (!this.htmlContainers || this.htmlContainers.length === 0) {
380
+ return null;
381
+ }
382
+ if (this.reportOptions.length === 1) {
383
+ // Single option - use the only container
384
+ return ((_a = this.htmlContainers.first) === null || _a === void 0 ? void 0 : _a.nativeElement) || null;
385
+ }
386
+ else {
387
+ // Multiple options - find container by data-tab-index
388
+ const container = this.htmlContainers.find(ref => ref.nativeElement.getAttribute('data-tab-index') === optionIndex.toString());
389
+ return (container === null || container === void 0 ? void 0 : container.nativeElement) || null;
390
+ }
391
+ }
392
+ /**
393
+ * Retry loading the current option
394
+ */
395
+ retryCurrentOption() {
396
+ // Clear the error
397
+ this.currentError = null;
398
+ // Remove the cached host for this option to force recreation
399
+ if (this.reactHostCache.has(this.selectedReportOptionIndex)) {
400
+ const host = this.reactHostCache.get(this.selectedReportOptionIndex);
401
+ if (host) {
402
+ host.destroy();
47
403
  }
404
+ this.reactHostCache.delete(this.selectedReportOptionIndex);
48
405
  }
406
+ // Try creating it again
407
+ this.createReactHostForOption(this.selectedReportOptionIndex);
408
+ }
409
+ /**
410
+ * Handle create report request for a specific option
411
+ */
412
+ createReportForOption(optionIndex) {
413
+ this.isCreatingReport = true;
414
+ // Emit the event with the option index so the parent can handle it
415
+ this.CreateReportRequested.emit(optionIndex);
416
+ }
417
+ ngAfterViewInit() {
418
+ if (this.SkipData) {
419
+ this.setupReportOptions(this.SkipData);
420
+ }
421
+ // Wait for ViewChildren to be available
422
+ setTimeout(() => {
423
+ if (this.HTMLReport && this.ComponentObjectName && this.SkipData) {
424
+ // Create the initial React host for the first option
425
+ this.createReactHostForOption(this.selectedReportOptionIndex);
426
+ }
427
+ });
428
+ }
429
+ ngOnDestroy() {
430
+ // Clean up all cached React hosts
431
+ this.reactHostCache.forEach(host => {
432
+ try {
433
+ host.destroy();
434
+ }
435
+ catch (e) {
436
+ console.error('Error destroying React host:', e);
437
+ }
438
+ });
439
+ this.reactHostCache.clear();
440
+ }
441
+ ngOnChanges(changes) {
442
+ if (changes['SkipData'] && !changes['SkipData'].firstChange) {
443
+ // Update all cached React components with new data
444
+ const newData = this.getFlattenedDataContext();
445
+ this.reactHostCache.forEach(host => {
446
+ try {
447
+ host.updateState('data', newData);
448
+ }
449
+ catch (e) {
450
+ console.error('Error updating React host data:', e);
451
+ }
452
+ });
453
+ }
454
+ }
455
+ /**
456
+ * Get the currently active React host
457
+ */
458
+ getCurrentReactHost() {
459
+ if (this.currentHostIndex !== null && this.reactHostCache.has(this.currentHostIndex)) {
460
+ return this.reactHostCache.get(this.currentHostIndex) || null;
461
+ }
462
+ return null;
49
463
  }
50
464
  get SkipData() {
51
465
  return this._skipData ? this._skipData : undefined;
@@ -54,191 +468,615 @@ export class SkipDynamicHTMLReportComponent {
54
468
  const hadData = this._skipData ? true : false;
55
469
  this._skipData = d;
56
470
  if (d) {
57
- this.HTMLReport = d.htmlReport;
58
- this.HTMLReportObjectName = d.htmlReportObjectName;
471
+ // For backward compatibility, check if we have component options
472
+ if (d.componentOptions && d.componentOptions.length > 0) {
473
+ // Use the first component option (or the highest ranked one)
474
+ const component = d.componentOptions[0];
475
+ this.HTMLReport = BuildSkipComponentCompleteCode(component.option);
476
+ this.ComponentObjectName = component.option.componentName;
477
+ }
478
+ else {
479
+ // Fallback for old format
480
+ this.HTMLReport = d.htmlReport;
481
+ this.ComponentObjectName = d.htmlReportObjectName;
482
+ }
59
483
  }
60
484
  if (d && hadData) {
61
- // normally the initFunction is called in ngAfterViewInit, but here the data changed so we need to call it again
62
- this.invokeHTMLInitFunction();
485
+ // Update the current display with new data
486
+ this.updateCurrentReport();
63
487
  }
64
488
  }
65
- invokeHTMLInitFunction() {
489
+ /**
490
+ * Sets up the report options from the SkipData, prioritizing the new htmlReportOptions array
491
+ * but falling back to the deprecated htmlReport/htmlReportObjectName for backward compatibility
492
+ */
493
+ setupReportOptions(data) {
494
+ // Check if we have the new htmlReportOptions array
495
+ if (data.componentOptions && data.componentOptions.length > 0) {
496
+ // Sort by AIRank (lower numbers = better ranking)
497
+ this.reportOptions = [...data.componentOptions].sort((a, b) => {
498
+ var _a, _b;
499
+ const rankA = (_a = a.AIRank) !== null && _a !== void 0 ? _a : Number.MAX_SAFE_INTEGER;
500
+ const rankB = (_b = b.AIRank) !== null && _b !== void 0 ? _b : Number.MAX_SAFE_INTEGER;
501
+ return rankA - rankB;
502
+ });
503
+ // Select the best option (first in sorted array)
504
+ this.selectedReportOptionIndex = 0;
505
+ const bestOption = this.reportOptions[0];
506
+ this.HTMLReport = BuildSkipComponentCompleteCode(bestOption.option);
507
+ this.ComponentObjectName = bestOption.option.componentName;
508
+ }
509
+ }
510
+ /**
511
+ * Create a React host for a specific option index
512
+ */
513
+ createReactHostForOption(optionIndex) {
66
514
  return __awaiter(this, void 0, void 0, function* () {
67
- var _a;
515
+ var _a, _b, _c;
516
+ const option = this.reportOptions[optionIndex];
517
+ if (!option)
518
+ return;
519
+ const container = this.getContainerForOption(optionIndex);
520
+ if (!container)
521
+ return;
68
522
  try {
69
- const container = (_a = this.htmlContainer) === null || _a === void 0 ? void 0 : _a.nativeElement;
70
- if (container && this.HTMLReportObjectName) {
71
- // First set the HTML as is, with script tags
72
- container.innerHTML = this.HTMLReport;
73
- // Force Angular to detect changes
74
- this.cdr.detectChanges();
75
- // Now find and manually execute all scripts in the container
76
- const scriptElements = container.querySelectorAll('script');
77
- yield this.loadScriptsSequentially(scriptElements);
78
- // scriptElements.forEach((script: HTMLScriptElement) => {
79
- // // For external scripts
80
- // if (script.src) {
81
- // // Create a new script element
82
- // const newScript = document.createElement('script');
83
- // newScript.src = script.src;
84
- // document.head.appendChild(newScript);
85
- // }
86
- // // For inline scripts
87
- // else if (script.textContent) {
88
- // // Execute the script content directly
89
- // try {
90
- // // This will execute the script in global context
91
- // eval(script.textContent);
92
- // } catch (error) {
93
- // console.error('Error executing script:', error);
94
- // }
95
- // }
96
- // });
97
- this.finishHTMLInitialization();
523
+ const componentCode = BuildSkipComponentCompleteCode(option.option);
524
+ // Check for unresolved placeholders in the code
525
+ if (componentCode.includes('<<') && componentCode.includes('>>')) {
526
+ const placeholderMatch = componentCode.match(/<<([^>]+)>>/);
527
+ const placeholderName = placeholderMatch ? placeholderMatch[1] : 'Unknown';
528
+ this.currentError = {
529
+ type: 'Incomplete Component',
530
+ message: `This component option contains unresolved placeholders (${placeholderName}). The component generation was not completed successfully.`,
531
+ technicalDetails: `The component code contains placeholder tokens that should have been replaced with actual implementations. This typically happens when the AI generation process was interrupted or encountered an error.\n\nPlaceholder found: <<${placeholderName}>>`
532
+ };
533
+ return;
98
534
  }
99
- else {
100
- console.warn('HTML Report container not found or init function name not provided');
535
+ const md = new Metadata();
536
+ const data = this.getFlattenedDataContext();
537
+ // Create the React component host directly in the tab container
538
+ const reactHost = new SkipReactComponentHost({
539
+ componentCode: componentCode,
540
+ container: container,
541
+ callbacks: this.callbacks,
542
+ data: data,
543
+ utilities: this.SetupUtilities(md),
544
+ styles: this.SetupStyles()
545
+ });
546
+ // Initialize and render the React component
547
+ yield reactHost.initialize();
548
+ // Cache the host
549
+ this.reactHostCache.set(optionIndex, reactHost);
550
+ // Update current index if this is the selected option
551
+ if (optionIndex === this.selectedReportOptionIndex) {
552
+ this.currentHostIndex = optionIndex;
101
553
  }
102
554
  }
103
555
  catch (e) {
104
- LogError(e);
105
- }
106
- });
107
- }
108
- loadScriptsSequentially(scriptElements) {
109
- return __awaiter(this, void 0, void 0, function* () {
110
- for (let i = 0; i < scriptElements.length; i++) {
111
- const script = scriptElements[i];
112
- // For external scripts
113
- if (script.src) {
114
- // we use the promise to ensure we are awaiting for the script to load before moving on to the next one
115
- yield new Promise((resolve, reject) => {
116
- const newScript = document.createElement('script');
117
- newScript.src = script.src;
118
- // Set up handlers
119
- newScript.onload = () => resolve();
120
- newScript.onerror = (error) => {
121
- console.error('Error loading script:', script.src, error);
122
- resolve(); // Resolve anyway to continue loading other scripts
123
- };
124
- document.head.appendChild(newScript);
125
- });
556
+ console.error('Error creating React host:', e);
557
+ // Determine the type of error and create a user-friendly message
558
+ let errorType = 'Component Initialization Error';
559
+ let errorMessage = 'Failed to initialize the React component.';
560
+ let technicalDetails = e.toString();
561
+ if ((_a = e.message) === null || _a === void 0 ? void 0 : _a.includes('JSX transpilation failed')) {
562
+ errorType = 'Code Compilation Error';
563
+ errorMessage = 'The component code could not be compiled. This usually indicates a syntax error in the generated code.';
564
+ technicalDetails = e.message;
126
565
  }
127
- // For inline scripts
128
- else if (script.textContent) {
129
- try {
130
- // Execute inline script
131
- eval(script.textContent);
132
- }
133
- catch (error) {
134
- console.error('Error executing inline script:', error);
135
- // Continue to next script even if this one failed
136
- }
566
+ else if ((_b = e.message) === null || _b === void 0 ? void 0 : _b.includes('is not defined')) {
567
+ errorType = 'Missing Dependency';
568
+ errorMessage = 'The component is trying to use a feature or library that is not available.';
137
569
  }
570
+ else if ((_c = e.message) === null || _c === void 0 ? void 0 : _c.includes('Cannot read properties')) {
571
+ errorType = 'Property Access Error';
572
+ errorMessage = 'The component is trying to access data that doesn\'t exist. This often happens when property names don\'t match the data structure.';
573
+ }
574
+ this.currentError = {
575
+ type: errorType,
576
+ message: errorMessage,
577
+ technicalDetails: technicalDetails + '\n\nComponent Option: ' + (optionIndex + 1) + '\nComponent Name: ' + option.option.componentName
578
+ };
579
+ LogError(e);
138
580
  }
139
- console.log('All scripts loaded');
140
581
  });
141
582
  }
142
- finishHTMLInitialization() {
583
+ getFlattenedDataContext() {
143
584
  var _a;
144
- try {
145
- if (!this.HTMLReportObjectName) {
146
- console.warn('HTML Report object name not provided');
147
- return;
585
+ const flattenedDataContext = {};
586
+ if ((_a = this.SkipData) === null || _a === void 0 ? void 0 : _a.dataContext) {
587
+ const loadedItems = this.SkipData.dataContext.Items.filter((i) => { var _a; return i.DataLoaded && ((_a = i._Data) === null || _a === void 0 ? void 0 : _a.length) > 0; });
588
+ for (let i = 0; i < loadedItems.length; i++) {
589
+ flattenedDataContext["data_item_" + i] = loadedItems[i]._Data;
148
590
  }
149
- const reportObject = window[this.HTMLReportObjectName];
591
+ }
592
+ return flattenedDataContext;
593
+ }
594
+ // Event handler implementations
595
+ handleRefreshData() {
596
+ console.log('Component requested data refresh');
597
+ // Emit an event or call parent component method to refresh data
598
+ }
599
+ handleOpenEntityRecord(entityName, key) {
600
+ if (entityName) {
601
+ // bubble this up to our parent component as we don't directly open records in this component
150
602
  const md = new Metadata();
151
- if (reportObject && ((_a = this.SkipData) === null || _a === void 0 ? void 0 : _a.dataContext)) {
152
- const castedObject = reportObject;
153
- const userState = {};
154
- const flattenedDataContext = {};
155
- // Flatten the data context to make it easier to work with
156
- const loadedItems = this.SkipData.dataContext.Items.filter((i) => { var _a; return i.DataLoaded && ((_a = i._Data) === null || _a === void 0 ? void 0 : _a.length) > 0; });
157
- for (let i = 0; i < loadedItems.length; i++) {
158
- flattenedDataContext["data_item_" + i] = loadedItems[i]._Data;
603
+ const entityMatch = md.EntityByName(entityName);
604
+ if (!entityMatch) {
605
+ // couldn't find it, but sometimes the AI uses a table name or a view name, let's check for that
606
+ const altMatch = md.Entities.filter(e => e.BaseTable.toLowerCase() === entityName.toLowerCase() ||
607
+ e.BaseView.toLowerCase() === entityName.toLowerCase() ||
608
+ e.SchemaName.toLowerCase() + '.' + e.BaseTable.toLowerCase() === entityName.toLowerCase() ||
609
+ e.SchemaName.toLowerCase() + '.' + e.BaseView.toLowerCase() === entityName.toLowerCase());
610
+ if (altMatch && altMatch.length === 1) {
611
+ entityName = altMatch[0].Name;
159
612
  }
160
- castedObject.init(flattenedDataContext, userState, {
161
- RefreshData: () => {
162
- // this is a callback function that can be called from the HTML report to refresh data
163
- console.log('HTML Report requested data refresh');
164
- // need to implement this
165
- },
166
- OpenEntityRecord: (entityName, key) => {
167
- // this is a callback function that can be called from the HTML report to open an entity record
168
- if (entityName) {
169
- // bubble this up to our parent component as we don't directly open records in this component
170
- const md = new Metadata();
171
- const entityMatch = md.EntityByName(entityName);
172
- if (!entityMatch) {
173
- // couldn't find it, but sometimes the AI uses a table name or a view name, let's check for that
174
- const altMatch = md.Entities.filter(e => e.BaseTable.toLowerCase() === entityName.toLowerCase() ||
175
- e.BaseView.toLowerCase() === entityName.toLowerCase() ||
176
- e.SchemaName.toLowerCase() + '.' + e.BaseTable.toLowerCase() === entityName.toLowerCase() ||
177
- e.SchemaName.toLowerCase() + '.' + e.BaseView.toLowerCase() === entityName.toLowerCase());
178
- if (altMatch && altMatch.length === 1) {
179
- entityName = altMatch[0].Name;
180
- }
181
- }
182
- const cKey = new CompositeKey(key);
183
- this.DrillDownEvent.emit(new DrillDownInfo(entityName, cKey.ToWhereClause()));
613
+ }
614
+ const cKey = new CompositeKey(key);
615
+ this.DrillDownEvent.emit(new DrillDownInfo(entityName, cKey.ToWhereClause()));
616
+ }
617
+ }
618
+ handleUpdateUserState(userState) {
619
+ console.log('Component updated user state:', userState);
620
+ // TODO: Implement user state persistence if needed
621
+ }
622
+ handleNotifyEvent(eventName, eventData) {
623
+ console.log(`Component raised event: ${eventName} notified with data:`, eventData);
624
+ // TODO: Handle custom events as needed
625
+ }
626
+ SetupUtilities(md) {
627
+ const rv = new RunView();
628
+ const rq = new RunQuery();
629
+ const u = {
630
+ md: this.CreateSimpleMetadata(md),
631
+ rv: this.CreateSimpleRunView(rv),
632
+ rq: this.CreateSimpleRunQuery(rq)
633
+ };
634
+ return u;
635
+ }
636
+ CreateSimpleMetadata(md) {
637
+ return {
638
+ entities: md.Entities.map(e => MapEntityInfoToSkipEntityInfo(e))
639
+ };
640
+ }
641
+ SetupStyles() {
642
+ // Return modern, contemporary styles for generated components
643
+ return {
644
+ colors: {
645
+ // Primary colors - modern purple/blue gradient feel
646
+ primary: '#5B4FE9',
647
+ primaryHover: '#4940D4',
648
+ primaryLight: '#E8E6FF',
649
+ // Secondary colors - sophisticated gray
650
+ secondary: '#64748B',
651
+ secondaryHover: '#475569',
652
+ // Status colors
653
+ success: '#10B981',
654
+ successLight: '#D1FAE5',
655
+ warning: '#F59E0B',
656
+ warningLight: '#FEF3C7',
657
+ error: '#EF4444',
658
+ errorLight: '#FEE2E2',
659
+ info: '#3B82F6',
660
+ infoLight: '#DBEAFE',
661
+ // Base colors
662
+ background: '#FFFFFF',
663
+ surface: '#F8FAFC',
664
+ surfaceHover: '#F1F5F9',
665
+ // Text colors with better contrast
666
+ text: '#1E293B',
667
+ textSecondary: '#64748B',
668
+ textTertiary: '#94A3B8',
669
+ textInverse: '#FFFFFF',
670
+ // Border colors
671
+ border: '#E2E8F0',
672
+ borderLight: '#F1F5F9',
673
+ borderFocus: '#5B4FE9',
674
+ // Shadows (as color strings for easy use)
675
+ shadow: 'rgba(0, 0, 0, 0.05)',
676
+ shadowMedium: 'rgba(0, 0, 0, 0.1)',
677
+ shadowLarge: 'rgba(0, 0, 0, 0.15)',
678
+ },
679
+ spacing: {
680
+ xs: '4px',
681
+ sm: '8px',
682
+ md: '16px',
683
+ lg: '24px',
684
+ xl: '32px',
685
+ xxl: '48px',
686
+ xxxl: '64px',
687
+ },
688
+ typography: {
689
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, sans-serif',
690
+ fontSize: {
691
+ xs: '11px',
692
+ sm: '12px',
693
+ md: '14px',
694
+ lg: '16px',
695
+ xl: '20px',
696
+ xxl: '24px',
697
+ xxxl: '32px',
698
+ },
699
+ fontWeight: {
700
+ light: '300',
701
+ regular: '400',
702
+ medium: '500',
703
+ semibold: '600',
704
+ bold: '700',
705
+ },
706
+ lineHeight: {
707
+ tight: '1.25',
708
+ normal: '1.5',
709
+ relaxed: '1.75',
710
+ },
711
+ },
712
+ borders: {
713
+ radius: {
714
+ sm: '6px',
715
+ md: '8px',
716
+ lg: '12px',
717
+ xl: '16px',
718
+ full: '9999px',
719
+ },
720
+ width: {
721
+ thin: '1px',
722
+ medium: '2px',
723
+ thick: '3px',
724
+ },
725
+ },
726
+ shadows: {
727
+ sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
728
+ md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
729
+ lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
730
+ xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
731
+ inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
732
+ },
733
+ transitions: {
734
+ fast: '150ms ease-in-out',
735
+ normal: '250ms ease-in-out',
736
+ slow: '350ms ease-in-out',
737
+ },
738
+ overflow: 'auto' // Default overflow style
739
+ };
740
+ }
741
+ CreateSimpleRunQuery(rq) {
742
+ return {
743
+ runQuery: (params) => __awaiter(this, void 0, void 0, function* () {
744
+ // Run a single query and return the results
745
+ try {
746
+ const result = yield rq.RunQuery(params);
747
+ return result;
748
+ }
749
+ catch (error) {
750
+ LogError(error);
751
+ throw error; // Re-throw to handle it in the caller
752
+ }
753
+ })
754
+ };
755
+ }
756
+ CreateSimpleRunView(rv) {
757
+ return {
758
+ runView: (params) => __awaiter(this, void 0, void 0, function* () {
759
+ // Run a single view and return the results
760
+ try {
761
+ const result = yield rv.RunView(params);
762
+ return result;
763
+ }
764
+ catch (error) {
765
+ LogError(error);
766
+ throw error; // Re-throw to handle it in the caller
767
+ }
768
+ }),
769
+ runViews: (params) => __awaiter(this, void 0, void 0, function* () {
770
+ // Runs multiple views and returns the results
771
+ try {
772
+ const results = yield rv.RunViews(params);
773
+ return results;
774
+ }
775
+ catch (error) {
776
+ LogError(error);
777
+ throw error; // Re-throw to handle it in the caller
778
+ }
779
+ })
780
+ };
781
+ }
782
+ SetupCallbacks() {
783
+ const cb = {
784
+ RefreshData: () => {
785
+ // this is a callback function that can be called from the component to refresh data
786
+ console.log('Component requested data refresh');
787
+ // need to implement this
788
+ },
789
+ OpenEntityRecord: (entityName, key) => {
790
+ // this is a callback function that can be called from the component to open an entity record
791
+ if (entityName) {
792
+ // bubble this up to our parent component as we don't directly open records in this component
793
+ const md = new Metadata();
794
+ const entityMatch = md.EntityByName(entityName);
795
+ if (!entityMatch) {
796
+ // couldn't find it, but sometimes the AI uses a table name or a view name, let's check for that
797
+ const altMatch = md.Entities.filter(e => e.BaseTable.toLowerCase() === entityName.toLowerCase() ||
798
+ e.BaseView.toLowerCase() === entityName.toLowerCase() ||
799
+ e.SchemaName.toLowerCase() + '.' + e.BaseTable.toLowerCase() === entityName.toLowerCase() ||
800
+ e.SchemaName.toLowerCase() + '.' + e.BaseView.toLowerCase() === entityName.toLowerCase());
801
+ if (altMatch && altMatch.length === 1) {
802
+ entityName = altMatch[0].Name;
184
803
  }
185
- },
186
- UpdateUserState: (userState) => {
187
- // this is a callback function that can be called from the HTML report to update user state
188
- console.log('HTML Report updated user state:', userState);
189
- // need to implement this
190
- },
191
- NotifyEvent: (eventName, eventData) => {
192
- // this is a callback function that can be called from the HTML report to notify an event
193
- console.log(`HTML Report raised event: ${eventName} notified with data:`, eventData);
194
804
  }
195
- });
805
+ const cKey = new CompositeKey(key);
806
+ this.DrillDownEvent.emit(new DrillDownInfo(entityName, cKey.ToWhereClause()));
807
+ }
808
+ },
809
+ UpdateUserState: (userState) => {
810
+ // this is a callback function that can be called from the component to update user state
811
+ console.log('Component updated user state:', userState);
812
+ // need to implement this
813
+ },
814
+ NotifyEvent: (eventName, eventData) => {
815
+ // this is a callback function that can be called from the component to notify an event
816
+ console.log(`Component raised event: ${eventName} notified with data:`, eventData);
817
+ }
818
+ };
819
+ return cb;
820
+ }
821
+ refreshReport(data) {
822
+ return __awaiter(this, void 0, void 0, function* () {
823
+ const currentHost = this.getCurrentReactHost();
824
+ if (currentHost) {
825
+ currentHost.refresh(data);
196
826
  }
197
827
  else {
198
- console.warn(`HTML Report object ${this.HTMLReportObjectName} not found or invalid data context`);
828
+ // If no React host is available, create one for the current option
829
+ this.createReactHostForOption(this.selectedReportOptionIndex);
199
830
  }
200
- }
201
- catch (e) {
202
- LogError(e);
203
- }
831
+ });
204
832
  }
205
833
  }
206
- SkipDynamicHTMLReportComponent.ɵfac = function SkipDynamicHTMLReportComponent_Factory(t) { return new (t || SkipDynamicHTMLReportComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
834
+ SkipDynamicHTMLReportComponent.ɵfac = function SkipDynamicHTMLReportComponent_Factory(t) { return new (t || SkipDynamicHTMLReportComponent)(); };
207
835
  SkipDynamicHTMLReportComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SkipDynamicHTMLReportComponent, selectors: [["skip-dynamic-html-report"]], viewQuery: function SkipDynamicHTMLReportComponent_Query(rf, ctx) { if (rf & 1) {
208
836
  i0.ɵɵviewQuery(_c0, 5);
209
837
  } if (rf & 2) {
210
838
  let _t;
211
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.htmlContainer = _t.first);
212
- } }, inputs: { HTMLReport: "HTMLReport", HTMLReportObjectName: "HTMLReportObjectName", ShowPrintReport: "ShowPrintReport", SkipData: "SkipData" }, outputs: { DrillDownEvent: "DrillDownEvent" }, decls: 3, vars: 1, consts: [["htmlContainer", ""], ["kendoButton", "", 3, "click", 4, "ngIf"], ["mjFillContainer", ""], ["kendoButton", "", 3, "click"], [1, "fa-regular", "fa-image"]], template: function SkipDynamicHTMLReportComponent_Template(rf, ctx) { if (rf & 1) {
213
- i0.ɵɵtemplate(0, SkipDynamicHTMLReportComponent_button_0_Template, 3, 0, "button", 1);
214
- i0.ɵɵelement(1, "div", 2, 0);
839
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.htmlContainers = _t);
840
+ } }, inputs: { HTMLReport: "HTMLReport", ComponentObjectName: "ComponentObjectName", ShowPrintReport: "ShowPrintReport", ShowReportOptionsToggle: "ShowReportOptionsToggle", ShowCreateReportButton: "ShowCreateReportButton", matchingReportID: "matchingReportID", SkipData: "SkipData" }, outputs: { DrillDownEvent: "DrillDownEvent", CreateReportRequested: "CreateReportRequested" }, features: [i0.ɵɵNgOnChangesFeature], decls: 2, vars: 1, consts: [["htmlContainer", ""], [2, "height", "100%", "display", "flex", "flex-direction", "column", 3, "keepTabContent"], [2, "height", "100%", "display", "flex", "flex-direction", "column"], [2, "height", "100%", "display", "flex", "flex-direction", "column", 3, "tabSelect", "keepTabContent"], [3, "selected"], ["kendoTabTitle", ""], ["kendoTabContent", ""], [1, "fa-solid", "fa-star", "star-icon"], [1, "tab-action-bar"], [1, "tab-actions-left"], [1, "tab-actions-right"], ["class", "tab-action-button create-button", 3, "disabled", "click", 4, "ngIf"], ["class", "tab-action-button print-button", "title", "Print Report", 3, "click", 4, "ngIf"], [2, "flex", "1", "position", "relative", "min-height", "0"], [2, "top", "0", "left", "0", "right", "0", "bottom", "0", "display", "flex", "align-items", "flex-start", "justify-content", "center", "padding-top", "20px", "background", "rgba(255, 255, 255, 0.95)", "z-index", "10"], [1, "tab-action-button", "create-button", 3, "click", "disabled"], [1, "fa-solid", "fa-plus"], ["title", "Print Report", 1, "tab-action-button", "print-button", 3, "click"], [1, "fa-solid", "fa-print"], [2, "width", "90%", "max-width", "600px", "height", "500px", "background-color", "#f8f9fa", "border", "2px solid #dc3545", "border-radius", "8px", "padding", "20px", "overflow-y", "auto", "box-shadow", "0 4px 6px rgba(0, 0, 0, 0.1)"], [2, "position", "relative"], ["kendoButton", "", 2, "position", "absolute", "top", "0", "right", "0", "font-size", "12px", 3, "click"], [1, "fa-solid", "fa-copy"], [2, "color", "#dc3545", "margin-top", "0", "margin-right", "150px", "font-size", "18px"], [1, "fa-solid", "fa-exclamation-triangle"], [2, "margin-bottom", "10px", "font-size", "14px"], [2, "background-color", "#fff", "border", "1px solid #dee2e6", "border-radius", "4px", "padding", "12px", "margin-bottom", "12px", "font-family", "'Courier New', monospace", "font-size", "12px"], [2, "margin-top", "8px"], [2, "background-color", "#e7f3ff", "border", "1px solid #b3d9ff", "border-radius", "4px", "padding", "12px", "margin-bottom", "12px"], [2, "font-size", "14px"], [2, "margin", "8px 0 0 20px", "padding", "0", "font-size", "13px"], ["kendoButton", "", 2, "font-size", "13px", 3, "click"], [1, "fa-solid", "fa-rotate"], [2, "cursor", "pointer", "color", "#0056b3"], [2, "margin-top", "8px", "white-space", "pre-wrap", "word-break", "break-word", "font-size", "11px"], [2, "position", "absolute", "top", "0", "left", "0", "right", "0", "bottom", "0", "display", "flex", "align-items", "flex-start", "justify-content", "center", "padding-top", "20px", "background", "rgba(255, 255, 255, 0.95)", "z-index", "10"]], template: function SkipDynamicHTMLReportComponent_Template(rf, ctx) { if (rf & 1) {
841
+ i0.ɵɵtemplate(0, SkipDynamicHTMLReportComponent_Conditional_0_Template, 3, 1, "kendo-tabstrip", 1)(1, SkipDynamicHTMLReportComponent_Conditional_1_Template, 9, 3, "div", 2);
215
842
  } if (rf & 2) {
216
- i0.ɵɵproperty("ngIf", ctx.ShowPrintReport);
217
- } }, dependencies: [i1.NgIf, i2.FillContainer, i3.ButtonComponent], styles: ["button[_ngcontent-%COMP%] { margin-top: 5px; margin-bottom: 5px;}"] });
843
+ i0.ɵɵconditional(ctx.reportOptions.length > 1 ? 0 : 1);
844
+ } }, dependencies: [i1.NgIf, i2.TabStripComponent, i2.TabStripTabComponent, i2.TabContentDirective, i2.TabTitleDirective, i3.ButtonComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n position: relative;\n }\n \n \n\n .tab-action-bar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background-color: #fafafa;\n border-bottom: 1px solid #e0e0e0;\n }\n \n .tab-actions-left[_ngcontent-%COMP%], \n .tab-actions-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n \n \n\n .tab-action-button[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n background-color: transparent;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: #333;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n \n .tab-action-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: #f5f5f5;\n border-color: #d0d0d0;\n }\n \n .tab-action-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .tab-action-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n \n \n\n .tab-action-button.create-button[_ngcontent-%COMP%], \n .tab-action-button.print-button[_ngcontent-%COMP%] {\n background-color: white;\n color: #333;\n border-color: #e0e0e0;\n }\n \n .tab-action-button.create-button[_ngcontent-%COMP%]:hover:not(:disabled), \n .tab-action-button.print-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: #f5f5f5;\n border-color: #d0d0d0;\n }\n \n \n\n .k-tabstrip {\n border: none;\n height: 100%;\n display: flex;\n flex-direction: column;\n margin: 10px 5px 5px 5px;\n }\n \n .k-tabstrip-items {\n background: #f8f9fa;\n border: none;\n border-radius: 8px 8px 0 0;\n flex: 0 0 auto;\n padding: 8px 12px 0 12px;\n gap: 4px;\n display: flex;\n }\n \n .k-tabstrip-items-wrapper {\n height: 100%;\n }\n \n .k-content {\n flex: 1;\n overflow: hidden;\n padding: 0;\n background: white;\n border: 1px solid #e0e0e0;\n border-top: none;\n border-radius: 0 0 8px 8px;\n }\n \n .k-tabstrip .k-item {\n margin-right: 2px;\n border: none;\n background: transparent;\n border-radius: 6px 6px 0 0;\n padding: 2px;\n transition: all 0.2s ease;\n }\n \n .k-tabstrip .k-item.k-selected {\n background: white;\n border: 1px solid #e0e0e0;\n border-bottom: 1px solid white;\n margin-bottom: -1px;\n z-index: 1;\n }\n \n .k-tabstrip .k-link {\n padding: 8px 16px;\n font-weight: 500;\n font-size: 13px;\n color: #666;\n transition: all 0.15s ease;\n border-radius: 4px 4px 0 0;\n background: transparent;\n border: none;\n text-transform: lowercase;\n }\n \n .k-tabstrip .k-link:first-letter {\n text-transform: uppercase;\n }\n \n .k-tabstrip .k-item:hover:not(.k-selected) .k-link {\n color: #333;\n background: rgba(0, 0, 0, 0.04);\n }\n \n .k-tabstrip .k-item.k-selected .k-link {\n color: #1976d2;\n font-weight: 600;\n background: white;\n }\n \n \n\n .k-tabstrip .k-link .star-icon {\n display: inline-block;\n margin-right: 4px;\n color: #ffd700;\n font-size: 12px;\n vertical-align: middle;\n }\n \n \n\n .k-tabstrip-items::before, \n .k-tabstrip-items::after {\n display: none;\n }\n \n .k-tabstrip .k-item::before, \n .k-tabstrip .k-item::after {\n display: none;\n }\n \n \n\n .k-tabstrip .k-link:focus {\n outline: none;\n box-shadow: none;\n }\n \n \n\n .k-tabstrip .k-content.k-state-active {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n \n \n\n .react-host-container[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n }"] });
218
845
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SkipDynamicHTMLReportComponent, [{
219
846
  type: Component,
220
847
  args: [{ selector: 'skip-dynamic-html-report', template: `
221
- <button kendoButton *ngIf="ShowPrintReport" (click)="PrintReport()">
222
- <span class="fa-regular fa-image"></span>
223
- Print
224
- </button>
225
- <div #htmlContainer mjFillContainer>
226
- <!-- this is where we'll dynamically inject the HTML that was AI generated -->
227
- </div>
228
- `, styles: ["button { margin-top: 5px; margin-bottom: 5px;}"] }]
229
- }], () => [{ type: i0.ChangeDetectorRef }], { HTMLReport: [{
848
+ @if (reportOptions.length > 1) {
849
+ <!-- Multiple options: show tabs -->
850
+ <kendo-tabstrip
851
+ (tabSelect)="onTabSelect($event)"
852
+ [keepTabContent]="true"
853
+ style="height: 100%; display: flex; flex-direction: column;">
854
+ @for (option of reportOptions; track option; let i = $index) {
855
+ <kendo-tabstrip-tab [selected]="i === selectedReportOptionIndex">
856
+ <ng-template kendoTabTitle>
857
+ @if (isTopRanked(i)) {
858
+ <i class="fa-solid fa-star star-icon"></i>
859
+ }
860
+ {{ getTabTitle(i) }}
861
+ </ng-template>
862
+ <ng-template kendoTabContent>
863
+ <div style="height: 100%; display: flex; flex-direction: column;">
864
+ <!-- Tab Action Bar -->
865
+ <div class="tab-action-bar">
866
+ <div class="tab-actions-left">
867
+ <!-- Space for future left-aligned actions -->
868
+ </div>
869
+ <div class="tab-actions-right">
870
+ <button class="tab-action-button create-button"
871
+ *ngIf="ShowCreateReportButton && !matchingReportID"
872
+ (click)="createReportForOption(i)"
873
+ [disabled]="isCreatingReport">
874
+ <i class="fa-solid fa-plus"></i>
875
+ <span>Create Report</span>
876
+ </button>
877
+ <button class="tab-action-button print-button"
878
+ *ngIf="ShowPrintReport"
879
+ (click)="PrintReport()"
880
+ title="Print Report">
881
+ <i class="fa-solid fa-print"></i>
882
+ <span>Print Report</span>
883
+ </button>
884
+ </div>
885
+ </div>
886
+
887
+ <!-- React component container -->
888
+ <div #htmlContainer [attr.data-tab-index]="i"
889
+ style="flex: 1; position: relative; min-height: 0;">
890
+ <!-- Content will be rendered here by React host -->
891
+
892
+ <!-- Error overlay for this tab (shown on top of content when needed) -->
893
+ @if (currentError && selectedReportOptionIndex === i) {
894
+ <div style="top: 0;
895
+ left: 0;
896
+ right: 0;
897
+ bottom: 0;
898
+ display: flex;
899
+ align-items: flex-start;
900
+ justify-content: center;
901
+ padding-top: 20px;
902
+ background: rgba(255, 255, 255, 0.95);
903
+ z-index: 10;">
904
+ <div style="width: 90%;
905
+ max-width: 600px;
906
+ height: 500px;
907
+ background-color: #f8f9fa;
908
+ border: 2px solid #dc3545;
909
+ border-radius: 8px;
910
+ padding: 20px;
911
+ overflow-y: auto;
912
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);">
913
+ <div style="position: relative;">
914
+ <button kendoButton (click)="copyErrorToClipboard()"
915
+ style="position: absolute; top: 0; right: 0; font-size: 12px;">
916
+ <span class="fa-solid fa-copy"></span>
917
+ Copy Error Details
918
+ </button>
919
+ <h3 style="color: #dc3545; margin-top: 0; margin-right: 150px; font-size: 18px;">
920
+ <span class="fa-solid fa-exclamation-triangle"></span>
921
+ Component Rendering Error
922
+ </h3>
923
+ </div>
924
+ <p style="margin-bottom: 10px; font-size: 14px;">
925
+ The selected component option could not be rendered due to the following error:
926
+ </p>
927
+ <div style="background-color: #fff; border: 1px solid #dee2e6;
928
+ border-radius: 4px; padding: 12px; margin-bottom: 12px;
929
+ font-family: 'Courier New', monospace; font-size: 12px;">
930
+ <strong>Error Type:</strong> {{ currentError.type }}<br>
931
+ <strong>Details:</strong> {{ currentError.message }}
932
+ @if (currentError.technicalDetails) {
933
+ <details style="margin-top: 8px;">
934
+ <summary style="cursor: pointer; color: #0056b3;">Technical Details (click to expand)</summary>
935
+ <pre style="margin-top: 8px; white-space: pre-wrap; word-break: break-word; font-size: 11px;">{{ currentError.technicalDetails }}</pre>
936
+ </details>
937
+ }
938
+ </div>
939
+ <div style="background-color: #e7f3ff; border: 1px solid #b3d9ff;
940
+ border-radius: 4px; padding: 12px; margin-bottom: 12px;">
941
+ <strong style="font-size: 14px;">What to do:</strong>
942
+ <ol style="margin: 8px 0 0 20px; padding: 0; font-size: 13px;">
943
+ <li>Try selecting a different report option from the tabs above</li>
944
+ <li>Copy the error details and send them back to Skip in the chat to get a corrected version</li>
945
+ <li>Contact your IT department if the issue persists</li>
946
+ </ol>
947
+ </div>
948
+ <button kendoButton (click)="retryCurrentOption()" style="font-size: 13px;">
949
+ <span class="fa-solid fa-rotate"></span>
950
+ Retry
951
+ </button>
952
+ </div>
953
+ </div>
954
+ }
955
+ </div>
956
+ </div>
957
+ </ng-template>
958
+ </kendo-tabstrip-tab>
959
+ }
960
+ </kendo-tabstrip>
961
+ } @else {
962
+ <!-- Single option: no tabs needed -->
963
+ <div style="height: 100%; display: flex; flex-direction: column;">
964
+ <!-- Tab Action Bar -->
965
+ <div class="tab-action-bar">
966
+ <div class="tab-actions-left">
967
+ <!-- Space for future left-aligned actions -->
968
+ </div>
969
+ <div class="tab-actions-right">
970
+ <button class="tab-action-button create-button"
971
+ *ngIf="ShowCreateReportButton && !matchingReportID"
972
+ (click)="createReportForOption(0)"
973
+ [disabled]="isCreatingReport">
974
+ <i class="fa-solid fa-plus"></i>
975
+ <span>Create Report</span>
976
+ </button>
977
+ <button class="tab-action-button print-button"
978
+ *ngIf="ShowPrintReport"
979
+ (click)="PrintReport()"
980
+ title="Print Report">
981
+ <i class="fa-solid fa-print"></i>
982
+ <span>Print Report</span>
983
+ </button>
984
+ </div>
985
+ </div>
986
+
987
+ <!-- React component container -->
988
+ <div #htmlContainer style="flex: 1; position: relative; min-height: 0;">
989
+ <!-- Content will be rendered here by React host -->
990
+
991
+ <!-- Error overlay (shown on top of content when needed) -->
992
+ @if (currentError) {
993
+ <div style="position: absolute;
994
+ top: 0;
995
+ left: 0;
996
+ right: 0;
997
+ bottom: 0;
998
+ display: flex;
999
+ align-items: flex-start;
1000
+ justify-content: center;
1001
+ padding-top: 20px;
1002
+ background: rgba(255, 255, 255, 0.95);
1003
+ z-index: 10;">
1004
+ <div style="width: 90%;
1005
+ max-width: 600px;
1006
+ height: 500px;
1007
+ background-color: #f8f9fa;
1008
+ border: 2px solid #dc3545;
1009
+ border-radius: 8px;
1010
+ padding: 20px;
1011
+ overflow-y: auto;
1012
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);">
1013
+ <div style="position: relative;">
1014
+ <button kendoButton (click)="copyErrorToClipboard()"
1015
+ style="position: absolute; top: 0; right: 0; font-size: 12px;">
1016
+ <span class="fa-solid fa-copy"></span>
1017
+ Copy Error Details
1018
+ </button>
1019
+ <h3 style="color: #dc3545; margin-top: 0; margin-right: 150px; font-size: 18px;">
1020
+ <span class="fa-solid fa-exclamation-triangle"></span>
1021
+ Component Rendering Error
1022
+ </h3>
1023
+ </div>
1024
+ <p style="margin-bottom: 10px; font-size: 14px;">
1025
+ The selected component option could not be rendered due to the following error:
1026
+ </p>
1027
+ <div style="background-color: #fff; border: 1px solid #dee2e6;
1028
+ border-radius: 4px; padding: 12px; margin-bottom: 12px;
1029
+ font-family: 'Courier New', monospace; font-size: 12px;">
1030
+ <strong>Error Type:</strong> {{ currentError.type }}<br>
1031
+ <strong>Details:</strong> {{ currentError.message }}
1032
+ @if (currentError.technicalDetails) {
1033
+ <details style="margin-top: 8px;">
1034
+ <summary style="cursor: pointer; color: #0056b3;">Technical Details (click to expand)</summary>
1035
+ <pre style="margin-top: 8px; white-space: pre-wrap; word-break: break-word; font-size: 11px;">{{ currentError.technicalDetails }}</pre>
1036
+ </details>
1037
+ }
1038
+ </div>
1039
+ <div style="background-color: #e7f3ff; border: 1px solid #b3d9ff;
1040
+ border-radius: 4px; padding: 12px; margin-bottom: 12px;">
1041
+ <strong style="font-size: 14px;">What to do:</strong>
1042
+ <ol style="margin: 8px 0 0 20px; padding: 0; font-size: 13px;">
1043
+ <li>Copy the error details and send them back to Skip in the chat to get a corrected version</li>
1044
+ <li>Contact your IT department if the issue persists</li>
1045
+ </ol>
1046
+ </div>
1047
+ <button kendoButton (click)="retryCurrentOption()" style="font-size: 13px;">
1048
+ <span class="fa-solid fa-rotate"></span>
1049
+ Retry
1050
+ </button>
1051
+ </div>
1052
+ </div>
1053
+ }
1054
+ </div>
1055
+ </div>
1056
+ }
1057
+
1058
+ `, styles: ["\n :host {\n display: block;\n height: 100%;\n position: relative;\n }\n \n /* Tab Action Bar */\n .tab-action-bar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background-color: #fafafa;\n border-bottom: 1px solid #e0e0e0;\n }\n \n .tab-actions-left,\n .tab-actions-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n \n /* Tab Action Buttons */\n .tab-action-button {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n background-color: transparent;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: #333;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n \n .tab-action-button:hover:not(:disabled) {\n background-color: #f5f5f5;\n border-color: #d0d0d0;\n }\n \n .tab-action-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .tab-action-button i {\n font-size: 12px;\n }\n \n /* Both buttons use the same white/secondary style */\n .tab-action-button.create-button,\n .tab-action-button.print-button {\n background-color: white;\n color: #333;\n border-color: #e0e0e0;\n }\n \n .tab-action-button.create-button:hover:not(:disabled),\n .tab-action-button.print-button:hover:not(:disabled) {\n background-color: #f5f5f5;\n border-color: #d0d0d0;\n }\n \n /* Tab styling */\n ::ng-deep .k-tabstrip {\n border: none;\n height: 100%;\n display: flex;\n flex-direction: column;\n margin: 10px 5px 5px 5px;\n }\n \n ::ng-deep .k-tabstrip-items {\n background: #f8f9fa;\n border: none;\n border-radius: 8px 8px 0 0;\n flex: 0 0 auto;\n padding: 8px 12px 0 12px;\n gap: 4px;\n display: flex;\n }\n \n ::ng-deep .k-tabstrip-items-wrapper {\n height: 100%;\n }\n \n ::ng-deep .k-content {\n flex: 1;\n overflow: hidden;\n padding: 0;\n background: white;\n border: 1px solid #e0e0e0;\n border-top: none;\n border-radius: 0 0 8px 8px;\n }\n \n ::ng-deep .k-tabstrip .k-item {\n margin-right: 2px;\n border: none;\n background: transparent;\n border-radius: 6px 6px 0 0;\n padding: 2px;\n transition: all 0.2s ease;\n }\n \n ::ng-deep .k-tabstrip .k-item.k-selected {\n background: white;\n border: 1px solid #e0e0e0;\n border-bottom: 1px solid white;\n margin-bottom: -1px;\n z-index: 1;\n }\n \n ::ng-deep .k-tabstrip .k-link {\n padding: 8px 16px;\n font-weight: 500;\n font-size: 13px;\n color: #666;\n transition: all 0.15s ease;\n border-radius: 4px 4px 0 0;\n background: transparent;\n border: none;\n text-transform: lowercase;\n }\n \n ::ng-deep .k-tabstrip .k-link:first-letter {\n text-transform: uppercase;\n }\n \n ::ng-deep .k-tabstrip .k-item:hover:not(.k-selected) .k-link {\n color: #333;\n background: rgba(0, 0, 0, 0.04);\n }\n \n ::ng-deep .k-tabstrip .k-item.k-selected .k-link {\n color: #1976d2;\n font-weight: 600;\n background: white;\n }\n \n /* Star icon styling */\n ::ng-deep .k-tabstrip .k-link .star-icon {\n display: inline-block;\n margin-right: 4px;\n color: #ffd700;\n font-size: 12px;\n vertical-align: middle;\n }\n \n /* Hide default Kendo tab styling */\n ::ng-deep .k-tabstrip-items::before,\n ::ng-deep .k-tabstrip-items::after {\n display: none;\n }\n \n ::ng-deep .k-tabstrip .k-item::before,\n ::ng-deep .k-tabstrip .k-item::after {\n display: none;\n }\n \n /* Remove focus outline */\n ::ng-deep .k-tabstrip .k-link:focus {\n outline: none;\n box-shadow: none;\n }\n \n /* Make sure tab content fills available space */\n ::ng-deep .k-tabstrip .k-content.k-state-active {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n \n /* React host container */\n .react-host-container {\n width: 100%;\n height: 100%;\n }\n "] }]
1059
+ }], () => [], { HTMLReport: [{
230
1060
  type: Input
231
- }], HTMLReportObjectName: [{
1061
+ }], ComponentObjectName: [{
232
1062
  type: Input
233
1063
  }], ShowPrintReport: [{
234
1064
  type: Input
1065
+ }], ShowReportOptionsToggle: [{
1066
+ type: Input
1067
+ }], ShowCreateReportButton: [{
1068
+ type: Input
1069
+ }], matchingReportID: [{
1070
+ type: Input
235
1071
  }], DrillDownEvent: [{
236
1072
  type: Output
237
- }], htmlContainer: [{
238
- type: ViewChild,
239
- args: ['htmlContainer', { static: false }]
1073
+ }], CreateReportRequested: [{
1074
+ type: Output
1075
+ }], htmlContainers: [{
1076
+ type: ViewChildren,
1077
+ args: ['htmlContainer']
240
1078
  }], SkipData: [{
241
1079
  type: Input
242
1080
  }] }); })();
243
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SkipDynamicHTMLReportComponent, { className: "SkipDynamicHTMLReportComponent", filePath: "src/lib/dynamic-report/dynamic-html-report.ts", lineNumber: 22 }); })();
1081
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SkipDynamicHTMLReportComponent, { className: "SkipDynamicHTMLReportComponent", filePath: "src/lib/dynamic-report/dynamic-html-report.ts", lineNumber: 407 }); })();
244
1082
  //# sourceMappingURL=dynamic-html-report.js.map