@memberjunction/ng-dashboards 5.21.0 → 5.23.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/README.md +51 -0
- package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js +364 -362
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +2 -2
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +313 -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 +2792 -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 +382 -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 +2683 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -0
- package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +191 -197
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +9 -8
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +305 -299
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +319 -313
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +240 -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 +1767 -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/APIKeys/api-applications-panel.component.js +10 -12
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-create-dialog.component.js +13 -19
- package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.js +12 -14
- package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +61 -68
- package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
- package/dist/APIKeys/api-usage-panel.component.js +10 -11
- package/dist/APIKeys/api-usage-panel.component.js.map +1 -1
- package/dist/Actions/components/actions-list-view.component.js +82 -96
- package/dist/Actions/components/actions-list-view.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +130 -134
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +40 -46
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/Actions/components/code-management.component.js +2 -2
- package/dist/Actions/components/code-management.component.js.map +1 -1
- package/dist/Actions/components/entity-integration.component.js +2 -2
- package/dist/Actions/components/entity-integration.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +127 -132
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/executions-list-view.component.js +2 -2
- package/dist/Actions/components/executions-list-view.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.js +11 -17
- package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +5 -11
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-list-item.component.js +8 -10
- package/dist/Actions/components/explorer/action-list-item.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-toolbar.component.js +112 -133
- package/dist/Actions/components/explorer/action-toolbar.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-tree-panel.component.js +63 -83
- package/dist/Actions/components/explorer/action-tree-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.js +17 -21
- package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js +17 -21
- package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
- package/dist/Actions/components/scheduled-actions.component.js +2 -2
- package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
- package/dist/Actions/components/security-permissions.component.js +2 -2
- package/dist/Actions/components/security-permissions.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts +13 -5
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +168 -145
- package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts +4 -5
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +197 -200
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +5 -7
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +142 -148
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/browser/component-browser.component.js +153 -166
- package/dist/ComponentStudio/components/browser/component-browser.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +15 -20
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +16 -21
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js +18 -23
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/spec-editor.component.js +25 -30
- package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +10 -11
- package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +24 -35
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/text-import-dialog.component.js +15 -17
- package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +7 -6
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +6 -5
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +7 -6
- package/dist/Credentials/components/credentials-types-resource.component.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/DashboardBrowser/dashboard-share-dialog.component.js +9 -9
- package/dist/DashboardBrowser/dashboard-share-dialog.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/Integration/components/connections/connections.component.js +4 -4
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +246 -259
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
- package/dist/Integration/components/widgets/integration-card.component.js +7 -9
- package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
- package/dist/Integration/integration.module.d.ts +6 -10
- package/dist/Integration/integration.module.d.ts.map +1 -1
- package/dist/Integration/integration.module.js +12 -20
- package/dist/Integration/integration.module.js.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +106 -0
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +607 -0
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -0
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +126 -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 +1086 -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 +5 -0
- package/dist/KnowledgeHub/index.d.ts.map +1 -0
- package/dist/KnowledgeHub/index.js +6 -0
- package/dist/KnowledgeHub/index.js.map +1 -0
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +9 -7
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +5 -4
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +10 -9
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js +141 -132
- package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-log-detail-panel.component.js +4 -4
- package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js +141 -128
- package/dist/MCP/components/mcp-server-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.js +210 -218
- package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +2 -2
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/MCP/mcp.module.d.ts +6 -9
- package/dist/MCP/mcp.module.d.ts.map +1 -1
- package/dist/MCP/mcp.module.js +20 -22
- package/dist/MCP/mcp.module.js.map +1 -1
- 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/Scheduling/components/scheduling-activity.component.js +5 -4
- package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +6 -5
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +93 -92
- package/dist/Scheduling/components/scheduling-overview.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 +122 -54
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/actions-dashboards.module.d.ts +8 -13
- package/dist/actions-dashboards.module.d.ts.map +1 -1
- package/dist/actions-dashboards.module.js +6 -27
- package/dist/actions-dashboards.module.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +14 -11
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +58 -44
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/communication-dashboards.module.d.ts +4 -8
- package/dist/communication-dashboards.module.d.ts.map +1 -1
- package/dist/communication-dashboards.module.js +0 -19
- package/dist/communication-dashboards.module.js.map +1 -1
- package/dist/component-studio-dashboards.module.d.ts +7 -11
- package/dist/component-studio-dashboards.module.d.ts.map +1 -1
- package/dist/component-studio-dashboards.module.js +22 -34
- package/dist/component-studio-dashboards.module.js.map +1 -1
- package/dist/core-dashboards.module.d.ts +13 -18
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +18 -31
- package/dist/core-dashboards.module.js.map +1 -1
- package/dist/credentials-dashboards.module.d.ts +5 -8
- package/dist/credentials-dashboards.module.d.ts.map +1 -1
- package/dist/credentials-dashboards.module.js +3 -19
- package/dist/credentials-dashboards.module.js.map +1 -1
- package/dist/data-explorer-dashboards.module.d.ts +7 -13
- package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
- package/dist/data-explorer-dashboards.module.js +0 -27
- package/dist/data-explorer-dashboards.module.js.map +1 -1
- package/dist/lists-dashboards.module.d.ts +5 -8
- package/dist/lists-dashboards.module.d.ts.map +1 -1
- package/dist/lists-dashboards.module.js +3 -19
- package/dist/lists-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +5 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +6 -1
- package/dist/public-api.js.map +1 -1
- package/dist/scheduling-dashboards.module.d.ts +6 -10
- package/dist/scheduling-dashboards.module.d.ts.map +1 -1
- package/dist/scheduling-dashboards.module.js +3 -23
- package/dist/scheduling-dashboards.module.js.map +1 -1
- package/dist/testing-dashboards.module.d.ts +7 -12
- package/dist/testing-dashboards.module.d.ts.map +1 -1
- package/dist/testing-dashboards.module.js +4 -27
- package/dist/testing-dashboards.module.js.map +1 -1
- package/package.json +47 -53
|
@@ -8,8 +8,9 @@ import * as i0 from "@angular/core";
|
|
|
8
8
|
import * as i1 from "../services/scheduling-instrumentation.service";
|
|
9
9
|
import * as i2 from "@angular/common";
|
|
10
10
|
import * as i3 from "@angular/forms";
|
|
11
|
-
import * as i4 from "@memberjunction/ng-
|
|
12
|
-
import * as i5 from "@memberjunction/ng-
|
|
11
|
+
import * as i4 from "@memberjunction/ng-ui-components";
|
|
12
|
+
import * as i5 from "@memberjunction/ng-shared-generic";
|
|
13
|
+
import * as i6 from "@memberjunction/ng-scheduling";
|
|
13
14
|
function SchedulingJobsComponent_For_10_Template(rf, ctx) { if (rf & 1) {
|
|
14
15
|
i0.ɵɵelementStart(0, "option", 8);
|
|
15
16
|
i0.ɵɵtext(1);
|
|
@@ -495,7 +496,7 @@ export class SchedulingJobsComponent {
|
|
|
495
496
|
this.settingsPersistSubject.next();
|
|
496
497
|
}
|
|
497
498
|
static ɵfac = function SchedulingJobsComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SchedulingJobsComponent)(i0.ɵɵdirectiveInject(i1.SchedulingInstrumentationService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
498
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SchedulingJobsComponent, selectors: [["app-scheduling-jobs"]], inputs: { initialState: "initialState" }, outputs: { stateChange: "stateChange" }, standalone: false, decls: 29, vars: 10, consts: [[1, "jobs-container"], [1, "jobs-toolbar"], [1, "toolbar-left"], [1, "search-box"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search jobs...", 3, "input", "value"], [1, "filter-select", 3, "change", "value"], ["value", ""], [3, "value"], [1, "toolbar-right"], [1, "result-count"], [
|
|
499
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SchedulingJobsComponent, selectors: [["app-scheduling-jobs"]], inputs: { initialState: "initialState" }, outputs: { stateChange: "stateChange" }, standalone: false, decls: 29, vars: 10, consts: [[1, "jobs-container"], [1, "jobs-toolbar"], [1, "toolbar-left"], [1, "search-box"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search jobs...", 3, "input", "value"], [1, "filter-select", 3, "change", "value"], ["value", ""], [3, "value"], [1, "toolbar-right"], [1, "result-count"], ["mjButton", "", "variant", "secondary", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "primary-btn", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "loading-container"], [1, "empty-state"], [1, "jobs-grid"], [3, "Close", "Saved", "Deleted", "IsOpen", "ScheduledJobID"], ["text", "Loading jobs...", "size", "medium"], [1, "empty-icon"], [1, "fa-solid", "fa-calendar-xmark"], [1, "primary-btn"], [1, "job-card"], [1, "job-card", 3, "click"], [1, "job-card-header"], [1, "job-card-title"], [1, "type-icon"], [1, "job-name"], [1, "status-chip", 3, "ngClass"], [1, "job-card-body"], [1, "job-description"], [1, "job-meta-grid"], [1, "meta-item"], [1, "meta-label"], [1, "meta-value"], [1, "meta-value", "mono"], [1, "success-section"], [1, "success-header"], [1, "success-label"], [1, "success-value"], [1, "success-bar-track"], [1, "success-bar-fill"], [1, "run-stats"], [1, "stat-success"], [1, "fa-solid", "fa-check"], [1, "stat-failure"], [1, "fa-solid", "fa-xmark"], [1, "stat-total"], [1, "delete-confirm-overlay"], [1, "job-card-footer"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click"], [1, "fa-solid", "fa-up-right-from-square"], ["mjButton", "", "variant", "danger", "size", "sm", 3, "click"], [1, "fa-solid", "fa-trash-can"], [1, "delete-confirm-overlay", 3, "click"], [1, "delete-confirm-content"], [1, "fa-solid", "fa-triangle-exclamation", "delete-warn-icon"], [1, "delete-confirm-text"], [1, "delete-confirm-actions"], [1, "delete-confirm-btn", 3, "click", "disabled"], [1, "delete-cancel-btn", 3, "click"], [1, "fa-solid", "fa-spinner", "fa-spin"]], template: function SchedulingJobsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
499
500
|
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "div", 3);
|
|
500
501
|
i0.ɵɵelement(4, "i", 4);
|
|
501
502
|
i0.ɵɵelementStart(5, "input", 5);
|
|
@@ -555,11 +556,11 @@ export class SchedulingJobsComponent {
|
|
|
555
556
|
i0.ɵɵconditional(!ctx.IsLoading && ctx.FilteredJobs.length > 0 ? 27 : -1);
|
|
556
557
|
i0.ɵɵadvance();
|
|
557
558
|
i0.ɵɵproperty("IsOpen", ctx.SlideoutOpen)("ScheduledJobID", (ctx.SelectedJob == null ? null : ctx.SelectedJob.jobId) ?? null);
|
|
558
|
-
} }, dependencies: [i2.NgClass, i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i4.LoadingComponent, i5.ScheduledJobSlidePanelComponent], styles: [".jobs-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n position: relative;\n}\n\n\n\n.jobs-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.toolbar-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.toolbar-right[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.search-box[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n min-width: 240px;\n transition: border-color 0.2s;\n}\n\n.search-box[_ngcontent-%COMP%]:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.search-box[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n}\n\n.search-box[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n border: none;\n outline: none;\n background: transparent;\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n width: 100%;\n}\n\n.filter-select[_ngcontent-%COMP%] {\n padding: 8px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 0.85rem;\n color: var(--mj-text-secondary);\n cursor: pointer;\n outline: none;\n transition: border-color 0.2s;\n}\n\n.filter-select[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-brand-primary);\n}\n\n.result-count[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.control-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.2s ease;\n}\n\n.control-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.primary-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 20px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 10px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 600;\n transition: all 0.2s ease;\n}\n\n.primary-btn[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-md);\n}\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 64px 24px;\n background: var(--mj-bg-surface-card);\n border-radius: 16px;\n border: 2px dashed var(--mj-border-default);\n text-align: center;\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 20px;\n}\n\n.empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2rem;\n color: var(--mj-text-muted);\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 1.1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 8px;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n margin: 0 0 16px;\n font-size: 0.9rem;\n}\n\n\n\n.jobs-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));\n gap: 16px;\n}\n\n.job-card[_ngcontent-%COMP%] {\n position: relative;\n background: var(--mj-bg-surface-card);\n border-radius: 16px;\n border: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.job-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n border-color: var(--mj-brand-primary);\n}\n\n\n\n.job-card-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.job-card-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex: 1;\n min-width: 0;\n}\n\n.type-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 1rem;\n flex-shrink: 0;\n}\n\n.job-name[_ngcontent-%COMP%] {\n font-weight: 700;\n color: var(--mj-text-primary);\n font-size: 0.9rem;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: 1.3;\n}\n\n.status-chip[_ngcontent-%COMP%] {\n font-size: 0.7rem;\n font-weight: 700;\n padding: 3px 10px;\n border-radius: 12px;\n flex-shrink: 0;\n margin-left: 8px;\n}\n\n.status-active[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.status-paused[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n.status-disabled[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.status-pending[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-expired[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n\n\n\n.job-card-body[_ngcontent-%COMP%] {\n padding: 16px 20px;\n flex: 1;\n}\n\n.job-description[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: 1.4;\n}\n\n.job-meta-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.meta-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.meta-label[_ngcontent-%COMP%] {\n font-size: 0.65rem;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.meta-value[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.meta-value.mono[_ngcontent-%COMP%] {\n font-family: 'SFMono-Regular', Consolas, monospace;\n font-size: 0.75rem;\n}\n\n\n\n.success-section[_ngcontent-%COMP%] {\n padding-top: 12px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.success-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n}\n\n.success-label[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.success-value[_ngcontent-%COMP%] {\n font-size: 0.85rem;\n font-weight: 800;\n}\n\n.success-bar-track[_ngcontent-%COMP%] {\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.success-bar-fill[_ngcontent-%COMP%] {\n height: 100%;\n border-radius: 3px;\n transition: width 0.5s ease;\n}\n\n.run-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n margin-top: 8px;\n font-size: 0.75rem;\n}\n\n.stat-success[_ngcontent-%COMP%] { color: var(--mj-status-success); font-weight: 600; }\n.stat-failure[_ngcontent-%COMP%] { color: var(--mj-status-error); font-weight: 600; }\n.stat-total[_ngcontent-%COMP%] { color: var(--mj-text-muted); margin-left: auto; }\n\n\n\n.job-card-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n padding: 12px 20px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n background: var(--mj-bg-surface-sunken);\n}\n\n.action-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.2s;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n\n\n.slideout-backdrop[_ngcontent-%COMP%] {\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 animation: _ngcontent-%COMP%_fadeInBackdrop 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeInBackdrop {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.slideout-panel[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: -100%;\n height: 100vh;\n background: var(--mj-bg-surface-card);\n box-shadow: var(--mj-shadow-lg);\n z-index: 1000;\n transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n overflow-y: auto;\n}\n\n.slideout-panel.open[_ngcontent-%COMP%] {\n right: 0;\n}\n\n.slideout-resize-handle[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n background: rgba(255, 255, 255, 0.95);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n border-radius: 16px;\n backdrop-filter: blur(4px);\n}\n\n.slideout-resize-handle[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.slideout-resize-handle[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n\n\n.delete-confirm-overlay[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n background: rgba(255, 255, 255, 0.95);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n border-radius: 16px;\n backdrop-filter: blur(4px);\n}\n\n.delete-confirm-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 24px;\n text-align: center;\n}\n\n.delete-warn-icon[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n color: var(--mj-status-error);\n}\n\n.delete-confirm-text[_ngcontent-%COMP%] {\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.delete-confirm-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-top: 4px;\n}\n\n.delete-confirm-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 16px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 600;\n transition: background 0.2s;\n}\n\n.delete-confirm-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-status-error-text);\n}\n\n.delete-confirm-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n\n.delete-cancel-btn[_ngcontent-%COMP%] {\n padding: 6px 16px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 500;\n transition: all 0.2s;\n}\n\n.delete-cancel-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n\n\n.action-btn-danger[_ngcontent-%COMP%] {\n margin-left: auto;\n color: var(--mj-status-error);\n border-color: var(--mj-status-error-border);\n}\n\n.action-btn-danger[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error);\n color: var(--mj-status-error-text);\n}\n\n\n\n@media (max-width: 1024px) {\n .jobs-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n }\n}\n\n@media (max-width: 768px) {\n .jobs-toolbar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n .toolbar-right[_ngcontent-%COMP%] {\n justify-content: space-between;\n }\n .jobs-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n .search-box[_ngcontent-%COMP%] {\n min-width: auto;\n flex: 1;\n }\n}"], changeDetection: 0 });
|
|
559
|
+
} }, dependencies: [i2.NgClass, i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i4.MJButtonDirective, i5.LoadingComponent, i6.ScheduledJobSlidePanelComponent], styles: [".jobs-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n position: relative;\n}\n\n\n\n.jobs-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.toolbar-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.toolbar-right[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.search-box[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n min-width: 240px;\n transition: border-color 0.2s;\n}\n\n.search-box[_ngcontent-%COMP%]:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.search-box[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n}\n\n.search-box[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n border: none;\n outline: none;\n background: transparent;\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n width: 100%;\n}\n\n.filter-select[_ngcontent-%COMP%] {\n padding: 8px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 0.85rem;\n color: var(--mj-text-secondary);\n cursor: pointer;\n outline: none;\n transition: border-color 0.2s;\n}\n\n.filter-select[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-brand-primary);\n}\n\n.result-count[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.control-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.2s ease;\n}\n\n.control-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.primary-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 20px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 10px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 600;\n transition: all 0.2s ease;\n}\n\n.primary-btn[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-md);\n}\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 64px 24px;\n background: var(--mj-bg-surface-card);\n border-radius: 16px;\n border: 2px dashed var(--mj-border-default);\n text-align: center;\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 20px;\n}\n\n.empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2rem;\n color: var(--mj-text-muted);\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 1.1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 8px;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n margin: 0 0 16px;\n font-size: 0.9rem;\n}\n\n\n\n.jobs-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));\n gap: 16px;\n}\n\n.job-card[_ngcontent-%COMP%] {\n position: relative;\n background: var(--mj-bg-surface-card);\n border-radius: 16px;\n border: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.job-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n border-color: var(--mj-brand-primary);\n}\n\n\n\n.job-card-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.job-card-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex: 1;\n min-width: 0;\n}\n\n.type-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 1rem;\n flex-shrink: 0;\n}\n\n.job-name[_ngcontent-%COMP%] {\n font-weight: 700;\n color: var(--mj-text-primary);\n font-size: 0.9rem;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: 1.3;\n}\n\n.status-chip[_ngcontent-%COMP%] {\n font-size: 0.7rem;\n font-weight: 700;\n padding: 3px 10px;\n border-radius: 12px;\n flex-shrink: 0;\n margin-left: 8px;\n}\n\n.status-active[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.status-paused[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n.status-disabled[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.status-pending[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-expired[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n\n\n\n.job-card-body[_ngcontent-%COMP%] {\n padding: 16px 20px;\n flex: 1;\n}\n\n.job-description[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: 1.4;\n}\n\n.job-meta-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.meta-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.meta-label[_ngcontent-%COMP%] {\n font-size: 0.65rem;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.meta-value[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.meta-value.mono[_ngcontent-%COMP%] {\n font-family: 'SFMono-Regular', Consolas, monospace;\n font-size: 0.75rem;\n}\n\n\n\n.success-section[_ngcontent-%COMP%] {\n padding-top: 12px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.success-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n}\n\n.success-label[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.success-value[_ngcontent-%COMP%] {\n font-size: 0.85rem;\n font-weight: 800;\n}\n\n.success-bar-track[_ngcontent-%COMP%] {\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.success-bar-fill[_ngcontent-%COMP%] {\n height: 100%;\n border-radius: 3px;\n transition: width 0.5s ease;\n}\n\n.run-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n margin-top: 8px;\n font-size: 0.75rem;\n}\n\n.stat-success[_ngcontent-%COMP%] { color: var(--mj-status-success); font-weight: 600; }\n.stat-failure[_ngcontent-%COMP%] { color: var(--mj-status-error); font-weight: 600; }\n.stat-total[_ngcontent-%COMP%] { color: var(--mj-text-muted); margin-left: auto; }\n\n\n\n.job-card-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n padding: 12px 20px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n background: var(--mj-bg-surface-sunken);\n}\n\n.action-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.2s;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n\n\n.slideout-backdrop[_ngcontent-%COMP%] {\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 animation: _ngcontent-%COMP%_fadeInBackdrop 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeInBackdrop {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.slideout-panel[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: -100%;\n height: 100vh;\n background: var(--mj-bg-surface-card);\n box-shadow: var(--mj-shadow-lg);\n z-index: 1000;\n transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n overflow-y: auto;\n}\n\n.slideout-panel.open[_ngcontent-%COMP%] {\n right: 0;\n}\n\n.slideout-resize-handle[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n background: rgba(255, 255, 255, 0.95);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n border-radius: 16px;\n backdrop-filter: blur(4px);\n}\n\n.slideout-resize-handle[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.slideout-resize-handle[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n\n\n.delete-confirm-overlay[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n background: rgba(255, 255, 255, 0.95);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n border-radius: 16px;\n backdrop-filter: blur(4px);\n}\n\n.delete-confirm-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 24px;\n text-align: center;\n}\n\n.delete-warn-icon[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n color: var(--mj-status-error);\n}\n\n.delete-confirm-text[_ngcontent-%COMP%] {\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.delete-confirm-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-top: 4px;\n}\n\n.delete-confirm-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 16px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 600;\n transition: background 0.2s;\n}\n\n.delete-confirm-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-status-error-text);\n}\n\n.delete-confirm-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n\n.delete-cancel-btn[_ngcontent-%COMP%] {\n padding: 6px 16px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 500;\n transition: all 0.2s;\n}\n\n.delete-cancel-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n\n\n.action-btn-danger[_ngcontent-%COMP%] {\n margin-left: auto;\n color: var(--mj-status-error);\n border-color: var(--mj-status-error-border);\n}\n\n.action-btn-danger[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error);\n color: var(--mj-status-error-text);\n}\n\n\n\n@media (max-width: 1024px) {\n .jobs-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n }\n}\n\n@media (max-width: 768px) {\n .jobs-toolbar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n .toolbar-right[_ngcontent-%COMP%] {\n justify-content: space-between;\n }\n .jobs-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n .search-box[_ngcontent-%COMP%] {\n min-width: auto;\n flex: 1;\n }\n}"], changeDetection: 0 });
|
|
559
560
|
}
|
|
560
561
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SchedulingJobsComponent, [{
|
|
561
562
|
type: Component,
|
|
562
|
-
args: [{ standalone: false, selector: 'app-scheduling-jobs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"jobs-container\">\n <!-- Toolbar -->\n <div class=\"jobs-toolbar\">\n <div class=\"toolbar-left\">\n <div class=\"search-box\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Search jobs...\"\n [value]=\"SearchTerm\"\n (input)=\"OnSearchChange($any($event.target).value)\" />\n </div>\n <select class=\"filter-select\" [value]=\"StatusFilter\" (change)=\"OnStatusFilterChange($any($event.target).value)\">\n <option value=\"\">All Statuses</option>\n @for (s of StatusOptions.slice(1); track s) {\n <option [value]=\"s\">{{s}}</option>\n }\n </select>\n <select class=\"filter-select\" [value]=\"TypeFilter\" (change)=\"OnTypeFilterChange($any($event.target).value)\">\n <option value=\"\">All Types</option>\n @for (t of TypeOptions.slice(1); track t) {\n <option [value]=\"t\">{{t}}</option>\n }\n </select>\n </div>\n <div class=\"toolbar-right\">\n <span class=\"result-count\">{{FilteredJobs.length}} of {{Jobs.length}} jobs</span>\n <button class=\"control-btn\" (click)=\"Refresh()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Refresh\n </button>\n <button class=\"primary-btn\" (click)=\"OpenCreateSlideout()\">\n <i class=\"fa-solid fa-plus\"></i> New Job\n </button>\n </div>\n </div>\n\n <!-- Loading -->\n @if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading jobs...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Empty State -->\n @if (!IsLoading && FilteredJobs.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-calendar-xmark\"></i>\n </div>\n <h3>No jobs found</h3>\n @if (SearchTerm || StatusFilter || TypeFilter) {\n <p>Try adjusting your filters</p>\n }\n @if (!SearchTerm && !StatusFilter && !TypeFilter) {\n <p>Create your first scheduled job to get started</p>\n }\n @if (!SearchTerm && !StatusFilter && !TypeFilter) {\n <button class=\"primary-btn\" (click)=\"OpenCreateSlideout()\">\n <i class=\"fa-solid fa-plus\"></i> Create Job\n </button>\n }\n </div>\n }\n\n <!-- Job Cards Grid -->\n @if (!IsLoading && FilteredJobs.length > 0) {\n <div class=\"jobs-grid\">\n @for (job of FilteredJobs; track job) {\n <div\n class=\"job-card\"\n (click)=\"OpenEditSlideout(job)\">\n <!-- Card Header -->\n <div class=\"job-card-header\">\n <div class=\"job-card-title\">\n <i [class]=\"GetTypeIcon(job.jobType)\" class=\"type-icon\"></i>\n <span class=\"job-name\">{{job.jobName}}</span>\n </div>\n <span class=\"status-chip\" [ngClass]=\"GetStatusClass(job.status)\">{{job.status}}</span>\n </div>\n <!-- Card Body -->\n <div class=\"job-card-body\">\n @if (job.description) {\n <div class=\"job-description\">{{job.description}}</div>\n }\n <div class=\"job-meta-grid\">\n <div class=\"meta-item\">\n <span class=\"meta-label\">Type</span>\n <span class=\"meta-value\">{{job.jobType}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Schedule</span>\n <span class=\"meta-value mono\">{{job.cronExpression}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Last Run</span>\n <span class=\"meta-value\">{{FormatDate(job.lastRunAt)}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Next Run</span>\n <span class=\"meta-value\">{{FormatDate(job.nextRunAt)}}</span>\n </div>\n </div>\n <!-- Success Rate Bar -->\n <div class=\"success-section\">\n <div class=\"success-header\">\n <span class=\"success-label\">Success Rate</span>\n <span class=\"success-value\" [style.color]=\"GetSuccessRateColor(job.successRate)\">\n {{FormatPercentage(job.successRate)}}\n </span>\n </div>\n <div class=\"success-bar-track\">\n <div class=\"success-bar-fill\"\n [style.width]=\"(job.successRate * 100) + '%'\"\n [style.background]=\"GetSuccessRateColor(job.successRate)\">\n </div>\n </div>\n <div class=\"run-stats\">\n <span class=\"stat-success\"><i class=\"fa-solid fa-check\"></i> {{job.successCount}}</span>\n <span class=\"stat-failure\"><i class=\"fa-solid fa-xmark\"></i> {{job.failureCount}}</span>\n <span class=\"stat-total\">{{job.totalRuns}} total</span>\n </div>\n </div>\n </div>\n <!-- Delete confirmation overlay -->\n @if (IsDeleteConfirming(job.jobId)) {\n <div class=\"delete-confirm-overlay\" (click)=\"$event.stopPropagation()\">\n <div class=\"delete-confirm-content\">\n <i class=\"fa-solid fa-triangle-exclamation delete-warn-icon\"></i>\n <span class=\"delete-confirm-text\">Delete this scheduled job?</span>\n <div class=\"delete-confirm-actions\">\n <button class=\"delete-confirm-btn\" [disabled]=\"IsDeleting\" (click)=\"ConfirmDelete(job.jobId, $event)\">\n @if (IsDeleting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Deleting...\n } @else {\n Delete\n }\n </button>\n <button class=\"delete-cancel-btn\" (click)=\"CancelDelete($event)\">Cancel</button>\n </div>\n </div>\n </div>\n }\n <!-- Card Footer -->\n <div class=\"job-card-footer\">\n <button class=\"action-btn\" (click)=\"ToggleJobStatus(job, $event)\">\n <i [class]=\"job.status === 'Active' ? 'fa-solid fa-pause' : 'fa-solid fa-play'\"></i>\n {{job.status === 'Active' ? 'Pause' : 'Resume'}}\n </button>\n <button class=\"action-btn\" (click)=\"OpenEntityRecord(job); $event.stopPropagation()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n Full Details\n </button>\n <button class=\"action-btn action-btn-danger\" (click)=\"ShowDeleteConfirm(job, $event)\">\n <i class=\"fa-solid fa-trash-can\"></i>\n Delete\n </button>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Slideout Panel -->\n <mj-scheduled-job-slide-panel\n [IsOpen]=\"SlideoutOpen\"\n [ScheduledJobID]=\"SelectedJob?.jobId ?? null\"\n (Close)=\"CloseSlideout()\"\n (Saved)=\"OnSlideoutSaved()\"\n (Deleted)=\"OnSlideoutSaved()\">\n </mj-scheduled-job-slide-panel>\n</div>\n", styles: [".jobs-container {\n display: flex;\n flex-direction: column;\n gap: 20px;\n position: relative;\n}\n\n/* \u2500\u2500 Toolbar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.jobs-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.toolbar-left {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.toolbar-right {\n display: flex;\n gap: 8px;\n align-items: center;\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: 1px solid var(--mj-border-default);\n border-radius: 10px;\n min-width: 240px;\n transition: border-color 0.2s;\n}\n\n.search-box:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.search-box i {\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n}\n\n.search-box input {\n border: none;\n outline: none;\n background: transparent;\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n width: 100%;\n}\n\n.filter-select {\n padding: 8px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 0.85rem;\n color: var(--mj-text-secondary);\n cursor: pointer;\n outline: none;\n transition: border-color 0.2s;\n}\n\n.filter-select:focus {\n border-color: var(--mj-brand-primary);\n}\n\n.result-count {\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.control-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.2s ease;\n}\n\n.control-btn:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.primary-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 20px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 10px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 600;\n transition: all 0.2s ease;\n}\n\n.primary-btn:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-md);\n}\n\n/* \u2500\u2500 Loading & Empty \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.loading-container {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 64px 24px;\n background: var(--mj-bg-surface-card);\n border-radius: 16px;\n border: 2px dashed var(--mj-border-default);\n text-align: center;\n}\n\n.empty-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 20px;\n}\n\n.empty-icon i {\n font-size: 2rem;\n color: var(--mj-text-muted);\n}\n\n.empty-state h3 {\n font-size: 1.1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 8px;\n}\n\n.empty-state p {\n color: var(--mj-text-secondary);\n margin: 0 0 16px;\n font-size: 0.9rem;\n}\n\n/* \u2500\u2500 Job Cards Grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.jobs-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));\n gap: 16px;\n}\n\n.job-card {\n position: relative;\n background: var(--mj-bg-surface-card);\n border-radius: 16px;\n border: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.job-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n border-color: var(--mj-brand-primary);\n}\n\n/* Card Header */\n.job-card-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.job-card-title {\n display: flex;\n align-items: center;\n gap: 10px;\n flex: 1;\n min-width: 0;\n}\n\n.type-icon {\n color: var(--mj-brand-primary);\n font-size: 1rem;\n flex-shrink: 0;\n}\n\n.job-name {\n font-weight: 700;\n color: var(--mj-text-primary);\n font-size: 0.9rem;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: 1.3;\n}\n\n.status-chip {\n font-size: 0.7rem;\n font-weight: 700;\n padding: 3px 10px;\n border-radius: 12px;\n flex-shrink: 0;\n margin-left: 8px;\n}\n\n.status-active { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.status-paused { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n.status-disabled { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.status-pending { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-expired { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n\n/* Card Body */\n.job-card-body {\n padding: 16px 20px;\n flex: 1;\n}\n\n.job-description {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: 1.4;\n}\n\n.job-meta-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.meta-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.meta-label {\n font-size: 0.65rem;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.meta-value {\n font-size: 0.8rem;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.meta-value.mono {\n font-family: 'SFMono-Regular', Consolas, monospace;\n font-size: 0.75rem;\n}\n\n/* Success Rate */\n.success-section {\n padding-top: 12px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.success-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n}\n\n.success-label {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.success-value {\n font-size: 0.85rem;\n font-weight: 800;\n}\n\n.success-bar-track {\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.success-bar-fill {\n height: 100%;\n border-radius: 3px;\n transition: width 0.5s ease;\n}\n\n.run-stats {\n display: flex;\n gap: 12px;\n margin-top: 8px;\n font-size: 0.75rem;\n}\n\n.stat-success { color: var(--mj-status-success); font-weight: 600; }\n.stat-failure { color: var(--mj-status-error); font-weight: 600; }\n.stat-total { color: var(--mj-text-muted); margin-left: auto; }\n\n/* Card Footer */\n.job-card-footer {\n display: flex;\n gap: 8px;\n padding: 12px 20px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n background: var(--mj-bg-surface-sunken);\n}\n\n.action-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.2s;\n}\n\n.action-btn:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n/* \u2500\u2500 Slideout Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.slideout-backdrop {\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 animation: fadeInBackdrop 0.2s ease;\n}\n\n@keyframes fadeInBackdrop {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.slideout-panel {\n position: fixed;\n top: 0;\n right: -100%;\n height: 100vh;\n background: var(--mj-bg-surface-card);\n box-shadow: var(--mj-shadow-lg);\n z-index: 1000;\n transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n overflow-y: auto;\n}\n\n.slideout-panel.open {\n right: 0;\n}\n\n.slideout-resize-handle {\n position: absolute;\n inset: 0;\n background: rgba(255, 255, 255, 0.95);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n border-radius: 16px;\n backdrop-filter: blur(4px);\n}\n\n.slideout-resize-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.slideout-resize-handle:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n/* \u2500\u2500 Delete Confirmation Overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.delete-confirm-overlay {\n position: absolute;\n inset: 0;\n background: rgba(255, 255, 255, 0.95);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n border-radius: 16px;\n backdrop-filter: blur(4px);\n}\n\n.delete-confirm-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 24px;\n text-align: center;\n}\n\n.delete-warn-icon {\n font-size: 1.5rem;\n color: var(--mj-status-error);\n}\n\n.delete-confirm-text {\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.delete-confirm-actions {\n display: flex;\n gap: 8px;\n margin-top: 4px;\n}\n\n.delete-confirm-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 16px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 600;\n transition: background 0.2s;\n}\n\n.delete-confirm-btn:hover:not(:disabled) {\n background: var(--mj-status-error-text);\n}\n\n.delete-confirm-btn:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n\n.delete-cancel-btn {\n padding: 6px 16px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 500;\n transition: all 0.2s;\n}\n\n.delete-cancel-btn:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n/* \u2500\u2500 Danger Action Button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.action-btn-danger {\n margin-left: auto;\n color: var(--mj-status-error);\n border-color: var(--mj-status-error-border);\n}\n\n.action-btn-danger:hover {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error);\n color: var(--mj-status-error-text);\n}\n\n/* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n@media (max-width: 1024px) {\n .jobs-grid {\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n }\n}\n\n@media (max-width: 768px) {\n .jobs-toolbar {\n flex-direction: column;\n align-items: stretch;\n }\n .toolbar-right {\n justify-content: space-between;\n }\n .jobs-grid {\n grid-template-columns: 1fr;\n }\n .search-box {\n min-width: auto;\n flex: 1;\n }\n}\n"] }]
|
|
563
|
+
args: [{ standalone: false, selector: 'app-scheduling-jobs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"jobs-container\">\n <!-- Toolbar -->\n <div class=\"jobs-toolbar\">\n <div class=\"toolbar-left\">\n <div class=\"search-box\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Search jobs...\"\n [value]=\"SearchTerm\"\n (input)=\"OnSearchChange($any($event.target).value)\" />\n </div>\n <select class=\"filter-select\" [value]=\"StatusFilter\" (change)=\"OnStatusFilterChange($any($event.target).value)\">\n <option value=\"\">All Statuses</option>\n @for (s of StatusOptions.slice(1); track s) {\n <option [value]=\"s\">{{s}}</option>\n }\n </select>\n <select class=\"filter-select\" [value]=\"TypeFilter\" (change)=\"OnTypeFilterChange($any($event.target).value)\">\n <option value=\"\">All Types</option>\n @for (t of TypeOptions.slice(1); track t) {\n <option [value]=\"t\">{{t}}</option>\n }\n </select>\n </div>\n <div class=\"toolbar-right\">\n <span class=\"result-count\">{{FilteredJobs.length}} of {{Jobs.length}} jobs</span>\n <button mjButton variant=\"secondary\" (click)=\"Refresh()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Refresh\n </button>\n <button class=\"primary-btn\" (click)=\"OpenCreateSlideout()\">\n <i class=\"fa-solid fa-plus\"></i> New Job\n </button>\n </div>\n </div>\n\n <!-- Loading -->\n @if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading jobs...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Empty State -->\n @if (!IsLoading && FilteredJobs.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-calendar-xmark\"></i>\n </div>\n <h3>No jobs found</h3>\n @if (SearchTerm || StatusFilter || TypeFilter) {\n <p>Try adjusting your filters</p>\n }\n @if (!SearchTerm && !StatusFilter && !TypeFilter) {\n <p>Create your first scheduled job to get started</p>\n }\n @if (!SearchTerm && !StatusFilter && !TypeFilter) {\n <button class=\"primary-btn\" (click)=\"OpenCreateSlideout()\">\n <i class=\"fa-solid fa-plus\"></i> Create Job\n </button>\n }\n </div>\n }\n\n <!-- Job Cards Grid -->\n @if (!IsLoading && FilteredJobs.length > 0) {\n <div class=\"jobs-grid\">\n @for (job of FilteredJobs; track job) {\n <div\n class=\"job-card\"\n (click)=\"OpenEditSlideout(job)\">\n <!-- Card Header -->\n <div class=\"job-card-header\">\n <div class=\"job-card-title\">\n <i [class]=\"GetTypeIcon(job.jobType)\" class=\"type-icon\"></i>\n <span class=\"job-name\">{{job.jobName}}</span>\n </div>\n <span class=\"status-chip\" [ngClass]=\"GetStatusClass(job.status)\">{{job.status}}</span>\n </div>\n <!-- Card Body -->\n <div class=\"job-card-body\">\n @if (job.description) {\n <div class=\"job-description\">{{job.description}}</div>\n }\n <div class=\"job-meta-grid\">\n <div class=\"meta-item\">\n <span class=\"meta-label\">Type</span>\n <span class=\"meta-value\">{{job.jobType}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Schedule</span>\n <span class=\"meta-value mono\">{{job.cronExpression}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Last Run</span>\n <span class=\"meta-value\">{{FormatDate(job.lastRunAt)}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Next Run</span>\n <span class=\"meta-value\">{{FormatDate(job.nextRunAt)}}</span>\n </div>\n </div>\n <!-- Success Rate Bar -->\n <div class=\"success-section\">\n <div class=\"success-header\">\n <span class=\"success-label\">Success Rate</span>\n <span class=\"success-value\" [style.color]=\"GetSuccessRateColor(job.successRate)\">\n {{FormatPercentage(job.successRate)}}\n </span>\n </div>\n <div class=\"success-bar-track\">\n <div class=\"success-bar-fill\"\n [style.width]=\"(job.successRate * 100) + '%'\"\n [style.background]=\"GetSuccessRateColor(job.successRate)\">\n </div>\n </div>\n <div class=\"run-stats\">\n <span class=\"stat-success\"><i class=\"fa-solid fa-check\"></i> {{job.successCount}}</span>\n <span class=\"stat-failure\"><i class=\"fa-solid fa-xmark\"></i> {{job.failureCount}}</span>\n <span class=\"stat-total\">{{job.totalRuns}} total</span>\n </div>\n </div>\n </div>\n <!-- Delete confirmation overlay -->\n @if (IsDeleteConfirming(job.jobId)) {\n <div class=\"delete-confirm-overlay\" (click)=\"$event.stopPropagation()\">\n <div class=\"delete-confirm-content\">\n <i class=\"fa-solid fa-triangle-exclamation delete-warn-icon\"></i>\n <span class=\"delete-confirm-text\">Delete this scheduled job?</span>\n <div class=\"delete-confirm-actions\">\n <button class=\"delete-confirm-btn\" [disabled]=\"IsDeleting\" (click)=\"ConfirmDelete(job.jobId, $event)\">\n @if (IsDeleting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Deleting...\n } @else {\n Delete\n }\n </button>\n <button class=\"delete-cancel-btn\" (click)=\"CancelDelete($event)\">Cancel</button>\n </div>\n </div>\n </div>\n }\n <!-- Card Footer -->\n <div class=\"job-card-footer\">\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"ToggleJobStatus(job, $event)\">\n <i [class]=\"job.status === 'Active' ? 'fa-solid fa-pause' : 'fa-solid fa-play'\"></i>\n {{job.status === 'Active' ? 'Pause' : 'Resume'}}\n </button>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"OpenEntityRecord(job); $event.stopPropagation()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n Full Details\n </button>\n <button mjButton variant=\"danger\" size=\"sm\" (click)=\"ShowDeleteConfirm(job, $event)\">\n <i class=\"fa-solid fa-trash-can\"></i>\n Delete\n </button>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Slideout Panel -->\n <mj-scheduled-job-slide-panel\n [IsOpen]=\"SlideoutOpen\"\n [ScheduledJobID]=\"SelectedJob?.jobId ?? null\"\n (Close)=\"CloseSlideout()\"\n (Saved)=\"OnSlideoutSaved()\"\n (Deleted)=\"OnSlideoutSaved()\">\n </mj-scheduled-job-slide-panel>\n</div>\n", styles: [".jobs-container {\n display: flex;\n flex-direction: column;\n gap: 20px;\n position: relative;\n}\n\n/* \u2500\u2500 Toolbar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.jobs-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.toolbar-left {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.toolbar-right {\n display: flex;\n gap: 8px;\n align-items: center;\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: 1px solid var(--mj-border-default);\n border-radius: 10px;\n min-width: 240px;\n transition: border-color 0.2s;\n}\n\n.search-box:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.search-box i {\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n}\n\n.search-box input {\n border: none;\n outline: none;\n background: transparent;\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n width: 100%;\n}\n\n.filter-select {\n padding: 8px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 0.85rem;\n color: var(--mj-text-secondary);\n cursor: pointer;\n outline: none;\n transition: border-color 0.2s;\n}\n\n.filter-select:focus {\n border-color: var(--mj-brand-primary);\n}\n\n.result-count {\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.control-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.2s ease;\n}\n\n.control-btn:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.primary-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 20px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 10px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 600;\n transition: all 0.2s ease;\n}\n\n.primary-btn:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-md);\n}\n\n/* \u2500\u2500 Loading & Empty \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.loading-container {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 64px 24px;\n background: var(--mj-bg-surface-card);\n border-radius: 16px;\n border: 2px dashed var(--mj-border-default);\n text-align: center;\n}\n\n.empty-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 20px;\n}\n\n.empty-icon i {\n font-size: 2rem;\n color: var(--mj-text-muted);\n}\n\n.empty-state h3 {\n font-size: 1.1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 8px;\n}\n\n.empty-state p {\n color: var(--mj-text-secondary);\n margin: 0 0 16px;\n font-size: 0.9rem;\n}\n\n/* \u2500\u2500 Job Cards Grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.jobs-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));\n gap: 16px;\n}\n\n.job-card {\n position: relative;\n background: var(--mj-bg-surface-card);\n border-radius: 16px;\n border: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.job-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n border-color: var(--mj-brand-primary);\n}\n\n/* Card Header */\n.job-card-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.job-card-title {\n display: flex;\n align-items: center;\n gap: 10px;\n flex: 1;\n min-width: 0;\n}\n\n.type-icon {\n color: var(--mj-brand-primary);\n font-size: 1rem;\n flex-shrink: 0;\n}\n\n.job-name {\n font-weight: 700;\n color: var(--mj-text-primary);\n font-size: 0.9rem;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: 1.3;\n}\n\n.status-chip {\n font-size: 0.7rem;\n font-weight: 700;\n padding: 3px 10px;\n border-radius: 12px;\n flex-shrink: 0;\n margin-left: 8px;\n}\n\n.status-active { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.status-paused { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n.status-disabled { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.status-pending { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-expired { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n\n/* Card Body */\n.job-card-body {\n padding: 16px 20px;\n flex: 1;\n}\n\n.job-description {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: 1.4;\n}\n\n.job-meta-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.meta-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.meta-label {\n font-size: 0.65rem;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.meta-value {\n font-size: 0.8rem;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.meta-value.mono {\n font-family: 'SFMono-Regular', Consolas, monospace;\n font-size: 0.75rem;\n}\n\n/* Success Rate */\n.success-section {\n padding-top: 12px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.success-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n}\n\n.success-label {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.success-value {\n font-size: 0.85rem;\n font-weight: 800;\n}\n\n.success-bar-track {\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.success-bar-fill {\n height: 100%;\n border-radius: 3px;\n transition: width 0.5s ease;\n}\n\n.run-stats {\n display: flex;\n gap: 12px;\n margin-top: 8px;\n font-size: 0.75rem;\n}\n\n.stat-success { color: var(--mj-status-success); font-weight: 600; }\n.stat-failure { color: var(--mj-status-error); font-weight: 600; }\n.stat-total { color: var(--mj-text-muted); margin-left: auto; }\n\n/* Card Footer */\n.job-card-footer {\n display: flex;\n gap: 8px;\n padding: 12px 20px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n background: var(--mj-bg-surface-sunken);\n}\n\n.action-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.2s;\n}\n\n.action-btn:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n/* \u2500\u2500 Slideout Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.slideout-backdrop {\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 animation: fadeInBackdrop 0.2s ease;\n}\n\n@keyframes fadeInBackdrop {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.slideout-panel {\n position: fixed;\n top: 0;\n right: -100%;\n height: 100vh;\n background: var(--mj-bg-surface-card);\n box-shadow: var(--mj-shadow-lg);\n z-index: 1000;\n transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n overflow-y: auto;\n}\n\n.slideout-panel.open {\n right: 0;\n}\n\n.slideout-resize-handle {\n position: absolute;\n inset: 0;\n background: rgba(255, 255, 255, 0.95);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n border-radius: 16px;\n backdrop-filter: blur(4px);\n}\n\n.slideout-resize-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.slideout-resize-handle:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n/* \u2500\u2500 Delete Confirmation Overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.delete-confirm-overlay {\n position: absolute;\n inset: 0;\n background: rgba(255, 255, 255, 0.95);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n border-radius: 16px;\n backdrop-filter: blur(4px);\n}\n\n.delete-confirm-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 24px;\n text-align: center;\n}\n\n.delete-warn-icon {\n font-size: 1.5rem;\n color: var(--mj-status-error);\n}\n\n.delete-confirm-text {\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.delete-confirm-actions {\n display: flex;\n gap: 8px;\n margin-top: 4px;\n}\n\n.delete-confirm-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 16px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 600;\n transition: background 0.2s;\n}\n\n.delete-confirm-btn:hover:not(:disabled) {\n background: var(--mj-status-error-text);\n}\n\n.delete-confirm-btn:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n\n.delete-cancel-btn {\n padding: 6px 16px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n font-size: 0.8rem;\n font-weight: 500;\n transition: all 0.2s;\n}\n\n.delete-cancel-btn:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n/* \u2500\u2500 Danger Action Button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.action-btn-danger {\n margin-left: auto;\n color: var(--mj-status-error);\n border-color: var(--mj-status-error-border);\n}\n\n.action-btn-danger:hover {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error);\n color: var(--mj-status-error-text);\n}\n\n/* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n@media (max-width: 1024px) {\n .jobs-grid {\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n }\n}\n\n@media (max-width: 768px) {\n .jobs-toolbar {\n flex-direction: column;\n align-items: stretch;\n }\n .toolbar-right {\n justify-content: space-between;\n }\n .jobs-grid {\n grid-template-columns: 1fr;\n }\n .search-box {\n min-width: auto;\n flex: 1;\n }\n}\n"] }]
|
|
563
564
|
}], () => [{ type: i1.SchedulingInstrumentationService }, { type: i0.ChangeDetectorRef }], { initialState: [{
|
|
564
565
|
type: Input
|
|
565
566
|
}], stateChange: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduling-jobs.component.js","sourceRoot":"","sources":["../../../src/Scheduling/components/scheduling-jobs.component.ts","../../../src/Scheduling/components/scheduling-jobs.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';\nimport { Subscription, BehaviorSubject, Subject, combineLatest } from 'rxjs';\nimport { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';\nimport { CompositeKey } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport {\n SchedulingInstrumentationService,\n JobStatistics,\n JobTypeStatistics\n} from '../services/scheduling-instrumentation.service';\n\n@Component({\n standalone: false,\n selector: 'app-scheduling-jobs',\n templateUrl: './scheduling-jobs.component.html',\n styleUrls: ['./scheduling-jobs.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class SchedulingJobsComponent implements OnInit, OnDestroy {\n @Input() initialState: Record<string, unknown> = {};\n @Output() stateChange = new EventEmitter<Record<string, unknown>>();\n\n public Jobs: JobStatistics[] = [];\n public FilteredJobs: JobStatistics[] = [];\n public JobTypes: JobTypeStatistics[] = [];\n public IsLoading = true;\n\n // Slideout state\n public SlideoutOpen = false;\n public SelectedJob: JobStatistics | null = null;\n\n // Delete confirmation state\n public DeleteConfirmJobId: string | null = null;\n public IsDeleting = false;\n\n // Filters\n public SearchTerm = '';\n public StatusFilter = '';\n public TypeFilter = '';\n\n public StatusOptions = ['', 'Active', 'Paused', 'Disabled', 'Pending', 'Expired'];\n public TypeOptions: string[] = [''];\n\n // Settings keys\n private static readonly SEARCH_STATE_KEY = 'Scheduling.JobsSearchState';\n\n private searchSubject = new BehaviorSubject<string>('');\n private statusSubject = new BehaviorSubject<string>('');\n private typeSubject = new BehaviorSubject<string>('');\n private settingsPersistSubject = new Subject<void>();\n private destroy$ = new Subject<void>();\n private subscriptions: Subscription[] = [];\n private settingsLoaded = false;\n\n constructor(\n private schedulingService: SchedulingInstrumentationService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.loadUserSettings();\n this.restoreState();\n this.setupFilters();\n this.setupSettingsPersistence();\n\n this.subscriptions.push(\n this.schedulingService.jobStatistics$.subscribe(jobs => {\n this.Jobs = jobs;\n this.IsLoading = false;\n this.updateTypeOptions();\n this.applyFilters();\n this.cdr.markForCheck();\n }),\n this.schedulingService.jobTypes$.subscribe(types => {\n this.JobTypes = types;\n this.cdr.markForCheck();\n })\n );\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n this.subscriptions.forEach(s => s.unsubscribe());\n }\n\n private loadUserSettings(): void {\n try {\n const stateStr = UserInfoEngine.Instance.GetSetting(SchedulingJobsComponent.SEARCH_STATE_KEY);\n if (stateStr) {\n const state = JSON.parse(stateStr) as Record<string, string>;\n if (state.searchTerm) this.SearchTerm = state.searchTerm;\n if (state.statusFilter) this.StatusFilter = state.statusFilter;\n if (state.typeFilter) this.TypeFilter = state.typeFilter;\n }\n } catch (error) {\n console.warn('[SchedulingJobs] Failed to load user settings:', error);\n } finally {\n this.settingsLoaded = true;\n }\n }\n\n private setupSettingsPersistence(): void {\n this.settingsPersistSubject.pipe(\n debounceTime(500),\n takeUntil(this.destroy$)\n ).subscribe(() => {\n this.persistSearchState();\n });\n }\n\n private persistSearchState(): void {\n if (!this.settingsLoaded) return;\n try {\n const state = {\n searchTerm: this.SearchTerm,\n statusFilter: this.StatusFilter,\n typeFilter: this.TypeFilter\n };\n UserInfoEngine.Instance.SetSettingDebounced(\n SchedulingJobsComponent.SEARCH_STATE_KEY,\n JSON.stringify(state)\n );\n } catch (error) {\n console.warn('[SchedulingJobs] Failed to persist search state:', error);\n }\n }\n\n private restoreState(): void {\n if (this.initialState) {\n if (this.initialState['searchTerm']) this.SearchTerm = this.initialState['searchTerm'] as string;\n if (this.initialState['statusFilter']) this.StatusFilter = this.initialState['statusFilter'] as string;\n if (this.initialState['typeFilter']) this.TypeFilter = this.initialState['typeFilter'] as string;\n }\n }\n\n private setupFilters(): void {\n this.subscriptions.push(\n combineLatest([\n this.searchSubject.pipe(debounceTime(300), distinctUntilChanged()),\n this.statusSubject.pipe(distinctUntilChanged()),\n this.typeSubject.pipe(distinctUntilChanged())\n ]).subscribe(() => {\n this.applyFilters();\n this.emitState();\n this.cdr.markForCheck();\n })\n );\n\n this.searchSubject.next(this.SearchTerm);\n this.statusSubject.next(this.StatusFilter);\n this.typeSubject.next(this.TypeFilter);\n }\n\n public OnSearchChange(term: string): void {\n this.SearchTerm = term;\n this.searchSubject.next(term);\n }\n\n public OnStatusFilterChange(status: string): void {\n this.StatusFilter = status;\n this.statusSubject.next(status);\n }\n\n public OnTypeFilterChange(type: string): void {\n this.TypeFilter = type;\n this.typeSubject.next(type);\n }\n\n public Refresh(): void {\n this.schedulingService.refresh();\n }\n\n public OpenCreateSlideout(): void {\n this.SelectedJob = null;\n this.SlideoutOpen = true;\n this.cdr.markForCheck();\n }\n\n public OpenEditSlideout(job: JobStatistics): void {\n this.SelectedJob = job;\n this.SlideoutOpen = true;\n this.cdr.markForCheck();\n }\n\n public CloseSlideout(): void {\n this.SlideoutOpen = false;\n this.SelectedJob = null;\n this.cdr.markForCheck();\n }\n\n public OnSlideoutSaved(): void {\n this.CloseSlideout();\n this.schedulingService.refresh();\n }\n\n public async ToggleJobStatus(job: JobStatistics, event: MouseEvent): Promise<void> {\n event.stopPropagation();\n const newStatus = job.status === 'Active' ? 'Paused' : 'Active';\n await this.schedulingService.updateJobStatus(job.jobId, newStatus as 'Active' | 'Paused');\n }\n\n public ShowDeleteConfirm(job: JobStatistics, event: MouseEvent): void {\n event.stopPropagation();\n this.DeleteConfirmJobId = job.jobId;\n this.cdr.markForCheck();\n }\n\n public CancelDelete(event: MouseEvent): void {\n event.stopPropagation();\n this.DeleteConfirmJobId = null;\n this.cdr.markForCheck();\n }\n\n public async ConfirmDelete(jobId: string, event: MouseEvent): Promise<void> {\n event.stopPropagation();\n this.IsDeleting = true;\n this.cdr.markForCheck();\n try {\n const result = await this.schedulingService.deleteJob(jobId);\n if (result) {\n this.DeleteConfirmJobId = null;\n }\n } catch (err) {\n console.error('[SchedulingJobs] Delete error:', err);\n } finally {\n this.IsDeleting = false;\n this.cdr.markForCheck();\n }\n }\n\n public IsDeleteConfirming(jobId: string): boolean {\n return this.DeleteConfirmJobId === jobId;\n }\n\n public OpenEntityRecord(job: JobStatistics): void {\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromSingleKeyValuePair('ID', job.jobId);\n SharedService.Instance.OpenEntityRecord('MJ: Scheduled Jobs', compositeKey);\n }\n\n public GetStatusClass(status: string): string {\n switch (status) {\n case 'Active': return 'status-active';\n case 'Paused': return 'status-paused';\n case 'Disabled': return 'status-disabled';\n case 'Pending': return 'status-pending';\n case 'Expired': return 'status-expired';\n default: return '';\n }\n }\n\n public GetSuccessRateColor(rate: number): string {\n if (rate >= 0.9) return '#10b981';\n if (rate >= 0.7) return '#f59e0b';\n return '#ef4444';\n }\n\n public GetTypeIcon(typeName: string): string {\n const lower = typeName.toLowerCase();\n if (lower.includes('agent')) return 'fa-solid fa-robot';\n if (lower.includes('action')) return 'fa-solid fa-bolt';\n return 'fa-solid fa-gear';\n }\n\n public FormatDate(date: Date | undefined): string {\n if (!date) return '-';\n return date.toLocaleString(undefined, {\n month: 'numeric', day: 'numeric', year: '2-digit',\n hour: 'numeric', minute: '2-digit', hour12: true\n });\n }\n\n public FormatPercentage(value: number): string {\n return `${(value * 100).toFixed(1)}%`;\n }\n\n private applyFilters(): void {\n let filtered = [...this.Jobs];\n\n if (this.SearchTerm) {\n const term = this.SearchTerm.toLowerCase();\n filtered = filtered.filter(j =>\n j.jobName.toLowerCase().includes(term) ||\n j.jobType.toLowerCase().includes(term) ||\n (j.description && j.description.toLowerCase().includes(term))\n );\n }\n\n if (this.StatusFilter) {\n filtered = filtered.filter(j => j.status === this.StatusFilter);\n }\n\n if (this.TypeFilter) {\n filtered = filtered.filter(j => j.jobType === this.TypeFilter);\n }\n\n this.FilteredJobs = filtered;\n }\n\n private updateTypeOptions(): void {\n const types = new Set(this.Jobs.map(j => j.jobType));\n this.TypeOptions = ['', ...Array.from(types).sort()];\n }\n\n private emitState(): void {\n this.stateChange.emit({\n searchTerm: this.SearchTerm,\n statusFilter: this.StatusFilter,\n typeFilter: this.TypeFilter\n });\n this.settingsPersistSubject.next();\n }\n}\n","<div class=\"jobs-container\">\n <!-- Toolbar -->\n <div class=\"jobs-toolbar\">\n <div class=\"toolbar-left\">\n <div class=\"search-box\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Search jobs...\"\n [value]=\"SearchTerm\"\n (input)=\"OnSearchChange($any($event.target).value)\" />\n </div>\n <select class=\"filter-select\" [value]=\"StatusFilter\" (change)=\"OnStatusFilterChange($any($event.target).value)\">\n <option value=\"\">All Statuses</option>\n @for (s of StatusOptions.slice(1); track s) {\n <option [value]=\"s\">{{s}}</option>\n }\n </select>\n <select class=\"filter-select\" [value]=\"TypeFilter\" (change)=\"OnTypeFilterChange($any($event.target).value)\">\n <option value=\"\">All Types</option>\n @for (t of TypeOptions.slice(1); track t) {\n <option [value]=\"t\">{{t}}</option>\n }\n </select>\n </div>\n <div class=\"toolbar-right\">\n <span class=\"result-count\">{{FilteredJobs.length}} of {{Jobs.length}} jobs</span>\n <button class=\"control-btn\" (click)=\"Refresh()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Refresh\n </button>\n <button class=\"primary-btn\" (click)=\"OpenCreateSlideout()\">\n <i class=\"fa-solid fa-plus\"></i> New Job\n </button>\n </div>\n </div>\n\n <!-- Loading -->\n @if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading jobs...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Empty State -->\n @if (!IsLoading && FilteredJobs.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-calendar-xmark\"></i>\n </div>\n <h3>No jobs found</h3>\n @if (SearchTerm || StatusFilter || TypeFilter) {\n <p>Try adjusting your filters</p>\n }\n @if (!SearchTerm && !StatusFilter && !TypeFilter) {\n <p>Create your first scheduled job to get started</p>\n }\n @if (!SearchTerm && !StatusFilter && !TypeFilter) {\n <button class=\"primary-btn\" (click)=\"OpenCreateSlideout()\">\n <i class=\"fa-solid fa-plus\"></i> Create Job\n </button>\n }\n </div>\n }\n\n <!-- Job Cards Grid -->\n @if (!IsLoading && FilteredJobs.length > 0) {\n <div class=\"jobs-grid\">\n @for (job of FilteredJobs; track job) {\n <div\n class=\"job-card\"\n (click)=\"OpenEditSlideout(job)\">\n <!-- Card Header -->\n <div class=\"job-card-header\">\n <div class=\"job-card-title\">\n <i [class]=\"GetTypeIcon(job.jobType)\" class=\"type-icon\"></i>\n <span class=\"job-name\">{{job.jobName}}</span>\n </div>\n <span class=\"status-chip\" [ngClass]=\"GetStatusClass(job.status)\">{{job.status}}</span>\n </div>\n <!-- Card Body -->\n <div class=\"job-card-body\">\n @if (job.description) {\n <div class=\"job-description\">{{job.description}}</div>\n }\n <div class=\"job-meta-grid\">\n <div class=\"meta-item\">\n <span class=\"meta-label\">Type</span>\n <span class=\"meta-value\">{{job.jobType}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Schedule</span>\n <span class=\"meta-value mono\">{{job.cronExpression}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Last Run</span>\n <span class=\"meta-value\">{{FormatDate(job.lastRunAt)}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Next Run</span>\n <span class=\"meta-value\">{{FormatDate(job.nextRunAt)}}</span>\n </div>\n </div>\n <!-- Success Rate Bar -->\n <div class=\"success-section\">\n <div class=\"success-header\">\n <span class=\"success-label\">Success Rate</span>\n <span class=\"success-value\" [style.color]=\"GetSuccessRateColor(job.successRate)\">\n {{FormatPercentage(job.successRate)}}\n </span>\n </div>\n <div class=\"success-bar-track\">\n <div class=\"success-bar-fill\"\n [style.width]=\"(job.successRate * 100) + '%'\"\n [style.background]=\"GetSuccessRateColor(job.successRate)\">\n </div>\n </div>\n <div class=\"run-stats\">\n <span class=\"stat-success\"><i class=\"fa-solid fa-check\"></i> {{job.successCount}}</span>\n <span class=\"stat-failure\"><i class=\"fa-solid fa-xmark\"></i> {{job.failureCount}}</span>\n <span class=\"stat-total\">{{job.totalRuns}} total</span>\n </div>\n </div>\n </div>\n <!-- Delete confirmation overlay -->\n @if (IsDeleteConfirming(job.jobId)) {\n <div class=\"delete-confirm-overlay\" (click)=\"$event.stopPropagation()\">\n <div class=\"delete-confirm-content\">\n <i class=\"fa-solid fa-triangle-exclamation delete-warn-icon\"></i>\n <span class=\"delete-confirm-text\">Delete this scheduled job?</span>\n <div class=\"delete-confirm-actions\">\n <button class=\"delete-confirm-btn\" [disabled]=\"IsDeleting\" (click)=\"ConfirmDelete(job.jobId, $event)\">\n @if (IsDeleting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Deleting...\n } @else {\n Delete\n }\n </button>\n <button class=\"delete-cancel-btn\" (click)=\"CancelDelete($event)\">Cancel</button>\n </div>\n </div>\n </div>\n }\n <!-- Card Footer -->\n <div class=\"job-card-footer\">\n <button class=\"action-btn\" (click)=\"ToggleJobStatus(job, $event)\">\n <i [class]=\"job.status === 'Active' ? 'fa-solid fa-pause' : 'fa-solid fa-play'\"></i>\n {{job.status === 'Active' ? 'Pause' : 'Resume'}}\n </button>\n <button class=\"action-btn\" (click)=\"OpenEntityRecord(job); $event.stopPropagation()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n Full Details\n </button>\n <button class=\"action-btn action-btn-danger\" (click)=\"ShowDeleteConfirm(job, $event)\">\n <i class=\"fa-solid fa-trash-can\"></i>\n Delete\n </button>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Slideout Panel -->\n <mj-scheduled-job-slide-panel\n [IsOpen]=\"SlideoutOpen\"\n [ScheduledJobID]=\"SelectedJob?.jobId ?? null\"\n (Close)=\"CloseSlideout()\"\n (Saved)=\"OnSlideoutSaved()\"\n (Deleted)=\"OnSlideoutSaved()\">\n </mj-scheduled-job-slide-panel>\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"scheduling-jobs.component.js","sourceRoot":"","sources":["../../../src/Scheduling/components/scheduling-jobs.component.ts","../../../src/Scheduling/components/scheduling-jobs.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';\nimport { Subscription, BehaviorSubject, Subject, combineLatest } from 'rxjs';\nimport { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';\nimport { CompositeKey } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport {\n SchedulingInstrumentationService,\n JobStatistics,\n JobTypeStatistics\n} from '../services/scheduling-instrumentation.service';\n\n@Component({\n standalone: false,\n selector: 'app-scheduling-jobs',\n templateUrl: './scheduling-jobs.component.html',\n styleUrls: ['./scheduling-jobs.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class SchedulingJobsComponent implements OnInit, OnDestroy {\n @Input() initialState: Record<string, unknown> = {};\n @Output() stateChange = new EventEmitter<Record<string, unknown>>();\n\n public Jobs: JobStatistics[] = [];\n public FilteredJobs: JobStatistics[] = [];\n public JobTypes: JobTypeStatistics[] = [];\n public IsLoading = true;\n\n // Slideout state\n public SlideoutOpen = false;\n public SelectedJob: JobStatistics | null = null;\n\n // Delete confirmation state\n public DeleteConfirmJobId: string | null = null;\n public IsDeleting = false;\n\n // Filters\n public SearchTerm = '';\n public StatusFilter = '';\n public TypeFilter = '';\n\n public StatusOptions = ['', 'Active', 'Paused', 'Disabled', 'Pending', 'Expired'];\n public TypeOptions: string[] = [''];\n\n // Settings keys\n private static readonly SEARCH_STATE_KEY = 'Scheduling.JobsSearchState';\n\n private searchSubject = new BehaviorSubject<string>('');\n private statusSubject = new BehaviorSubject<string>('');\n private typeSubject = new BehaviorSubject<string>('');\n private settingsPersistSubject = new Subject<void>();\n private destroy$ = new Subject<void>();\n private subscriptions: Subscription[] = [];\n private settingsLoaded = false;\n\n constructor(\n private schedulingService: SchedulingInstrumentationService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.loadUserSettings();\n this.restoreState();\n this.setupFilters();\n this.setupSettingsPersistence();\n\n this.subscriptions.push(\n this.schedulingService.jobStatistics$.subscribe(jobs => {\n this.Jobs = jobs;\n this.IsLoading = false;\n this.updateTypeOptions();\n this.applyFilters();\n this.cdr.markForCheck();\n }),\n this.schedulingService.jobTypes$.subscribe(types => {\n this.JobTypes = types;\n this.cdr.markForCheck();\n })\n );\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n this.subscriptions.forEach(s => s.unsubscribe());\n }\n\n private loadUserSettings(): void {\n try {\n const stateStr = UserInfoEngine.Instance.GetSetting(SchedulingJobsComponent.SEARCH_STATE_KEY);\n if (stateStr) {\n const state = JSON.parse(stateStr) as Record<string, string>;\n if (state.searchTerm) this.SearchTerm = state.searchTerm;\n if (state.statusFilter) this.StatusFilter = state.statusFilter;\n if (state.typeFilter) this.TypeFilter = state.typeFilter;\n }\n } catch (error) {\n console.warn('[SchedulingJobs] Failed to load user settings:', error);\n } finally {\n this.settingsLoaded = true;\n }\n }\n\n private setupSettingsPersistence(): void {\n this.settingsPersistSubject.pipe(\n debounceTime(500),\n takeUntil(this.destroy$)\n ).subscribe(() => {\n this.persistSearchState();\n });\n }\n\n private persistSearchState(): void {\n if (!this.settingsLoaded) return;\n try {\n const state = {\n searchTerm: this.SearchTerm,\n statusFilter: this.StatusFilter,\n typeFilter: this.TypeFilter\n };\n UserInfoEngine.Instance.SetSettingDebounced(\n SchedulingJobsComponent.SEARCH_STATE_KEY,\n JSON.stringify(state)\n );\n } catch (error) {\n console.warn('[SchedulingJobs] Failed to persist search state:', error);\n }\n }\n\n private restoreState(): void {\n if (this.initialState) {\n if (this.initialState['searchTerm']) this.SearchTerm = this.initialState['searchTerm'] as string;\n if (this.initialState['statusFilter']) this.StatusFilter = this.initialState['statusFilter'] as string;\n if (this.initialState['typeFilter']) this.TypeFilter = this.initialState['typeFilter'] as string;\n }\n }\n\n private setupFilters(): void {\n this.subscriptions.push(\n combineLatest([\n this.searchSubject.pipe(debounceTime(300), distinctUntilChanged()),\n this.statusSubject.pipe(distinctUntilChanged()),\n this.typeSubject.pipe(distinctUntilChanged())\n ]).subscribe(() => {\n this.applyFilters();\n this.emitState();\n this.cdr.markForCheck();\n })\n );\n\n this.searchSubject.next(this.SearchTerm);\n this.statusSubject.next(this.StatusFilter);\n this.typeSubject.next(this.TypeFilter);\n }\n\n public OnSearchChange(term: string): void {\n this.SearchTerm = term;\n this.searchSubject.next(term);\n }\n\n public OnStatusFilterChange(status: string): void {\n this.StatusFilter = status;\n this.statusSubject.next(status);\n }\n\n public OnTypeFilterChange(type: string): void {\n this.TypeFilter = type;\n this.typeSubject.next(type);\n }\n\n public Refresh(): void {\n this.schedulingService.refresh();\n }\n\n public OpenCreateSlideout(): void {\n this.SelectedJob = null;\n this.SlideoutOpen = true;\n this.cdr.markForCheck();\n }\n\n public OpenEditSlideout(job: JobStatistics): void {\n this.SelectedJob = job;\n this.SlideoutOpen = true;\n this.cdr.markForCheck();\n }\n\n public CloseSlideout(): void {\n this.SlideoutOpen = false;\n this.SelectedJob = null;\n this.cdr.markForCheck();\n }\n\n public OnSlideoutSaved(): void {\n this.CloseSlideout();\n this.schedulingService.refresh();\n }\n\n public async ToggleJobStatus(job: JobStatistics, event: MouseEvent): Promise<void> {\n event.stopPropagation();\n const newStatus = job.status === 'Active' ? 'Paused' : 'Active';\n await this.schedulingService.updateJobStatus(job.jobId, newStatus as 'Active' | 'Paused');\n }\n\n public ShowDeleteConfirm(job: JobStatistics, event: MouseEvent): void {\n event.stopPropagation();\n this.DeleteConfirmJobId = job.jobId;\n this.cdr.markForCheck();\n }\n\n public CancelDelete(event: MouseEvent): void {\n event.stopPropagation();\n this.DeleteConfirmJobId = null;\n this.cdr.markForCheck();\n }\n\n public async ConfirmDelete(jobId: string, event: MouseEvent): Promise<void> {\n event.stopPropagation();\n this.IsDeleting = true;\n this.cdr.markForCheck();\n try {\n const result = await this.schedulingService.deleteJob(jobId);\n if (result) {\n this.DeleteConfirmJobId = null;\n }\n } catch (err) {\n console.error('[SchedulingJobs] Delete error:', err);\n } finally {\n this.IsDeleting = false;\n this.cdr.markForCheck();\n }\n }\n\n public IsDeleteConfirming(jobId: string): boolean {\n return this.DeleteConfirmJobId === jobId;\n }\n\n public OpenEntityRecord(job: JobStatistics): void {\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromSingleKeyValuePair('ID', job.jobId);\n SharedService.Instance.OpenEntityRecord('MJ: Scheduled Jobs', compositeKey);\n }\n\n public GetStatusClass(status: string): string {\n switch (status) {\n case 'Active': return 'status-active';\n case 'Paused': return 'status-paused';\n case 'Disabled': return 'status-disabled';\n case 'Pending': return 'status-pending';\n case 'Expired': return 'status-expired';\n default: return '';\n }\n }\n\n public GetSuccessRateColor(rate: number): string {\n if (rate >= 0.9) return '#10b981';\n if (rate >= 0.7) return '#f59e0b';\n return '#ef4444';\n }\n\n public GetTypeIcon(typeName: string): string {\n const lower = typeName.toLowerCase();\n if (lower.includes('agent')) return 'fa-solid fa-robot';\n if (lower.includes('action')) return 'fa-solid fa-bolt';\n return 'fa-solid fa-gear';\n }\n\n public FormatDate(date: Date | undefined): string {\n if (!date) return '-';\n return date.toLocaleString(undefined, {\n month: 'numeric', day: 'numeric', year: '2-digit',\n hour: 'numeric', minute: '2-digit', hour12: true\n });\n }\n\n public FormatPercentage(value: number): string {\n return `${(value * 100).toFixed(1)}%`;\n }\n\n private applyFilters(): void {\n let filtered = [...this.Jobs];\n\n if (this.SearchTerm) {\n const term = this.SearchTerm.toLowerCase();\n filtered = filtered.filter(j =>\n j.jobName.toLowerCase().includes(term) ||\n j.jobType.toLowerCase().includes(term) ||\n (j.description && j.description.toLowerCase().includes(term))\n );\n }\n\n if (this.StatusFilter) {\n filtered = filtered.filter(j => j.status === this.StatusFilter);\n }\n\n if (this.TypeFilter) {\n filtered = filtered.filter(j => j.jobType === this.TypeFilter);\n }\n\n this.FilteredJobs = filtered;\n }\n\n private updateTypeOptions(): void {\n const types = new Set(this.Jobs.map(j => j.jobType));\n this.TypeOptions = ['', ...Array.from(types).sort()];\n }\n\n private emitState(): void {\n this.stateChange.emit({\n searchTerm: this.SearchTerm,\n statusFilter: this.StatusFilter,\n typeFilter: this.TypeFilter\n });\n this.settingsPersistSubject.next();\n }\n}\n","<div class=\"jobs-container\">\n <!-- Toolbar -->\n <div class=\"jobs-toolbar\">\n <div class=\"toolbar-left\">\n <div class=\"search-box\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Search jobs...\"\n [value]=\"SearchTerm\"\n (input)=\"OnSearchChange($any($event.target).value)\" />\n </div>\n <select class=\"filter-select\" [value]=\"StatusFilter\" (change)=\"OnStatusFilterChange($any($event.target).value)\">\n <option value=\"\">All Statuses</option>\n @for (s of StatusOptions.slice(1); track s) {\n <option [value]=\"s\">{{s}}</option>\n }\n </select>\n <select class=\"filter-select\" [value]=\"TypeFilter\" (change)=\"OnTypeFilterChange($any($event.target).value)\">\n <option value=\"\">All Types</option>\n @for (t of TypeOptions.slice(1); track t) {\n <option [value]=\"t\">{{t}}</option>\n }\n </select>\n </div>\n <div class=\"toolbar-right\">\n <span class=\"result-count\">{{FilteredJobs.length}} of {{Jobs.length}} jobs</span>\n <button mjButton variant=\"secondary\" (click)=\"Refresh()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Refresh\n </button>\n <button class=\"primary-btn\" (click)=\"OpenCreateSlideout()\">\n <i class=\"fa-solid fa-plus\"></i> New Job\n </button>\n </div>\n </div>\n\n <!-- Loading -->\n @if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading jobs...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Empty State -->\n @if (!IsLoading && FilteredJobs.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-calendar-xmark\"></i>\n </div>\n <h3>No jobs found</h3>\n @if (SearchTerm || StatusFilter || TypeFilter) {\n <p>Try adjusting your filters</p>\n }\n @if (!SearchTerm && !StatusFilter && !TypeFilter) {\n <p>Create your first scheduled job to get started</p>\n }\n @if (!SearchTerm && !StatusFilter && !TypeFilter) {\n <button class=\"primary-btn\" (click)=\"OpenCreateSlideout()\">\n <i class=\"fa-solid fa-plus\"></i> Create Job\n </button>\n }\n </div>\n }\n\n <!-- Job Cards Grid -->\n @if (!IsLoading && FilteredJobs.length > 0) {\n <div class=\"jobs-grid\">\n @for (job of FilteredJobs; track job) {\n <div\n class=\"job-card\"\n (click)=\"OpenEditSlideout(job)\">\n <!-- Card Header -->\n <div class=\"job-card-header\">\n <div class=\"job-card-title\">\n <i [class]=\"GetTypeIcon(job.jobType)\" class=\"type-icon\"></i>\n <span class=\"job-name\">{{job.jobName}}</span>\n </div>\n <span class=\"status-chip\" [ngClass]=\"GetStatusClass(job.status)\">{{job.status}}</span>\n </div>\n <!-- Card Body -->\n <div class=\"job-card-body\">\n @if (job.description) {\n <div class=\"job-description\">{{job.description}}</div>\n }\n <div class=\"job-meta-grid\">\n <div class=\"meta-item\">\n <span class=\"meta-label\">Type</span>\n <span class=\"meta-value\">{{job.jobType}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Schedule</span>\n <span class=\"meta-value mono\">{{job.cronExpression}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Last Run</span>\n <span class=\"meta-value\">{{FormatDate(job.lastRunAt)}}</span>\n </div>\n <div class=\"meta-item\">\n <span class=\"meta-label\">Next Run</span>\n <span class=\"meta-value\">{{FormatDate(job.nextRunAt)}}</span>\n </div>\n </div>\n <!-- Success Rate Bar -->\n <div class=\"success-section\">\n <div class=\"success-header\">\n <span class=\"success-label\">Success Rate</span>\n <span class=\"success-value\" [style.color]=\"GetSuccessRateColor(job.successRate)\">\n {{FormatPercentage(job.successRate)}}\n </span>\n </div>\n <div class=\"success-bar-track\">\n <div class=\"success-bar-fill\"\n [style.width]=\"(job.successRate * 100) + '%'\"\n [style.background]=\"GetSuccessRateColor(job.successRate)\">\n </div>\n </div>\n <div class=\"run-stats\">\n <span class=\"stat-success\"><i class=\"fa-solid fa-check\"></i> {{job.successCount}}</span>\n <span class=\"stat-failure\"><i class=\"fa-solid fa-xmark\"></i> {{job.failureCount}}</span>\n <span class=\"stat-total\">{{job.totalRuns}} total</span>\n </div>\n </div>\n </div>\n <!-- Delete confirmation overlay -->\n @if (IsDeleteConfirming(job.jobId)) {\n <div class=\"delete-confirm-overlay\" (click)=\"$event.stopPropagation()\">\n <div class=\"delete-confirm-content\">\n <i class=\"fa-solid fa-triangle-exclamation delete-warn-icon\"></i>\n <span class=\"delete-confirm-text\">Delete this scheduled job?</span>\n <div class=\"delete-confirm-actions\">\n <button class=\"delete-confirm-btn\" [disabled]=\"IsDeleting\" (click)=\"ConfirmDelete(job.jobId, $event)\">\n @if (IsDeleting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Deleting...\n } @else {\n Delete\n }\n </button>\n <button class=\"delete-cancel-btn\" (click)=\"CancelDelete($event)\">Cancel</button>\n </div>\n </div>\n </div>\n }\n <!-- Card Footer -->\n <div class=\"job-card-footer\">\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"ToggleJobStatus(job, $event)\">\n <i [class]=\"job.status === 'Active' ? 'fa-solid fa-pause' : 'fa-solid fa-play'\"></i>\n {{job.status === 'Active' ? 'Pause' : 'Resume'}}\n </button>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"OpenEntityRecord(job); $event.stopPropagation()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n Full Details\n </button>\n <button mjButton variant=\"danger\" size=\"sm\" (click)=\"ShowDeleteConfirm(job, $event)\">\n <i class=\"fa-solid fa-trash-can\"></i>\n Delete\n </button>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Slideout Panel -->\n <mj-scheduled-job-slide-panel\n [IsOpen]=\"SlideoutOpen\"\n [ScheduledJobID]=\"SelectedJob?.jobId ?? null\"\n (Close)=\"CloseSlideout()\"\n (Saved)=\"OnSlideoutSaved()\"\n (Deleted)=\"OnSlideoutSaved()\">\n </mj-scheduled-job-slide-panel>\n</div>\n"]}
|