@memberjunction/ng-dashboards 5.0.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AI/components/agents/agent-configuration.component.d.ts +12 -12
- package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.d.ts +4 -4
- package/dist/AI/components/agents/agent-editor.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +1 -1
- package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
- package/dist/AI/components/agents/agent-filter-panel.component.d.ts +3 -3
- package/dist/AI/components/agents/agent-filter-panel.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-filter-panel.component.js +1 -1
- package/dist/AI/components/agents/agent-filter-panel.component.js.map +1 -1
- package/dist/AI/components/charts/performance-heatmap.component.js +1 -1
- package/dist/AI/components/charts/time-series-chart.component.js +1 -1
- package/dist/AI/components/execution-monitoring.component.js +1 -1
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.d.ts +5 -5
- package/dist/AI/components/models/model-management.component.d.ts.map +1 -1
- package/dist/AI/components/models/model-management.component.js +2 -2
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts +7 -7
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-filter-panel.component.js +1 -1
- package/dist/AI/components/prompts/prompt-management.component.d.ts +4 -4
- package/dist/AI/components/prompts/prompt-management.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +2 -2
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.d.ts +6 -6
- package/dist/AI/components/prompts/prompt-version-control.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.js +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.js.map +1 -1
- package/dist/AI/components/system/system-config-filter-panel.component.js +1 -1
- package/dist/AI/components/system/system-configuration.component.d.ts +4 -4
- package/dist/AI/components/system/system-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +1 -1
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/widgets/kpi-card.component.js +1 -1
- package/dist/AI/components/widgets/live-execution-widget.component.js +1 -1
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +1 -1
- package/dist/APIKeys/api-key-create-dialog.component.js +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.js +1 -1
- package/dist/APIKeys/api-key-list.component.js +1 -1
- package/dist/APIKeys/api-keys-resource.component.js +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +1 -1
- package/dist/APIKeys/api-usage-panel.component.js +1 -1
- package/dist/Actions/components/actions-list-view.component.js +1 -1
- package/dist/Actions/components/actions-overview.component.js +1 -1
- package/dist/Actions/components/categories-list-view.component.js +1 -1
- package/dist/Actions/components/code-management.component.js +1 -1
- package/dist/Actions/components/entity-integration.component.js +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +1 -1
- package/dist/Actions/components/executions-list-view.component.js +1 -1
- package/dist/Actions/components/explorer/action-breadcrumb.component.js +1 -1
- package/dist/Actions/components/explorer/action-card.component.d.ts +5 -5
- package/dist/Actions/components/explorer/action-card.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.js +1 -1
- package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.d.ts +6 -6
- package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +2 -2
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-list-item.component.d.ts +5 -5
- package/dist/Actions/components/explorer/action-list-item.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-list-item.component.js +1 -1
- package/dist/Actions/components/explorer/action-list-item.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-toolbar.component.js +1 -1
- package/dist/Actions/components/explorer/action-tree-panel.component.d.ts +2 -2
- package/dist/Actions/components/explorer/action-tree-panel.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-tree-panel.component.js +1 -1
- package/dist/Actions/components/explorer/action-tree-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.js +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js +1 -1
- package/dist/Actions/components/scheduled-actions.component.js +1 -1
- package/dist/Actions/components/security-permissions.component.js +1 -1
- package/dist/Communication/communication-dashboard.component.js +1 -1
- package/dist/Communication/communication-logs-resource.component.js +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +1 -1
- package/dist/Communication/communication-providers-resource.component.js +1 -1
- package/dist/Communication/communication-runs-resource.component.js +1 -1
- package/dist/Communication/communication-templates-resource.component.js +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +1 -1
- package/dist/ComponentStudio/components/browser/component-browser.component.js +1 -1
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +1 -1
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +1 -1
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js +1 -1
- package/dist/ComponentStudio/components/editors/spec-editor.component.js +1 -1
- package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +1 -1
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +1 -1
- package/dist/ComponentStudio/components/text-import-dialog.component.js +1 -1
- package/dist/ComponentStudio/components/workspace/component-preview.component.js +1 -1
- package/dist/ComponentStudio/components/workspace/editor-tabs.component.js +1 -1
- package/dist/ComponentStudio/services/component-studio-state.service.d.ts +3 -3
- package/dist/ComponentStudio/services/component-studio-state.service.d.ts.map +1 -1
- package/dist/ComponentStudio/services/component-studio-state.service.js.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +1 -1
- package/dist/Credentials/credentials-dashboard.component.js +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts +4 -0
- package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +17 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js +1 -1
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +1 -1
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts +4 -4
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +2 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.js +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +1 -1
- package/dist/Home/home-dashboard.component.js +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +1 -1
- package/dist/Lists/components/venn-diagram/venn-diagram.component.js +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js +1 -1
- package/dist/MCP/components/mcp-log-detail-panel.component.js +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.js +1 -1
- package/dist/MCP/mcp-dashboard.component.js +1 -1
- package/dist/MCP/mcp-filter-panel.component.js +1 -1
- package/dist/MCP/mcp-resource.component.js +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts +22 -2
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +147 -63
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/components/job-slideout.component.js +1 -1
- package/dist/Scheduling/components/scheduling-activity-resource.component.js +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js +1 -1
- package/dist/Scheduling/components/scheduling-jobs-resource.component.js +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +1 -1
- package/dist/Scheduling/components/scheduling-overview-resource.component.js +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.js +1 -1
- package/dist/Testing/components/testing-analytics-resource.component.js +1 -1
- package/dist/Testing/components/testing-analytics.component.js +1 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.js +1 -1
- package/dist/Testing/components/testing-dashboard-tab.component.js +1 -1
- package/dist/Testing/components/testing-explorer-resource.component.js +1 -1
- package/dist/Testing/components/testing-explorer.component.js +1 -1
- package/dist/Testing/components/testing-review-resource.component.js +1 -1
- package/dist/Testing/components/testing-review.component.js +1 -1
- package/dist/Testing/components/testing-runs-resource.component.js +1 -1
- package/dist/Testing/components/testing-runs.component.js +1 -1
- package/dist/Testing/components/widgets/oracle-breakdown-table.component.js +1 -1
- package/dist/Testing/components/widgets/suite-tree.component.js +2 -2
- package/dist/Testing/components/widgets/test-run-detail-panel.component.js +1 -1
- package/dist/Testing/services/testing-instrumentation.service.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +1 -1
- package/dist/VersionHistory/components/diff-resource.component.js +1 -1
- package/dist/VersionHistory/components/graph-resource.component.js +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js +1 -1
- package/package.json +38 -38
- package/dist/AI/ai-dashboard.component.d.ts +0 -62
- package/dist/AI/ai-dashboard.component.d.ts.map +0 -1
- package/dist/AI/ai-dashboard.component.js +0 -338
- package/dist/AI/ai-dashboard.component.js.map +0 -1
- package/dist/AI/components/models/model-management-v2.component.d.ts +0 -96
- package/dist/AI/components/models/model-management-v2.component.d.ts.map +0 -1
- package/dist/AI/components/models/model-management-v2.component.js +0 -981
- package/dist/AI/components/models/model-management-v2.component.js.map +0 -1
- package/dist/AI/components/prompts/prompt-management-v2.component.d.ts +0 -97
- package/dist/AI/components/prompts/prompt-management-v2.component.d.ts.map +0 -1
- package/dist/AI/components/prompts/prompt-management-v2.component.js +0 -811
- package/dist/AI/components/prompts/prompt-management-v2.component.js.map +0 -1
- package/dist/Actions/actions-management-dashboard.component.d.ts +0 -52
- package/dist/Actions/actions-management-dashboard.component.d.ts.map +0 -1
- package/dist/Actions/actions-management-dashboard.component.js +0 -308
- package/dist/Actions/actions-management-dashboard.component.js.map +0 -1
- package/dist/Credentials/components/credential-category-edit-panel.component.d.ts +0 -44
- package/dist/Credentials/components/credential-category-edit-panel.component.d.ts.map +0 -1
- package/dist/Credentials/components/credential-category-edit-panel.component.js +0 -456
- package/dist/Credentials/components/credential-category-edit-panel.component.js.map +0 -1
- package/dist/Credentials/components/credential-edit-panel.component.d.ts +0 -70
- package/dist/Credentials/components/credential-edit-panel.component.d.ts.map +0 -1
- package/dist/Credentials/components/credential-edit-panel.component.js +0 -694
- package/dist/Credentials/components/credential-edit-panel.component.js.map +0 -1
- package/dist/Credentials/components/credential-type-edit-panel.component.d.ts +0 -56
- package/dist/Credentials/components/credential-type-edit-panel.component.d.ts.map +0 -1
- package/dist/Credentials/components/credential-type-edit-panel.component.js +0 -563
- package/dist/Credentials/components/credential-type-edit-panel.component.js.map +0 -1
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts +0 -245
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts.map +0 -1
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js +0 -1143
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js.map +0 -1
- package/dist/EntityAdmin/components/entity-details.component.d.ts +0 -50
- package/dist/EntityAdmin/components/entity-details.component.d.ts.map +0 -1
- package/dist/EntityAdmin/components/entity-details.component.js +0 -680
- package/dist/EntityAdmin/components/entity-details.component.js.map +0 -1
- package/dist/EntityAdmin/components/entity-filter-panel.component.d.ts +0 -31
- package/dist/EntityAdmin/components/entity-filter-panel.component.d.ts.map +0 -1
- package/dist/EntityAdmin/components/entity-filter-panel.component.js +0 -160
- package/dist/EntityAdmin/components/entity-filter-panel.component.js.map +0 -1
- package/dist/EntityAdmin/components/erd-composite.component.d.ts +0 -73
- package/dist/EntityAdmin/components/erd-composite.component.d.ts.map +0 -1
- package/dist/EntityAdmin/components/erd-composite.component.js +0 -271
- package/dist/EntityAdmin/components/erd-composite.component.js.map +0 -1
- package/dist/EntityAdmin/components/erd-diagram.component.d.ts +0 -47
- package/dist/EntityAdmin/components/erd-diagram.component.d.ts.map +0 -1
- package/dist/EntityAdmin/components/erd-diagram.component.js +0 -618
- package/dist/EntityAdmin/components/erd-diagram.component.js.map +0 -1
- package/dist/Scheduling/components/scheduling-health-resource.component.d.ts +0 -20
- package/dist/Scheduling/components/scheduling-health-resource.component.d.ts.map +0 -1
- package/dist/Scheduling/components/scheduling-health-resource.component.js +0 -55
- package/dist/Scheduling/components/scheduling-health-resource.component.js.map +0 -1
- package/dist/Scheduling/components/scheduling-health.component.d.ts +0 -30
- package/dist/Scheduling/components/scheduling-health.component.d.ts.map +0 -1
- package/dist/Scheduling/components/scheduling-health.component.js +0 -315
- package/dist/Scheduling/components/scheduling-health.component.js.map +0 -1
- package/dist/Scheduling/components/scheduling-history-resource.component.d.ts +0 -20
- package/dist/Scheduling/components/scheduling-history-resource.component.d.ts.map +0 -1
- package/dist/Scheduling/components/scheduling-history-resource.component.js +0 -55
- package/dist/Scheduling/components/scheduling-history-resource.component.js.map +0 -1
- package/dist/Scheduling/components/scheduling-history.component.d.ts +0 -48
- package/dist/Scheduling/components/scheduling-history.component.d.ts.map +0 -1
- package/dist/Scheduling/components/scheduling-history.component.js +0 -377
- package/dist/Scheduling/components/scheduling-history.component.js.map +0 -1
- package/dist/Scheduling/components/scheduling-monitor-resource.component.d.ts +0 -20
- package/dist/Scheduling/components/scheduling-monitor-resource.component.d.ts.map +0 -1
- package/dist/Scheduling/components/scheduling-monitor-resource.component.js +0 -55
- package/dist/Scheduling/components/scheduling-monitor-resource.component.js.map +0 -1
- package/dist/Scheduling/components/scheduling-monitoring.component.d.ts +0 -37
- package/dist/Scheduling/components/scheduling-monitoring.component.d.ts.map +0 -1
- package/dist/Scheduling/components/scheduling-monitoring.component.js +0 -488
- package/dist/Scheduling/components/scheduling-monitoring.component.js.map +0 -1
- package/dist/Scheduling/components/scheduling-types-resource.component.d.ts +0 -20
- package/dist/Scheduling/components/scheduling-types-resource.component.d.ts.map +0 -1
- package/dist/Scheduling/components/scheduling-types-resource.component.js +0 -55
- package/dist/Scheduling/components/scheduling-types-resource.component.js.map +0 -1
- package/dist/Scheduling/components/scheduling-types.component.d.ts +0 -22
- package/dist/Scheduling/components/scheduling-types.component.d.ts.map +0 -1
- package/dist/Scheduling/components/scheduling-types.component.js +0 -165
- package/dist/Scheduling/components/scheduling-types.component.js.map +0 -1
- package/dist/Testing/components/testing-execution-resource.component.d.ts +0 -20
- package/dist/Testing/components/testing-execution-resource.component.d.ts.map +0 -1
- package/dist/Testing/components/testing-execution-resource.component.js +0 -55
- package/dist/Testing/components/testing-execution-resource.component.js.map +0 -1
- package/dist/Testing/components/testing-execution.component.d.ts +0 -71
- package/dist/Testing/components/testing-execution.component.d.ts.map +0 -1
- package/dist/Testing/components/testing-execution.component.js +0 -845
- package/dist/Testing/components/testing-execution.component.js.map +0 -1
- package/dist/Testing/components/testing-feedback-resource.component.d.ts +0 -20
- package/dist/Testing/components/testing-feedback-resource.component.d.ts.map +0 -1
- package/dist/Testing/components/testing-feedback-resource.component.js +0 -55
- package/dist/Testing/components/testing-feedback-resource.component.js.map +0 -1
- package/dist/Testing/components/testing-feedback.component.d.ts +0 -111
- package/dist/Testing/components/testing-feedback.component.d.ts.map +0 -1
- package/dist/Testing/components/testing-feedback.component.js +0 -1486
- package/dist/Testing/components/testing-feedback.component.js.map +0 -1
- package/dist/Testing/components/testing-overview-resource.component.d.ts +0 -20
- package/dist/Testing/components/testing-overview-resource.component.d.ts.map +0 -1
- package/dist/Testing/components/testing-overview-resource.component.js +0 -55
- package/dist/Testing/components/testing-overview-resource.component.js.map +0 -1
- package/dist/Testing/components/testing-overview.component.d.ts +0 -30
- package/dist/Testing/components/testing-overview.component.d.ts.map +0 -1
- package/dist/Testing/components/testing-overview.component.js +0 -361
- package/dist/Testing/components/testing-overview.component.js.map +0 -1
- package/dist/Testing/components/testing-version-comparison.component.d.ts +0 -62
- package/dist/Testing/components/testing-version-comparison.component.d.ts.map +0 -1
- package/dist/Testing/components/testing-version-comparison.component.js +0 -815
- package/dist/Testing/components/testing-version-comparison.component.js.map +0 -1
- package/dist/Testing/components/testing-version-resource.component.d.ts +0 -20
- package/dist/Testing/components/testing-version-resource.component.d.ts.map +0 -1
- package/dist/Testing/components/testing-version-resource.component.js +0 -55
- package/dist/Testing/components/testing-version-resource.component.js.map +0 -1
- package/dist/generic/base-dashboard.d.ts +0 -65
- package/dist/generic/base-dashboard.d.ts.map +0 -1
- package/dist/generic/base-dashboard.js +0 -74
- package/dist/generic/base-dashboard.js.map +0 -1
|
@@ -1,845 +0,0 @@
|
|
|
1
|
-
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
-
import { Subject, combineLatest, BehaviorSubject } from 'rxjs';
|
|
3
|
-
import { takeUntil, map } from 'rxjs/operators';
|
|
4
|
-
import { CompositeKey, Metadata } from '@memberjunction/core';
|
|
5
|
-
import { SharedService } from '@memberjunction/ng-shared';
|
|
6
|
-
import { GraphQLTestingClient } from '@memberjunction/graphql-dataprovider';
|
|
7
|
-
import { TestRunDialogComponent } from '@memberjunction/ng-testing';
|
|
8
|
-
import * as i0 from "@angular/core";
|
|
9
|
-
import * as i1 from "../services/testing-instrumentation.service";
|
|
10
|
-
import * as i2 from "@progress/kendo-angular-dialog";
|
|
11
|
-
import * as i3 from "@angular/forms";
|
|
12
|
-
import * as i4 from "@memberjunction/ng-testing";
|
|
13
|
-
import * as i5 from "@memberjunction/ng-shared-generic";
|
|
14
|
-
import * as i6 from "@angular/common";
|
|
15
|
-
const _forTrack0 = ($index, $item) => $item.id;
|
|
16
|
-
const _c0 = () => [];
|
|
17
|
-
function TestingExecutionComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
18
|
-
i0.ɵɵelementStart(0, "div", 9);
|
|
19
|
-
i0.ɵɵelement(1, "span", 61);
|
|
20
|
-
i0.ɵɵelementStart(2, "span", 62);
|
|
21
|
-
i0.ɵɵtext(3, "Live");
|
|
22
|
-
i0.ɵɵelementEnd()();
|
|
23
|
-
} }
|
|
24
|
-
function TestingExecutionComponent_Conditional_51_Template(rf, ctx) { if (rf & 1) {
|
|
25
|
-
const _r1 = i0.ɵɵgetCurrentView();
|
|
26
|
-
i0.ɵɵelementStart(0, "button", 63);
|
|
27
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Conditional_51_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.clearSearch()); });
|
|
28
|
-
i0.ɵɵelement(1, "i", 23);
|
|
29
|
-
i0.ɵɵelementEnd();
|
|
30
|
-
} }
|
|
31
|
-
function TestingExecutionComponent_Conditional_112_Template(rf, ctx) { if (rf & 1) {
|
|
32
|
-
i0.ɵɵelementStart(0, "div", 58);
|
|
33
|
-
i0.ɵɵelement(1, "mj-loading", 64);
|
|
34
|
-
i0.ɵɵelementEnd();
|
|
35
|
-
} }
|
|
36
|
-
function TestingExecutionComponent_Conditional_114_Template(rf, ctx) { if (rf & 1) {
|
|
37
|
-
const _r3 = i0.ɵɵgetCurrentView();
|
|
38
|
-
i0.ɵɵelementStart(0, "div", 59);
|
|
39
|
-
i0.ɵɵelement(1, "i", 65);
|
|
40
|
-
i0.ɵɵelementStart(2, "p");
|
|
41
|
-
i0.ɵɵtext(3, "No test executions found");
|
|
42
|
-
i0.ɵɵelementEnd();
|
|
43
|
-
i0.ɵɵelementStart(4, "button", 66);
|
|
44
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Conditional_114_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.startNewTest()); });
|
|
45
|
-
i0.ɵɵelement(5, "i", 14);
|
|
46
|
-
i0.ɵɵtext(6, " Run Your First Test ");
|
|
47
|
-
i0.ɵɵelementEnd()();
|
|
48
|
-
} }
|
|
49
|
-
function TestingExecutionComponent_For_116_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
50
|
-
i0.ɵɵelementStart(0, "div", 74);
|
|
51
|
-
i0.ɵɵelement(1, "div", 86);
|
|
52
|
-
i0.ɵɵelementEnd();
|
|
53
|
-
} if (rf & 2) {
|
|
54
|
-
const execution_r5 = i0.ɵɵnextContext().$implicit;
|
|
55
|
-
i0.ɵɵadvance();
|
|
56
|
-
i0.ɵɵstyleProp("width", execution_r5.progress, "%");
|
|
57
|
-
} }
|
|
58
|
-
function TestingExecutionComponent_For_116_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
59
|
-
const _r6 = i0.ɵɵgetCurrentView();
|
|
60
|
-
i0.ɵɵelementStart(0, "button", 87);
|
|
61
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_For_116_Conditional_22_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const execution_r5 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelExecution(execution_r5)); });
|
|
62
|
-
i0.ɵɵelement(1, "i", 88);
|
|
63
|
-
i0.ɵɵelementEnd();
|
|
64
|
-
} }
|
|
65
|
-
function TestingExecutionComponent_For_116_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
66
|
-
const _r7 = i0.ɵɵgetCurrentView();
|
|
67
|
-
i0.ɵɵelementStart(0, "button", 89);
|
|
68
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_For_116_Conditional_23_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r7); const execution_r5 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.rerunTest(execution_r5)); });
|
|
69
|
-
i0.ɵɵelement(1, "i", 90);
|
|
70
|
-
i0.ɵɵelementEnd();
|
|
71
|
-
} }
|
|
72
|
-
function TestingExecutionComponent_For_116_Template(rf, ctx) { if (rf & 1) {
|
|
73
|
-
const _r4 = i0.ɵɵgetCurrentView();
|
|
74
|
-
i0.ɵɵelementStart(0, "div", 67)(1, "div", 68)(2, "div", 69)(3, "div", 70);
|
|
75
|
-
i0.ɵɵtext(4);
|
|
76
|
-
i0.ɵɵelementEnd();
|
|
77
|
-
i0.ɵɵelementStart(5, "div", 71);
|
|
78
|
-
i0.ɵɵtext(6);
|
|
79
|
-
i0.ɵɵelementEnd()()();
|
|
80
|
-
i0.ɵɵelementStart(7, "div", 72);
|
|
81
|
-
i0.ɵɵelement(8, "app-test-status-badge", 73);
|
|
82
|
-
i0.ɵɵtemplate(9, TestingExecutionComponent_For_116_Conditional_9_Template, 2, 2, "div", 74);
|
|
83
|
-
i0.ɵɵelementEnd();
|
|
84
|
-
i0.ɵɵelementStart(10, "div", 75);
|
|
85
|
-
i0.ɵɵelement(11, "app-score-indicator", 76);
|
|
86
|
-
i0.ɵɵelementEnd();
|
|
87
|
-
i0.ɵɵelementStart(12, "div", 77);
|
|
88
|
-
i0.ɵɵtext(13);
|
|
89
|
-
i0.ɵɵelementEnd();
|
|
90
|
-
i0.ɵɵelementStart(14, "div", 78);
|
|
91
|
-
i0.ɵɵelement(15, "app-cost-display", 79);
|
|
92
|
-
i0.ɵɵelementEnd();
|
|
93
|
-
i0.ɵɵelementStart(16, "div", 80);
|
|
94
|
-
i0.ɵɵtext(17);
|
|
95
|
-
i0.ɵɵpipe(18, "date");
|
|
96
|
-
i0.ɵɵelementEnd();
|
|
97
|
-
i0.ɵɵelementStart(19, "div", 81)(20, "button", 82);
|
|
98
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_For_116_Template_button_click_20_listener() { const execution_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.viewDetails(execution_r5)); });
|
|
99
|
-
i0.ɵɵelement(21, "i", 83);
|
|
100
|
-
i0.ɵɵelementEnd();
|
|
101
|
-
i0.ɵɵtemplate(22, TestingExecutionComponent_For_116_Conditional_22_Template, 2, 0, "button", 84)(23, TestingExecutionComponent_For_116_Conditional_23_Template, 2, 0, "button", 85);
|
|
102
|
-
i0.ɵɵelementEnd()();
|
|
103
|
-
} if (rf & 2) {
|
|
104
|
-
const execution_r5 = ctx.$implicit;
|
|
105
|
-
const ctx_r1 = i0.ɵɵnextContext();
|
|
106
|
-
i0.ɵɵclassProp("running", execution_r5.status === "Running");
|
|
107
|
-
i0.ɵɵadvance(4);
|
|
108
|
-
i0.ɵɵtextInterpolate(execution_r5.testName);
|
|
109
|
-
i0.ɵɵadvance(2);
|
|
110
|
-
i0.ɵɵtextInterpolate(execution_r5.suiteName);
|
|
111
|
-
i0.ɵɵadvance(2);
|
|
112
|
-
i0.ɵɵproperty("status", execution_r5.status);
|
|
113
|
-
i0.ɵɵadvance();
|
|
114
|
-
i0.ɵɵconditional(execution_r5.status === "Running" ? 9 : -1);
|
|
115
|
-
i0.ɵɵadvance(2);
|
|
116
|
-
i0.ɵɵproperty("score", execution_r5.score)("showBar", false)("showIcon", false);
|
|
117
|
-
i0.ɵɵadvance(2);
|
|
118
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r1.formatDuration(execution_r5.duration), " ");
|
|
119
|
-
i0.ɵɵadvance(2);
|
|
120
|
-
i0.ɵɵproperty("cost", execution_r5.cost)("showIcon", false);
|
|
121
|
-
i0.ɵɵadvance(2);
|
|
122
|
-
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind2(18, 14, execution_r5.startedAt, "short"), " ");
|
|
123
|
-
i0.ɵɵadvance(5);
|
|
124
|
-
i0.ɵɵconditional(execution_r5.status === "Running" ? 22 : 23);
|
|
125
|
-
} }
|
|
126
|
-
export class TestingExecutionComponent {
|
|
127
|
-
instrumentationService;
|
|
128
|
-
dialogService;
|
|
129
|
-
cdr;
|
|
130
|
-
viewContainerRef;
|
|
131
|
-
initialState;
|
|
132
|
-
stateChange = new EventEmitter();
|
|
133
|
-
destroy$ = new Subject();
|
|
134
|
-
activeDialogRef = null;
|
|
135
|
-
isRefreshing = false;
|
|
136
|
-
isLoading = false;
|
|
137
|
-
lastUpdated = new Date();
|
|
138
|
-
filters = {
|
|
139
|
-
status: 'all',
|
|
140
|
-
suite: 'all',
|
|
141
|
-
timeRange: 'month', // Default to "This Month" to show more data
|
|
142
|
-
searchText: ''
|
|
143
|
-
};
|
|
144
|
-
// Track previous time range to detect changes requiring server re-query
|
|
145
|
-
previousTimeRange = 'month';
|
|
146
|
-
// BehaviorSubject to trigger client-side filter updates
|
|
147
|
-
filterTrigger$ = new BehaviorSubject(undefined);
|
|
148
|
-
executions$;
|
|
149
|
-
filteredExecutions$;
|
|
150
|
-
runningCount$;
|
|
151
|
-
completedTodayCount$;
|
|
152
|
-
failedTodayCount$;
|
|
153
|
-
avgDurationToday$;
|
|
154
|
-
hasRunningTests$;
|
|
155
|
-
testingClient;
|
|
156
|
-
constructor(instrumentationService, dialogService, cdr, viewContainerRef) {
|
|
157
|
-
this.instrumentationService = instrumentationService;
|
|
158
|
-
this.dialogService = dialogService;
|
|
159
|
-
this.cdr = cdr;
|
|
160
|
-
this.viewContainerRef = viewContainerRef;
|
|
161
|
-
// Initialize GraphQL testing client for cancel/rerun operations
|
|
162
|
-
const dataProvider = Metadata.Provider;
|
|
163
|
-
this.testingClient = new GraphQLTestingClient(dataProvider);
|
|
164
|
-
// Subscribe to loading state
|
|
165
|
-
this.instrumentationService.isLoading$.pipe(takeUntil(this.destroy$)).subscribe(loading => {
|
|
166
|
-
this.isLoading = loading;
|
|
167
|
-
this.cdr.markForCheck();
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
ngOnInit() {
|
|
171
|
-
// Apply initial state if provided
|
|
172
|
-
if (this.initialState) {
|
|
173
|
-
this.filters = { ...this.filters, ...this.initialState.filters };
|
|
174
|
-
}
|
|
175
|
-
// Set the service date range based on the selected time range filter
|
|
176
|
-
this.updateServiceDateRange();
|
|
177
|
-
this.setupObservables();
|
|
178
|
-
}
|
|
179
|
-
ngOnDestroy() {
|
|
180
|
-
// Close any open dialog when component is destroyed
|
|
181
|
-
if (this.activeDialogRef) {
|
|
182
|
-
try {
|
|
183
|
-
this.activeDialogRef.close();
|
|
184
|
-
}
|
|
185
|
-
catch (error) {
|
|
186
|
-
// Dialog might already be closed, ignore error
|
|
187
|
-
}
|
|
188
|
-
this.activeDialogRef = null;
|
|
189
|
-
}
|
|
190
|
-
this.destroy$.next();
|
|
191
|
-
this.destroy$.complete();
|
|
192
|
-
}
|
|
193
|
-
setupObservables() {
|
|
194
|
-
this.executions$ = this.instrumentationService.testRuns$.pipe(map(runs => runs.map(run => this.mapToExecutionItem(run))), takeUntil(this.destroy$));
|
|
195
|
-
// Combine executions with filter trigger to react to client-side filter changes
|
|
196
|
-
this.filteredExecutions$ = combineLatest([
|
|
197
|
-
this.executions$,
|
|
198
|
-
this.filterTrigger$
|
|
199
|
-
]).pipe(map(([executions]) => this.applyFilters(executions)), takeUntil(this.destroy$));
|
|
200
|
-
// KPI counts are now based on the full executions$ (which respects the service date range)
|
|
201
|
-
// This means the counts will match the selected time range filter
|
|
202
|
-
this.runningCount$ = this.executions$.pipe(map(execs => execs.filter(e => e.status === 'Running').length));
|
|
203
|
-
this.completedTodayCount$ = this.executions$.pipe(map(execs => execs.filter(e => e.status === 'Passed').length));
|
|
204
|
-
this.failedTodayCount$ = this.executions$.pipe(map(execs => execs.filter(e => e.status === 'Failed' || e.status === 'Error').length));
|
|
205
|
-
this.avgDurationToday$ = this.executions$.pipe(map(execs => {
|
|
206
|
-
const completedExecs = execs.filter(e => e.completedAt || e.status !== 'Running');
|
|
207
|
-
if (completedExecs.length === 0)
|
|
208
|
-
return 0;
|
|
209
|
-
const totalDuration = completedExecs.reduce((sum, e) => sum + e.duration, 0);
|
|
210
|
-
return totalDuration / completedExecs.length;
|
|
211
|
-
}));
|
|
212
|
-
this.hasRunningTests$ = this.runningCount$.pipe(map(count => count > 0));
|
|
213
|
-
}
|
|
214
|
-
mapToExecutionItem(run) {
|
|
215
|
-
const startedAt = run.runDateTime;
|
|
216
|
-
const completedAt = null;
|
|
217
|
-
const duration = run.duration;
|
|
218
|
-
const progress = run.status === 'Running' ? Math.random() * 100 : 100;
|
|
219
|
-
return {
|
|
220
|
-
id: run.id,
|
|
221
|
-
testId: run.testId,
|
|
222
|
-
testName: run.testName,
|
|
223
|
-
suiteName: run.suiteName,
|
|
224
|
-
status: run.status,
|
|
225
|
-
score: run.score,
|
|
226
|
-
duration,
|
|
227
|
-
cost: run.cost,
|
|
228
|
-
startedAt,
|
|
229
|
-
completedAt,
|
|
230
|
-
progress
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
applyFilters(executions) {
|
|
234
|
-
let filtered = [...executions];
|
|
235
|
-
// Apply status filter
|
|
236
|
-
if (this.filters.status !== 'all') {
|
|
237
|
-
if (this.filters.status === 'running') {
|
|
238
|
-
filtered = filtered.filter(e => e.status === 'Running');
|
|
239
|
-
}
|
|
240
|
-
else if (this.filters.status === 'completed') {
|
|
241
|
-
filtered = filtered.filter(e => e.status === 'Passed' || e.status === 'Skipped');
|
|
242
|
-
}
|
|
243
|
-
else if (this.filters.status === 'failed') {
|
|
244
|
-
filtered = filtered.filter(e => e.status === 'Failed' || e.status === 'Error');
|
|
245
|
-
}
|
|
246
|
-
else if (this.filters.status === 'passed') {
|
|
247
|
-
filtered = filtered.filter(e => e.status === 'Passed');
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
// Note: Time range filtering is now handled by the service via updateServiceDateRange()
|
|
251
|
-
// This ensures the KPIs and list use the same data set
|
|
252
|
-
// Apply search text filter
|
|
253
|
-
if (this.filters.searchText) {
|
|
254
|
-
const searchLower = this.filters.searchText.toLowerCase();
|
|
255
|
-
filtered = filtered.filter(e => e.testName.toLowerCase().includes(searchLower) ||
|
|
256
|
-
e.suiteName.toLowerCase().includes(searchLower));
|
|
257
|
-
}
|
|
258
|
-
// Sort by most recent first
|
|
259
|
-
filtered.sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime());
|
|
260
|
-
return filtered;
|
|
261
|
-
}
|
|
262
|
-
onFilterChange() {
|
|
263
|
-
// Only re-query server when time range changes - status/search filtering is client-side only
|
|
264
|
-
if (this.filters.timeRange !== this.previousTimeRange) {
|
|
265
|
-
this.previousTimeRange = this.filters.timeRange;
|
|
266
|
-
this.updateServiceDateRange();
|
|
267
|
-
}
|
|
268
|
-
// Trigger client-side filter update via observable
|
|
269
|
-
this.filterTrigger$.next();
|
|
270
|
-
this.emitStateChange();
|
|
271
|
-
this.cdr.markForCheck();
|
|
272
|
-
}
|
|
273
|
-
updateServiceDateRange() {
|
|
274
|
-
const now = new Date();
|
|
275
|
-
let startDate;
|
|
276
|
-
switch (this.filters.timeRange) {
|
|
277
|
-
case 'today':
|
|
278
|
-
startDate = new Date(now);
|
|
279
|
-
startDate.setHours(0, 0, 0, 0);
|
|
280
|
-
break;
|
|
281
|
-
case 'week':
|
|
282
|
-
startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
283
|
-
break;
|
|
284
|
-
case 'month':
|
|
285
|
-
startDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
286
|
-
break;
|
|
287
|
-
case 'all':
|
|
288
|
-
default:
|
|
289
|
-
// For "all time", use a very old date (e.g., 1 year ago)
|
|
290
|
-
startDate = new Date(now.getTime() - 365 * 24 * 60 * 60 * 1000);
|
|
291
|
-
break;
|
|
292
|
-
}
|
|
293
|
-
this.instrumentationService.setDateRange(startDate, now);
|
|
294
|
-
}
|
|
295
|
-
clearSearch() {
|
|
296
|
-
this.filters.searchText = '';
|
|
297
|
-
this.onFilterChange();
|
|
298
|
-
}
|
|
299
|
-
refresh() {
|
|
300
|
-
this.isRefreshing = true;
|
|
301
|
-
this.instrumentationService.refresh();
|
|
302
|
-
setTimeout(() => {
|
|
303
|
-
this.isRefreshing = false;
|
|
304
|
-
this.lastUpdated = new Date();
|
|
305
|
-
this.cdr.markForCheck();
|
|
306
|
-
}, 1000);
|
|
307
|
-
}
|
|
308
|
-
filterByStatus(status) {
|
|
309
|
-
this.filters.status = status;
|
|
310
|
-
this.onFilterChange();
|
|
311
|
-
}
|
|
312
|
-
startNewTest() {
|
|
313
|
-
this.activeDialogRef = this.dialogService.open({
|
|
314
|
-
content: TestRunDialogComponent,
|
|
315
|
-
width: 1000,
|
|
316
|
-
height: 750,
|
|
317
|
-
title: 'Run Test',
|
|
318
|
-
actions: []
|
|
319
|
-
});
|
|
320
|
-
this.activeDialogRef.result.pipe(takeUntil(this.destroy$)).subscribe({
|
|
321
|
-
next: (result) => {
|
|
322
|
-
if (result && typeof result === 'object' && 'testExecuted' in result && result.testExecuted) {
|
|
323
|
-
this.refresh();
|
|
324
|
-
}
|
|
325
|
-
},
|
|
326
|
-
error: () => {
|
|
327
|
-
this.activeDialogRef = null;
|
|
328
|
-
},
|
|
329
|
-
complete: () => {
|
|
330
|
-
this.activeDialogRef = null;
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
viewDetails(execution) {
|
|
335
|
-
SharedService.Instance.OpenEntityRecord('MJ: Test Runs', CompositeKey.FromID(execution.id));
|
|
336
|
-
}
|
|
337
|
-
async cancelExecution(execution) {
|
|
338
|
-
// For now, show a notification - full cancel support requires server-side CancelTest mutation
|
|
339
|
-
// which we documented in the plan but haven't implemented yet
|
|
340
|
-
SharedService.Instance.CreateSimpleNotification(`Cancellation requested for "${execution.testName}". Full cancellation support coming soon.`, 'warning', 3000);
|
|
341
|
-
// Refresh after a delay to pick up any status changes
|
|
342
|
-
setTimeout(() => this.refresh(), 1500);
|
|
343
|
-
}
|
|
344
|
-
async rerunTest(execution) {
|
|
345
|
-
if (!execution.testId) {
|
|
346
|
-
SharedService.Instance.CreateSimpleNotification('Cannot re-run: Test ID not available', 'error', 3000);
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
// Open the test run dialog with the test pre-selected
|
|
350
|
-
this.activeDialogRef = this.dialogService.open({
|
|
351
|
-
content: TestRunDialogComponent,
|
|
352
|
-
width: 1000,
|
|
353
|
-
height: 750,
|
|
354
|
-
title: 'Re-run Test',
|
|
355
|
-
actions: []
|
|
356
|
-
});
|
|
357
|
-
// Pre-configure the dialog with the test
|
|
358
|
-
const dialogComponent = this.activeDialogRef.content.instance;
|
|
359
|
-
dialogComponent.runMode = 'test';
|
|
360
|
-
dialogComponent.selectedTestId = execution.testId;
|
|
361
|
-
this.activeDialogRef.result.pipe(takeUntil(this.destroy$)).subscribe({
|
|
362
|
-
next: (result) => {
|
|
363
|
-
if (result && typeof result === 'object' && 'testExecuted' in result && result.testExecuted) {
|
|
364
|
-
SharedService.Instance.CreateSimpleNotification(`Test "${execution.testName}" completed`, 'success', 3000);
|
|
365
|
-
this.refresh();
|
|
366
|
-
}
|
|
367
|
-
},
|
|
368
|
-
error: () => {
|
|
369
|
-
this.activeDialogRef = null;
|
|
370
|
-
},
|
|
371
|
-
complete: () => {
|
|
372
|
-
this.activeDialogRef = null;
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
formatDuration(milliseconds) {
|
|
377
|
-
if (milliseconds < 1000)
|
|
378
|
-
return `${milliseconds}ms`;
|
|
379
|
-
const seconds = Math.floor(milliseconds / 1000);
|
|
380
|
-
const minutes = Math.floor(seconds / 60);
|
|
381
|
-
if (minutes > 0)
|
|
382
|
-
return `${minutes}m ${seconds % 60}s`;
|
|
383
|
-
return `${seconds}s`;
|
|
384
|
-
}
|
|
385
|
-
getTimeRangeLabel() {
|
|
386
|
-
switch (this.filters.timeRange) {
|
|
387
|
-
case 'today': return 'Today';
|
|
388
|
-
case 'week': return 'This Week';
|
|
389
|
-
case 'month': return 'This Month';
|
|
390
|
-
case 'all': return 'All Time';
|
|
391
|
-
default: return '';
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
emitStateChange() {
|
|
395
|
-
this.stateChange.emit({
|
|
396
|
-
filters: this.filters
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
static ɵfac = function TestingExecutionComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TestingExecutionComponent)(i0.ɵɵdirectiveInject(i1.TestingInstrumentationService), i0.ɵɵdirectiveInject(i2.DialogService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ViewContainerRef)); };
|
|
400
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestingExecutionComponent, selectors: [["app-testing-execution"]], inputs: { initialState: "initialState" }, outputs: { stateChange: "stateChange" }, decls: 118, vars: 41, consts: [["kendoDialogContainer", "", 1, "testing-execution"], [1, "execution-header"], [1, "header-left"], [1, "header-icon"], [1, "fa-solid", "fa-play-circle"], [1, "header-text"], [1, "header-meta"], [1, "last-updated"], [1, "fa-solid", "fa-clock"], [1, "live-indicator"], [1, "header-actions"], [1, "action-btn", "refresh-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-sync-alt"], [1, "action-btn", "primary-btn", 3, "click"], [1, "fa-solid", "fa-play"], [1, "filter-bar"], [1, "filter-chips"], [1, "filter-chip", 3, "click"], [1, "filter-chip", "running", 3, "click"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "filter-chip", "passed", 3, "click"], [1, "fa-solid", "fa-check"], [1, "filter-chip", "failed", 3, "click"], [1, "fa-solid", "fa-times"], [1, "filter-controls"], [1, "time-select"], [3, "ngModelChange", "change", "ngModel"], ["value", "today"], ["value", "week"], ["value", "month"], ["value", "all"], [1, "search-input"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search tests...", 3, "ngModelChange", "input", "ngModel"], [1, "clear-btn"], [1, "kpi-grid"], [1, "kpi-card", "running", "clickable", 3, "click"], [1, "kpi-icon"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-arrow"], [1, "fa-solid", "fa-chevron-right"], [1, "kpi-card", "passed", "clickable", 3, "click"], [1, "fa-solid", "fa-check-circle"], [1, "kpi-card", "failed", "clickable", 3, "click"], [1, "fa-solid", "fa-exclamation-circle"], [1, "kpi-card", "duration"], [1, "execution-content"], [1, "execution-list"], [1, "list-header"], [1, "header-cell", "test-name"], [1, "header-cell", "status"], [1, "header-cell", "score"], [1, "header-cell", "duration"], [1, "header-cell", "cost"], [1, "header-cell", "timestamp"], [1, "header-cell", "actions"], [1, "loading-placeholder"], [1, "no-data"], [1, "execution-row", 3, "running"], [1, "pulse"], [1, "text"], [1, "clear-btn", 3, "click"], ["text", "Loading test executions..."], [1, "fa-solid", "fa-inbox"], [1, "action-btn", "primary", 3, "click"], [1, "execution-row"], [1, "cell", "test-name"], [1, "test-info"], [1, "name"], [1, "suite"], [1, "cell", "status"], [3, "status"], [1, "progress-bar"], [1, "cell", "score"], [3, "score", "showBar", "showIcon"], [1, "cell", "duration"], [1, "cell", "cost"], [3, "cost", "showIcon"], [1, "cell", "timestamp"], [1, "cell", "actions"], ["title", "View Details", 1, "icon-btn", 3, "click"], [1, "fa-solid", "fa-eye"], ["title", "Cancel", 1, "icon-btn", "danger"], ["title", "Re-run", 1, "icon-btn"], [1, "progress-fill"], ["title", "Cancel", 1, "icon-btn", "danger", 3, "click"], [1, "fa-solid", "fa-stop"], ["title", "Re-run", 1, "icon-btn", 3, "click"], [1, "fa-solid", "fa-redo"]], template: function TestingExecutionComponent_Template(rf, ctx) { if (rf & 1) {
|
|
401
|
-
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "div", 3);
|
|
402
|
-
i0.ɵɵelement(4, "i", 4);
|
|
403
|
-
i0.ɵɵelementEnd();
|
|
404
|
-
i0.ɵɵelementStart(5, "div", 5)(6, "h2");
|
|
405
|
-
i0.ɵɵtext(7, "Test Execution Monitor");
|
|
406
|
-
i0.ɵɵelementEnd();
|
|
407
|
-
i0.ɵɵelementStart(8, "div", 6)(9, "span", 7);
|
|
408
|
-
i0.ɵɵelement(10, "i", 8);
|
|
409
|
-
i0.ɵɵtext(11);
|
|
410
|
-
i0.ɵɵpipe(12, "date");
|
|
411
|
-
i0.ɵɵelementEnd();
|
|
412
|
-
i0.ɵɵtemplate(13, TestingExecutionComponent_Conditional_13_Template, 4, 0, "div", 9);
|
|
413
|
-
i0.ɵɵpipe(14, "async");
|
|
414
|
-
i0.ɵɵelementEnd()()();
|
|
415
|
-
i0.ɵɵelementStart(15, "div", 10)(16, "button", 11);
|
|
416
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Template_button_click_16_listener() { return ctx.refresh(); });
|
|
417
|
-
i0.ɵɵelement(17, "i", 12);
|
|
418
|
-
i0.ɵɵelementStart(18, "span");
|
|
419
|
-
i0.ɵɵtext(19, "Refresh");
|
|
420
|
-
i0.ɵɵelementEnd()();
|
|
421
|
-
i0.ɵɵelementStart(20, "button", 13);
|
|
422
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Template_button_click_20_listener() { return ctx.startNewTest(); });
|
|
423
|
-
i0.ɵɵelement(21, "i", 14);
|
|
424
|
-
i0.ɵɵelementStart(22, "span");
|
|
425
|
-
i0.ɵɵtext(23, "Run Test");
|
|
426
|
-
i0.ɵɵelementEnd()()()();
|
|
427
|
-
i0.ɵɵelementStart(24, "div", 15)(25, "div", 16)(26, "button", 17);
|
|
428
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Template_button_click_26_listener() { ctx.filters.status = "all"; return ctx.onFilterChange(); });
|
|
429
|
-
i0.ɵɵtext(27, " All ");
|
|
430
|
-
i0.ɵɵelementEnd();
|
|
431
|
-
i0.ɵɵelementStart(28, "button", 18);
|
|
432
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Template_button_click_28_listener() { ctx.filters.status = "running"; return ctx.onFilterChange(); });
|
|
433
|
-
i0.ɵɵelement(29, "i", 19);
|
|
434
|
-
i0.ɵɵtext(30, " Running ");
|
|
435
|
-
i0.ɵɵelementEnd();
|
|
436
|
-
i0.ɵɵelementStart(31, "button", 20);
|
|
437
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Template_button_click_31_listener() { ctx.filters.status = "passed"; return ctx.onFilterChange(); });
|
|
438
|
-
i0.ɵɵelement(32, "i", 21);
|
|
439
|
-
i0.ɵɵtext(33, " Passed ");
|
|
440
|
-
i0.ɵɵelementEnd();
|
|
441
|
-
i0.ɵɵelementStart(34, "button", 22);
|
|
442
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Template_button_click_34_listener() { ctx.filters.status = "failed"; return ctx.onFilterChange(); });
|
|
443
|
-
i0.ɵɵelement(35, "i", 23);
|
|
444
|
-
i0.ɵɵtext(36, " Failed ");
|
|
445
|
-
i0.ɵɵelementEnd()();
|
|
446
|
-
i0.ɵɵelementStart(37, "div", 24)(38, "div", 25)(39, "select", 26);
|
|
447
|
-
i0.ɵɵtwoWayListener("ngModelChange", function TestingExecutionComponent_Template_select_ngModelChange_39_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.filters.timeRange, $event) || (ctx.filters.timeRange = $event); return $event; });
|
|
448
|
-
i0.ɵɵlistener("change", function TestingExecutionComponent_Template_select_change_39_listener() { return ctx.onFilterChange(); });
|
|
449
|
-
i0.ɵɵelementStart(40, "option", 27);
|
|
450
|
-
i0.ɵɵtext(41, "Today");
|
|
451
|
-
i0.ɵɵelementEnd();
|
|
452
|
-
i0.ɵɵelementStart(42, "option", 28);
|
|
453
|
-
i0.ɵɵtext(43, "This Week");
|
|
454
|
-
i0.ɵɵelementEnd();
|
|
455
|
-
i0.ɵɵelementStart(44, "option", 29);
|
|
456
|
-
i0.ɵɵtext(45, "This Month");
|
|
457
|
-
i0.ɵɵelementEnd();
|
|
458
|
-
i0.ɵɵelementStart(46, "option", 30);
|
|
459
|
-
i0.ɵɵtext(47, "All Time");
|
|
460
|
-
i0.ɵɵelementEnd()()();
|
|
461
|
-
i0.ɵɵelementStart(48, "div", 31);
|
|
462
|
-
i0.ɵɵelement(49, "i", 32);
|
|
463
|
-
i0.ɵɵelementStart(50, "input", 33);
|
|
464
|
-
i0.ɵɵtwoWayListener("ngModelChange", function TestingExecutionComponent_Template_input_ngModelChange_50_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.filters.searchText, $event) || (ctx.filters.searchText = $event); return $event; });
|
|
465
|
-
i0.ɵɵlistener("input", function TestingExecutionComponent_Template_input_input_50_listener() { return ctx.onFilterChange(); });
|
|
466
|
-
i0.ɵɵelementEnd();
|
|
467
|
-
i0.ɵɵtemplate(51, TestingExecutionComponent_Conditional_51_Template, 2, 0, "button", 34);
|
|
468
|
-
i0.ɵɵelementEnd()()();
|
|
469
|
-
i0.ɵɵelementStart(52, "div", 35)(53, "div", 36);
|
|
470
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Template_div_click_53_listener() { return ctx.filterByStatus("running"); });
|
|
471
|
-
i0.ɵɵelementStart(54, "div", 37);
|
|
472
|
-
i0.ɵɵelement(55, "i", 19);
|
|
473
|
-
i0.ɵɵelementEnd();
|
|
474
|
-
i0.ɵɵelementStart(56, "div", 38)(57, "div", 39);
|
|
475
|
-
i0.ɵɵtext(58);
|
|
476
|
-
i0.ɵɵpipe(59, "async");
|
|
477
|
-
i0.ɵɵelementEnd();
|
|
478
|
-
i0.ɵɵelementStart(60, "div", 40);
|
|
479
|
-
i0.ɵɵtext(61, "Running Now");
|
|
480
|
-
i0.ɵɵelementEnd()();
|
|
481
|
-
i0.ɵɵelementStart(62, "div", 41);
|
|
482
|
-
i0.ɵɵelement(63, "i", 42);
|
|
483
|
-
i0.ɵɵelementEnd()();
|
|
484
|
-
i0.ɵɵelementStart(64, "div", 43);
|
|
485
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Template_div_click_64_listener() { return ctx.filterByStatus("passed"); });
|
|
486
|
-
i0.ɵɵelementStart(65, "div", 37);
|
|
487
|
-
i0.ɵɵelement(66, "i", 44);
|
|
488
|
-
i0.ɵɵelementEnd();
|
|
489
|
-
i0.ɵɵelementStart(67, "div", 38)(68, "div", 39);
|
|
490
|
-
i0.ɵɵtext(69);
|
|
491
|
-
i0.ɵɵpipe(70, "async");
|
|
492
|
-
i0.ɵɵelementEnd();
|
|
493
|
-
i0.ɵɵelementStart(71, "div", 40);
|
|
494
|
-
i0.ɵɵtext(72);
|
|
495
|
-
i0.ɵɵelementEnd()();
|
|
496
|
-
i0.ɵɵelementStart(73, "div", 41);
|
|
497
|
-
i0.ɵɵelement(74, "i", 42);
|
|
498
|
-
i0.ɵɵelementEnd()();
|
|
499
|
-
i0.ɵɵelementStart(75, "div", 45);
|
|
500
|
-
i0.ɵɵlistener("click", function TestingExecutionComponent_Template_div_click_75_listener() { return ctx.filterByStatus("failed"); });
|
|
501
|
-
i0.ɵɵelementStart(76, "div", 37);
|
|
502
|
-
i0.ɵɵelement(77, "i", 46);
|
|
503
|
-
i0.ɵɵelementEnd();
|
|
504
|
-
i0.ɵɵelementStart(78, "div", 38)(79, "div", 39);
|
|
505
|
-
i0.ɵɵtext(80);
|
|
506
|
-
i0.ɵɵpipe(81, "async");
|
|
507
|
-
i0.ɵɵelementEnd();
|
|
508
|
-
i0.ɵɵelementStart(82, "div", 40);
|
|
509
|
-
i0.ɵɵtext(83);
|
|
510
|
-
i0.ɵɵelementEnd()();
|
|
511
|
-
i0.ɵɵelementStart(84, "div", 41);
|
|
512
|
-
i0.ɵɵelement(85, "i", 42);
|
|
513
|
-
i0.ɵɵelementEnd()();
|
|
514
|
-
i0.ɵɵelementStart(86, "div", 47)(87, "div", 37);
|
|
515
|
-
i0.ɵɵelement(88, "i", 8);
|
|
516
|
-
i0.ɵɵelementEnd();
|
|
517
|
-
i0.ɵɵelementStart(89, "div", 38)(90, "div", 39);
|
|
518
|
-
i0.ɵɵtext(91);
|
|
519
|
-
i0.ɵɵpipe(92, "async");
|
|
520
|
-
i0.ɵɵelementEnd();
|
|
521
|
-
i0.ɵɵelementStart(93, "div", 40);
|
|
522
|
-
i0.ɵɵtext(94, "Avg Duration");
|
|
523
|
-
i0.ɵɵelementEnd()()()();
|
|
524
|
-
i0.ɵɵelementStart(95, "div", 48)(96, "div", 49)(97, "div", 50)(98, "div", 51);
|
|
525
|
-
i0.ɵɵtext(99, "Test Name");
|
|
526
|
-
i0.ɵɵelementEnd();
|
|
527
|
-
i0.ɵɵelementStart(100, "div", 52);
|
|
528
|
-
i0.ɵɵtext(101, "Status");
|
|
529
|
-
i0.ɵɵelementEnd();
|
|
530
|
-
i0.ɵɵelementStart(102, "div", 53);
|
|
531
|
-
i0.ɵɵtext(103, "Score");
|
|
532
|
-
i0.ɵɵelementEnd();
|
|
533
|
-
i0.ɵɵelementStart(104, "div", 54);
|
|
534
|
-
i0.ɵɵtext(105, "Duration");
|
|
535
|
-
i0.ɵɵelementEnd();
|
|
536
|
-
i0.ɵɵelementStart(106, "div", 55);
|
|
537
|
-
i0.ɵɵtext(107, "Cost");
|
|
538
|
-
i0.ɵɵelementEnd();
|
|
539
|
-
i0.ɵɵelementStart(108, "div", 56);
|
|
540
|
-
i0.ɵɵtext(109, "Started At");
|
|
541
|
-
i0.ɵɵelementEnd();
|
|
542
|
-
i0.ɵɵelementStart(110, "div", 57);
|
|
543
|
-
i0.ɵɵtext(111, "Actions");
|
|
544
|
-
i0.ɵɵelementEnd()();
|
|
545
|
-
i0.ɵɵtemplate(112, TestingExecutionComponent_Conditional_112_Template, 2, 0, "div", 58);
|
|
546
|
-
i0.ɵɵpipe(113, "async");
|
|
547
|
-
i0.ɵɵtemplate(114, TestingExecutionComponent_Conditional_114_Template, 7, 0, "div", 59);
|
|
548
|
-
i0.ɵɵrepeaterCreate(115, TestingExecutionComponent_For_116_Template, 24, 17, "div", 60, _forTrack0);
|
|
549
|
-
i0.ɵɵpipe(117, "async");
|
|
550
|
-
i0.ɵɵelementEnd()()();
|
|
551
|
-
} if (rf & 2) {
|
|
552
|
-
let tmp_11_0;
|
|
553
|
-
let tmp_12_0;
|
|
554
|
-
let tmp_14_0;
|
|
555
|
-
let tmp_16_0;
|
|
556
|
-
let tmp_17_0;
|
|
557
|
-
let tmp_18_0;
|
|
558
|
-
i0.ɵɵadvance(11);
|
|
559
|
-
i0.ɵɵtextInterpolate1(" Updated ", i0.ɵɵpipeBind2(12, 23, ctx.lastUpdated, "shortTime"), " ");
|
|
560
|
-
i0.ɵɵadvance(2);
|
|
561
|
-
i0.ɵɵconditional(i0.ɵɵpipeBind1(14, 26, ctx.hasRunningTests$) ? 13 : -1);
|
|
562
|
-
i0.ɵɵadvance(3);
|
|
563
|
-
i0.ɵɵproperty("disabled", ctx.isRefreshing);
|
|
564
|
-
i0.ɵɵadvance();
|
|
565
|
-
i0.ɵɵclassProp("spinning", ctx.isRefreshing);
|
|
566
|
-
i0.ɵɵadvance(9);
|
|
567
|
-
i0.ɵɵclassProp("active", ctx.filters.status === "all");
|
|
568
|
-
i0.ɵɵadvance(2);
|
|
569
|
-
i0.ɵɵclassProp("active", ctx.filters.status === "running");
|
|
570
|
-
i0.ɵɵadvance(3);
|
|
571
|
-
i0.ɵɵclassProp("active", ctx.filters.status === "passed");
|
|
572
|
-
i0.ɵɵadvance(3);
|
|
573
|
-
i0.ɵɵclassProp("active", ctx.filters.status === "failed");
|
|
574
|
-
i0.ɵɵadvance(5);
|
|
575
|
-
i0.ɵɵtwoWayProperty("ngModel", ctx.filters.timeRange);
|
|
576
|
-
i0.ɵɵadvance(11);
|
|
577
|
-
i0.ɵɵtwoWayProperty("ngModel", ctx.filters.searchText);
|
|
578
|
-
i0.ɵɵadvance();
|
|
579
|
-
i0.ɵɵconditional(ctx.filters.searchText ? 51 : -1);
|
|
580
|
-
i0.ɵɵadvance(7);
|
|
581
|
-
i0.ɵɵtextInterpolate((tmp_11_0 = i0.ɵɵpipeBind1(59, 28, ctx.runningCount$)) !== null && tmp_11_0 !== undefined ? tmp_11_0 : 0);
|
|
582
|
-
i0.ɵɵadvance(11);
|
|
583
|
-
i0.ɵɵtextInterpolate((tmp_12_0 = i0.ɵɵpipeBind1(70, 30, ctx.completedTodayCount$)) !== null && tmp_12_0 !== undefined ? tmp_12_0 : 0);
|
|
584
|
-
i0.ɵɵadvance(3);
|
|
585
|
-
i0.ɵɵtextInterpolate1("Passed ", ctx.getTimeRangeLabel(), "");
|
|
586
|
-
i0.ɵɵadvance(8);
|
|
587
|
-
i0.ɵɵtextInterpolate((tmp_14_0 = i0.ɵɵpipeBind1(81, 32, ctx.failedTodayCount$)) !== null && tmp_14_0 !== undefined ? tmp_14_0 : 0);
|
|
588
|
-
i0.ɵɵadvance(3);
|
|
589
|
-
i0.ɵɵtextInterpolate1("Failed ", ctx.getTimeRangeLabel(), "");
|
|
590
|
-
i0.ɵɵadvance(8);
|
|
591
|
-
i0.ɵɵtextInterpolate(ctx.formatDuration((tmp_16_0 = i0.ɵɵpipeBind1(92, 34, ctx.avgDurationToday$)) !== null && tmp_16_0 !== undefined ? tmp_16_0 : 0));
|
|
592
|
-
i0.ɵɵadvance(21);
|
|
593
|
-
i0.ɵɵconditional(ctx.isLoading ? 112 : ((tmp_17_0 = i0.ɵɵpipeBind1(113, 36, ctx.filteredExecutions$)) == null ? null : tmp_17_0.length) === 0 ? 114 : -1);
|
|
594
|
-
i0.ɵɵadvance(3);
|
|
595
|
-
i0.ɵɵrepeater((tmp_18_0 = i0.ɵɵpipeBind1(117, 38, ctx.filteredExecutions$)) !== null && tmp_18_0 !== undefined ? tmp_18_0 : i0.ɵɵpureFunction0(40, _c0));
|
|
596
|
-
} }, dependencies: [i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i3.DefaultValueAccessor, i3.SelectControlValueAccessor, i3.NgControlStatus, i3.NgModel, i2.DialogContainerDirective, i4.TestStatusBadgeComponent, i4.ScoreIndicatorComponent, i4.CostDisplayComponent, i5.LoadingComponent, i6.AsyncPipe, i6.DatePipe], styles: ["\n\n\n\n\n .testing-execution[_ngcontent-%COMP%] {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: linear-gradient(135deg, #f8fafc 0%, #eef2f7 100%);\n }\n\n \n\n .execution-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);\n padding: 24px 28px;\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(99, 102, 241, 0.25);\n }\n\n .header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .header-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 22px;\n color: white;\n }\n\n .header-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 20px;\n font-weight: 600;\n color: white;\n }\n\n .header-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .last-updated[_ngcontent-%COMP%] {\n font-size: 12px;\n color: rgba(255, 255, 255, 0.8);\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .last-updated[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n }\n\n .live-indicator[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 12px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n color: white;\n }\n\n .pulse[_ngcontent-%COMP%] {\n width: 8px;\n height: 8px;\n background: #22c55e;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_pulse 2s infinite;\n box-shadow: 0 0 8px #22c55e;\n }\n\n @keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(1.3); }\n }\n\n .header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n }\n\n .action-btn[_ngcontent-%COMP%] {\n display: 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.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .refresh-btn[_ngcontent-%COMP%] {\n background: rgba(255, 255, 255, 0.15);\n color: white;\n border: 1px solid rgba(255, 255, 255, 0.25);\n }\n\n .refresh-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.25);\n transform: translateY(-1px);\n }\n\n .primary-btn[_ngcontent-%COMP%] {\n background: white;\n color: #6366f1;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n\n .primary-btn[_ngcontent-%COMP%]:hover {\n background: #f8f9ff;\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);\n }\n\n .action-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none !important;\n }\n\n .spinning[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_spin 1s linear infinite;\n }\n\n @keyframes _ngcontent-%COMP%_spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n \n\n .filter-bar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n margin-bottom: 20px;\n padding: 16px 20px;\n background: white;\n border-radius: 14px;\n box-shadow: 0 2px 12px rgba(99, 102, 241, 0.06);\n }\n\n .filter-chips[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n }\n\n .filter-chip[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: #f1f5f9;\n border: 2px solid transparent;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 600;\n color: #64748b;\n cursor: pointer;\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .filter-chip[_ngcontent-%COMP%]:hover {\n background: #e2e8f0;\n color: #475569;\n }\n\n .filter-chip.active[_ngcontent-%COMP%] {\n background: #6366f1;\n color: white;\n border-color: #6366f1;\n }\n\n .filter-chip.running.active[_ngcontent-%COMP%] {\n background: #3b82f6;\n border-color: #3b82f6;\n }\n\n .filter-chip.passed.active[_ngcontent-%COMP%] {\n background: #22c55e;\n border-color: #22c55e;\n }\n\n .filter-chip.failed.active[_ngcontent-%COMP%] {\n background: #ef4444;\n border-color: #ef4444;\n }\n\n .filter-chip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n }\n\n .filter-controls[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n align-items: center;\n }\n\n .time-select[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n padding: 10px 14px;\n border: 2px solid #e2e8f0;\n border-radius: 10px;\n font-size: 13px;\n font-weight: 500;\n color: #475569;\n background: white;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .time-select[_ngcontent-%COMP%] select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #6366f1;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n }\n\n .search-input[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 16px;\n background: #f8fafc;\n border: 2px solid #e2e8f0;\n border-radius: 10px;\n min-width: 250px;\n transition: all 0.2s ease;\n }\n\n .search-input[_ngcontent-%COMP%]:focus-within {\n border-color: #6366f1;\n background: white;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n }\n\n .search-input[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #94a3b8;\n font-size: 14px;\n }\n\n .search-input[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: #334155;\n }\n\n .search-input[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder {\n color: #94a3b8;\n }\n\n .clear-btn[_ngcontent-%COMP%] {\n padding: 4px 8px;\n border: none;\n background: transparent;\n color: #94a3b8;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.2s ease;\n }\n\n .clear-btn[_ngcontent-%COMP%]:hover {\n background: #e2e8f0;\n color: #64748b;\n }\n\n \n\n .kpi-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 20px;\n }\n\n .kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: white;\n border-radius: 14px;\n box-shadow: 0 2px 12px rgba(99, 102, 241, 0.06);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n position: relative;\n overflow: hidden;\n }\n\n .kpi-card[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 4px;\n height: 100%;\n border-radius: 4px 0 0 4px;\n }\n\n .kpi-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n }\n\n .kpi-card.clickable[_ngcontent-%COMP%]:hover {\n transform: translateY(-3px);\n box-shadow: 0 8px 24px rgba(99, 102, 241, 0.15);\n }\n\n .kpi-card.running[_ngcontent-%COMP%]::before { background: linear-gradient(180deg, #3b82f6, #60a5fa); }\n .kpi-card.passed[_ngcontent-%COMP%]::before { background: linear-gradient(180deg, #22c55e, #4ade80); }\n .kpi-card.failed[_ngcontent-%COMP%]::before { background: linear-gradient(180deg, #ef4444, #f87171); }\n .kpi-card.duration[_ngcontent-%COMP%]::before { background: linear-gradient(180deg, #8b5cf6, #a78bfa); }\n\n .kpi-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 20px;\n }\n\n .kpi-card.running[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: rgba(59, 130, 246, 0.1);\n color: #3b82f6;\n }\n\n .kpi-card.passed[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: rgba(34, 197, 94, 0.1);\n color: #22c55e;\n }\n\n .kpi-card.failed[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: rgba(239, 68, 68, 0.1);\n color: #ef4444;\n }\n\n .kpi-card.duration[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: rgba(139, 92, 246, 0.1);\n color: #8b5cf6;\n }\n\n .kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .kpi-value[_ngcontent-%COMP%] {\n font-size: 26px;\n font-weight: 700;\n color: #1e293b;\n line-height: 1;\n margin-bottom: 4px;\n }\n\n .kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .kpi-arrow[_ngcontent-%COMP%] {\n color: #cbd5e1;\n font-size: 14px;\n opacity: 0;\n transition: all 0.3s ease;\n }\n\n .kpi-card.clickable[_ngcontent-%COMP%]:hover .kpi-arrow[_ngcontent-%COMP%] {\n opacity: 1;\n color: #6366f1;\n transform: translateX(4px);\n }\n\n \n\n .execution-content[_ngcontent-%COMP%] {\n background: white;\n border-radius: 14px;\n box-shadow: 0 2px 12px rgba(99, 102, 241, 0.06);\n overflow: hidden;\n }\n\n .execution-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n }\n\n \n\n .list-header[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 120px 100px 100px 140px 100px;\n gap: 20px;\n padding: 16px 24px;\n background: linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%);\n border-bottom: 1px solid #e2e8f0;\n font-size: 11px;\n font-weight: 700;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .header-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n }\n\n \n\n .execution-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 120px 100px 100px 140px 100px;\n gap: 20px;\n padding: 18px 24px;\n border-bottom: 1px solid #f1f5f9;\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .execution-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n }\n\n .execution-row[_ngcontent-%COMP%]:hover {\n background: linear-gradient(90deg, rgba(99, 102, 241, 0.03) 0%, rgba(139, 92, 246, 0.03) 100%);\n }\n\n .execution-row.running[_ngcontent-%COMP%] {\n background: linear-gradient(90deg, rgba(59, 130, 246, 0.08) 0%, rgba(59, 130, 246, 0.04) 100%);\n border-left: 3px solid #3b82f6;\n }\n\n .execution-row.running[_ngcontent-%COMP%]:hover {\n background: linear-gradient(90deg, rgba(59, 130, 246, 0.12) 0%, rgba(59, 130, 246, 0.06) 100%);\n }\n\n \n\n .cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n font-size: 13px;\n color: #334155;\n }\n\n .cell.test-name[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n\n .test-info[_ngcontent-%COMP%] .name[_ngcontent-%COMP%] {\n font-weight: 600;\n color: #1e293b;\n font-size: 14px;\n }\n\n .test-info[_ngcontent-%COMP%] .suite[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #64748b;\n }\n\n .cell.status[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 8px;\n align-items: flex-start;\n }\n\n .progress-bar[_ngcontent-%COMP%] {\n width: 100%;\n height: 4px;\n background: #e2e8f0;\n border-radius: 2px;\n overflow: hidden;\n }\n\n .progress-fill[_ngcontent-%COMP%] {\n height: 100%;\n background: linear-gradient(90deg, #3b82f6, #60a5fa);\n border-radius: 2px;\n transition: width 0.3s ease;\n }\n\n .cell.actions[_ngcontent-%COMP%] {\n gap: 8px;\n justify-content: flex-end;\n }\n\n \n\n .icon-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n color: #64748b;\n cursor: pointer;\n border-radius: 10px;\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n font-size: 14px;\n }\n\n .icon-btn[_ngcontent-%COMP%]:hover {\n background: #6366f1;\n border-color: #6366f1;\n color: white;\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);\n }\n\n .icon-btn.danger[_ngcontent-%COMP%]:hover {\n background: #ef4444;\n border-color: #ef4444;\n box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);\n }\n\n \n\n .loading-placeholder[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 80px 40px;\n background: linear-gradient(180deg, #fafbff 0%, #f8fafc 100%);\n }\n\n \n\n .no-data[_ngcontent-%COMP%] {\n padding: 80px 40px;\n text-align: center;\n background: linear-gradient(180deg, #fafbff 0%, #f8fafc 100%);\n }\n\n .no-data[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 64px;\n color: #cbd5e1;\n margin-bottom: 20px;\n }\n\n .no-data[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 16px;\n color: #64748b;\n margin-bottom: 24px;\n }\n\n .no-data[_ngcontent-%COMP%] .action-btn[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);\n color: white;\n padding: 12px 24px;\n border-radius: 12px;\n font-weight: 600;\n box-shadow: 0 4px 16px rgba(99, 102, 241, 0.3);\n }\n\n .no-data[_ngcontent-%COMP%] .action-btn[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 24px rgba(99, 102, 241, 0.4);\n }\n\n \n\n @media (max-width: 1400px) {\n .kpi-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n }\n\n @media (max-width: 1200px) {\n .filter-bar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n\n .filter-chips[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n .filter-controls[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n .list-header[_ngcontent-%COMP%], \n .execution-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr 100px 80px 100px;\n }\n\n .header-cell.cost[_ngcontent-%COMP%], \n .header-cell.timestamp[_ngcontent-%COMP%], \n .cell.cost[_ngcontent-%COMP%], \n .cell.timestamp[_ngcontent-%COMP%] {\n display: none;\n }\n }\n\n @media (max-width: 768px) {\n .kpi-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .search-input[_ngcontent-%COMP%] {\n min-width: 200px;\n }\n }"], changeDetection: 0 });
|
|
597
|
-
}
|
|
598
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TestingExecutionComponent, [{
|
|
599
|
-
type: Component,
|
|
600
|
-
args: [{ selector: 'app-testing-execution', changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
601
|
-
<div class="testing-execution" kendoDialogContainer>
|
|
602
|
-
<!-- Premium Header with Gradient -->
|
|
603
|
-
<div class="execution-header">
|
|
604
|
-
<div class="header-left">
|
|
605
|
-
<div class="header-icon">
|
|
606
|
-
<i class="fa-solid fa-play-circle"></i>
|
|
607
|
-
</div>
|
|
608
|
-
<div class="header-text">
|
|
609
|
-
<h2>Test Execution Monitor</h2>
|
|
610
|
-
<div class="header-meta">
|
|
611
|
-
<span class="last-updated">
|
|
612
|
-
<i class="fa-solid fa-clock"></i>
|
|
613
|
-
Updated {{ lastUpdated | date:'shortTime' }}
|
|
614
|
-
</span>
|
|
615
|
-
@if (hasRunningTests$ | async) {
|
|
616
|
-
<div class="live-indicator">
|
|
617
|
-
<span class="pulse"></span>
|
|
618
|
-
<span class="text">Live</span>
|
|
619
|
-
</div>
|
|
620
|
-
}
|
|
621
|
-
</div>
|
|
622
|
-
</div>
|
|
623
|
-
</div>
|
|
624
|
-
<div class="header-actions">
|
|
625
|
-
<button class="action-btn refresh-btn" (click)="refresh()" [disabled]="isRefreshing">
|
|
626
|
-
<i class="fa-solid fa-sync-alt" [class.spinning]="isRefreshing"></i>
|
|
627
|
-
<span>Refresh</span>
|
|
628
|
-
</button>
|
|
629
|
-
<button class="action-btn primary-btn" (click)="startNewTest()">
|
|
630
|
-
<i class="fa-solid fa-play"></i>
|
|
631
|
-
<span>Run Test</span>
|
|
632
|
-
</button>
|
|
633
|
-
</div>
|
|
634
|
-
</div>
|
|
635
|
-
|
|
636
|
-
<!-- Smart Filter Bar -->
|
|
637
|
-
<div class="filter-bar">
|
|
638
|
-
<div class="filter-chips">
|
|
639
|
-
<button
|
|
640
|
-
class="filter-chip"
|
|
641
|
-
[class.active]="filters.status === 'all'"
|
|
642
|
-
(click)="filters.status = 'all'; onFilterChange()"
|
|
643
|
-
>
|
|
644
|
-
All
|
|
645
|
-
</button>
|
|
646
|
-
<button
|
|
647
|
-
class="filter-chip running"
|
|
648
|
-
[class.active]="filters.status === 'running'"
|
|
649
|
-
(click)="filters.status = 'running'; onFilterChange()"
|
|
650
|
-
>
|
|
651
|
-
<i class="fa-solid fa-spinner fa-spin"></i>
|
|
652
|
-
Running
|
|
653
|
-
</button>
|
|
654
|
-
<button
|
|
655
|
-
class="filter-chip passed"
|
|
656
|
-
[class.active]="filters.status === 'passed'"
|
|
657
|
-
(click)="filters.status = 'passed'; onFilterChange()"
|
|
658
|
-
>
|
|
659
|
-
<i class="fa-solid fa-check"></i>
|
|
660
|
-
Passed
|
|
661
|
-
</button>
|
|
662
|
-
<button
|
|
663
|
-
class="filter-chip failed"
|
|
664
|
-
[class.active]="filters.status === 'failed'"
|
|
665
|
-
(click)="filters.status = 'failed'; onFilterChange()"
|
|
666
|
-
>
|
|
667
|
-
<i class="fa-solid fa-times"></i>
|
|
668
|
-
Failed
|
|
669
|
-
</button>
|
|
670
|
-
</div>
|
|
671
|
-
|
|
672
|
-
<div class="filter-controls">
|
|
673
|
-
<div class="time-select">
|
|
674
|
-
<select [(ngModel)]="filters.timeRange" (change)="onFilterChange()">
|
|
675
|
-
<option value="today">Today</option>
|
|
676
|
-
<option value="week">This Week</option>
|
|
677
|
-
<option value="month">This Month</option>
|
|
678
|
-
<option value="all">All Time</option>
|
|
679
|
-
</select>
|
|
680
|
-
</div>
|
|
681
|
-
|
|
682
|
-
<div class="search-input">
|
|
683
|
-
<i class="fa-solid fa-search"></i>
|
|
684
|
-
<input
|
|
685
|
-
type="text"
|
|
686
|
-
[(ngModel)]="filters.searchText"
|
|
687
|
-
(input)="onFilterChange()"
|
|
688
|
-
placeholder="Search tests..."
|
|
689
|
-
/>
|
|
690
|
-
@if (filters.searchText) {
|
|
691
|
-
<button class="clear-btn" (click)="clearSearch()">
|
|
692
|
-
<i class="fa-solid fa-times"></i>
|
|
693
|
-
</button>
|
|
694
|
-
}
|
|
695
|
-
</div>
|
|
696
|
-
</div>
|
|
697
|
-
</div>
|
|
698
|
-
|
|
699
|
-
<!-- KPI Cards (Actionable) -->
|
|
700
|
-
<div class="kpi-grid">
|
|
701
|
-
<div
|
|
702
|
-
class="kpi-card running clickable"
|
|
703
|
-
(click)="filterByStatus('running')"
|
|
704
|
-
>
|
|
705
|
-
<div class="kpi-icon">
|
|
706
|
-
<i class="fa-solid fa-spinner fa-spin"></i>
|
|
707
|
-
</div>
|
|
708
|
-
<div class="kpi-content">
|
|
709
|
-
<div class="kpi-value">{{ (runningCount$ | async) ?? 0 }}</div>
|
|
710
|
-
<div class="kpi-label">Running Now</div>
|
|
711
|
-
</div>
|
|
712
|
-
<div class="kpi-arrow">
|
|
713
|
-
<i class="fa-solid fa-chevron-right"></i>
|
|
714
|
-
</div>
|
|
715
|
-
</div>
|
|
716
|
-
|
|
717
|
-
<div
|
|
718
|
-
class="kpi-card passed clickable"
|
|
719
|
-
(click)="filterByStatus('passed')"
|
|
720
|
-
>
|
|
721
|
-
<div class="kpi-icon">
|
|
722
|
-
<i class="fa-solid fa-check-circle"></i>
|
|
723
|
-
</div>
|
|
724
|
-
<div class="kpi-content">
|
|
725
|
-
<div class="kpi-value">{{ (completedTodayCount$ | async) ?? 0 }}</div>
|
|
726
|
-
<div class="kpi-label">Passed {{ getTimeRangeLabel() }}</div>
|
|
727
|
-
</div>
|
|
728
|
-
<div class="kpi-arrow">
|
|
729
|
-
<i class="fa-solid fa-chevron-right"></i>
|
|
730
|
-
</div>
|
|
731
|
-
</div>
|
|
732
|
-
|
|
733
|
-
<div
|
|
734
|
-
class="kpi-card failed clickable"
|
|
735
|
-
(click)="filterByStatus('failed')"
|
|
736
|
-
>
|
|
737
|
-
<div class="kpi-icon">
|
|
738
|
-
<i class="fa-solid fa-exclamation-circle"></i>
|
|
739
|
-
</div>
|
|
740
|
-
<div class="kpi-content">
|
|
741
|
-
<div class="kpi-value">{{ (failedTodayCount$ | async) ?? 0 }}</div>
|
|
742
|
-
<div class="kpi-label">Failed {{ getTimeRangeLabel() }}</div>
|
|
743
|
-
</div>
|
|
744
|
-
<div class="kpi-arrow">
|
|
745
|
-
<i class="fa-solid fa-chevron-right"></i>
|
|
746
|
-
</div>
|
|
747
|
-
</div>
|
|
748
|
-
|
|
749
|
-
<div class="kpi-card duration">
|
|
750
|
-
<div class="kpi-icon">
|
|
751
|
-
<i class="fa-solid fa-clock"></i>
|
|
752
|
-
</div>
|
|
753
|
-
<div class="kpi-content">
|
|
754
|
-
<div class="kpi-value">{{ formatDuration((avgDurationToday$ | async) ?? 0) }}</div>
|
|
755
|
-
<div class="kpi-label">Avg Duration</div>
|
|
756
|
-
</div>
|
|
757
|
-
</div>
|
|
758
|
-
</div>
|
|
759
|
-
|
|
760
|
-
<div class="execution-content">
|
|
761
|
-
<div class="execution-list">
|
|
762
|
-
<div class="list-header">
|
|
763
|
-
<div class="header-cell test-name">Test Name</div>
|
|
764
|
-
<div class="header-cell status">Status</div>
|
|
765
|
-
<div class="header-cell score">Score</div>
|
|
766
|
-
<div class="header-cell duration">Duration</div>
|
|
767
|
-
<div class="header-cell cost">Cost</div>
|
|
768
|
-
<div class="header-cell timestamp">Started At</div>
|
|
769
|
-
<div class="header-cell actions">Actions</div>
|
|
770
|
-
</div>
|
|
771
|
-
|
|
772
|
-
@if (isLoading) {
|
|
773
|
-
<div class="loading-placeholder">
|
|
774
|
-
<mj-loading text="Loading test executions..."></mj-loading>
|
|
775
|
-
</div>
|
|
776
|
-
} @else if ((filteredExecutions$ | async)?.length === 0) {
|
|
777
|
-
<div class="no-data">
|
|
778
|
-
<i class="fa-solid fa-inbox"></i>
|
|
779
|
-
<p>No test executions found</p>
|
|
780
|
-
<button class="action-btn primary" (click)="startNewTest()">
|
|
781
|
-
<i class="fa-solid fa-play"></i>
|
|
782
|
-
Run Your First Test
|
|
783
|
-
</button>
|
|
784
|
-
</div>
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
@for (execution of (filteredExecutions$ | async) ?? []; track execution.id) {
|
|
788
|
-
<div class="execution-row" [class.running]="execution.status === 'Running'">
|
|
789
|
-
<div class="cell test-name">
|
|
790
|
-
<div class="test-info">
|
|
791
|
-
<div class="name">{{ execution.testName }}</div>
|
|
792
|
-
<div class="suite">{{ execution.suiteName }}</div>
|
|
793
|
-
</div>
|
|
794
|
-
</div>
|
|
795
|
-
<div class="cell status">
|
|
796
|
-
<app-test-status-badge [status]="execution.status"></app-test-status-badge>
|
|
797
|
-
@if (execution.status === 'Running') {
|
|
798
|
-
<div class="progress-bar">
|
|
799
|
-
<div class="progress-fill" [style.width.%]="execution.progress"></div>
|
|
800
|
-
</div>
|
|
801
|
-
}
|
|
802
|
-
</div>
|
|
803
|
-
<div class="cell score">
|
|
804
|
-
<app-score-indicator
|
|
805
|
-
[score]="execution.score"
|
|
806
|
-
[showBar]="false"
|
|
807
|
-
[showIcon]="false"
|
|
808
|
-
></app-score-indicator>
|
|
809
|
-
</div>
|
|
810
|
-
<div class="cell duration">
|
|
811
|
-
{{ formatDuration(execution.duration) }}
|
|
812
|
-
</div>
|
|
813
|
-
<div class="cell cost">
|
|
814
|
-
<app-cost-display [cost]="execution.cost" [showIcon]="false"></app-cost-display>
|
|
815
|
-
</div>
|
|
816
|
-
<div class="cell timestamp">
|
|
817
|
-
{{ execution.startedAt | date:'short' }}
|
|
818
|
-
</div>
|
|
819
|
-
<div class="cell actions">
|
|
820
|
-
<button class="icon-btn" (click)="viewDetails(execution)" title="View Details">
|
|
821
|
-
<i class="fa-solid fa-eye"></i>
|
|
822
|
-
</button>
|
|
823
|
-
@if (execution.status === 'Running') {
|
|
824
|
-
<button class="icon-btn danger" (click)="cancelExecution(execution)" title="Cancel">
|
|
825
|
-
<i class="fa-solid fa-stop"></i>
|
|
826
|
-
</button>
|
|
827
|
-
} @else {
|
|
828
|
-
<button class="icon-btn" (click)="rerunTest(execution)" title="Re-run">
|
|
829
|
-
<i class="fa-solid fa-redo"></i>
|
|
830
|
-
</button>
|
|
831
|
-
}
|
|
832
|
-
</div>
|
|
833
|
-
</div>
|
|
834
|
-
}
|
|
835
|
-
</div>
|
|
836
|
-
</div>
|
|
837
|
-
</div>
|
|
838
|
-
`, styles: ["\n /* ============================================\n Testing Execution - Premium Design System\n ============================================ */\n\n .testing-execution {\n padding: 24px;\n height: 100%;\n overflow-y: auto;\n background: linear-gradient(135deg, #f8fafc 0%, #eef2f7 100%);\n }\n\n /* Premium Header */\n .execution-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);\n padding: 24px 28px;\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(99, 102, 241, 0.25);\n }\n\n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .header-icon {\n width: 48px;\n height: 48px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 22px;\n color: white;\n }\n\n .header-text h2 {\n margin: 0 0 4px 0;\n font-size: 20px;\n font-weight: 600;\n color: white;\n }\n\n .header-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .last-updated {\n font-size: 12px;\n color: rgba(255, 255, 255, 0.8);\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .last-updated i {\n font-size: 11px;\n }\n\n .live-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 12px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n color: white;\n }\n\n .pulse {\n width: 8px;\n height: 8px;\n background: #22c55e;\n border-radius: 50%;\n animation: pulse 2s infinite;\n box-shadow: 0 0 8px #22c55e;\n }\n\n @keyframes pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(1.3); }\n }\n\n .header-actions {\n display: flex;\n gap: 12px;\n }\n\n .action-btn {\n display: 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.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .refresh-btn {\n background: rgba(255, 255, 255, 0.15);\n color: white;\n border: 1px solid rgba(255, 255, 255, 0.25);\n }\n\n .refresh-btn:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.25);\n transform: translateY(-1px);\n }\n\n .primary-btn {\n background: white;\n color: #6366f1;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n\n .primary-btn:hover {\n background: #f8f9ff;\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);\n }\n\n .action-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none !important;\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 /* Smart 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: 16px 20px;\n background: white;\n border-radius: 14px;\n box-shadow: 0 2px 12px rgba(99, 102, 241, 0.06);\n }\n\n .filter-chips {\n display: flex;\n gap: 8px;\n }\n\n .filter-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: #f1f5f9;\n border: 2px solid transparent;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 600;\n color: #64748b;\n cursor: pointer;\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .filter-chip:hover {\n background: #e2e8f0;\n color: #475569;\n }\n\n .filter-chip.active {\n background: #6366f1;\n color: white;\n border-color: #6366f1;\n }\n\n .filter-chip.running.active {\n background: #3b82f6;\n border-color: #3b82f6;\n }\n\n .filter-chip.passed.active {\n background: #22c55e;\n border-color: #22c55e;\n }\n\n .filter-chip.failed.active {\n background: #ef4444;\n border-color: #ef4444;\n }\n\n .filter-chip i {\n font-size: 11px;\n }\n\n .filter-controls {\n display: flex;\n gap: 12px;\n align-items: center;\n }\n\n .time-select select {\n padding: 10px 14px;\n border: 2px solid #e2e8f0;\n border-radius: 10px;\n font-size: 13px;\n font-weight: 500;\n color: #475569;\n background: white;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .time-select select:focus {\n outline: none;\n border-color: #6366f1;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n }\n\n .search-input {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 16px;\n background: #f8fafc;\n border: 2px solid #e2e8f0;\n border-radius: 10px;\n min-width: 250px;\n transition: all 0.2s ease;\n }\n\n .search-input:focus-within {\n border-color: #6366f1;\n background: white;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n }\n\n .search-input i {\n color: #94a3b8;\n font-size: 14px;\n }\n\n .search-input input {\n flex: 1;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: #334155;\n }\n\n .search-input input::placeholder {\n color: #94a3b8;\n }\n\n .clear-btn {\n padding: 4px 8px;\n border: none;\n background: transparent;\n color: #94a3b8;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.2s ease;\n }\n\n .clear-btn:hover {\n background: #e2e8f0;\n color: #64748b;\n }\n\n /* KPI Cards Grid */\n .kpi-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 20px;\n }\n\n .kpi-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: white;\n border-radius: 14px;\n box-shadow: 0 2px 12px rgba(99, 102, 241, 0.06);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n position: relative;\n overflow: hidden;\n }\n\n .kpi-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 4px;\n height: 100%;\n border-radius: 4px 0 0 4px;\n }\n\n .kpi-card.clickable {\n cursor: pointer;\n }\n\n .kpi-card.clickable:hover {\n transform: translateY(-3px);\n box-shadow: 0 8px 24px rgba(99, 102, 241, 0.15);\n }\n\n .kpi-card.running::before { background: linear-gradient(180deg, #3b82f6, #60a5fa); }\n .kpi-card.passed::before { background: linear-gradient(180deg, #22c55e, #4ade80); }\n .kpi-card.failed::before { background: linear-gradient(180deg, #ef4444, #f87171); }\n .kpi-card.duration::before { background: linear-gradient(180deg, #8b5cf6, #a78bfa); }\n\n .kpi-icon {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 20px;\n }\n\n .kpi-card.running .kpi-icon {\n background: rgba(59, 130, 246, 0.1);\n color: #3b82f6;\n }\n\n .kpi-card.passed .kpi-icon {\n background: rgba(34, 197, 94, 0.1);\n color: #22c55e;\n }\n\n .kpi-card.failed .kpi-icon {\n background: rgba(239, 68, 68, 0.1);\n color: #ef4444;\n }\n\n .kpi-card.duration .kpi-icon {\n background: rgba(139, 92, 246, 0.1);\n color: #8b5cf6;\n }\n\n .kpi-content {\n flex: 1;\n }\n\n .kpi-value {\n font-size: 26px;\n font-weight: 700;\n color: #1e293b;\n line-height: 1;\n margin-bottom: 4px;\n }\n\n .kpi-label {\n font-size: 12px;\n font-weight: 500;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .kpi-arrow {\n color: #cbd5e1;\n font-size: 14px;\n opacity: 0;\n transition: all 0.3s ease;\n }\n\n .kpi-card.clickable:hover .kpi-arrow {\n opacity: 1;\n color: #6366f1;\n transform: translateX(4px);\n }\n\n /* Execution List Container */\n .execution-content {\n background: white;\n border-radius: 14px;\n box-shadow: 0 2px 12px rgba(99, 102, 241, 0.06);\n overflow: hidden;\n }\n\n .execution-list {\n display: flex;\n flex-direction: column;\n }\n\n /* List Header */\n .list-header {\n display: grid;\n grid-template-columns: 2fr 120px 100px 100px 140px 100px;\n gap: 20px;\n padding: 16px 24px;\n background: linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%);\n border-bottom: 1px solid #e2e8f0;\n font-size: 11px;\n font-weight: 700;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .header-cell {\n display: flex;\n align-items: center;\n }\n\n /* Execution Row */\n .execution-row {\n display: grid;\n grid-template-columns: 2fr 120px 100px 100px 140px 100px;\n gap: 20px;\n padding: 18px 24px;\n border-bottom: 1px solid #f1f5f9;\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .execution-row:last-child {\n border-bottom: none;\n }\n\n .execution-row:hover {\n background: linear-gradient(90deg, rgba(99, 102, 241, 0.03) 0%, rgba(139, 92, 246, 0.03) 100%);\n }\n\n .execution-row.running {\n background: linear-gradient(90deg, rgba(59, 130, 246, 0.08) 0%, rgba(59, 130, 246, 0.04) 100%);\n border-left: 3px solid #3b82f6;\n }\n\n .execution-row.running:hover {\n background: linear-gradient(90deg, rgba(59, 130, 246, 0.12) 0%, rgba(59, 130, 246, 0.06) 100%);\n }\n\n /* Cells */\n .cell {\n display: flex;\n align-items: center;\n font-size: 13px;\n color: #334155;\n }\n\n .cell.test-name {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n\n .test-info .name {\n font-weight: 600;\n color: #1e293b;\n font-size: 14px;\n }\n\n .test-info .suite {\n font-size: 12px;\n color: #64748b;\n }\n\n .cell.status {\n flex-direction: column;\n gap: 8px;\n align-items: flex-start;\n }\n\n .progress-bar {\n width: 100%;\n height: 4px;\n background: #e2e8f0;\n border-radius: 2px;\n overflow: hidden;\n }\n\n .progress-fill {\n height: 100%;\n background: linear-gradient(90deg, #3b82f6, #60a5fa);\n border-radius: 2px;\n transition: width 0.3s ease;\n }\n\n .cell.actions {\n gap: 8px;\n justify-content: flex-end;\n }\n\n /* Action Buttons */\n .icon-btn {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n color: #64748b;\n cursor: pointer;\n border-radius: 10px;\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n font-size: 14px;\n }\n\n .icon-btn:hover {\n background: #6366f1;\n border-color: #6366f1;\n color: white;\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);\n }\n\n .icon-btn.danger:hover {\n background: #ef4444;\n border-color: #ef4444;\n box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);\n }\n\n /* Loading State */\n .loading-placeholder {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 80px 40px;\n background: linear-gradient(180deg, #fafbff 0%, #f8fafc 100%);\n }\n\n /* Empty State */\n .no-data {\n padding: 80px 40px;\n text-align: center;\n background: linear-gradient(180deg, #fafbff 0%, #f8fafc 100%);\n }\n\n .no-data i {\n font-size: 64px;\n color: #cbd5e1;\n margin-bottom: 20px;\n }\n\n .no-data p {\n font-size: 16px;\n color: #64748b;\n margin-bottom: 24px;\n }\n\n .no-data .action-btn {\n background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);\n color: white;\n padding: 12px 24px;\n border-radius: 12px;\n font-weight: 600;\n box-shadow: 0 4px 16px rgba(99, 102, 241, 0.3);\n }\n\n .no-data .action-btn:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 24px rgba(99, 102, 241, 0.4);\n }\n\n /* Responsive */\n @media (max-width: 1400px) {\n .kpi-grid {\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-chips {\n justify-content: center;\n }\n\n .filter-controls {\n justify-content: center;\n }\n\n .list-header,\n .execution-row {\n grid-template-columns: 1fr 100px 80px 100px;\n }\n\n .header-cell.cost,\n .header-cell.timestamp,\n .cell.cost,\n .cell.timestamp {\n display: none;\n }\n }\n\n @media (max-width: 768px) {\n .kpi-grid {\n grid-template-columns: 1fr;\n }\n\n .search-input {\n min-width: 200px;\n }\n }\n "] }]
|
|
839
|
-
}], () => [{ type: i1.TestingInstrumentationService }, { type: i2.DialogService }, { type: i0.ChangeDetectorRef }, { type: i0.ViewContainerRef }], { initialState: [{
|
|
840
|
-
type: Input
|
|
841
|
-
}], stateChange: [{
|
|
842
|
-
type: Output
|
|
843
|
-
}] }); })();
|
|
844
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestingExecutionComponent, { className: "TestingExecutionComponent" }); })();
|
|
845
|
-
//# sourceMappingURL=testing-execution.component.js.map
|