@memberjunction/ng-dashboards 2.129.0 → 2.130.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Testing/components/testing-execution.component.d.ts +16 -5
- package/dist/Testing/components/testing-execution.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-execution.component.js +452 -273
- package/dist/Testing/components/testing-execution.component.js.map +1 -1
- package/dist/Testing/components/testing-feedback.component.d.ts +70 -14
- package/dist/Testing/components/testing-feedback.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-feedback.component.js +1177 -479
- package/dist/Testing/components/testing-feedback.component.js.map +1 -1
- package/dist/Testing/components/testing-overview.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-overview.component.js +182 -162
- package/dist/Testing/components/testing-overview.component.js.map +1 -1
- package/dist/Testing/components/testing-version-comparison.component.d.ts +4 -0
- package/dist/Testing/components/testing-version-comparison.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-version-comparison.component.js +19 -5
- package/dist/Testing/components/testing-version-comparison.component.js.map +1 -1
- package/dist/Testing/services/testing-instrumentation.service.d.ts +47 -1
- package/dist/Testing/services/testing-instrumentation.service.d.ts.map +1 -1
- package/dist/Testing/services/testing-instrumentation.service.js +243 -60
- package/dist/Testing/services/testing-instrumentation.service.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +36 -34
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/package.json +27 -27
|
@@ -1,178 +1,241 @@
|
|
|
1
1
|
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
-
import { Subject } from 'rxjs';
|
|
3
|
-
import { takeUntil, map } from 'rxjs/operators';
|
|
4
|
-
import { CompositeKey } from '@memberjunction/core';
|
|
2
|
+
import { BehaviorSubject, Observable, Subject, combineLatest } from 'rxjs';
|
|
3
|
+
import { takeUntil, map, shareReplay, switchMap } from 'rxjs/operators';
|
|
4
|
+
import { CompositeKey, Metadata, RunView } from '@memberjunction/core';
|
|
5
5
|
import { SharedService } from '@memberjunction/ng-shared';
|
|
6
6
|
import * as i0 from "@angular/core";
|
|
7
7
|
import * as i1 from "../services/testing-instrumentation.service";
|
|
8
8
|
import * as i2 from "@angular/common";
|
|
9
9
|
import * as i3 from "@angular/forms";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
i0.ɵɵelementStart(0, "div", 52)(1, "span", 53);
|
|
15
|
-
i0.ɵɵtext(2);
|
|
16
|
-
i0.ɵɵpipe(3, "async");
|
|
10
|
+
const _c0 = () => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
11
|
+
function TestingFeedbackComponent_div_6_span_1_Template(rf, ctx) { if (rf & 1) {
|
|
12
|
+
i0.ɵɵelementStart(0, "span", 48);
|
|
13
|
+
i0.ɵɵtext(1);
|
|
17
14
|
i0.ɵɵelementEnd();
|
|
18
|
-
|
|
19
|
-
i0.ɵɵ
|
|
15
|
+
} if (rf & 2) {
|
|
16
|
+
const count_r1 = i0.ɵɵnextContext().ngIf;
|
|
17
|
+
i0.ɵɵadvance();
|
|
18
|
+
i0.ɵɵtextInterpolate(count_r1);
|
|
19
|
+
} }
|
|
20
|
+
function TestingFeedbackComponent_div_6_Template(rf, ctx) { if (rf & 1) {
|
|
21
|
+
i0.ɵɵelementStart(0, "div", 45);
|
|
22
|
+
i0.ɵɵtemplate(1, TestingFeedbackComponent_div_6_span_1_Template, 2, 1, "span", 46);
|
|
23
|
+
i0.ɵɵelementStart(2, "span", 47);
|
|
24
|
+
i0.ɵɵtext(3);
|
|
20
25
|
i0.ɵɵelementEnd()();
|
|
21
26
|
} if (rf & 2) {
|
|
22
|
-
const
|
|
27
|
+
const count_r1 = ctx.ngIf;
|
|
28
|
+
i0.ɵɵadvance();
|
|
29
|
+
i0.ɵɵproperty("ngIf", count_r1 > 0);
|
|
23
30
|
i0.ɵɵadvance(2);
|
|
24
|
-
i0.ɵɵtextInterpolate(
|
|
31
|
+
i0.ɵɵtextInterpolate(count_r1 > 0 ? "Pending Review" : "All Reviewed");
|
|
25
32
|
} }
|
|
26
|
-
function
|
|
33
|
+
function TestingFeedbackComponent_div_64_Template(rf, ctx) { if (rf & 1) {
|
|
27
34
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
28
|
-
i0.ɵɵelementStart(0, "
|
|
29
|
-
i0.ɵɵ
|
|
30
|
-
i0.ɵɵ
|
|
35
|
+
i0.ɵɵelementStart(0, "div", 27)(1, "label");
|
|
36
|
+
i0.ɵɵtext(2, "Reason");
|
|
37
|
+
i0.ɵɵelementEnd();
|
|
38
|
+
i0.ɵɵelementStart(3, "select", 28);
|
|
39
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TestingFeedbackComponent_div_64_Template_select_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.filters.reason, $event) || (ctx_r2.filters.reason = $event); return i0.ɵɵresetView($event); });
|
|
40
|
+
i0.ɵɵlistener("change", function TestingFeedbackComponent_div_64_Template_select_change_3_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onFilterChange()); });
|
|
41
|
+
i0.ɵɵelementStart(4, "option", 49);
|
|
42
|
+
i0.ɵɵtext(5, "All Reasons");
|
|
31
43
|
i0.ɵɵelementEnd();
|
|
44
|
+
i0.ɵɵelementStart(6, "option", 50);
|
|
45
|
+
i0.ɵɵtext(7, "No Feedback");
|
|
46
|
+
i0.ɵɵelementEnd();
|
|
47
|
+
i0.ɵɵelementStart(8, "option", 51);
|
|
48
|
+
i0.ɵɵtext(9, "High Score but Failed");
|
|
49
|
+
i0.ɵɵelementEnd();
|
|
50
|
+
i0.ɵɵelementStart(10, "option", 52);
|
|
51
|
+
i0.ɵɵtext(11, "Low Score but Passed");
|
|
52
|
+
i0.ɵɵelementEnd()()();
|
|
53
|
+
} if (rf & 2) {
|
|
54
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
55
|
+
i0.ɵɵadvance(3);
|
|
56
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.filters.reason);
|
|
32
57
|
} }
|
|
33
|
-
function
|
|
34
|
-
|
|
35
|
-
i0.ɵɵ
|
|
36
|
-
i0.ɵɵ
|
|
58
|
+
function TestingFeedbackComponent_div_65_option_6_Template(rf, ctx) { if (rf & 1) {
|
|
59
|
+
i0.ɵɵelementStart(0, "option", 53);
|
|
60
|
+
i0.ɵɵtext(1);
|
|
61
|
+
i0.ɵɵelementEnd();
|
|
62
|
+
} if (rf & 2) {
|
|
63
|
+
const suite_r5 = ctx.$implicit;
|
|
64
|
+
i0.ɵɵproperty("ngValue", suite_r5.ID);
|
|
65
|
+
i0.ɵɵadvance();
|
|
66
|
+
i0.ɵɵtextInterpolate(suite_r5.Name);
|
|
67
|
+
} }
|
|
68
|
+
function TestingFeedbackComponent_div_65_Template(rf, ctx) { if (rf & 1) {
|
|
69
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
70
|
+
i0.ɵɵelementStart(0, "div", 27)(1, "label");
|
|
71
|
+
i0.ɵɵtext(2, "Test Suite");
|
|
37
72
|
i0.ɵɵelementEnd();
|
|
38
|
-
i0.ɵɵelementStart(
|
|
39
|
-
i0.ɵɵ
|
|
73
|
+
i0.ɵɵelementStart(3, "select", 28);
|
|
74
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TestingFeedbackComponent_div_65_Template_select_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.filters.suiteId, $event) || (ctx_r2.filters.suiteId = $event); return i0.ɵɵresetView($event); });
|
|
75
|
+
i0.ɵɵlistener("change", function TestingFeedbackComponent_div_65_Template_select_change_3_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onFilterChange()); });
|
|
76
|
+
i0.ɵɵelementStart(4, "option", 53);
|
|
77
|
+
i0.ɵɵtext(5, "All Suites");
|
|
40
78
|
i0.ɵɵelementEnd();
|
|
41
|
-
i0.ɵɵ
|
|
42
|
-
i0.ɵɵ
|
|
79
|
+
i0.ɵɵtemplate(6, TestingFeedbackComponent_div_65_option_6_Template, 2, 2, "option", 54);
|
|
80
|
+
i0.ɵɵpipe(7, "async");
|
|
43
81
|
i0.ɵɵelementEnd()();
|
|
44
|
-
|
|
45
|
-
i0.ɵɵ
|
|
82
|
+
} if (rf & 2) {
|
|
83
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
84
|
+
i0.ɵɵadvance(3);
|
|
85
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.filters.suiteId);
|
|
86
|
+
i0.ɵɵadvance();
|
|
87
|
+
i0.ɵɵproperty("ngValue", null);
|
|
88
|
+
i0.ɵɵadvance(2);
|
|
89
|
+
i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind1(7, 3, ctx_r2.testSuites$));
|
|
90
|
+
} }
|
|
91
|
+
function TestingFeedbackComponent_button_72_Template(rf, ctx) { if (rf & 1) {
|
|
92
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
93
|
+
i0.ɵɵelementStart(0, "button", 55);
|
|
94
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_button_72_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.clearSearch()); });
|
|
95
|
+
i0.ɵɵelement(1, "i", 56);
|
|
46
96
|
i0.ɵɵelementEnd();
|
|
47
|
-
|
|
48
|
-
|
|
97
|
+
} }
|
|
98
|
+
function TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_div_23_button_9_Template(rf, ctx) { if (rf & 1) {
|
|
99
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
100
|
+
i0.ɵɵelementStart(0, "button", 101);
|
|
101
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_div_23_button_9_Template_button_click_0_listener() { const star_r12 = i0.ɵɵrestoreView(_r11).$implicit; const item_r9 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.setRating(item_r9, star_r12)); });
|
|
102
|
+
i0.ɵɵelement(1, "i", 102);
|
|
49
103
|
i0.ɵɵelementEnd();
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
i0.ɵɵ
|
|
53
|
-
i0.ɵɵ
|
|
54
|
-
|
|
104
|
+
} if (rf & 2) {
|
|
105
|
+
const star_r12 = ctx.$implicit;
|
|
106
|
+
const item_r9 = i0.ɵɵnextContext(2).$implicit;
|
|
107
|
+
i0.ɵɵclassProp("filled", star_r12 <= item_r9.feedbackRating);
|
|
108
|
+
} }
|
|
109
|
+
function TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_div_23_Template(rf, ctx) { if (rf & 1) {
|
|
110
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
111
|
+
i0.ɵɵelementStart(0, "div", 82)(1, "div", 83)(2, "div", 84)(3, "h4");
|
|
112
|
+
i0.ɵɵtext(4, "Provide Your Feedback");
|
|
55
113
|
i0.ɵɵelementEnd();
|
|
56
|
-
i0.ɵɵelementStart(
|
|
57
|
-
i0.ɵɵ
|
|
58
|
-
i0.ɵɵelementEnd()();
|
|
59
|
-
i0.ɵɵelementStart(22, "div", 81)(23, "button", 82);
|
|
60
|
-
i0.ɵɵlistener("click", function TestingFeedbackComponent_For_97_Conditional_23_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r5); const item_r4 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.submitFeedback(item_r4)); });
|
|
61
|
-
i0.ɵɵelement(24, "i", 83);
|
|
62
|
-
i0.ɵɵtext(25, " Submit Feedback ");
|
|
63
|
-
i0.ɵɵelementEnd();
|
|
64
|
-
i0.ɵɵelementStart(26, "button", 84);
|
|
65
|
-
i0.ɵɵlistener("click", function TestingFeedbackComponent_For_97_Conditional_23_Template_button_click_26_listener() { i0.ɵɵrestoreView(_r5); const item_r4 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.skipFeedback(item_r4)); });
|
|
66
|
-
i0.ɵɵelement(27, "i", 85);
|
|
67
|
-
i0.ɵɵtext(28, " Skip for Now ");
|
|
68
|
-
i0.ɵɵelementEnd()()();
|
|
69
|
-
i0.ɵɵelementStart(29, "div", 86)(30, "h4");
|
|
70
|
-
i0.ɵɵtext(31, "Test Context");
|
|
114
|
+
i0.ɵɵelementStart(5, "div", 85)(6, "label");
|
|
115
|
+
i0.ɵɵtext(7, "Human Rating");
|
|
71
116
|
i0.ɵɵelementEnd();
|
|
72
|
-
i0.ɵɵelementStart(
|
|
73
|
-
i0.ɵɵ
|
|
117
|
+
i0.ɵɵelementStart(8, "div", 86);
|
|
118
|
+
i0.ɵɵtemplate(9, TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_div_23_button_9_Template, 2, 2, "button", 87);
|
|
119
|
+
i0.ɵɵelementStart(10, "span", 88);
|
|
120
|
+
i0.ɵɵtext(11);
|
|
121
|
+
i0.ɵɵelementEnd()()();
|
|
122
|
+
i0.ɵɵelementStart(12, "div", 89)(13, "label");
|
|
123
|
+
i0.ɵɵtext(14, "Is the Automated Result Correct?");
|
|
74
124
|
i0.ɵɵelementEnd();
|
|
75
|
-
i0.ɵɵelementStart(
|
|
76
|
-
i0.ɵɵ
|
|
77
|
-
i0.ɵɵ
|
|
78
|
-
i0.ɵɵ
|
|
79
|
-
i0.ɵɵtext(40, "Automated Score");
|
|
125
|
+
i0.ɵɵelementStart(15, "div", 90)(16, "button", 91);
|
|
126
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_div_23_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r10); const item_r9 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.setCorrectness(item_r9, true)); });
|
|
127
|
+
i0.ɵɵelement(17, "i", 92);
|
|
128
|
+
i0.ɵɵtext(18, " Correct ");
|
|
80
129
|
i0.ɵɵelementEnd();
|
|
81
|
-
i0.ɵɵelementStart(
|
|
82
|
-
i0.ɵɵ
|
|
83
|
-
i0.ɵɵ
|
|
84
|
-
i0.ɵɵ
|
|
85
|
-
i0.ɵɵ
|
|
130
|
+
i0.ɵɵelementStart(19, "button", 93);
|
|
131
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_div_23_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r10); const item_r9 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.setCorrectness(item_r9, false)); });
|
|
132
|
+
i0.ɵɵelement(20, "i", 56);
|
|
133
|
+
i0.ɵɵtext(21, " Incorrect ");
|
|
134
|
+
i0.ɵɵelementEnd()()();
|
|
135
|
+
i0.ɵɵelementStart(22, "div", 94)(23, "label");
|
|
136
|
+
i0.ɵɵtext(24, "Comments / Correction Notes");
|
|
86
137
|
i0.ɵɵelementEnd();
|
|
87
|
-
i0.ɵɵelementStart(
|
|
88
|
-
i0.ɵɵ
|
|
138
|
+
i0.ɵɵelementStart(25, "textarea", 95);
|
|
139
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_div_23_Template_textarea_ngModelChange_25_listener($event) { i0.ɵɵrestoreView(_r10); const item_r9 = i0.ɵɵnextContext().$implicit; i0.ɵɵtwoWayBindingSet(item_r9.feedbackComments, $event) || (item_r9.feedbackComments = $event); return i0.ɵɵresetView($event); });
|
|
89
140
|
i0.ɵɵelementEnd()();
|
|
90
|
-
i0.ɵɵelementStart(
|
|
91
|
-
i0.ɵɵ
|
|
141
|
+
i0.ɵɵelementStart(26, "div", 96)(27, "button", 97);
|
|
142
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_div_23_Template_button_click_27_listener() { i0.ɵɵrestoreView(_r10); const item_r9 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.submitFeedback(item_r9)); });
|
|
143
|
+
i0.ɵɵelement(28, "i", 98);
|
|
144
|
+
i0.ɵɵtext(29);
|
|
92
145
|
i0.ɵɵelementEnd();
|
|
93
|
-
i0.ɵɵelementStart(
|
|
94
|
-
i0.ɵɵ
|
|
95
|
-
i0.ɵɵ
|
|
96
|
-
i0.ɵɵ
|
|
97
|
-
i0.ɵɵ
|
|
98
|
-
i0.ɵɵlistener("click", function TestingFeedbackComponent_For_97_Conditional_23_Template_button_click_54_listener() { i0.ɵɵrestoreView(_r5); const item_r4 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.viewFullDetails(item_r4)); });
|
|
99
|
-
i0.ɵɵelement(55, "i", 93);
|
|
100
|
-
i0.ɵɵtext(56, " View Full Test Details ");
|
|
101
|
-
i0.ɵɵelementEnd()()()();
|
|
146
|
+
i0.ɵɵelementStart(30, "button", 99);
|
|
147
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_div_23_Template_button_click_30_listener() { i0.ɵɵrestoreView(_r10); const item_r9 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.viewFullDetails(item_r9)); });
|
|
148
|
+
i0.ɵɵelement(31, "i", 100);
|
|
149
|
+
i0.ɵɵtext(32, " View Full Details ");
|
|
150
|
+
i0.ɵɵelementEnd()()()()();
|
|
102
151
|
} if (rf & 2) {
|
|
103
|
-
const
|
|
104
|
-
const
|
|
152
|
+
const item_r9 = i0.ɵɵnextContext().$implicit;
|
|
153
|
+
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
154
|
+
i0.ɵɵproperty("@slideDown", undefined);
|
|
105
155
|
i0.ɵɵadvance(9);
|
|
106
|
-
i0.ɵɵ
|
|
107
|
-
i0.ɵɵadvance(
|
|
108
|
-
i0.ɵɵ
|
|
109
|
-
i0.ɵɵadvance(6);
|
|
110
|
-
i0.ɵɵtwoWayProperty("ngModel", item_r4.feedbackComments);
|
|
111
|
-
i0.ɵɵadvance(16);
|
|
112
|
-
i0.ɵɵtextInterpolate(item_r4.testRunID);
|
|
113
|
-
i0.ɵɵadvance(5);
|
|
114
|
-
i0.ɵɵproperty("score", item_r4.automatedScore)("showBar", true);
|
|
115
|
-
i0.ɵɵadvance(5);
|
|
116
|
-
i0.ɵɵproperty("status", ctx_r0.getTestStatus(item_r4.automatedStatus));
|
|
156
|
+
i0.ɵɵproperty("ngForOf", i0.ɵɵpureFunction0(10, _c0));
|
|
157
|
+
i0.ɵɵadvance(2);
|
|
158
|
+
i0.ɵɵtextInterpolate1("", item_r9.feedbackRating, "/10");
|
|
117
159
|
i0.ɵɵadvance(5);
|
|
118
|
-
i0.ɵɵ
|
|
160
|
+
i0.ɵɵclassProp("active", item_r9.feedbackIsCorrect === true);
|
|
161
|
+
i0.ɵɵadvance(3);
|
|
162
|
+
i0.ɵɵclassProp("active", item_r9.feedbackIsCorrect === false);
|
|
163
|
+
i0.ɵɵadvance(6);
|
|
164
|
+
i0.ɵɵtwoWayProperty("ngModel", item_r9.feedbackComments);
|
|
165
|
+
i0.ɵɵadvance(2);
|
|
166
|
+
i0.ɵɵproperty("disabled", ctx_r2.isSubmitting);
|
|
167
|
+
i0.ɵɵadvance(2);
|
|
168
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r2.isSubmitting ? "Submitting..." : "Submit Feedback", " ");
|
|
119
169
|
} }
|
|
120
|
-
function
|
|
121
|
-
const
|
|
122
|
-
i0.ɵɵelementStart(0, "div",
|
|
123
|
-
i0.ɵɵlistener("click", function
|
|
124
|
-
i0.ɵɵelementStart(2, "div",
|
|
170
|
+
function TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
171
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
172
|
+
i0.ɵɵelementStart(0, "div", 68)(1, "div", 69);
|
|
173
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_Template_div_click_1_listener() { const item_r9 = i0.ɵɵrestoreView(_r8).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.toggleExpanded(item_r9.testRunID)); });
|
|
174
|
+
i0.ɵɵelementStart(2, "div", 70)(3, "div", 71);
|
|
125
175
|
i0.ɵɵtext(4);
|
|
126
176
|
i0.ɵɵelementEnd();
|
|
127
|
-
i0.ɵɵelementStart(5, "div",
|
|
128
|
-
i0.ɵɵelement(7, "i",
|
|
177
|
+
i0.ɵɵelementStart(5, "div", 72)(6, "span", 73);
|
|
178
|
+
i0.ɵɵelement(7, "i", 74);
|
|
129
179
|
i0.ɵɵtext(8);
|
|
130
180
|
i0.ɵɵpipe(9, "date");
|
|
131
181
|
i0.ɵɵelementEnd();
|
|
132
|
-
i0.ɵɵelementStart(10, "span",
|
|
133
|
-
i0.ɵɵtext(11, "
|
|
182
|
+
i0.ɵɵelementStart(10, "span", 75);
|
|
183
|
+
i0.ɵɵtext(11, " Score: ");
|
|
134
184
|
i0.ɵɵelementStart(12, "strong");
|
|
135
185
|
i0.ɵɵtext(13);
|
|
136
|
-
i0.ɵɵelementEnd()
|
|
137
|
-
i0.ɵɵ
|
|
138
|
-
i0.ɵɵ
|
|
139
|
-
i0.ɵɵ
|
|
186
|
+
i0.ɵɵelementEnd();
|
|
187
|
+
i0.ɵɵtext(14, "/10 ");
|
|
188
|
+
i0.ɵɵelementEnd();
|
|
189
|
+
i0.ɵɵelementStart(15, "span", 76);
|
|
190
|
+
i0.ɵɵtext(16);
|
|
140
191
|
i0.ɵɵelementEnd()()();
|
|
141
|
-
i0.ɵɵelementStart(17, "div",
|
|
142
|
-
i0.ɵɵelement(19, "i",
|
|
192
|
+
i0.ɵɵelementStart(17, "div", 77)(18, "span", 78);
|
|
193
|
+
i0.ɵɵelement(19, "i", 79);
|
|
143
194
|
i0.ɵɵtext(20);
|
|
144
195
|
i0.ɵɵelementEnd()();
|
|
145
|
-
i0.ɵɵelementStart(21, "button",
|
|
146
|
-
i0.ɵɵelement(22, "i",
|
|
196
|
+
i0.ɵɵelementStart(21, "button", 80);
|
|
197
|
+
i0.ɵɵelement(22, "i", 79);
|
|
147
198
|
i0.ɵɵelementEnd()();
|
|
148
|
-
i0.ɵɵtemplate(23,
|
|
199
|
+
i0.ɵɵtemplate(23, TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_div_23_Template, 33, 11, "div", 81);
|
|
149
200
|
i0.ɵɵelementEnd();
|
|
150
201
|
} if (rf & 2) {
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
i0.ɵɵclassProp("expanded",
|
|
202
|
+
const item_r9 = ctx.$implicit;
|
|
203
|
+
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
204
|
+
i0.ɵɵclassProp("expanded", ctx_r2.expandedItem === item_r9.testRunID);
|
|
154
205
|
i0.ɵɵadvance(4);
|
|
155
|
-
i0.ɵɵtextInterpolate(
|
|
206
|
+
i0.ɵɵtextInterpolate(item_r9.testName);
|
|
156
207
|
i0.ɵɵadvance(4);
|
|
157
|
-
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind2(9,
|
|
208
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind2(9, 22, item_r9.runDateTime, "short"), " ");
|
|
158
209
|
i0.ɵɵadvance(5);
|
|
159
|
-
i0.ɵɵtextInterpolate(
|
|
160
|
-
i0.ɵɵadvance(
|
|
161
|
-
i0.ɵɵ
|
|
210
|
+
i0.ɵɵtextInterpolate((item_r9.automatedScore * 10).toFixed(2));
|
|
211
|
+
i0.ɵɵadvance(2);
|
|
212
|
+
i0.ɵɵclassMap("status-" + item_r9.automatedStatus.toLowerCase());
|
|
213
|
+
i0.ɵɵadvance();
|
|
214
|
+
i0.ɵɵtextInterpolate1(" ", item_r9.automatedStatus, " ");
|
|
162
215
|
i0.ɵɵadvance(2);
|
|
163
|
-
i0.ɵɵclassMap(
|
|
216
|
+
i0.ɵɵclassMap(item_r9.reason);
|
|
164
217
|
i0.ɵɵadvance();
|
|
165
|
-
i0.ɵɵclassProp("fa-circle-info",
|
|
218
|
+
i0.ɵɵclassProp("fa-circle-info", item_r9.reason === "no-feedback")("fa-arrow-up", item_r9.reason === "high-score-failed")("fa-arrow-down", item_r9.reason === "low-score-passed");
|
|
166
219
|
i0.ɵɵadvance();
|
|
167
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
220
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r2.formatReason(item_r9.reason), " ");
|
|
168
221
|
i0.ɵɵadvance(2);
|
|
169
|
-
i0.ɵɵclassProp("fa-chevron-down",
|
|
222
|
+
i0.ɵɵclassProp("fa-chevron-down", ctx_r2.expandedItem !== item_r9.testRunID)("fa-chevron-up", ctx_r2.expandedItem === item_r9.testRunID);
|
|
170
223
|
i0.ɵɵadvance();
|
|
171
|
-
i0.ɵɵ
|
|
224
|
+
i0.ɵɵproperty("ngIf", ctx_r2.expandedItem === item_r9.testRunID);
|
|
172
225
|
} }
|
|
173
|
-
function
|
|
174
|
-
i0.ɵɵ
|
|
175
|
-
i0.ɵɵ
|
|
226
|
+
function TestingFeedbackComponent_div_73_div_15_ng_container_1_Template(rf, ctx) { if (rf & 1) {
|
|
227
|
+
i0.ɵɵelementContainerStart(0);
|
|
228
|
+
i0.ɵɵtemplate(1, TestingFeedbackComponent_div_73_div_15_ng_container_1_div_1_Template, 24, 25, "div", 67);
|
|
229
|
+
i0.ɵɵelementContainerEnd();
|
|
230
|
+
} if (rf & 2) {
|
|
231
|
+
const items_r13 = i0.ɵɵnextContext().ngIf;
|
|
232
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
233
|
+
i0.ɵɵadvance();
|
|
234
|
+
i0.ɵɵproperty("ngForOf", items_r13)("ngForTrackBy", ctx_r2.trackByTestRunId);
|
|
235
|
+
} }
|
|
236
|
+
function TestingFeedbackComponent_div_73_div_15_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
237
|
+
i0.ɵɵelementStart(0, "div", 103);
|
|
238
|
+
i0.ɵɵelement(1, "i", 104);
|
|
176
239
|
i0.ɵɵelementStart(2, "h3");
|
|
177
240
|
i0.ɵɵtext(3, "All Caught Up!");
|
|
178
241
|
i0.ɵɵelementEnd();
|
|
@@ -180,85 +243,536 @@ function TestingFeedbackComponent_ForEmpty_98_Template(rf, ctx) { if (rf & 1) {
|
|
|
180
243
|
i0.ɵɵtext(5, "No tests currently require feedback review.");
|
|
181
244
|
i0.ɵɵelementEnd()();
|
|
182
245
|
} }
|
|
246
|
+
function TestingFeedbackComponent_div_73_div_15_Template(rf, ctx) { if (rf & 1) {
|
|
247
|
+
i0.ɵɵelementStart(0, "div", 65);
|
|
248
|
+
i0.ɵɵtemplate(1, TestingFeedbackComponent_div_73_div_15_ng_container_1_Template, 2, 2, "ng-container", 66)(2, TestingFeedbackComponent_div_73_div_15_ng_template_2_Template, 6, 0, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor);
|
|
249
|
+
i0.ɵɵelementEnd();
|
|
250
|
+
} if (rf & 2) {
|
|
251
|
+
const items_r13 = ctx.ngIf;
|
|
252
|
+
const emptyPending_r14 = i0.ɵɵreference(3);
|
|
253
|
+
i0.ɵɵadvance();
|
|
254
|
+
i0.ɵɵproperty("ngIf", items_r13.length > 0)("ngIfElse", emptyPending_r14);
|
|
255
|
+
} }
|
|
256
|
+
function TestingFeedbackComponent_div_73_Template(rf, ctx) { if (rf & 1) {
|
|
257
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
258
|
+
i0.ɵɵelementStart(0, "div", 57)(1, "div", 58)(2, "h3");
|
|
259
|
+
i0.ɵɵelement(3, "i", 59);
|
|
260
|
+
i0.ɵɵtext(4, " Tests Requiring Review ");
|
|
261
|
+
i0.ɵɵelementEnd();
|
|
262
|
+
i0.ɵɵelementStart(5, "div", 60)(6, "label");
|
|
263
|
+
i0.ɵɵtext(7, "Sort by:");
|
|
264
|
+
i0.ɵɵelementEnd();
|
|
265
|
+
i0.ɵɵelementStart(8, "select", 28);
|
|
266
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TestingFeedbackComponent_div_73_Template_select_ngModelChange_8_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.sortBy, $event) || (ctx_r2.sortBy = $event); return i0.ɵɵresetView($event); });
|
|
267
|
+
i0.ɵɵlistener("change", function TestingFeedbackComponent_div_73_Template_select_change_8_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onSortChange()); });
|
|
268
|
+
i0.ɵɵelementStart(9, "option", 61);
|
|
269
|
+
i0.ɵɵtext(10, "Date");
|
|
270
|
+
i0.ɵɵelementEnd();
|
|
271
|
+
i0.ɵɵelementStart(11, "option", 62);
|
|
272
|
+
i0.ɵɵtext(12, "Priority");
|
|
273
|
+
i0.ɵɵelementEnd();
|
|
274
|
+
i0.ɵɵelementStart(13, "option", 63);
|
|
275
|
+
i0.ɵɵtext(14, "Test Name");
|
|
276
|
+
i0.ɵɵelementEnd()()()();
|
|
277
|
+
i0.ɵɵtemplate(15, TestingFeedbackComponent_div_73_div_15_Template, 4, 2, "div", 64);
|
|
278
|
+
i0.ɵɵpipe(16, "async");
|
|
279
|
+
i0.ɵɵelementEnd();
|
|
280
|
+
} if (rf & 2) {
|
|
281
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
282
|
+
i0.ɵɵadvance(8);
|
|
283
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.sortBy);
|
|
284
|
+
i0.ɵɵadvance(7);
|
|
285
|
+
i0.ɵɵproperty("ngIf", i0.ɵɵpipeBind1(16, 2, ctx_r2.filteredPending$));
|
|
286
|
+
} }
|
|
287
|
+
function TestingFeedbackComponent_div_74_div_15_ng_container_1_div_1_i_15_Template(rf, ctx) { if (rf & 1) {
|
|
288
|
+
i0.ɵɵelement(0, "i", 102);
|
|
289
|
+
} if (rf & 2) {
|
|
290
|
+
const s_r17 = ctx.$implicit;
|
|
291
|
+
const item_r18 = i0.ɵɵnextContext().$implicit;
|
|
292
|
+
i0.ɵɵclassProp("filled", s_r17 <= item_r18.rating);
|
|
293
|
+
} }
|
|
294
|
+
function TestingFeedbackComponent_div_74_div_15_ng_container_1_div_1_div_24_Template(rf, ctx) { if (rf & 1) {
|
|
295
|
+
i0.ɵɵelementStart(0, "div", 124)(1, "p");
|
|
296
|
+
i0.ɵɵtext(2);
|
|
297
|
+
i0.ɵɵelementEnd()();
|
|
298
|
+
} if (rf & 2) {
|
|
299
|
+
const item_r18 = i0.ɵɵnextContext().$implicit;
|
|
300
|
+
i0.ɵɵadvance(2);
|
|
301
|
+
i0.ɵɵtextInterpolate(item_r18.comments);
|
|
302
|
+
} }
|
|
303
|
+
function TestingFeedbackComponent_div_74_div_15_ng_container_1_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
304
|
+
const _r16 = i0.ɵɵgetCurrentView();
|
|
305
|
+
i0.ɵɵelementStart(0, "div", 108)(1, "div", 109)(2, "div", 110)(3, "div", 111);
|
|
306
|
+
i0.ɵɵtext(4);
|
|
307
|
+
i0.ɵɵelementEnd();
|
|
308
|
+
i0.ɵɵelementStart(5, "div", 112)(6, "span", 113);
|
|
309
|
+
i0.ɵɵelement(7, "i", 114);
|
|
310
|
+
i0.ɵɵtext(8);
|
|
311
|
+
i0.ɵɵelementEnd();
|
|
312
|
+
i0.ɵɵelementStart(9, "span", 73);
|
|
313
|
+
i0.ɵɵelement(10, "i", 115);
|
|
314
|
+
i0.ɵɵtext(11);
|
|
315
|
+
i0.ɵɵpipe(12, "date");
|
|
316
|
+
i0.ɵɵelementEnd()()();
|
|
317
|
+
i0.ɵɵelementStart(13, "div", 116)(14, "div", 117);
|
|
318
|
+
i0.ɵɵtemplate(15, TestingFeedbackComponent_div_74_div_15_ng_container_1_div_1_i_15_Template, 1, 2, "i", 118);
|
|
319
|
+
i0.ɵɵelementEnd();
|
|
320
|
+
i0.ɵɵelementStart(16, "span", 119);
|
|
321
|
+
i0.ɵɵtext(17);
|
|
322
|
+
i0.ɵɵelementEnd()();
|
|
323
|
+
i0.ɵɵelementStart(18, "div", 120)(19, "span", 121);
|
|
324
|
+
i0.ɵɵelement(20, "i", 79);
|
|
325
|
+
i0.ɵɵtext(21);
|
|
326
|
+
i0.ɵɵelementEnd()();
|
|
327
|
+
i0.ɵɵelementStart(22, "button", 122);
|
|
328
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_div_74_div_15_ng_container_1_div_1_Template_button_click_22_listener() { const item_r18 = i0.ɵɵrestoreView(_r16).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.viewTestRun(item_r18.testRunID)); });
|
|
329
|
+
i0.ɵɵelement(23, "i", 100);
|
|
330
|
+
i0.ɵɵelementEnd()();
|
|
331
|
+
i0.ɵɵtemplate(24, TestingFeedbackComponent_div_74_div_15_ng_container_1_div_1_div_24_Template, 3, 1, "div", 123);
|
|
332
|
+
i0.ɵɵelementEnd();
|
|
333
|
+
} if (rf & 2) {
|
|
334
|
+
const item_r18 = ctx.$implicit;
|
|
335
|
+
i0.ɵɵadvance(4);
|
|
336
|
+
i0.ɵɵtextInterpolate(item_r18.testName);
|
|
337
|
+
i0.ɵɵadvance(4);
|
|
338
|
+
i0.ɵɵtextInterpolate1(" ", item_r18.reviewerName, " ");
|
|
339
|
+
i0.ɵɵadvance(3);
|
|
340
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind2(12, 15, item_r18.reviewedAt, "short"), " ");
|
|
341
|
+
i0.ɵɵadvance(4);
|
|
342
|
+
i0.ɵɵproperty("ngForOf", i0.ɵɵpureFunction0(18, _c0));
|
|
343
|
+
i0.ɵɵadvance(2);
|
|
344
|
+
i0.ɵɵtextInterpolate1("", item_r18.rating, "/10");
|
|
345
|
+
i0.ɵɵadvance(2);
|
|
346
|
+
i0.ɵɵclassProp("correct", item_r18.isCorrect)("incorrect", !item_r18.isCorrect);
|
|
347
|
+
i0.ɵɵadvance();
|
|
348
|
+
i0.ɵɵclassProp("fa-check", item_r18.isCorrect)("fa-times", !item_r18.isCorrect);
|
|
349
|
+
i0.ɵɵadvance();
|
|
350
|
+
i0.ɵɵtextInterpolate1(" ", item_r18.isCorrect ? "Correct" : "Incorrect", " ");
|
|
351
|
+
i0.ɵɵadvance(3);
|
|
352
|
+
i0.ɵɵproperty("ngIf", item_r18.comments);
|
|
353
|
+
} }
|
|
354
|
+
function TestingFeedbackComponent_div_74_div_15_ng_container_1_Template(rf, ctx) { if (rf & 1) {
|
|
355
|
+
i0.ɵɵelementContainerStart(0);
|
|
356
|
+
i0.ɵɵtemplate(1, TestingFeedbackComponent_div_74_div_15_ng_container_1_div_1_Template, 25, 19, "div", 107);
|
|
357
|
+
i0.ɵɵelementContainerEnd();
|
|
358
|
+
} if (rf & 2) {
|
|
359
|
+
const items_r19 = i0.ɵɵnextContext().ngIf;
|
|
360
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
361
|
+
i0.ɵɵadvance();
|
|
362
|
+
i0.ɵɵproperty("ngForOf", items_r19)("ngForTrackBy", ctx_r2.trackByReviewedId);
|
|
363
|
+
} }
|
|
364
|
+
function TestingFeedbackComponent_div_74_div_15_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
365
|
+
i0.ɵɵelementStart(0, "div", 125);
|
|
366
|
+
i0.ɵɵelement(1, "i", 126);
|
|
367
|
+
i0.ɵɵelementStart(2, "h3");
|
|
368
|
+
i0.ɵɵtext(3, "No Reviews Yet");
|
|
369
|
+
i0.ɵɵelementEnd();
|
|
370
|
+
i0.ɵɵelementStart(4, "p");
|
|
371
|
+
i0.ɵɵtext(5, "No feedback has been submitted yet. Start by reviewing pending tests.");
|
|
372
|
+
i0.ɵɵelementEnd()();
|
|
373
|
+
} }
|
|
374
|
+
function TestingFeedbackComponent_div_74_div_15_Template(rf, ctx) { if (rf & 1) {
|
|
375
|
+
i0.ɵɵelementStart(0, "div", 65);
|
|
376
|
+
i0.ɵɵtemplate(1, TestingFeedbackComponent_div_74_div_15_ng_container_1_Template, 2, 2, "ng-container", 66)(2, TestingFeedbackComponent_div_74_div_15_ng_template_2_Template, 6, 0, "ng-template", null, 1, i0.ɵɵtemplateRefExtractor);
|
|
377
|
+
i0.ɵɵelementEnd();
|
|
378
|
+
} if (rf & 2) {
|
|
379
|
+
const items_r19 = ctx.ngIf;
|
|
380
|
+
const emptyReviewed_r20 = i0.ɵɵreference(3);
|
|
381
|
+
i0.ɵɵadvance();
|
|
382
|
+
i0.ɵɵproperty("ngIf", items_r19.length > 0)("ngIfElse", emptyReviewed_r20);
|
|
383
|
+
} }
|
|
384
|
+
function TestingFeedbackComponent_div_74_Template(rf, ctx) { if (rf & 1) {
|
|
385
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
386
|
+
i0.ɵɵelementStart(0, "div", 57)(1, "div", 58)(2, "h3");
|
|
387
|
+
i0.ɵɵelement(3, "i", 105);
|
|
388
|
+
i0.ɵɵtext(4, " Reviewed Feedback History ");
|
|
389
|
+
i0.ɵɵelementEnd();
|
|
390
|
+
i0.ɵɵelementStart(5, "div", 60)(6, "label");
|
|
391
|
+
i0.ɵɵtext(7, "Sort by:");
|
|
392
|
+
i0.ɵɵelementEnd();
|
|
393
|
+
i0.ɵɵelementStart(8, "select", 28);
|
|
394
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TestingFeedbackComponent_div_74_Template_select_ngModelChange_8_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.reviewedSortBy, $event) || (ctx_r2.reviewedSortBy = $event); return i0.ɵɵresetView($event); });
|
|
395
|
+
i0.ɵɵlistener("change", function TestingFeedbackComponent_div_74_Template_select_change_8_listener() { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onReviewedSortChange()); });
|
|
396
|
+
i0.ɵɵelementStart(9, "option", 61);
|
|
397
|
+
i0.ɵɵtext(10, "Review Date");
|
|
398
|
+
i0.ɵɵelementEnd();
|
|
399
|
+
i0.ɵɵelementStart(11, "option", 106);
|
|
400
|
+
i0.ɵɵtext(12, "Rating");
|
|
401
|
+
i0.ɵɵelementEnd();
|
|
402
|
+
i0.ɵɵelementStart(13, "option", 63);
|
|
403
|
+
i0.ɵɵtext(14, "Test Name");
|
|
404
|
+
i0.ɵɵelementEnd()()()();
|
|
405
|
+
i0.ɵɵtemplate(15, TestingFeedbackComponent_div_74_div_15_Template, 4, 2, "div", 64);
|
|
406
|
+
i0.ɵɵpipe(16, "async");
|
|
407
|
+
i0.ɵɵelementEnd();
|
|
408
|
+
} if (rf & 2) {
|
|
409
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
410
|
+
i0.ɵɵadvance(8);
|
|
411
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.reviewedSortBy);
|
|
412
|
+
i0.ɵɵadvance(7);
|
|
413
|
+
i0.ɵɵproperty("ngIf", i0.ɵɵpipeBind1(16, 2, ctx_r2.filteredReviewed$));
|
|
414
|
+
} }
|
|
415
|
+
function TestingFeedbackComponent_div_75_div_5_ng_container_1_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
416
|
+
const _r21 = i0.ɵɵgetCurrentView();
|
|
417
|
+
i0.ɵɵelementStart(0, "div", 130);
|
|
418
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_div_75_div_5_ng_container_1_div_1_Template_div_click_0_listener() { const suite_r22 = i0.ɵɵrestoreView(_r21).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.selectSuite(suite_r22.suiteId)); });
|
|
419
|
+
i0.ɵɵelementStart(1, "div", 131)(2, "div", 132);
|
|
420
|
+
i0.ɵɵelement(3, "i", 22);
|
|
421
|
+
i0.ɵɵelementEnd();
|
|
422
|
+
i0.ɵɵelementStart(4, "div", 133)(5, "h4");
|
|
423
|
+
i0.ɵɵtext(6);
|
|
424
|
+
i0.ɵɵelementEnd();
|
|
425
|
+
i0.ɵɵelementStart(7, "div", 134)(8, "span");
|
|
426
|
+
i0.ɵɵtext(9);
|
|
427
|
+
i0.ɵɵelementEnd()()()();
|
|
428
|
+
i0.ɵɵelementStart(10, "div", 135)(11, "div", 136)(12, "div", 137);
|
|
429
|
+
i0.ɵɵtext(13);
|
|
430
|
+
i0.ɵɵelementEnd();
|
|
431
|
+
i0.ɵɵelementStart(14, "div", 43);
|
|
432
|
+
i0.ɵɵtext(15, "Pending");
|
|
433
|
+
i0.ɵɵelementEnd()();
|
|
434
|
+
i0.ɵɵelementStart(16, "div", 136)(17, "div", 138);
|
|
435
|
+
i0.ɵɵtext(18);
|
|
436
|
+
i0.ɵɵelementEnd();
|
|
437
|
+
i0.ɵɵelementStart(19, "div", 43);
|
|
438
|
+
i0.ɵɵtext(20, "Reviewed");
|
|
439
|
+
i0.ɵɵelementEnd()();
|
|
440
|
+
i0.ɵɵelementStart(21, "div", 136)(22, "div", 44);
|
|
441
|
+
i0.ɵɵtext(23);
|
|
442
|
+
i0.ɵɵpipe(24, "number");
|
|
443
|
+
i0.ɵɵelementEnd();
|
|
444
|
+
i0.ɵɵelementStart(25, "div", 43);
|
|
445
|
+
i0.ɵɵtext(26, "Avg Rating");
|
|
446
|
+
i0.ɵɵelementEnd()();
|
|
447
|
+
i0.ɵɵelementStart(27, "div", 136)(28, "div", 44);
|
|
448
|
+
i0.ɵɵtext(29);
|
|
449
|
+
i0.ɵɵpipe(30, "number");
|
|
450
|
+
i0.ɵɵelementEnd();
|
|
451
|
+
i0.ɵɵelementStart(31, "div", 43);
|
|
452
|
+
i0.ɵɵtext(32, "Agreement");
|
|
453
|
+
i0.ɵɵelementEnd()();
|
|
454
|
+
i0.ɵɵelementStart(33, "div", 136)(34, "div", 44);
|
|
455
|
+
i0.ɵɵtext(35);
|
|
456
|
+
i0.ɵɵpipe(36, "number");
|
|
457
|
+
i0.ɵɵelementEnd();
|
|
458
|
+
i0.ɵɵelementStart(37, "div", 43);
|
|
459
|
+
i0.ɵɵtext(38, "Pass Rate");
|
|
460
|
+
i0.ɵɵelementEnd()()();
|
|
461
|
+
i0.ɵɵelement(39, "i", 139);
|
|
462
|
+
i0.ɵɵelementEnd();
|
|
463
|
+
} if (rf & 2) {
|
|
464
|
+
const suite_r22 = ctx.$implicit;
|
|
465
|
+
i0.ɵɵadvance(6);
|
|
466
|
+
i0.ɵɵtextInterpolate(suite_r22.suiteName);
|
|
467
|
+
i0.ɵɵadvance(3);
|
|
468
|
+
i0.ɵɵtextInterpolate1("", suite_r22.totalRuns, " test runs");
|
|
469
|
+
i0.ɵɵadvance(4);
|
|
470
|
+
i0.ɵɵtextInterpolate(suite_r22.pendingCount);
|
|
471
|
+
i0.ɵɵadvance(5);
|
|
472
|
+
i0.ɵɵtextInterpolate(suite_r22.reviewedCount);
|
|
473
|
+
i0.ɵɵadvance(5);
|
|
474
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(24, 15, suite_r22.avgRating, "1.1-1"));
|
|
475
|
+
i0.ɵɵadvance(5);
|
|
476
|
+
i0.ɵɵclassProp("good", suite_r22.agreementRate >= 70)("bad", suite_r22.agreementRate < 50);
|
|
477
|
+
i0.ɵɵadvance();
|
|
478
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind2(30, 18, suite_r22.agreementRate, "1.0-0"), "% ");
|
|
479
|
+
i0.ɵɵadvance(5);
|
|
480
|
+
i0.ɵɵclassProp("good", suite_r22.passRate >= 80)("bad", suite_r22.passRate < 50);
|
|
481
|
+
i0.ɵɵadvance();
|
|
482
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind2(36, 21, suite_r22.passRate, "1.0-0"), "% ");
|
|
483
|
+
} }
|
|
484
|
+
function TestingFeedbackComponent_div_75_div_5_ng_container_1_Template(rf, ctx) { if (rf & 1) {
|
|
485
|
+
i0.ɵɵelementContainerStart(0);
|
|
486
|
+
i0.ɵɵtemplate(1, TestingFeedbackComponent_div_75_div_5_ng_container_1_div_1_Template, 40, 24, "div", 129);
|
|
487
|
+
i0.ɵɵelementContainerEnd();
|
|
488
|
+
} if (rf & 2) {
|
|
489
|
+
const suites_r23 = i0.ɵɵnextContext().ngIf;
|
|
490
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
491
|
+
i0.ɵɵadvance();
|
|
492
|
+
i0.ɵɵproperty("ngForOf", suites_r23)("ngForTrackBy", ctx_r2.trackBySuiteId);
|
|
493
|
+
} }
|
|
494
|
+
function TestingFeedbackComponent_div_75_div_5_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
495
|
+
i0.ɵɵelementStart(0, "div", 125);
|
|
496
|
+
i0.ɵɵelement(1, "i", 22);
|
|
497
|
+
i0.ɵɵelementStart(2, "h3");
|
|
498
|
+
i0.ɵɵtext(3, "No Test Suites");
|
|
499
|
+
i0.ɵɵelementEnd();
|
|
500
|
+
i0.ɵɵelementStart(4, "p");
|
|
501
|
+
i0.ɵɵtext(5, "No test suites have been created yet.");
|
|
502
|
+
i0.ɵɵelementEnd()();
|
|
503
|
+
} }
|
|
504
|
+
function TestingFeedbackComponent_div_75_div_5_Template(rf, ctx) { if (rf & 1) {
|
|
505
|
+
i0.ɵɵelementStart(0, "div", 128);
|
|
506
|
+
i0.ɵɵtemplate(1, TestingFeedbackComponent_div_75_div_5_ng_container_1_Template, 2, 2, "ng-container", 66)(2, TestingFeedbackComponent_div_75_div_5_ng_template_2_Template, 6, 0, "ng-template", null, 2, i0.ɵɵtemplateRefExtractor);
|
|
507
|
+
i0.ɵɵelementEnd();
|
|
508
|
+
} if (rf & 2) {
|
|
509
|
+
const suites_r23 = ctx.ngIf;
|
|
510
|
+
const emptySuites_r24 = i0.ɵɵreference(3);
|
|
511
|
+
i0.ɵɵadvance();
|
|
512
|
+
i0.ɵɵproperty("ngIf", suites_r23.length > 0)("ngIfElse", emptySuites_r24);
|
|
513
|
+
} }
|
|
514
|
+
function TestingFeedbackComponent_div_75_Template(rf, ctx) { if (rf & 1) {
|
|
515
|
+
i0.ɵɵelementStart(0, "div", 57)(1, "div", 58)(2, "h3");
|
|
516
|
+
i0.ɵɵelement(3, "i", 22);
|
|
517
|
+
i0.ɵɵtext(4, " Feedback by Test Suite ");
|
|
518
|
+
i0.ɵɵelementEnd()();
|
|
519
|
+
i0.ɵɵtemplate(5, TestingFeedbackComponent_div_75_div_5_Template, 4, 2, "div", 127);
|
|
520
|
+
i0.ɵɵpipe(6, "async");
|
|
521
|
+
i0.ɵɵelementEnd();
|
|
522
|
+
} if (rf & 2) {
|
|
523
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
524
|
+
i0.ɵɵadvance(5);
|
|
525
|
+
i0.ɵɵproperty("ngIf", i0.ɵɵpipeBind1(6, 1, ctx_r2.suiteAggregations$));
|
|
526
|
+
} }
|
|
183
527
|
export class TestingFeedbackComponent {
|
|
184
528
|
instrumentationService;
|
|
185
529
|
cdr;
|
|
186
530
|
initialState;
|
|
187
531
|
stateChange = new EventEmitter();
|
|
188
532
|
destroy$ = new Subject();
|
|
533
|
+
filterTrigger$ = new BehaviorSubject(undefined);
|
|
534
|
+
metadata = new Metadata();
|
|
535
|
+
viewMode = 'pending';
|
|
536
|
+
isRefreshing = false;
|
|
537
|
+
isSubmitting = false;
|
|
538
|
+
expandedItem = null;
|
|
189
539
|
filters = {
|
|
190
|
-
status: '
|
|
540
|
+
status: 'all',
|
|
191
541
|
reason: 'all',
|
|
542
|
+
suiteId: null,
|
|
192
543
|
searchText: ''
|
|
193
544
|
};
|
|
194
|
-
sortBy = '
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
filteredFeedback$;
|
|
545
|
+
sortBy = 'date';
|
|
546
|
+
reviewedSortBy = 'date';
|
|
547
|
+
// Observables
|
|
198
548
|
pendingCount$;
|
|
199
|
-
discrepancyCount$;
|
|
200
549
|
reviewedCount$;
|
|
550
|
+
suiteCount$;
|
|
201
551
|
accuracyRate$;
|
|
202
552
|
totalFeedback$;
|
|
203
553
|
avgRating$;
|
|
204
554
|
agreementRate$;
|
|
205
|
-
|
|
555
|
+
discrepancyCount$;
|
|
556
|
+
filteredPending$;
|
|
557
|
+
filteredReviewed$;
|
|
558
|
+
suiteAggregations$;
|
|
559
|
+
testSuites$;
|
|
560
|
+
// Local data cache for filtering
|
|
561
|
+
pendingData = [];
|
|
562
|
+
reviewedData = [];
|
|
206
563
|
constructor(instrumentationService, cdr) {
|
|
207
564
|
this.instrumentationService = instrumentationService;
|
|
208
565
|
this.cdr = cdr;
|
|
209
566
|
}
|
|
210
567
|
ngOnInit() {
|
|
211
|
-
this.setupObservables();
|
|
212
568
|
if (this.initialState) {
|
|
213
|
-
|
|
214
|
-
|
|
569
|
+
if (this.initialState.filters) {
|
|
570
|
+
this.filters = { ...this.filters, ...this.initialState.filters };
|
|
571
|
+
}
|
|
572
|
+
if (this.initialState.viewMode) {
|
|
573
|
+
this.viewMode = this.initialState.viewMode;
|
|
574
|
+
}
|
|
575
|
+
if (this.initialState.sortBy) {
|
|
576
|
+
this.sortBy = this.initialState.sortBy;
|
|
577
|
+
}
|
|
215
578
|
}
|
|
579
|
+
this.setupObservables();
|
|
580
|
+
this.loadTestSuites();
|
|
216
581
|
}
|
|
217
582
|
ngOnDestroy() {
|
|
218
583
|
this.destroy$.next();
|
|
219
584
|
this.destroy$.complete();
|
|
220
585
|
}
|
|
221
586
|
setupObservables() {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
this.
|
|
229
|
-
this.
|
|
230
|
-
this.discrepancyCount$ = this.pendingFeedback$.pipe(map(
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
587
|
+
// Stats from service
|
|
588
|
+
const feedbackStats$ = this.instrumentationService.feedbackStats$.pipe(takeUntil(this.destroy$), shareReplay(1));
|
|
589
|
+
this.pendingCount$ = this.instrumentationService.pendingFeedback$.pipe(map(items => items.length), takeUntil(this.destroy$));
|
|
590
|
+
this.reviewedCount$ = feedbackStats$.pipe(map(stats => stats.reviewedCount));
|
|
591
|
+
this.accuracyRate$ = feedbackStats$.pipe(map(stats => stats.accuracyRate));
|
|
592
|
+
this.totalFeedback$ = feedbackStats$.pipe(map(stats => stats.totalFeedback));
|
|
593
|
+
this.avgRating$ = feedbackStats$.pipe(map(stats => stats.avgRating));
|
|
594
|
+
this.agreementRate$ = feedbackStats$.pipe(map(stats => stats.agreementRate));
|
|
595
|
+
this.discrepancyCount$ = this.instrumentationService.pendingFeedback$.pipe(map(items => items.filter(f => f.reason === 'high-score-failed' || f.reason === 'low-score-passed').length), takeUntil(this.destroy$));
|
|
596
|
+
// Filtered pending items
|
|
597
|
+
this.filteredPending$ = combineLatest([
|
|
598
|
+
this.instrumentationService.pendingFeedback$,
|
|
599
|
+
this.filterTrigger$
|
|
600
|
+
]).pipe(map(([items]) => {
|
|
601
|
+
const enhanced = items.map(f => ({
|
|
602
|
+
...f,
|
|
603
|
+
feedbackRating: 5,
|
|
604
|
+
feedbackIsCorrect: true,
|
|
605
|
+
feedbackComments: ''
|
|
606
|
+
}));
|
|
607
|
+
this.pendingData = enhanced;
|
|
608
|
+
return this.filterAndSortPending(enhanced);
|
|
609
|
+
}), takeUntil(this.destroy$));
|
|
610
|
+
// Load and filter reviewed feedback
|
|
611
|
+
this.filteredReviewed$ = combineLatest([
|
|
612
|
+
this.loadReviewedFeedback(),
|
|
613
|
+
this.filterTrigger$
|
|
614
|
+
]).pipe(map(([items]) => {
|
|
615
|
+
this.reviewedData = items;
|
|
616
|
+
return this.filterAndSortReviewed(items);
|
|
617
|
+
}), takeUntil(this.destroy$));
|
|
618
|
+
// Suite aggregations
|
|
619
|
+
this.suiteAggregations$ = this.loadSuiteAggregations().pipe(takeUntil(this.destroy$));
|
|
620
|
+
this.suiteCount$ = this.suiteAggregations$.pipe(map(suites => suites.length));
|
|
239
621
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
622
|
+
async loadTestSuites() {
|
|
623
|
+
const rv = new RunView();
|
|
624
|
+
const result = await rv.RunView({
|
|
625
|
+
EntityName: 'MJ: Test Suites',
|
|
626
|
+
ExtraFilter: "Status = 'Active'",
|
|
627
|
+
OrderBy: 'Name',
|
|
628
|
+
ResultType: 'entity_object'
|
|
629
|
+
});
|
|
630
|
+
this.testSuites$ = new BehaviorSubject(result.Results || []).asObservable();
|
|
631
|
+
this.cdr.markForCheck();
|
|
632
|
+
}
|
|
633
|
+
loadReviewedFeedback() {
|
|
634
|
+
return combineLatest([
|
|
635
|
+
this.instrumentationService.dateRange$,
|
|
636
|
+
this.instrumentationService.isLoading$
|
|
637
|
+
]).pipe(switchMap(([dateRange]) => {
|
|
638
|
+
return new Observable(observer => {
|
|
639
|
+
this.loadReviewedFeedbackAsync(dateRange.start, dateRange.end).then(data => {
|
|
640
|
+
observer.next(data);
|
|
641
|
+
observer.complete();
|
|
642
|
+
}, error => observer.error(error));
|
|
643
|
+
});
|
|
644
|
+
}), shareReplay(1));
|
|
645
|
+
}
|
|
646
|
+
async loadReviewedFeedbackAsync(start, end) {
|
|
647
|
+
const rv = new RunView();
|
|
648
|
+
const result = await rv.RunView({
|
|
649
|
+
EntityName: 'MJ: Test Run Feedbacks',
|
|
650
|
+
ExtraFilter: `__mj_CreatedAt >= '${start.toISOString()}' AND __mj_CreatedAt <= '${end.toISOString()}'`,
|
|
651
|
+
OrderBy: '__mj_CreatedAt DESC',
|
|
652
|
+
MaxRows: 500,
|
|
653
|
+
ResultType: 'entity_object'
|
|
654
|
+
});
|
|
655
|
+
const feedbacks = result.Results || [];
|
|
656
|
+
// Get test run details for each feedback
|
|
657
|
+
if (feedbacks.length === 0)
|
|
658
|
+
return [];
|
|
659
|
+
const testRunIds = feedbacks.map(f => f.TestRunID);
|
|
660
|
+
const testRunResult = await rv.RunView({
|
|
661
|
+
EntityName: 'MJ: Test Runs',
|
|
662
|
+
ExtraFilter: `ID IN ('${testRunIds.join("','")}')`,
|
|
663
|
+
ResultType: 'entity_object'
|
|
664
|
+
});
|
|
665
|
+
const testRunMap = new Map();
|
|
666
|
+
(testRunResult.Results || []).forEach(tr => testRunMap.set(tr.ID, tr));
|
|
667
|
+
return feedbacks.map(f => {
|
|
668
|
+
const testRun = testRunMap.get(f.TestRunID);
|
|
669
|
+
return {
|
|
670
|
+
id: f.ID,
|
|
671
|
+
testRunID: f.TestRunID,
|
|
672
|
+
testName: testRun?.Test || 'Unknown Test',
|
|
673
|
+
rating: f.Rating || 0,
|
|
674
|
+
isCorrect: f.IsCorrect ?? true,
|
|
675
|
+
comments: f.CorrectionSummary || '',
|
|
676
|
+
reviewerName: f.ReviewerUser || 'Unknown',
|
|
677
|
+
reviewedAt: f.__mj_CreatedAt ? new Date(f.__mj_CreatedAt) : new Date(),
|
|
678
|
+
automatedScore: testRun?.Score || 0,
|
|
679
|
+
automatedStatus: testRun?.Status || 'Unknown'
|
|
680
|
+
};
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
loadSuiteAggregations() {
|
|
684
|
+
return combineLatest([
|
|
685
|
+
this.instrumentationService.dateRange$,
|
|
686
|
+
this.instrumentationService.isLoading$
|
|
687
|
+
]).pipe(switchMap(([dateRange]) => {
|
|
688
|
+
return new Observable(observer => {
|
|
689
|
+
this.loadSuiteAggregationsAsync(dateRange.start, dateRange.end).then(data => {
|
|
690
|
+
observer.next(data);
|
|
691
|
+
observer.complete();
|
|
692
|
+
}, error => observer.error(error));
|
|
693
|
+
});
|
|
694
|
+
}), shareReplay(1));
|
|
695
|
+
}
|
|
696
|
+
async loadSuiteAggregationsAsync(start, end) {
|
|
697
|
+
const rv = new RunView();
|
|
698
|
+
// Get all test suites
|
|
699
|
+
const suitesResult = await rv.RunView({
|
|
700
|
+
EntityName: 'MJ: Test Suites',
|
|
701
|
+
ExtraFilter: "Status = 'Active'",
|
|
702
|
+
ResultType: 'entity_object'
|
|
703
|
+
});
|
|
704
|
+
const suites = suitesResult.Results || [];
|
|
705
|
+
if (suites.length === 0)
|
|
706
|
+
return [];
|
|
707
|
+
// Get test runs in date range
|
|
708
|
+
const runsResult = await rv.RunView({
|
|
709
|
+
EntityName: 'MJ: Test Runs',
|
|
710
|
+
ExtraFilter: `StartedAt >= '${start.toISOString()}' AND StartedAt <= '${end.toISOString()}'`,
|
|
711
|
+
ResultType: 'entity_object'
|
|
712
|
+
});
|
|
713
|
+
const runs = runsResult.Results || [];
|
|
714
|
+
// Get feedback in date range
|
|
715
|
+
const feedbackResult = await rv.RunView({
|
|
716
|
+
EntityName: 'MJ: Test Run Feedbacks',
|
|
717
|
+
ExtraFilter: `__mj_CreatedAt >= '${start.toISOString()}'`,
|
|
718
|
+
ResultType: 'entity_object'
|
|
719
|
+
});
|
|
720
|
+
const feedbacks = feedbackResult.Results || [];
|
|
721
|
+
const feedbackMap = new Map();
|
|
722
|
+
feedbacks.forEach(f => feedbackMap.set(f.TestRunID, f));
|
|
723
|
+
// Aggregate by suite (simplified - would need TestSuiteTest join for accuracy)
|
|
724
|
+
const aggregations = suites.map(suite => {
|
|
725
|
+
// Filter runs by test suite (simplified)
|
|
726
|
+
const suiteRuns = runs; // In reality, need to join through TestSuiteTest
|
|
727
|
+
const totalRuns = suiteRuns.length;
|
|
728
|
+
const passedRuns = suiteRuns.filter(r => r.Status === 'Passed').length;
|
|
729
|
+
const reviewedRuns = suiteRuns.filter(r => feedbackMap.has(r.ID));
|
|
730
|
+
const reviewedCount = reviewedRuns.length;
|
|
731
|
+
const pendingCount = totalRuns - reviewedCount;
|
|
732
|
+
const ratings = reviewedRuns
|
|
733
|
+
.map(r => feedbackMap.get(r.ID)?.Rating || 0)
|
|
734
|
+
.filter(r => r > 0);
|
|
735
|
+
const avgRating = ratings.length > 0
|
|
736
|
+
? ratings.reduce((sum, r) => sum + r, 0) / ratings.length
|
|
737
|
+
: 0;
|
|
738
|
+
const correctCount = reviewedRuns
|
|
739
|
+
.filter(r => feedbackMap.get(r.ID)?.IsCorrect === true).length;
|
|
740
|
+
const agreementRate = reviewedCount > 0
|
|
741
|
+
? (correctCount / reviewedCount) * 100
|
|
742
|
+
: 0;
|
|
743
|
+
const passRate = totalRuns > 0 ? (passedRuns / totalRuns) * 100 : 0;
|
|
744
|
+
return {
|
|
745
|
+
suiteId: suite.ID,
|
|
746
|
+
suiteName: suite.Name,
|
|
747
|
+
totalRuns,
|
|
748
|
+
reviewedCount,
|
|
749
|
+
pendingCount,
|
|
750
|
+
avgRating,
|
|
751
|
+
agreementRate,
|
|
752
|
+
passRate
|
|
753
|
+
};
|
|
754
|
+
});
|
|
755
|
+
return aggregations.sort((a, b) => b.pendingCount - a.pendingCount);
|
|
756
|
+
}
|
|
757
|
+
filterAndSortPending(items) {
|
|
758
|
+
let filtered = [...items];
|
|
759
|
+
// Filter by reason
|
|
247
760
|
if (this.filters.reason !== 'all') {
|
|
248
761
|
filtered = filtered.filter(f => f.reason === this.filters.reason);
|
|
249
762
|
}
|
|
763
|
+
// Filter by search text
|
|
250
764
|
if (this.filters.searchText) {
|
|
251
765
|
const searchLower = this.filters.searchText.toLowerCase();
|
|
252
766
|
filtered = filtered.filter(f => f.testName.toLowerCase().includes(searchLower));
|
|
253
767
|
}
|
|
768
|
+
// Sort
|
|
254
769
|
filtered.sort((a, b) => {
|
|
255
770
|
if (this.sortBy === 'date') {
|
|
256
771
|
return b.runDateTime.getTime() - a.runDateTime.getTime();
|
|
257
772
|
}
|
|
258
773
|
else if (this.sortBy === 'priority') {
|
|
259
774
|
const priorityOrder = { 'high-score-failed': 1, 'low-score-passed': 2, 'no-feedback': 3 };
|
|
260
|
-
return (priorityOrder[a.reason] || 99) -
|
|
261
|
-
(priorityOrder[b.reason] || 99);
|
|
775
|
+
return (priorityOrder[a.reason] || 99) - (priorityOrder[b.reason] || 99);
|
|
262
776
|
}
|
|
263
777
|
else {
|
|
264
778
|
return a.testName.localeCompare(b.testName);
|
|
@@ -266,280 +780,399 @@ export class TestingFeedbackComponent {
|
|
|
266
780
|
});
|
|
267
781
|
return filtered;
|
|
268
782
|
}
|
|
269
|
-
|
|
783
|
+
filterAndSortReviewed(items) {
|
|
784
|
+
let filtered = [...items];
|
|
785
|
+
// Filter by search text
|
|
786
|
+
if (this.filters.searchText) {
|
|
787
|
+
const searchLower = this.filters.searchText.toLowerCase();
|
|
788
|
+
filtered = filtered.filter(f => f.testName.toLowerCase().includes(searchLower) ||
|
|
789
|
+
f.reviewerName.toLowerCase().includes(searchLower));
|
|
790
|
+
}
|
|
791
|
+
// Sort
|
|
792
|
+
filtered.sort((a, b) => {
|
|
793
|
+
if (this.reviewedSortBy === 'date') {
|
|
794
|
+
return b.reviewedAt.getTime() - a.reviewedAt.getTime();
|
|
795
|
+
}
|
|
796
|
+
else if (this.reviewedSortBy === 'rating') {
|
|
797
|
+
return b.rating - a.rating;
|
|
798
|
+
}
|
|
799
|
+
else {
|
|
800
|
+
return a.testName.localeCompare(b.testName);
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
return filtered;
|
|
804
|
+
}
|
|
805
|
+
// Event handlers
|
|
806
|
+
setViewMode(mode) {
|
|
807
|
+
this.viewMode = mode;
|
|
808
|
+
this.expandedItem = null;
|
|
270
809
|
this.emitStateChange();
|
|
271
810
|
this.cdr.markForCheck();
|
|
272
811
|
}
|
|
273
|
-
|
|
274
|
-
this.
|
|
275
|
-
this.
|
|
812
|
+
onViewModeChange() {
|
|
813
|
+
this.expandedItem = null;
|
|
814
|
+
this.emitStateChange();
|
|
815
|
+
this.cdr.markForCheck();
|
|
816
|
+
}
|
|
817
|
+
onFilterChange() {
|
|
818
|
+
this.filterTrigger$.next();
|
|
819
|
+
this.emitStateChange();
|
|
820
|
+
this.cdr.markForCheck();
|
|
276
821
|
}
|
|
277
822
|
onSortChange() {
|
|
823
|
+
this.filterTrigger$.next();
|
|
278
824
|
this.emitStateChange();
|
|
279
825
|
this.cdr.markForCheck();
|
|
280
826
|
}
|
|
827
|
+
onReviewedSortChange() {
|
|
828
|
+
this.filterTrigger$.next();
|
|
829
|
+
this.cdr.markForCheck();
|
|
830
|
+
}
|
|
831
|
+
clearSearch() {
|
|
832
|
+
this.filters.searchText = '';
|
|
833
|
+
this.onFilterChange();
|
|
834
|
+
}
|
|
281
835
|
toggleExpanded(testRunID) {
|
|
282
836
|
this.expandedItem = this.expandedItem === testRunID ? null : testRunID;
|
|
283
837
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
this.expandedItem = null;
|
|
287
|
-
this.cdr.markForCheck();
|
|
838
|
+
setRating(item, rating) {
|
|
839
|
+
item.feedbackRating = rating;
|
|
288
840
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
841
|
+
setCorrectness(item, isCorrect) {
|
|
842
|
+
item.feedbackIsCorrect = isCorrect;
|
|
843
|
+
}
|
|
844
|
+
async submitFeedback(item) {
|
|
845
|
+
if (this.isSubmitting)
|
|
846
|
+
return;
|
|
847
|
+
this.isSubmitting = true;
|
|
292
848
|
this.cdr.markForCheck();
|
|
849
|
+
try {
|
|
850
|
+
const success = await this.instrumentationService.submitFeedback(item.testRunID, item.feedbackRating, item.feedbackIsCorrect, item.feedbackComments);
|
|
851
|
+
if (success) {
|
|
852
|
+
this.expandedItem = null;
|
|
853
|
+
// Refresh will happen via the service
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
console.error('Failed to submit feedback');
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
catch (error) {
|
|
860
|
+
console.error('Error submitting feedback:', error);
|
|
861
|
+
}
|
|
862
|
+
finally {
|
|
863
|
+
this.isSubmitting = false;
|
|
864
|
+
this.cdr.markForCheck();
|
|
865
|
+
}
|
|
293
866
|
}
|
|
294
867
|
viewFullDetails(item) {
|
|
295
868
|
SharedService.Instance.OpenEntityRecord('MJ: Test Runs', CompositeKey.FromID(item.testRunID));
|
|
296
869
|
}
|
|
870
|
+
viewTestRun(testRunId) {
|
|
871
|
+
SharedService.Instance.OpenEntityRecord('MJ: Test Runs', CompositeKey.FromID(testRunId));
|
|
872
|
+
}
|
|
873
|
+
selectSuite(suiteId) {
|
|
874
|
+
this.filters.suiteId = suiteId;
|
|
875
|
+
this.viewMode = 'pending';
|
|
876
|
+
this.onFilterChange();
|
|
877
|
+
}
|
|
297
878
|
refresh() {
|
|
879
|
+
this.isRefreshing = true;
|
|
880
|
+
this.cdr.markForCheck();
|
|
298
881
|
this.instrumentationService.refresh();
|
|
882
|
+
setTimeout(() => {
|
|
883
|
+
this.isRefreshing = false;
|
|
884
|
+
this.cdr.markForCheck();
|
|
885
|
+
}, 1500);
|
|
299
886
|
}
|
|
300
887
|
formatReason(reason) {
|
|
301
888
|
switch (reason) {
|
|
302
889
|
case 'no-feedback': return 'No Feedback';
|
|
303
|
-
case 'high-score-failed': return 'High Score
|
|
304
|
-
case 'low-score-passed': return 'Low Score
|
|
890
|
+
case 'high-score-failed': return 'High Score Failed';
|
|
891
|
+
case 'low-score-passed': return 'Low Score Passed';
|
|
305
892
|
default: return reason;
|
|
306
893
|
}
|
|
307
894
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
return
|
|
895
|
+
// Track by functions
|
|
896
|
+
trackByTestRunId(index, item) {
|
|
897
|
+
return item.testRunID;
|
|
898
|
+
}
|
|
899
|
+
trackByReviewedId(index, item) {
|
|
900
|
+
return item.id;
|
|
901
|
+
}
|
|
902
|
+
trackBySuiteId(index, item) {
|
|
903
|
+
return item.suiteId;
|
|
311
904
|
}
|
|
312
905
|
emitStateChange() {
|
|
313
906
|
this.stateChange.emit({
|
|
314
907
|
filters: this.filters,
|
|
908
|
+
viewMode: this.viewMode,
|
|
315
909
|
sortBy: this.sortBy
|
|
316
910
|
});
|
|
317
911
|
}
|
|
318
912
|
static ɵfac = function TestingFeedbackComponent_Factory(t) { return new (t || TestingFeedbackComponent)(i0.ɵɵdirectiveInject(i1.TestingInstrumentationService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
319
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestingFeedbackComponent, selectors: [["app-testing-feedback"]], inputs: { initialState: "initialState" }, outputs: { stateChange: "stateChange" }, decls:
|
|
320
|
-
i0.ɵɵelementStart(0, "div",
|
|
321
|
-
i0.ɵɵelement(4, "i",
|
|
913
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestingFeedbackComponent, selectors: [["app-testing-feedback"]], inputs: { initialState: "initialState" }, outputs: { stateChange: "stateChange" }, decls: 107, vars: 54, consts: [["emptyPending", ""], ["emptyReviewed", ""], ["emptySuites", ""], [1, "testing-feedback"], [1, "feedback-header"], [1, "header-left"], [1, "fa-solid", "fa-clipboard-check"], ["class", "pending-badge", 4, "ngIf"], [1, "header-actions"], [1, "action-btn", "refresh-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-refresh"], [1, "feedback-summary"], [1, "summary-card", "clickable", 3, "click"], [1, "summary-icon", "pending"], [1, "fa-solid", "fa-hourglass-half"], [1, "summary-content"], [1, "summary-value"], [1, "summary-label"], [1, "fa-solid", "fa-chevron-right", "summary-arrow"], [1, "summary-icon", "reviewed"], [1, "fa-solid", "fa-check-circle"], [1, "summary-icon", "suites"], [1, "fa-solid", "fa-layer-group"], [1, "summary-card"], [1, "summary-icon", "accuracy"], [1, "fa-solid", "fa-bullseye"], [1, "feedback-filters"], [1, "filter-group"], [3, "ngModelChange", "change", "ngModel"], ["value", "pending"], ["value", "reviewed"], ["value", "suites"], ["class", "filter-group", 4, "ngIf"], [1, "filter-group", "search"], [1, "search-input-wrapper"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search tests...", 3, "ngModelChange", "input", "ngModel"], ["class", "clear-btn", 3, "click", 4, "ngIf"], ["class", "feedback-content", 4, "ngIf"], [1, "feedback-stats"], [1, "fa-solid", "fa-chart-pie"], [1, "stats-grid"], [1, "stat-card"], [1, "stat-label"], [1, "stat-value"], [1, "pending-badge"], ["class", "badge-count", 4, "ngIf"], [1, "badge-text"], [1, "badge-count"], ["value", "all"], ["value", "no-feedback"], ["value", "high-score-failed"], ["value", "low-score-passed"], [3, "ngValue"], [3, "ngValue", 4, "ngFor", "ngForOf"], [1, "clear-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "feedback-content"], [1, "content-header"], [1, "fa-solid", "fa-list-check"], [1, "sort-controls"], ["value", "date"], ["value", "priority"], ["value", "test-name"], ["class", "feedback-list", 4, "ngIf"], [1, "feedback-list"], [4, "ngIf", "ngIfElse"], ["class", "feedback-item", 3, "expanded", 4, "ngFor", "ngForOf", "ngForTrackBy"], [1, "feedback-item"], [1, "item-header", 3, "click"], [1, "item-main"], [1, "item-title"], [1, "item-meta"], [1, "meta-date"], [1, "fa-solid", "fa-clock"], [1, "meta-score"], [1, "meta-status"], [1, "item-reason"], [1, "reason-badge"], [1, "fa-solid"], [1, "expand-btn"], ["class", "item-content", 4, "ngIf"], [1, "item-content"], [1, "feedback-form"], [1, "form-section"], [1, "rating-section"], [1, "rating-stars-input"], ["class", "star-btn", 3, "filled", "click", 4, "ngFor", "ngForOf"], [1, "rating-display"], [1, "correctness-section"], [1, "correctness-buttons"], [1, "correctness-btn", "correct", 3, "click"], [1, "fa-solid", "fa-check"], [1, "correctness-btn", "incorrect", 3, "click"], [1, "form-group"], ["rows", "3", "placeholder", "Explain your assessment or provide correction notes...", 1, "comments-textarea", 3, "ngModelChange", "ngModel"], [1, "form-actions"], [1, "submit-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-paper-plane"], [1, "view-btn", 3, "click"], [1, "fa-solid", "fa-external-link"], [1, "star-btn", 3, "click"], [1, "fa-solid", "fa-star"], [1, "empty-state", "success"], [1, "fa-solid", "fa-check-double"], [1, "fa-solid", "fa-history"], ["value", "rating"], ["class", "reviewed-item", 4, "ngFor", "ngForOf", "ngForTrackBy"], [1, "reviewed-item"], [1, "reviewed-header"], [1, "reviewed-main"], [1, "reviewed-title"], [1, "reviewed-meta"], [1, "meta-reviewer"], [1, "fa-solid", "fa-user"], [1, "fa-solid", "fa-calendar"], [1, "reviewed-rating"], [1, "rating-stars"], ["class", "fa-solid fa-star", 3, "filled", 4, "ngFor", "ngForOf"], [1, "rating-text"], [1, "reviewed-verdict"], [1, "verdict-badge"], [1, "view-btn-small", 3, "click"], ["class", "reviewed-comments", 4, "ngIf"], [1, "reviewed-comments"], [1, "empty-state"], [1, "fa-solid", "fa-clipboard"], ["class", "suites-list", 4, "ngIf"], [1, "suites-list"], ["class", "suite-card", 3, "click", 4, "ngFor", "ngForOf", "ngForTrackBy"], [1, "suite-card", 3, "click"], [1, "suite-header"], [1, "suite-icon"], [1, "suite-info"], [1, "suite-meta"], [1, "suite-stats"], [1, "suite-stat"], [1, "stat-value", "pending"], [1, "stat-value", "reviewed"], [1, "fa-solid", "fa-chevron-right", "suite-arrow"]], template: function TestingFeedbackComponent_Template(rf, ctx) { if (rf & 1) {
|
|
914
|
+
i0.ɵɵelementStart(0, "div", 3)(1, "div", 4)(2, "div", 5)(3, "h2");
|
|
915
|
+
i0.ɵɵelement(4, "i", 6);
|
|
322
916
|
i0.ɵɵtext(5, " Human Feedback Review ");
|
|
323
917
|
i0.ɵɵelementEnd();
|
|
324
|
-
i0.ɵɵtemplate(6, TestingFeedbackComponent_div_6_Template,
|
|
918
|
+
i0.ɵɵtemplate(6, TestingFeedbackComponent_div_6_Template, 4, 2, "div", 7);
|
|
325
919
|
i0.ɵɵpipe(7, "async");
|
|
326
920
|
i0.ɵɵelementEnd();
|
|
327
|
-
i0.ɵɵelementStart(8, "div",
|
|
921
|
+
i0.ɵɵelementStart(8, "div", 8)(9, "button", 9);
|
|
328
922
|
i0.ɵɵlistener("click", function TestingFeedbackComponent_Template_button_click_9_listener() { return ctx.refresh(); });
|
|
329
|
-
i0.ɵɵelement(10, "i",
|
|
330
|
-
i0.ɵɵtext(11
|
|
923
|
+
i0.ɵɵelement(10, "i", 10);
|
|
924
|
+
i0.ɵɵtext(11);
|
|
331
925
|
i0.ɵɵelementEnd()()();
|
|
332
|
-
i0.ɵɵelementStart(12, "div",
|
|
333
|
-
i0.ɵɵ
|
|
926
|
+
i0.ɵɵelementStart(12, "div", 11)(13, "div", 12);
|
|
927
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_Template_div_click_13_listener() { return ctx.setViewMode("pending"); });
|
|
928
|
+
i0.ɵɵelementStart(14, "div", 13);
|
|
929
|
+
i0.ɵɵelement(15, "i", 14);
|
|
334
930
|
i0.ɵɵelementEnd();
|
|
335
|
-
i0.ɵɵelementStart(16, "
|
|
336
|
-
i0.ɵɵ
|
|
337
|
-
i0.ɵɵ
|
|
338
|
-
i0.ɵɵelementStart(17, "option", 11);
|
|
339
|
-
i0.ɵɵtext(18, "All");
|
|
931
|
+
i0.ɵɵelementStart(16, "div", 15)(17, "div", 16);
|
|
932
|
+
i0.ɵɵtext(18);
|
|
933
|
+
i0.ɵɵpipe(19, "async");
|
|
340
934
|
i0.ɵɵelementEnd();
|
|
341
|
-
i0.ɵɵelementStart(
|
|
342
|
-
i0.ɵɵtext(
|
|
935
|
+
i0.ɵɵelementStart(20, "div", 17);
|
|
936
|
+
i0.ɵɵtext(21, "Pending Review");
|
|
937
|
+
i0.ɵɵelementEnd()();
|
|
938
|
+
i0.ɵɵelement(22, "i", 18);
|
|
343
939
|
i0.ɵɵelementEnd();
|
|
344
|
-
i0.ɵɵelementStart(
|
|
345
|
-
i0.ɵɵ
|
|
346
|
-
i0.ɵɵ
|
|
347
|
-
i0.ɵɵ
|
|
348
|
-
i0.ɵɵtext(25, "Reason");
|
|
940
|
+
i0.ɵɵelementStart(23, "div", 12);
|
|
941
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_Template_div_click_23_listener() { return ctx.setViewMode("reviewed"); });
|
|
942
|
+
i0.ɵɵelementStart(24, "div", 19);
|
|
943
|
+
i0.ɵɵelement(25, "i", 20);
|
|
349
944
|
i0.ɵɵelementEnd();
|
|
350
|
-
i0.ɵɵelementStart(26, "
|
|
351
|
-
i0.ɵɵ
|
|
352
|
-
i0.ɵɵ
|
|
353
|
-
i0.ɵɵelementStart(27, "option", 11);
|
|
354
|
-
i0.ɵɵtext(28, "All Reasons");
|
|
945
|
+
i0.ɵɵelementStart(26, "div", 15)(27, "div", 16);
|
|
946
|
+
i0.ɵɵtext(28);
|
|
947
|
+
i0.ɵɵpipe(29, "async");
|
|
355
948
|
i0.ɵɵelementEnd();
|
|
356
|
-
i0.ɵɵelementStart(
|
|
357
|
-
i0.ɵɵtext(
|
|
949
|
+
i0.ɵɵelementStart(30, "div", 17);
|
|
950
|
+
i0.ɵɵtext(31, "Reviewed");
|
|
951
|
+
i0.ɵɵelementEnd()();
|
|
952
|
+
i0.ɵɵelement(32, "i", 18);
|
|
358
953
|
i0.ɵɵelementEnd();
|
|
359
|
-
i0.ɵɵelementStart(
|
|
360
|
-
i0.ɵɵ
|
|
954
|
+
i0.ɵɵelementStart(33, "div", 12);
|
|
955
|
+
i0.ɵɵlistener("click", function TestingFeedbackComponent_Template_div_click_33_listener() { return ctx.setViewMode("suites"); });
|
|
956
|
+
i0.ɵɵelementStart(34, "div", 21);
|
|
957
|
+
i0.ɵɵelement(35, "i", 22);
|
|
361
958
|
i0.ɵɵelementEnd();
|
|
362
|
-
i0.ɵɵelementStart(
|
|
363
|
-
i0.ɵɵtext(
|
|
364
|
-
i0.ɵɵ
|
|
365
|
-
i0.ɵɵelementStart(35, "div", 17)(36, "label");
|
|
366
|
-
i0.ɵɵtext(37, "Search");
|
|
959
|
+
i0.ɵɵelementStart(36, "div", 15)(37, "div", 16);
|
|
960
|
+
i0.ɵɵtext(38);
|
|
961
|
+
i0.ɵɵpipe(39, "async");
|
|
367
962
|
i0.ɵɵelementEnd();
|
|
368
|
-
i0.ɵɵelementStart(
|
|
369
|
-
i0.ɵɵ
|
|
370
|
-
i0.ɵɵ
|
|
371
|
-
i0.ɵɵ
|
|
372
|
-
i0.ɵɵlistener("input", function TestingFeedbackComponent_Template_input_input_40_listener() { return ctx.onFilterChange(); });
|
|
963
|
+
i0.ɵɵelementStart(40, "div", 17);
|
|
964
|
+
i0.ɵɵtext(41, "Test Suites");
|
|
965
|
+
i0.ɵɵelementEnd()();
|
|
966
|
+
i0.ɵɵelement(42, "i", 18);
|
|
373
967
|
i0.ɵɵelementEnd();
|
|
374
|
-
i0.ɵɵ
|
|
375
|
-
i0.ɵɵelementEnd()()();
|
|
376
|
-
i0.ɵɵelementStart(42, "div", 22)(43, "div", 23)(44, "div", 24);
|
|
968
|
+
i0.ɵɵelementStart(43, "div", 23)(44, "div", 24);
|
|
377
969
|
i0.ɵɵelement(45, "i", 25);
|
|
378
970
|
i0.ɵɵelementEnd();
|
|
379
|
-
i0.ɵɵelementStart(46, "div",
|
|
971
|
+
i0.ɵɵelementStart(46, "div", 15)(47, "div", 16);
|
|
380
972
|
i0.ɵɵtext(48);
|
|
381
973
|
i0.ɵɵpipe(49, "async");
|
|
974
|
+
i0.ɵɵpipe(50, "number");
|
|
382
975
|
i0.ɵɵelementEnd();
|
|
383
|
-
i0.ɵɵelementStart(
|
|
384
|
-
i0.ɵɵtext(
|
|
385
|
-
i0.ɵɵelementEnd()()();
|
|
386
|
-
i0.ɵɵelementStart(
|
|
387
|
-
i0.ɵɵ
|
|
388
|
-
i0.ɵɵelementEnd();
|
|
389
|
-
i0.ɵɵelementStart(55, "div", 26)(56, "div", 27);
|
|
390
|
-
i0.ɵɵtext(57);
|
|
391
|
-
i0.ɵɵpipe(58, "async");
|
|
976
|
+
i0.ɵɵelementStart(51, "div", 17);
|
|
977
|
+
i0.ɵɵtext(52, "Human-AI Agreement");
|
|
978
|
+
i0.ɵɵelementEnd()()()();
|
|
979
|
+
i0.ɵɵelementStart(53, "div", 26)(54, "div", 27)(55, "label");
|
|
980
|
+
i0.ɵɵtext(56, "View");
|
|
392
981
|
i0.ɵɵelementEnd();
|
|
393
|
-
i0.ɵɵelementStart(
|
|
394
|
-
i0.ɵɵ
|
|
395
|
-
i0.ɵɵ
|
|
396
|
-
i0.ɵɵelementStart(
|
|
397
|
-
i0.ɵɵ
|
|
982
|
+
i0.ɵɵelementStart(57, "select", 28);
|
|
983
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TestingFeedbackComponent_Template_select_ngModelChange_57_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.viewMode, $event) || (ctx.viewMode = $event); return $event; });
|
|
984
|
+
i0.ɵɵlistener("change", function TestingFeedbackComponent_Template_select_change_57_listener() { return ctx.onViewModeChange(); });
|
|
985
|
+
i0.ɵɵelementStart(58, "option", 29);
|
|
986
|
+
i0.ɵɵtext(59, "Pending Reviews");
|
|
398
987
|
i0.ɵɵelementEnd();
|
|
399
|
-
i0.ɵɵelementStart(
|
|
400
|
-
i0.ɵɵtext(
|
|
401
|
-
i0.ɵɵpipe(67, "async");
|
|
988
|
+
i0.ɵɵelementStart(60, "option", 30);
|
|
989
|
+
i0.ɵɵtext(61, "Reviewed Feedback");
|
|
402
990
|
i0.ɵɵelementEnd();
|
|
403
|
-
i0.ɵɵelementStart(
|
|
404
|
-
i0.ɵɵtext(
|
|
991
|
+
i0.ɵɵelementStart(62, "option", 31);
|
|
992
|
+
i0.ɵɵtext(63, "By Test Suite");
|
|
405
993
|
i0.ɵɵelementEnd()()();
|
|
406
|
-
i0.ɵɵ
|
|
407
|
-
i0.ɵɵ
|
|
408
|
-
i0.ɵɵ
|
|
409
|
-
i0.ɵɵelementStart(73, "div", 26)(74, "div", 27);
|
|
410
|
-
i0.ɵɵtext(75);
|
|
411
|
-
i0.ɵɵpipe(76, "async");
|
|
412
|
-
i0.ɵɵpipe(77, "number");
|
|
413
|
-
i0.ɵɵelementEnd();
|
|
414
|
-
i0.ɵɵelementStart(78, "div", 28);
|
|
415
|
-
i0.ɵɵtext(79, "Human-AI Agreement");
|
|
416
|
-
i0.ɵɵelementEnd()()()();
|
|
417
|
-
i0.ɵɵelementStart(80, "div", 35)(81, "div", 36)(82, "h3");
|
|
418
|
-
i0.ɵɵelement(83, "i", 37);
|
|
419
|
-
i0.ɵɵtext(84, " Tests Requiring Review ");
|
|
420
|
-
i0.ɵɵelementEnd();
|
|
421
|
-
i0.ɵɵelementStart(85, "div", 38)(86, "label");
|
|
422
|
-
i0.ɵɵtext(87, "Sort by:");
|
|
994
|
+
i0.ɵɵtemplate(64, TestingFeedbackComponent_div_64_Template, 12, 1, "div", 32)(65, TestingFeedbackComponent_div_65_Template, 8, 5, "div", 32);
|
|
995
|
+
i0.ɵɵelementStart(66, "div", 33)(67, "label");
|
|
996
|
+
i0.ɵɵtext(68, "Search");
|
|
423
997
|
i0.ɵɵelementEnd();
|
|
424
|
-
i0.ɵɵelementStart(
|
|
425
|
-
i0.ɵɵ
|
|
426
|
-
i0.ɵɵ
|
|
427
|
-
i0.ɵɵ
|
|
428
|
-
i0.ɵɵ
|
|
998
|
+
i0.ɵɵelementStart(69, "div", 34);
|
|
999
|
+
i0.ɵɵelement(70, "i", 35);
|
|
1000
|
+
i0.ɵɵelementStart(71, "input", 36);
|
|
1001
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TestingFeedbackComponent_Template_input_ngModelChange_71_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.filters.searchText, $event) || (ctx.filters.searchText = $event); return $event; });
|
|
1002
|
+
i0.ɵɵlistener("input", function TestingFeedbackComponent_Template_input_input_71_listener() { return ctx.onFilterChange(); });
|
|
429
1003
|
i0.ɵɵelementEnd();
|
|
430
|
-
i0.ɵɵ
|
|
431
|
-
i0.ɵɵ
|
|
432
|
-
i0.ɵɵ
|
|
433
|
-
i0.ɵɵelementStart(
|
|
434
|
-
i0.ɵɵ
|
|
435
|
-
i0.ɵɵ
|
|
436
|
-
i0.ɵɵelementStart(95, "div", 42);
|
|
437
|
-
i0.ɵɵrepeaterCreate(96, TestingFeedbackComponent_For_97_Template, 24, 23, "div", 43, _forTrack0, false, TestingFeedbackComponent_ForEmpty_98_Template, 6, 0, "div", 44);
|
|
438
|
-
i0.ɵɵpipe(99, "async");
|
|
439
|
-
i0.ɵɵelementEnd()();
|
|
440
|
-
i0.ɵɵelementStart(100, "div", 45)(101, "div", 46)(102, "h3");
|
|
441
|
-
i0.ɵɵelement(103, "i", 47);
|
|
442
|
-
i0.ɵɵtext(104, " Feedback Statistics ");
|
|
1004
|
+
i0.ɵɵtemplate(72, TestingFeedbackComponent_button_72_Template, 2, 0, "button", 37);
|
|
1005
|
+
i0.ɵɵelementEnd()()();
|
|
1006
|
+
i0.ɵɵtemplate(73, TestingFeedbackComponent_div_73_Template, 17, 4, "div", 38)(74, TestingFeedbackComponent_div_74_Template, 17, 4, "div", 38)(75, TestingFeedbackComponent_div_75_Template, 7, 3, "div", 38);
|
|
1007
|
+
i0.ɵɵelementStart(76, "div", 39)(77, "h3");
|
|
1008
|
+
i0.ɵɵelement(78, "i", 40);
|
|
1009
|
+
i0.ɵɵtext(79, " Feedback Statistics ");
|
|
443
1010
|
i0.ɵɵelementEnd();
|
|
444
|
-
i0.ɵɵelementStart(
|
|
445
|
-
i0.ɵɵtext(
|
|
1011
|
+
i0.ɵɵelementStart(80, "div", 41)(81, "div", 42)(82, "div", 43);
|
|
1012
|
+
i0.ɵɵtext(83, "Total Feedback");
|
|
446
1013
|
i0.ɵɵelementEnd();
|
|
447
|
-
i0.ɵɵelementStart(
|
|
448
|
-
i0.ɵɵtext(
|
|
449
|
-
i0.ɵɵpipe(
|
|
1014
|
+
i0.ɵɵelementStart(84, "div", 44);
|
|
1015
|
+
i0.ɵɵtext(85);
|
|
1016
|
+
i0.ɵɵpipe(86, "async");
|
|
450
1017
|
i0.ɵɵelementEnd()();
|
|
451
|
-
i0.ɵɵelementStart(
|
|
452
|
-
i0.ɵɵtext(
|
|
1018
|
+
i0.ɵɵelementStart(87, "div", 42)(88, "div", 43);
|
|
1019
|
+
i0.ɵɵtext(89, "Avg Rating");
|
|
453
1020
|
i0.ɵɵelementEnd();
|
|
454
|
-
i0.ɵɵelementStart(
|
|
455
|
-
i0.ɵɵtext(
|
|
456
|
-
i0.ɵɵpipe(
|
|
457
|
-
i0.ɵɵpipe(
|
|
1021
|
+
i0.ɵɵelementStart(90, "div", 44);
|
|
1022
|
+
i0.ɵɵtext(91);
|
|
1023
|
+
i0.ɵɵpipe(92, "async");
|
|
1024
|
+
i0.ɵɵpipe(93, "number");
|
|
458
1025
|
i0.ɵɵelementEnd()();
|
|
459
|
-
i0.ɵɵelementStart(
|
|
460
|
-
i0.ɵɵtext(
|
|
1026
|
+
i0.ɵɵelementStart(94, "div", 42)(95, "div", 43);
|
|
1027
|
+
i0.ɵɵtext(96, "Agreement Rate");
|
|
461
1028
|
i0.ɵɵelementEnd();
|
|
462
|
-
i0.ɵɵelementStart(
|
|
463
|
-
i0.ɵɵtext(
|
|
464
|
-
i0.ɵɵpipe(
|
|
465
|
-
i0.ɵɵpipe(
|
|
1029
|
+
i0.ɵɵelementStart(97, "div", 44);
|
|
1030
|
+
i0.ɵɵtext(98);
|
|
1031
|
+
i0.ɵɵpipe(99, "async");
|
|
1032
|
+
i0.ɵɵpipe(100, "number");
|
|
466
1033
|
i0.ɵɵelementEnd()();
|
|
467
|
-
i0.ɵɵelementStart(
|
|
468
|
-
i0.ɵɵtext(
|
|
1034
|
+
i0.ɵɵelementStart(101, "div", 42)(102, "div", 43);
|
|
1035
|
+
i0.ɵɵtext(103, "Discrepancy Count");
|
|
469
1036
|
i0.ɵɵelementEnd();
|
|
470
|
-
i0.ɵɵelementStart(
|
|
471
|
-
i0.ɵɵtext(
|
|
472
|
-
i0.ɵɵpipe(
|
|
473
|
-
i0.ɵɵ
|
|
474
|
-
i0.ɵɵelementEnd()()()()()();
|
|
1037
|
+
i0.ɵɵelementStart(104, "div", 44);
|
|
1038
|
+
i0.ɵɵtext(105);
|
|
1039
|
+
i0.ɵɵpipe(106, "async");
|
|
1040
|
+
i0.ɵɵelementEnd()()()()();
|
|
475
1041
|
} if (rf & 2) {
|
|
1042
|
+
let tmp_5_0;
|
|
1043
|
+
let tmp_7_0;
|
|
1044
|
+
let tmp_9_0;
|
|
476
1045
|
let tmp_10_0;
|
|
1046
|
+
let tmp_19_0;
|
|
1047
|
+
let tmp_20_0;
|
|
1048
|
+
let tmp_21_0;
|
|
1049
|
+
let tmp_22_0;
|
|
477
1050
|
i0.ɵɵadvance(6);
|
|
478
|
-
i0.ɵɵproperty("ngIf", i0.ɵɵpipeBind1(7,
|
|
479
|
-
i0.ɵɵadvance(
|
|
480
|
-
i0.ɵɵ
|
|
1051
|
+
i0.ɵɵproperty("ngIf", i0.ɵɵpipeBind1(7, 27, ctx.pendingCount$));
|
|
1052
|
+
i0.ɵɵadvance(3);
|
|
1053
|
+
i0.ɵɵproperty("disabled", ctx.isRefreshing);
|
|
1054
|
+
i0.ɵɵadvance();
|
|
1055
|
+
i0.ɵɵclassProp("fa-spin", ctx.isRefreshing);
|
|
1056
|
+
i0.ɵɵadvance();
|
|
1057
|
+
i0.ɵɵtextInterpolate1(" ", ctx.isRefreshing ? "Refreshing..." : "Refresh", " ");
|
|
1058
|
+
i0.ɵɵadvance(2);
|
|
1059
|
+
i0.ɵɵclassProp("active", ctx.viewMode === "pending");
|
|
1060
|
+
i0.ɵɵadvance(5);
|
|
1061
|
+
i0.ɵɵtextInterpolate((tmp_5_0 = i0.ɵɵpipeBind1(19, 29, ctx.pendingCount$)) !== null && tmp_5_0 !== undefined ? tmp_5_0 : 0);
|
|
1062
|
+
i0.ɵɵadvance(5);
|
|
1063
|
+
i0.ɵɵclassProp("active", ctx.viewMode === "reviewed");
|
|
1064
|
+
i0.ɵɵadvance(5);
|
|
1065
|
+
i0.ɵɵtextInterpolate((tmp_7_0 = i0.ɵɵpipeBind1(29, 31, ctx.reviewedCount$)) !== null && tmp_7_0 !== undefined ? tmp_7_0 : 0);
|
|
1066
|
+
i0.ɵɵadvance(5);
|
|
1067
|
+
i0.ɵɵclassProp("active", ctx.viewMode === "suites");
|
|
1068
|
+
i0.ɵɵadvance(5);
|
|
1069
|
+
i0.ɵɵtextInterpolate((tmp_9_0 = i0.ɵɵpipeBind1(39, 33, ctx.suiteCount$)) !== null && tmp_9_0 !== undefined ? tmp_9_0 : 0);
|
|
481
1070
|
i0.ɵɵadvance(10);
|
|
482
|
-
i0.ɵɵ
|
|
483
|
-
i0.ɵɵadvance(
|
|
1071
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(50, 37, (tmp_10_0 = i0.ɵɵpipeBind1(49, 35, ctx.accuracyRate$)) !== null && tmp_10_0 !== undefined ? tmp_10_0 : 0, "1.1-1"), "%");
|
|
1072
|
+
i0.ɵɵadvance(9);
|
|
1073
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx.viewMode);
|
|
1074
|
+
i0.ɵɵadvance(7);
|
|
1075
|
+
i0.ɵɵproperty("ngIf", ctx.viewMode === "pending");
|
|
1076
|
+
i0.ɵɵadvance();
|
|
1077
|
+
i0.ɵɵproperty("ngIf", ctx.viewMode !== "suites");
|
|
1078
|
+
i0.ɵɵadvance(6);
|
|
484
1079
|
i0.ɵɵtwoWayProperty("ngModel", ctx.filters.searchText);
|
|
485
1080
|
i0.ɵɵadvance();
|
|
486
1081
|
i0.ɵɵproperty("ngIf", ctx.filters.searchText);
|
|
487
|
-
i0.ɵɵadvance(
|
|
488
|
-
i0.ɵɵ
|
|
489
|
-
i0.ɵɵadvance(
|
|
490
|
-
i0.ɵɵ
|
|
491
|
-
i0.ɵɵadvance(
|
|
492
|
-
i0.ɵɵ
|
|
493
|
-
i0.ɵɵadvance(
|
|
494
|
-
i0.ɵɵ
|
|
495
|
-
i0.ɵɵadvance(13);
|
|
496
|
-
i0.ɵɵtwoWayProperty("ngModel", ctx.sortBy);
|
|
497
|
-
i0.ɵɵadvance(8);
|
|
498
|
-
i0.ɵɵrepeater((tmp_10_0 = i0.ɵɵpipeBind1(99, 28, ctx.filteredFeedback$)) !== null && tmp_10_0 !== undefined ? tmp_10_0 : i0.ɵɵpureFunction0(47, _c0));
|
|
499
|
-
i0.ɵɵadvance(14);
|
|
500
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(111, 30, ctx.totalFeedback$) || 0);
|
|
1082
|
+
i0.ɵɵadvance();
|
|
1083
|
+
i0.ɵɵproperty("ngIf", ctx.viewMode === "pending");
|
|
1084
|
+
i0.ɵɵadvance();
|
|
1085
|
+
i0.ɵɵproperty("ngIf", ctx.viewMode === "reviewed");
|
|
1086
|
+
i0.ɵɵadvance();
|
|
1087
|
+
i0.ɵɵproperty("ngIf", ctx.viewMode === "suites");
|
|
1088
|
+
i0.ɵɵadvance(10);
|
|
1089
|
+
i0.ɵɵtextInterpolate((tmp_19_0 = i0.ɵɵpipeBind1(86, 40, ctx.totalFeedback$)) !== null && tmp_19_0 !== undefined ? tmp_19_0 : 0);
|
|
501
1090
|
i0.ɵɵadvance(6);
|
|
502
|
-
i0.ɵɵ
|
|
1091
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(93, 44, (tmp_20_0 = i0.ɵɵpipeBind1(92, 42, ctx.avgRating$)) !== null && tmp_20_0 !== undefined ? tmp_20_0 : 0, "1.1-1"), "/10");
|
|
503
1092
|
i0.ɵɵadvance(7);
|
|
504
|
-
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(
|
|
1093
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(100, 49, (tmp_21_0 = i0.ɵɵpipeBind1(99, 47, ctx.agreementRate$)) !== null && tmp_21_0 !== undefined ? tmp_21_0 : 0, "1.1-1"), "%");
|
|
505
1094
|
i0.ɵɵadvance(7);
|
|
506
|
-
i0.ɵɵ
|
|
507
|
-
} }, dependencies: [i2.NgIf, i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i3.DefaultValueAccessor, i3.NumberValueAccessor, i3.CheckboxControlValueAccessor, i3.SelectControlValueAccessor, i3.NgControlStatus, i3.MinValidator, i3.MaxValidator, i3.NgModel, i4.TestStatusBadgeComponent, i4.ScoreIndicatorComponent, i2.AsyncPipe, i2.DecimalPipe, i2.DatePipe], styles: [".testing-feedback[_ngcontent-%COMP%] {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background: #f8f9fa;\n }\n\n .feedback-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 24px;\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n\n .header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .header-left[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .header-left[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #2196f3;\n }\n\n .pending-badge[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: #fff3e0;\n border: 2px solid #ff9800;\n border-radius: 20px;\n }\n\n .badge-count[_ngcontent-%COMP%] {\n background: #ff9800;\n color: white;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 700;\n }\n\n .badge-text[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: #ff9800;\n }\n\n .action-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid #ddd;\n border-radius: 4px;\n background: white;\n color: #666;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .action-btn[_ngcontent-%COMP%]:hover {\n background: #f5f5f5;\n }\n\n .feedback-filters[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n margin-bottom: 20px;\n background: white;\n padding: 16px;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n\n .filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 150px;\n }\n\n .filter-group.search[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .filter-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n color: #666;\n text-transform: uppercase;\n }\n\n .filter-group[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n padding: 8px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 13px;\n background: white;\n }\n\n .search-input-wrapper[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n }\n\n .search-input-wrapper[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n position: absolute;\n left: 12px;\n color: #999;\n font-size: 12px;\n }\n\n .search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n padding: 8px 40px 8px 36px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 13px;\n }\n\n .clear-btn[_ngcontent-%COMP%] {\n position: absolute;\n right: 8px;\n background: none;\n border: none;\n color: #999;\n cursor: pointer;\n padding: 4px;\n }\n\n .clear-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n }\n\n .feedback-summary[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n }\n\n .summary-card[_ngcontent-%COMP%] {\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .summary-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 24px;\n color: white;\n }\n\n .summary-icon.pending[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);\n }\n\n .summary-icon.discrepancy[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f44336 0%, #d32f2f 100%);\n }\n\n .summary-icon.reviewed[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #4caf50 0%, #388e3c 100%);\n }\n\n .summary-icon.accuracy[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #2196f3 0%, #1976d2 100%);\n }\n\n .summary-content[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .summary-value[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: #333;\n line-height: 1;\n margin-bottom: 6px;\n }\n\n .summary-label[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #666;\n font-weight: 600;\n text-transform: uppercase;\n }\n\n .feedback-content[_ngcontent-%COMP%] {\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n margin-bottom: 24px;\n }\n\n .content-header[_ngcontent-%COMP%] {\n padding: 20px;\n background: #f8f9fa;\n border-bottom: 2px solid #e0e0e0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .content-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .content-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #2196f3;\n }\n\n .sort-controls[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #666;\n }\n\n .sort-controls[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n padding: 6px 10px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 12px;\n }\n\n .feedback-list[_ngcontent-%COMP%] {\n max-height: 800px;\n overflow-y: auto;\n }\n\n .feedback-item[_ngcontent-%COMP%] {\n border-bottom: 1px solid #f0f0f0;\n transition: all 0.3s ease;\n }\n\n .feedback-item.expanded[_ngcontent-%COMP%] {\n background: #f8f9fa;\n }\n\n .item-header[_ngcontent-%COMP%] {\n padding: 20px;\n display: flex;\n align-items: center;\n gap: 16px;\n cursor: pointer;\n transition: background 0.2s ease;\n }\n\n .item-header[_ngcontent-%COMP%]:hover {\n background: rgba(33, 150, 243, 0.05);\n }\n\n .item-main[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .item-title[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 600;\n color: #333;\n margin-bottom: 8px;\n }\n\n .item-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: #666;\n }\n\n .item-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .item-reason[_ngcontent-%COMP%] {\n min-width: 180px;\n }\n\n .reason-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n }\n\n .reason-badge.no-feedback[_ngcontent-%COMP%] {\n background: #e3f2fd;\n color: #2196f3;\n }\n\n .reason-badge.high-score-failed[_ngcontent-%COMP%] {\n background: #ffebee;\n color: #f44336;\n }\n\n .reason-badge.low-score-passed[_ngcontent-%COMP%] {\n background: #fff3e0;\n color: #ff9800;\n }\n\n .expand-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: #666;\n cursor: pointer;\n padding: 8px;\n border-radius: 4px;\n transition: all 0.2s ease;\n font-size: 16px;\n }\n\n .expand-btn[_ngcontent-%COMP%]:hover {\n background: #e0e0e0;\n }\n\n .item-content[_ngcontent-%COMP%] {\n padding: 20px;\n border-top: 1px solid #e0e0e0;\n animation: _ngcontent-%COMP%_slideDown 0.3s ease;\n }\n\n @keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .feedback-form[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 1fr;\n gap: 24px;\n }\n\n .form-section[_ngcontent-%COMP%] h4[_ngcontent-%COMP%], \n .context-section[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n padding-bottom: 12px;\n border-bottom: 2px solid #f0f0f0;\n }\n\n .form-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 2fr;\n gap: 16px;\n margin-bottom: 16px;\n }\n\n .form-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .form-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: #666;\n }\n\n .rating-input[_ngcontent-%COMP%] {\n padding: 8px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 14px;\n }\n\n .checkbox-group[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n }\n\n .checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #333;\n cursor: pointer;\n }\n\n .checkbox-label[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n }\n\n .comments-textarea[_ngcontent-%COMP%] {\n padding: 10px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 13px;\n font-family: inherit;\n resize: vertical;\n }\n\n .form-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n margin-top: 16px;\n }\n\n .submit-btn[_ngcontent-%COMP%], \n .skip-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border: none;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .submit-btn[_ngcontent-%COMP%] {\n background: #2196f3;\n color: white;\n }\n\n .submit-btn[_ngcontent-%COMP%]:hover {\n background: #1976d2;\n }\n\n .skip-btn[_ngcontent-%COMP%] {\n background: #f5f5f5;\n color: #666;\n }\n\n .skip-btn[_ngcontent-%COMP%]:hover {\n background: #e0e0e0;\n }\n\n .context-details[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n margin-bottom: 16px;\n }\n\n .detail-item[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px;\n background: white;\n border-radius: 4px;\n border: 1px solid #e0e0e0;\n }\n\n .detail-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n color: #666;\n text-transform: uppercase;\n }\n\n .detail-value[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: #333;\n }\n\n .view-details-btn[_ngcontent-%COMP%] {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px;\n border: 1px solid #2196f3;\n border-radius: 4px;\n background: white;\n color: #2196f3;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .view-details-btn[_ngcontent-%COMP%]:hover {\n background: #e3f2fd;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 80px 20px;\n text-align: center;\n color: #999;\n }\n\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 64px;\n margin-bottom: 20px;\n opacity: 0.3;\n color: #4caf50;\n }\n\n .empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 20px;\n color: #666;\n margin: 0 0 12px 0;\n }\n\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n margin: 0;\n }\n\n .feedback-stats[_ngcontent-%COMP%] {\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n\n .feedback-stats[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 20px 0;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n padding-bottom: 12px;\n border-bottom: 2px solid #f0f0f0;\n }\n\n .feedback-stats[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #2196f3;\n }\n\n .stats-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n }\n\n .stat-card[_ngcontent-%COMP%] {\n background: #f8f9fa;\n padding: 16px;\n border-radius: 6px;\n text-align: center;\n }\n\n .stat-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n color: #666;\n text-transform: uppercase;\n margin-bottom: 8px;\n }\n\n .stat-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: #333;\n }\n\n @media (max-width: 1200px) {\n .feedback-form[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .form-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n }"], changeDetection: 0 });
|
|
1095
|
+
i0.ɵɵtextInterpolate((tmp_22_0 = i0.ɵɵpipeBind1(106, 52, ctx.discrepancyCount$)) !== null && tmp_22_0 !== undefined ? tmp_22_0 : 0);
|
|
1096
|
+
} }, dependencies: [i2.NgForOf, i2.NgIf, i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i3.DefaultValueAccessor, i3.SelectControlValueAccessor, i3.NgControlStatus, i3.NgModel, i2.AsyncPipe, i2.DecimalPipe, i2.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n }\n\n .testing-feedback[_ngcontent-%COMP%] {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background: #f8f9fa;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n \n\n .feedback-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n background: white;\n padding: 20px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n\n .header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .header-left[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 22px;\n font-weight: 700;\n color: #1e293b;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .header-left[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #3b82f6;\n }\n\n .pending-badge[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 14px;\n background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 100%);\n border: 1px solid #fb923c;\n border-radius: 20px;\n }\n\n .badge-count[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);\n color: white;\n min-width: 24px;\n height: 24px;\n padding: 0 6px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 700;\n }\n\n .badge-text[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: #ea580c;\n }\n\n .action-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 18px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n background: white;\n color: #64748b;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .action-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #f8fafc;\n border-color: #cbd5e1;\n }\n\n .action-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n \n\n .feedback-summary[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 20px;\n }\n\n .summary-card[_ngcontent-%COMP%] {\n background: white;\n padding: 20px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n display: flex;\n align-items: center;\n gap: 16px;\n transition: all 0.2s ease;\n position: relative;\n }\n\n .summary-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n }\n\n .summary-card.clickable[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);\n }\n\n .summary-card.active[_ngcontent-%COMP%] {\n border: 2px solid #3b82f6;\n background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);\n }\n\n .summary-icon[_ngcontent-%COMP%] {\n width: 52px;\n height: 52px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 22px;\n color: white;\n flex-shrink: 0;\n }\n\n .summary-icon.pending[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);\n }\n\n .summary-icon.reviewed[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);\n }\n\n .summary-icon.suites[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);\n }\n\n .summary-icon.accuracy[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n }\n\n .summary-content[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .summary-value[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: #1e293b;\n line-height: 1;\n margin-bottom: 4px;\n }\n\n .summary-label[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #64748b;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .summary-arrow[_ngcontent-%COMP%] {\n color: #94a3b8;\n font-size: 14px;\n }\n\n \n\n .feedback-filters[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n margin-bottom: 20px;\n background: white;\n padding: 16px 20px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n flex-wrap: wrap;\n }\n\n .filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 140px;\n }\n\n .filter-group.search[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 200px;\n }\n\n .filter-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 700;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .filter-group[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n padding: 10px 12px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 13px;\n background: white;\n color: #1e293b;\n cursor: pointer;\n }\n\n .filter-group[_ngcontent-%COMP%] select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n }\n\n .search-input-wrapper[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n }\n\n .search-input-wrapper[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n position: absolute;\n left: 12px;\n color: #94a3b8;\n font-size: 13px;\n }\n\n .search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n padding: 10px 40px 10px 36px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 13px;\n }\n\n .search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n }\n\n .clear-btn[_ngcontent-%COMP%] {\n position: absolute;\n right: 8px;\n background: none;\n border: none;\n color: #94a3b8;\n cursor: pointer;\n padding: 6px;\n border-radius: 4px;\n }\n\n .clear-btn[_ngcontent-%COMP%]:hover {\n color: #64748b;\n background: #f1f5f9;\n }\n\n \n\n .feedback-content[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n margin-bottom: 20px;\n }\n\n .content-header[_ngcontent-%COMP%] {\n padding: 20px;\n background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);\n border-bottom: 1px solid #e2e8f0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .content-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #1e293b;\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n .content-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #3b82f6;\n }\n\n .sort-controls[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #64748b;\n }\n\n .sort-controls[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n padding: 6px 10px;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n font-size: 12px;\n background: white;\n }\n\n \n\n .feedback-list[_ngcontent-%COMP%] {\n max-height: 600px;\n overflow-y: auto;\n }\n\n .feedback-item[_ngcontent-%COMP%] {\n border-bottom: 1px solid #f1f5f9;\n transition: all 0.2s ease;\n }\n\n .feedback-item.expanded[_ngcontent-%COMP%] {\n background: #f8fafc;\n }\n\n .item-header[_ngcontent-%COMP%] {\n padding: 16px 20px;\n display: flex;\n align-items: center;\n gap: 16px;\n cursor: pointer;\n transition: background 0.2s ease;\n }\n\n .item-header[_ngcontent-%COMP%]:hover {\n background: rgba(59, 130, 246, 0.04);\n }\n\n .item-main[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n\n .item-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #1e293b;\n margin-bottom: 6px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .item-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: #64748b;\n flex-wrap: wrap;\n }\n\n .item-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 5px;\n }\n\n .meta-status[_ngcontent-%COMP%] {\n padding: 2px 8px;\n border-radius: 4px;\n font-weight: 600;\n font-size: 11px;\n }\n\n .meta-status.status-passed[_ngcontent-%COMP%] { background: #dcfce7; color: #16a34a; }\n .meta-status.status-failed[_ngcontent-%COMP%] { background: #fee2e2; color: #dc2626; }\n .meta-status.status-error[_ngcontent-%COMP%] { background: #fef3c7; color: #d97706; }\n .meta-status.status-running[_ngcontent-%COMP%] { background: #dbeafe; color: #2563eb; }\n\n .item-reason[_ngcontent-%COMP%] {\n flex-shrink: 0;\n }\n\n .reason-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n }\n\n .reason-badge.no-feedback[_ngcontent-%COMP%] {\n background: #dbeafe;\n color: #2563eb;\n }\n\n .reason-badge.high-score-failed[_ngcontent-%COMP%] {\n background: #fee2e2;\n color: #dc2626;\n }\n\n .reason-badge.low-score-passed[_ngcontent-%COMP%] {\n background: #fef3c7;\n color: #d97706;\n }\n\n .expand-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: #94a3b8;\n cursor: pointer;\n padding: 8px;\n border-radius: 6px;\n transition: all 0.2s ease;\n font-size: 14px;\n }\n\n .expand-btn[_ngcontent-%COMP%]:hover {\n background: #e2e8f0;\n color: #64748b;\n }\n\n \n\n .item-content[_ngcontent-%COMP%] {\n padding: 20px;\n border-top: 1px solid #e2e8f0;\n background: white;\n }\n\n .feedback-form[_ngcontent-%COMP%] {\n max-width: 600px;\n }\n\n .form-section[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 20px 0;\n font-size: 15px;\n font-weight: 600;\n color: #1e293b;\n }\n\n .rating-section[_ngcontent-%COMP%], \n .correctness-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n }\n\n .rating-section[_ngcontent-%COMP%] label[_ngcontent-%COMP%], \n .correctness-section[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #64748b;\n margin-bottom: 10px;\n }\n\n .rating-stars-input[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .star-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n font-size: 22px;\n color: #e2e8f0;\n cursor: pointer;\n padding: 2px;\n transition: all 0.15s ease;\n }\n\n .star-btn[_ngcontent-%COMP%]:hover {\n transform: scale(1.2);\n }\n\n .star-btn.filled[_ngcontent-%COMP%] {\n color: #f59e0b;\n }\n\n .rating-display[_ngcontent-%COMP%] {\n margin-left: 12px;\n font-size: 16px;\n font-weight: 700;\n color: #1e293b;\n }\n\n .correctness-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n }\n\n .correctness-btn[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 20px;\n border: 2px solid #e2e8f0;\n border-radius: 10px;\n background: white;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .correctness-btn.correct[_ngcontent-%COMP%]:hover, \n .correctness-btn.correct.active[_ngcontent-%COMP%] {\n border-color: #22c55e;\n background: #f0fdf4;\n color: #16a34a;\n }\n\n .correctness-btn.incorrect[_ngcontent-%COMP%]:hover, \n .correctness-btn.incorrect.active[_ngcontent-%COMP%] {\n border-color: #ef4444;\n background: #fef2f2;\n color: #dc2626;\n }\n\n .form-group[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n }\n\n .form-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #64748b;\n margin-bottom: 8px;\n }\n\n .comments-textarea[_ngcontent-%COMP%] {\n width: 100%;\n padding: 12px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 14px;\n font-family: inherit;\n resize: vertical;\n min-height: 80px;\n }\n\n .comments-textarea[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n }\n\n .form-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n margin-top: 20px;\n }\n\n .submit-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 24px;\n border: none;\n border-radius: 8px;\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .submit-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);\n }\n\n .submit-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n .view-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 20px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n background: white;\n color: #64748b;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .view-btn[_ngcontent-%COMP%]:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n }\n\n \n\n .reviewed-item[_ngcontent-%COMP%] {\n padding: 16px 20px;\n border-bottom: 1px solid #f1f5f9;\n }\n\n .reviewed-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .reviewed-main[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n\n .reviewed-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #1e293b;\n margin-bottom: 4px;\n }\n\n .reviewed-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: #64748b;\n }\n\n .reviewed-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 5px;\n }\n\n .reviewed-rating[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n }\n\n .rating-stars[_ngcontent-%COMP%] {\n display: flex;\n gap: 2px;\n }\n\n .rating-stars[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #e2e8f0;\n }\n\n .rating-stars[_ngcontent-%COMP%] i.filled[_ngcontent-%COMP%] {\n color: #f59e0b;\n }\n\n .rating-text[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: #64748b;\n }\n\n .reviewed-verdict[_ngcontent-%COMP%] {\n flex-shrink: 0;\n }\n\n .verdict-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n }\n\n .verdict-badge.correct[_ngcontent-%COMP%] {\n background: #dcfce7;\n color: #16a34a;\n }\n\n .verdict-badge.incorrect[_ngcontent-%COMP%] {\n background: #fee2e2;\n color: #dc2626;\n }\n\n .view-btn-small[_ngcontent-%COMP%] {\n background: none;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n padding: 8px;\n color: #64748b;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .view-btn-small[_ngcontent-%COMP%]:hover {\n background: #f8fafc;\n border-color: #cbd5e1;\n }\n\n .reviewed-comments[_ngcontent-%COMP%] {\n margin-top: 12px;\n padding: 12px;\n background: #f8fafc;\n border-radius: 8px;\n border-left: 3px solid #3b82f6;\n }\n\n .reviewed-comments[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: #475569;\n line-height: 1.5;\n }\n\n \n\n .suites-list[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .suite-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 12px;\n cursor: pointer;\n transition: all 0.2s ease;\n margin-bottom: 12px;\n }\n\n .suite-card[_ngcontent-%COMP%]:hover {\n border-color: #3b82f6;\n background: white;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n }\n\n .suite-card[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n }\n\n .suite-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n flex: 1;\n min-width: 0;\n }\n\n .suite-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n border-radius: 10px;\n background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 18px;\n flex-shrink: 0;\n }\n\n .suite-info[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 15px;\n font-weight: 600;\n color: #1e293b;\n }\n\n .suite-meta[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #64748b;\n }\n\n .suite-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 20px;\n }\n\n .suite-stat[_ngcontent-%COMP%] {\n text-align: center;\n min-width: 60px;\n }\n\n .suite-stat[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: #1e293b;\n }\n\n .suite-stat[_ngcontent-%COMP%] .stat-value.pending[_ngcontent-%COMP%] {\n color: #f97316;\n }\n\n .suite-stat[_ngcontent-%COMP%] .stat-value.reviewed[_ngcontent-%COMP%] {\n color: #22c55e;\n }\n\n .suite-stat[_ngcontent-%COMP%] .stat-value.good[_ngcontent-%COMP%] {\n color: #22c55e;\n }\n\n .suite-stat[_ngcontent-%COMP%] .stat-value.bad[_ngcontent-%COMP%] {\n color: #ef4444;\n }\n\n .suite-stat[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #94a3b8;\n font-weight: 600;\n text-transform: uppercase;\n }\n\n .suite-arrow[_ngcontent-%COMP%] {\n color: #94a3b8;\n font-size: 14px;\n }\n\n \n\n .empty-state[_ngcontent-%COMP%] {\n padding: 60px 20px;\n text-align: center;\n }\n\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 56px;\n margin-bottom: 16px;\n color: #cbd5e1;\n }\n\n .empty-state.success[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #22c55e;\n }\n\n .empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 18px;\n color: #475569;\n margin: 0 0 8px 0;\n font-weight: 600;\n }\n\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #94a3b8;\n margin: 0;\n }\n\n \n\n .feedback-stats[_ngcontent-%COMP%] {\n background: white;\n padding: 20px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n\n .feedback-stats[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 20px 0;\n font-size: 16px;\n font-weight: 600;\n color: #1e293b;\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n .feedback-stats[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #3b82f6;\n }\n\n .stats-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n }\n\n .stat-card[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);\n padding: 16px;\n border-radius: 10px;\n text-align: center;\n }\n\n .stat-card[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 700;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n\n .stat-card[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: #1e293b;\n }\n\n \n\n @media (max-width: 1024px) {\n .feedback-summary[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .suite-stats[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n gap: 12px;\n }\n }\n\n @media (max-width: 768px) {\n .testing-feedback[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .feedback-header[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n align-items: flex-start;\n }\n\n .feedback-summary[_ngcontent-%COMP%] {\n grid-template-columns: 1fr 1fr;\n }\n\n .summary-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .summary-value[_ngcontent-%COMP%] {\n font-size: 22px;\n }\n\n .feedback-filters[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .filter-group[_ngcontent-%COMP%] {\n min-width: 100%;\n }\n\n .item-header[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .item-reason[_ngcontent-%COMP%] {\n width: 100%;\n margin-top: 8px;\n }\n\n .correctness-buttons[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .form-actions[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .reviewed-header[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .suite-card[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .suite-stats[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: space-between;\n }\n }"], data: { animation: [] }, changeDetection: 0 });
|
|
508
1097
|
}
|
|
509
1098
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TestingFeedbackComponent, [{
|
|
510
1099
|
type: Component,
|
|
511
1100
|
args: [{ selector: 'app-testing-feedback', changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
512
1101
|
<div class="testing-feedback">
|
|
1102
|
+
<!-- Header -->
|
|
513
1103
|
<div class="feedback-header">
|
|
514
1104
|
<div class="header-left">
|
|
515
1105
|
<h2>
|
|
516
1106
|
<i class="fa-solid fa-clipboard-check"></i>
|
|
517
1107
|
Human Feedback Review
|
|
518
1108
|
</h2>
|
|
519
|
-
<div class="pending-badge" *ngIf="(pendingCount$ | async)
|
|
520
|
-
<span class="badge-count">{{
|
|
521
|
-
<span class="badge-text">Pending Review</span>
|
|
1109
|
+
<div class="pending-badge" *ngIf="(pendingCount$ | async) as count">
|
|
1110
|
+
<span class="badge-count" *ngIf="count > 0">{{ count }}</span>
|
|
1111
|
+
<span class="badge-text">{{ count > 0 ? 'Pending Review' : 'All Reviewed' }}</span>
|
|
522
1112
|
</div>
|
|
523
1113
|
</div>
|
|
524
1114
|
<div class="header-actions">
|
|
525
|
-
<button class="action-btn" (click)="refresh()">
|
|
526
|
-
<i class="fa-solid fa-refresh"></i>
|
|
527
|
-
Refresh
|
|
1115
|
+
<button class="action-btn refresh-btn" (click)="refresh()" [disabled]="isRefreshing">
|
|
1116
|
+
<i class="fa-solid fa-refresh" [class.fa-spin]="isRefreshing"></i>
|
|
1117
|
+
{{ isRefreshing ? 'Refreshing...' : 'Refresh' }}
|
|
528
1118
|
</button>
|
|
529
1119
|
</div>
|
|
530
1120
|
</div>
|
|
531
1121
|
|
|
532
|
-
<!--
|
|
1122
|
+
<!-- KPI Summary Cards - Clickable -->
|
|
1123
|
+
<div class="feedback-summary">
|
|
1124
|
+
<div class="summary-card clickable" [class.active]="viewMode === 'pending'" (click)="setViewMode('pending')">
|
|
1125
|
+
<div class="summary-icon pending">
|
|
1126
|
+
<i class="fa-solid fa-hourglass-half"></i>
|
|
1127
|
+
</div>
|
|
1128
|
+
<div class="summary-content">
|
|
1129
|
+
<div class="summary-value">{{ (pendingCount$ | async) ?? 0 }}</div>
|
|
1130
|
+
<div class="summary-label">Pending Review</div>
|
|
1131
|
+
</div>
|
|
1132
|
+
<i class="fa-solid fa-chevron-right summary-arrow"></i>
|
|
1133
|
+
</div>
|
|
1134
|
+
<div class="summary-card clickable" [class.active]="viewMode === 'reviewed'" (click)="setViewMode('reviewed')">
|
|
1135
|
+
<div class="summary-icon reviewed">
|
|
1136
|
+
<i class="fa-solid fa-check-circle"></i>
|
|
1137
|
+
</div>
|
|
1138
|
+
<div class="summary-content">
|
|
1139
|
+
<div class="summary-value">{{ (reviewedCount$ | async) ?? 0 }}</div>
|
|
1140
|
+
<div class="summary-label">Reviewed</div>
|
|
1141
|
+
</div>
|
|
1142
|
+
<i class="fa-solid fa-chevron-right summary-arrow"></i>
|
|
1143
|
+
</div>
|
|
1144
|
+
<div class="summary-card clickable" [class.active]="viewMode === 'suites'" (click)="setViewMode('suites')">
|
|
1145
|
+
<div class="summary-icon suites">
|
|
1146
|
+
<i class="fa-solid fa-layer-group"></i>
|
|
1147
|
+
</div>
|
|
1148
|
+
<div class="summary-content">
|
|
1149
|
+
<div class="summary-value">{{ (suiteCount$ | async) ?? 0 }}</div>
|
|
1150
|
+
<div class="summary-label">Test Suites</div>
|
|
1151
|
+
</div>
|
|
1152
|
+
<i class="fa-solid fa-chevron-right summary-arrow"></i>
|
|
1153
|
+
</div>
|
|
1154
|
+
<div class="summary-card">
|
|
1155
|
+
<div class="summary-icon accuracy">
|
|
1156
|
+
<i class="fa-solid fa-bullseye"></i>
|
|
1157
|
+
</div>
|
|
1158
|
+
<div class="summary-content">
|
|
1159
|
+
<div class="summary-value">{{ (accuracyRate$ | async) ?? 0 | number:'1.1-1' }}%</div>
|
|
1160
|
+
<div class="summary-label">Human-AI Agreement</div>
|
|
1161
|
+
</div>
|
|
1162
|
+
</div>
|
|
1163
|
+
</div>
|
|
1164
|
+
|
|
1165
|
+
<!-- Filters Bar -->
|
|
533
1166
|
<div class="feedback-filters">
|
|
534
1167
|
<div class="filter-group">
|
|
535
|
-
<label>
|
|
536
|
-
<select [(ngModel)]="
|
|
537
|
-
<option value="
|
|
538
|
-
<option value="
|
|
539
|
-
<option value="
|
|
1168
|
+
<label>View</label>
|
|
1169
|
+
<select [(ngModel)]="viewMode" (change)="onViewModeChange()">
|
|
1170
|
+
<option value="pending">Pending Reviews</option>
|
|
1171
|
+
<option value="reviewed">Reviewed Feedback</option>
|
|
1172
|
+
<option value="suites">By Test Suite</option>
|
|
540
1173
|
</select>
|
|
541
1174
|
</div>
|
|
542
|
-
<div class="filter-group">
|
|
1175
|
+
<div class="filter-group" *ngIf="viewMode === 'pending'">
|
|
543
1176
|
<label>Reason</label>
|
|
544
1177
|
<select [(ngModel)]="filters.reason" (change)="onFilterChange()">
|
|
545
1178
|
<option value="all">All Reasons</option>
|
|
@@ -548,6 +1181,13 @@ export class TestingFeedbackComponent {
|
|
|
548
1181
|
<option value="low-score-passed">Low Score but Passed</option>
|
|
549
1182
|
</select>
|
|
550
1183
|
</div>
|
|
1184
|
+
<div class="filter-group" *ngIf="viewMode !== 'suites'">
|
|
1185
|
+
<label>Test Suite</label>
|
|
1186
|
+
<select [(ngModel)]="filters.suiteId" (change)="onFilterChange()">
|
|
1187
|
+
<option [ngValue]="null">All Suites</option>
|
|
1188
|
+
<option *ngFor="let suite of testSuites$ | async" [ngValue]="suite.ID">{{ suite.Name }}</option>
|
|
1189
|
+
</select>
|
|
1190
|
+
</div>
|
|
551
1191
|
<div class="filter-group search">
|
|
552
1192
|
<label>Search</label>
|
|
553
1193
|
<div class="search-input-wrapper">
|
|
@@ -558,59 +1198,15 @@ export class TestingFeedbackComponent {
|
|
|
558
1198
|
(input)="onFilterChange()"
|
|
559
1199
|
placeholder="Search tests..."
|
|
560
1200
|
/>
|
|
561
|
-
<button
|
|
562
|
-
class="clear-btn"
|
|
563
|
-
*ngIf="filters.searchText"
|
|
564
|
-
(click)="clearSearch()"
|
|
565
|
-
>
|
|
1201
|
+
<button class="clear-btn" *ngIf="filters.searchText" (click)="clearSearch()">
|
|
566
1202
|
<i class="fa-solid fa-times"></i>
|
|
567
1203
|
</button>
|
|
568
1204
|
</div>
|
|
569
1205
|
</div>
|
|
570
1206
|
</div>
|
|
571
1207
|
|
|
572
|
-
<!--
|
|
573
|
-
<div class="feedback-
|
|
574
|
-
<div class="summary-card">
|
|
575
|
-
<div class="summary-icon pending">
|
|
576
|
-
<i class="fa-solid fa-hourglass-half"></i>
|
|
577
|
-
</div>
|
|
578
|
-
<div class="summary-content">
|
|
579
|
-
<div class="summary-value">{{ (pendingCount$ | async) || 0 }}</div>
|
|
580
|
-
<div class="summary-label">Pending Review</div>
|
|
581
|
-
</div>
|
|
582
|
-
</div>
|
|
583
|
-
<div class="summary-card">
|
|
584
|
-
<div class="summary-icon discrepancy">
|
|
585
|
-
<i class="fa-solid fa-triangle-exclamation"></i>
|
|
586
|
-
</div>
|
|
587
|
-
<div class="summary-content">
|
|
588
|
-
<div class="summary-value">{{ (discrepancyCount$ | async) || 0 }}</div>
|
|
589
|
-
<div class="summary-label">Score Discrepancies</div>
|
|
590
|
-
</div>
|
|
591
|
-
</div>
|
|
592
|
-
<div class="summary-card">
|
|
593
|
-
<div class="summary-icon reviewed">
|
|
594
|
-
<i class="fa-solid fa-check-circle"></i>
|
|
595
|
-
</div>
|
|
596
|
-
<div class="summary-content">
|
|
597
|
-
<div class="summary-value">{{ (reviewedCount$ | async) || 0 }}</div>
|
|
598
|
-
<div class="summary-label">Reviewed</div>
|
|
599
|
-
</div>
|
|
600
|
-
</div>
|
|
601
|
-
<div class="summary-card">
|
|
602
|
-
<div class="summary-icon accuracy">
|
|
603
|
-
<i class="fa-solid fa-bullseye"></i>
|
|
604
|
-
</div>
|
|
605
|
-
<div class="summary-content">
|
|
606
|
-
<div class="summary-value">{{ (accuracyRate$ | async) || 0 | number:'1.1-1' }}%</div>
|
|
607
|
-
<div class="summary-label">Human-AI Agreement</div>
|
|
608
|
-
</div>
|
|
609
|
-
</div>
|
|
610
|
-
</div>
|
|
611
|
-
|
|
612
|
-
<!-- Pending Reviews List -->
|
|
613
|
-
<div class="feedback-content">
|
|
1208
|
+
<!-- Pending Reviews View -->
|
|
1209
|
+
<div class="feedback-content" *ngIf="viewMode === 'pending'">
|
|
614
1210
|
<div class="content-header">
|
|
615
1211
|
<h3>
|
|
616
1212
|
<i class="fa-solid fa-list-check"></i>
|
|
@@ -626,9 +1222,10 @@ export class TestingFeedbackComponent {
|
|
|
626
1222
|
</div>
|
|
627
1223
|
</div>
|
|
628
1224
|
|
|
629
|
-
<div class="feedback-list">
|
|
630
|
-
|
|
631
|
-
<div class="feedback-item"
|
|
1225
|
+
<div class="feedback-list" *ngIf="(filteredPending$ | async) as items">
|
|
1226
|
+
<ng-container *ngIf="items.length > 0; else emptyPending">
|
|
1227
|
+
<div class="feedback-item" *ngFor="let item of items; trackBy: trackByTestRunId"
|
|
1228
|
+
[class.expanded]="expandedItem === item.testRunID">
|
|
632
1229
|
<div class="item-header" (click)="toggleExpanded(item.testRunID)">
|
|
633
1230
|
<div class="item-main">
|
|
634
1231
|
<div class="item-title">{{ item.testName }}</div>
|
|
@@ -638,10 +1235,10 @@ export class TestingFeedbackComponent {
|
|
|
638
1235
|
{{ item.runDateTime | date:'short' }}
|
|
639
1236
|
</span>
|
|
640
1237
|
<span class="meta-score">
|
|
641
|
-
|
|
1238
|
+
Score: <strong>{{ (item.automatedScore * 10).toFixed(2) }}</strong>/10
|
|
642
1239
|
</span>
|
|
643
|
-
<span class="meta-status">
|
|
644
|
-
|
|
1240
|
+
<span class="meta-status" [class]="'status-' + item.automatedStatus.toLowerCase()">
|
|
1241
|
+
{{ item.automatedStatus }}
|
|
645
1242
|
</span>
|
|
646
1243
|
</div>
|
|
647
1244
|
</div>
|
|
@@ -659,130 +1256,231 @@ export class TestingFeedbackComponent {
|
|
|
659
1256
|
</button>
|
|
660
1257
|
</div>
|
|
661
1258
|
|
|
662
|
-
|
|
663
|
-
<div class="
|
|
664
|
-
<div class="
|
|
665
|
-
<
|
|
666
|
-
|
|
667
|
-
<
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
placeholder="Rate 1-10"
|
|
677
|
-
/>
|
|
678
|
-
</div>
|
|
679
|
-
<div class="form-group">
|
|
680
|
-
<label>Is Automated Result Correct?</label>
|
|
681
|
-
<div class="checkbox-group">
|
|
682
|
-
<label class="checkbox-label">
|
|
683
|
-
<input type="checkbox" [(ngModel)]="item.feedbackIsCorrect" />
|
|
684
|
-
<span>Yes, the automated assessment is correct</span>
|
|
685
|
-
</label>
|
|
686
|
-
</div>
|
|
687
|
-
</div>
|
|
688
|
-
</div>
|
|
689
|
-
<div class="form-group">
|
|
690
|
-
<label>Comments / Notes</label>
|
|
691
|
-
<textarea
|
|
692
|
-
[(ngModel)]="item.feedbackComments"
|
|
693
|
-
rows="4"
|
|
694
|
-
class="comments-textarea"
|
|
695
|
-
placeholder="Provide detailed feedback about this test result..."
|
|
696
|
-
></textarea>
|
|
1259
|
+
<div class="item-content" *ngIf="expandedItem === item.testRunID" [@slideDown]>
|
|
1260
|
+
<div class="feedback-form">
|
|
1261
|
+
<div class="form-section">
|
|
1262
|
+
<h4>Provide Your Feedback</h4>
|
|
1263
|
+
<div class="rating-section">
|
|
1264
|
+
<label>Human Rating</label>
|
|
1265
|
+
<div class="rating-stars-input">
|
|
1266
|
+
<button *ngFor="let star of [1,2,3,4,5,6,7,8,9,10]"
|
|
1267
|
+
class="star-btn"
|
|
1268
|
+
[class.filled]="star <= item.feedbackRating"
|
|
1269
|
+
(click)="setRating(item, star)">
|
|
1270
|
+
<i class="fa-solid fa-star"></i>
|
|
1271
|
+
</button>
|
|
1272
|
+
<span class="rating-display">{{ item.feedbackRating }}/10</span>
|
|
697
1273
|
</div>
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
1274
|
+
</div>
|
|
1275
|
+
<div class="correctness-section">
|
|
1276
|
+
<label>Is the Automated Result Correct?</label>
|
|
1277
|
+
<div class="correctness-buttons">
|
|
1278
|
+
<button class="correctness-btn correct" [class.active]="item.feedbackIsCorrect === true"
|
|
1279
|
+
(click)="setCorrectness(item, true)">
|
|
1280
|
+
<i class="fa-solid fa-check"></i>
|
|
1281
|
+
Correct
|
|
702
1282
|
</button>
|
|
703
|
-
<button class="
|
|
704
|
-
|
|
705
|
-
|
|
1283
|
+
<button class="correctness-btn incorrect" [class.active]="item.feedbackIsCorrect === false"
|
|
1284
|
+
(click)="setCorrectness(item, false)">
|
|
1285
|
+
<i class="fa-solid fa-times"></i>
|
|
1286
|
+
Incorrect
|
|
706
1287
|
</button>
|
|
707
1288
|
</div>
|
|
708
1289
|
</div>
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
<
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
<span class="detail-label">Status</span>
|
|
725
|
-
<span class="detail-value">
|
|
726
|
-
<app-test-status-badge [status]="getTestStatus(item.automatedStatus)"></app-test-status-badge>
|
|
727
|
-
</span>
|
|
728
|
-
</div>
|
|
729
|
-
<div class="detail-item">
|
|
730
|
-
<span class="detail-label">Run Date</span>
|
|
731
|
-
<span class="detail-value">{{ item.runDateTime | date:'medium' }}</span>
|
|
732
|
-
</div>
|
|
733
|
-
</div>
|
|
734
|
-
<button class="view-details-btn" (click)="viewFullDetails(item)">
|
|
1290
|
+
<div class="form-group">
|
|
1291
|
+
<label>Comments / Correction Notes</label>
|
|
1292
|
+
<textarea
|
|
1293
|
+
[(ngModel)]="item.feedbackComments"
|
|
1294
|
+
rows="3"
|
|
1295
|
+
class="comments-textarea"
|
|
1296
|
+
placeholder="Explain your assessment or provide correction notes..."
|
|
1297
|
+
></textarea>
|
|
1298
|
+
</div>
|
|
1299
|
+
<div class="form-actions">
|
|
1300
|
+
<button class="submit-btn" (click)="submitFeedback(item)" [disabled]="isSubmitting">
|
|
1301
|
+
<i class="fa-solid fa-paper-plane"></i>
|
|
1302
|
+
{{ isSubmitting ? 'Submitting...' : 'Submit Feedback' }}
|
|
1303
|
+
</button>
|
|
1304
|
+
<button class="view-btn" (click)="viewFullDetails(item)">
|
|
735
1305
|
<i class="fa-solid fa-external-link"></i>
|
|
736
|
-
View Full
|
|
1306
|
+
View Full Details
|
|
737
1307
|
</button>
|
|
738
1308
|
</div>
|
|
739
1309
|
</div>
|
|
740
1310
|
</div>
|
|
741
|
-
|
|
1311
|
+
</div>
|
|
742
1312
|
</div>
|
|
743
|
-
|
|
744
|
-
|
|
1313
|
+
</ng-container>
|
|
1314
|
+
<ng-template #emptyPending>
|
|
1315
|
+
<div class="empty-state success">
|
|
745
1316
|
<i class="fa-solid fa-check-double"></i>
|
|
746
1317
|
<h3>All Caught Up!</h3>
|
|
747
1318
|
<p>No tests currently require feedback review.</p>
|
|
748
1319
|
</div>
|
|
749
|
-
|
|
1320
|
+
</ng-template>
|
|
750
1321
|
</div>
|
|
751
1322
|
</div>
|
|
752
1323
|
|
|
753
|
-
<!-- Feedback
|
|
754
|
-
<div class="feedback-
|
|
755
|
-
<div class="
|
|
1324
|
+
<!-- Reviewed Feedback View -->
|
|
1325
|
+
<div class="feedback-content" *ngIf="viewMode === 'reviewed'">
|
|
1326
|
+
<div class="content-header">
|
|
756
1327
|
<h3>
|
|
757
|
-
<i class="fa-solid fa-
|
|
758
|
-
Feedback
|
|
1328
|
+
<i class="fa-solid fa-history"></i>
|
|
1329
|
+
Reviewed Feedback History
|
|
759
1330
|
</h3>
|
|
760
|
-
<div class="
|
|
761
|
-
<
|
|
762
|
-
|
|
763
|
-
<
|
|
1331
|
+
<div class="sort-controls">
|
|
1332
|
+
<label>Sort by:</label>
|
|
1333
|
+
<select [(ngModel)]="reviewedSortBy" (change)="onReviewedSortChange()">
|
|
1334
|
+
<option value="date">Review Date</option>
|
|
1335
|
+
<option value="rating">Rating</option>
|
|
1336
|
+
<option value="test-name">Test Name</option>
|
|
1337
|
+
</select>
|
|
1338
|
+
</div>
|
|
1339
|
+
</div>
|
|
1340
|
+
|
|
1341
|
+
<div class="feedback-list" *ngIf="(filteredReviewed$ | async) as items">
|
|
1342
|
+
<ng-container *ngIf="items.length > 0; else emptyReviewed">
|
|
1343
|
+
<div class="reviewed-item" *ngFor="let item of items; trackBy: trackByReviewedId">
|
|
1344
|
+
<div class="reviewed-header">
|
|
1345
|
+
<div class="reviewed-main">
|
|
1346
|
+
<div class="reviewed-title">{{ item.testName }}</div>
|
|
1347
|
+
<div class="reviewed-meta">
|
|
1348
|
+
<span class="meta-reviewer">
|
|
1349
|
+
<i class="fa-solid fa-user"></i>
|
|
1350
|
+
{{ item.reviewerName }}
|
|
1351
|
+
</span>
|
|
1352
|
+
<span class="meta-date">
|
|
1353
|
+
<i class="fa-solid fa-calendar"></i>
|
|
1354
|
+
{{ item.reviewedAt | date:'short' }}
|
|
1355
|
+
</span>
|
|
1356
|
+
</div>
|
|
1357
|
+
</div>
|
|
1358
|
+
<div class="reviewed-rating">
|
|
1359
|
+
<div class="rating-stars">
|
|
1360
|
+
<i class="fa-solid fa-star" *ngFor="let s of [1,2,3,4,5,6,7,8,9,10]"
|
|
1361
|
+
[class.filled]="s <= item.rating"></i>
|
|
1362
|
+
</div>
|
|
1363
|
+
<span class="rating-text">{{ item.rating }}/10</span>
|
|
1364
|
+
</div>
|
|
1365
|
+
<div class="reviewed-verdict">
|
|
1366
|
+
<span class="verdict-badge" [class.correct]="item.isCorrect" [class.incorrect]="!item.isCorrect">
|
|
1367
|
+
<i class="fa-solid" [class.fa-check]="item.isCorrect" [class.fa-times]="!item.isCorrect"></i>
|
|
1368
|
+
{{ item.isCorrect ? 'Correct' : 'Incorrect' }}
|
|
1369
|
+
</span>
|
|
1370
|
+
</div>
|
|
1371
|
+
<button class="view-btn-small" (click)="viewTestRun(item.testRunID)">
|
|
1372
|
+
<i class="fa-solid fa-external-link"></i>
|
|
1373
|
+
</button>
|
|
1374
|
+
</div>
|
|
1375
|
+
<div class="reviewed-comments" *ngIf="item.comments">
|
|
1376
|
+
<p>{{ item.comments }}</p>
|
|
1377
|
+
</div>
|
|
764
1378
|
</div>
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
1379
|
+
</ng-container>
|
|
1380
|
+
<ng-template #emptyReviewed>
|
|
1381
|
+
<div class="empty-state">
|
|
1382
|
+
<i class="fa-solid fa-clipboard"></i>
|
|
1383
|
+
<h3>No Reviews Yet</h3>
|
|
1384
|
+
<p>No feedback has been submitted yet. Start by reviewing pending tests.</p>
|
|
768
1385
|
</div>
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
1386
|
+
</ng-template>
|
|
1387
|
+
</div>
|
|
1388
|
+
</div>
|
|
1389
|
+
|
|
1390
|
+
<!-- Test Suite Aggregation View -->
|
|
1391
|
+
<div class="feedback-content" *ngIf="viewMode === 'suites'">
|
|
1392
|
+
<div class="content-header">
|
|
1393
|
+
<h3>
|
|
1394
|
+
<i class="fa-solid fa-layer-group"></i>
|
|
1395
|
+
Feedback by Test Suite
|
|
1396
|
+
</h3>
|
|
1397
|
+
</div>
|
|
1398
|
+
|
|
1399
|
+
<div class="suites-list" *ngIf="(suiteAggregations$ | async) as suites">
|
|
1400
|
+
<ng-container *ngIf="suites.length > 0; else emptySuites">
|
|
1401
|
+
<div class="suite-card" *ngFor="let suite of suites; trackBy: trackBySuiteId"
|
|
1402
|
+
(click)="selectSuite(suite.suiteId)">
|
|
1403
|
+
<div class="suite-header">
|
|
1404
|
+
<div class="suite-icon">
|
|
1405
|
+
<i class="fa-solid fa-layer-group"></i>
|
|
1406
|
+
</div>
|
|
1407
|
+
<div class="suite-info">
|
|
1408
|
+
<h4>{{ suite.suiteName }}</h4>
|
|
1409
|
+
<div class="suite-meta">
|
|
1410
|
+
<span>{{ suite.totalRuns }} test runs</span>
|
|
1411
|
+
</div>
|
|
1412
|
+
</div>
|
|
1413
|
+
</div>
|
|
1414
|
+
<div class="suite-stats">
|
|
1415
|
+
<div class="suite-stat">
|
|
1416
|
+
<div class="stat-value pending">{{ suite.pendingCount }}</div>
|
|
1417
|
+
<div class="stat-label">Pending</div>
|
|
1418
|
+
</div>
|
|
1419
|
+
<div class="suite-stat">
|
|
1420
|
+
<div class="stat-value reviewed">{{ suite.reviewedCount }}</div>
|
|
1421
|
+
<div class="stat-label">Reviewed</div>
|
|
1422
|
+
</div>
|
|
1423
|
+
<div class="suite-stat">
|
|
1424
|
+
<div class="stat-value">{{ suite.avgRating | number:'1.1-1' }}</div>
|
|
1425
|
+
<div class="stat-label">Avg Rating</div>
|
|
1426
|
+
</div>
|
|
1427
|
+
<div class="suite-stat">
|
|
1428
|
+
<div class="stat-value" [class.good]="suite.agreementRate >= 70" [class.bad]="suite.agreementRate < 50">
|
|
1429
|
+
{{ suite.agreementRate | number:'1.0-0' }}%
|
|
1430
|
+
</div>
|
|
1431
|
+
<div class="stat-label">Agreement</div>
|
|
1432
|
+
</div>
|
|
1433
|
+
<div class="suite-stat">
|
|
1434
|
+
<div class="stat-value" [class.good]="suite.passRate >= 80" [class.bad]="suite.passRate < 50">
|
|
1435
|
+
{{ suite.passRate | number:'1.0-0' }}%
|
|
1436
|
+
</div>
|
|
1437
|
+
<div class="stat-label">Pass Rate</div>
|
|
1438
|
+
</div>
|
|
1439
|
+
</div>
|
|
1440
|
+
<i class="fa-solid fa-chevron-right suite-arrow"></i>
|
|
772
1441
|
</div>
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
1442
|
+
</ng-container>
|
|
1443
|
+
<ng-template #emptySuites>
|
|
1444
|
+
<div class="empty-state">
|
|
1445
|
+
<i class="fa-solid fa-layer-group"></i>
|
|
1446
|
+
<h3>No Test Suites</h3>
|
|
1447
|
+
<p>No test suites have been created yet.</p>
|
|
776
1448
|
</div>
|
|
1449
|
+
</ng-template>
|
|
1450
|
+
</div>
|
|
1451
|
+
</div>
|
|
1452
|
+
|
|
1453
|
+
<!-- Summary Statistics -->
|
|
1454
|
+
<div class="feedback-stats">
|
|
1455
|
+
<h3>
|
|
1456
|
+
<i class="fa-solid fa-chart-pie"></i>
|
|
1457
|
+
Feedback Statistics
|
|
1458
|
+
</h3>
|
|
1459
|
+
<div class="stats-grid">
|
|
1460
|
+
<div class="stat-card">
|
|
1461
|
+
<div class="stat-label">Total Feedback</div>
|
|
1462
|
+
<div class="stat-value">{{ (totalFeedback$ | async) ?? 0 }}</div>
|
|
1463
|
+
</div>
|
|
1464
|
+
<div class="stat-card">
|
|
1465
|
+
<div class="stat-label">Avg Rating</div>
|
|
1466
|
+
<div class="stat-value">{{ (avgRating$ | async) ?? 0 | number:'1.1-1' }}/10</div>
|
|
1467
|
+
</div>
|
|
1468
|
+
<div class="stat-card">
|
|
1469
|
+
<div class="stat-label">Agreement Rate</div>
|
|
1470
|
+
<div class="stat-value">{{ (agreementRate$ | async) ?? 0 | number:'1.1-1' }}%</div>
|
|
1471
|
+
</div>
|
|
1472
|
+
<div class="stat-card">
|
|
1473
|
+
<div class="stat-label">Discrepancy Count</div>
|
|
1474
|
+
<div class="stat-value">{{ (discrepancyCount$ | async) ?? 0 }}</div>
|
|
777
1475
|
</div>
|
|
778
1476
|
</div>
|
|
779
1477
|
</div>
|
|
780
1478
|
</div>
|
|
781
|
-
`, styles: ["\n .testing-feedback {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background: #f8f9fa;\n }\n\n .feedback-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 24px;\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n\n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .header-left h2 {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .header-left h2 i {\n color: #2196f3;\n }\n\n .pending-badge {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: #fff3e0;\n border: 2px solid #ff9800;\n border-radius: 20px;\n }\n\n .badge-count {\n background: #ff9800;\n color: white;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 700;\n }\n\n .badge-text {\n font-size: 12px;\n font-weight: 600;\n color: #ff9800;\n }\n\n .action-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid #ddd;\n border-radius: 4px;\n background: white;\n color: #666;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .action-btn:hover {\n background: #f5f5f5;\n }\n\n .feedback-filters {\n display: flex;\n gap: 16px;\n margin-bottom: 20px;\n background: white;\n padding: 16px;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n\n .filter-group {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 150px;\n }\n\n .filter-group.search {\n flex: 1;\n }\n\n .filter-group label {\n font-size: 11px;\n font-weight: 600;\n color: #666;\n text-transform: uppercase;\n }\n\n .filter-group select {\n padding: 8px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 13px;\n background: white;\n }\n\n .search-input-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n }\n\n .search-input-wrapper i {\n position: absolute;\n left: 12px;\n color: #999;\n font-size: 12px;\n }\n\n .search-input-wrapper input {\n flex: 1;\n padding: 8px 40px 8px 36px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 13px;\n }\n\n .clear-btn {\n position: absolute;\n right: 8px;\n background: none;\n border: none;\n color: #999;\n cursor: pointer;\n padding: 4px;\n }\n\n .clear-btn:hover {\n color: #333;\n }\n\n .feedback-summary {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n }\n\n .summary-card {\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .summary-icon {\n width: 56px;\n height: 56px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 24px;\n color: white;\n }\n\n .summary-icon.pending {\n background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);\n }\n\n .summary-icon.discrepancy {\n background: linear-gradient(135deg, #f44336 0%, #d32f2f 100%);\n }\n\n .summary-icon.reviewed {\n background: linear-gradient(135deg, #4caf50 0%, #388e3c 100%);\n }\n\n .summary-icon.accuracy {\n background: linear-gradient(135deg, #2196f3 0%, #1976d2 100%);\n }\n\n .summary-content {\n flex: 1;\n }\n\n .summary-value {\n font-size: 28px;\n font-weight: 700;\n color: #333;\n line-height: 1;\n margin-bottom: 6px;\n }\n\n .summary-label {\n font-size: 11px;\n color: #666;\n font-weight: 600;\n text-transform: uppercase;\n }\n\n .feedback-content {\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n margin-bottom: 24px;\n }\n\n .content-header {\n padding: 20px;\n background: #f8f9fa;\n border-bottom: 2px solid #e0e0e0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .content-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .content-header h3 i {\n color: #2196f3;\n }\n\n .sort-controls {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #666;\n }\n\n .sort-controls select {\n padding: 6px 10px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 12px;\n }\n\n .feedback-list {\n max-height: 800px;\n overflow-y: auto;\n }\n\n .feedback-item {\n border-bottom: 1px solid #f0f0f0;\n transition: all 0.3s ease;\n }\n\n .feedback-item.expanded {\n background: #f8f9fa;\n }\n\n .item-header {\n padding: 20px;\n display: flex;\n align-items: center;\n gap: 16px;\n cursor: pointer;\n transition: background 0.2s ease;\n }\n\n .item-header:hover {\n background: rgba(33, 150, 243, 0.05);\n }\n\n .item-main {\n flex: 1;\n }\n\n .item-title {\n font-size: 15px;\n font-weight: 600;\n color: #333;\n margin-bottom: 8px;\n }\n\n .item-meta {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: #666;\n }\n\n .item-meta span {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .item-reason {\n min-width: 180px;\n }\n\n .reason-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n }\n\n .reason-badge.no-feedback {\n background: #e3f2fd;\n color: #2196f3;\n }\n\n .reason-badge.high-score-failed {\n background: #ffebee;\n color: #f44336;\n }\n\n .reason-badge.low-score-passed {\n background: #fff3e0;\n color: #ff9800;\n }\n\n .expand-btn {\n background: none;\n border: none;\n color: #666;\n cursor: pointer;\n padding: 8px;\n border-radius: 4px;\n transition: all 0.2s ease;\n font-size: 16px;\n }\n\n .expand-btn:hover {\n background: #e0e0e0;\n }\n\n .item-content {\n padding: 20px;\n border-top: 1px solid #e0e0e0;\n animation: slideDown 0.3s ease;\n }\n\n @keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .feedback-form {\n display: grid;\n grid-template-columns: 2fr 1fr;\n gap: 24px;\n }\n\n .form-section h4,\n .context-section h4 {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n padding-bottom: 12px;\n border-bottom: 2px solid #f0f0f0;\n }\n\n .form-row {\n display: grid;\n grid-template-columns: 1fr 2fr;\n gap: 16px;\n margin-bottom: 16px;\n }\n\n .form-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .form-group label {\n font-size: 12px;\n font-weight: 600;\n color: #666;\n }\n\n .rating-input {\n padding: 8px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 14px;\n }\n\n .checkbox-group {\n display: flex;\n align-items: center;\n }\n\n .checkbox-label {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #333;\n cursor: pointer;\n }\n\n .checkbox-label input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n }\n\n .comments-textarea {\n padding: 10px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 13px;\n font-family: inherit;\n resize: vertical;\n }\n\n .form-actions {\n display: flex;\n gap: 12px;\n margin-top: 16px;\n }\n\n .submit-btn,\n .skip-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border: none;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .submit-btn {\n background: #2196f3;\n color: white;\n }\n\n .submit-btn:hover {\n background: #1976d2;\n }\n\n .skip-btn {\n background: #f5f5f5;\n color: #666;\n }\n\n .skip-btn:hover {\n background: #e0e0e0;\n }\n\n .context-details {\n display: flex;\n flex-direction: column;\n gap: 12px;\n margin-bottom: 16px;\n }\n\n .detail-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px;\n background: white;\n border-radius: 4px;\n border: 1px solid #e0e0e0;\n }\n\n .detail-label {\n font-size: 11px;\n font-weight: 600;\n color: #666;\n text-transform: uppercase;\n }\n\n .detail-value {\n font-size: 13px;\n font-weight: 500;\n color: #333;\n }\n\n .view-details-btn {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px;\n border: 1px solid #2196f3;\n border-radius: 4px;\n background: white;\n color: #2196f3;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .view-details-btn:hover {\n background: #e3f2fd;\n }\n\n .empty-state {\n padding: 80px 20px;\n text-align: center;\n color: #999;\n }\n\n .empty-state i {\n font-size: 64px;\n margin-bottom: 20px;\n opacity: 0.3;\n color: #4caf50;\n }\n\n .empty-state h3 {\n font-size: 20px;\n color: #666;\n margin: 0 0 12px 0;\n }\n\n .empty-state p {\n font-size: 14px;\n margin: 0;\n }\n\n .feedback-stats {\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n\n .feedback-stats h3 {\n margin: 0 0 20px 0;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n padding-bottom: 12px;\n border-bottom: 2px solid #f0f0f0;\n }\n\n .feedback-stats h3 i {\n color: #2196f3;\n }\n\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n }\n\n .stat-card {\n background: #f8f9fa;\n padding: 16px;\n border-radius: 6px;\n text-align: center;\n }\n\n .stat-label {\n font-size: 11px;\n font-weight: 600;\n color: #666;\n text-transform: uppercase;\n margin-bottom: 8px;\n }\n\n .stat-value {\n font-size: 24px;\n font-weight: 700;\n color: #333;\n }\n\n @media (max-width: 1200px) {\n .feedback-form {\n grid-template-columns: 1fr;\n }\n\n .form-row {\n grid-template-columns: 1fr;\n }\n }\n "] }]
|
|
1479
|
+
`, animations: [], styles: ["\n :host {\n display: block;\n height: 100%;\n }\n\n .testing-feedback {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background: #f8f9fa;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n /* Header */\n .feedback-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n background: white;\n padding: 20px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n\n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .header-left h2 {\n margin: 0;\n font-size: 22px;\n font-weight: 700;\n color: #1e293b;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .header-left h2 i {\n color: #3b82f6;\n }\n\n .pending-badge {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 14px;\n background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 100%);\n border: 1px solid #fb923c;\n border-radius: 20px;\n }\n\n .badge-count {\n background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);\n color: white;\n min-width: 24px;\n height: 24px;\n padding: 0 6px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 700;\n }\n\n .badge-text {\n font-size: 12px;\n font-weight: 600;\n color: #ea580c;\n }\n\n .action-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 18px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n background: white;\n color: #64748b;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .action-btn:hover:not(:disabled) {\n background: #f8fafc;\n border-color: #cbd5e1;\n }\n\n .action-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n /* Summary Cards */\n .feedback-summary {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 20px;\n }\n\n .summary-card {\n background: white;\n padding: 20px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n display: flex;\n align-items: center;\n gap: 16px;\n transition: all 0.2s ease;\n position: relative;\n }\n\n .summary-card.clickable {\n cursor: pointer;\n }\n\n .summary-card.clickable:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);\n }\n\n .summary-card.active {\n border: 2px solid #3b82f6;\n background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);\n }\n\n .summary-icon {\n width: 52px;\n height: 52px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 22px;\n color: white;\n flex-shrink: 0;\n }\n\n .summary-icon.pending {\n background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);\n }\n\n .summary-icon.reviewed {\n background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);\n }\n\n .summary-icon.suites {\n background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);\n }\n\n .summary-icon.accuracy {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n }\n\n .summary-content {\n flex: 1;\n }\n\n .summary-value {\n font-size: 28px;\n font-weight: 700;\n color: #1e293b;\n line-height: 1;\n margin-bottom: 4px;\n }\n\n .summary-label {\n font-size: 11px;\n color: #64748b;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .summary-arrow {\n color: #94a3b8;\n font-size: 14px;\n }\n\n /* Filters */\n .feedback-filters {\n display: flex;\n gap: 16px;\n margin-bottom: 20px;\n background: white;\n padding: 16px 20px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n flex-wrap: wrap;\n }\n\n .filter-group {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 140px;\n }\n\n .filter-group.search {\n flex: 1;\n min-width: 200px;\n }\n\n .filter-group label {\n font-size: 10px;\n font-weight: 700;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .filter-group select {\n padding: 10px 12px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 13px;\n background: white;\n color: #1e293b;\n cursor: pointer;\n }\n\n .filter-group select:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n }\n\n .search-input-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n }\n\n .search-input-wrapper > i {\n position: absolute;\n left: 12px;\n color: #94a3b8;\n font-size: 13px;\n }\n\n .search-input-wrapper input {\n flex: 1;\n padding: 10px 40px 10px 36px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 13px;\n }\n\n .search-input-wrapper input:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n }\n\n .clear-btn {\n position: absolute;\n right: 8px;\n background: none;\n border: none;\n color: #94a3b8;\n cursor: pointer;\n padding: 6px;\n border-radius: 4px;\n }\n\n .clear-btn:hover {\n color: #64748b;\n background: #f1f5f9;\n }\n\n /* Content Area */\n .feedback-content {\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n margin-bottom: 20px;\n }\n\n .content-header {\n padding: 20px;\n background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);\n border-bottom: 1px solid #e2e8f0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .content-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #1e293b;\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n .content-header h3 i {\n color: #3b82f6;\n }\n\n .sort-controls {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #64748b;\n }\n\n .sort-controls select {\n padding: 6px 10px;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n font-size: 12px;\n background: white;\n }\n\n /* Feedback List */\n .feedback-list {\n max-height: 600px;\n overflow-y: auto;\n }\n\n .feedback-item {\n border-bottom: 1px solid #f1f5f9;\n transition: all 0.2s ease;\n }\n\n .feedback-item.expanded {\n background: #f8fafc;\n }\n\n .item-header {\n padding: 16px 20px;\n display: flex;\n align-items: center;\n gap: 16px;\n cursor: pointer;\n transition: background 0.2s ease;\n }\n\n .item-header:hover {\n background: rgba(59, 130, 246, 0.04);\n }\n\n .item-main {\n flex: 1;\n min-width: 0;\n }\n\n .item-title {\n font-size: 14px;\n font-weight: 600;\n color: #1e293b;\n margin-bottom: 6px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .item-meta {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: #64748b;\n flex-wrap: wrap;\n }\n\n .item-meta span {\n display: flex;\n align-items: center;\n gap: 5px;\n }\n\n .meta-status {\n padding: 2px 8px;\n border-radius: 4px;\n font-weight: 600;\n font-size: 11px;\n }\n\n .meta-status.status-passed { background: #dcfce7; color: #16a34a; }\n .meta-status.status-failed { background: #fee2e2; color: #dc2626; }\n .meta-status.status-error { background: #fef3c7; color: #d97706; }\n .meta-status.status-running { background: #dbeafe; color: #2563eb; }\n\n .item-reason {\n flex-shrink: 0;\n }\n\n .reason-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n }\n\n .reason-badge.no-feedback {\n background: #dbeafe;\n color: #2563eb;\n }\n\n .reason-badge.high-score-failed {\n background: #fee2e2;\n color: #dc2626;\n }\n\n .reason-badge.low-score-passed {\n background: #fef3c7;\n color: #d97706;\n }\n\n .expand-btn {\n background: none;\n border: none;\n color: #94a3b8;\n cursor: pointer;\n padding: 8px;\n border-radius: 6px;\n transition: all 0.2s ease;\n font-size: 14px;\n }\n\n .expand-btn:hover {\n background: #e2e8f0;\n color: #64748b;\n }\n\n /* Expanded Content */\n .item-content {\n padding: 20px;\n border-top: 1px solid #e2e8f0;\n background: white;\n }\n\n .feedback-form {\n max-width: 600px;\n }\n\n .form-section h4 {\n margin: 0 0 20px 0;\n font-size: 15px;\n font-weight: 600;\n color: #1e293b;\n }\n\n .rating-section,\n .correctness-section {\n margin-bottom: 20px;\n }\n\n .rating-section label,\n .correctness-section label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #64748b;\n margin-bottom: 10px;\n }\n\n .rating-stars-input {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .star-btn {\n background: none;\n border: none;\n font-size: 22px;\n color: #e2e8f0;\n cursor: pointer;\n padding: 2px;\n transition: all 0.15s ease;\n }\n\n .star-btn:hover {\n transform: scale(1.2);\n }\n\n .star-btn.filled {\n color: #f59e0b;\n }\n\n .rating-display {\n margin-left: 12px;\n font-size: 16px;\n font-weight: 700;\n color: #1e293b;\n }\n\n .correctness-buttons {\n display: flex;\n gap: 12px;\n }\n\n .correctness-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 20px;\n border: 2px solid #e2e8f0;\n border-radius: 10px;\n background: white;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .correctness-btn.correct:hover,\n .correctness-btn.correct.active {\n border-color: #22c55e;\n background: #f0fdf4;\n color: #16a34a;\n }\n\n .correctness-btn.incorrect:hover,\n .correctness-btn.incorrect.active {\n border-color: #ef4444;\n background: #fef2f2;\n color: #dc2626;\n }\n\n .form-group {\n margin-bottom: 16px;\n }\n\n .form-group label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #64748b;\n margin-bottom: 8px;\n }\n\n .comments-textarea {\n width: 100%;\n padding: 12px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 14px;\n font-family: inherit;\n resize: vertical;\n min-height: 80px;\n }\n\n .comments-textarea:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n }\n\n .form-actions {\n display: flex;\n gap: 12px;\n margin-top: 20px;\n }\n\n .submit-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 24px;\n border: none;\n border-radius: 8px;\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .submit-btn:hover:not(:disabled) {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);\n }\n\n .submit-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n .view-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 20px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n background: white;\n color: #64748b;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .view-btn:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n }\n\n /* Reviewed Items */\n .reviewed-item {\n padding: 16px 20px;\n border-bottom: 1px solid #f1f5f9;\n }\n\n .reviewed-header {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .reviewed-main {\n flex: 1;\n min-width: 0;\n }\n\n .reviewed-title {\n font-size: 14px;\n font-weight: 600;\n color: #1e293b;\n margin-bottom: 4px;\n }\n\n .reviewed-meta {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: #64748b;\n }\n\n .reviewed-meta span {\n display: flex;\n align-items: center;\n gap: 5px;\n }\n\n .reviewed-rating {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n }\n\n .rating-stars {\n display: flex;\n gap: 2px;\n }\n\n .rating-stars i {\n font-size: 12px;\n color: #e2e8f0;\n }\n\n .rating-stars i.filled {\n color: #f59e0b;\n }\n\n .rating-text {\n font-size: 12px;\n font-weight: 600;\n color: #64748b;\n }\n\n .reviewed-verdict {\n flex-shrink: 0;\n }\n\n .verdict-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n }\n\n .verdict-badge.correct {\n background: #dcfce7;\n color: #16a34a;\n }\n\n .verdict-badge.incorrect {\n background: #fee2e2;\n color: #dc2626;\n }\n\n .view-btn-small {\n background: none;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n padding: 8px;\n color: #64748b;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .view-btn-small:hover {\n background: #f8fafc;\n border-color: #cbd5e1;\n }\n\n .reviewed-comments {\n margin-top: 12px;\n padding: 12px;\n background: #f8fafc;\n border-radius: 8px;\n border-left: 3px solid #3b82f6;\n }\n\n .reviewed-comments p {\n margin: 0;\n font-size: 13px;\n color: #475569;\n line-height: 1.5;\n }\n\n /* Suite Cards */\n .suites-list {\n padding: 16px;\n }\n\n .suite-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 12px;\n cursor: pointer;\n transition: all 0.2s ease;\n margin-bottom: 12px;\n }\n\n .suite-card:hover {\n border-color: #3b82f6;\n background: white;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n }\n\n .suite-card:last-child {\n margin-bottom: 0;\n }\n\n .suite-header {\n display: flex;\n align-items: center;\n gap: 14px;\n flex: 1;\n min-width: 0;\n }\n\n .suite-icon {\n width: 44px;\n height: 44px;\n border-radius: 10px;\n background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 18px;\n flex-shrink: 0;\n }\n\n .suite-info h4 {\n margin: 0 0 4px 0;\n font-size: 15px;\n font-weight: 600;\n color: #1e293b;\n }\n\n .suite-meta {\n font-size: 12px;\n color: #64748b;\n }\n\n .suite-stats {\n display: flex;\n gap: 20px;\n }\n\n .suite-stat {\n text-align: center;\n min-width: 60px;\n }\n\n .suite-stat .stat-value {\n font-size: 18px;\n font-weight: 700;\n color: #1e293b;\n }\n\n .suite-stat .stat-value.pending {\n color: #f97316;\n }\n\n .suite-stat .stat-value.reviewed {\n color: #22c55e;\n }\n\n .suite-stat .stat-value.good {\n color: #22c55e;\n }\n\n .suite-stat .stat-value.bad {\n color: #ef4444;\n }\n\n .suite-stat .stat-label {\n font-size: 10px;\n color: #94a3b8;\n font-weight: 600;\n text-transform: uppercase;\n }\n\n .suite-arrow {\n color: #94a3b8;\n font-size: 14px;\n }\n\n /* Empty States */\n .empty-state {\n padding: 60px 20px;\n text-align: center;\n }\n\n .empty-state i {\n font-size: 56px;\n margin-bottom: 16px;\n color: #cbd5e1;\n }\n\n .empty-state.success i {\n color: #22c55e;\n }\n\n .empty-state h3 {\n font-size: 18px;\n color: #475569;\n margin: 0 0 8px 0;\n font-weight: 600;\n }\n\n .empty-state p {\n font-size: 14px;\n color: #94a3b8;\n margin: 0;\n }\n\n /* Statistics */\n .feedback-stats {\n background: white;\n padding: 20px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n\n .feedback-stats h3 {\n margin: 0 0 20px 0;\n font-size: 16px;\n font-weight: 600;\n color: #1e293b;\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n .feedback-stats h3 i {\n color: #3b82f6;\n }\n\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n }\n\n .stat-card {\n background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);\n padding: 16px;\n border-radius: 10px;\n text-align: center;\n }\n\n .stat-card .stat-label {\n font-size: 10px;\n font-weight: 700;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n\n .stat-card .stat-value {\n font-size: 24px;\n font-weight: 700;\n color: #1e293b;\n }\n\n /* Responsive */\n @media (max-width: 1024px) {\n .feedback-summary {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .suite-stats {\n flex-wrap: wrap;\n gap: 12px;\n }\n }\n\n @media (max-width: 768px) {\n .testing-feedback {\n padding: 16px;\n }\n\n .feedback-header {\n flex-direction: column;\n gap: 16px;\n align-items: flex-start;\n }\n\n .feedback-summary {\n grid-template-columns: 1fr 1fr;\n }\n\n .summary-card {\n padding: 16px;\n }\n\n .summary-value {\n font-size: 22px;\n }\n\n .feedback-filters {\n flex-direction: column;\n }\n\n .filter-group {\n min-width: 100%;\n }\n\n .item-header {\n flex-wrap: wrap;\n }\n\n .item-reason {\n width: 100%;\n margin-top: 8px;\n }\n\n .correctness-buttons {\n flex-direction: column;\n }\n\n .form-actions {\n flex-direction: column;\n }\n\n .reviewed-header {\n flex-wrap: wrap;\n }\n\n .suite-card {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .suite-stats {\n width: 100%;\n justify-content: space-between;\n }\n }\n "] }]
|
|
782
1480
|
}], () => [{ type: i1.TestingInstrumentationService }, { type: i0.ChangeDetectorRef }], { initialState: [{
|
|
783
1481
|
type: Input
|
|
784
1482
|
}], stateChange: [{
|
|
785
1483
|
type: Output
|
|
786
1484
|
}] }); })();
|
|
787
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestingFeedbackComponent, { className: "TestingFeedbackComponent", filePath: "src/Testing/components/testing-feedback.component.ts", lineNumber:
|
|
1485
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestingFeedbackComponent, { className: "TestingFeedbackComponent", filePath: "src/Testing/components/testing-feedback.component.ts", lineNumber: 1431 }); })();
|
|
788
1486
|
//# sourceMappingURL=testing-feedback.component.js.map
|