@memberjunction/ng-feedback 0.0.1 → 5.30.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 (38) hide show
  1. package/dist/lib/components/feedback-button.component.d.ts +59 -0
  2. package/dist/lib/components/feedback-button.component.d.ts.map +1 -0
  3. package/dist/lib/components/feedback-button.component.js +108 -0
  4. package/dist/lib/components/feedback-button.component.js.map +1 -0
  5. package/dist/lib/components/feedback-form.component.d.ts +101 -0
  6. package/dist/lib/components/feedback-form.component.d.ts.map +1 -0
  7. package/dist/lib/components/feedback-form.component.js +920 -0
  8. package/dist/lib/components/feedback-form.component.js.map +1 -0
  9. package/dist/lib/feedback.config.d.ts +67 -0
  10. package/dist/lib/feedback.config.d.ts.map +1 -0
  11. package/dist/lib/feedback.config.js +33 -0
  12. package/dist/lib/feedback.config.js.map +1 -0
  13. package/dist/lib/feedback.constants.d.ts +14 -0
  14. package/dist/lib/feedback.constants.d.ts.map +1 -0
  15. package/dist/lib/feedback.constants.js +60 -0
  16. package/dist/lib/feedback.constants.js.map +1 -0
  17. package/dist/lib/feedback.module.d.ts +77 -0
  18. package/dist/lib/feedback.module.d.ts.map +1 -0
  19. package/dist/lib/feedback.module.js +121 -0
  20. package/dist/lib/feedback.module.js.map +1 -0
  21. package/dist/lib/feedback.types.d.ts +73 -0
  22. package/dist/lib/feedback.types.d.ts.map +1 -0
  23. package/dist/lib/feedback.types.js +2 -0
  24. package/dist/lib/feedback.types.js.map +1 -0
  25. package/dist/lib/services/feedback-dialog.service.d.ts +85 -0
  26. package/dist/lib/services/feedback-dialog.service.d.ts.map +1 -0
  27. package/dist/lib/services/feedback-dialog.service.js +177 -0
  28. package/dist/lib/services/feedback-dialog.service.js.map +1 -0
  29. package/dist/lib/services/feedback.service.d.ts +63 -0
  30. package/dist/lib/services/feedback.service.d.ts.map +1 -0
  31. package/dist/lib/services/feedback.service.js +240 -0
  32. package/dist/lib/services/feedback.service.js.map +1 -0
  33. package/dist/public-api.d.ts +9 -0
  34. package/dist/public-api.d.ts.map +1 -0
  35. package/dist/public-api.js +18 -0
  36. package/dist/public-api.js.map +1 -0
  37. package/package.json +37 -7
  38. package/README.md +0 -45
@@ -0,0 +1,920 @@
1
+ import { Component, Input, Output, EventEmitter, Inject } from '@angular/core';
2
+ import { FormsModule } from '@angular/forms';
3
+ import { FEEDBACK_CONFIG, mergeFieldConfig } from '../feedback.config';
4
+ import { MJDialogComponent, MJDialogActionsComponent, MJButtonDirective } from '@memberjunction/ng-ui-components';
5
+ import { SharedGenericModule } from '@memberjunction/ng-shared-generic';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "../services/feedback.service";
8
+ import * as i2 from "@angular/forms";
9
+ import * as i3 from "@memberjunction/ng-shared-generic";
10
+ function FeedbackFormComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
11
+ i0.ɵɵelementStart(0, "div", 1);
12
+ i0.ɵɵtext(1);
13
+ i0.ɵɵelementEnd();
14
+ } if (rf & 2) {
15
+ const ctx_r0 = i0.ɵɵnextContext();
16
+ i0.ɵɵadvance();
17
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.config.subtitle, " ");
18
+ } }
19
+ function FeedbackFormComponent_Conditional_6_Conditional_17_Template(rf, ctx) { if (rf & 1) {
20
+ i0.ɵɵelementStart(0, "div", 14);
21
+ i0.ɵɵelement(1, "i", 21);
22
+ i0.ɵɵtext(2, " Analyzing feedback type... ");
23
+ i0.ɵɵelementEnd();
24
+ } }
25
+ function FeedbackFormComponent_Conditional_6_Conditional_18_Template(rf, ctx) { if (rf & 1) {
26
+ i0.ɵɵelementStart(0, "div", 15);
27
+ i0.ɵɵelement(1, "i", 22);
28
+ i0.ɵɵtext(2);
29
+ i0.ɵɵelementEnd();
30
+ } if (rf & 2) {
31
+ const ctx_r0 = i0.ɵɵnextContext(2);
32
+ i0.ɵɵadvance(2);
33
+ i0.ɵɵtextInterpolate1(" Classified as ", ctx_r0.Category, " ");
34
+ } }
35
+ function FeedbackFormComponent_Conditional_6_Conditional_19_Conditional_0_Template(rf, ctx) { if (rf & 1) {
36
+ const _r3 = i0.ɵɵgetCurrentView();
37
+ i0.ɵɵelementStart(0, "div", 8)(1, "label", 9);
38
+ i0.ɵɵtext(2, " Steps to Reproduce ");
39
+ i0.ɵɵelementStart(3, "span", 23);
40
+ i0.ɵɵtext(4, "(recommended)");
41
+ i0.ɵɵelementEnd()();
42
+ i0.ɵɵelementStart(5, "textarea", 24);
43
+ i0.ɵɵtwoWayListener("ngModelChange", function FeedbackFormComponent_Conditional_6_Conditional_19_Conditional_0_Template_textarea_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.StepsToReproduce, $event) || (ctx_r0.StepsToReproduce = $event); return i0.ɵɵresetView($event); });
44
+ i0.ɵɵelementEnd()();
45
+ } if (rf & 2) {
46
+ const ctx_r0 = i0.ɵɵnextContext(3);
47
+ i0.ɵɵadvance(5);
48
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.StepsToReproduce);
49
+ } }
50
+ function FeedbackFormComponent_Conditional_6_Conditional_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
51
+ const _r4 = i0.ɵɵgetCurrentView();
52
+ i0.ɵɵelementStart(0, "div", 8)(1, "label", 9);
53
+ i0.ɵɵtext(2, "Expected Behavior");
54
+ i0.ɵɵelementEnd();
55
+ i0.ɵɵelementStart(3, "textarea", 25);
56
+ i0.ɵɵtwoWayListener("ngModelChange", function FeedbackFormComponent_Conditional_6_Conditional_19_Conditional_1_Template_textarea_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.ExpectedBehavior, $event) || (ctx_r0.ExpectedBehavior = $event); return i0.ɵɵresetView($event); });
57
+ i0.ɵɵelementEnd()();
58
+ } if (rf & 2) {
59
+ const ctx_r0 = i0.ɵɵnextContext(3);
60
+ i0.ɵɵadvance(3);
61
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.ExpectedBehavior);
62
+ } }
63
+ function FeedbackFormComponent_Conditional_6_Conditional_19_Conditional_2_Template(rf, ctx) { if (rf & 1) {
64
+ const _r5 = i0.ɵɵgetCurrentView();
65
+ i0.ɵɵelementStart(0, "div", 8)(1, "label", 9);
66
+ i0.ɵɵtext(2, "Actual Behavior");
67
+ i0.ɵɵelementEnd();
68
+ i0.ɵɵelementStart(3, "textarea", 26);
69
+ i0.ɵɵtwoWayListener("ngModelChange", function FeedbackFormComponent_Conditional_6_Conditional_19_Conditional_2_Template_textarea_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.ActualBehavior, $event) || (ctx_r0.ActualBehavior = $event); return i0.ɵɵresetView($event); });
70
+ i0.ɵɵelementEnd()();
71
+ } if (rf & 2) {
72
+ const ctx_r0 = i0.ɵɵnextContext(3);
73
+ i0.ɵɵadvance(3);
74
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.ActualBehavior);
75
+ } }
76
+ function FeedbackFormComponent_Conditional_6_Conditional_19_Template(rf, ctx) { if (rf & 1) {
77
+ i0.ɵɵconditionalCreate(0, FeedbackFormComponent_Conditional_6_Conditional_19_Conditional_0_Template, 6, 1, "div", 8);
78
+ i0.ɵɵconditionalCreate(1, FeedbackFormComponent_Conditional_6_Conditional_19_Conditional_1_Template, 4, 1, "div", 8);
79
+ i0.ɵɵconditionalCreate(2, FeedbackFormComponent_Conditional_6_Conditional_19_Conditional_2_Template, 4, 1, "div", 8);
80
+ } if (rf & 2) {
81
+ const ctx_r0 = i0.ɵɵnextContext(2);
82
+ i0.ɵɵconditional(ctx_r0.FieldConfig.showStepsToReproduce ? 0 : -1);
83
+ i0.ɵɵadvance();
84
+ i0.ɵɵconditional(ctx_r0.FieldConfig.showExpectedBehavior ? 1 : -1);
85
+ i0.ɵɵadvance();
86
+ i0.ɵɵconditional(ctx_r0.FieldConfig.showActualBehavior ? 2 : -1);
87
+ } }
88
+ function FeedbackFormComponent_Conditional_6_Conditional_20_Conditional_0_Template(rf, ctx) { if (rf & 1) {
89
+ const _r6 = i0.ɵɵgetCurrentView();
90
+ i0.ɵɵelementStart(0, "div", 8)(1, "label", 9);
91
+ i0.ɵɵtext(2, " Use Case ");
92
+ i0.ɵɵelementStart(3, "span", 23);
93
+ i0.ɵɵtext(4, "(recommended)");
94
+ i0.ɵɵelementEnd()();
95
+ i0.ɵɵelementStart(5, "textarea", 27);
96
+ i0.ɵɵtwoWayListener("ngModelChange", function FeedbackFormComponent_Conditional_6_Conditional_20_Conditional_0_Template_textarea_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.UseCase, $event) || (ctx_r0.UseCase = $event); return i0.ɵɵresetView($event); });
97
+ i0.ɵɵelementEnd()();
98
+ } if (rf & 2) {
99
+ const ctx_r0 = i0.ɵɵnextContext(3);
100
+ i0.ɵɵadvance(5);
101
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.UseCase);
102
+ } }
103
+ function FeedbackFormComponent_Conditional_6_Conditional_20_Conditional_1_Template(rf, ctx) { if (rf & 1) {
104
+ const _r7 = i0.ɵɵgetCurrentView();
105
+ i0.ɵɵelementStart(0, "div", 8)(1, "label", 9);
106
+ i0.ɵɵtext(2, " Proposed Solution ");
107
+ i0.ɵɵelementStart(3, "span", 23);
108
+ i0.ɵɵtext(4, "(optional)");
109
+ i0.ɵɵelementEnd()();
110
+ i0.ɵɵelementStart(5, "textarea", 28);
111
+ i0.ɵɵtwoWayListener("ngModelChange", function FeedbackFormComponent_Conditional_6_Conditional_20_Conditional_1_Template_textarea_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.ProposedSolution, $event) || (ctx_r0.ProposedSolution = $event); return i0.ɵɵresetView($event); });
112
+ i0.ɵɵelementEnd()();
113
+ } if (rf & 2) {
114
+ const ctx_r0 = i0.ɵɵnextContext(3);
115
+ i0.ɵɵadvance(5);
116
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.ProposedSolution);
117
+ } }
118
+ function FeedbackFormComponent_Conditional_6_Conditional_20_Template(rf, ctx) { if (rf & 1) {
119
+ i0.ɵɵconditionalCreate(0, FeedbackFormComponent_Conditional_6_Conditional_20_Conditional_0_Template, 6, 1, "div", 8);
120
+ i0.ɵɵconditionalCreate(1, FeedbackFormComponent_Conditional_6_Conditional_20_Conditional_1_Template, 6, 1, "div", 8);
121
+ } if (rf & 2) {
122
+ const ctx_r0 = i0.ɵɵnextContext(2);
123
+ i0.ɵɵconditional(ctx_r0.FieldConfig.showUseCase ? 0 : -1);
124
+ i0.ɵɵadvance();
125
+ i0.ɵɵconditional(ctx_r0.FieldConfig.showProposedSolution ? 1 : -1);
126
+ } }
127
+ function FeedbackFormComponent_Conditional_6_Conditional_21_Conditional_1_Template(rf, ctx) { if (rf & 1) {
128
+ const _r8 = i0.ɵɵgetCurrentView();
129
+ i0.ɵɵelementStart(0, "div", 29)(1, "label", 9);
130
+ i0.ɵɵtext(2, "Your Name ");
131
+ i0.ɵɵelementStart(3, "span", 23);
132
+ i0.ɵɵtext(4, "(optional)");
133
+ i0.ɵɵelementEnd()();
134
+ i0.ɵɵelementStart(5, "input", 30);
135
+ i0.ɵɵtwoWayListener("ngModelChange", function FeedbackFormComponent_Conditional_6_Conditional_21_Conditional_1_Template_input_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.Name, $event) || (ctx_r0.Name = $event); return i0.ɵɵresetView($event); });
136
+ i0.ɵɵelementEnd()();
137
+ } if (rf & 2) {
138
+ const ctx_r0 = i0.ɵɵnextContext(3);
139
+ i0.ɵɵadvance(5);
140
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.Name);
141
+ } }
142
+ function FeedbackFormComponent_Conditional_6_Conditional_21_Conditional_2_Template(rf, ctx) { if (rf & 1) {
143
+ const _r9 = i0.ɵɵgetCurrentView();
144
+ i0.ɵɵelementStart(0, "div", 29)(1, "label", 9);
145
+ i0.ɵɵtext(2, "Email ");
146
+ i0.ɵɵelementStart(3, "span", 23);
147
+ i0.ɵɵtext(4, "(for follow-up)");
148
+ i0.ɵɵelementEnd()();
149
+ i0.ɵɵelementStart(5, "input", 31);
150
+ i0.ɵɵtwoWayListener("ngModelChange", function FeedbackFormComponent_Conditional_6_Conditional_21_Conditional_2_Template_input_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r0 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r0.Email, $event) || (ctx_r0.Email = $event); return i0.ɵɵresetView($event); });
151
+ i0.ɵɵelementEnd()();
152
+ } if (rf & 2) {
153
+ const ctx_r0 = i0.ɵɵnextContext(3);
154
+ i0.ɵɵadvance(5);
155
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.Email);
156
+ } }
157
+ function FeedbackFormComponent_Conditional_6_Conditional_21_Template(rf, ctx) { if (rf & 1) {
158
+ i0.ɵɵelementStart(0, "div", 16);
159
+ i0.ɵɵconditionalCreate(1, FeedbackFormComponent_Conditional_6_Conditional_21_Conditional_1_Template, 6, 1, "div", 29);
160
+ i0.ɵɵconditionalCreate(2, FeedbackFormComponent_Conditional_6_Conditional_21_Conditional_2_Template, 6, 1, "div", 29);
161
+ i0.ɵɵelementEnd();
162
+ } if (rf & 2) {
163
+ const ctx_r0 = i0.ɵɵnextContext(2);
164
+ i0.ɵɵadvance();
165
+ i0.ɵɵconditional(ctx_r0.FieldConfig.showName ? 1 : -1);
166
+ i0.ɵɵadvance();
167
+ i0.ɵɵconditional(ctx_r0.FieldConfig.showEmail ? 2 : -1);
168
+ } }
169
+ function FeedbackFormComponent_Conditional_6_Conditional_22_Template(rf, ctx) { if (rf & 1) {
170
+ const _r10 = i0.ɵɵgetCurrentView();
171
+ i0.ɵɵelementStart(0, "div", 8)(1, "label", 9);
172
+ i0.ɵɵtext(2, "Screenshot");
173
+ i0.ɵɵelementEnd();
174
+ i0.ɵɵelementStart(3, "div", 32);
175
+ i0.ɵɵelement(4, "img", 33);
176
+ i0.ɵɵelementStart(5, "button", 34);
177
+ i0.ɵɵlistener("click", function FeedbackFormComponent_Conditional_6_Conditional_22_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.RemoveScreenshot()); });
178
+ i0.ɵɵelement(6, "i", 35);
179
+ i0.ɵɵelementEnd()();
180
+ i0.ɵɵelementStart(7, "div", 36);
181
+ i0.ɵɵelement(8, "i", 37);
182
+ i0.ɵɵtext(9, " This screenshot will be included in the public GitHub issue. ");
183
+ i0.ɵɵelementEnd()();
184
+ } if (rf & 2) {
185
+ const ctx_r0 = i0.ɵɵnextContext(2);
186
+ i0.ɵɵadvance(4);
187
+ i0.ɵɵproperty("src", ctx_r0.ScreenshotDataUrl, i0.ɵɵsanitizeUrl);
188
+ } }
189
+ function FeedbackFormComponent_Conditional_6_Conditional_23_Template(rf, ctx) { if (rf & 1) {
190
+ const _r11 = i0.ɵɵgetCurrentView();
191
+ i0.ɵɵelementStart(0, "div", 8)(1, "button", 38);
192
+ i0.ɵɵlistener("click", function FeedbackFormComponent_Conditional_6_Conditional_23_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r11); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.IncludeScreenshot()); });
193
+ i0.ɵɵelement(2, "i", 39);
194
+ i0.ɵɵtext(3, " Include screenshot of current view ");
195
+ i0.ɵɵelementEnd()();
196
+ } }
197
+ function FeedbackFormComponent_Conditional_6_Conditional_24_Template(rf, ctx) { if (rf & 1) {
198
+ i0.ɵɵelementStart(0, "div", 8)(1, "div", 40);
199
+ i0.ɵɵelement(2, "i", 21);
200
+ i0.ɵɵtext(3, " Preparing screenshot... ");
201
+ i0.ɵɵelementEnd()();
202
+ } }
203
+ function FeedbackFormComponent_Conditional_6_Conditional_25_Template(rf, ctx) { if (rf & 1) {
204
+ i0.ɵɵelementStart(0, "div", 17);
205
+ i0.ɵɵelement(1, "i", 41);
206
+ i0.ɵɵelementStart(2, "span");
207
+ i0.ɵɵtext(3);
208
+ i0.ɵɵelementEnd()();
209
+ } if (rf & 2) {
210
+ const ctx_r0 = i0.ɵɵnextContext(2);
211
+ i0.ɵɵadvance(3);
212
+ i0.ɵɵtextInterpolate(ctx_r0.ErrorMessage);
213
+ } }
214
+ function FeedbackFormComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
215
+ const _r2 = i0.ɵɵgetCurrentView();
216
+ i0.ɵɵelementStart(0, "div", 4)(1, "div", 8)(2, "label", 9);
217
+ i0.ɵɵtext(3, " Title ");
218
+ i0.ɵɵelementStart(4, "span", 10);
219
+ i0.ɵɵtext(5, "*");
220
+ i0.ɵɵelementEnd()();
221
+ i0.ɵɵelementStart(6, "input", 11);
222
+ i0.ɵɵtwoWayListener("ngModelChange", function FeedbackFormComponent_Conditional_6_Template_input_ngModelChange_6_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.Title, $event) || (ctx_r0.Title = $event); return i0.ɵɵresetView($event); });
223
+ i0.ɵɵlistener("ngModelChange", function FeedbackFormComponent_Conditional_6_Template_input_ngModelChange_6_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnFieldChange()); });
224
+ i0.ɵɵelementEnd();
225
+ i0.ɵɵelementStart(7, "div", 12);
226
+ i0.ɵɵtext(8);
227
+ i0.ɵɵelementEnd()();
228
+ i0.ɵɵelementStart(9, "div", 8)(10, "label", 9);
229
+ i0.ɵɵtext(11, " Description ");
230
+ i0.ɵɵelementStart(12, "span", 10);
231
+ i0.ɵɵtext(13, "*");
232
+ i0.ɵɵelementEnd()();
233
+ i0.ɵɵelementStart(14, "textarea", 13);
234
+ i0.ɵɵtwoWayListener("ngModelChange", function FeedbackFormComponent_Conditional_6_Template_textarea_ngModelChange_14_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.Description, $event) || (ctx_r0.Description = $event); return i0.ɵɵresetView($event); });
235
+ i0.ɵɵlistener("ngModelChange", function FeedbackFormComponent_Conditional_6_Template_textarea_ngModelChange_14_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnFieldChange()); });
236
+ i0.ɵɵelementEnd();
237
+ i0.ɵɵelementStart(15, "div", 12);
238
+ i0.ɵɵtext(16);
239
+ i0.ɵɵelementEnd();
240
+ i0.ɵɵconditionalCreate(17, FeedbackFormComponent_Conditional_6_Conditional_17_Template, 3, 0, "div", 14)(18, FeedbackFormComponent_Conditional_6_Conditional_18_Template, 3, 1, "div", 15);
241
+ i0.ɵɵelementEnd();
242
+ i0.ɵɵconditionalCreate(19, FeedbackFormComponent_Conditional_6_Conditional_19_Template, 3, 3);
243
+ i0.ɵɵconditionalCreate(20, FeedbackFormComponent_Conditional_6_Conditional_20_Template, 2, 2);
244
+ i0.ɵɵconditionalCreate(21, FeedbackFormComponent_Conditional_6_Conditional_21_Template, 3, 2, "div", 16);
245
+ i0.ɵɵconditionalCreate(22, FeedbackFormComponent_Conditional_6_Conditional_22_Template, 10, 1, "div", 8)(23, FeedbackFormComponent_Conditional_6_Conditional_23_Template, 4, 0, "div", 8)(24, FeedbackFormComponent_Conditional_6_Conditional_24_Template, 4, 0, "div", 8);
246
+ i0.ɵɵconditionalCreate(25, FeedbackFormComponent_Conditional_6_Conditional_25_Template, 4, 1, "div", 17);
247
+ i0.ɵɵelementStart(26, "label", 18)(27, "input", 19);
248
+ i0.ɵɵtwoWayListener("ngModelChange", function FeedbackFormComponent_Conditional_6_Template_input_ngModelChange_27_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.CertificationAccepted, $event) || (ctx_r0.CertificationAccepted = $event); return i0.ɵɵresetView($event); });
249
+ i0.ɵɵelementEnd();
250
+ i0.ɵɵelementStart(28, "span", 20);
251
+ i0.ɵɵtext(29, " I certify that I am authorized to submit this on behalf of my organization and that this submission does not contain confidential or sensitive information. This will be posted to a public GitHub repository. ");
252
+ i0.ɵɵelementEnd()()();
253
+ } if (rf & 2) {
254
+ const ctx_r0 = i0.ɵɵnextContext();
255
+ i0.ɵɵadvance(6);
256
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.Title);
257
+ i0.ɵɵproperty("maxlength", 256);
258
+ i0.ɵɵadvance();
259
+ i0.ɵɵclassProp("warning", ctx_r0.Title.length > 0 && ctx_r0.Title.length < 5);
260
+ i0.ɵɵadvance();
261
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.Title.length, "/256 (minimum 5 characters) ");
262
+ i0.ɵɵadvance(6);
263
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.Description);
264
+ i0.ɵɵproperty("maxlength", 10000);
265
+ i0.ɵɵadvance();
266
+ i0.ɵɵclassProp("warning", ctx_r0.Description.length > 0 && ctx_r0.Description.length < 20);
267
+ i0.ɵɵadvance();
268
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.Description.length, "/10000 (minimum 20 characters) ");
269
+ i0.ɵɵadvance();
270
+ i0.ɵɵconditional(ctx_r0.IsClassifying ? 17 : ctx_r0.WasAutoClassified ? 18 : -1);
271
+ i0.ɵɵadvance(2);
272
+ i0.ɵɵconditional(ctx_r0.Category === "bug" ? 19 : -1);
273
+ i0.ɵɵadvance();
274
+ i0.ɵɵconditional(ctx_r0.Category === "feature" ? 20 : -1);
275
+ i0.ɵɵadvance();
276
+ i0.ɵɵconditional(ctx_r0.FieldConfig.showName || ctx_r0.FieldConfig.showEmail ? 21 : -1);
277
+ i0.ɵɵadvance();
278
+ i0.ɵɵconditional(ctx_r0.ScreenshotIncluded && ctx_r0.ScreenshotDataUrl ? 22 : ctx_r0.ScreenshotDataUrl && !ctx_r0.ScreenshotIncluded ? 23 : ctx_r0.IsCapturingScreenshot ? 24 : -1);
279
+ i0.ɵɵadvance(3);
280
+ i0.ɵɵconditional(ctx_r0.ErrorMessage ? 25 : -1);
281
+ i0.ɵɵadvance(2);
282
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.CertificationAccepted);
283
+ } }
284
+ function FeedbackFormComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
285
+ i0.ɵɵelement(0, "mj-loading", 5);
286
+ } }
287
+ function FeedbackFormComponent_Conditional_8_Conditional_4_Template(rf, ctx) { if (rf & 1) {
288
+ i0.ɵɵelementStart(0, "p")(1, "a", 43);
289
+ i0.ɵɵtext(2);
290
+ i0.ɵɵelementEnd()();
291
+ } if (rf & 2) {
292
+ const ctx_r0 = i0.ɵɵnextContext(2);
293
+ i0.ɵɵadvance();
294
+ i0.ɵɵproperty("href", ctx_r0.IssueUrl, i0.ɵɵsanitizeUrl);
295
+ i0.ɵɵadvance();
296
+ i0.ɵɵtextInterpolate1(" View Issue #", ctx_r0.IssueNumber, " ");
297
+ } }
298
+ function FeedbackFormComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
299
+ i0.ɵɵelementStart(0, "div", 6);
300
+ i0.ɵɵelement(1, "i", 42);
301
+ i0.ɵɵelementStart(2, "h3");
302
+ i0.ɵɵtext(3);
303
+ i0.ɵɵelementEnd();
304
+ i0.ɵɵconditionalCreate(4, FeedbackFormComponent_Conditional_8_Conditional_4_Template, 3, 2, "p");
305
+ i0.ɵɵelementEnd();
306
+ } if (rf & 2) {
307
+ const ctx_r0 = i0.ɵɵnextContext();
308
+ i0.ɵɵadvance(3);
309
+ i0.ɵɵtextInterpolate(ctx_r0.config.successMessage || "Thank you! Your feedback has been submitted.");
310
+ i0.ɵɵadvance();
311
+ i0.ɵɵconditional(ctx_r0.IssueUrl && ctx_r0.config.showIssueLink !== false ? 4 : -1);
312
+ } }
313
+ function FeedbackFormComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
314
+ const _r12 = i0.ɵɵgetCurrentView();
315
+ i0.ɵɵelementStart(0, "button", 44);
316
+ i0.ɵɵlistener("click", function FeedbackFormComponent_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnSubmit()); });
317
+ i0.ɵɵelement(1, "i", 45);
318
+ i0.ɵɵtext(2);
319
+ i0.ɵɵelementEnd();
320
+ i0.ɵɵelementStart(3, "button", 46);
321
+ i0.ɵɵlistener("click", function FeedbackFormComponent_Conditional_10_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r12); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnCancel()); });
322
+ i0.ɵɵtext(4, "Cancel");
323
+ i0.ɵɵelementEnd();
324
+ } if (rf & 2) {
325
+ const ctx_r0 = i0.ɵɵnextContext();
326
+ i0.ɵɵproperty("disabled", !ctx_r0.CanSubmit() || ctx_r0.IsSubmitting);
327
+ i0.ɵɵadvance();
328
+ i0.ɵɵclassProp("fa-spinner", ctx_r0.IsSubmitting)("fa-spin", ctx_r0.IsSubmitting)("fa-paper-plane", !ctx_r0.IsSubmitting);
329
+ i0.ɵɵadvance();
330
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.IsSubmitting ? "Submitting..." : ctx_r0.config.submitButtonText || "Submit", " ");
331
+ i0.ɵɵadvance();
332
+ i0.ɵɵproperty("disabled", ctx_r0.IsSubmitting);
333
+ } }
334
+ function FeedbackFormComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
335
+ const _r13 = i0.ɵɵgetCurrentView();
336
+ i0.ɵɵelementStart(0, "button", 47);
337
+ i0.ɵɵlistener("click", function FeedbackFormComponent_Conditional_11_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnCancel()); });
338
+ i0.ɵɵtext(1, "Close");
339
+ i0.ɵɵelementEnd();
340
+ } }
341
+ export class FeedbackFormComponent {
342
+ config;
343
+ feedbackService;
344
+ cdr;
345
+ /** Controls mj-dialog visibility — set by FeedbackDialogService */
346
+ DialogVisible = true;
347
+ // Inputs for pre-filling
348
+ PrefilledCategory;
349
+ PrefilledTitle;
350
+ ContextData;
351
+ /** Current page/view name (for apps where URL doesn't reflect navigation) */
352
+ CurrentPage;
353
+ // Outputs
354
+ Submitted = new EventEmitter();
355
+ Success = new EventEmitter();
356
+ Error = new EventEmitter();
357
+ Cancelled = new EventEmitter();
358
+ DialogClosed = new EventEmitter();
359
+ // Form fields
360
+ Category = 'bug';
361
+ Title = '';
362
+ Description = '';
363
+ StepsToReproduce = '';
364
+ ExpectedBehavior = '';
365
+ ActualBehavior = '';
366
+ Severity = 'minor';
367
+ UseCase = '';
368
+ ProposedSolution = '';
369
+ Environment = '';
370
+ AffectedArea = '';
371
+ Name = '';
372
+ Email = '';
373
+ // State
374
+ IsSubmitting = false;
375
+ IsClassifying = false;
376
+ WasAutoClassified = false;
377
+ SubmissionSuccess = false;
378
+ ErrorMessage = '';
379
+ lastClassifiedTitle = '';
380
+ lastClassifiedDescription = '';
381
+ IssueNumber;
382
+ IssueUrl;
383
+ ScreenshotDataUrl;
384
+ ScreenshotIncluded = false;
385
+ IsCapturingScreenshot = true;
386
+ CertificationAccepted = false;
387
+ classifyTimeout;
388
+ // Merged field config
389
+ FieldConfig;
390
+ constructor(config, feedbackService, cdr) {
391
+ this.config = config;
392
+ this.feedbackService = feedbackService;
393
+ this.cdr = cdr;
394
+ this.FieldConfig = mergeFieldConfig(config.fields);
395
+ }
396
+ ngOnInit() {
397
+ // Apply pre-filled values
398
+ if (this.PrefilledCategory) {
399
+ this.Category = this.PrefilledCategory;
400
+ }
401
+ if (this.PrefilledTitle) {
402
+ this.Title = this.PrefilledTitle;
403
+ }
404
+ // Extract screenshot from context data — store locally but don't include in submission until user opts in
405
+ if (this.ContextData?.['screenshot'] && typeof this.ContextData['screenshot'] === 'string') {
406
+ this.ScreenshotDataUrl = this.ContextData['screenshot'];
407
+ delete this.ContextData['screenshot'];
408
+ }
409
+ }
410
+ /**
411
+ * User opts in to include the screenshot
412
+ */
413
+ IncludeScreenshot() {
414
+ this.ScreenshotIncluded = true;
415
+ if (this.ScreenshotDataUrl) {
416
+ if (!this.ContextData) {
417
+ this.ContextData = {};
418
+ }
419
+ this.ContextData['screenshot'] = this.ScreenshotDataUrl;
420
+ }
421
+ this.cdr.detectChanges();
422
+ }
423
+ /**
424
+ * Remove the attached screenshot (opt back out)
425
+ */
426
+ RemoveScreenshot() {
427
+ this.ScreenshotIncluded = false;
428
+ if (this.ContextData) {
429
+ delete this.ContextData['screenshot'];
430
+ }
431
+ this.cdr.detectChanges();
432
+ }
433
+ /**
434
+ * Handle field value changes to ensure button state updates.
435
+ * Triggers LLM auto-classification after a debounce when description is long enough.
436
+ */
437
+ OnFieldChange() {
438
+ this.cdr.detectChanges();
439
+ this.scheduleClassification();
440
+ }
441
+ /**
442
+ * Schedule LLM classification with debounce (1 second after user stops typing)
443
+ */
444
+ scheduleClassification() {
445
+ if (this.classifyTimeout) {
446
+ clearTimeout(this.classifyTimeout);
447
+ }
448
+ // Only classify if we have enough text and haven't already classified this content
449
+ if (this.Title.trim().length >= 5 && this.Description.trim().length >= 20) {
450
+ this.classifyTimeout = setTimeout(() => this.runClassification(), 1000);
451
+ }
452
+ }
453
+ /**
454
+ * Run LLM classification and apply suggestions
455
+ */
456
+ async runClassification() {
457
+ if (this.IsClassifying || this.IsSubmitting)
458
+ return;
459
+ const title = this.Title.trim();
460
+ const description = this.Description.trim();
461
+ // Skip if content hasn't changed since last classification
462
+ if (title === this.lastClassifiedTitle && description === this.lastClassifiedDescription)
463
+ return;
464
+ this.IsClassifying = true;
465
+ this.cdr.detectChanges();
466
+ const result = await this.feedbackService.Classify(title, description);
467
+ this.IsClassifying = false;
468
+ if (result) {
469
+ this.Category = result.category;
470
+ this.Severity = result.severity;
471
+ this.WasAutoClassified = true;
472
+ this.lastClassifiedTitle = title;
473
+ this.lastClassifiedDescription = description;
474
+ }
475
+ this.cdr.detectChanges();
476
+ }
477
+ /**
478
+ * Check if form is valid for submission
479
+ */
480
+ CanSubmit() {
481
+ if (!this.Title.trim() || this.Title.length < 5) {
482
+ return false;
483
+ }
484
+ if (!this.Description.trim() || this.Description.length < 20) {
485
+ return false;
486
+ }
487
+ if (!this.Category) {
488
+ return false;
489
+ }
490
+ if (!this.CertificationAccepted) {
491
+ return false;
492
+ }
493
+ return true;
494
+ }
495
+ /**
496
+ * Submit the feedback
497
+ */
498
+ async OnSubmit() {
499
+ if (!this.CanSubmit() || this.IsSubmitting) {
500
+ return;
501
+ }
502
+ this.IsSubmitting = true;
503
+ this.ErrorMessage = '';
504
+ this.cdr.detectChanges();
505
+ const submission = this.buildSubmission();
506
+ this.Submitted.emit(submission);
507
+ this.feedbackService.Submit(submission).subscribe({
508
+ next: (response) => {
509
+ this.IsSubmitting = false;
510
+ if (response.success) {
511
+ this.SubmissionSuccess = true;
512
+ this.IssueNumber = response.issueNumber;
513
+ this.IssueUrl = response.issueUrl;
514
+ this.Success.emit(response);
515
+ }
516
+ else {
517
+ const message = response.error || 'Submission failed. Please try again.';
518
+ this.ErrorMessage = message;
519
+ this.Error.emit(new Error(message));
520
+ }
521
+ this.cdr.detectChanges();
522
+ },
523
+ error: (error) => {
524
+ this.IsSubmitting = false;
525
+ this.ErrorMessage = error.message;
526
+ this.Error.emit(error);
527
+ this.cdr.detectChanges();
528
+ }
529
+ });
530
+ }
531
+ /**
532
+ * Build the feedback submission object from current form state
533
+ */
534
+ buildSubmission() {
535
+ const submission = {
536
+ title: this.Title.trim(),
537
+ description: this.Description.trim(),
538
+ category: this.Category,
539
+ metadata: this.ContextData,
540
+ currentPage: this.CurrentPage
541
+ };
542
+ if (this.Category === 'bug') {
543
+ this.applyBugFields(submission);
544
+ }
545
+ if (this.Category === 'feature') {
546
+ this.applyFeatureFields(submission);
547
+ }
548
+ this.applyOptionalFields(submission);
549
+ return submission;
550
+ }
551
+ applyBugFields(submission) {
552
+ if (this.StepsToReproduce.trim()) {
553
+ submission.stepsToReproduce = this.StepsToReproduce.trim();
554
+ }
555
+ if (this.ExpectedBehavior.trim()) {
556
+ submission.expectedBehavior = this.ExpectedBehavior.trim();
557
+ }
558
+ if (this.ActualBehavior.trim()) {
559
+ submission.actualBehavior = this.ActualBehavior.trim();
560
+ }
561
+ if (this.Severity) {
562
+ submission.severity = this.Severity;
563
+ }
564
+ }
565
+ applyFeatureFields(submission) {
566
+ if (this.UseCase.trim()) {
567
+ submission.useCase = this.UseCase.trim();
568
+ }
569
+ if (this.ProposedSolution.trim()) {
570
+ submission.proposedSolution = this.ProposedSolution.trim();
571
+ }
572
+ }
573
+ applyOptionalFields(submission) {
574
+ if (this.Environment && this.FieldConfig.showEnvironment) {
575
+ submission.environment = this.Environment;
576
+ }
577
+ if (this.AffectedArea && this.FieldConfig.showAffectedArea) {
578
+ submission.affectedArea = this.AffectedArea;
579
+ }
580
+ if (this.Name.trim() && this.FieldConfig.showName) {
581
+ submission.name = this.Name.trim();
582
+ }
583
+ if (this.Email.trim() && this.FieldConfig.showEmail) {
584
+ submission.email = this.Email.trim();
585
+ }
586
+ }
587
+ /**
588
+ * Cancel and close the dialog
589
+ */
590
+ OnCancel() {
591
+ this.DialogVisible = false;
592
+ this.Cancelled.emit();
593
+ this.DialogClosed.emit({ success: this.SubmissionSuccess });
594
+ }
595
+ /**
596
+ * Reset the form
597
+ */
598
+ Reset() {
599
+ this.Title = '';
600
+ this.Description = '';
601
+ this.StepsToReproduce = '';
602
+ this.ExpectedBehavior = '';
603
+ this.ActualBehavior = '';
604
+ this.UseCase = '';
605
+ this.ProposedSolution = '';
606
+ this.Name = '';
607
+ this.Email = '';
608
+ this.ErrorMessage = '';
609
+ this.SubmissionSuccess = false;
610
+ this.cdr.detectChanges();
611
+ }
612
+ static ɵfac = function FeedbackFormComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FeedbackFormComponent)(i0.ɵɵdirectiveInject(FEEDBACK_CONFIG), i0.ɵɵdirectiveInject(i1.FeedbackService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
613
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FeedbackFormComponent, selectors: [["mj-feedback-form"]], inputs: { PrefilledCategory: "PrefilledCategory", PrefilledTitle: "PrefilledTitle", ContextData: "ContextData", CurrentPage: "CurrentPage" }, outputs: { Submitted: "Submitted", Success: "Success", Error: "Error", Cancelled: "Cancelled", DialogClosed: "DialogClosed" }, decls: 12, vars: 8, consts: [["Size", "lg", 3, "Close", "Visible", "Title"], [1, "feedback-subtitle"], [1, "feedback-privacy-notice"], [1, "fa-solid", "fa-circle-info"], [1, "feedback-form-content"], ["text", "Submitting your feedback...", "size", "medium"], [1, "feedback-success"], ["mjButton", "", "variant", "primary", "type", "button"], [1, "feedback-section"], [1, "feedback-label"], [1, "required"], ["type", "text", "placeholder", "Brief summary of your feedback...", 1, "mj-input", 3, "ngModelChange", "ngModel", "maxlength"], [1, "char-count"], ["placeholder", "Please provide a detailed description...", "rows", "4", 1, "mj-textarea", 3, "ngModelChange", "ngModel", "maxlength"], [1, "classify-indicator"], [1, "classify-indicator", "classified"], [1, "feedback-row"], [1, "feedback-error"], [1, "certification-label"], ["type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "ngModel"], [1, "certification-text"], [1, "fas", "fa-spinner", "fa-spin"], [1, "fas", "fa-wand-magic-sparkles"], [1, "optional-hint"], ["placeholder", "1. Go to...\n2. Click on...\n3. See error...", "rows", "3", 1, "mj-textarea", 3, "ngModelChange", "ngModel"], ["placeholder", "What should have happened?", "rows", "2", 1, "mj-textarea", 3, "ngModelChange", "ngModel"], ["placeholder", "What actually happened?", "rows", "2", 1, "mj-textarea", 3, "ngModelChange", "ngModel"], ["placeholder", "What problem would this solve? Why is it needed?", "rows", "3", 1, "mj-textarea", 3, "ngModelChange", "ngModel"], ["placeholder", "How might this work?", "rows", "2", 1, "mj-textarea", 3, "ngModelChange", "ngModel"], [1, "feedback-section", "half"], ["type", "text", "placeholder", "John Doe", 1, "mj-input", 3, "ngModelChange", "ngModel"], ["type", "text", "placeholder", "john@example.com", 1, "mj-input", 3, "ngModelChange", "ngModel"], [1, "screenshot-preview"], ["alt", "Screenshot of current view", 3, "src"], ["type", "button", "title", "Remove screenshot", 1, "screenshot-remove", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "screenshot-public-notice"], [1, "fa-solid", "fa-eye"], ["type", "button", 1, "screenshot-include-btn", 3, "click"], [1, "fa-solid", "fa-camera"], [1, "screenshot-loading"], [1, "fas", "fa-exclamation-triangle"], [1, "fas", "fa-check-circle", "fa-3x"], ["target", "_blank", "rel", "noopener noreferrer", 3, "href"], ["mjButton", "", "variant", "primary", "type", "button", 3, "click", "disabled"], [1, "fas"], ["mjButton", "", "type", "button", 3, "click", "disabled"], ["mjButton", "", "variant", "primary", "type", "button", 3, "click"]], template: function FeedbackFormComponent_Template(rf, ctx) { if (rf & 1) {
614
+ i0.ɵɵelementStart(0, "mj-dialog", 0);
615
+ i0.ɵɵlistener("Close", function FeedbackFormComponent_Template_mj_dialog_Close_0_listener() { return ctx.OnCancel(); });
616
+ i0.ɵɵconditionalCreate(1, FeedbackFormComponent_Conditional_1_Template, 2, 1, "div", 1);
617
+ i0.ɵɵelementStart(2, "div", 2);
618
+ i0.ɵɵelement(3, "i", 3);
619
+ i0.ɵɵelementStart(4, "span");
620
+ i0.ɵɵtext(5, "Feedback is submitted as a public GitHub issue. Please do not include confidential or sensitive information.");
621
+ i0.ɵɵelementEnd()();
622
+ i0.ɵɵconditionalCreate(6, FeedbackFormComponent_Conditional_6_Template, 30, 17, "div", 4);
623
+ i0.ɵɵconditionalCreate(7, FeedbackFormComponent_Conditional_7_Template, 1, 0, "mj-loading", 5);
624
+ i0.ɵɵconditionalCreate(8, FeedbackFormComponent_Conditional_8_Template, 5, 2, "div", 6);
625
+ i0.ɵɵelementStart(9, "mj-dialog-actions");
626
+ i0.ɵɵconditionalCreate(10, FeedbackFormComponent_Conditional_10_Template, 5, 9);
627
+ i0.ɵɵconditionalCreate(11, FeedbackFormComponent_Conditional_11_Template, 2, 0, "button", 7);
628
+ i0.ɵɵelementEnd()();
629
+ } if (rf & 2) {
630
+ i0.ɵɵproperty("Visible", ctx.DialogVisible)("Title", ctx.config.title || "Submit Feedback");
631
+ i0.ɵɵadvance();
632
+ i0.ɵɵconditional(ctx.config.subtitle ? 1 : -1);
633
+ i0.ɵɵadvance(5);
634
+ i0.ɵɵconditional(!ctx.IsSubmitting && !ctx.SubmissionSuccess ? 6 : -1);
635
+ i0.ɵɵadvance();
636
+ i0.ɵɵconditional(ctx.IsSubmitting ? 7 : -1);
637
+ i0.ɵɵadvance();
638
+ i0.ɵɵconditional(ctx.SubmissionSuccess ? 8 : -1);
639
+ i0.ɵɵadvance(2);
640
+ i0.ɵɵconditional(!ctx.SubmissionSuccess ? 10 : -1);
641
+ i0.ɵɵadvance();
642
+ i0.ɵɵconditional(ctx.SubmissionSuccess ? 11 : -1);
643
+ } }, dependencies: [FormsModule, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.NgControlStatus, i2.MaxLengthValidator, i2.NgModel, MJDialogComponent, MJDialogActionsComponent, MJButtonDirective, SharedGenericModule, i3.LoadingComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n }\n\n \n\n .feedback-subtitle[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n margin-bottom: var(--mj-space-2);\n }\n\n \n\n .feedback-privacy-notice[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2-5) var(--mj-space-3);\n background: var(--mj-status-warning-bg);\n border: 1px solid var(--mj-status-warning-border);\n border-radius: var(--mj-radius-md);\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n margin-bottom: var(--mj-space-2);\n }\n\n .feedback-privacy-notice[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n flex-shrink: 0;\n margin-top: 1px;\n }\n\n \n\n .feedback-form-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n max-height: 60vh;\n overflow-y: auto;\n padding: 0 var(--mj-space-1);\n }\n\n .feedback-section[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1-5);\n }\n\n .feedback-section.half[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n\n .feedback-row[_ngcontent-%COMP%] {\n display: flex;\n gap: var(--mj-space-4);\n }\n\n \n\n .feedback-label[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-semibold);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n }\n\n .required[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n }\n\n .optional-hint[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-normal);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n }\n\n .classify-indicator[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n }\n\n .classify-indicator.classified[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n }\n\n .char-count[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n text-align: right;\n }\n\n .char-count.warning[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n }\n\n .screenshot-include-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-2-5) var(--mj-space-3);\n border: 1px dashed var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n font-family: var(--mj-font-family);\n cursor: pointer;\n transition: var(--mj-transition-fast);\n }\n\n .screenshot-include-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n }\n\n .screenshot-public-notice[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n margin-top: var(--mj-space-1);\n }\n\n .screenshot-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-4);\n border: 1px dashed var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n }\n\n \n\n .certification-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: var(--mj-space-2);\n cursor: pointer;\n padding: var(--mj-space-3);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-sunken);\n }\n\n .certification-label[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex-shrink: 0;\n margin-top: 2px;\n }\n\n .certification-text[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n line-height: 1.5;\n }\n\n \n\n .screenshot-preview[_ngcontent-%COMP%] {\n position: relative;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n }\n\n .screenshot-preview[_ngcontent-%COMP%] img[_ngcontent-%COMP%] {\n width: 100%;\n display: block;\n }\n\n .screenshot-remove[_ngcontent-%COMP%] {\n position: absolute;\n top: var(--mj-space-1);\n right: var(--mj-space-1);\n width: 24px;\n height: 24px;\n border: none;\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-overlay);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: var(--mj-text-xs);\n }\n\n .screenshot-remove[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\n }\n\n \n\n .feedback-success[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--mj-space-4);\n padding: var(--mj-space-14) var(--mj-space-5);\n text-align: center;\n }\n\n .feedback-success[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n }\n\n .feedback-success[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n margin: 0;\n }\n\n .feedback-success[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: var(--mj-text-link);\n text-decoration: none;\n }\n\n .feedback-success[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n color: var(--mj-text-link-hover);\n }\n\n \n\n .feedback-error[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-3);\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: var(--mj-radius-md);\n color: var(--mj-status-error-text);\n font-size: var(--mj-text-sm);\n }"] });
644
+ }
645
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FeedbackFormComponent, [{
646
+ type: Component,
647
+ args: [{ standalone: true, imports: [FormsModule, MJDialogComponent, MJDialogActionsComponent, MJButtonDirective, SharedGenericModule], selector: 'mj-feedback-form', template: `
648
+ <mj-dialog
649
+ [Visible]="DialogVisible"
650
+ [Title]="config.title || 'Submit Feedback'"
651
+ Size="lg"
652
+ (Close)="OnCancel()">
653
+
654
+ <!-- Subtitle -->
655
+ @if (config.subtitle) {
656
+ <div class="feedback-subtitle">
657
+ {{ config.subtitle }}
658
+ </div>
659
+ }
660
+
661
+ <!-- Privacy notice -->
662
+ <div class="feedback-privacy-notice">
663
+ <i class="fa-solid fa-circle-info"></i>
664
+ <span>Feedback is submitted as a public GitHub issue. Please do not include confidential or sensitive information.</span>
665
+ </div>
666
+
667
+ @if (!IsSubmitting && !SubmissionSuccess) {
668
+ <div class="feedback-form-content">
669
+ <!-- Title -->
670
+ <div class="feedback-section">
671
+ <label class="feedback-label">
672
+ Title <span class="required">*</span>
673
+ </label>
674
+ <input
675
+ type="text"
676
+ class="mj-input"
677
+ [(ngModel)]="Title"
678
+ (ngModelChange)="OnFieldChange()"
679
+ placeholder="Brief summary of your feedback..."
680
+ [maxlength]="256" />
681
+ <div class="char-count" [class.warning]="Title.length > 0 && Title.length < 5">
682
+ {{ Title.length }}/256 (minimum 5 characters)
683
+ </div>
684
+ </div>
685
+
686
+ <!-- Description -->
687
+ <div class="feedback-section">
688
+ <label class="feedback-label">
689
+ Description <span class="required">*</span>
690
+ </label>
691
+ <textarea
692
+ class="mj-textarea"
693
+ [(ngModel)]="Description"
694
+ (ngModelChange)="OnFieldChange()"
695
+ placeholder="Please provide a detailed description..."
696
+ rows="4"
697
+ [maxlength]="10000"></textarea>
698
+ <div class="char-count" [class.warning]="Description.length > 0 && Description.length < 20">
699
+ {{ Description.length }}/10000 (minimum 20 characters)
700
+ </div>
701
+ @if (IsClassifying) {
702
+ <div class="classify-indicator">
703
+ <i class="fas fa-spinner fa-spin"></i> Analyzing feedback type...
704
+ </div>
705
+ } @else if (WasAutoClassified) {
706
+ <div class="classify-indicator classified">
707
+ <i class="fas fa-wand-magic-sparkles"></i> Classified as {{ Category }}
708
+ </div>
709
+ }
710
+ </div>
711
+
712
+ <!-- Bug-specific fields -->
713
+ @if (Category === 'bug') {
714
+ <!-- Steps to reproduce -->
715
+ @if (FieldConfig.showStepsToReproduce) {
716
+ <div class="feedback-section">
717
+ <label class="feedback-label">
718
+ Steps to Reproduce <span class="optional-hint">(recommended)</span>
719
+ </label>
720
+ <textarea
721
+ class="mj-textarea"
722
+ [(ngModel)]="StepsToReproduce"
723
+ placeholder="1. Go to...&#10;2. Click on...&#10;3. See error..."
724
+ rows="3"></textarea>
725
+ </div>
726
+ }
727
+
728
+ <!-- Expected Behavior -->
729
+ @if (FieldConfig.showExpectedBehavior) {
730
+ <div class="feedback-section">
731
+ <label class="feedback-label">Expected Behavior</label>
732
+ <textarea
733
+ class="mj-textarea"
734
+ [(ngModel)]="ExpectedBehavior"
735
+ placeholder="What should have happened?"
736
+ rows="2"></textarea>
737
+ </div>
738
+ }
739
+
740
+ <!-- Actual Behavior -->
741
+ @if (FieldConfig.showActualBehavior) {
742
+ <div class="feedback-section">
743
+ <label class="feedback-label">Actual Behavior</label>
744
+ <textarea
745
+ class="mj-textarea"
746
+ [(ngModel)]="ActualBehavior"
747
+ placeholder="What actually happened?"
748
+ rows="2"></textarea>
749
+ </div>
750
+ }
751
+
752
+ <!-- Severity is auto-classified by LLM, no dropdown needed -->
753
+ }
754
+
755
+ <!-- Feature-specific fields -->
756
+ @if (Category === 'feature') {
757
+ @if (FieldConfig.showUseCase) {
758
+ <div class="feedback-section">
759
+ <label class="feedback-label">
760
+ Use Case <span class="optional-hint">(recommended)</span>
761
+ </label>
762
+ <textarea
763
+ class="mj-textarea"
764
+ [(ngModel)]="UseCase"
765
+ placeholder="What problem would this solve? Why is it needed?"
766
+ rows="3"></textarea>
767
+ </div>
768
+ }
769
+
770
+ @if (FieldConfig.showProposedSolution) {
771
+ <div class="feedback-section">
772
+ <label class="feedback-label">
773
+ Proposed Solution <span class="optional-hint">(optional)</span>
774
+ </label>
775
+ <textarea
776
+ class="mj-textarea"
777
+ [(ngModel)]="ProposedSolution"
778
+ placeholder="How might this work?"
779
+ rows="2"></textarea>
780
+ </div>
781
+ }
782
+ }
783
+
784
+ <!-- Environment and affected area are auto-classified by LLM -->
785
+
786
+ <!-- Contact info row -->
787
+ @if (FieldConfig.showName || FieldConfig.showEmail) {
788
+ <div class="feedback-row">
789
+ @if (FieldConfig.showName) {
790
+ <div class="feedback-section half">
791
+ <label class="feedback-label">Your Name <span class="optional-hint">(optional)</span></label>
792
+ <input
793
+ type="text"
794
+ class="mj-input"
795
+ [(ngModel)]="Name"
796
+ placeholder="John Doe" />
797
+ </div>
798
+ }
799
+ @if (FieldConfig.showEmail) {
800
+ <div class="feedback-section half">
801
+ <label class="feedback-label">Email <span class="optional-hint">(for follow-up)</span></label>
802
+ <input
803
+ type="text"
804
+ class="mj-input"
805
+ [(ngModel)]="Email"
806
+ placeholder="john@example.com" />
807
+ </div>
808
+ }
809
+ </div>
810
+ }
811
+
812
+ <!-- Screenshot opt-in -->
813
+ @if (ScreenshotIncluded && ScreenshotDataUrl) {
814
+ <div class="feedback-section">
815
+ <label class="feedback-label">Screenshot</label>
816
+ <div class="screenshot-preview">
817
+ <img [src]="ScreenshotDataUrl" alt="Screenshot of current view" />
818
+ <button class="screenshot-remove" (click)="RemoveScreenshot()" type="button" title="Remove screenshot">
819
+ <i class="fa-solid fa-xmark"></i>
820
+ </button>
821
+ </div>
822
+ <div class="screenshot-public-notice">
823
+ <i class="fa-solid fa-eye"></i> This screenshot will be included in the public GitHub issue.
824
+ </div>
825
+ </div>
826
+ } @else if (ScreenshotDataUrl && !ScreenshotIncluded) {
827
+ <div class="feedback-section">
828
+ <button class="screenshot-include-btn" (click)="IncludeScreenshot()" type="button">
829
+ <i class="fa-solid fa-camera"></i> Include screenshot of current view
830
+ </button>
831
+ </div>
832
+ } @else if (IsCapturingScreenshot) {
833
+ <div class="feedback-section">
834
+ <div class="screenshot-loading">
835
+ <i class="fas fa-spinner fa-spin"></i> Preparing screenshot...
836
+ </div>
837
+ </div>
838
+ }
839
+
840
+ <!-- Error message -->
841
+ @if (ErrorMessage) {
842
+ <div class="feedback-error">
843
+ <i class="fas fa-exclamation-triangle"></i>
844
+ <span>{{ ErrorMessage }}</span>
845
+ </div>
846
+ }
847
+
848
+ <!-- Certification checkbox -->
849
+ <label class="certification-label">
850
+ <input type="checkbox" class="mj-checkbox" [(ngModel)]="CertificationAccepted" />
851
+ <span class="certification-text">
852
+ I certify that I am authorized to submit this on behalf of my organization and that this submission does not contain confidential or sensitive information. This will be posted to a public GitHub repository.
853
+ </span>
854
+ </label>
855
+ </div>
856
+ }
857
+
858
+ <!-- Loading state -->
859
+ @if (IsSubmitting) {
860
+ <mj-loading text="Submitting your feedback..." size="medium"></mj-loading>
861
+ }
862
+
863
+ <!-- Success state -->
864
+ @if (SubmissionSuccess) {
865
+ <div class="feedback-success">
866
+ <i class="fas fa-check-circle fa-3x"></i>
867
+ <h3>{{ config.successMessage || 'Thank you! Your feedback has been submitted.' }}</h3>
868
+ @if (IssueUrl && (config.showIssueLink !== false)) {
869
+ <p>
870
+ <a [href]="IssueUrl" target="_blank" rel="noopener noreferrer">
871
+ View Issue #{{ IssueNumber }}
872
+ </a>
873
+ </p>
874
+ }
875
+ </div>
876
+ }
877
+
878
+ <mj-dialog-actions>
879
+ @if (!SubmissionSuccess) {
880
+ <button
881
+ mjButton
882
+ variant="primary"
883
+ (click)="OnSubmit()"
884
+ [disabled]="!CanSubmit() || IsSubmitting"
885
+ type="button">
886
+ <i class="fas" [class.fa-spinner]="IsSubmitting" [class.fa-spin]="IsSubmitting" [class.fa-paper-plane]="!IsSubmitting"></i>
887
+ {{ IsSubmitting ? 'Submitting...' : (config.submitButtonText || 'Submit') }}
888
+ </button>
889
+ <button mjButton (click)="OnCancel()" [disabled]="IsSubmitting" type="button">Cancel</button>
890
+ }
891
+ @if (SubmissionSuccess) {
892
+ <button mjButton variant="primary" (click)="OnCancel()" type="button">Close</button>
893
+ }
894
+ </mj-dialog-actions>
895
+ </mj-dialog>
896
+ `, styles: ["\n :host {\n display: block;\n }\n\n /* Subtitle */\n .feedback-subtitle {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n margin-bottom: var(--mj-space-2);\n }\n\n /* Privacy notice */\n .feedback-privacy-notice {\n display: flex;\n align-items: flex-start;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2-5) var(--mj-space-3);\n background: var(--mj-status-warning-bg);\n border: 1px solid var(--mj-status-warning-border);\n border-radius: var(--mj-radius-md);\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n margin-bottom: var(--mj-space-2);\n }\n\n .feedback-privacy-notice i {\n flex-shrink: 0;\n margin-top: 1px;\n }\n\n /* Form content \u2014 horizontal padding prevents focus rings from being clipped by overflow */\n .feedback-form-content {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n max-height: 60vh;\n overflow-y: auto;\n padding: 0 var(--mj-space-1);\n }\n\n .feedback-section {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1-5);\n }\n\n .feedback-section.half {\n flex: 1;\n min-width: 0;\n }\n\n .feedback-row {\n display: flex;\n gap: var(--mj-space-4);\n }\n\n /* Labels */\n .feedback-label {\n font-weight: var(--mj-font-semibold);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n }\n\n .required {\n color: var(--mj-status-error);\n }\n\n .optional-hint {\n font-weight: var(--mj-font-normal);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n }\n\n .classify-indicator {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n }\n\n .classify-indicator.classified {\n color: var(--mj-brand-primary);\n }\n\n .char-count {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n text-align: right;\n }\n\n .char-count.warning {\n color: var(--mj-status-warning);\n }\n\n .screenshot-include-btn {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-2-5) var(--mj-space-3);\n border: 1px dashed var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n font-family: var(--mj-font-family);\n cursor: pointer;\n transition: var(--mj-transition-fast);\n }\n\n .screenshot-include-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n }\n\n .screenshot-public-notice {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n margin-top: var(--mj-space-1);\n }\n\n .screenshot-loading {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-4);\n border: 1px dashed var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n }\n\n /* Certification checkbox */\n .certification-label {\n display: flex;\n align-items: flex-start;\n gap: var(--mj-space-2);\n cursor: pointer;\n padding: var(--mj-space-3);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-sunken);\n }\n\n .certification-label input {\n flex-shrink: 0;\n margin-top: 2px;\n }\n\n .certification-text {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n line-height: 1.5;\n }\n\n /* Screenshot preview */\n .screenshot-preview {\n position: relative;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n }\n\n .screenshot-preview img {\n width: 100%;\n display: block;\n }\n\n .screenshot-remove {\n position: absolute;\n top: var(--mj-space-1);\n right: var(--mj-space-1);\n width: 24px;\n height: 24px;\n border: none;\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-overlay);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: var(--mj-text-xs);\n }\n\n .screenshot-remove:hover {\n background: var(--mj-status-error);\n }\n\n /* Success state */\n .feedback-success {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--mj-space-4);\n padding: var(--mj-space-14) var(--mj-space-5);\n text-align: center;\n }\n\n .feedback-success i {\n color: var(--mj-status-success);\n }\n\n .feedback-success h3 {\n color: var(--mj-text-primary);\n margin: 0;\n }\n\n .feedback-success a {\n color: var(--mj-text-link);\n text-decoration: none;\n }\n\n .feedback-success a:hover {\n text-decoration: underline;\n color: var(--mj-text-link-hover);\n }\n\n /* Error state */\n .feedback-error {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-3);\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: var(--mj-radius-md);\n color: var(--mj-status-error-text);\n font-size: var(--mj-text-sm);\n }\n "] }]
897
+ }], () => [{ type: undefined, decorators: [{
898
+ type: Inject,
899
+ args: [FEEDBACK_CONFIG]
900
+ }] }, { type: i1.FeedbackService }, { type: i0.ChangeDetectorRef }], { PrefilledCategory: [{
901
+ type: Input
902
+ }], PrefilledTitle: [{
903
+ type: Input
904
+ }], ContextData: [{
905
+ type: Input
906
+ }], CurrentPage: [{
907
+ type: Input
908
+ }], Submitted: [{
909
+ type: Output
910
+ }], Success: [{
911
+ type: Output
912
+ }], Error: [{
913
+ type: Output
914
+ }], Cancelled: [{
915
+ type: Output
916
+ }], DialogClosed: [{
917
+ type: Output
918
+ }] }); })();
919
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FeedbackFormComponent, { className: "FeedbackFormComponent", filePath: "src/lib/components/feedback-form.component.ts", lineNumber: 502 }); })();
920
+ //# sourceMappingURL=feedback-form.component.js.map