@memberjunction/ng-dashboards 5.20.0 → 5.22.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/autotagging-pipeline-resource.component.d.ts +102 -0
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +583 -0
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +148 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +773 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +241 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -0
- package/dist/AI/components/vectors/vector-management-resource.component.js +1782 -0
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -0
- package/dist/AI/index.d.ts +3 -0
- package/dist/AI/index.d.ts.map +1 -1
- package/dist/AI/index.js +6 -0
- package/dist/AI/index.js.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.d.ts +50 -7
- package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.js +161 -193
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts +11 -0
- package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +57 -0
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +10 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +35 -11
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.d.ts +1 -0
- package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.js +8 -4
- package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.d.ts +181 -1
- package/dist/Home/home-dashboard.component.d.ts.map +1 -1
- package/dist/Home/home-dashboard.component.js +1704 -182
- package/dist/Home/home-dashboard.component.js.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +121 -0
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +1058 -0
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -0
- package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.d.ts +56 -0
- package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.js +291 -0
- package/dist/KnowledgeHub/components/results-detail/search-result-detail.component.js.map +1 -0
- package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.d.ts +85 -0
- package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.js +461 -0
- package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.js.map +1 -0
- package/dist/KnowledgeHub/index.d.ts +4 -0
- package/dist/KnowledgeHub/index.d.ts.map +1 -0
- package/dist/KnowledgeHub/index.js +5 -0
- package/dist/KnowledgeHub/index.js.map +1 -0
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +5 -1
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.js +1 -0
- package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.d.ts +7 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.js +63 -8
- package/dist/Testing/components/testing-dashboard-tab-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab.component.d.ts +9 -1
- package/dist/Testing/components/testing-dashboard-tab.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab.component.js +109 -62
- package/dist/Testing/components/testing-dashboard-tab.component.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +2 -1
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +241 -200
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-runs-resource.component.d.ts +7 -1
- package/dist/Testing/components/testing-runs-resource.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-runs-resource.component.js +63 -8
- package/dist/Testing/components/testing-runs-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-runs.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-runs.component.js +7 -5
- package/dist/Testing/components/testing-runs.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.d.ts +9 -1
- package/dist/Testing/testing-dashboard.component.d.ts.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +128 -59
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +26 -19
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +40 -5
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/core-dashboards.module.d.ts +1 -0
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +3 -0
- package/dist/core-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +4 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +5 -1
- package/dist/public-api.js.map +1 -1
- package/dist/testing-dashboards.module.d.ts +5 -4
- package/dist/testing-dashboards.module.d.ts.map +1 -1
- package/dist/testing-dashboards.module.js +4 -0
- package/dist/testing-dashboards.module.js.map +1 -1
- package/package.json +44 -42
|
@@ -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 } 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 <!-- Page Header -->\n <div class=\"runs-container\" (keydown.escape)=\"CloseDetailPanel()\">\n <div class=\"page-header\">\n <div class=\"header-title\">\n <i class=\"fa-solid fa-list-check\"></i>\n <h2>Test Runs</h2>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn btn-secondary\" (click)=\"Refresh()\" [disabled]=\"IsRefreshing\">\n <i class=\"fa-solid fa-sync-alt\" [class.spinning]=\"IsRefreshing\"></i>\n Refresh\n </button>\n <button class=\"btn btn-primary\" (click)=\"StartNewTest()\">\n <i class=\"fa-solid fa-play\"></i>\n Run Test\n </button>\n </div>\n </div>\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 <div class=\"table-empty\">\n <i class=\"fa-solid fa-inbox\"></i>\n <p>No test runs found</p>\n <span class=\"empty-hint\">Try adjusting your filters or run a new test.</span>\n </div>\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: #22c55e\"></i> Yes\n } @else if (SelectedRun.humanIsCorrect === false) {\n <i class=\"fa-solid fa-times\" style=\"color: #ef4444\"></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 `,\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 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 .table-empty {\n padding: 80px 40px;\n text-align: center;\n }\n\n .table-empty i {\n font-size: 48px;\n color: var(--mj-border-strong);\n margin-bottom: 16px;\n }\n\n .table-empty p {\n font-size: 16px;\n color: var(--mj-text-muted);\n margin: 0 0 8px 0;\n }\n\n .empty-hint {\n font-size: 13px;\n color: var(--mj-text-disabled);\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})\nexport class TestingRunsComponent implements OnInit, OnDestroy {\n @Input() initialState: Record<string, unknown> | null = null;\n @Output() stateChange = new EventEmitter<Record<string, unknown>>();\n\n private destroy$ = new Subject<void>();\n 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 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 }\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 this.testingDialogService.OpenTestRunDialog({ viewContainerRef: this.viewContainerRef });\n }\n\n SelectRun(run: TestRunWithFeedbackSummary): void {\n this.SelectedRun = run;\n this.resetFeedbackForm();\n this.cdr.markForCheck();\n }\n\n CloseDetailPanel(): void {\n this.SelectedRun = null;\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.OpenTestDialog(run.testId, this.viewContainerRef);\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 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 });\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":"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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 } 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 <!-- Page Header -->\n <div class=\"runs-container\" (keydown.escape)=\"CloseDetailPanel()\">\n <div class=\"page-header\">\n <div class=\"header-title\">\n <i class=\"fa-solid fa-list-check\"></i>\n <h2>Test Runs</h2>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn btn-secondary\" (click)=\"Refresh()\" [disabled]=\"IsRefreshing\">\n <i class=\"fa-solid fa-sync-alt\" [class.spinning]=\"IsRefreshing\"></i>\n Refresh\n </button>\n <button class=\"btn btn-primary\" (click)=\"StartNewTest()\">\n <i class=\"fa-solid fa-play\"></i>\n Run Test\n </button>\n </div>\n </div>\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 <div class=\"table-empty\">\n <i class=\"fa-solid fa-inbox\"></i>\n <p>No test runs found</p>\n <span class=\"empty-hint\">Try adjusting your filters or run a new test.</span>\n </div>\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: #22c55e\"></i> Yes\n } @else if (SelectedRun.humanIsCorrect === false) {\n <i class=\"fa-solid fa-times\" style=\"color: #ef4444\"></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 `,\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 .table-empty {\n padding: 80px 40px;\n text-align: center;\n }\n\n .table-empty i {\n font-size: 48px;\n color: var(--mj-border-strong);\n margin-bottom: 16px;\n }\n\n .table-empty p {\n font-size: 16px;\n color: var(--mj-text-muted);\n margin: 0 0 8px 0;\n }\n\n .empty-hint {\n font-size: 13px;\n color: var(--mj-text-disabled);\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 @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 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 }\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.cdr.markForCheck();\n }\n\n CloseDetailPanel(): void {\n this.SelectedRun = null;\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 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 });\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,6 +1,7 @@
|
|
|
1
1
|
import { AfterViewInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
|
|
2
2
|
import { BaseDashboard } from '@memberjunction/ng-shared';
|
|
3
3
|
import { ResourceData } from '@memberjunction/core-entities';
|
|
4
|
+
import { TestingDialogService, TestingExecutionService, ActiveRun } from '@memberjunction/ng-testing';
|
|
4
5
|
import * as i0 from "@angular/core";
|
|
5
6
|
interface TestingDashboardState {
|
|
6
7
|
activeTab: string;
|
|
@@ -11,9 +12,12 @@ interface TestingDashboardState {
|
|
|
11
12
|
}
|
|
12
13
|
export declare class TestingDashboardComponent extends BaseDashboard implements AfterViewInit, OnDestroy {
|
|
13
14
|
private cdr;
|
|
15
|
+
testingDialogService: TestingDialogService;
|
|
16
|
+
private executionService;
|
|
14
17
|
isLoading: boolean;
|
|
15
18
|
activeTab: string;
|
|
16
19
|
selectedIndex: number;
|
|
20
|
+
ActiveRuns: ActiveRun[];
|
|
17
21
|
dashboardState: Record<string, unknown> | null;
|
|
18
22
|
runsState: Record<string, unknown> | null;
|
|
19
23
|
analyticsState: Record<string, unknown> | null;
|
|
@@ -26,7 +30,8 @@ export declare class TestingDashboardComponent extends BaseDashboard implements
|
|
|
26
30
|
selected: boolean;
|
|
27
31
|
}[];
|
|
28
32
|
private stateChangeSubject;
|
|
29
|
-
|
|
33
|
+
private destroy$;
|
|
34
|
+
constructor(cdr: ChangeDetectorRef, testingDialogService: TestingDialogService, executionService: TestingExecutionService);
|
|
30
35
|
GetResourceDisplayName(data: ResourceData): Promise<string>;
|
|
31
36
|
ngAfterViewInit(): void;
|
|
32
37
|
ngOnDestroy(): void;
|
|
@@ -42,6 +47,9 @@ export declare class TestingDashboardComponent extends BaseDashboard implements
|
|
|
42
47
|
initDashboard(): void;
|
|
43
48
|
loadData(): void;
|
|
44
49
|
getCurrentTabLabel(): string;
|
|
50
|
+
OnPanelClosed(): void;
|
|
51
|
+
OnViewActiveRun(run: ActiveRun): void;
|
|
52
|
+
OnViewRunningTestFromTab(testId: string): void;
|
|
45
53
|
private updateNavigationSelection;
|
|
46
54
|
static ɵfac: i0.ɵɵFactoryDeclaration<TestingDashboardComponent, never>;
|
|
47
55
|
static ɵcmp: i0.ɵɵComponentDeclaration<TestingDashboardComponent, "mj-testing-dashboard", never, {}, {}, never, never, false, never>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing-dashboard.component.d.ts","sourceRoot":"","sources":["../../src/Testing/testing-dashboard.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAA2B,MAAM,eAAe,CAAC;AAChH,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAI1D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;;
|
|
1
|
+
{"version":3,"file":"testing-dashboard.component.d.ts","sourceRoot":"","sources":["../../src/Testing/testing-dashboard.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAA2B,MAAM,eAAe,CAAC;AAChH,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAI1D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;;AAEtG,UAAU,qBAAqB;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,qBAQa,yBAA0B,SAAQ,aAAc,YAAW,aAAa,EAAE,SAAS;IAgC5F,OAAO,CAAC,GAAG;IACJ,oBAAoB,EAAE,oBAAoB;IACjD,OAAO,CAAC,gBAAgB;IAhCnB,SAAS,UAAS;IAClB,SAAS,SAAe;IACxB,aAAa,SAAK;IAGlB,UAAU,EAAE,SAAS,EAAE,CAAM;IAG7B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAQ;IACtD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAQ;IACjD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAQ;IACtD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAQ;IAG1D,OAAO,CAAC,WAAW,CAAqB;IAGjC,eAAe,EAAE,MAAM,EAAE,CAAgD;IAEzE,gBAAgB;;;;QAKrB;IAEF,OAAO,CAAC,kBAAkB,CAAwC;IAClE,OAAO,CAAC,QAAQ,CAAuB;gBAG7B,GAAG,EAAE,iBAAiB,EACvB,oBAAoB,EAAE,oBAAoB,EACzC,gBAAgB,EAAE,uBAAuB;IAO7C,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjE,eAAe,IAAI,IAAI;IAsBvB,WAAW,IAAI,IAAI;IAMZ,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAUhC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIzC,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,eAAe;IAYhB,sBAAsB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK5D,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAKvD,sBAAsB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK5D,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAKzD,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG,IAAI;IAiBjE,aAAa,IAAI,IAAI;IAWrB,QAAQ,IAAI,IAAI;IAYT,kBAAkB,IAAI,MAAM;IAK5B,aAAa,IAAI,IAAI;IAKrB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI;IAKrC,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKrD,OAAO,CAAC,yBAAyB;yCA3LtB,yBAAyB;2CAAzB,yBAAyB;CAgMrC"}
|