@memberjunction/ng-dashboards 5.48.0 → 5.50.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/autotagging/tabs/sources-tab.component.js +1 -1
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +1 -1
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.js +2 -2
- package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts +7 -0
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +25 -5
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.d.ts +7 -0
- package/dist/Lists/components/lists-my-lists-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +66 -37
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/services/list-set-operations.service.d.ts.map +1 -1
- package/dist/Lists/services/list-set-operations.service.js +29 -12
- package/dist/Lists/services/list-set-operations.service.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts +7 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.js +11 -4
- package/dist/PredictiveStudio/components/ps-pipelines.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +2 -2
- package/dist/Testing/components/testing-runs.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-runs.component.js +35 -25
- package/dist/Testing/components/testing-runs.component.js.map +1 -1
- package/dist/Testing/services/testing-instrumentation.service.d.ts +5 -0
- package/dist/Testing/services/testing-instrumentation.service.d.ts.map +1 -1
- package/dist/Testing/services/testing-instrumentation.service.js +8 -2
- package/dist/Testing/services/testing-instrumentation.service.js.map +1 -1
- package/dist/ThemeStudio/theme-agent-context.d.ts +64 -0
- package/dist/ThemeStudio/theme-agent-context.d.ts.map +1 -0
- package/dist/ThemeStudio/theme-agent-context.js +129 -0
- package/dist/ThemeStudio/theme-agent-context.js.map +1 -0
- package/dist/ThemeStudio/theme-manager-dashboard.component.d.ts +62 -0
- package/dist/ThemeStudio/theme-manager-dashboard.component.d.ts.map +1 -0
- package/dist/ThemeStudio/theme-manager-dashboard.component.js +464 -0
- package/dist/ThemeStudio/theme-manager-dashboard.component.js.map +1 -0
- package/dist/ThemeStudio/theme-manager-resource.component.d.ts +31 -0
- package/dist/ThemeStudio/theme-manager-resource.component.d.ts.map +1 -0
- package/dist/ThemeStudio/theme-manager-resource.component.js +97 -0
- package/dist/ThemeStudio/theme-manager-resource.component.js.map +1 -0
- package/dist/ThemeStudio/theme-studio-dashboard.component.d.ts +351 -0
- package/dist/ThemeStudio/theme-studio-dashboard.component.d.ts.map +1 -0
- package/dist/ThemeStudio/theme-studio-dashboard.component.js +2931 -0
- package/dist/ThemeStudio/theme-studio-dashboard.component.js.map +1 -0
- package/dist/ThemeStudio/theme-studio-resource.component.d.ts +28 -0
- package/dist/ThemeStudio/theme-studio-resource.component.d.ts.map +1 -0
- package/dist/ThemeStudio/theme-studio-resource.component.js +96 -0
- package/dist/ThemeStudio/theme-studio-resource.component.js.map +1 -0
- package/dist/ThemeStudio/theme-studio.constants.d.ts +79 -0
- package/dist/ThemeStudio/theme-studio.constants.d.ts.map +1 -0
- package/dist/ThemeStudio/theme-studio.constants.js +217 -0
- package/dist/ThemeStudio/theme-studio.constants.js.map +1 -0
- package/dist/core-dashboards.module.d.ts +56 -52
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +24 -1
- package/dist/core-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +4 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +4 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +63 -60
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing-runs.component.js","sourceRoot":"","sources":["../../../src/Testing/components/testing-runs.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 ViewContainerRef,\n HostListener\n} from '@angular/core';\nimport { Observable, Subject, BehaviorSubject, combineLatest } from 'rxjs';\nimport { takeUntil, map, tap } from 'rxjs/operators';\nimport { CompositeKey } from '@memberjunction/core';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { TestingDialogService } from '@memberjunction/ng-testing';\nimport { EvaluationPreferences, DEFAULT_EVALUATION_PREFERENCES } from '@memberjunction/ng-testing';\nimport {\n TestingInstrumentationService,\n TestRunWithFeedbackSummary,\n EvaluationSummaryMetrics\n} from '../services/testing-instrumentation.service';\n\ntype StatusFilter = 'all' | 'running' | 'passed' | 'failed' | 'error';\ntype TimeRange = 'today' | 'week' | 'month' | '90days';\n\ninterface RunsFilterState {\n status: StatusFilter;\n timeRange: TimeRange;\n searchText: string;\n}\n\ninterface FilteredStats {\n totalRuns: number;\n passRate: number;\n avgDuration: number;\n totalCost: number;\n}\n\n@Component({\n standalone: false,\n selector: 'app-testing-runs',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n @if (HideToolbar) {\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n } @else {\n <mj-page-layout>\n <mj-page-header\n Title=\"Test Runs\"\n Icon=\"fa-solid fa-list-check\"\n Subtitle=\"Test execution history and monitoring\">\n <div actions>\n <mj-refresh-button [Loading]=\"IsRefreshing\" (Clicked)=\"Refresh()\"></mj-refresh-button>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"StartNewTest()\">\n <i class=\"fa-solid fa-play\"></i> <span class=\"action-btn-label\">Run Test</span>\n </button>\n </div>\n </mj-page-header>\n <mj-page-body>\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n </mj-page-body>\n </mj-page-layout>\n }\n\n <ng-template #content>\n <div class=\"runs-container\" (keydown.escape)=\"CloseDetailPanel()\">\n\n <!-- Filter Bar -->\n <div class=\"filter-bar\">\n <div class=\"filter-left\">\n <div class=\"filter-chips\">\n @for (chip of StatusChips; track chip.value) {\n <button\n class=\"chip\"\n [class.active]=\"filterState.status === chip.value\"\n [attr.data-status]=\"chip.value\"\n (click)=\"SetStatusFilter(chip.value)\"\n >\n @if (chip.icon) {\n <i [class]=\"chip.icon\"></i>\n }\n {{ chip.label }}\n </button>\n }\n </div>\n <span class=\"result-count\">{{ (FilteredRuns$ | async)?.length ?? 0 }} results</span>\n </div>\n <div class=\"filter-right\">\n <select\n class=\"time-select\"\n [value]=\"filterState.timeRange\"\n (change)=\"OnTimeRangeChange($event)\"\n >\n <option value=\"today\">Today</option>\n <option value=\"week\">This Week</option>\n <option value=\"month\">This Month</option>\n <option value=\"90days\">Last 90 Days</option>\n </select>\n <div class=\"search-box\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search by test name...\"\n [value]=\"filterState.searchText\"\n (input)=\"OnSearchInput($event)\"\n />\n @if (filterState.searchText) {\n <button class=\"clear-search\" (click)=\"ClearSearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Summary Stats Row -->\n @if (FilteredStats$ | async; as stats) {\n <div class=\"stats-row\">\n <div class=\"stat-card\">\n <div class=\"stat-icon total\"><i class=\"fa-solid fa-hashtag\"></i></div>\n <div class=\"stat-body\">\n <div class=\"stat-value\">{{ stats.totalRuns }}</div>\n <div class=\"stat-label\">Total Runs</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon pass\"><i class=\"fa-solid fa-check-circle\"></i></div>\n <div class=\"stat-body\">\n <div class=\"stat-value\">{{ FormatPercent(stats.passRate) }}</div>\n <div class=\"stat-label\">Pass Rate</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon duration\"><i class=\"fa-solid fa-clock\"></i></div>\n <div class=\"stat-body\">\n <div class=\"stat-value\">{{ FormatDuration(stats.avgDuration) }}</div>\n <div class=\"stat-label\">Avg Duration</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon cost\"><i class=\"fa-solid fa-dollar-sign\"></i></div>\n <div class=\"stat-body\">\n <div class=\"stat-value\">{{ FormatCostTotal(stats.totalCost) }}</div>\n <div class=\"stat-label\">Total Cost</div>\n </div>\n </div>\n </div>\n }\n\n <!-- Runs Table -->\n <div class=\"runs-table-wrapper\">\n <div class=\"table-header\">\n <div class=\"col col-name\">Test Name</div>\n <div class=\"col col-eval\">Evaluation</div>\n <div class=\"col col-score\">Score</div>\n <div class=\"col col-duration\">Duration</div>\n <div class=\"col col-cost\">Cost</div>\n <div class=\"col col-time\">Started</div>\n <div class=\"col col-actions\">Actions</div>\n </div>\n\n @if (instrumentationService.isLoading$ | async) {\n <div class=\"table-loading\">\n <mj-loading text=\"Loading test runs...\"></mj-loading>\n </div>\n } @else if ((FilteredRuns$ | async)?.length === 0) {\n <mj-empty-state Variant=\"no-results\" Icon=\"fa-solid fa-inbox\"\n Title=\"No test runs found\"\n Message=\"Try adjusting your filters or run a new test.\" />\n } @else {\n @for (run of FilteredRuns$ | async; track TrackByRunId($index, run)) {\n <div\n class=\"table-row\"\n [class.is-running]=\"run.status === 'Running'\"\n [class.is-selected]=\"SelectedRun?.id === run.id\"\n (click)=\"SelectRun(run)\"\n >\n <div class=\"col col-name\">\n <span class=\"test-name-link\" (click)=\"NavigateToTest(run, $event)\">\n {{ run.testName }}\n </span>\n </div>\n <div class=\"col col-eval\">\n <app-evaluation-badge\n [executionStatus]=\"run.status\"\n [originalStatus]=\"run.status\"\n [autoScore]=\"run.score\"\n [passedChecks]=\"run.passedChecks\"\n [failedChecks]=\"run.failedChecks\"\n [totalChecks]=\"run.totalChecks\"\n [humanRating]=\"run.humanRating\"\n [humanIsCorrect]=\"run.humanIsCorrect\"\n [hasHumanFeedback]=\"run.hasHumanFeedback\"\n [preferences]=\"EvalPreferences\"\n mode=\"compact\"\n ></app-evaluation-badge>\n </div>\n <div class=\"col col-score\">\n <app-score-indicator [score]=\"run.score\" [showBar]=\"true\"></app-score-indicator>\n </div>\n <div class=\"col col-duration\">{{ FormatDuration(run.duration) }}</div>\n <div class=\"col col-cost\">\n <app-cost-display [cost]=\"run.cost\"></app-cost-display>\n </div>\n <div class=\"col col-time\">{{ FormatRelativeTime(run.runDateTime) }}</div>\n <div class=\"col col-actions\">\n <button class=\"icon-btn\" title=\"View details\" (click)=\"SelectRun(run); $event.stopPropagation()\">\n <i class=\"fa-solid fa-eye\"></i>\n </button>\n <button class=\"icon-btn\" title=\"Re-run test\" (click)=\"RerunTest(run); $event.stopPropagation()\">\n <i class=\"fa-solid fa-rotate-right\"></i>\n </button>\n </div>\n </div>\n }\n }\n </div>\n\n <!-- Detail Panel (slide-in) -->\n @if (SelectedRun) {\n <div class=\"detail-overlay\" (click)=\"CloseDetailPanel()\"></div>\n <div class=\"detail-panel\">\n <div class=\"detail-panel-header\">\n <div class=\"detail-title-section\">\n <h3>{{ SelectedRun.testName }}</h3>\n <app-test-status-badge [status]=\"SelectedRun.status\"></app-test-status-badge>\n </div>\n <button class=\"close-btn\" (click)=\"CloseDetailPanel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"detail-panel-body\">\n <!-- Metrics row -->\n <div class=\"detail-metrics\">\n <div class=\"detail-metric\">\n <span class=\"dm-label\">Score</span>\n <app-score-indicator [score]=\"SelectedRun.score\" [showBar]=\"true\"></app-score-indicator>\n </div>\n <div class=\"detail-metric\">\n <span class=\"dm-label\">Duration</span>\n <span class=\"dm-value\">{{ FormatDuration(SelectedRun.duration) }}</span>\n </div>\n <div class=\"detail-metric\">\n <span class=\"dm-label\">Cost</span>\n <app-cost-display [cost]=\"SelectedRun.cost\"></app-cost-display>\n </div>\n <div class=\"detail-metric\">\n <span class=\"dm-label\">Started</span>\n <span class=\"dm-value\">{{ FormatDateTime(SelectedRun.runDateTime) }}</span>\n </div>\n </div>\n\n <!-- Evaluation Badge (expanded) -->\n <div class=\"detail-section\">\n <h4><i class=\"fa-solid fa-clipboard-check\"></i> Evaluation</h4>\n <app-evaluation-badge\n [executionStatus]=\"SelectedRun.status\"\n [originalStatus]=\"SelectedRun.status\"\n [autoScore]=\"SelectedRun.score\"\n [passedChecks]=\"SelectedRun.passedChecks\"\n [failedChecks]=\"SelectedRun.failedChecks\"\n [totalChecks]=\"SelectedRun.totalChecks\"\n [humanRating]=\"SelectedRun.humanRating\"\n [humanIsCorrect]=\"SelectedRun.humanIsCorrect\"\n [hasHumanFeedback]=\"SelectedRun.hasHumanFeedback\"\n [preferences]=\"EvalPreferences\"\n mode=\"expanded\"\n ></app-evaluation-badge>\n </div>\n\n <!-- Execution Context -->\n @if (SelectedRun.targetType) {\n <div class=\"detail-section\">\n <h4><i class=\"fa-solid fa-server\"></i> Execution Context</h4>\n <mj-execution-context></mj-execution-context>\n </div>\n }\n\n <!-- Inline Feedback Form -->\n <div class=\"detail-section feedback-section\">\n <h4><i class=\"fa-solid fa-comment-dots\"></i> Human Feedback</h4>\n @if (SelectedRun.hasHumanFeedback) {\n <div class=\"existing-feedback\">\n <span class=\"feedback-label\">Rating:</span>\n <span class=\"feedback-value\">{{ SelectedRun.humanRating }}/10</span>\n <span class=\"feedback-label\">Correct:</span>\n <span class=\"feedback-value\">\n @if (SelectedRun.humanIsCorrect === true) {\n <i class=\"fa-solid fa-check\" style=\"color: var(--mj-status-success)\"></i> Yes\n } @else if (SelectedRun.humanIsCorrect === false) {\n <i class=\"fa-solid fa-times\" style=\"color: var(--mj-status-error)\"></i> No\n } @else {\n --\n }\n </span>\n @if (SelectedRun.humanComments) {\n <div class=\"feedback-comments\">{{ SelectedRun.humanComments }}</div>\n }\n </div>\n } @else {\n <div class=\"feedback-form\">\n <div class=\"rating-row\">\n <label>Rating</label>\n <div class=\"rating-buttons\">\n @for (n of RatingValues; track n) {\n <button\n class=\"rating-btn\"\n [class.selected]=\"feedbackRating === n\"\n (click)=\"feedbackRating = n\"\n >\n {{ n }}\n </button>\n }\n </div>\n </div>\n <div class=\"correctness-row\">\n <label>Is the result correct?</label>\n <div class=\"toggle-group\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"feedbackIsCorrect === true\"\n (click)=\"feedbackIsCorrect = true\"\n >\n <i class=\"fa-solid fa-check\"></i> Yes\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"feedbackIsCorrect === false\"\n (click)=\"feedbackIsCorrect = false\"\n >\n <i class=\"fa-solid fa-times\"></i> No\n </button>\n </div>\n </div>\n <div class=\"comments-row\">\n <label>Comments</label>\n <textarea\n rows=\"3\"\n placeholder=\"Optional feedback comments...\"\n [value]=\"feedbackComments\"\n (input)=\"OnFeedbackCommentInput($event)\"\n ></textarea>\n </div>\n <button\n class=\"btn btn-primary submit-feedback-btn\"\n (click)=\"SubmitFeedback()\"\n [disabled]=\"IsSubmittingFeedback\"\n >\n <i class=\"fa-solid fa-paper-plane\"></i>\n {{ IsSubmittingFeedback ? 'Submitting...' : 'Submit Feedback' }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </ng-template>\n `,\n styles: [`\n /* ==========================================\n Testing Runs Component\n ========================================== */\n\n .runs-container {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-surface-card);\n position: relative;\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 }\n\n .header-title {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .header-title i {\n font-size: 22px;\n color: var(--mj-brand-primary);\n }\n\n .header-title h2 {\n margin: 0;\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n }\n\n .header-actions {\n display: flex;\n gap: 10px;\n }\n\n /* Buttons */\n .btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 10px 18px;\n border: none;\n border-radius: 10px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n }\n\n .btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-md);\n }\n\n .btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n }\n\n .btn-secondary:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n }\n\n .spinning {\n animation: spin 1s linear infinite;\n }\n\n @keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n /* Filter Bar */\n .filter-bar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n margin-bottom: 20px;\n padding: 14px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n }\n\n .filter-left {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .filter-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 14px;\n background: var(--mj-bg-surface-sunken);\n border: 2px solid transparent;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .chip:hover {\n background: var(--mj-border-default);\n }\n\n .chip.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n }\n\n .chip.active[data-status=\"running\"] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n }\n\n .chip.active[data-status=\"passed\"] {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n }\n\n .chip.active[data-status=\"failed\"] {\n background: var(--mj-status-error);\n border-color: var(--mj-status-error);\n }\n\n .chip.active[data-status=\"error\"] {\n background: var(--mj-status-warning);\n border-color: var(--mj-status-warning);\n }\n\n .result-count {\n font-size: 12px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n white-space: nowrap;\n }\n\n .filter-right {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .time-select {\n padding: 8px 12px;\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n }\n\n .time-select:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n }\n\n .search-box {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n background: var(--mj-bg-surface-card);\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n min-width: 220px;\n transition: border-color 0.2s ease;\n }\n\n .search-box:focus-within {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n }\n\n .search-box i {\n color: var(--mj-text-disabled);\n font-size: 13px;\n }\n\n .search-box input {\n flex: 1;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: var(--mj-text-secondary);\n }\n\n .search-box input::placeholder {\n color: var(--mj-text-disabled);\n }\n\n .clear-search {\n border: none;\n background: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 4px;\n }\n\n .clear-search:hover {\n color: var(--mj-text-muted);\n background: var(--mj-border-default);\n }\n\n /* Stats Row */\n .stats-row {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 14px;\n margin-bottom: 20px;\n }\n\n .stat-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n }\n\n .stat-icon {\n width: 42px;\n height: 42px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n }\n\n .stat-icon.total { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n .stat-icon.pass { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n .stat-icon.duration { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n .stat-icon.cost { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n\n .stat-body {\n flex: 1;\n }\n\n .stat-value {\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.1;\n }\n\n .stat-label {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-top: 2px;\n }\n\n /* Runs Table */\n .runs-table-wrapper {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n }\n\n .table-header {\n display: grid;\n grid-template-columns: 2fr 140px 120px 100px 100px 120px 90px;\n gap: 12px;\n padding: 14px 24px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 11px;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .table-row {\n display: grid;\n grid-template-columns: 2fr 140px 120px 100px 100px 120px 90px;\n gap: 12px;\n padding: 14px 24px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n cursor: pointer;\n transition: background 0.15s ease;\n align-items: center;\n }\n\n .table-row:last-child {\n border-bottom: none;\n }\n\n .table-row:hover {\n background: var(--mj-bg-surface-card);\n }\n\n .table-row.is-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 6%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n }\n\n .table-row.is-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 4%, var(--mj-bg-surface));\n }\n\n .table-row.is-running .test-name-link::after {\n content: '';\n display: inline-block;\n width: 8px;\n height: 8px;\n background: var(--mj-brand-primary);\n border-radius: 50%;\n margin-left: 8px;\n animation: pulse-dot 1.5s infinite;\n }\n\n @keyframes pulse-dot {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.3; }\n }\n\n .col {\n display: flex;\n align-items: center;\n font-size: 13px;\n color: var(--mj-text-secondary);\n overflow: hidden;\n }\n\n .test-name-link {\n font-weight: 600;\n color: var(--mj-text-primary);\n cursor: pointer;\n text-decoration: none;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .test-name-link:hover {\n color: var(--mj-brand-primary);\n text-decoration: underline;\n }\n\n .col-actions {\n gap: 6px;\n justify-content: flex-end;\n }\n\n .icon-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n color: var(--mj-text-muted);\n cursor: pointer;\n border-radius: 8px;\n font-size: 13px;\n transition: all 0.2s ease;\n }\n\n .icon-btn:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-md);\n }\n\n /* Table states */\n .table-loading {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 80px 40px;\n }\n\n /* Detail Panel Overlay */\n .detail-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 999;\n }\n\n /* Detail Panel */\n .detail-panel {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 520px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-lg);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n animation: slideIn 0.25s ease-out;\n }\n\n @keyframes slideIn {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n }\n\n .detail-panel-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n }\n\n .detail-title-section {\n display: flex;\n flex-direction: column;\n gap: 8px;\n flex: 1;\n min-width: 0;\n }\n\n .detail-title-section h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .close-btn {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 14px;\n flex-shrink: 0;\n margin-left: 12px;\n transition: all 0.15s ease;\n }\n\n .close-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .detail-panel-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px 24px;\n }\n\n .detail-metrics {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n margin-bottom: 24px;\n }\n\n .detail-metric {\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n border-left: 3px solid var(--mj-brand-primary);\n }\n\n .dm-label {\n display: block;\n font-size: 10px;\n font-weight: 700;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n }\n\n .dm-value {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n\n .detail-section {\n margin-bottom: 24px;\n }\n\n .detail-section h4 {\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .detail-section h4 i {\n color: var(--mj-brand-primary);\n font-size: 14px;\n }\n\n /* Feedback Section */\n .existing-feedback {\n display: flex;\n flex-wrap: wrap;\n gap: 8px 16px;\n align-items: center;\n padding: 14px;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n font-size: 13px;\n }\n\n .feedback-label {\n font-weight: 600;\n color: var(--mj-text-muted);\n }\n\n .feedback-value {\n color: var(--mj-text-primary);\n font-weight: 500;\n }\n\n .feedback-comments {\n width: 100%;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid color-mix(in srgb, var(--mj-status-success) 25%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-text-secondary);\n font-style: italic;\n }\n\n .feedback-form {\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n .feedback-form label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n margin-bottom: 6px;\n }\n\n .rating-buttons {\n display: flex;\n gap: 4px;\n }\n\n .rating-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 8px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.15s ease;\n }\n\n .rating-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n }\n\n .rating-btn.selected {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n }\n\n .toggle-group {\n display: flex;\n gap: 8px;\n }\n\n .toggle-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 8px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.15s ease;\n }\n\n .toggle-btn.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n .comments-row textarea {\n width: 100%;\n padding: 10px 12px;\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n font-family: inherit;\n color: var(--mj-text-secondary);\n resize: vertical;\n box-sizing: border-box;\n }\n\n .comments-row textarea:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n }\n\n .comments-row textarea::placeholder {\n color: var(--mj-text-disabled);\n }\n\n .submit-feedback-btn {\n align-self: flex-start;\n }\n\n /* Responsive */\n @media (max-width: 1400px) {\n .stats-row {\n grid-template-columns: repeat(2, 1fr);\n }\n }\n\n @media (max-width: 1200px) {\n .filter-bar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .filter-left, .filter-right {\n justify-content: center;\n }\n\n .table-header, .table-row {\n grid-template-columns: 2fr 120px 100px 100px 80px;\n }\n\n .col-eval, .col-time {\n display: none;\n }\n }\n\n @media (max-width: 768px) {\n .stats-row {\n grid-template-columns: 1fr;\n }\n\n .detail-panel {\n width: 100vw;\n max-width: 100vw;\n }\n }\n\n @media (max-width: 480px) {\n .table-header, .table-row {\n grid-template-columns: 1fr 80px 60px;\n }\n\n .col-score, .col-duration {\n display: none;\n }\n\n .chip {\n min-height: 44px;\n padding: 8px 14px;\n }\n\n .table-row {\n min-height: 44px;\n }\n }\n `]\n})\nexport class TestingRunsComponent implements OnInit, OnDestroy {\n @Input() initialState: Record<string, unknown> | null = null;\n /** When true, the inner bespoke .page-header is hidden — the parent shell owns the chrome. */\n @Input() HideToolbar = false;\n @Output() stateChange = new EventEmitter<Record<string, unknown>>();\n\n private destroy$ = new Subject<void>();\n private filterTrigger$ = new BehaviorSubject<void>(undefined);\n\n // Filter state\n filterState: RunsFilterState = {\n status: 'all',\n timeRange: 'month',\n searchText: ''\n };\n\n // Feedback form state\n feedbackRating = 5;\n feedbackIsCorrect: boolean | null = null;\n feedbackComments = '';\n IsSubmittingFeedback = false;\n IsRefreshing = false;\n\n SelectedRun: TestRunWithFeedbackSummary | null = null;\n\n /** Latest filtered/visible runs, cached for state reporting (agent context). */\n private latestVisibleRuns: TestRunWithFeedbackSummary[] = [];\n\n EvalPreferences: EvaluationPreferences = { ...DEFAULT_EVALUATION_PREFERENCES, showAuto: true };\n\n // Observables\n FilteredRuns$!: Observable<TestRunWithFeedbackSummary[]>;\n FilteredStats$!: Observable<FilteredStats>;\n\n // Constants\n readonly StatusChips: Array<{ value: StatusFilter; label: string; icon: string }> = [\n { value: 'all', label: 'All', icon: '' },\n { value: 'running', label: 'Running', icon: 'fa-solid fa-spinner fa-spin' },\n { value: 'passed', label: 'Passed', icon: 'fa-solid fa-check' },\n { value: 'failed', label: 'Failed', icon: 'fa-solid fa-times' },\n { value: 'error', label: 'Error', icon: 'fa-solid fa-exclamation-triangle' }\n ];\n\n readonly RatingValues: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n\n constructor(\n public instrumentationService: TestingInstrumentationService,\n private testingDialogService: TestingDialogService,\n private cdr: ChangeDetectorRef,\n private viewContainerRef: ViewContainerRef\n ) {}\n\n ngOnInit(): void {\n this.applyInitialState();\n this.updateServiceDateRange();\n this.setupObservables();\n this.subscribeToAgentFilterIntents();\n this.subscribeToAgentSelectionIntents();\n }\n\n /**\n * Apply agent-driven run-SELECTION intents published on the shared\n * instrumentation service (from the dashboard's `SelectTestRun` / open-run\n * client tools). The dashboard owns no `SelectedRun` UI state — it publishes a\n * target run id (+ open flag + monotonic nonce) here, and this surface resolves\n * it against the currently-loaded runs. Read-only navigational affordance:\n * selecting opens the detail panel; `open` additionally opens the run's record\n * in the entity workspace. Neither executes a test.\n */\n private subscribeToAgentSelectionIntents(): void {\n let lastNonce = -1;\n combineLatest([\n this.instrumentationService.runSelectionIntent$,\n this.instrumentationService.testRunsWithFeedback$,\n ]).pipe(\n takeUntil(this.destroy$)\n ).subscribe(([intent, runs]) => {\n if (!intent || intent.nonce === lastNonce) {\n return;\n }\n const run = runs.find(r => r.id.toLowerCase() === intent.runId.toLowerCase());\n if (!run) {\n return; // Run not in the loaded set yet; a later testRunsWithFeedback$ tick may carry it.\n }\n lastNonce = intent.nonce;\n this.SelectRun(run);\n if (intent.open) {\n SharedService.Instance.OpenEntityRecord('MJ: Test Runs', CompositeKey.FromID(run.id));\n }\n this.emitStateChange();\n this.cdr.markForCheck();\n });\n }\n\n /**\n * Apply agent-driven filter intents published on the shared instrumentation\n * service (from the Testing dashboard's `FilterTestsByStatus` / `SearchTests`\n * client tools). Decouples those tools from this component's lifetime — the\n * intent is replayed via BehaviorSubject when this surface mounts.\n */\n private subscribeToAgentFilterIntents(): void {\n this.instrumentationService.runsFilterIntent$.pipe(\n takeUntil(this.destroy$)\n ).subscribe(intent => {\n if (!intent) return;\n let changed = false;\n if (intent.status && intent.status !== this.filterState.status) {\n this.filterState.status = intent.status;\n changed = true;\n }\n if (intent.searchText != null && intent.searchText !== this.filterState.searchText) {\n this.filterState.searchText = intent.searchText;\n changed = true;\n }\n if (changed) {\n this.filterTrigger$.next();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n });\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n @HostListener('document:keydown.escape')\n OnEscapeKey(): void {\n if (this.SelectedRun) {\n this.CloseDetailPanel();\n }\n }\n\n // ------- Public Methods -------\n\n SetStatusFilter(status: StatusFilter): void {\n this.filterState.status = status;\n this.filterTrigger$.next();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n OnTimeRangeChange(event: Event): void {\n const select = event.target as HTMLSelectElement;\n this.filterState.timeRange = select.value as TimeRange;\n this.updateServiceDateRange();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n OnSearchInput(event: Event): void {\n const input = event.target as HTMLInputElement;\n this.filterState.searchText = input.value;\n this.filterTrigger$.next();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n ClearSearch(): void {\n this.filterState.searchText = '';\n this.filterTrigger$.next();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n Refresh(): void {\n this.IsRefreshing = true;\n this.instrumentationService.refresh();\n setTimeout(() => {\n this.IsRefreshing = false;\n this.cdr.markForCheck();\n }, 1000);\n }\n\n StartNewTest(): void {\n console.log('[TestingRuns] StartNewTest called, service IsPanelOpen before:', this.testingDialogService.IsPanelOpen);\n this.testingDialogService.OpenAsPanel();\n console.log('[TestingRuns] After OpenAsPanel, IsPanelOpen:', this.testingDialogService.IsPanelOpen);\n }\n\n SelectRun(run: TestRunWithFeedbackSummary): void {\n this.SelectedRun = run;\n this.resetFeedbackForm();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n CloseDetailPanel(): void {\n this.SelectedRun = null;\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n NavigateToTest(run: TestRunWithFeedbackSummary, event: MouseEvent): void {\n event.stopPropagation();\n SharedService.Instance.OpenEntityRecord('MJ: Test Runs', CompositeKey.FromID(run.id));\n }\n\n RerunTest(run: TestRunWithFeedbackSummary): void {\n if (!run.testId) return;\n this.testingDialogService.OpenTestPanel(run.testId);\n }\n\n async SubmitFeedback(): Promise<void> {\n if (!this.SelectedRun) return;\n\n this.IsSubmittingFeedback = true;\n this.cdr.markForCheck();\n\n const success = await this.instrumentationService.submitFeedback(\n this.SelectedRun.id,\n this.feedbackRating,\n this.feedbackIsCorrect === true,\n this.feedbackComments\n );\n\n this.IsSubmittingFeedback = false;\n\n if (success) {\n // Update the selected run to reflect feedback was submitted\n this.SelectedRun = {\n ...this.SelectedRun,\n hasHumanFeedback: true,\n humanRating: this.feedbackRating,\n humanIsCorrect: this.feedbackIsCorrect,\n humanComments: this.feedbackComments\n };\n }\n\n this.cdr.markForCheck();\n }\n\n OnFeedbackCommentInput(event: Event): void {\n const textarea = event.target as HTMLTextAreaElement;\n this.feedbackComments = textarea.value;\n }\n\n TrackByRunId(_index: number, run: TestRunWithFeedbackSummary): string {\n return run.id;\n }\n\n // ------- Formatting Helpers -------\n\n FormatDuration(milliseconds: number): string {\n if (milliseconds < 1000) return `${Math.round(milliseconds)}ms`;\n const seconds = Math.floor(milliseconds / 1000);\n const minutes = Math.floor(seconds / 60);\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\n return `${seconds}s`;\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 diffMinutes = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n\n if (diffMinutes < 1) return 'Just now';\n if (diffMinutes < 60) return `${diffMinutes}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n\n return this.formatShortDate(date);\n }\n\n FormatDateTime(date: Date): string {\n const d = date instanceof Date ? date : new Date(date);\n return d.toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit'\n });\n }\n\n FormatPercent(value: number): string {\n return `${Math.round(value)}%`;\n }\n\n FormatCostTotal(cost: number): string {\n if (cost < 0.01) return '$0.00';\n if (cost < 1) return `$${cost.toFixed(2)}`;\n return `$${cost.toFixed(2)}`;\n }\n\n // ------- Private Methods -------\n\n private setupObservables(): void {\n const data$ = this.instrumentationService.testRunsWithFeedback$.pipe(\n takeUntil(this.destroy$)\n );\n\n this.FilteredRuns$ = combineLatest([data$, this.filterTrigger$]).pipe(\n map(([runs]) => this.applyClientFilters(runs)),\n tap(runs => {\n this.latestVisibleRuns = runs;\n // Re-report so the dashboard's agent context reflects the visible set.\n this.emitStateChange();\n }),\n takeUntil(this.destroy$)\n );\n\n this.FilteredStats$ = this.FilteredRuns$.pipe(\n map(runs => this.computeStats(runs)),\n takeUntil(this.destroy$)\n );\n }\n\n private applyClientFilters(runs: TestRunWithFeedbackSummary[]): TestRunWithFeedbackSummary[] {\n let filtered = runs;\n\n filtered = this.filterByStatus(filtered);\n filtered = this.filterBySearch(filtered);\n filtered = this.sortRunsWithRunningFirst(filtered);\n\n return filtered;\n }\n\n private filterByStatus(runs: TestRunWithFeedbackSummary[]): TestRunWithFeedbackSummary[] {\n const status = this.filterState.status;\n if (status === 'all') return runs;\n\n const statusMap: Record<string, string[]> = {\n running: ['Running'],\n passed: ['Passed'],\n failed: ['Failed'],\n error: ['Error', 'Timeout']\n };\n\n const validStatuses = statusMap[status] ?? [];\n return runs.filter(r => validStatuses.includes(r.status));\n }\n\n private filterBySearch(runs: TestRunWithFeedbackSummary[]): TestRunWithFeedbackSummary[] {\n const text = this.filterState.searchText.toLowerCase().trim();\n if (!text) return runs;\n return runs.filter(r => r.testName.toLowerCase().includes(text));\n }\n\n private sortRunsWithRunningFirst(runs: TestRunWithFeedbackSummary[]): TestRunWithFeedbackSummary[] {\n return [...runs].sort((a, b) => {\n // Running tests at the top\n if (a.status === 'Running' && b.status !== 'Running') return -1;\n if (a.status !== 'Running' && b.status === 'Running') return 1;\n // Then by StartedAt DESC\n return b.runDateTime.getTime() - a.runDateTime.getTime();\n });\n }\n\n private computeStats(runs: TestRunWithFeedbackSummary[]): FilteredStats {\n const total = runs.length;\n if (total === 0) {\n return { totalRuns: 0, passRate: 0, avgDuration: 0, totalCost: 0 };\n }\n\n const passed = runs.filter(r => r.status === 'Passed').length;\n const passRate = (passed / total) * 100;\n\n const completedRuns = runs.filter(r => r.duration > 0 && r.status !== 'Running');\n const avgDuration = completedRuns.length > 0\n ? completedRuns.reduce((sum, r) => sum + r.duration, 0) / completedRuns.length\n : 0;\n\n const totalCost = runs.reduce((sum, r) => sum + r.cost, 0);\n\n return { totalRuns: total, passRate, avgDuration, totalCost };\n }\n\n private updateServiceDateRange(): void {\n const now = new Date();\n let startDate: Date;\n\n switch (this.filterState.timeRange) {\n case 'today':\n startDate = new Date(now);\n startDate.setHours(0, 0, 0, 0);\n break;\n case 'week':\n startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n break;\n case 'month':\n startDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);\n break;\n case '90days':\n startDate = new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000);\n break;\n default:\n startDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);\n break;\n }\n\n this.instrumentationService.setDateRange(startDate, now);\n }\n\n private applyInitialState(): void {\n if (!this.initialState) return;\n\n const state = this.initialState;\n if (state['status'] && typeof state['status'] === 'string') {\n this.filterState.status = state['status'] as StatusFilter;\n }\n if (state['timeRange'] && typeof state['timeRange'] === 'string') {\n this.filterState.timeRange = state['timeRange'] as TimeRange;\n }\n if (state['searchText'] && typeof state['searchText'] === 'string') {\n this.filterState.searchText = state['searchText'] as string;\n }\n }\n\n private emitStateChange(): void {\n this.stateChange.emit({\n status: this.filterState.status,\n timeRange: this.filterState.timeRange,\n searchText: this.filterState.searchText,\n // Richer state for the dashboard's agent context (selected run id+NAME,\n // visible run names + count, detail-panel state). Read-only — the dashboard\n // does not mutate this; it only publishes it to the agent.\n visibleRunCount: this.latestVisibleRuns.length,\n visibleRunNames: this.latestVisibleRuns.map(r => r.testName),\n selectedRunId: this.SelectedRun?.id ?? null,\n selectedRunName: this.SelectedRun?.testName ?? null,\n detailPanelOpen: this.SelectedRun != null\n });\n }\n\n private resetFeedbackForm(): void {\n this.feedbackRating = 5;\n this.feedbackIsCorrect = null;\n this.feedbackComments = '';\n this.IsSubmittingFeedback = false;\n }\n\n private formatShortDate(date: Date): string {\n const d = date instanceof Date ? date : new Date(date);\n return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"testing-runs.component.js","sourceRoot":"","sources":["../../../src/Testing/components/testing-runs.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAGT,KAAK,EACL,MAAM,EACN,YAAY,EAEZ,uBAAuB,EAEvB,YAAY,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAc,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,EAAyB,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;;;;;;;;;;IA6B7F,wBAAyD;;;IAAzD,qGAA0C;;;;IAA3B,6CAAyB;;;IAepC,wBAAyD;;;;IAPvD,AADF,AAJF,AADF,sCAAgB,wBAIqC,aACpC,2BACuD;IAAtB,uMAAW,gBAAS,KAAC;IAAC,iBAAoB;IACtF,iCAAsE;IAAzB,wLAAS,qBAAc,KAAC;IACnE,uBAAgC;IAAC,+BAA+B;IAAA,wBAAQ;IAG9E,AADE,AADE,AAD0E,iBAAO,EACxE,EACL,EACS;IACjB,oCAAc;IACZ,qGAA0C;IAE9C,AADE,iBAAe,EACA;;;;IATQ,eAAwB;IAAxB,6CAAwB;IAO9B,eAAyB;IAAzB,6CAAyB;;;IAoBhC,oBAA2B;;;IAAxB,2BAAmB;;;;IAP1B,kCAKC;IADC,yNAAS,qCAA2B,KAAC;IAErC,yGAAiB;IAGjB,YACF;IAAA,iBAAS;;;;IARP,qEAAkD;;IAIlD,cAEC;IAFD,uCAEC;IACD,cACF;IADE,8CACF;;;;IAyBA,kCAAqD;IAAxB,wMAAS,oBAAa,KAAC;IAClD,wBAAiC;IACnC,iBAAS;;;IAUX,AADF,AADF,+BAAuB,cACE,cACQ;IAAA,wBAAmC;IAAA,iBAAM;IAEpE,AADF,+BAAuB,cACG;IAAA,YAAqB;IAAA,iBAAM;IACnD,+BAAwB;IAAA,0BAAU;IAEtC,AADE,AADoC,iBAAM,EACpC,EACF;IAEJ,AADF,+BAAuB,eACO;IAAA,yBAAwC;IAAA,iBAAM;IAExE,AADF,gCAAuB,eACG;IAAA,aAAmC;IAAA,iBAAM;IACjE,gCAAwB;IAAA,0BAAS;IAErC,AADE,AADmC,iBAAM,EACnC,EACF;IAEJ,AADF,gCAAuB,eACW;IAAA,yBAAiC;IAAA,iBAAM;IAErE,AADF,gCAAuB,eACG;IAAA,aAAuC;IAAA,iBAAM;IACrE,gCAAwB;IAAA,6BAAY;IAExC,AADE,AADsC,iBAAM,EACtC,EACF;IAEJ,AADF,gCAAuB,eACO;IAAA,yBAAuC;IAAA,iBAAM;IAEvE,AADF,gCAAuB,eACG;IAAA,aAAsC;IAAA,iBAAM;IACpE,gCAAwB;IAAA,2BAAU;IAGxC,AADE,AADE,AADoC,iBAAM,EACpC,EACF,EACF;;;;IAzBwB,eAAqB;IAArB,wCAAqB;IAOrB,eAAmC;IAAnC,6DAAmC;IAOnC,eAAuC;IAAvC,iEAAuC;IAOvC,eAAsC;IAAtC,gEAAsC;;;IAoBlE,+BAA2B;IACzB,iCAAqD;IACvD,iBAAM;;;IAEN,qCAE4D;;;;IAG1D,+BAKC;IADC,qOAAS,yBAAc,KAAC;IAGtB,AADF,+BAA0B,eAC2C;IAAtC,4OAAS,sCAA2B,KAAC;IAChE,YACF;IACF,AADE,iBAAO,EACH;IACN,+BAA0B;IACxB,2CAYwB;IAC1B,iBAAM;IACN,+BAA2B;IACzB,0CAAgF;IAClF,iBAAM;IACN,+BAA8B;IAAA,YAAkC;IAAA,iBAAM;IACtE,gCAA0B;IACxB,wCAAuD;IACzD,iBAAM;IACN,gCAA0B;IAAA,aAAyC;IAAA,iBAAM;IAEvE,AADF,gCAA6B,kBACsE;IAAnD,yNAAS,yBAAc,wBAAE,wBAAwB,KAAC;IAC9F,yBAA+B;IACjC,iBAAS;IACT,mCAAgG;IAAnD,yNAAS,yBAAc,wBAAE,wBAAwB,KAAC;IAC7F,yBAAwC;IAG9C,AADE,AADE,iBAAS,EACL,EACF;;;;IAvCJ,AADA,0DAA6C,2FACG;IAK5C,eACF;IADE,iDACF;IAIE,eAA8B;IAS9B,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,gDAA8B,kCACD,4BACN,sCACU,sCACA,oCACF,oCACA,0CACM,8CACI,uCACV;IAKZ,eAAmB;IAAC,AAApB,qCAAmB,iBAAiB;IAE7B,eAAkC;IAAlC,6DAAkC;IAE5C,eAAiB;IAAjB,mCAAiB;IAEX,eAAyC;IAAzC,oEAAyC;;;IAlCvE,wJA4CC;;;;IA5CD,yDA4CC;;;IA4DK,AADF,+BAA4B,SACtB;IAAA,wBAAkC;IAAC,kCAAiB;IAAA,iBAAK;IAC7D,2CAMuB;IACzB,iBAAM;;;IANF,eAA+C;IAI/C,AADA,AADA,AADA,AADA,oEAA+C,mDACJ,2DACQ,6DACE,uEACU;;;IAe3D,wBAAyE;IAAC,qBAC5E;;;IACE,wBAAuE;IAAC,oBAC1E;;;IACE,oBACF;;;IAGA,+BAA+B;IAAA,YAA+B;IAAA,iBAAM;;;IAArC,cAA+B;IAA/B,sDAA+B;;;IAbhE,AADF,+BAA+B,eACA;IAAA,uBAAO;IAAA,iBAAO;IAC3C,gCAA6B;IAAA,YAAgC;IAAA,iBAAO;IACpE,gCAA6B;IAAA,wBAAQ;IAAA,iBAAO;IAC5C,gCAA6B;IAKzB,AAFA,AAFF,wHAA2C,kGAEQ,oGAE1C;IAGX,iBAAO;IACP,qIAAiC;IAGnC,iBAAM;;;IAdyB,eAAgC;IAAhC,gEAAgC;IAG3D,eAMC;IAND,uHAMC;IAEH,eAEC;IAFD,4DAEC;;;;IAQK,kCAIC;IADC,wRAA4B;IAE5B,YACF;IAAA,iBAAS;;;;IAJP,2DAAuC;IAGvC,cACF;IADE,sCACF;;;;IATJ,AADF,AADF,+BAA2B,cACD,YACf;IAAA,sBAAM;IAAA,iBAAQ;IACrB,+BAA4B;IAC1B,yJAQC;IAEL,AADE,iBAAM,EACF;IAEJ,AADF,+BAA6B,YACpB;IAAA,sCAAsB;IAAA,iBAAQ;IAEnC,AADF,gCAA0B,kBAKvB;IADC,oPAA6B,IAAI,KAAC;IAElC,yBAAiC;IAAC,sBACpC;IAAA,iBAAS;IACT,mCAIC;IADC,oPAA6B,KAAK,KAAC;IAEnC,yBAAiC;IAAC,qBACpC;IAEJ,AADE,AADE,iBAAS,EACL,EACF;IAEJ,AADF,gCAA0B,aACjB;IAAA,yBAAQ;IAAA,iBAAQ;IACvB,qCAKC;IADC,iOAAS,qCAA8B,KAAC;IAE5C,AADG,iBAAW,EACR;IACN,mCAIC;IAFC,yNAAS,uBAAgB,KAAC;IAG1B,yBAAuC;IACvC,aACF;IACF,AADE,iBAAS,EACL;;;IA/CA,eAQC;IARD,kCAQC;IAQC,eAA2C;IAA3C,2DAA2C;IAO3C,eAA4C;IAA5C,4DAA4C;IAY9C,eAA0B;IAA1B,+CAA0B;IAO5B,cAAiC;IAAjC,sDAAiC;IAGjC,eACF;IADE,kGACF;;;;IAzIV,+BAAyD;IAA7B,sMAAS,yBAAkB,KAAC;IAAC,iBAAM;IAIzD,AADF,AADF,AADF,+BAA0B,cACS,cACG,SAC5B;IAAA,YAA0B;IAAA,iBAAK;IACnC,4CAA6E;IAC/E,iBAAM;IACN,kCAAuD;IAA7B,yMAAS,yBAAkB,KAAC;IACpD,wBAAiC;IAErC,AADE,iBAAS,EACL;IAMA,AADF,AADF,AAFF,+BAA+B,eAED,eACC,gBACF;IAAA,sBAAK;IAAA,iBAAO;IACnC,2CAAwF;IAC1F,iBAAM;IAEJ,AADF,gCAA2B,gBACF;IAAA,yBAAQ;IAAA,iBAAO;IACtC,iCAAuB;IAAA,aAA0C;IACnE,AADmE,iBAAO,EACpE;IAEJ,AADF,gCAA2B,gBACF;IAAA,qBAAI;IAAA,iBAAO;IAClC,wCAA+D;IACjE,iBAAM;IAEJ,AADF,gCAA2B,gBACF;IAAA,wBAAO;IAAA,iBAAO;IACrC,iCAAuB;IAAA,aAA6C;IAExE,AADE,AADsE,iBAAO,EACvE,EACF;IAIJ,AADF,gCAA4B,UACtB;IAAA,yBAA2C;IAAC,4BAAU;IAAA,iBAAK;IAC/D,4CAYwB;IAC1B,iBAAM;IAGN,sHAA8B;IAe5B,AADF,gCAA6C,UACvC;IAAA,yBAAwC;IAAC,gCAAc;IAAA,iBAAK;IAmB9D,AAlBF,uHAAoC,iGAkB3B;IAwDf,AADE,AADE,iBAAM,EACF,EACF;;;IA1II,eAA0B;IAA1B,iDAA0B;IACP,cAA6B;IAA7B,kDAA6B;IAY7B,eAA2B;IAAC,AAA5B,gDAA2B,iBAAiB;IAI1C,eAA0C;IAA1C,wEAA0C;IAI/C,eAAyB;IAAzB,8CAAyB;IAIpB,eAA6C;IAA7C,2EAA6C;IAQpE,eAAsC;IAStC,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,2DAAsC,6CACD,uCACN,iDACU,iDACA,+CACF,+CACA,qDACM,yDACI,uCAClB;IAMnC,cAWC;IAXD,yDAWC;IAKC,eAuEC;IAvED,+DAuEC;;;;IAtSX,8BAAkE;IAAtC,uMAAkB,yBAAkB,KAAC;IAK3D,AADF,AADF,8BAAwB,cACG,cACG;IACxB,yGAYC;IACH,iBAAM;IACN,gCAA2B;IAAA,YAAkD;;IAC/E,AAD+E,iBAAO,EAChF;IAEJ,AADF,+BAA0B,kBAKvB;IADC,iMAAU,gCAAyB,KAAC;IAEpC,mCAAsB;IAAA,sBAAK;IAAA,iBAAS;IACpC,mCAAqB;IAAA,0BAAS;IAAA,iBAAS;IACvC,mCAAsB;IAAA,2BAAU;IAAA,iBAAS;IACzC,mCAAuB;IAAA,6BAAY;IACrC,AADqC,iBAAS,EACrC;IACT,gCAAwB;IACtB,yBAAkC;IAClC,kCAKE;IADA,8LAAS,4BAAqB,KAAC;IAJjC,iBAKE;IACF,0GAA8B;IAOpC,AADE,AADE,iBAAM,EACF,EACF;IAGN,wGAAwC;;IAoCpC,AADF,AADF,gCAAgC,eACJ,eACE;IAAA,0BAAS;IAAA,iBAAM;IACzC,gCAA0B;IAAA,2BAAU;IAAA,iBAAM;IAC1C,gCAA2B;IAAA,sBAAK;IAAA,iBAAM;IACtC,gCAA8B;IAAA,yBAAQ;IAAA,iBAAM;IAC5C,gCAA0B;IAAA,qBAAI;IAAA,iBAAM;IACpC,gCAA0B;IAAA,wBAAO;IAAA,iBAAM;IACvC,gCAA6B;IAAA,wBAAO;IACtC,AADsC,iBAAM,EACtC;IAEN,uGAAiD;;;IAQ/C,AAJA,wHAAkD,sEAI3C;IA+CX,iBAAM;IAGN,8FAAmB;IAiJrB,iBAAM;;;;;;IArSE,eAYC;IAZD,iCAYC;IAEwB,eAAkD;IAAlD,oIAAkD;IAK3E,eAA+B;IAA/B,oDAA+B;IAa7B,gBAAgC;IAAhC,qDAAgC;IAGlC,cAIC;IAJD,yDAIC;IAMP,cA+BC;IA/BD,6FA+BC;IAcC,gBAsDC;IAtDD,oMAsDC;IAIH,eAgJC;IAhJD,8CAgJC;;AAyuBP,MAAM,OAAO,oBAAoB;IA8CtB;IACC;IACA;IACA;IAhDD,YAAY,GAAmC,IAAI,CAAC;IAC7D,8FAA8F;IACrF,WAAW,GAAG,KAAK,CAAC;IACnB,WAAW,GAAG,IAAI,YAAY,EAA2B,CAAC;IAE5D,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;IAC/B,cAAc,GAAG,IAAI,eAAe,CAAO,SAAS,CAAC,CAAC;IAE9D,eAAe;IACf,WAAW,GAAoB;QAC7B,MAAM,EAAE,KAAK;QACb,SAAS,EAAE,OAAO;QAClB,UAAU,EAAE,EAAE;KACf,CAAC;IAEF,sBAAsB;IACtB,cAAc,GAAG,CAAC,CAAC;IACnB,iBAAiB,GAAmB,IAAI,CAAC;IACzC,gBAAgB,GAAG,EAAE,CAAC;IACtB,oBAAoB,GAAG,KAAK,CAAC;IAC7B,YAAY,GAAG,KAAK,CAAC;IAErB,WAAW,GAAsC,IAAI,CAAC;IAEtD,gFAAgF;IACxE,iBAAiB,GAAiC,EAAE,CAAC;IAE7D,eAAe,GAA0B,EAAE,GAAG,8BAA8B,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAE/F,cAAc;IACd,aAAa,CAA4C;IACzD,cAAc,CAA6B;IAE3C,YAAY;IACH,WAAW,GAAgE;QAClF,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE;QACxC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,6BAA6B,EAAE;QAC3E,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,mBAAmB,EAAE;QAC/D,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,mBAAmB,EAAE;QAC/D,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,kCAAkC,EAAE;KAC7E,CAAC;IAEO,YAAY,GAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAElE,YACS,sBAAqD,EACpD,oBAA0C,EAC1C,GAAsB,EACtB,gBAAkC;QAHnC,2BAAsB,GAAtB,sBAAsB,CAA+B;QACpD,yBAAoB,GAApB,oBAAoB,CAAsB;QAC1C,QAAG,GAAH,GAAG,CAAmB;QACtB,qBAAgB,GAAhB,gBAAgB,CAAkB;IACzC,CAAC;IAEJ,QAAQ;QACN,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC9B,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,CAAC,6BAA6B,EAAE,CAAC;QACrC,IAAI,CAAC,gCAAgC,EAAE,CAAC;IAC1C,CAAC;IAED;;;;;;;;OAQG;IACK,gCAAgC;QACtC,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;QACnB,aAAa,CAAC;YACZ,IAAI,CAAC,sBAAsB,CAAC,mBAAmB;YAC/C,IAAI,CAAC,sBAAsB,CAAC,qBAAqB;SAClD,CAAC,CAAC,IAAI,CACL,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CACzB,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE;YAC7B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC1C,OAAO;YACT,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;YAC9E,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,OAAO,CAAC,kFAAkF;YAC5F,CAAC;YACD,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC;YACzB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACpB,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBAChB,aAAa,CAAC,QAAQ,CAAC,gBAAgB,CAAC,eAAe,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YACxF,CAAC;YACD,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACK,6BAA6B;QACnC,IAAI,CAAC,sBAAsB,CAAC,iBAAiB,CAAC,IAAI,CAChD,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CACzB,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;YACnB,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;gBAC/D,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;gBACxC,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;YACD,IAAI,MAAM,CAAC,UAAU,IAAI,IAAI,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;gBACnF,IAAI,CAAC,WAAW,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;gBAChD,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;YACD,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;gBAC3B,IAAI,CAAC,eAAe,EAAE,CAAC;gBACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,WAAW;QACT,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAGD,WAAW;QACT,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,iCAAiC;IAEjC,eAAe,CAAC,MAAoB;QAClC,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;QACjC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IAED,iBAAiB,CAAC,KAAY;QAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,MAA2B,CAAC;QACjD,IAAI,CAAC,WAAW,CAAC,SAAS,GAAG,MAAM,CAAC,KAAkB,CAAC;QACvD,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC9B,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IAED,aAAa,CAAC,KAAY;QACxB,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B,CAAC;QAC/C,IAAI,CAAC,WAAW,CAAC,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1C,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IAED,WAAW;QACT,IAAI,CAAC,WAAW,CAAC,UAAU,GAAG,EAAE,CAAC;QACjC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IAED,OAAO;QACL,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,sBAAsB,CAAC,OAAO,EAAE,CAAC;QACtC,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC1B,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,CAAC;IAED,YAAY;QACV,OAAO,CAAC,GAAG,CAAC,gEAAgE,EAAE,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC;QACrH,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,+CAA+C,EAAE,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC;IACtG,CAAC;IAED,SAAS,CAAC,GAA+B;QACvC,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;QACvB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IAED,gBAAgB;QACd,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IAED,cAAc,CAAC,GAA+B,EAAE,KAAiB;QAC/D,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,aAAa,CAAC,QAAQ,CAAC,gBAAgB,CAAC,eAAe,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACxF,CAAC;IAED,SAAS,CAAC,GAA+B;QACvC,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,CAAC,oBAAoB,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QAE9B,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACjC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAExB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,cAAc,CAC9D,IAAI,CAAC,WAAW,CAAC,EAAE,EACnB,IAAI,CAAC,cAAc,EACnB,IAAI,CAAC,iBAAiB,KAAK,IAAI,EAC/B,IAAI,CAAC,gBAAgB,CACtB,CAAC;QAEF,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;QAElC,IAAI,OAAO,EAAE,CAAC;YACZ,4DAA4D;YAC5D,IAAI,CAAC,WAAW,GAAG;gBACjB,GAAG,IAAI,CAAC,WAAW;gBACnB,gBAAgB,EAAE,IAAI;gBACtB,WAAW,EAAE,IAAI,CAAC,cAAc;gBAChC,cAAc,EAAE,IAAI,CAAC,iBAAiB;gBACtC,aAAa,EAAE,IAAI,CAAC,gBAAgB;aACrC,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IAED,sBAAsB,CAAC,KAAY;QACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAA6B,CAAC;QACrD,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC,KAAK,CAAC;IACzC,CAAC;IAED,YAAY,CAAC,MAAc,EAAE,GAA+B;QAC1D,OAAO,GAAG,CAAC,EAAE,CAAC;IAChB,CAAC;IAED,qCAAqC;IAErC,cAAc,CAAC,YAAoB;QACjC,IAAI,YAAY,GAAG,IAAI;YAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC;QAChE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QACzC,IAAI,OAAO,GAAG,CAAC;YAAE,OAAO,GAAG,OAAO,KAAK,OAAO,GAAG,EAAE,GAAG,CAAC;QACvD,OAAO,GAAG,OAAO,GAAG,CAAC;IACvB,CAAC;IAED,kBAAkB,CAAC,IAAU;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;QAC9E,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC;QAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;QAE/C,IAAI,WAAW,GAAG,CAAC;YAAE,OAAO,UAAU,CAAC;QACvC,IAAI,WAAW,GAAG,EAAE;YAAE,OAAO,GAAG,WAAW,OAAO,CAAC;QACnD,IAAI,SAAS,GAAG,EAAE;YAAE,OAAO,GAAG,SAAS,OAAO,CAAC;QAE/C,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,cAAc,CAAC,IAAU;QACvB,MAAM,CAAC,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,OAAO,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE;YACjC,KAAK,EAAE,OAAO;YACd,GAAG,EAAE,SAAS;YACd,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;IACL,CAAC;IAED,aAAa,CAAC,KAAa;QACzB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;IACjC,CAAC;IAED,eAAe,CAAC,IAAY;QAC1B,IAAI,IAAI,GAAG,IAAI;YAAE,OAAO,OAAO,CAAC;QAChC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/B,CAAC;IAED,kCAAkC;IAE1B,gBAAgB;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,sBAAsB,CAAC,qBAAqB,CAAC,IAAI,CAClE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CACzB,CAAC;QAEF,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CACnE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAC9C,GAAG,CAAC,IAAI,CAAC,EAAE;YACT,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;YAC9B,uEAAuE;YACvE,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC,CAAC,EACF,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CACzB,CAAC;QAEF,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAC3C,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EACpC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CACzB,CAAC;IACJ,CAAC;IAEO,kBAAkB,CAAC,IAAkC;QAC3D,IAAI,QAAQ,GAAG,IAAI,CAAC;QAEpB,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzC,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzC,QAAQ,GAAG,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC;QAEnD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEO,cAAc,CAAC,IAAkC;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QACvC,IAAI,MAAM,KAAK,KAAK;YAAE,OAAO,IAAI,CAAC;QAElC,MAAM,SAAS,GAA6B;YAC1C,OAAO,EAAE,CAAC,SAAS,CAAC;YACpB,MAAM,EAAE,CAAC,QAAQ,CAAC;YAClB,MAAM,EAAE,CAAC,QAAQ,CAAC;YAClB,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;SAC5B,CAAC;QAEF,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,CAAC;IAEO,cAAc,CAAC,IAAkC;QACvD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QAC9D,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IACnE,CAAC;IAEO,wBAAwB,CAAC,IAAkC;QACjE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7B,2BAA2B;YAC3B,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,CAAC,CAAC,CAAC;YAChE,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,CAAC,CAAC;YAC/D,yBAAyB;YACzB,OAAO,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,YAAY,CAAC,IAAkC;QACrD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChB,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;QACrE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;QAC9D,MAAM,QAAQ,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC;QAExC,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;QACjF,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC;YAC1C,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG,aAAa,CAAC,MAAM;YAC9E,CAAC,CAAC,CAAC,CAAC;QAEN,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAE3D,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;IAChE,CAAC;IAEO,sBAAsB;QAC5B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,SAAe,CAAC;QAEpB,QAAQ,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;YACnC,KAAK,OAAO;gBACV,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC1B,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC/B,MAAM;YACR,KAAK,MAAM;gBACT,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;gBAC9D,MAAM;YACR,KAAK,OAAO;gBACV,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;gBAC/D,MAAM;YACR,KAAK,QAAQ;gBACX,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;gBAC/D,MAAM;YACR;gBACE,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;gBAC/D,MAAM;QACV,CAAC;QAED,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC3D,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO;QAE/B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC;QAChC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC3D,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAiB,CAAC;QAC5D,CAAC;QACD,IAAI,KAAK,CAAC,WAAW,CAAC,IAAI,OAAO,KAAK,CAAC,WAAW,CAAC,KAAK,QAAQ,EAAE,CAAC;YACjE,IAAI,CAAC,WAAW,CAAC,SAAS,GAAG,KAAK,CAAC,WAAW,CAAc,CAAC;QAC/D,CAAC;QACD,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,OAAO,KAAK,CAAC,YAAY,CAAC,KAAK,QAAQ,EAAE,CAAC;YACnE,IAAI,CAAC,WAAW,CAAC,UAAU,GAAG,KAAK,CAAC,YAAY,CAAW,CAAC;QAC9D,CAAC;IACH,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YACpB,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM;YAC/B,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS;YACrC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,UAAU;YACvC,wEAAwE;YACxE,4EAA4E;YAC5E,2DAA2D;YAC3D,eAAe,EAAE,IAAI,CAAC,iBAAiB,CAAC,MAAM;YAC9C,eAAe,EAAE,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC5D,aAAa,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,IAAI;YAC3C,eAAe,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,IAAI,IAAI;YACnD,eAAe,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI;SAC1C,CAAC,CAAC;IACL,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;IACpC,CAAC;IAEO,eAAe,CAAC,IAAU;QAChC,MAAM,CAAC,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,OAAO,CAAC,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAC7E,CAAC;8GApbU,oBAAoB;6DAApB,oBAAoB;YAApB,2GAAA,iBAAa,0BAAO;;YAviC3B,AAFF,4FAAmB,yEAEV;YAmBT,wHAAsB;;YArBtB,yCAmBC;;;iFAshCQ,oBAAoB;cA9iChC,SAAS;6BACI,KAAK,YACP,kBAAkB,mBACX,uBAAuB,CAAC,MAAM,YACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoUT;;kBAuuBA,KAAK;;kBAEL,KAAK;;kBACL,MAAM;;kBA2HN,YAAY;mBAAC,yBAAyB;;kFA/H5B,oBAAoB","sourcesContent":["import {\n Component,\n OnInit,\n OnDestroy,\n Input,\n Output,\n EventEmitter,\n ChangeDetectorRef,\n ChangeDetectionStrategy,\n ViewContainerRef,\n HostListener\n} from '@angular/core';\nimport { Observable, Subject, BehaviorSubject, combineLatest } from 'rxjs';\nimport { takeUntil, map, tap } from 'rxjs/operators';\nimport { CompositeKey } from '@memberjunction/core';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { TestingDialogService } from '@memberjunction/ng-testing';\nimport { EvaluationPreferences, DEFAULT_EVALUATION_PREFERENCES } from '@memberjunction/ng-testing';\nimport {\n TestingInstrumentationService,\n TestRunWithFeedbackSummary,\n EvaluationSummaryMetrics\n} from '../services/testing-instrumentation.service';\n\ntype StatusFilter = 'all' | 'running' | 'passed' | 'failed' | 'error';\ntype TimeRange = 'today' | 'week' | 'month' | '90days';\n\ninterface RunsFilterState {\n status: StatusFilter;\n timeRange: TimeRange;\n searchText: string;\n}\n\ninterface FilteredStats {\n totalRuns: number;\n passRate: number;\n avgDuration: number;\n totalCost: number;\n}\n\n@Component({\n standalone: false,\n selector: 'app-testing-runs',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n @if (HideToolbar) {\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n } @else {\n <mj-page-layout>\n <mj-page-header\n Title=\"Test Runs\"\n Icon=\"fa-solid fa-list-check\"\n Subtitle=\"Test execution history and monitoring\">\n <div actions>\n <mj-refresh-button [Loading]=\"IsRefreshing\" (Clicked)=\"Refresh()\"></mj-refresh-button>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"StartNewTest()\">\n <i class=\"fa-solid fa-play\"></i> <span class=\"action-btn-label\">Run Test</span>\n </button>\n </div>\n </mj-page-header>\n <mj-page-body>\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n </mj-page-body>\n </mj-page-layout>\n }\n\n <ng-template #content>\n <div class=\"runs-container\" (keydown.escape)=\"CloseDetailPanel()\">\n\n <!-- Filter Bar -->\n <div class=\"filter-bar\">\n <div class=\"filter-left\">\n <div class=\"filter-chips\">\n @for (chip of StatusChips; track chip.value) {\n <button\n class=\"chip\"\n [class.active]=\"filterState.status === chip.value\"\n [attr.data-status]=\"chip.value\"\n (click)=\"SetStatusFilter(chip.value)\"\n >\n @if (chip.icon) {\n <i [class]=\"chip.icon\"></i>\n }\n {{ chip.label }}\n </button>\n }\n </div>\n <span class=\"result-count\">{{ (FilteredRuns$ | async)?.length ?? 0 }} results</span>\n </div>\n <div class=\"filter-right\">\n <select\n class=\"time-select\"\n [value]=\"filterState.timeRange\"\n (change)=\"OnTimeRangeChange($event)\"\n >\n <option value=\"today\">Today</option>\n <option value=\"week\">This Week</option>\n <option value=\"month\">This Month</option>\n <option value=\"90days\">Last 90 Days</option>\n </select>\n <div class=\"search-box\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search by test name...\"\n [value]=\"filterState.searchText\"\n (input)=\"OnSearchInput($event)\"\n />\n @if (filterState.searchText) {\n <button class=\"clear-search\" (click)=\"ClearSearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Summary Stats Row -->\n @if (FilteredStats$ | async; as stats) {\n <div class=\"stats-row\">\n <div class=\"stat-card\">\n <div class=\"stat-icon total\"><i class=\"fa-solid fa-hashtag\"></i></div>\n <div class=\"stat-body\">\n <div class=\"stat-value\">{{ stats.totalRuns }}</div>\n <div class=\"stat-label\">Total Runs</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon pass\"><i class=\"fa-solid fa-check-circle\"></i></div>\n <div class=\"stat-body\">\n <div class=\"stat-value\">{{ FormatPercent(stats.passRate) }}</div>\n <div class=\"stat-label\">Pass Rate</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon duration\"><i class=\"fa-solid fa-clock\"></i></div>\n <div class=\"stat-body\">\n <div class=\"stat-value\">{{ FormatDuration(stats.avgDuration) }}</div>\n <div class=\"stat-label\">Avg Duration</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon cost\"><i class=\"fa-solid fa-dollar-sign\"></i></div>\n <div class=\"stat-body\">\n <div class=\"stat-value\">{{ FormatCostTotal(stats.totalCost) }}</div>\n <div class=\"stat-label\">Total Cost</div>\n </div>\n </div>\n </div>\n }\n\n <!-- Runs Table -->\n <div class=\"runs-table-wrapper\">\n <div class=\"table-header\">\n <div class=\"col col-name\">Test Name</div>\n <div class=\"col col-eval\">Evaluation</div>\n <div class=\"col col-score\">Score</div>\n <div class=\"col col-duration\">Duration</div>\n <div class=\"col col-cost\">Cost</div>\n <div class=\"col col-time\">Started</div>\n <div class=\"col col-actions\">Actions</div>\n </div>\n\n @if (instrumentationService.isLoading$ | async) {\n <div class=\"table-loading\">\n <mj-loading text=\"Loading test runs...\"></mj-loading>\n </div>\n } @else if ((FilteredRuns$ | async)?.length === 0) {\n <mj-empty-state Variant=\"no-results\" Icon=\"fa-solid fa-inbox\"\n Title=\"No test runs found\"\n Message=\"Try adjusting your filters or run a new test.\" />\n } @else {\n @for (run of FilteredRuns$ | async; track TrackByRunId($index, run)) {\n <div\n class=\"table-row\"\n [class.is-running]=\"run.status === 'Running'\"\n [class.is-selected]=\"SelectedRun?.id === run.id\"\n (click)=\"SelectRun(run)\"\n >\n <div class=\"col col-name\">\n <span class=\"test-name-link\" (click)=\"NavigateToTest(run, $event)\">\n {{ run.testName }}\n </span>\n </div>\n <div class=\"col col-eval\">\n <app-evaluation-badge\n [executionStatus]=\"run.status\"\n [originalStatus]=\"run.status\"\n [autoScore]=\"run.score\"\n [passedChecks]=\"run.passedChecks\"\n [failedChecks]=\"run.failedChecks\"\n [totalChecks]=\"run.totalChecks\"\n [humanRating]=\"run.humanRating\"\n [humanIsCorrect]=\"run.humanIsCorrect\"\n [hasHumanFeedback]=\"run.hasHumanFeedback\"\n [preferences]=\"EvalPreferences\"\n mode=\"compact\"\n ></app-evaluation-badge>\n </div>\n <div class=\"col col-score\">\n <app-score-indicator [score]=\"run.score\" [showBar]=\"true\"></app-score-indicator>\n </div>\n <div class=\"col col-duration\">{{ FormatDuration(run.duration) }}</div>\n <div class=\"col col-cost\">\n <app-cost-display [cost]=\"run.cost\"></app-cost-display>\n </div>\n <div class=\"col col-time\">{{ FormatRelativeTime(run.runDateTime) }}</div>\n <div class=\"col col-actions\">\n <button class=\"icon-btn\" title=\"View details\" (click)=\"SelectRun(run); $event.stopPropagation()\">\n <i class=\"fa-solid fa-eye\"></i>\n </button>\n <button class=\"icon-btn\" title=\"Re-run test\" (click)=\"RerunTest(run); $event.stopPropagation()\">\n <i class=\"fa-solid fa-rotate-right\"></i>\n </button>\n </div>\n </div>\n }\n }\n </div>\n\n <!-- Detail Panel (slide-in) -->\n @if (SelectedRun) {\n <div class=\"detail-overlay\" (click)=\"CloseDetailPanel()\"></div>\n <div class=\"detail-panel\">\n <div class=\"detail-panel-header\">\n <div class=\"detail-title-section\">\n <h3>{{ SelectedRun.testName }}</h3>\n <app-test-status-badge [status]=\"SelectedRun.status\"></app-test-status-badge>\n </div>\n <button class=\"close-btn\" (click)=\"CloseDetailPanel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"detail-panel-body\">\n <!-- Metrics row -->\n <div class=\"detail-metrics\">\n <div class=\"detail-metric\">\n <span class=\"dm-label\">Score</span>\n <app-score-indicator [score]=\"SelectedRun.score\" [showBar]=\"true\"></app-score-indicator>\n </div>\n <div class=\"detail-metric\">\n <span class=\"dm-label\">Duration</span>\n <span class=\"dm-value\">{{ FormatDuration(SelectedRun.duration) }}</span>\n </div>\n <div class=\"detail-metric\">\n <span class=\"dm-label\">Cost</span>\n <app-cost-display [cost]=\"SelectedRun.cost\"></app-cost-display>\n </div>\n <div class=\"detail-metric\">\n <span class=\"dm-label\">Started</span>\n <span class=\"dm-value\">{{ FormatDateTime(SelectedRun.runDateTime) }}</span>\n </div>\n </div>\n\n <!-- Evaluation Badge (expanded) -->\n <div class=\"detail-section\">\n <h4><i class=\"fa-solid fa-clipboard-check\"></i> Evaluation</h4>\n <app-evaluation-badge\n [executionStatus]=\"SelectedRun.status\"\n [originalStatus]=\"SelectedRun.status\"\n [autoScore]=\"SelectedRun.score\"\n [passedChecks]=\"SelectedRun.passedChecks\"\n [failedChecks]=\"SelectedRun.failedChecks\"\n [totalChecks]=\"SelectedRun.totalChecks\"\n [humanRating]=\"SelectedRun.humanRating\"\n [humanIsCorrect]=\"SelectedRun.humanIsCorrect\"\n [hasHumanFeedback]=\"SelectedRun.hasHumanFeedback\"\n [preferences]=\"EvalPreferences\"\n mode=\"expanded\"\n ></app-evaluation-badge>\n </div>\n\n <!-- Execution Context -->\n @if (SelectedRun.targetType) {\n <div class=\"detail-section\">\n <h4><i class=\"fa-solid fa-server\"></i> Execution Context</h4>\n <mj-execution-context\n [machineName]=\"SelectedRun.machineName ?? null\"\n [machineId]=\"SelectedRun.machineID ?? null\"\n [runByUserName]=\"SelectedRun.runByUserName ?? null\"\n [runByUserEmail]=\"SelectedRun.runByUserEmail ?? null\"\n [runContextDetailsJson]=\"SelectedRun.runContextDetails ?? null\">\n </mj-execution-context>\n </div>\n }\n\n <!-- Inline Feedback Form -->\n <div class=\"detail-section feedback-section\">\n <h4><i class=\"fa-solid fa-comment-dots\"></i> Human Feedback</h4>\n @if (SelectedRun.hasHumanFeedback) {\n <div class=\"existing-feedback\">\n <span class=\"feedback-label\">Rating:</span>\n <span class=\"feedback-value\">{{ SelectedRun.humanRating }}/10</span>\n <span class=\"feedback-label\">Correct:</span>\n <span class=\"feedback-value\">\n @if (SelectedRun.humanIsCorrect === true) {\n <i class=\"fa-solid fa-check\" style=\"color: var(--mj-status-success)\"></i> Yes\n } @else if (SelectedRun.humanIsCorrect === false) {\n <i class=\"fa-solid fa-times\" style=\"color: var(--mj-status-error)\"></i> No\n } @else {\n --\n }\n </span>\n @if (SelectedRun.humanComments) {\n <div class=\"feedback-comments\">{{ SelectedRun.humanComments }}</div>\n }\n </div>\n } @else {\n <div class=\"feedback-form\">\n <div class=\"rating-row\">\n <label>Rating</label>\n <div class=\"rating-buttons\">\n @for (n of RatingValues; track n) {\n <button\n class=\"rating-btn\"\n [class.selected]=\"feedbackRating === n\"\n (click)=\"feedbackRating = n\"\n >\n {{ n }}\n </button>\n }\n </div>\n </div>\n <div class=\"correctness-row\">\n <label>Is the result correct?</label>\n <div class=\"toggle-group\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"feedbackIsCorrect === true\"\n (click)=\"feedbackIsCorrect = true\"\n >\n <i class=\"fa-solid fa-check\"></i> Yes\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"feedbackIsCorrect === false\"\n (click)=\"feedbackIsCorrect = false\"\n >\n <i class=\"fa-solid fa-times\"></i> No\n </button>\n </div>\n </div>\n <div class=\"comments-row\">\n <label>Comments</label>\n <textarea\n rows=\"3\"\n placeholder=\"Optional feedback comments...\"\n [value]=\"feedbackComments\"\n (input)=\"OnFeedbackCommentInput($event)\"\n ></textarea>\n </div>\n <button\n class=\"btn btn-primary submit-feedback-btn\"\n (click)=\"SubmitFeedback()\"\n [disabled]=\"IsSubmittingFeedback\"\n >\n <i class=\"fa-solid fa-paper-plane\"></i>\n {{ IsSubmittingFeedback ? 'Submitting...' : 'Submit Feedback' }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </ng-template>\n `,\n styles: [`\n /* ==========================================\n Testing Runs Component\n ========================================== */\n\n .runs-container {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-surface-card);\n position: relative;\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 }\n\n .header-title {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .header-title i {\n font-size: 22px;\n color: var(--mj-brand-primary);\n }\n\n .header-title h2 {\n margin: 0;\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n }\n\n .header-actions {\n display: flex;\n gap: 10px;\n }\n\n /* Buttons */\n .btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 10px 18px;\n border: none;\n border-radius: 10px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n }\n\n .btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-md);\n }\n\n .btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n }\n\n .btn-secondary:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n }\n\n .spinning {\n animation: spin 1s linear infinite;\n }\n\n @keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n /* Filter Bar */\n .filter-bar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n margin-bottom: 20px;\n padding: 14px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n }\n\n .filter-left {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .filter-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 14px;\n background: var(--mj-bg-surface-sunken);\n border: 2px solid transparent;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .chip:hover {\n background: var(--mj-border-default);\n }\n\n .chip.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n }\n\n .chip.active[data-status=\"running\"] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n }\n\n .chip.active[data-status=\"passed\"] {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n }\n\n .chip.active[data-status=\"failed\"] {\n background: var(--mj-status-error);\n border-color: var(--mj-status-error);\n }\n\n .chip.active[data-status=\"error\"] {\n background: var(--mj-status-warning);\n border-color: var(--mj-status-warning);\n }\n\n .result-count {\n font-size: 12px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n white-space: nowrap;\n }\n\n .filter-right {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .time-select {\n padding: 8px 12px;\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n }\n\n .time-select:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n }\n\n .search-box {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n background: var(--mj-bg-surface-card);\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n min-width: 220px;\n transition: border-color 0.2s ease;\n }\n\n .search-box:focus-within {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n }\n\n .search-box i {\n color: var(--mj-text-disabled);\n font-size: 13px;\n }\n\n .search-box input {\n flex: 1;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: var(--mj-text-secondary);\n }\n\n .search-box input::placeholder {\n color: var(--mj-text-disabled);\n }\n\n .clear-search {\n border: none;\n background: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 4px;\n }\n\n .clear-search:hover {\n color: var(--mj-text-muted);\n background: var(--mj-border-default);\n }\n\n /* Stats Row */\n .stats-row {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 14px;\n margin-bottom: 20px;\n }\n\n .stat-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n }\n\n .stat-icon {\n width: 42px;\n height: 42px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n }\n\n .stat-icon.total { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n .stat-icon.pass { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n .stat-icon.duration { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n .stat-icon.cost { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n\n .stat-body {\n flex: 1;\n }\n\n .stat-value {\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.1;\n }\n\n .stat-label {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-top: 2px;\n }\n\n /* Runs Table */\n .runs-table-wrapper {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n }\n\n .table-header {\n display: grid;\n grid-template-columns: 2fr 140px 120px 100px 100px 120px 90px;\n gap: 12px;\n padding: 14px 24px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 11px;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .table-row {\n display: grid;\n grid-template-columns: 2fr 140px 120px 100px 100px 120px 90px;\n gap: 12px;\n padding: 14px 24px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n cursor: pointer;\n transition: background 0.15s ease;\n align-items: center;\n }\n\n .table-row:last-child {\n border-bottom: none;\n }\n\n .table-row:hover {\n background: var(--mj-bg-surface-card);\n }\n\n .table-row.is-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 6%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n }\n\n .table-row.is-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 4%, var(--mj-bg-surface));\n }\n\n .table-row.is-running .test-name-link::after {\n content: '';\n display: inline-block;\n width: 8px;\n height: 8px;\n background: var(--mj-brand-primary);\n border-radius: 50%;\n margin-left: 8px;\n animation: pulse-dot 1.5s infinite;\n }\n\n @keyframes pulse-dot {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.3; }\n }\n\n .col {\n display: flex;\n align-items: center;\n font-size: 13px;\n color: var(--mj-text-secondary);\n overflow: hidden;\n }\n\n .test-name-link {\n font-weight: 600;\n color: var(--mj-text-primary);\n cursor: pointer;\n text-decoration: none;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .test-name-link:hover {\n color: var(--mj-brand-primary);\n text-decoration: underline;\n }\n\n .col-actions {\n gap: 6px;\n justify-content: flex-end;\n }\n\n .icon-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n color: var(--mj-text-muted);\n cursor: pointer;\n border-radius: 8px;\n font-size: 13px;\n transition: all 0.2s ease;\n }\n\n .icon-btn:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-md);\n }\n\n /* Table states */\n .table-loading {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 80px 40px;\n }\n\n /* Detail Panel Overlay */\n .detail-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 999;\n }\n\n /* Detail Panel */\n .detail-panel {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 520px;\n max-width: 90vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-lg);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n animation: slideIn 0.25s ease-out;\n }\n\n @keyframes slideIn {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n }\n\n .detail-panel-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n }\n\n .detail-title-section {\n display: flex;\n flex-direction: column;\n gap: 8px;\n flex: 1;\n min-width: 0;\n }\n\n .detail-title-section h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .close-btn {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 14px;\n flex-shrink: 0;\n margin-left: 12px;\n transition: all 0.15s ease;\n }\n\n .close-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .detail-panel-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px 24px;\n }\n\n .detail-metrics {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n margin-bottom: 24px;\n }\n\n .detail-metric {\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n border-left: 3px solid var(--mj-brand-primary);\n }\n\n .dm-label {\n display: block;\n font-size: 10px;\n font-weight: 700;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n }\n\n .dm-value {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n\n .detail-section {\n margin-bottom: 24px;\n }\n\n .detail-section h4 {\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .detail-section h4 i {\n color: var(--mj-brand-primary);\n font-size: 14px;\n }\n\n /* Feedback Section */\n .existing-feedback {\n display: flex;\n flex-wrap: wrap;\n gap: 8px 16px;\n align-items: center;\n padding: 14px;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n font-size: 13px;\n }\n\n .feedback-label {\n font-weight: 600;\n color: var(--mj-text-muted);\n }\n\n .feedback-value {\n color: var(--mj-text-primary);\n font-weight: 500;\n }\n\n .feedback-comments {\n width: 100%;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid color-mix(in srgb, var(--mj-status-success) 25%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-text-secondary);\n font-style: italic;\n }\n\n .feedback-form {\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n .feedback-form label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n margin-bottom: 6px;\n }\n\n .rating-buttons {\n display: flex;\n gap: 4px;\n }\n\n .rating-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 8px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.15s ease;\n }\n\n .rating-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n }\n\n .rating-btn.selected {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n }\n\n .toggle-group {\n display: flex;\n gap: 8px;\n }\n\n .toggle-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 8px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.15s ease;\n }\n\n .toggle-btn.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n .comments-row textarea {\n width: 100%;\n padding: 10px 12px;\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n font-family: inherit;\n color: var(--mj-text-secondary);\n resize: vertical;\n box-sizing: border-box;\n }\n\n .comments-row textarea:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n }\n\n .comments-row textarea::placeholder {\n color: var(--mj-text-disabled);\n }\n\n .submit-feedback-btn {\n align-self: flex-start;\n }\n\n /* Responsive */\n @media (max-width: 1400px) {\n .stats-row {\n grid-template-columns: repeat(2, 1fr);\n }\n }\n\n @media (max-width: 1200px) {\n .filter-bar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .filter-left, .filter-right {\n justify-content: center;\n }\n\n .table-header, .table-row {\n grid-template-columns: 2fr 120px 100px 100px 80px;\n }\n\n .col-eval, .col-time {\n display: none;\n }\n }\n\n @media (max-width: 768px) {\n .stats-row {\n grid-template-columns: 1fr;\n }\n\n .detail-panel {\n width: 100vw;\n max-width: 100vw;\n }\n }\n\n @media (max-width: 480px) {\n .table-header, .table-row {\n grid-template-columns: 1fr 80px 60px;\n }\n\n .col-score, .col-duration {\n display: none;\n }\n\n .chip {\n min-height: 44px;\n padding: 8px 14px;\n }\n\n .table-row {\n min-height: 44px;\n }\n }\n `]\n})\nexport class TestingRunsComponent implements OnInit, OnDestroy {\n @Input() initialState: Record<string, unknown> | null = null;\n /** When true, the inner bespoke .page-header is hidden — the parent shell owns the chrome. */\n @Input() HideToolbar = false;\n @Output() stateChange = new EventEmitter<Record<string, unknown>>();\n\n private destroy$ = new Subject<void>();\n private filterTrigger$ = new BehaviorSubject<void>(undefined);\n\n // Filter state\n filterState: RunsFilterState = {\n status: 'all',\n timeRange: 'month',\n searchText: ''\n };\n\n // Feedback form state\n feedbackRating = 5;\n feedbackIsCorrect: boolean | null = null;\n feedbackComments = '';\n IsSubmittingFeedback = false;\n IsRefreshing = false;\n\n SelectedRun: TestRunWithFeedbackSummary | null = null;\n\n /** Latest filtered/visible runs, cached for state reporting (agent context). */\n private latestVisibleRuns: TestRunWithFeedbackSummary[] = [];\n\n EvalPreferences: EvaluationPreferences = { ...DEFAULT_EVALUATION_PREFERENCES, showAuto: true };\n\n // Observables\n FilteredRuns$!: Observable<TestRunWithFeedbackSummary[]>;\n FilteredStats$!: Observable<FilteredStats>;\n\n // Constants\n readonly StatusChips: Array<{ value: StatusFilter; label: string; icon: string }> = [\n { value: 'all', label: 'All', icon: '' },\n { value: 'running', label: 'Running', icon: 'fa-solid fa-spinner fa-spin' },\n { value: 'passed', label: 'Passed', icon: 'fa-solid fa-check' },\n { value: 'failed', label: 'Failed', icon: 'fa-solid fa-times' },\n { value: 'error', label: 'Error', icon: 'fa-solid fa-exclamation-triangle' }\n ];\n\n readonly RatingValues: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n\n constructor(\n public instrumentationService: TestingInstrumentationService,\n private testingDialogService: TestingDialogService,\n private cdr: ChangeDetectorRef,\n private viewContainerRef: ViewContainerRef\n ) {}\n\n ngOnInit(): void {\n this.applyInitialState();\n this.updateServiceDateRange();\n this.setupObservables();\n this.subscribeToAgentFilterIntents();\n this.subscribeToAgentSelectionIntents();\n }\n\n /**\n * Apply agent-driven run-SELECTION intents published on the shared\n * instrumentation service (from the dashboard's `SelectTestRun` / open-run\n * client tools). The dashboard owns no `SelectedRun` UI state — it publishes a\n * target run id (+ open flag + monotonic nonce) here, and this surface resolves\n * it against the currently-loaded runs. Read-only navigational affordance:\n * selecting opens the detail panel; `open` additionally opens the run's record\n * in the entity workspace. Neither executes a test.\n */\n private subscribeToAgentSelectionIntents(): void {\n let lastNonce = -1;\n combineLatest([\n this.instrumentationService.runSelectionIntent$,\n this.instrumentationService.testRunsWithFeedback$,\n ]).pipe(\n takeUntil(this.destroy$)\n ).subscribe(([intent, runs]) => {\n if (!intent || intent.nonce === lastNonce) {\n return;\n }\n const run = runs.find(r => r.id.toLowerCase() === intent.runId.toLowerCase());\n if (!run) {\n return; // Run not in the loaded set yet; a later testRunsWithFeedback$ tick may carry it.\n }\n lastNonce = intent.nonce;\n this.SelectRun(run);\n if (intent.open) {\n SharedService.Instance.OpenEntityRecord('MJ: Test Runs', CompositeKey.FromID(run.id));\n }\n this.emitStateChange();\n this.cdr.markForCheck();\n });\n }\n\n /**\n * Apply agent-driven filter intents published on the shared instrumentation\n * service (from the Testing dashboard's `FilterTestsByStatus` / `SearchTests`\n * client tools). Decouples those tools from this component's lifetime — the\n * intent is replayed via BehaviorSubject when this surface mounts.\n */\n private subscribeToAgentFilterIntents(): void {\n this.instrumentationService.runsFilterIntent$.pipe(\n takeUntil(this.destroy$)\n ).subscribe(intent => {\n if (!intent) return;\n let changed = false;\n if (intent.status && intent.status !== this.filterState.status) {\n this.filterState.status = intent.status;\n changed = true;\n }\n if (intent.searchText != null && intent.searchText !== this.filterState.searchText) {\n this.filterState.searchText = intent.searchText;\n changed = true;\n }\n if (changed) {\n this.filterTrigger$.next();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n });\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n @HostListener('document:keydown.escape')\n OnEscapeKey(): void {\n if (this.SelectedRun) {\n this.CloseDetailPanel();\n }\n }\n\n // ------- Public Methods -------\n\n SetStatusFilter(status: StatusFilter): void {\n this.filterState.status = status;\n this.filterTrigger$.next();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n OnTimeRangeChange(event: Event): void {\n const select = event.target as HTMLSelectElement;\n this.filterState.timeRange = select.value as TimeRange;\n this.updateServiceDateRange();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n OnSearchInput(event: Event): void {\n const input = event.target as HTMLInputElement;\n this.filterState.searchText = input.value;\n this.filterTrigger$.next();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n ClearSearch(): void {\n this.filterState.searchText = '';\n this.filterTrigger$.next();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n Refresh(): void {\n this.IsRefreshing = true;\n this.instrumentationService.refresh();\n setTimeout(() => {\n this.IsRefreshing = false;\n this.cdr.markForCheck();\n }, 1000);\n }\n\n StartNewTest(): void {\n console.log('[TestingRuns] StartNewTest called, service IsPanelOpen before:', this.testingDialogService.IsPanelOpen);\n this.testingDialogService.OpenAsPanel();\n console.log('[TestingRuns] After OpenAsPanel, IsPanelOpen:', this.testingDialogService.IsPanelOpen);\n }\n\n SelectRun(run: TestRunWithFeedbackSummary): void {\n this.SelectedRun = run;\n this.resetFeedbackForm();\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n CloseDetailPanel(): void {\n this.SelectedRun = null;\n this.emitStateChange();\n this.cdr.markForCheck();\n }\n\n NavigateToTest(run: TestRunWithFeedbackSummary, event: MouseEvent): void {\n event.stopPropagation();\n SharedService.Instance.OpenEntityRecord('MJ: Test Runs', CompositeKey.FromID(run.id));\n }\n\n RerunTest(run: TestRunWithFeedbackSummary): void {\n if (!run.testId) return;\n this.testingDialogService.OpenTestPanel(run.testId);\n }\n\n async SubmitFeedback(): Promise<void> {\n if (!this.SelectedRun) return;\n\n this.IsSubmittingFeedback = true;\n this.cdr.markForCheck();\n\n const success = await this.instrumentationService.submitFeedback(\n this.SelectedRun.id,\n this.feedbackRating,\n this.feedbackIsCorrect === true,\n this.feedbackComments\n );\n\n this.IsSubmittingFeedback = false;\n\n if (success) {\n // Update the selected run to reflect feedback was submitted\n this.SelectedRun = {\n ...this.SelectedRun,\n hasHumanFeedback: true,\n humanRating: this.feedbackRating,\n humanIsCorrect: this.feedbackIsCorrect,\n humanComments: this.feedbackComments\n };\n }\n\n this.cdr.markForCheck();\n }\n\n OnFeedbackCommentInput(event: Event): void {\n const textarea = event.target as HTMLTextAreaElement;\n this.feedbackComments = textarea.value;\n }\n\n TrackByRunId(_index: number, run: TestRunWithFeedbackSummary): string {\n return run.id;\n }\n\n // ------- Formatting Helpers -------\n\n FormatDuration(milliseconds: number): string {\n if (milliseconds < 1000) return `${Math.round(milliseconds)}ms`;\n const seconds = Math.floor(milliseconds / 1000);\n const minutes = Math.floor(seconds / 60);\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\n return `${seconds}s`;\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 diffMinutes = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n\n if (diffMinutes < 1) return 'Just now';\n if (diffMinutes < 60) return `${diffMinutes}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n\n return this.formatShortDate(date);\n }\n\n FormatDateTime(date: Date): string {\n const d = date instanceof Date ? date : new Date(date);\n return d.toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit'\n });\n }\n\n FormatPercent(value: number): string {\n return `${Math.round(value)}%`;\n }\n\n FormatCostTotal(cost: number): string {\n if (cost < 0.01) return '$0.00';\n if (cost < 1) return `$${cost.toFixed(2)}`;\n return `$${cost.toFixed(2)}`;\n }\n\n // ------- Private Methods -------\n\n private setupObservables(): void {\n const data$ = this.instrumentationService.testRunsWithFeedback$.pipe(\n takeUntil(this.destroy$)\n );\n\n this.FilteredRuns$ = combineLatest([data$, this.filterTrigger$]).pipe(\n map(([runs]) => this.applyClientFilters(runs)),\n tap(runs => {\n this.latestVisibleRuns = runs;\n // Re-report so the dashboard's agent context reflects the visible set.\n this.emitStateChange();\n }),\n takeUntil(this.destroy$)\n );\n\n this.FilteredStats$ = this.FilteredRuns$.pipe(\n map(runs => this.computeStats(runs)),\n takeUntil(this.destroy$)\n );\n }\n\n private applyClientFilters(runs: TestRunWithFeedbackSummary[]): TestRunWithFeedbackSummary[] {\n let filtered = runs;\n\n filtered = this.filterByStatus(filtered);\n filtered = this.filterBySearch(filtered);\n filtered = this.sortRunsWithRunningFirst(filtered);\n\n return filtered;\n }\n\n private filterByStatus(runs: TestRunWithFeedbackSummary[]): TestRunWithFeedbackSummary[] {\n const status = this.filterState.status;\n if (status === 'all') return runs;\n\n const statusMap: Record<string, string[]> = {\n running: ['Running'],\n passed: ['Passed'],\n failed: ['Failed'],\n error: ['Error', 'Timeout']\n };\n\n const validStatuses = statusMap[status] ?? [];\n return runs.filter(r => validStatuses.includes(r.status));\n }\n\n private filterBySearch(runs: TestRunWithFeedbackSummary[]): TestRunWithFeedbackSummary[] {\n const text = this.filterState.searchText.toLowerCase().trim();\n if (!text) return runs;\n return runs.filter(r => r.testName.toLowerCase().includes(text));\n }\n\n private sortRunsWithRunningFirst(runs: TestRunWithFeedbackSummary[]): TestRunWithFeedbackSummary[] {\n return [...runs].sort((a, b) => {\n // Running tests at the top\n if (a.status === 'Running' && b.status !== 'Running') return -1;\n if (a.status !== 'Running' && b.status === 'Running') return 1;\n // Then by StartedAt DESC\n return b.runDateTime.getTime() - a.runDateTime.getTime();\n });\n }\n\n private computeStats(runs: TestRunWithFeedbackSummary[]): FilteredStats {\n const total = runs.length;\n if (total === 0) {\n return { totalRuns: 0, passRate: 0, avgDuration: 0, totalCost: 0 };\n }\n\n const passed = runs.filter(r => r.status === 'Passed').length;\n const passRate = (passed / total) * 100;\n\n const completedRuns = runs.filter(r => r.duration > 0 && r.status !== 'Running');\n const avgDuration = completedRuns.length > 0\n ? completedRuns.reduce((sum, r) => sum + r.duration, 0) / completedRuns.length\n : 0;\n\n const totalCost = runs.reduce((sum, r) => sum + r.cost, 0);\n\n return { totalRuns: total, passRate, avgDuration, totalCost };\n }\n\n private updateServiceDateRange(): void {\n const now = new Date();\n let startDate: Date;\n\n switch (this.filterState.timeRange) {\n case 'today':\n startDate = new Date(now);\n startDate.setHours(0, 0, 0, 0);\n break;\n case 'week':\n startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n break;\n case 'month':\n startDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);\n break;\n case '90days':\n startDate = new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000);\n break;\n default:\n startDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);\n break;\n }\n\n this.instrumentationService.setDateRange(startDate, now);\n }\n\n private applyInitialState(): void {\n if (!this.initialState) return;\n\n const state = this.initialState;\n if (state['status'] && typeof state['status'] === 'string') {\n this.filterState.status = state['status'] as StatusFilter;\n }\n if (state['timeRange'] && typeof state['timeRange'] === 'string') {\n this.filterState.timeRange = state['timeRange'] as TimeRange;\n }\n if (state['searchText'] && typeof state['searchText'] === 'string') {\n this.filterState.searchText = state['searchText'] as string;\n }\n }\n\n private emitStateChange(): void {\n this.stateChange.emit({\n status: this.filterState.status,\n timeRange: this.filterState.timeRange,\n searchText: this.filterState.searchText,\n // Richer state for the dashboard's agent context (selected run id+NAME,\n // visible run names + count, detail-panel state). Read-only — the dashboard\n // does not mutate this; it only publishes it to the agent.\n visibleRunCount: this.latestVisibleRuns.length,\n visibleRunNames: this.latestVisibleRuns.map(r => r.testName),\n selectedRunId: this.SelectedRun?.id ?? null,\n selectedRunName: this.SelectedRun?.testName ?? null,\n detailPanelOpen: this.SelectedRun != null\n });\n }\n\n private resetFeedbackForm(): void {\n this.feedbackRating = 5;\n this.feedbackIsCorrect = null;\n this.feedbackComments = '';\n this.IsSubmittingFeedback = false;\n }\n\n private formatShortDate(date: Date): string {\n const d = date instanceof Date ? date : new Date(date);\n return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });\n }\n}\n"]}
|
|
@@ -25,6 +25,11 @@ export interface TestRunSummary {
|
|
|
25
25
|
runDateTime: Date;
|
|
26
26
|
targetType: string;
|
|
27
27
|
targetLogID: string;
|
|
28
|
+
machineName?: string | null;
|
|
29
|
+
machineID?: string | null;
|
|
30
|
+
runByUserName?: string | null;
|
|
31
|
+
runByUserEmail?: string | null;
|
|
32
|
+
runContextDetails?: string | null;
|
|
28
33
|
}
|
|
29
34
|
export interface SuiteHierarchyNode {
|
|
30
35
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing-instrumentation.service.d.ts","sourceRoot":"","sources":["../../../src/Testing/services/testing-instrumentation.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAwC,MAAM,MAAM,CAAC;AAExE,OAAO,EAAqB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;;AAI5E,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,IAAI,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"testing-instrumentation.service.d.ts","sourceRoot":"","sources":["../../../src/Testing/services/testing-instrumentation.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -699,7 +699,7 @@ export class TestingInstrumentationService {
|
|
|
699
699
|
ExtraFilter: filter,
|
|
700
700
|
OrderBy: 'StartedAt DESC',
|
|
701
701
|
MaxRows: 1000,
|
|
702
|
-
Fields: ['ID', 'TestID', 'Test', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt', 'TargetType', 'TargetLogID', 'PassedChecks', 'FailedChecks', 'TotalChecks'],
|
|
702
|
+
Fields: ['ID', 'TestID', 'Test', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt', 'TargetType', 'TargetLogID', 'PassedChecks', 'FailedChecks', 'TotalChecks', 'MachineName', 'MachineID', 'RunByUserName', 'RunByUserEmail', 'RunContextDetails'],
|
|
703
703
|
ResultType: 'simple',
|
|
704
704
|
CacheLocal: true
|
|
705
705
|
},
|
|
@@ -749,7 +749,13 @@ export class TestingInstrumentationService {
|
|
|
749
749
|
humanIsCorrect: feedback?.IsCorrect ?? null,
|
|
750
750
|
humanComments: feedback?.Comments ?? null,
|
|
751
751
|
hasHumanFeedback: !!feedback,
|
|
752
|
-
feedbackId: feedback?.ID ?? null
|
|
752
|
+
feedbackId: feedback?.ID ?? null,
|
|
753
|
+
// Execution context
|
|
754
|
+
machineName: run.MachineName,
|
|
755
|
+
machineID: run.MachineID,
|
|
756
|
+
runByUserName: run.RunByUserName,
|
|
757
|
+
runByUserEmail: run.RunByUserEmail,
|
|
758
|
+
runContextDetails: run.RunContextDetails
|
|
753
759
|
};
|
|
754
760
|
});
|
|
755
761
|
}
|