@memberjunction/ng-dashboards 5.4.1 → 5.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AI/components/agents/agent-configuration.component.js +4 -4
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +5 -4
- package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +3 -3
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +8 -7
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +3 -3
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +4 -4
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.d.ts.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +3 -2
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
- package/dist/APIKeys/api-keys-resource.component.js +2 -2
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.d.ts.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +4 -3
- package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +3 -3
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +3 -2
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +2 -2
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +2 -2
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.js +3 -2
- package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js +3 -2
- package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +2 -2
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts +6 -0
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +19 -6
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +4 -0
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +13 -4
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts +2 -0
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +13 -9
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +11 -11
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +3 -3
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.d.ts +2 -0
- package/dist/Credentials/components/credentials-types-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +13 -9
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +11 -11
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js +4 -3
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +4 -3
- package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +11 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +140 -108
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.js +4 -1
- package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.d.ts.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.js +9 -8
- package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +2 -2
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/home-application.js +2 -2
- package/dist/Home/home-application.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +3 -3
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.d.ts +1 -0
- package/dist/Lists/components/lists-categories-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +17 -14
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +2 -2
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.d.ts +1 -0
- package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +15 -12
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.d.ts.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js +3 -2
- package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.d.ts.map +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.js +8 -7
- package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +22 -22
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts +2 -0
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +14 -10
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js +2 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +1 -0
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +22 -18
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-review.component.d.ts +1 -0
- package/dist/Testing/components/testing-review.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-review.component.js +14 -10
- package/dist/Testing/components/testing-review.component.js.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.js +6 -6
- package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/graph-resource.component.js +2 -2
- package/dist/VersionHistory/components/graph-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js +3 -3
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/package.json +38 -38
|
@@ -38,6 +38,7 @@ export declare class TestingReviewComponent implements OnInit, OnDestroy {
|
|
|
38
38
|
private restoreState;
|
|
39
39
|
private setupSubscriptions;
|
|
40
40
|
SetView(mode: ViewMode): void;
|
|
41
|
+
IsItemExpanded(testRunID: string): boolean;
|
|
41
42
|
ToggleExpand(testRunID: string): void;
|
|
42
43
|
SelectRating(n: number): void;
|
|
43
44
|
SelectCorrectness(value: boolean): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing-review.component.d.ts","sourceRoot":"","sources":["../../../src/Testing/components/testing-review.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EACN,SAAS,EAGT,YAAY,EACZ,iBAAiB,EAElB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,6BAA6B,EAC7B,eAAe,EAEf,0BAA0B,EAC1B,wBAAwB,EACzB,MAAM,6CAA6C,CAAC;;
|
|
1
|
+
{"version":3,"file":"testing-review.component.d.ts","sourceRoot":"","sources":["../../../src/Testing/components/testing-review.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EACN,SAAS,EAGT,YAAY,EACZ,iBAAiB,EAElB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,6BAA6B,EAC7B,eAAe,EAEf,0BAA0B,EAC1B,wBAAwB,EACzB,MAAM,6CAA6C,CAAC;;AAGrD,KAAK,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AACpC,KAAK,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEnD,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAsoCa,sBAAuB,YAAW,MAAM,EAAE,SAAS;IA6B5D,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,GAAG;IA7BJ,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAQ;IACnD,WAAW,wCAA+C;IAEpE,OAAO,CAAC,QAAQ,CAAuB;IAGvC,WAAW,EAAE,QAAQ,CAAW;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IACrC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IACxC,YAAY,UAAS;IACrB,YAAY,UAAS;IACrB,iBAAiB,SAAM;IACvB,gBAAgB,EAAE,WAAW,CAAU;IAGvC,SAAS,EAAE,eAAe,CAAmD;IAG7E,YAAY,EAAE,eAAe,EAAE,CAAM;IACrC,YAAY,EAAE,0BAA0B,EAAE,CAAM;IAChD,oBAAoB,EAAE,0BAA0B,EAAE,CAAM;IACxD,OAAO,EAAE,wBAAwB,GAAG,IAAI,CAAQ;IAChD,YAAY,SAAK;IAGjB,QAAQ,CAAC,aAAa,WAAmC;gBAG/C,sBAAsB,EAAE,6BAA6B,EACrD,GAAG,EAAE,iBAAiB;IAGhC,QAAQ,IAAI,IAAI;IAKhB,WAAW,IAAI,IAAI;IASnB,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,IAAI,cAAc,IAAI,MAAM,CAK3B;IAED,IAAI,aAAa,IAAI,MAAM,CAI1B;IAMD,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,kBAAkB;IA6B1B,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAW7B,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI1C,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAUrC,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAK7B,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAKvC,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAK9B,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBxD,QAAQ,IAAI,IAAI;IAkBhB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAOnC,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAOvC,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAStC,OAAO,IAAI,IAAI;IAef,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAKzE,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IA0BtC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,mBAAmB;IA0B3B,OAAO,CAAC,SAAS;yCAlSN,sBAAsB;2CAAtB,sBAAsB;CAqSlC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
|
|
2
2
|
import { Subject } from 'rxjs';
|
|
3
3
|
import { takeUntil } from 'rxjs/operators';
|
|
4
|
+
import { UUIDsEqual } from '@memberjunction/global';
|
|
4
5
|
import * as i0 from "@angular/core";
|
|
5
6
|
import * as i1 from "../services/testing-instrumentation.service";
|
|
6
7
|
import * as i2 from "@angular/forms";
|
|
@@ -194,7 +195,7 @@ function TestingReviewComponent_Conditional_19_Conditional_2_For_2_Template(rf,
|
|
|
194
195
|
} if (rf & 2) {
|
|
195
196
|
const item_r3 = ctx.$implicit;
|
|
196
197
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
197
|
-
i0.ɵɵclassProp("expanded", ctx_r0.
|
|
198
|
+
i0.ɵɵclassProp("expanded", ctx_r0.IsItemExpanded(item_r3.testRunID));
|
|
198
199
|
i0.ɵɵadvance(4);
|
|
199
200
|
i0.ɵɵtextInterpolate(item_r3.testName);
|
|
200
201
|
i0.ɵɵadvance(4);
|
|
@@ -208,9 +209,9 @@ function TestingReviewComponent_Conditional_19_Conditional_2_For_2_Template(rf,
|
|
|
208
209
|
i0.ɵɵadvance();
|
|
209
210
|
i0.ɵɵconditional(item_r3.reason === "no-feedback" ? 13 : item_r3.reason === "high-score-failed" ? 14 : 15);
|
|
210
211
|
i0.ɵɵadvance(4);
|
|
211
|
-
i0.ɵɵclassProp("fa-chevron-down", ctx_r0.
|
|
212
|
+
i0.ɵɵclassProp("fa-chevron-down", !ctx_r0.IsItemExpanded(item_r3.testRunID))("fa-chevron-up", ctx_r0.IsItemExpanded(item_r3.testRunID));
|
|
212
213
|
i0.ɵɵadvance();
|
|
213
|
-
i0.ɵɵconditional(ctx_r0.
|
|
214
|
+
i0.ɵɵconditional(ctx_r0.IsItemExpanded(item_r3.testRunID) ? 18 : -1);
|
|
214
215
|
} }
|
|
215
216
|
function TestingReviewComponent_Conditional_19_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
216
217
|
i0.ɵɵelementStart(0, "div", 42);
|
|
@@ -463,8 +464,11 @@ export class TestingReviewComponent {
|
|
|
463
464
|
// ------------------------------------------------------------------
|
|
464
465
|
// Queue interactions
|
|
465
466
|
// ------------------------------------------------------------------
|
|
467
|
+
IsItemExpanded(testRunID) {
|
|
468
|
+
return UUIDsEqual(this.ExpandedItemId, testRunID);
|
|
469
|
+
}
|
|
466
470
|
ToggleExpand(testRunID) {
|
|
467
|
-
if (this.ExpandedItemId
|
|
471
|
+
if (UUIDsEqual(this.ExpandedItemId, testRunID)) {
|
|
468
472
|
this.ExpandedItemId = null;
|
|
469
473
|
}
|
|
470
474
|
else {
|
|
@@ -503,7 +507,7 @@ export class TestingReviewComponent {
|
|
|
503
507
|
}
|
|
504
508
|
}
|
|
505
509
|
SkipItem() {
|
|
506
|
-
const currentIndex = this.PendingItems.findIndex(i => i.testRunID
|
|
510
|
+
const currentIndex = this.PendingItems.findIndex(i => UUIDsEqual(i.testRunID, this.ExpandedItemId));
|
|
507
511
|
this.ExpandedItemId = null;
|
|
508
512
|
this.resetForm();
|
|
509
513
|
// Expand the next item if available
|
|
@@ -766,7 +770,7 @@ export class TestingReviewComponent {
|
|
|
766
770
|
} @else {
|
|
767
771
|
<div class="queue-list">
|
|
768
772
|
@for (item of PendingItems; track item.testRunID) {
|
|
769
|
-
<div class="queue-item" [class.expanded]="
|
|
773
|
+
<div class="queue-item" [class.expanded]="IsItemExpanded(item.testRunID)">
|
|
770
774
|
<div class="queue-item-header" (click)="ToggleExpand(item.testRunID)">
|
|
771
775
|
<div class="item-info">
|
|
772
776
|
<div class="item-name">{{ item.testName }}</div>
|
|
@@ -790,13 +794,13 @@ export class TestingReviewComponent {
|
|
|
790
794
|
}
|
|
791
795
|
</span>
|
|
792
796
|
<button class="expand-toggle">
|
|
793
|
-
<i class="fa-solid" [class.fa-chevron-down]="
|
|
794
|
-
[class.fa-chevron-up]="
|
|
797
|
+
<i class="fa-solid" [class.fa-chevron-down]="!IsItemExpanded(item.testRunID)"
|
|
798
|
+
[class.fa-chevron-up]="IsItemExpanded(item.testRunID)"></i>
|
|
795
799
|
</button>
|
|
796
800
|
</div>
|
|
797
801
|
</div>
|
|
798
802
|
|
|
799
|
-
@if (
|
|
803
|
+
@if (IsItemExpanded(item.testRunID)) {
|
|
800
804
|
<div class="review-form-panel">
|
|
801
805
|
<!-- Rating -->
|
|
802
806
|
<div class="form-section">
|
|
@@ -981,5 +985,5 @@ export class TestingReviewComponent {
|
|
|
981
985
|
}], stateChange: [{
|
|
982
986
|
type: Output
|
|
983
987
|
}] }); })();
|
|
984
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestingReviewComponent, { className: "TestingReviewComponent", filePath: "src/Testing/components/testing-review.component.ts", lineNumber:
|
|
988
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestingReviewComponent, { className: "TestingReviewComponent", filePath: "src/Testing/components/testing-review.component.ts", lineNumber: 1189 }); })();
|
|
985
989
|
//# sourceMappingURL=testing-review.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing-review.component.js","sourceRoot":"","sources":["../../../src/Testing/components/testing-review.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n OnInit,\n OnDestroy,\n Input,\n Output,\n EventEmitter,\n ChangeDetectorRef,\n ChangeDetectionStrategy\n} from '@angular/core';\nimport { Subject, Observable, combineLatest, BehaviorSubject } from 'rxjs';\nimport { takeUntil, map, shareReplay } from 'rxjs/operators';\nimport {\n TestingInstrumentationService,\n FeedbackPending,\n FeedbackStats,\n TestRunWithFeedbackSummary,\n EvaluationSummaryMetrics\n} from '../services/testing-instrumentation.service';\n\ntype ViewMode = 'queue' | 'history';\ntype HistorySort = 'date' | 'rating' | 'test-name';\n\ninterface ReviewFormState {\n rating: number | null;\n isCorrect: boolean | null;\n comments: string;\n}\n\n@Component({\n standalone: false,\n selector: 'app-testing-review',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <!-- Page Header -->\n <div class=\"review-page\">\n <div class=\"page-header\">\n <div class=\"header-left\">\n <h2>\n <i class=\"fa-solid fa-clipboard-check\"></i>\n Human Review\n </h2>\n @if (PendingCount > 0) {\n <div class=\"pending-badge\">\n <span class=\"badge-count\">{{ PendingCount }}</span>\n <span class=\"badge-text\">pending</span>\n </div>\n }\n </div>\n <button class=\"refresh-btn\" (click)=\"Refresh()\" [disabled]=\"IsRefreshing\">\n <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"IsRefreshing\"></i>\n {{ IsRefreshing ? 'Refreshing...' : 'Refresh' }}\n </button>\n </div>\n\n <!-- KPI Summary Row -->\n @if (Metrics) {\n <div class=\"kpi-row\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon orange\">\n <i class=\"fa-solid fa-hourglass-half\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ Metrics.humanPendingCount }}</div>\n <div class=\"kpi-label\">Pending Review</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon green\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ Metrics.humanReviewedCount }}</div>\n <div class=\"kpi-label\">Reviewed</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon gold\">\n <i class=\"fa-solid fa-star\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ FormatDecimal(Metrics.humanAvgRating, 1) }}<span class=\"kpi-unit\">/10</span></div>\n <div class=\"kpi-label\">Avg Rating</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon blue\">\n <i class=\"fa-solid fa-handshake\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ FormatDecimal(Metrics.agreementRate, 0) }}<span class=\"kpi-unit\">%</span></div>\n <div class=\"kpi-label\">Agreement Rate</div>\n </div>\n </div>\n </div>\n }\n\n <!-- View Mode Toggle -->\n <div class=\"view-toggle-bar\">\n <div class=\"toggle-group\">\n <button class=\"toggle-btn\" [class.active]=\"CurrentView === 'queue'\" (click)=\"SetView('queue')\">\n <i class=\"fa-solid fa-list-check\"></i>\n Review Queue\n </button>\n <button class=\"toggle-btn\" [class.active]=\"CurrentView === 'history'\" (click)=\"SetView('history')\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n History\n </button>\n </div>\n </div>\n\n <!-- Review Queue View -->\n @if (CurrentView === 'queue') {\n <div class=\"content-card\">\n @if (PendingItems.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-circle-check\"></i>\n <h3>All caught up!</h3>\n <p>No tests currently require human review.</p>\n </div>\n } @else {\n <div class=\"queue-list\">\n @for (item of PendingItems; track item.testRunID) {\n <div class=\"queue-item\" [class.expanded]=\"ExpandedItemId === item.testRunID\">\n <div class=\"queue-item-header\" (click)=\"ToggleExpand(item.testRunID)\">\n <div class=\"item-info\">\n <div class=\"item-name\">{{ item.testName }}</div>\n <div class=\"item-meta\">\n <span class=\"meta-time\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ FormatRelativeTime(item.runDateTime) }}\n </span>\n <app-score-indicator [score]=\"item.automatedScore\" [showBar]=\"true\"></app-score-indicator>\n <app-test-status-badge [status]=\"$any(item.automatedStatus)\"></app-test-status-badge>\n </div>\n </div>\n <div class=\"item-actions-area\">\n <span class=\"reason-badge\" [class]=\"'reason-' + item.reason\">\n @if (item.reason === 'no-feedback') {\n <i class=\"fa-solid fa-comment-slash\"></i> No Feedback\n } @else if (item.reason === 'high-score-failed') {\n <i class=\"fa-solid fa-triangle-exclamation\"></i> Score Mismatch\n } @else {\n <i class=\"fa-solid fa-circle-question\"></i> Needs Verification\n }\n </span>\n <button class=\"expand-toggle\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"ExpandedItemId !== item.testRunID\"\n [class.fa-chevron-up]=\"ExpandedItemId === item.testRunID\"></i>\n </button>\n </div>\n </div>\n\n @if (ExpandedItemId === item.testRunID) {\n <div class=\"review-form-panel\">\n <!-- Rating -->\n <div class=\"form-section\">\n <label class=\"form-label\">Rating</label>\n <div class=\"rating-row\">\n @for (n of RatingNumbers; track n) {\n <button class=\"rating-circle\"\n [class.selected]=\"FormState.rating != null && n <= FormState.rating\"\n [class.current]=\"FormState.rating === n\"\n (click)=\"SelectRating(n)\">\n {{ n }}\n </button>\n }\n @if (FormState.rating != null) {\n <span class=\"rating-display\">{{ FormState.rating }}/10</span>\n }\n </div>\n </div>\n\n <!-- Correctness -->\n <div class=\"form-section\">\n <label class=\"form-label\">Is the automated result correct?</label>\n <div class=\"correctness-row\">\n <button class=\"correctness-btn correct\"\n [class.active]=\"FormState.isCorrect === true\"\n (click)=\"SelectCorrectness(true)\">\n <i class=\"fa-solid fa-check\"></i> Correct\n </button>\n <button class=\"correctness-btn incorrect\"\n [class.active]=\"FormState.isCorrect === false\"\n (click)=\"SelectCorrectness(false)\">\n <i class=\"fa-solid fa-xmark\"></i> Incorrect\n </button>\n </div>\n </div>\n\n <!-- Notes -->\n <div class=\"form-section\">\n <label class=\"form-label\">Notes (optional)</label>\n <textarea class=\"notes-textarea\"\n rows=\"3\"\n placeholder=\"Add any comments about this evaluation...\"\n [value]=\"FormState.comments\"\n (input)=\"OnCommentsChange($event)\"></textarea>\n </div>\n\n <!-- Actions -->\n <div class=\"form-actions\">\n <button class=\"submit-btn\"\n [disabled]=\"!IsFormValid || IsSubmitting\"\n (click)=\"SubmitReview(item)\">\n <i class=\"fa-solid fa-paper-plane\"></i>\n {{ IsSubmitting ? 'Submitting...' : 'Submit' }}\n </button>\n <button class=\"skip-btn\" (click)=\"SkipItem()\">\n <i class=\"fa-solid fa-forward\"></i> Skip\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- History View -->\n @if (CurrentView === 'history') {\n <div class=\"content-card\">\n <!-- Filter Bar -->\n <div class=\"history-filters\">\n <div class=\"search-wrapper\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Search by test name...\"\n [value]=\"HistorySearchText\"\n (input)=\"OnHistorySearch($event)\" />\n </div>\n <div class=\"sort-control\">\n <label>Sort by:</label>\n <select [value]=\"HistorySortField\" (change)=\"OnHistorySortChange($event)\">\n <option value=\"date\">Date</option>\n <option value=\"rating\">Rating</option>\n <option value=\"test-name\">Test Name</option>\n </select>\n </div>\n </div>\n\n @if (FilteredHistoryItems.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-folder-open\"></i>\n <h3>No reviewed items</h3>\n <p>Reviewed tests will appear here once feedback is submitted.</p>\n </div>\n } @else {\n <div class=\"history-list\">\n @for (item of FilteredHistoryItems; track item.id) {\n <div class=\"history-item\">\n <div class=\"history-item-main\">\n <div class=\"history-name\">{{ item.testName }}</div>\n <div class=\"history-date\">\n <i class=\"fa-solid fa-calendar\"></i>\n {{ FormatRelativeTime(item.runDateTime) }}\n </div>\n </div>\n <div class=\"history-rating\">\n <div class=\"rating-dots\">\n @for (n of RatingNumbers; track n) {\n <span class=\"rating-dot\" [class.filled]=\"item.humanRating != null && n <= item.humanRating\"></span>\n }\n </div>\n <span class=\"rating-label\">{{ item.humanRating ?? 0 }}/10</span>\n </div>\n <div class=\"history-verdict\">\n @if (item.humanIsCorrect === true) {\n <span class=\"verdict correct\">\n <i class=\"fa-solid fa-check\"></i> Correct\n </span>\n } @else if (item.humanIsCorrect === false) {\n <span class=\"verdict incorrect\">\n <i class=\"fa-solid fa-xmark\"></i> Incorrect\n </span>\n }\n </div>\n <div class=\"history-auto-score\">\n <app-score-indicator [score]=\"item.score\" [showBar]=\"true\"></app-score-indicator>\n </div>\n @if (item.humanComments) {\n <div class=\"history-comments\"\n [class.expanded]=\"ExpandedHistoryId === item.id\"\n (click)=\"ToggleHistoryComment(item.id)\">\n <p>{{ item.humanComments }}</p>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Calibration Insights -->\n <div class=\"calibration-section\">\n <h3>\n <i class=\"fa-solid fa-scale-balanced\"></i>\n Human vs Auto Agreement\n </h3>\n <div class=\"calibration-body\">\n <div class=\"gauge-display\">\n <div class=\"gauge-ring\">\n <svg viewBox=\"0 0 120 120\" class=\"gauge-svg\">\n <circle cx=\"60\" cy=\"60\" r=\"52\" fill=\"none\" stroke=\"#e2e8f0\" stroke-width=\"10\" />\n <circle cx=\"60\" cy=\"60\" r=\"52\" fill=\"none\"\n [attr.stroke]=\"AgreementColor\"\n stroke-width=\"10\"\n stroke-linecap=\"round\"\n [attr.stroke-dasharray]=\"AgreementDash\"\n stroke-dashoffset=\"0\"\n transform=\"rotate(-90 60 60)\" />\n </svg>\n <div class=\"gauge-value\">{{ FormatDecimal(AgreementRate, 0) }}%</div>\n </div>\n </div>\n <div class=\"calibration-text\">\n <p class=\"calibration-description\">\n Measures how often human reviewers agree with automated evaluation scores.\n </p>\n @if (AgreementRate < 70) {\n <div class=\"calibration-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n Low agreement may indicate evaluation criteria need refinement.\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n `,\n styles: [`\n :host {\n display: block;\n height: 100%;\n }\n\n .review-page {\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 /* Page Header */\n .page-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 .refresh-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 .refresh-btn:hover:not(:disabled) {\n background: #f8fafc;\n border-color: #cbd5e1;\n }\n\n .refresh-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n /* KPI Row */\n .kpi-row {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 20px;\n }\n\n .kpi-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 }\n\n .kpi-icon {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 20px;\n color: white;\n flex-shrink: 0;\n }\n\n .kpi-icon.orange { background: linear-gradient(135deg, #f97316 0%, #ea580c 100%); }\n .kpi-icon.green { background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%); }\n .kpi-icon.gold { background: linear-gradient(135deg, #eab308 0%, #ca8a04 100%); }\n .kpi-icon.blue { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); }\n\n .kpi-content {\n flex: 1;\n min-width: 0;\n }\n\n .kpi-value {\n font-size: 26px;\n font-weight: 700;\n color: #1e293b;\n line-height: 1;\n margin-bottom: 4px;\n }\n\n .kpi-unit {\n font-size: 14px;\n font-weight: 500;\n color: #64748b;\n }\n\n .kpi-label {\n font-size: 11px;\n color: #64748b;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n /* View Toggle */\n .view-toggle-bar {\n margin-bottom: 20px;\n }\n\n .toggle-group {\n display: inline-flex;\n background: white;\n border-radius: 10px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n }\n\n .toggle-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 24px;\n border: none;\n background: white;\n color: #64748b;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .toggle-btn:hover:not(.active) {\n background: #f8fafc;\n }\n\n .toggle-btn.active {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n /* Content Card */\n .content-card {\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 /* Queue List */\n .queue-list {\n max-height: 600px;\n overflow-y: auto;\n }\n\n .queue-item {\n border-bottom: 1px solid #f1f5f9;\n transition: background 0.2s ease;\n }\n\n .queue-item.expanded {\n background: #f8fafc;\n }\n\n .queue-item:last-child {\n border-bottom: none;\n }\n\n .queue-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 .queue-item-header:hover {\n background: rgba(59, 130, 246, 0.04);\n }\n\n .item-info {\n flex: 1;\n min-width: 0;\n }\n\n .item-name {\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: 14px;\n font-size: 12px;\n color: #64748b;\n align-items: center;\n flex-wrap: wrap;\n }\n\n .meta-time {\n display: flex;\n align-items: center;\n gap: 5px;\n }\n\n .item-actions-area {\n display: flex;\n align-items: center;\n gap: 12px;\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-no-feedback {\n background: #dbeafe;\n color: #1e40af;\n }\n\n .reason-high-score-failed {\n background: #ffedd5;\n color: #c2410c;\n }\n\n .reason-low-score-passed {\n background: #fef9c3;\n color: #a16207;\n }\n\n .expand-toggle {\n background: none;\n border: none;\n color: #94a3b8;\n cursor: pointer;\n padding: 8px;\n border-radius: 6px;\n font-size: 14px;\n transition: all 0.2s ease;\n }\n\n .expand-toggle:hover {\n background: #e2e8f0;\n color: #64748b;\n }\n\n /* Review Form */\n .review-form-panel {\n padding: 20px 20px 20px 36px;\n border-top: 1px solid #e2e8f0;\n background: white;\n }\n\n .form-section {\n margin-bottom: 20px;\n }\n\n .form-section:last-of-type {\n margin-bottom: 16px;\n }\n\n .form-label {\n display: block;\n font-size: 12px;\n font-weight: 700;\n color: #475569;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 10px;\n }\n\n /* Rating Circles */\n .rating-row {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .rating-circle {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: 2px solid #e2e8f0;\n background: white;\n color: #94a3b8;\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.15s ease;\n }\n\n .rating-circle:hover {\n border-color: #3b82f6;\n color: #3b82f6;\n transform: scale(1.1);\n }\n\n .rating-circle.selected {\n background: #3b82f6;\n border-color: #3b82f6;\n color: white;\n }\n\n .rating-circle.current {\n background: #2563eb;\n border-color: #1d4ed8;\n color: white;\n box-shadow: 0 2px 6px rgba(37, 99, 235, 0.35);\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 .correctness-row {\n display: flex;\n gap: 12px;\n }\n\n .correctness-btn {\n flex: 1;\n max-width: 200px;\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 color: #64748b;\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: #166534;\n }\n\n .correctness-btn.incorrect:hover,\n .correctness-btn.incorrect.active {\n border-color: #ef4444;\n background: #fef2f2;\n color: #991b1b;\n }\n\n /* Notes */\n .notes-textarea {\n width: 100%;\n max-width: 500px;\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: 72px;\n box-sizing: border-box;\n }\n\n .notes-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 .form-actions {\n display: flex;\n gap: 12px;\n }\n\n .submit-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 11px 22px;\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.5;\n cursor: not-allowed;\n }\n\n .skip-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 11px 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 .skip-btn:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n }\n\n /* History Filters */\n .history-filters {\n display: flex;\n gap: 16px;\n padding: 16px 20px;\n border-bottom: 1px solid #f1f5f9;\n align-items: center;\n }\n\n .search-wrapper {\n flex: 1;\n position: relative;\n display: flex;\n align-items: center;\n }\n\n .search-wrapper > i {\n position: absolute;\n left: 12px;\n color: #94a3b8;\n font-size: 13px;\n }\n\n .search-wrapper input {\n width: 100%;\n padding: 10px 12px 10px 36px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 13px;\n }\n\n .search-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 .sort-control {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #64748b;\n flex-shrink: 0;\n }\n\n .sort-control select {\n padding: 8px 12px;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n font-size: 12px;\n background: white;\n }\n\n /* History List */\n .history-list {\n max-height: 600px;\n overflow-y: auto;\n }\n\n .history-item {\n padding: 16px 20px;\n border-bottom: 1px solid #f1f5f9;\n display: flex;\n align-items: center;\n gap: 16px;\n flex-wrap: wrap;\n }\n\n .history-item:last-child {\n border-bottom: none;\n }\n\n .history-item-main {\n flex: 1;\n min-width: 160px;\n }\n\n .history-name {\n font-size: 14px;\n font-weight: 600;\n color: #1e293b;\n margin-bottom: 4px;\n }\n\n .history-date {\n font-size: 12px;\n color: #94a3b8;\n display: flex;\n align-items: center;\n gap: 5px;\n }\n\n .history-rating {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .rating-dots {\n display: flex;\n gap: 3px;\n }\n\n .rating-dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #e2e8f0;\n }\n\n .rating-dot.filled {\n background: #f59e0b;\n }\n\n .rating-label {\n font-size: 12px;\n font-weight: 600;\n color: #64748b;\n }\n\n .history-verdict {\n flex-shrink: 0;\n }\n\n .verdict {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border-radius: 14px;\n font-size: 11px;\n font-weight: 600;\n }\n\n .verdict.correct {\n background: #dcfce7;\n color: #166534;\n }\n\n .verdict.incorrect {\n background: #fee2e2;\n color: #991b1b;\n }\n\n .history-auto-score {\n flex-shrink: 0;\n }\n\n .history-comments {\n width: 100%;\n margin-top: 8px;\n padding: 10px 14px;\n background: #f8fafc;\n border-radius: 8px;\n border-left: 3px solid #3b82f6;\n cursor: pointer;\n }\n\n .history-comments p {\n margin: 0;\n font-size: 13px;\n color: #475569;\n line-height: 1.5;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .history-comments.expanded p {\n white-space: normal;\n }\n\n /* Empty State */\n .empty-state {\n padding: 60px 20px;\n text-align: center;\n }\n\n .empty-state i {\n font-size: 52px;\n margin-bottom: 16px;\n color: #22c55e;\n }\n\n .empty-state h3 {\n font-size: 18px;\n color: #1e293b;\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 /* Calibration Section */\n .calibration-section {\n background: white;\n padding: 24px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n\n .calibration-section 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 .calibration-section h3 i {\n color: #3b82f6;\n }\n\n .calibration-body {\n display: flex;\n align-items: center;\n gap: 32px;\n }\n\n .gauge-display {\n flex-shrink: 0;\n }\n\n .gauge-ring {\n position: relative;\n width: 120px;\n height: 120px;\n }\n\n .gauge-svg {\n width: 100%;\n height: 100%;\n }\n\n .gauge-value {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 24px;\n font-weight: 800;\n color: #1e293b;\n }\n\n .calibration-text {\n flex: 1;\n }\n\n .calibration-description {\n margin: 0 0 12px 0;\n font-size: 14px;\n color: #64748b;\n line-height: 1.6;\n }\n\n .calibration-warning {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: #fef3c7;\n border: 1px solid #fbbf24;\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n color: #92400e;\n }\n\n .calibration-warning i {\n color: #d97706;\n font-size: 16px;\n flex-shrink: 0;\n }\n\n /* Success toast animation */\n .queue-item {\n animation: fadeIn 0.2s ease;\n }\n\n @keyframes fadeIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n /* Responsive */\n @media (max-width: 1024px) {\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n }\n\n @media (max-width: 768px) {\n .review-page {\n padding: 16px;\n }\n\n .page-header {\n flex-direction: column;\n gap: 16px;\n align-items: flex-start;\n }\n\n .kpi-row {\n grid-template-columns: 1fr 1fr;\n }\n\n .kpi-card {\n padding: 16px;\n }\n\n .kpi-value {\n font-size: 22px;\n }\n\n .queue-item-header {\n flex-wrap: wrap;\n }\n\n .item-actions-area {\n width: 100%;\n justify-content: flex-end;\n margin-top: 8px;\n }\n\n .correctness-row {\n flex-direction: column;\n }\n\n .correctness-btn {\n max-width: 100%;\n }\n\n .history-item {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .calibration-body {\n flex-direction: column;\n align-items: center;\n text-align: center;\n }\n }\n `]\n})\nexport class TestingReviewComponent implements OnInit, OnDestroy {\n @Input() initialState: Record<string, unknown> | null = null;\n @Output() stateChange = new EventEmitter<Record<string, unknown>>();\n\n private destroy$ = new Subject<void>();\n\n // View state\n CurrentView: ViewMode = 'queue';\n ExpandedItemId: string | null = null;\n ExpandedHistoryId: string | null = null;\n IsRefreshing = false;\n IsSubmitting = false;\n HistorySearchText = '';\n HistorySortField: HistorySort = 'date';\n\n // Form state for active review\n FormState: ReviewFormState = { rating: null, isCorrect: null, comments: '' };\n\n // Data\n PendingItems: FeedbackPending[] = [];\n HistoryItems: TestRunWithFeedbackSummary[] = [];\n FilteredHistoryItems: TestRunWithFeedbackSummary[] = [];\n Metrics: EvaluationSummaryMetrics | null = null;\n PendingCount = 0;\n\n // Constants\n readonly RatingNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n\n constructor(\n private instrumentationService: TestingInstrumentationService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.restoreState();\n this.setupSubscriptions();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ------------------------------------------------------------------\n // Computed properties\n // ------------------------------------------------------------------\n\n get IsFormValid(): boolean {\n return this.FormState.rating != null && this.FormState.isCorrect != null;\n }\n\n get AgreementRate(): number {\n return this.Metrics?.agreementRate ?? 0;\n }\n\n get AgreementColor(): string {\n const rate = this.AgreementRate;\n if (rate >= 80) return '#22c55e';\n if (rate >= 60) return '#eab308';\n return '#ef4444';\n }\n\n get AgreementDash(): string {\n const circumference = 2 * Math.PI * 52; // r=52\n const filled = (this.AgreementRate / 100) * circumference;\n return `${filled} ${circumference}`;\n }\n\n // ------------------------------------------------------------------\n // Setup\n // ------------------------------------------------------------------\n\n private restoreState(): void {\n if (!this.initialState) return;\n const view = this.initialState['viewMode'] as string | undefined;\n if (view === 'queue' || view === 'history') {\n this.CurrentView = view;\n }\n }\n\n private setupSubscriptions(): void {\n this.instrumentationService.pendingFeedback$\n .pipe(takeUntil(this.destroy$))\n .subscribe(items => {\n this.PendingItems = items;\n this.PendingCount = items.length;\n this.cdr.markForCheck();\n });\n\n this.instrumentationService.evaluationMetrics$\n .pipe(takeUntil(this.destroy$))\n .subscribe(metrics => {\n this.Metrics = metrics;\n this.cdr.markForCheck();\n });\n\n this.instrumentationService.testRunsWithFeedback$\n .pipe(takeUntil(this.destroy$))\n .subscribe(runs => {\n this.HistoryItems = runs.filter(r => r.hasHumanFeedback);\n this.applyHistoryFilters();\n this.cdr.markForCheck();\n });\n }\n\n // ------------------------------------------------------------------\n // View toggling\n // ------------------------------------------------------------------\n\n SetView(mode: ViewMode): void {\n this.CurrentView = mode;\n this.ExpandedItemId = null;\n this.emitState();\n this.cdr.markForCheck();\n }\n\n // ------------------------------------------------------------------\n // Queue interactions\n // ------------------------------------------------------------------\n\n ToggleExpand(testRunID: string): void {\n if (this.ExpandedItemId === testRunID) {\n this.ExpandedItemId = null;\n } else {\n this.ExpandedItemId = testRunID;\n this.resetForm();\n }\n this.cdr.markForCheck();\n }\n\n SelectRating(n: number): void {\n this.FormState = { ...this.FormState, rating: n };\n this.cdr.markForCheck();\n }\n\n SelectCorrectness(value: boolean): void {\n this.FormState = { ...this.FormState, isCorrect: value };\n this.cdr.markForCheck();\n }\n\n OnCommentsChange(event: Event): void {\n const target = event.target as HTMLTextAreaElement;\n this.FormState = { ...this.FormState, comments: target.value };\n }\n\n async SubmitReview(item: FeedbackPending): Promise<void> {\n if (!this.IsFormValid || this.IsSubmitting) return;\n\n this.IsSubmitting = true;\n this.cdr.markForCheck();\n\n try {\n const success = await this.instrumentationService.submitFeedback(\n item.testRunID,\n this.FormState.rating!,\n this.FormState.isCorrect!,\n this.FormState.comments\n );\n\n if (success) {\n this.ExpandedItemId = null;\n this.resetForm();\n }\n } finally {\n this.IsSubmitting = false;\n this.cdr.markForCheck();\n }\n }\n\n SkipItem(): void {\n const currentIndex = this.PendingItems.findIndex(\n i => i.testRunID === this.ExpandedItemId\n );\n this.ExpandedItemId = null;\n this.resetForm();\n\n // Expand the next item if available\n if (currentIndex >= 0 && currentIndex + 1 < this.PendingItems.length) {\n this.ExpandedItemId = this.PendingItems[currentIndex + 1].testRunID;\n }\n this.cdr.markForCheck();\n }\n\n // ------------------------------------------------------------------\n // History interactions\n // ------------------------------------------------------------------\n\n OnHistorySearch(event: Event): void {\n const target = event.target as HTMLInputElement;\n this.HistorySearchText = target.value;\n this.applyHistoryFilters();\n this.cdr.markForCheck();\n }\n\n OnHistorySortChange(event: Event): void {\n const target = event.target as HTMLSelectElement;\n this.HistorySortField = target.value as HistorySort;\n this.applyHistoryFilters();\n this.cdr.markForCheck();\n }\n\n ToggleHistoryComment(id: string): void {\n this.ExpandedHistoryId = this.ExpandedHistoryId === id ? null : id;\n this.cdr.markForCheck();\n }\n\n // ------------------------------------------------------------------\n // Refresh\n // ------------------------------------------------------------------\n\n Refresh(): void {\n this.IsRefreshing = true;\n this.cdr.markForCheck();\n this.instrumentationService.refresh();\n\n setTimeout(() => {\n this.IsRefreshing = false;\n this.cdr.markForCheck();\n }, 1500);\n }\n\n // ------------------------------------------------------------------\n // Formatting helpers\n // ------------------------------------------------------------------\n\n FormatDecimal(value: number | undefined | null, decimals: number): string {\n if (value == null) return '0';\n return value.toFixed(decimals);\n }\n\n FormatRelativeTime(date: Date): string {\n const now = Date.now();\n const then = date instanceof Date ? date.getTime() : new Date(date).getTime();\n const diffMs = now - then;\n const diffMin = Math.floor(diffMs / 60000);\n\n if (diffMin < 1) return 'just now';\n if (diffMin < 60) return `${diffMin}m ago`;\n\n const diffHours = Math.floor(diffMin / 60);\n if (diffHours < 24) return `${diffHours}h ago`;\n\n const diffDays = Math.floor(diffHours / 24);\n if (diffDays < 7) return `${diffDays}d ago`;\n\n const diffWeeks = Math.floor(diffDays / 7);\n if (diffWeeks < 4) return `${diffWeeks}w ago`;\n\n const diffMonths = Math.floor(diffDays / 30);\n return `${diffMonths}mo ago`;\n }\n\n // ------------------------------------------------------------------\n // Private helpers\n // ------------------------------------------------------------------\n\n private resetForm(): void {\n this.FormState = { rating: null, isCorrect: null, comments: '' };\n }\n\n private applyHistoryFilters(): void {\n let items = [...this.HistoryItems];\n\n // Search filter\n if (this.HistorySearchText) {\n const term = this.HistorySearchText.toLowerCase();\n items = items.filter(i => i.testName.toLowerCase().includes(term));\n }\n\n // Sort\n items.sort((a, b) => {\n switch (this.HistorySortField) {\n case 'date':\n return b.runDateTime.getTime() - a.runDateTime.getTime();\n case 'rating':\n return (b.humanRating ?? 0) - (a.humanRating ?? 0);\n case 'test-name':\n return a.testName.localeCompare(b.testName);\n default:\n return 0;\n }\n });\n\n this.FilteredHistoryItems = items;\n }\n\n private emitState(): void {\n this.stateChange.emit({ viewMode: this.CurrentView });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"testing-review.component.js","sourceRoot":"","sources":["../../../src/Testing/components/testing-review.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n OnInit,\n OnDestroy,\n Input,\n Output,\n EventEmitter,\n ChangeDetectorRef,\n ChangeDetectionStrategy\n} from '@angular/core';\nimport { Subject, Observable, combineLatest, BehaviorSubject } from 'rxjs';\nimport { takeUntil, map, shareReplay } from 'rxjs/operators';\nimport {\n TestingInstrumentationService,\n FeedbackPending,\n FeedbackStats,\n TestRunWithFeedbackSummary,\n EvaluationSummaryMetrics\n} from '../services/testing-instrumentation.service';\nimport { UUIDsEqual } from '@memberjunction/global';\n\ntype ViewMode = 'queue' | 'history';\ntype HistorySort = 'date' | 'rating' | 'test-name';\n\ninterface ReviewFormState {\n rating: number | null;\n isCorrect: boolean | null;\n comments: string;\n}\n\n@Component({\n standalone: false,\n selector: 'app-testing-review',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <!-- Page Header -->\n <div class=\"review-page\">\n <div class=\"page-header\">\n <div class=\"header-left\">\n <h2>\n <i class=\"fa-solid fa-clipboard-check\"></i>\n Human Review\n </h2>\n @if (PendingCount > 0) {\n <div class=\"pending-badge\">\n <span class=\"badge-count\">{{ PendingCount }}</span>\n <span class=\"badge-text\">pending</span>\n </div>\n }\n </div>\n <button class=\"refresh-btn\" (click)=\"Refresh()\" [disabled]=\"IsRefreshing\">\n <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"IsRefreshing\"></i>\n {{ IsRefreshing ? 'Refreshing...' : 'Refresh' }}\n </button>\n </div>\n\n <!-- KPI Summary Row -->\n @if (Metrics) {\n <div class=\"kpi-row\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon orange\">\n <i class=\"fa-solid fa-hourglass-half\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ Metrics.humanPendingCount }}</div>\n <div class=\"kpi-label\">Pending Review</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon green\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ Metrics.humanReviewedCount }}</div>\n <div class=\"kpi-label\">Reviewed</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon gold\">\n <i class=\"fa-solid fa-star\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ FormatDecimal(Metrics.humanAvgRating, 1) }}<span class=\"kpi-unit\">/10</span></div>\n <div class=\"kpi-label\">Avg Rating</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon blue\">\n <i class=\"fa-solid fa-handshake\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ FormatDecimal(Metrics.agreementRate, 0) }}<span class=\"kpi-unit\">%</span></div>\n <div class=\"kpi-label\">Agreement Rate</div>\n </div>\n </div>\n </div>\n }\n\n <!-- View Mode Toggle -->\n <div class=\"view-toggle-bar\">\n <div class=\"toggle-group\">\n <button class=\"toggle-btn\" [class.active]=\"CurrentView === 'queue'\" (click)=\"SetView('queue')\">\n <i class=\"fa-solid fa-list-check\"></i>\n Review Queue\n </button>\n <button class=\"toggle-btn\" [class.active]=\"CurrentView === 'history'\" (click)=\"SetView('history')\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n History\n </button>\n </div>\n </div>\n\n <!-- Review Queue View -->\n @if (CurrentView === 'queue') {\n <div class=\"content-card\">\n @if (PendingItems.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-circle-check\"></i>\n <h3>All caught up!</h3>\n <p>No tests currently require human review.</p>\n </div>\n } @else {\n <div class=\"queue-list\">\n @for (item of PendingItems; track item.testRunID) {\n <div class=\"queue-item\" [class.expanded]=\"IsItemExpanded(item.testRunID)\">\n <div class=\"queue-item-header\" (click)=\"ToggleExpand(item.testRunID)\">\n <div class=\"item-info\">\n <div class=\"item-name\">{{ item.testName }}</div>\n <div class=\"item-meta\">\n <span class=\"meta-time\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ FormatRelativeTime(item.runDateTime) }}\n </span>\n <app-score-indicator [score]=\"item.automatedScore\" [showBar]=\"true\"></app-score-indicator>\n <app-test-status-badge [status]=\"$any(item.automatedStatus)\"></app-test-status-badge>\n </div>\n </div>\n <div class=\"item-actions-area\">\n <span class=\"reason-badge\" [class]=\"'reason-' + item.reason\">\n @if (item.reason === 'no-feedback') {\n <i class=\"fa-solid fa-comment-slash\"></i> No Feedback\n } @else if (item.reason === 'high-score-failed') {\n <i class=\"fa-solid fa-triangle-exclamation\"></i> Score Mismatch\n } @else {\n <i class=\"fa-solid fa-circle-question\"></i> Needs Verification\n }\n </span>\n <button class=\"expand-toggle\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!IsItemExpanded(item.testRunID)\"\n [class.fa-chevron-up]=\"IsItemExpanded(item.testRunID)\"></i>\n </button>\n </div>\n </div>\n\n @if (IsItemExpanded(item.testRunID)) {\n <div class=\"review-form-panel\">\n <!-- Rating -->\n <div class=\"form-section\">\n <label class=\"form-label\">Rating</label>\n <div class=\"rating-row\">\n @for (n of RatingNumbers; track n) {\n <button class=\"rating-circle\"\n [class.selected]=\"FormState.rating != null && n <= FormState.rating\"\n [class.current]=\"FormState.rating === n\"\n (click)=\"SelectRating(n)\">\n {{ n }}\n </button>\n }\n @if (FormState.rating != null) {\n <span class=\"rating-display\">{{ FormState.rating }}/10</span>\n }\n </div>\n </div>\n\n <!-- Correctness -->\n <div class=\"form-section\">\n <label class=\"form-label\">Is the automated result correct?</label>\n <div class=\"correctness-row\">\n <button class=\"correctness-btn correct\"\n [class.active]=\"FormState.isCorrect === true\"\n (click)=\"SelectCorrectness(true)\">\n <i class=\"fa-solid fa-check\"></i> Correct\n </button>\n <button class=\"correctness-btn incorrect\"\n [class.active]=\"FormState.isCorrect === false\"\n (click)=\"SelectCorrectness(false)\">\n <i class=\"fa-solid fa-xmark\"></i> Incorrect\n </button>\n </div>\n </div>\n\n <!-- Notes -->\n <div class=\"form-section\">\n <label class=\"form-label\">Notes (optional)</label>\n <textarea class=\"notes-textarea\"\n rows=\"3\"\n placeholder=\"Add any comments about this evaluation...\"\n [value]=\"FormState.comments\"\n (input)=\"OnCommentsChange($event)\"></textarea>\n </div>\n\n <!-- Actions -->\n <div class=\"form-actions\">\n <button class=\"submit-btn\"\n [disabled]=\"!IsFormValid || IsSubmitting\"\n (click)=\"SubmitReview(item)\">\n <i class=\"fa-solid fa-paper-plane\"></i>\n {{ IsSubmitting ? 'Submitting...' : 'Submit' }}\n </button>\n <button class=\"skip-btn\" (click)=\"SkipItem()\">\n <i class=\"fa-solid fa-forward\"></i> Skip\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- History View -->\n @if (CurrentView === 'history') {\n <div class=\"content-card\">\n <!-- Filter Bar -->\n <div class=\"history-filters\">\n <div class=\"search-wrapper\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Search by test name...\"\n [value]=\"HistorySearchText\"\n (input)=\"OnHistorySearch($event)\" />\n </div>\n <div class=\"sort-control\">\n <label>Sort by:</label>\n <select [value]=\"HistorySortField\" (change)=\"OnHistorySortChange($event)\">\n <option value=\"date\">Date</option>\n <option value=\"rating\">Rating</option>\n <option value=\"test-name\">Test Name</option>\n </select>\n </div>\n </div>\n\n @if (FilteredHistoryItems.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-folder-open\"></i>\n <h3>No reviewed items</h3>\n <p>Reviewed tests will appear here once feedback is submitted.</p>\n </div>\n } @else {\n <div class=\"history-list\">\n @for (item of FilteredHistoryItems; track item.id) {\n <div class=\"history-item\">\n <div class=\"history-item-main\">\n <div class=\"history-name\">{{ item.testName }}</div>\n <div class=\"history-date\">\n <i class=\"fa-solid fa-calendar\"></i>\n {{ FormatRelativeTime(item.runDateTime) }}\n </div>\n </div>\n <div class=\"history-rating\">\n <div class=\"rating-dots\">\n @for (n of RatingNumbers; track n) {\n <span class=\"rating-dot\" [class.filled]=\"item.humanRating != null && n <= item.humanRating\"></span>\n }\n </div>\n <span class=\"rating-label\">{{ item.humanRating ?? 0 }}/10</span>\n </div>\n <div class=\"history-verdict\">\n @if (item.humanIsCorrect === true) {\n <span class=\"verdict correct\">\n <i class=\"fa-solid fa-check\"></i> Correct\n </span>\n } @else if (item.humanIsCorrect === false) {\n <span class=\"verdict incorrect\">\n <i class=\"fa-solid fa-xmark\"></i> Incorrect\n </span>\n }\n </div>\n <div class=\"history-auto-score\">\n <app-score-indicator [score]=\"item.score\" [showBar]=\"true\"></app-score-indicator>\n </div>\n @if (item.humanComments) {\n <div class=\"history-comments\"\n [class.expanded]=\"ExpandedHistoryId === item.id\"\n (click)=\"ToggleHistoryComment(item.id)\">\n <p>{{ item.humanComments }}</p>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Calibration Insights -->\n <div class=\"calibration-section\">\n <h3>\n <i class=\"fa-solid fa-scale-balanced\"></i>\n Human vs Auto Agreement\n </h3>\n <div class=\"calibration-body\">\n <div class=\"gauge-display\">\n <div class=\"gauge-ring\">\n <svg viewBox=\"0 0 120 120\" class=\"gauge-svg\">\n <circle cx=\"60\" cy=\"60\" r=\"52\" fill=\"none\" stroke=\"#e2e8f0\" stroke-width=\"10\" />\n <circle cx=\"60\" cy=\"60\" r=\"52\" fill=\"none\"\n [attr.stroke]=\"AgreementColor\"\n stroke-width=\"10\"\n stroke-linecap=\"round\"\n [attr.stroke-dasharray]=\"AgreementDash\"\n stroke-dashoffset=\"0\"\n transform=\"rotate(-90 60 60)\" />\n </svg>\n <div class=\"gauge-value\">{{ FormatDecimal(AgreementRate, 0) }}%</div>\n </div>\n </div>\n <div class=\"calibration-text\">\n <p class=\"calibration-description\">\n Measures how often human reviewers agree with automated evaluation scores.\n </p>\n @if (AgreementRate < 70) {\n <div class=\"calibration-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n Low agreement may indicate evaluation criteria need refinement.\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n `,\n styles: [`\n :host {\n display: block;\n height: 100%;\n }\n\n .review-page {\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 /* Page Header */\n .page-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 .refresh-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 .refresh-btn:hover:not(:disabled) {\n background: #f8fafc;\n border-color: #cbd5e1;\n }\n\n .refresh-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n /* KPI Row */\n .kpi-row {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 20px;\n }\n\n .kpi-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 }\n\n .kpi-icon {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 20px;\n color: white;\n flex-shrink: 0;\n }\n\n .kpi-icon.orange { background: linear-gradient(135deg, #f97316 0%, #ea580c 100%); }\n .kpi-icon.green { background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%); }\n .kpi-icon.gold { background: linear-gradient(135deg, #eab308 0%, #ca8a04 100%); }\n .kpi-icon.blue { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); }\n\n .kpi-content {\n flex: 1;\n min-width: 0;\n }\n\n .kpi-value {\n font-size: 26px;\n font-weight: 700;\n color: #1e293b;\n line-height: 1;\n margin-bottom: 4px;\n }\n\n .kpi-unit {\n font-size: 14px;\n font-weight: 500;\n color: #64748b;\n }\n\n .kpi-label {\n font-size: 11px;\n color: #64748b;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n /* View Toggle */\n .view-toggle-bar {\n margin-bottom: 20px;\n }\n\n .toggle-group {\n display: inline-flex;\n background: white;\n border-radius: 10px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n }\n\n .toggle-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 24px;\n border: none;\n background: white;\n color: #64748b;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .toggle-btn:hover:not(.active) {\n background: #f8fafc;\n }\n\n .toggle-btn.active {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n /* Content Card */\n .content-card {\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 /* Queue List */\n .queue-list {\n max-height: 600px;\n overflow-y: auto;\n }\n\n .queue-item {\n border-bottom: 1px solid #f1f5f9;\n transition: background 0.2s ease;\n }\n\n .queue-item.expanded {\n background: #f8fafc;\n }\n\n .queue-item:last-child {\n border-bottom: none;\n }\n\n .queue-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 .queue-item-header:hover {\n background: rgba(59, 130, 246, 0.04);\n }\n\n .item-info {\n flex: 1;\n min-width: 0;\n }\n\n .item-name {\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: 14px;\n font-size: 12px;\n color: #64748b;\n align-items: center;\n flex-wrap: wrap;\n }\n\n .meta-time {\n display: flex;\n align-items: center;\n gap: 5px;\n }\n\n .item-actions-area {\n display: flex;\n align-items: center;\n gap: 12px;\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-no-feedback {\n background: #dbeafe;\n color: #1e40af;\n }\n\n .reason-high-score-failed {\n background: #ffedd5;\n color: #c2410c;\n }\n\n .reason-low-score-passed {\n background: #fef9c3;\n color: #a16207;\n }\n\n .expand-toggle {\n background: none;\n border: none;\n color: #94a3b8;\n cursor: pointer;\n padding: 8px;\n border-radius: 6px;\n font-size: 14px;\n transition: all 0.2s ease;\n }\n\n .expand-toggle:hover {\n background: #e2e8f0;\n color: #64748b;\n }\n\n /* Review Form */\n .review-form-panel {\n padding: 20px 20px 20px 36px;\n border-top: 1px solid #e2e8f0;\n background: white;\n }\n\n .form-section {\n margin-bottom: 20px;\n }\n\n .form-section:last-of-type {\n margin-bottom: 16px;\n }\n\n .form-label {\n display: block;\n font-size: 12px;\n font-weight: 700;\n color: #475569;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 10px;\n }\n\n /* Rating Circles */\n .rating-row {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .rating-circle {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: 2px solid #e2e8f0;\n background: white;\n color: #94a3b8;\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.15s ease;\n }\n\n .rating-circle:hover {\n border-color: #3b82f6;\n color: #3b82f6;\n transform: scale(1.1);\n }\n\n .rating-circle.selected {\n background: #3b82f6;\n border-color: #3b82f6;\n color: white;\n }\n\n .rating-circle.current {\n background: #2563eb;\n border-color: #1d4ed8;\n color: white;\n box-shadow: 0 2px 6px rgba(37, 99, 235, 0.35);\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 .correctness-row {\n display: flex;\n gap: 12px;\n }\n\n .correctness-btn {\n flex: 1;\n max-width: 200px;\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 color: #64748b;\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: #166534;\n }\n\n .correctness-btn.incorrect:hover,\n .correctness-btn.incorrect.active {\n border-color: #ef4444;\n background: #fef2f2;\n color: #991b1b;\n }\n\n /* Notes */\n .notes-textarea {\n width: 100%;\n max-width: 500px;\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: 72px;\n box-sizing: border-box;\n }\n\n .notes-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 .form-actions {\n display: flex;\n gap: 12px;\n }\n\n .submit-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 11px 22px;\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.5;\n cursor: not-allowed;\n }\n\n .skip-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 11px 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 .skip-btn:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n }\n\n /* History Filters */\n .history-filters {\n display: flex;\n gap: 16px;\n padding: 16px 20px;\n border-bottom: 1px solid #f1f5f9;\n align-items: center;\n }\n\n .search-wrapper {\n flex: 1;\n position: relative;\n display: flex;\n align-items: center;\n }\n\n .search-wrapper > i {\n position: absolute;\n left: 12px;\n color: #94a3b8;\n font-size: 13px;\n }\n\n .search-wrapper input {\n width: 100%;\n padding: 10px 12px 10px 36px;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 13px;\n }\n\n .search-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 .sort-control {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #64748b;\n flex-shrink: 0;\n }\n\n .sort-control select {\n padding: 8px 12px;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n font-size: 12px;\n background: white;\n }\n\n /* History List */\n .history-list {\n max-height: 600px;\n overflow-y: auto;\n }\n\n .history-item {\n padding: 16px 20px;\n border-bottom: 1px solid #f1f5f9;\n display: flex;\n align-items: center;\n gap: 16px;\n flex-wrap: wrap;\n }\n\n .history-item:last-child {\n border-bottom: none;\n }\n\n .history-item-main {\n flex: 1;\n min-width: 160px;\n }\n\n .history-name {\n font-size: 14px;\n font-weight: 600;\n color: #1e293b;\n margin-bottom: 4px;\n }\n\n .history-date {\n font-size: 12px;\n color: #94a3b8;\n display: flex;\n align-items: center;\n gap: 5px;\n }\n\n .history-rating {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .rating-dots {\n display: flex;\n gap: 3px;\n }\n\n .rating-dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #e2e8f0;\n }\n\n .rating-dot.filled {\n background: #f59e0b;\n }\n\n .rating-label {\n font-size: 12px;\n font-weight: 600;\n color: #64748b;\n }\n\n .history-verdict {\n flex-shrink: 0;\n }\n\n .verdict {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border-radius: 14px;\n font-size: 11px;\n font-weight: 600;\n }\n\n .verdict.correct {\n background: #dcfce7;\n color: #166534;\n }\n\n .verdict.incorrect {\n background: #fee2e2;\n color: #991b1b;\n }\n\n .history-auto-score {\n flex-shrink: 0;\n }\n\n .history-comments {\n width: 100%;\n margin-top: 8px;\n padding: 10px 14px;\n background: #f8fafc;\n border-radius: 8px;\n border-left: 3px solid #3b82f6;\n cursor: pointer;\n }\n\n .history-comments p {\n margin: 0;\n font-size: 13px;\n color: #475569;\n line-height: 1.5;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .history-comments.expanded p {\n white-space: normal;\n }\n\n /* Empty State */\n .empty-state {\n padding: 60px 20px;\n text-align: center;\n }\n\n .empty-state i {\n font-size: 52px;\n margin-bottom: 16px;\n color: #22c55e;\n }\n\n .empty-state h3 {\n font-size: 18px;\n color: #1e293b;\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 /* Calibration Section */\n .calibration-section {\n background: white;\n padding: 24px;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n\n .calibration-section 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 .calibration-section h3 i {\n color: #3b82f6;\n }\n\n .calibration-body {\n display: flex;\n align-items: center;\n gap: 32px;\n }\n\n .gauge-display {\n flex-shrink: 0;\n }\n\n .gauge-ring {\n position: relative;\n width: 120px;\n height: 120px;\n }\n\n .gauge-svg {\n width: 100%;\n height: 100%;\n }\n\n .gauge-value {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 24px;\n font-weight: 800;\n color: #1e293b;\n }\n\n .calibration-text {\n flex: 1;\n }\n\n .calibration-description {\n margin: 0 0 12px 0;\n font-size: 14px;\n color: #64748b;\n line-height: 1.6;\n }\n\n .calibration-warning {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: #fef3c7;\n border: 1px solid #fbbf24;\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n color: #92400e;\n }\n\n .calibration-warning i {\n color: #d97706;\n font-size: 16px;\n flex-shrink: 0;\n }\n\n /* Success toast animation */\n .queue-item {\n animation: fadeIn 0.2s ease;\n }\n\n @keyframes fadeIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n /* Responsive */\n @media (max-width: 1024px) {\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n }\n\n @media (max-width: 768px) {\n .review-page {\n padding: 16px;\n }\n\n .page-header {\n flex-direction: column;\n gap: 16px;\n align-items: flex-start;\n }\n\n .kpi-row {\n grid-template-columns: 1fr 1fr;\n }\n\n .kpi-card {\n padding: 16px;\n }\n\n .kpi-value {\n font-size: 22px;\n }\n\n .queue-item-header {\n flex-wrap: wrap;\n }\n\n .item-actions-area {\n width: 100%;\n justify-content: flex-end;\n margin-top: 8px;\n }\n\n .correctness-row {\n flex-direction: column;\n }\n\n .correctness-btn {\n max-width: 100%;\n }\n\n .history-item {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .calibration-body {\n flex-direction: column;\n align-items: center;\n text-align: center;\n }\n }\n `]\n})\nexport class TestingReviewComponent implements OnInit, OnDestroy {\n @Input() initialState: Record<string, unknown> | null = null;\n @Output() stateChange = new EventEmitter<Record<string, unknown>>();\n\n private destroy$ = new Subject<void>();\n\n // View state\n CurrentView: ViewMode = 'queue';\n ExpandedItemId: string | null = null;\n ExpandedHistoryId: string | null = null;\n IsRefreshing = false;\n IsSubmitting = false;\n HistorySearchText = '';\n HistorySortField: HistorySort = 'date';\n\n // Form state for active review\n FormState: ReviewFormState = { rating: null, isCorrect: null, comments: '' };\n\n // Data\n PendingItems: FeedbackPending[] = [];\n HistoryItems: TestRunWithFeedbackSummary[] = [];\n FilteredHistoryItems: TestRunWithFeedbackSummary[] = [];\n Metrics: EvaluationSummaryMetrics | null = null;\n PendingCount = 0;\n\n // Constants\n readonly RatingNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n\n constructor(\n private instrumentationService: TestingInstrumentationService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.restoreState();\n this.setupSubscriptions();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ------------------------------------------------------------------\n // Computed properties\n // ------------------------------------------------------------------\n\n get IsFormValid(): boolean {\n return this.FormState.rating != null && this.FormState.isCorrect != null;\n }\n\n get AgreementRate(): number {\n return this.Metrics?.agreementRate ?? 0;\n }\n\n get AgreementColor(): string {\n const rate = this.AgreementRate;\n if (rate >= 80) return '#22c55e';\n if (rate >= 60) return '#eab308';\n return '#ef4444';\n }\n\n get AgreementDash(): string {\n const circumference = 2 * Math.PI * 52; // r=52\n const filled = (this.AgreementRate / 100) * circumference;\n return `${filled} ${circumference}`;\n }\n\n // ------------------------------------------------------------------\n // Setup\n // ------------------------------------------------------------------\n\n private restoreState(): void {\n if (!this.initialState) return;\n const view = this.initialState['viewMode'] as string | undefined;\n if (view === 'queue' || view === 'history') {\n this.CurrentView = view;\n }\n }\n\n private setupSubscriptions(): void {\n this.instrumentationService.pendingFeedback$\n .pipe(takeUntil(this.destroy$))\n .subscribe(items => {\n this.PendingItems = items;\n this.PendingCount = items.length;\n this.cdr.markForCheck();\n });\n\n this.instrumentationService.evaluationMetrics$\n .pipe(takeUntil(this.destroy$))\n .subscribe(metrics => {\n this.Metrics = metrics;\n this.cdr.markForCheck();\n });\n\n this.instrumentationService.testRunsWithFeedback$\n .pipe(takeUntil(this.destroy$))\n .subscribe(runs => {\n this.HistoryItems = runs.filter(r => r.hasHumanFeedback);\n this.applyHistoryFilters();\n this.cdr.markForCheck();\n });\n }\n\n // ------------------------------------------------------------------\n // View toggling\n // ------------------------------------------------------------------\n\n SetView(mode: ViewMode): void {\n this.CurrentView = mode;\n this.ExpandedItemId = null;\n this.emitState();\n this.cdr.markForCheck();\n }\n\n // ------------------------------------------------------------------\n // Queue interactions\n // ------------------------------------------------------------------\n\n IsItemExpanded(testRunID: string): boolean {\n return UUIDsEqual(this.ExpandedItemId, testRunID);\n }\n\n ToggleExpand(testRunID: string): void {\n if (UUIDsEqual(this.ExpandedItemId, testRunID)) {\n this.ExpandedItemId = null;\n } else {\n this.ExpandedItemId = testRunID;\n this.resetForm();\n }\n this.cdr.markForCheck();\n }\n\n SelectRating(n: number): void {\n this.FormState = { ...this.FormState, rating: n };\n this.cdr.markForCheck();\n }\n\n SelectCorrectness(value: boolean): void {\n this.FormState = { ...this.FormState, isCorrect: value };\n this.cdr.markForCheck();\n }\n\n OnCommentsChange(event: Event): void {\n const target = event.target as HTMLTextAreaElement;\n this.FormState = { ...this.FormState, comments: target.value };\n }\n\n async SubmitReview(item: FeedbackPending): Promise<void> {\n if (!this.IsFormValid || this.IsSubmitting) return;\n\n this.IsSubmitting = true;\n this.cdr.markForCheck();\n\n try {\n const success = await this.instrumentationService.submitFeedback(\n item.testRunID,\n this.FormState.rating!,\n this.FormState.isCorrect!,\n this.FormState.comments\n );\n\n if (success) {\n this.ExpandedItemId = null;\n this.resetForm();\n }\n } finally {\n this.IsSubmitting = false;\n this.cdr.markForCheck();\n }\n }\n\n SkipItem(): void {\n const currentIndex = this.PendingItems.findIndex(\n i => UUIDsEqual(i.testRunID, this.ExpandedItemId)\n );\n this.ExpandedItemId = null;\n this.resetForm();\n\n // Expand the next item if available\n if (currentIndex >= 0 && currentIndex + 1 < this.PendingItems.length) {\n this.ExpandedItemId = this.PendingItems[currentIndex + 1].testRunID;\n }\n this.cdr.markForCheck();\n }\n\n // ------------------------------------------------------------------\n // History interactions\n // ------------------------------------------------------------------\n\n OnHistorySearch(event: Event): void {\n const target = event.target as HTMLInputElement;\n this.HistorySearchText = target.value;\n this.applyHistoryFilters();\n this.cdr.markForCheck();\n }\n\n OnHistorySortChange(event: Event): void {\n const target = event.target as HTMLSelectElement;\n this.HistorySortField = target.value as HistorySort;\n this.applyHistoryFilters();\n this.cdr.markForCheck();\n }\n\n ToggleHistoryComment(id: string): void {\n this.ExpandedHistoryId = this.ExpandedHistoryId === id ? null : id;\n this.cdr.markForCheck();\n }\n\n // ------------------------------------------------------------------\n // Refresh\n // ------------------------------------------------------------------\n\n Refresh(): void {\n this.IsRefreshing = true;\n this.cdr.markForCheck();\n this.instrumentationService.refresh();\n\n setTimeout(() => {\n this.IsRefreshing = false;\n this.cdr.markForCheck();\n }, 1500);\n }\n\n // ------------------------------------------------------------------\n // Formatting helpers\n // ------------------------------------------------------------------\n\n FormatDecimal(value: number | undefined | null, decimals: number): string {\n if (value == null) return '0';\n return value.toFixed(decimals);\n }\n\n FormatRelativeTime(date: Date): string {\n const now = Date.now();\n const then = date instanceof Date ? date.getTime() : new Date(date).getTime();\n const diffMs = now - then;\n const diffMin = Math.floor(diffMs / 60000);\n\n if (diffMin < 1) return 'just now';\n if (diffMin < 60) return `${diffMin}m ago`;\n\n const diffHours = Math.floor(diffMin / 60);\n if (diffHours < 24) return `${diffHours}h ago`;\n\n const diffDays = Math.floor(diffHours / 24);\n if (diffDays < 7) return `${diffDays}d ago`;\n\n const diffWeeks = Math.floor(diffDays / 7);\n if (diffWeeks < 4) return `${diffWeeks}w ago`;\n\n const diffMonths = Math.floor(diffDays / 30);\n return `${diffMonths}mo ago`;\n }\n\n // ------------------------------------------------------------------\n // Private helpers\n // ------------------------------------------------------------------\n\n private resetForm(): void {\n this.FormState = { rating: null, isCorrect: null, comments: '' };\n }\n\n private applyHistoryFilters(): void {\n let items = [...this.HistoryItems];\n\n // Search filter\n if (this.HistorySearchText) {\n const term = this.HistorySearchText.toLowerCase();\n items = items.filter(i => i.testName.toLowerCase().includes(term));\n }\n\n // Sort\n items.sort((a, b) => {\n switch (this.HistorySortField) {\n case 'date':\n return b.runDateTime.getTime() - a.runDateTime.getTime();\n case 'rating':\n return (b.humanRating ?? 0) - (a.humanRating ?? 0);\n case 'test-name':\n return a.testName.localeCompare(b.testName);\n default:\n return 0;\n }\n });\n\n this.FilteredHistoryItems = items;\n }\n\n private emitState(): void {\n this.stateChange.emit({ viewMode: this.CurrentView });\n }\n}\n"]}
|
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var VersionHistoryDiffResourceComponent_1;
|
|
8
8
|
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
|
9
9
|
import { Subject } from 'rxjs';
|
|
10
|
-
import { RegisterClass } from '@memberjunction/global';
|
|
10
|
+
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
|
|
11
11
|
import { BaseResourceComponent } from '@memberjunction/ng-shared';
|
|
12
12
|
import { RunView, Metadata, CompositeKey, EntityRecordNameInput } from '@memberjunction/core';
|
|
13
13
|
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
@@ -683,7 +683,7 @@ let VersionHistoryDiffResourceComponent = class VersionHistoryDiffResourceCompon
|
|
|
683
683
|
else {
|
|
684
684
|
// Both exist - check if RecordChangeID differs (= Modified)
|
|
685
685
|
const toItem = toMap.get(key);
|
|
686
|
-
const changeType = item.RecordChangeID
|
|
686
|
+
const changeType = !UUIDsEqual(item.RecordChangeID, toItem.RecordChangeID)
|
|
687
687
|
? 'Modified' : 'Unchanged';
|
|
688
688
|
entityMap.get(entityName).push({
|
|
689
689
|
EntityName: entityName,
|
|
@@ -773,13 +773,13 @@ let VersionHistoryDiffResourceComponent = class VersionHistoryDiffResourceCompon
|
|
|
773
773
|
resolveEntityName(entityId) {
|
|
774
774
|
if (!entityId)
|
|
775
775
|
return 'Unknown';
|
|
776
|
-
const entity = this.metadata.Entities.find(e => e.ID
|
|
776
|
+
const entity = this.metadata.Entities.find(e => UUIDsEqual(e.ID, entityId));
|
|
777
777
|
return entity ? entity.Name : 'Unknown';
|
|
778
778
|
}
|
|
779
779
|
resolveEntityIcon(entityId) {
|
|
780
780
|
if (!entityId)
|
|
781
781
|
return 'fa-solid fa-table';
|
|
782
|
-
const entity = this.metadata.Entities.find(e => e.ID
|
|
782
|
+
const entity = this.metadata.Entities.find(e => UUIDsEqual(e.ID, entityId));
|
|
783
783
|
return entity?.Icon || 'fa-solid fa-table';
|
|
784
784
|
}
|
|
785
785
|
// =========================================================================
|
|
@@ -1064,13 +1064,13 @@ let VersionHistoryDiffResourceComponent = class VersionHistoryDiffResourceCompon
|
|
|
1064
1064
|
get FilteredFromLabels() {
|
|
1065
1065
|
if (!this.ToLabelId)
|
|
1066
1066
|
return this.AvailableLabels;
|
|
1067
|
-
return this.AvailableLabels.filter(l => l.ID
|
|
1067
|
+
return this.AvailableLabels.filter(l => !UUIDsEqual(l.ID, this.ToLabelId));
|
|
1068
1068
|
}
|
|
1069
1069
|
/** To dropdown excludes the currently selected From label. */
|
|
1070
1070
|
get FilteredToLabels() {
|
|
1071
1071
|
if (!this.FromLabelId)
|
|
1072
1072
|
return this.AvailableLabels;
|
|
1073
|
-
return this.AvailableLabels.filter(l => l.ID
|
|
1073
|
+
return this.AvailableLabels.filter(l => !UUIDsEqual(l.ID, this.FromLabelId));
|
|
1074
1074
|
}
|
|
1075
1075
|
/** Swap From and To label selections. */
|
|
1076
1076
|
SwapLabels() {
|