@rolatech/angular-automation 20.2.6-beta.1 → 20.2.7-beta.2

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.
@@ -1,18 +1,871 @@
1
1
  import * as i0 from '@angular/core';
2
- import { ViewEncapsulation, Component } from '@angular/core';
2
+ import { inject, DestroyRef, signal, computed, Component } from '@angular/core';
3
+ import { AutomationService } from '@rolatech/angular-services';
4
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
+ import { RouterLink, ActivatedRoute, Router } from '@angular/router';
6
+ import { forkJoin, switchMap, of, catchError } from 'rxjs';
7
+ import * as i1 from '@angular/material/button';
8
+ import { MatButtonModule } from '@angular/material/button';
9
+ import * as i1$1 from '@angular/forms';
10
+ import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
11
+ import * as i3 from '@angular/material/select';
12
+ import { MatSelectModule } from '@angular/material/select';
13
+ import * as i2 from '@angular/material/form-field';
14
+ import { MatFormFieldModule } from '@angular/material/form-field';
15
+ import * as i5 from '@angular/material/checkbox';
16
+ import { MatCheckboxModule } from '@angular/material/checkbox';
3
17
 
4
- class AngularAutomation {
5
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: AngularAutomation, deps: [], target: i0.ɵɵFactoryTarget.Component });
6
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.0", type: AngularAutomation, isStandalone: true, selector: "rolatech-angular-automation", ngImport: i0, template: "<p>AngularAutomation works!</p>\n", styles: [""], encapsulation: i0.ViewEncapsulation.None });
18
+ // angular-automation/src/lib/ui/automation-ui.util.ts
19
+ function safeJsonPretty(input) {
20
+ if (!input)
21
+ return '';
22
+ try {
23
+ return JSON.stringify(JSON.parse(input), null, 2);
24
+ }
25
+ catch {
26
+ return input; // already text
27
+ }
7
28
  }
8
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: AngularAutomation, decorators: [{
29
+ function isoToLocal(iso) {
30
+ if (!iso)
31
+ return '—';
32
+ const d = new Date(iso);
33
+ return isNaN(d.getTime()) ? String(iso) : d.toLocaleString();
34
+ }
35
+ function badgeClass(status) {
36
+ switch ((status ?? '').toUpperCase()) {
37
+ case 'SUCCEEDED':
38
+ return 'rt-badge rt-badge-success';
39
+ case 'FAILED':
40
+ return 'rt-badge rt-badge-danger';
41
+ case 'RUNNING':
42
+ return 'rt-badge rt-badge-info';
43
+ case 'QUEUED':
44
+ return 'rt-badge rt-badge-warn';
45
+ case 'CANCEL_REQUESTED':
46
+ case 'CANCELLED':
47
+ return 'rt-badge rt-badge-muted';
48
+ default:
49
+ return 'rt-badge rt-badge-muted';
50
+ }
51
+ }
52
+
53
+ function trackByValue(index, item) {
54
+ const v = (item?.value ?? '').trim();
55
+ return v ? v : `idx:${index}`;
56
+ }
57
+ function trackByStableId(index, item) {
58
+ const id = (item?.id ?? '').trim();
59
+ return id ? id : `idx:${index}`;
60
+ }
61
+ function trackByCode(index, item) {
62
+ const c = (item?.code ?? '').trim();
63
+ return c ? c : `idx:${index}`;
64
+ }
65
+
66
+ class AutomationManageIndex {
67
+ svc = inject(AutomationService);
68
+ destroyRef = inject(DestroyRef);
69
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
70
+ definitions = signal([], ...(ngDevMode ? [{ debugName: "definitions" }] : []));
71
+ schedules = signal([], ...(ngDevMode ? [{ debugName: "schedules" }] : []));
72
+ executions = signal([], ...(ngDevMode ? [{ debugName: "executions" }] : []));
73
+ isoToLocal = isoToLocal;
74
+ badgeClass = badgeClass;
75
+ trackByStableId = trackByStableId;
76
+ constructor() {
77
+ this.load();
78
+ }
79
+ load() {
80
+ this.loading.set(true);
81
+ forkJoin({
82
+ defs: this.svc.listDefinitions({ page: 1, limit: 50 }),
83
+ sch: this.svc.listSchedules({ page: 1, limit: 50 }),
84
+ exe: this.svc.listExecutions({ page: 1, limit: 20, sort: 'queuedAt desc' }),
85
+ })
86
+ .pipe(takeUntilDestroyed(this.destroyRef))
87
+ .subscribe({
88
+ next: ({ defs, sch, exe }) => {
89
+ this.definitions.set(defs.data ?? []);
90
+ this.schedules.set(sch.data ?? []);
91
+ this.executions.set(exe.data ?? []);
92
+ this.loading.set(false);
93
+ },
94
+ error: () => {
95
+ this.definitions.set([]);
96
+ this.schedules.set([]);
97
+ this.executions.set([]);
98
+ this.loading.set(false);
99
+ },
100
+ });
101
+ }
102
+ // --- computed helpers (cards) ---
103
+ defCount = computed(() => this.definitions().length, ...(ngDevMode ? [{ debugName: "defCount" }] : []));
104
+ defEnabledCount = computed(() => this.definitions().filter((d) => !!d.enabled).length, ...(ngDevMode ? [{ debugName: "defEnabledCount" }] : []));
105
+ defLastUpdated = computed(() => {
106
+ const d = [...this.definitions()]
107
+ .filter((x) => x.updatedAt)
108
+ .sort((a, b) => String(b.updatedAt).localeCompare(String(a.updatedAt)))[0];
109
+ return d?.updatedAt ?? '—';
110
+ }, ...(ngDevMode ? [{ debugName: "defLastUpdated" }] : []));
111
+ defHint = computed(() => {
112
+ const d = this.definitions()[0];
113
+ return d ? `Latest: ${d.code} → ${d.handlerKey}` : 'Create a definition to wire a Spring handler bean.';
114
+ }, ...(ngDevMode ? [{ debugName: "defHint" }] : []));
115
+ scheduleCount = computed(() => this.schedules().length, ...(ngDevMode ? [{ debugName: "scheduleCount" }] : []));
116
+ scheduleEnabledCount = computed(() => this.schedules().filter((s) => !!s.enabled).length, ...(ngDevMode ? [{ debugName: "scheduleEnabledCount" }] : []));
117
+ nextRunLabel = computed(() => {
118
+ const s = [...this.schedules()]
119
+ .filter((x) => !!x.nextRunAt)
120
+ .sort((a, b) => String(a.nextRunAt).localeCompare(String(b.nextRunAt)))[0];
121
+ return s?.nextRunAt ? isoToLocal(s.nextRunAt) : '—';
122
+ }, ...(ngDevMode ? [{ debugName: "nextRunLabel" }] : []));
123
+ scheduleHint = computed(() => {
124
+ const s = this.schedules()[0];
125
+ return s ? `Example: ${s.name} (${s.schedule})` : 'Create schedules to run definitions automatically.';
126
+ }, ...(ngDevMode ? [{ debugName: "scheduleHint" }] : []));
127
+ execCount = computed(() => this.executions().length, ...(ngDevMode ? [{ debugName: "execCount" }] : []));
128
+ execRunningCount = computed(() => this.executions().filter((e) => (e.status ?? '').toUpperCase() === 'RUNNING').length, ...(ngDevMode ? [{ debugName: "execRunningCount" }] : []));
129
+ execQueuedCount = computed(() => this.executions().filter((e) => (e.status ?? '').toUpperCase() === 'QUEUED').length, ...(ngDevMode ? [{ debugName: "execQueuedCount" }] : []));
130
+ execFailedCount = computed(() => this.executions().filter((e) => (e.status ?? '').toUpperCase() === 'FAILED').length, ...(ngDevMode ? [{ debugName: "execFailedCount" }] : []));
131
+ execSucceededCount = computed(() => this.executions().filter((e) => (e.status ?? '').toUpperCase() === 'SUCCEEDED').length, ...(ngDevMode ? [{ debugName: "execSucceededCount" }] : []));
132
+ execLastUpdated = computed(() => {
133
+ const e = [...this.executions()]
134
+ .filter((x) => x.queuedAt || x.createdAt)
135
+ .sort((a, b) => String(b.queuedAt ?? b.createdAt ?? '').localeCompare(String(a.queuedAt ?? a.createdAt ?? '')))[0];
136
+ return e?.queuedAt ? isoToLocal(e.queuedAt) : (e?.createdAt ?? '—');
137
+ }, ...(ngDevMode ? [{ debugName: "execLastUpdated" }] : []));
138
+ execHint = computed(() => {
139
+ const e = this.executions()[0];
140
+ return e ? `Latest: ${e.definitionCode ?? e.definitionId} • ${e.status}` : 'Trigger a run from a definition/schedule.';
141
+ }, ...(ngDevMode ? [{ debugName: "execHint" }] : []));
142
+ recentExecutions = computed(() => {
143
+ // already requested 20, keep top 8
144
+ return (this.executions() ?? []).slice(0, 8);
145
+ }, ...(ngDevMode ? [{ debugName: "recentExecutions" }] : []));
146
+ progressPct(e) {
147
+ const total = e.total ?? 0;
148
+ const done = e.processed ?? 0;
149
+ if (!total)
150
+ return 0;
151
+ return Math.max(0, Math.min(100, Math.round((done / total) * 100)));
152
+ }
153
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageIndex, deps: [], target: i0.ɵɵFactoryTarget.Component });
154
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageIndex, isStandalone: true, selector: "rolatech-automation-manage-index", ngImport: i0, template: "<div class=\"p-6 space-y-6 rt-page\">\n <!-- Header -->\n <div class=\"flex items-start justify-between gap-4\">\n <div>\n <div class=\"flex items-center gap-3\">\n <div class=\"h-11 w-11 rounded-2xl rt-soft grid place-items-center text-sm font-semibold\">A</div>\n <div>\n <h1 class=\"text-2xl font-semibold leading-tight\">Automation Center</h1>\n <p class=\"text-sm rt-muted\">Manage definitions, schedules, and executions (run history + logs).</p>\n </div>\n </div>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <button mat-stroked-button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n\n <a mat-flat-button class=\"rt-btn rt-btn-primary\" routerLink=\"executions\"> View executions </a>\n </div>\n </div>\n\n <!-- Top cards -->\n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <!-- Definitions -->\n <a routerLink=\"definitions\" class=\"group rounded-2xl rt-panel p-4 hover:shadow-lg transition\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-medium\">Definitions</div>\n <div class=\"text-xs rt-muted\">Handlers + default input JSON</div>\n </div>\n <div class=\"h-9 w-9 rounded-xl rt-soft grid place-items-center group-hover:shadow-sm transition\">\u2699\uFE0F</div>\n </div>\n\n <div class=\"mt-4 flex items-end justify-between\">\n <div class=\"text-3xl font-semibold\">{{ defCount() }}</div>\n <div class=\"text-xs rt-muted text-right\">\n Enabled: <span class=\"font-medium rt-strong\">{{ defEnabledCount() }}</span>\n </div>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted\">\n Last updated:\n <span class=\"rt-strong font-medium\">{{ defLastUpdated() }}</span>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted line-clamp-2\">{{ defHint() }}</div>\n </a>\n\n <!-- Schedules -->\n <a routerLink=\"schedules\" class=\"group rounded-2xl rt-panel p-4 hover:shadow-lg transition\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-medium\">Schedules</div>\n <div class=\"text-xs rt-muted\">Cron presets + next run times</div>\n </div>\n <div class=\"h-9 w-9 rounded-xl rt-soft grid place-items-center group-hover:shadow-sm transition\">\uD83D\uDDD3\uFE0F</div>\n </div>\n\n <div class=\"mt-4 flex items-end justify-between\">\n <div class=\"text-3xl font-semibold\">{{ scheduleCount() }}</div>\n <div class=\"text-xs rt-muted text-right\">\n Enabled: <span class=\"font-medium rt-strong\">{{ scheduleEnabledCount() }}</span>\n </div>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted\">\n Next run:\n <span class=\"rt-strong font-medium\">{{ nextRunLabel() }}</span>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted line-clamp-2\">{{ scheduleHint() }}</div>\n </a>\n\n <!-- Executions -->\n <a routerLink=\"executions\" class=\"group rounded-2xl rt-panel p-4 hover:shadow-lg transition\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-medium\">Executions</div>\n <div class=\"text-xs rt-muted\">Run history + progress</div>\n </div>\n <div class=\"h-9 w-9 rounded-xl rt-soft grid place-items-center group-hover:shadow-sm transition\">\uD83D\uDE80</div>\n </div>\n\n <div class=\"mt-4 flex items-end justify-between\">\n <div class=\"text-3xl font-semibold\">{{ execCount() }}</div>\n <div class=\"text-xs rt-muted text-right\">\n Running: <span class=\"font-medium rt-strong\">{{ execRunningCount() }}</span>\n </div>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted\">\n Latest:\n <span class=\"rt-strong font-medium\">{{ execLastUpdated() }}</span>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted line-clamp-2\">{{ execHint() }}</div>\n </a>\n </div>\n\n <!-- Recent executions -->\n <div class=\"rounded-2xl rt-panel overflow-hidden\">\n <div class=\"p-4 flex items-center justify-between\">\n <div>\n <div class=\"text-sm font-medium\">Recent executions</div>\n <div class=\"text-xs rt-muted\">Latest runs (best-effort order: newest first)</div>\n </div>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"executions\"> Open list </a>\n </div>\n\n <div class=\"overflow-auto\">\n <table class=\"min-w-[980px] w-full text-sm rt-table\">\n <thead>\n <tr>\n <th class=\"text-left p-3\">Status</th>\n <th class=\"text-left p-3\">Definition</th>\n <th class=\"text-left p-3\">Progress</th>\n <th class=\"text-left p-3\">Queued</th>\n <th class=\"text-left p-3\">Finished</th>\n <th class=\"text-right p-3\">Action</th>\n </tr>\n </thead>\n\n <tbody>\n @if (loading()) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">Loading...</td>\n </tr>\n } @else { @for (e of recentExecutions(); track trackByStableId($index, e)) {\n <tr>\n <td class=\"p-3\">\n <span [class]=\"badgeClass(e.status)\"> {{ e.status }} </span>\n </td>\n\n <td class=\"p-3 font-mono text-xs\">{{ e.definitionCode ?? e.definitionId }}</td>\n\n <td class=\"p-3\">\n <div class=\"text-xs rt-muted\">{{ e.processed }} / {{ e.total }}</div>\n <div class=\"rt-progress mt-1\">\n <div class=\"bar\" [style.width.%]=\"progressPct(e)\"></div>\n </div>\n </td>\n\n <td class=\"p-3 rt-muted\">{{ isoToLocal(e.queuedAt) }}</td>\n <td class=\"p-3 rt-muted\">{{ isoToLocal(e.finishedAt) }}</td>\n\n <td class=\"p-3 text-right\">\n <a class=\"rt-btn rt-btn-ghost\" [routerLink]=\"['executions', e.id]\"> Open </a>\n </td>\n </tr>\n } @if (recentExecutions().length === 0) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">No executions found.</td>\n </tr>\n } }\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Bottom quick actions -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div class=\"rounded-2xl rt-panel p-4\">\n <div class=\"text-sm font-medium\">Quick actions</div>\n <div class=\"text-xs rt-muted mt-1\">Common admin tasks</div>\n\n <div class=\"mt-4 flex flex-wrap gap-2\">\n <a class=\"rt-btn rt-btn-primary\" routerLink=\"definitions/create\"> Create definition </a>\n <a class=\"rt-btn\" routerLink=\"schedules/create\"> Create schedule </a>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"executions\"> View run history </a>\n </div>\n </div>\n\n <div class=\"rounded-2xl rt-panel p-4\">\n <div class=\"text-sm font-medium\">Health</div>\n <div class=\"text-xs rt-muted mt-1\">High-level snapshot</div>\n\n <div class=\"mt-4 grid grid-cols-3 gap-3 text-sm\">\n <div class=\"rounded-xl rt-soft p-3\">\n <div class=\"text-xs rt-muted\">Queued</div>\n <div class=\"text-lg font-semibold\">{{ execQueuedCount() }}</div>\n </div>\n\n <div class=\"rounded-xl rt-soft p-3\">\n <div class=\"text-xs rt-muted\">Failed</div>\n <div class=\"text-lg font-semibold\">{{ execFailedCount() }}</div>\n </div>\n\n <div class=\"rounded-xl rt-soft p-3\">\n <div class=\"text-xs rt-muted\">Succeeded</div>\n <div class=\"text-lg font-semibold\">{{ execSucceededCount() }}</div>\n </div>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted\">\n Tip: open an execution and use <span class=\"font-medium rt-strong\">Logs</span> for real-time troubleshooting.\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] });
155
+ }
156
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageIndex, decorators: [{
157
+ type: Component,
158
+ args: [{ selector: 'rolatech-automation-manage-index', imports: [RouterLink, MatButtonModule], template: "<div class=\"p-6 space-y-6 rt-page\">\n <!-- Header -->\n <div class=\"flex items-start justify-between gap-4\">\n <div>\n <div class=\"flex items-center gap-3\">\n <div class=\"h-11 w-11 rounded-2xl rt-soft grid place-items-center text-sm font-semibold\">A</div>\n <div>\n <h1 class=\"text-2xl font-semibold leading-tight\">Automation Center</h1>\n <p class=\"text-sm rt-muted\">Manage definitions, schedules, and executions (run history + logs).</p>\n </div>\n </div>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <button mat-stroked-button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n\n <a mat-flat-button class=\"rt-btn rt-btn-primary\" routerLink=\"executions\"> View executions </a>\n </div>\n </div>\n\n <!-- Top cards -->\n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <!-- Definitions -->\n <a routerLink=\"definitions\" class=\"group rounded-2xl rt-panel p-4 hover:shadow-lg transition\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-medium\">Definitions</div>\n <div class=\"text-xs rt-muted\">Handlers + default input JSON</div>\n </div>\n <div class=\"h-9 w-9 rounded-xl rt-soft grid place-items-center group-hover:shadow-sm transition\">\u2699\uFE0F</div>\n </div>\n\n <div class=\"mt-4 flex items-end justify-between\">\n <div class=\"text-3xl font-semibold\">{{ defCount() }}</div>\n <div class=\"text-xs rt-muted text-right\">\n Enabled: <span class=\"font-medium rt-strong\">{{ defEnabledCount() }}</span>\n </div>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted\">\n Last updated:\n <span class=\"rt-strong font-medium\">{{ defLastUpdated() }}</span>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted line-clamp-2\">{{ defHint() }}</div>\n </a>\n\n <!-- Schedules -->\n <a routerLink=\"schedules\" class=\"group rounded-2xl rt-panel p-4 hover:shadow-lg transition\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-medium\">Schedules</div>\n <div class=\"text-xs rt-muted\">Cron presets + next run times</div>\n </div>\n <div class=\"h-9 w-9 rounded-xl rt-soft grid place-items-center group-hover:shadow-sm transition\">\uD83D\uDDD3\uFE0F</div>\n </div>\n\n <div class=\"mt-4 flex items-end justify-between\">\n <div class=\"text-3xl font-semibold\">{{ scheduleCount() }}</div>\n <div class=\"text-xs rt-muted text-right\">\n Enabled: <span class=\"font-medium rt-strong\">{{ scheduleEnabledCount() }}</span>\n </div>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted\">\n Next run:\n <span class=\"rt-strong font-medium\">{{ nextRunLabel() }}</span>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted line-clamp-2\">{{ scheduleHint() }}</div>\n </a>\n\n <!-- Executions -->\n <a routerLink=\"executions\" class=\"group rounded-2xl rt-panel p-4 hover:shadow-lg transition\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-medium\">Executions</div>\n <div class=\"text-xs rt-muted\">Run history + progress</div>\n </div>\n <div class=\"h-9 w-9 rounded-xl rt-soft grid place-items-center group-hover:shadow-sm transition\">\uD83D\uDE80</div>\n </div>\n\n <div class=\"mt-4 flex items-end justify-between\">\n <div class=\"text-3xl font-semibold\">{{ execCount() }}</div>\n <div class=\"text-xs rt-muted text-right\">\n Running: <span class=\"font-medium rt-strong\">{{ execRunningCount() }}</span>\n </div>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted\">\n Latest:\n <span class=\"rt-strong font-medium\">{{ execLastUpdated() }}</span>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted line-clamp-2\">{{ execHint() }}</div>\n </a>\n </div>\n\n <!-- Recent executions -->\n <div class=\"rounded-2xl rt-panel overflow-hidden\">\n <div class=\"p-4 flex items-center justify-between\">\n <div>\n <div class=\"text-sm font-medium\">Recent executions</div>\n <div class=\"text-xs rt-muted\">Latest runs (best-effort order: newest first)</div>\n </div>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"executions\"> Open list </a>\n </div>\n\n <div class=\"overflow-auto\">\n <table class=\"min-w-[980px] w-full text-sm rt-table\">\n <thead>\n <tr>\n <th class=\"text-left p-3\">Status</th>\n <th class=\"text-left p-3\">Definition</th>\n <th class=\"text-left p-3\">Progress</th>\n <th class=\"text-left p-3\">Queued</th>\n <th class=\"text-left p-3\">Finished</th>\n <th class=\"text-right p-3\">Action</th>\n </tr>\n </thead>\n\n <tbody>\n @if (loading()) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">Loading...</td>\n </tr>\n } @else { @for (e of recentExecutions(); track trackByStableId($index, e)) {\n <tr>\n <td class=\"p-3\">\n <span [class]=\"badgeClass(e.status)\"> {{ e.status }} </span>\n </td>\n\n <td class=\"p-3 font-mono text-xs\">{{ e.definitionCode ?? e.definitionId }}</td>\n\n <td class=\"p-3\">\n <div class=\"text-xs rt-muted\">{{ e.processed }} / {{ e.total }}</div>\n <div class=\"rt-progress mt-1\">\n <div class=\"bar\" [style.width.%]=\"progressPct(e)\"></div>\n </div>\n </td>\n\n <td class=\"p-3 rt-muted\">{{ isoToLocal(e.queuedAt) }}</td>\n <td class=\"p-3 rt-muted\">{{ isoToLocal(e.finishedAt) }}</td>\n\n <td class=\"p-3 text-right\">\n <a class=\"rt-btn rt-btn-ghost\" [routerLink]=\"['executions', e.id]\"> Open </a>\n </td>\n </tr>\n } @if (recentExecutions().length === 0) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">No executions found.</td>\n </tr>\n } }\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Bottom quick actions -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div class=\"rounded-2xl rt-panel p-4\">\n <div class=\"text-sm font-medium\">Quick actions</div>\n <div class=\"text-xs rt-muted mt-1\">Common admin tasks</div>\n\n <div class=\"mt-4 flex flex-wrap gap-2\">\n <a class=\"rt-btn rt-btn-primary\" routerLink=\"definitions/create\"> Create definition </a>\n <a class=\"rt-btn\" routerLink=\"schedules/create\"> Create schedule </a>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"executions\"> View run history </a>\n </div>\n </div>\n\n <div class=\"rounded-2xl rt-panel p-4\">\n <div class=\"text-sm font-medium\">Health</div>\n <div class=\"text-xs rt-muted mt-1\">High-level snapshot</div>\n\n <div class=\"mt-4 grid grid-cols-3 gap-3 text-sm\">\n <div class=\"rounded-xl rt-soft p-3\">\n <div class=\"text-xs rt-muted\">Queued</div>\n <div class=\"text-lg font-semibold\">{{ execQueuedCount() }}</div>\n </div>\n\n <div class=\"rounded-xl rt-soft p-3\">\n <div class=\"text-xs rt-muted\">Failed</div>\n <div class=\"text-lg font-semibold\">{{ execFailedCount() }}</div>\n </div>\n\n <div class=\"rounded-xl rt-soft p-3\">\n <div class=\"text-xs rt-muted\">Succeeded</div>\n <div class=\"text-lg font-semibold\">{{ execSucceededCount() }}</div>\n </div>\n </div>\n\n <div class=\"mt-3 text-xs rt-muted\">\n Tip: open an execution and use <span class=\"font-medium rt-strong\">Logs</span> for real-time troubleshooting.\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
159
+ }], ctorParameters: () => [] });
160
+
161
+ class AutomationManageDetail {
162
+ route = inject(ActivatedRoute);
163
+ router = inject(Router);
164
+ svc = inject(AutomationService);
165
+ destroyRef = inject(DestroyRef);
166
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
167
+ id() {
168
+ return this.route.snapshot.params['id'];
169
+ }
170
+ constructor() {
171
+ const id = this.id();
172
+ // Try definition -> schedule -> execution (fast + safe)
173
+ this.svc
174
+ .getDefinition(id)
175
+ .pipe(takeUntilDestroyed(this.destroyRef), switchMap((d) => {
176
+ this.router.navigate(['/automations/definitions', d.id]);
177
+ return of(true);
178
+ }), catchError(() => this.svc.getSchedule(id).pipe(switchMap((s) => {
179
+ this.router.navigate(['/automations/schedules', s.id]);
180
+ return of(true);
181
+ }), catchError(() => this.svc.getExecution(id).pipe(switchMap((e) => {
182
+ this.router.navigate(['/automations/executions', e.id]);
183
+ return of(true);
184
+ }), catchError(() => of(false)))))))
185
+ .subscribe((ok) => {
186
+ this.loading.set(false);
187
+ });
188
+ }
189
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageDetail, deps: [], target: i0.ɵɵFactoryTarget.Component });
190
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageDetail, isStandalone: true, selector: "rolatech-automation-manage-detail", ngImport: i0, template: "<div class=\"p-6 max-w-2xl space-y-4 rt-page\">\n <h1 class=\"text-xl font-semibold\">Open Automation</h1>\n\n @if (loading()) {\n <div class=\"text-sm rt-muted\">Detecting resource type\u2026</div>\n } @else {\n <div class=\"rounded-2xl rt-panel p-4 space-y-3\">\n <div class=\"text-sm rt-muted\">\n Could not resolve id <span class=\"font-mono text-xs\">{{ id() }}</span> as a Definition / Schedule / Execution.\n </div>\n <div class=\"flex gap-2\">\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations/definitions\">Definitions</a>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations/schedules\">Schedules</a>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations/executions\">Executions</a>\n </div>\n </div>\n }\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
191
+ }
192
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageDetail, decorators: [{
193
+ type: Component,
194
+ args: [{ selector: 'rolatech-automation-manage-detail', imports: [RouterLink], template: "<div class=\"p-6 max-w-2xl space-y-4 rt-page\">\n <h1 class=\"text-xl font-semibold\">Open Automation</h1>\n\n @if (loading()) {\n <div class=\"text-sm rt-muted\">Detecting resource type\u2026</div>\n } @else {\n <div class=\"rounded-2xl rt-panel p-4 space-y-3\">\n <div class=\"text-sm rt-muted\">\n Could not resolve id <span class=\"font-mono text-xs\">{{ id() }}</span> as a Definition / Schedule / Execution.\n </div>\n <div class=\"flex gap-2\">\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations/definitions\">Definitions</a>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations/schedules\">Schedules</a>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations/executions\">Executions</a>\n </div>\n </div>\n }\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
195
+ }], ctorParameters: () => [] });
196
+
197
+ class AutomationManageDefinitionIndex {
198
+ svc = inject(AutomationService);
199
+ destroyRef = inject(DestroyRef);
200
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
201
+ items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
202
+ q = signal('', ...(ngDevMode ? [{ debugName: "q" }] : []));
203
+ filtered = computed(() => {
204
+ const qq = this.q().trim().toLowerCase();
205
+ if (!qq)
206
+ return this.items();
207
+ return this.items().filter((d) => (d.code + ' ' + d.name).toLowerCase().includes(qq));
208
+ }, ...(ngDevMode ? [{ debugName: "filtered" }] : []));
209
+ constructor() {
210
+ this.load();
211
+ }
212
+ load() {
213
+ this.loading.set(true);
214
+ this.svc
215
+ .listDefinitions()
216
+ .pipe(takeUntilDestroyed(this.destroyRef))
217
+ .subscribe({
218
+ next: (res) => {
219
+ this.items.set(res.data ?? []);
220
+ this.loading.set(false);
221
+ },
222
+ error: () => {
223
+ this.items.set([]);
224
+ this.loading.set(false);
225
+ },
226
+ });
227
+ }
228
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageDefinitionIndex, deps: [], target: i0.ɵɵFactoryTarget.Component });
229
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageDefinitionIndex, isStandalone: true, selector: "rolatech-automation-manage-definition-index", ngImport: i0, template: "<div class=\"p-6 space-y-4 rt-page\">\n <div class=\"flex items-center justify-between gap-3\">\n <div>\n <h1 class=\"text-xl font-semibold\">Definitions</h1>\n <p class=\"text-sm rt-muted\">Create and maintain automation definitions.</p>\n </div>\n\n <div class=\"flex gap-2\">\n <a mat-stroked-button class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations\">Back</a>\n <a mat-flat-button class=\"rt-btn rt-btn-primary\" routerLink=\"create\">Create</a>\n </div>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <input\n class=\"w-full max-w-md rt-input\"\n placeholder=\"Search code/name...\"\n [value]=\"q()\"\n (input)=\"q.set(($any($event.target).value ?? '').toString())\"\n />\n <button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n </div>\n\n <div class=\"rounded-2xl rt-panel overflow-hidden\">\n <div class=\"overflow-auto\">\n <table class=\"min-w-[900px] w-full text-sm rt-table\">\n <thead>\n <tr>\n <th class=\"text-left p-3\">Code</th>\n <th class=\"text-left p-3\">Name</th>\n <th class=\"text-left p-3\">Handler</th>\n <th class=\"text-left p-3\">Enabled</th>\n <th class=\"text-left p-3\">Updated</th>\n <th class=\"text-right p-3\">Action</th>\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">Loading...</td>\n </tr>\n } @else { @for (d of filtered(); track d.id) {\n <tr>\n <td class=\"p-3 font-mono text-xs\">{{ d.code }}</td>\n <td class=\"p-3\">{{ d.name }}</td>\n <td class=\"p-3 font-mono text-xs\">{{ d.handlerKey }}</td>\n <td class=\"p-3\">\n <span class=\"rt-badge\" [class]=\"d.enabled ? 'rt-badge-success' : 'rt-badge-muted'\">\n {{ d.enabled ? 'Enabled' : 'Disabled' }}\n </span>\n </td>\n <td class=\"p-3 rt-muted\">{{ d.updatedAt ?? '\u2014' }}</td>\n <td class=\"p-3 text-right\">\n <a class=\"rt-btn rt-btn-ghost\" [routerLink]=\"[d.id]\">Open</a>\n </td>\n </tr>\n } @if (!filtered().length) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">No definitions.</td>\n </tr>\n } }\n </tbody>\n </table>\n </div>\n </div>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] });
230
+ }
231
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageDefinitionIndex, decorators: [{
232
+ type: Component,
233
+ args: [{ selector: 'rolatech-automation-manage-definition-index', imports: [RouterLink, MatButtonModule], template: "<div class=\"p-6 space-y-4 rt-page\">\n <div class=\"flex items-center justify-between gap-3\">\n <div>\n <h1 class=\"text-xl font-semibold\">Definitions</h1>\n <p class=\"text-sm rt-muted\">Create and maintain automation definitions.</p>\n </div>\n\n <div class=\"flex gap-2\">\n <a mat-stroked-button class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations\">Back</a>\n <a mat-flat-button class=\"rt-btn rt-btn-primary\" routerLink=\"create\">Create</a>\n </div>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <input\n class=\"w-full max-w-md rt-input\"\n placeholder=\"Search code/name...\"\n [value]=\"q()\"\n (input)=\"q.set(($any($event.target).value ?? '').toString())\"\n />\n <button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n </div>\n\n <div class=\"rounded-2xl rt-panel overflow-hidden\">\n <div class=\"overflow-auto\">\n <table class=\"min-w-[900px] w-full text-sm rt-table\">\n <thead>\n <tr>\n <th class=\"text-left p-3\">Code</th>\n <th class=\"text-left p-3\">Name</th>\n <th class=\"text-left p-3\">Handler</th>\n <th class=\"text-left p-3\">Enabled</th>\n <th class=\"text-left p-3\">Updated</th>\n <th class=\"text-right p-3\">Action</th>\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">Loading...</td>\n </tr>\n } @else { @for (d of filtered(); track d.id) {\n <tr>\n <td class=\"p-3 font-mono text-xs\">{{ d.code }}</td>\n <td class=\"p-3\">{{ d.name }}</td>\n <td class=\"p-3 font-mono text-xs\">{{ d.handlerKey }}</td>\n <td class=\"p-3\">\n <span class=\"rt-badge\" [class]=\"d.enabled ? 'rt-badge-success' : 'rt-badge-muted'\">\n {{ d.enabled ? 'Enabled' : 'Disabled' }}\n </span>\n </td>\n <td class=\"p-3 rt-muted\">{{ d.updatedAt ?? '\u2014' }}</td>\n <td class=\"p-3 text-right\">\n <a class=\"rt-btn rt-btn-ghost\" [routerLink]=\"[d.id]\">Open</a>\n </td>\n </tr>\n } @if (!filtered().length) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">No definitions.</td>\n </tr>\n } }\n </tbody>\n </table>\n </div>\n </div>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
234
+ }], ctorParameters: () => [] });
235
+
236
+ class AutomationManageDefinitionDetail {
237
+ svc = inject(AutomationService);
238
+ route = inject(ActivatedRoute);
239
+ fb = inject(FormBuilder);
240
+ destroyRef = inject(DestroyRef);
241
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
242
+ saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : []));
243
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
244
+ item = signal(null, ...(ngDevMode ? [{ debugName: "item" }] : []));
245
+ prettyDefaultJson = signal('', ...(ngDevMode ? [{ debugName: "prettyDefaultJson" }] : []));
246
+ form = this.fb.group({
247
+ name: ['', [Validators.required, Validators.maxLength(200)]],
248
+ description: [''],
249
+ handlerKey: ['', [Validators.required, Validators.maxLength(200)]],
250
+ defaultInputJson: [''],
251
+ enabled: [true],
252
+ });
253
+ constructor() {
254
+ const id = this.route.snapshot.params['id'];
255
+ this.load(id);
256
+ }
257
+ load(id) {
258
+ this.loading.set(true);
259
+ this.svc
260
+ .getDefinition(id)
261
+ .pipe(takeUntilDestroyed(this.destroyRef))
262
+ .subscribe({
263
+ next: (res) => {
264
+ this.item.set(res.data);
265
+ this.form.patchValue({
266
+ name: res.data.name,
267
+ description: res.data.description ?? '',
268
+ handlerKey: res.data.handlerKey,
269
+ defaultInputJson: res.data.defaultInputJson ?? '',
270
+ enabled: res.data.enabled,
271
+ });
272
+ this.prettyDefaultJson.set(safeJsonPretty(res.data.defaultInputJson));
273
+ this.loading.set(false);
274
+ },
275
+ error: (e) => {
276
+ this.error.set(String(e?.error?.message ?? e?.message ?? e));
277
+ this.loading.set(false);
278
+ },
279
+ });
280
+ }
281
+ save() {
282
+ const d = this.item();
283
+ if (!d || this.form.invalid)
284
+ return;
285
+ const req = {
286
+ name: this.form.value.name ?? d.name,
287
+ description: this.form.value.description ?? null,
288
+ handlerKey: this.form.value.handlerKey ?? d.handlerKey,
289
+ defaultInputJson: this.form.value.defaultInputJson ?? null,
290
+ enabled: !!this.form.value.enabled,
291
+ };
292
+ this.saving.set(true);
293
+ this.error.set(null);
294
+ this.svc
295
+ .updateDefinition(d.id, req)
296
+ .pipe(takeUntilDestroyed(this.destroyRef))
297
+ .subscribe({
298
+ next: (updated) => {
299
+ this.item.set(updated);
300
+ this.prettyDefaultJson.set(safeJsonPretty(updated.defaultInputJson));
301
+ this.saving.set(false);
302
+ },
303
+ error: (e) => {
304
+ this.saving.set(false);
305
+ this.error.set(String(e?.error?.message ?? e?.message ?? e));
306
+ },
307
+ });
308
+ }
309
+ disable() {
310
+ const d = this.item();
311
+ if (!d)
312
+ return;
313
+ this.saving.set(true);
314
+ this.error.set(null);
315
+ this.svc
316
+ .deleteDefinition(d.id)
317
+ .pipe(takeUntilDestroyed(this.destroyRef))
318
+ .subscribe({
319
+ next: () => {
320
+ // reload
321
+ this.load(d.id);
322
+ this.saving.set(false);
323
+ },
324
+ error: (e) => {
325
+ this.saving.set(false);
326
+ this.error.set(String(e?.error?.message ?? e?.message ?? e));
327
+ },
328
+ });
329
+ }
330
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageDefinitionDetail, deps: [], target: i0.ɵɵFactoryTarget.Component });
331
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageDefinitionDetail, isStandalone: true, selector: "rolatech-automation-manage-definition-detail", ngImport: i0, template: "<div class=\"p-6 max-w-4xl space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Definition</h1>\n <p class=\"text-sm rt-muted\">{{ item()?.code ?? '\u2014' }}</p>\n </div>\n\n <div class=\"flex gap-2\">\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n <button class=\"rt-btn rt-btn-danger\" (click)=\"disable()\" [disabled]=\"saving() || !item()\">Disable</button>\n </div>\n </div>\n\n @if (loading()) {\n <div class=\"text-sm rt-muted\">Loading...</div>\n } @else {\n <form class=\"rounded-2xl rt-panel p-4 space-y-4\" [formGroup]=\"form\" (ngSubmit)=\"save()\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <label class=\"space-y-1\">\n <div class=\"text-sm font-medium\">Code</div>\n <input class=\"w-full rt-input font-mono text-sm\" [value]=\"item()?.code\" disabled />\n </label>\n <label class=\"space-y-1\">\n <div class=\"text-sm font-medium\">Name</div>\n <input class=\"w-full rt-input\" formControlName=\"name\" />\n </label>\n </div>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Handler Key</div>\n <input class=\"w-full rt-input font-mono text-sm\" formControlName=\"handlerKey\" />\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Description</div>\n <textarea class=\"w-full rt-input min-h-[80px]\" formControlName=\"description\"></textarea>\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Default Input JSON</div>\n <textarea class=\"w-full rt-input font-mono text-xs min-h-[160px]\" formControlName=\"defaultInputJson\"></textarea>\n </label>\n\n <div class=\"flex items-center justify-between\">\n <label class=\"flex items-center gap-2 text-sm\">\n <input type=\"checkbox\" class=\"rounded\" formControlName=\"enabled\" />\n Enabled\n </label>\n\n <button class=\"rt-btn rt-btn-primary\" [disabled]=\"form.invalid || saving()\">{{ saving() ? 'Saving\u2026' : 'Save' }}</button>\n </div>\n\n @if (error()) {\n <div class=\"text-sm rt-alert-danger\">{{ error() }}</div>\n }\n </form>\n\n <div class=\"rounded-2xl rt-panel p-4\">\n <div class=\"text-sm font-medium mb-2\">Preview: Default Input JSON</div>\n <pre class=\"text-xs rt-soft rounded-xl p-3 overflow-auto\">{{ prettyDefaultJson() }}</pre>\n </div>\n }\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
332
+ }
333
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageDefinitionDetail, decorators: [{
334
+ type: Component,
335
+ args: [{ selector: 'rolatech-automation-manage-definition-detail', imports: [RouterLink, ReactiveFormsModule], template: "<div class=\"p-6 max-w-4xl space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Definition</h1>\n <p class=\"text-sm rt-muted\">{{ item()?.code ?? '\u2014' }}</p>\n </div>\n\n <div class=\"flex gap-2\">\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n <button class=\"rt-btn rt-btn-danger\" (click)=\"disable()\" [disabled]=\"saving() || !item()\">Disable</button>\n </div>\n </div>\n\n @if (loading()) {\n <div class=\"text-sm rt-muted\">Loading...</div>\n } @else {\n <form class=\"rounded-2xl rt-panel p-4 space-y-4\" [formGroup]=\"form\" (ngSubmit)=\"save()\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <label class=\"space-y-1\">\n <div class=\"text-sm font-medium\">Code</div>\n <input class=\"w-full rt-input font-mono text-sm\" [value]=\"item()?.code\" disabled />\n </label>\n <label class=\"space-y-1\">\n <div class=\"text-sm font-medium\">Name</div>\n <input class=\"w-full rt-input\" formControlName=\"name\" />\n </label>\n </div>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Handler Key</div>\n <input class=\"w-full rt-input font-mono text-sm\" formControlName=\"handlerKey\" />\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Description</div>\n <textarea class=\"w-full rt-input min-h-[80px]\" formControlName=\"description\"></textarea>\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Default Input JSON</div>\n <textarea class=\"w-full rt-input font-mono text-xs min-h-[160px]\" formControlName=\"defaultInputJson\"></textarea>\n </label>\n\n <div class=\"flex items-center justify-between\">\n <label class=\"flex items-center gap-2 text-sm\">\n <input type=\"checkbox\" class=\"rounded\" formControlName=\"enabled\" />\n Enabled\n </label>\n\n <button class=\"rt-btn rt-btn-primary\" [disabled]=\"form.invalid || saving()\">{{ saving() ? 'Saving\u2026' : 'Save' }}</button>\n </div>\n\n @if (error()) {\n <div class=\"text-sm rt-alert-danger\">{{ error() }}</div>\n }\n </form>\n\n <div class=\"rounded-2xl rt-panel p-4\">\n <div class=\"text-sm font-medium mb-2\">Preview: Default Input JSON</div>\n <pre class=\"text-xs rt-soft rounded-xl p-3 overflow-auto\">{{ prettyDefaultJson() }}</pre>\n </div>\n }\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
336
+ }], ctorParameters: () => [] });
337
+
338
+ class AutomationManageExecutionIndex {
339
+ svc = inject(AutomationService);
340
+ destroyRef = inject(DestroyRef);
341
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
342
+ items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
343
+ badgeClass = badgeClass;
344
+ isoToLocal = isoToLocal;
345
+ constructor() {
346
+ this.load();
347
+ }
348
+ progressPct(e) {
349
+ const total = e.total ?? 0;
350
+ const done = e.processed ?? 0;
351
+ if (!total)
352
+ return 0;
353
+ return Math.max(0, Math.min(100, Math.round((done / total) * 100)));
354
+ }
355
+ load() {
356
+ this.loading.set(true);
357
+ this.svc
358
+ .listExecutions()
359
+ .pipe(takeUntilDestroyed(this.destroyRef))
360
+ .subscribe({
361
+ next: (res) => {
362
+ this.items.set(res.data ?? []);
363
+ this.loading.set(false);
364
+ },
365
+ error: () => {
366
+ this.items.set([]);
367
+ this.loading.set(false);
368
+ },
369
+ });
370
+ }
371
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageExecutionIndex, deps: [], target: i0.ɵɵFactoryTarget.Component });
372
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageExecutionIndex, isStandalone: true, selector: "rolatech-automation-manage-execution-index", ngImport: i0, template: "<div class=\"p-6 space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Executions</h1>\n <p class=\"text-sm rt-muted\">Review job runs, progress and errors.</p>\n </div>\n <div class=\"flex gap-2\">\n <a mat-stroked-button class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations\">Back</a>\n <button mat-stroked-button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n </div>\n </div>\n\n <div class=\"rounded-2xl rt-panel overflow-hidden\">\n <div class=\"overflow-auto\">\n <table class=\"min-w-[1000px] w-full text-sm rt-table\">\n <thead>\n <tr>\n <th class=\"text-left p-3\">Status</th>\n <th class=\"text-left p-3\">Definition</th>\n <th class=\"text-left p-3\">Progress</th>\n <th class=\"text-left p-3\">Queued</th>\n <th class=\"text-left p-3\">Finished</th>\n <th class=\"text-right p-3\">Action</th>\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">Loading...</td>\n </tr>\n } @else { @for (e of items(); track e.id) {\n <tr>\n <td class=\"p-3\">\n <span [class]=\"badgeClass(e.status)\"> {{ e.status }} </span>\n </td>\n <td class=\"p-3 font-mono text-xs\">{{ e.definitionCode ?? e.definitionId }}</td>\n <td class=\"p-3\">\n <div class=\"text-xs rt-muted\">{{ e.processed }} / {{ e.total }}</div>\n <div class=\"rt-progress mt-1\">\n <div class=\"bar\" [style.width.%]=\"progressPct(e)\"></div>\n </div>\n </td>\n <td class=\"p-3 rt-muted\">{{ isoToLocal(e.queuedAt) }}</td>\n <td class=\"p-3 rt-muted\">{{ isoToLocal(e.finishedAt) }}</td>\n <td class=\"p-3 text-right\">\n <a class=\"rt-btn rt-btn-ghost\" [routerLink]=\"[e.id]\">Open</a>\n </td>\n </tr>\n } @if (!items().length) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">No executions.</td>\n </tr>\n } }\n </tbody>\n </table>\n </div>\n </div>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] });
373
+ }
374
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageExecutionIndex, decorators: [{
9
375
  type: Component,
10
- args: [{ selector: 'rolatech-angular-automation', imports: [], encapsulation: ViewEncapsulation.None, template: "<p>AngularAutomation works!</p>\n" }]
376
+ args: [{ selector: 'rolatech-automation-manage-execution-index', imports: [RouterLink, MatButtonModule], template: "<div class=\"p-6 space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Executions</h1>\n <p class=\"text-sm rt-muted\">Review job runs, progress and errors.</p>\n </div>\n <div class=\"flex gap-2\">\n <a mat-stroked-button class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations\">Back</a>\n <button mat-stroked-button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n </div>\n </div>\n\n <div class=\"rounded-2xl rt-panel overflow-hidden\">\n <div class=\"overflow-auto\">\n <table class=\"min-w-[1000px] w-full text-sm rt-table\">\n <thead>\n <tr>\n <th class=\"text-left p-3\">Status</th>\n <th class=\"text-left p-3\">Definition</th>\n <th class=\"text-left p-3\">Progress</th>\n <th class=\"text-left p-3\">Queued</th>\n <th class=\"text-left p-3\">Finished</th>\n <th class=\"text-right p-3\">Action</th>\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">Loading...</td>\n </tr>\n } @else { @for (e of items(); track e.id) {\n <tr>\n <td class=\"p-3\">\n <span [class]=\"badgeClass(e.status)\"> {{ e.status }} </span>\n </td>\n <td class=\"p-3 font-mono text-xs\">{{ e.definitionCode ?? e.definitionId }}</td>\n <td class=\"p-3\">\n <div class=\"text-xs rt-muted\">{{ e.processed }} / {{ e.total }}</div>\n <div class=\"rt-progress mt-1\">\n <div class=\"bar\" [style.width.%]=\"progressPct(e)\"></div>\n </div>\n </td>\n <td class=\"p-3 rt-muted\">{{ isoToLocal(e.queuedAt) }}</td>\n <td class=\"p-3 rt-muted\">{{ isoToLocal(e.finishedAt) }}</td>\n <td class=\"p-3 text-right\">\n <a class=\"rt-btn rt-btn-ghost\" [routerLink]=\"[e.id]\">Open</a>\n </td>\n </tr>\n } @if (!items().length) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">No executions.</td>\n </tr>\n } }\n </tbody>\n </table>\n </div>\n </div>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
377
+ }], ctorParameters: () => [] });
378
+
379
+ class AutomationManageExecutionDetail {
380
+ svc = inject(AutomationService);
381
+ route = inject(ActivatedRoute);
382
+ destroyRef = inject(DestroyRef);
383
+ badgeClass = badgeClass;
384
+ isoToLocal = isoToLocal;
385
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
386
+ saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : []));
387
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
388
+ item = signal(null, ...(ngDevMode ? [{ debugName: "item" }] : []));
389
+ inputPretty = signal('', ...(ngDevMode ? [{ debugName: "inputPretty" }] : []));
390
+ constructor() {
391
+ this.load();
392
+ }
393
+ id() {
394
+ return this.route.snapshot.params['id'];
395
+ }
396
+ canCancel() {
397
+ const s = (this.item()?.status ?? '').toUpperCase();
398
+ return s === 'QUEUED' || s === 'RUNNING';
399
+ }
400
+ progressPct() {
401
+ const e = this.item();
402
+ const total = e?.total ?? 0;
403
+ const done = e?.processed ?? 0;
404
+ if (!total)
405
+ return 0;
406
+ return Math.max(0, Math.min(100, Math.round((done / total) * 100)));
407
+ }
408
+ load() {
409
+ this.loading.set(true);
410
+ this.error.set(null);
411
+ this.svc
412
+ .getExecution(this.id())
413
+ .pipe(takeUntilDestroyed(this.destroyRef))
414
+ .subscribe({
415
+ next: (e) => {
416
+ this.item.set(e.data);
417
+ this.inputPretty.set(safeJsonPretty(e.data.inputJson));
418
+ this.loading.set(false);
419
+ },
420
+ error: (err) => {
421
+ this.error.set(String(err?.error?.message ?? err?.message ?? err));
422
+ this.loading.set(false);
423
+ },
424
+ });
425
+ }
426
+ cancel() {
427
+ if (!this.canCancel())
428
+ return;
429
+ this.saving.set(true);
430
+ this.error.set(null);
431
+ this.svc
432
+ .cancelExecution(this.id())
433
+ .pipe(takeUntilDestroyed(this.destroyRef))
434
+ .subscribe({
435
+ next: () => {
436
+ this.saving.set(false);
437
+ this.load();
438
+ },
439
+ error: (err) => {
440
+ this.saving.set(false);
441
+ this.error.set(String(err?.error?.message ?? err?.message ?? err));
442
+ },
443
+ });
444
+ }
445
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageExecutionDetail, deps: [], target: i0.ɵɵFactoryTarget.Component });
446
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageExecutionDetail, isStandalone: true, selector: "rolatech-automation-manage-execution-detail", ngImport: i0, template: "<div class=\"p-6 max-w-5xl space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Execution</h1>\n <div class=\"text-sm rt-muted font-mono\">{{ item()?.id ?? '\u2014' }}</div>\n </div>\n <div class=\"flex gap-2\">\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n <a class=\"rt-btn rt-btn-ghost\" [routerLink]=\"['log']\">Logs</a>\n <button class=\"rt-btn rt-btn-danger\" (click)=\"cancel()\" [disabled]=\"saving() || !canCancel()\">Cancel</button>\n </div>\n </div>\n\n @if (loading()) {\n <div class=\"text-sm rt-muted\">Loading...</div>\n } @else {\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-4\">\n <div class=\"lg:col-span-2 rounded-2xl rt-panel p-4 space-y-4\">\n <div class=\"flex items-center justify-between\">\n <span [class]=\"badgeClass(item()?.status)\">{{ item()?.status }}</span>\n <button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n </div>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-3 text-sm\">\n <div>\n <div class=\"text-xs rt-muted\">Definition</div>\n <div class=\"font-mono text-xs\">{{ item()?.definitionCode ?? item()?.definitionId }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Schedule</div>\n <div class=\"font-mono text-xs\">{{ item()?.scheduleId ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Queued</div>\n <div>{{ isoToLocal(item()?.queuedAt) }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Started</div>\n <div>{{ isoToLocal(item()?.startedAt) }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Finished</div>\n <div>{{ isoToLocal(item()?.finishedAt) }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Idempotency</div>\n <div class=\"font-mono text-xs\">{{ item()?.idempotencyKey ?? '\u2014' }}</div>\n </div>\n </div>\n\n <div>\n <div class=\"text-xs rt-muted mb-1\">Progress</div>\n <div class=\"text-sm\">{{ item()?.processed ?? 0 }} / {{ item()?.total ?? 0 }}</div>\n <div class=\"rt-progress mt-1\">\n <div class=\"bar\" [style.width.%]=\"progressPct()\"></div>\n </div>\n </div>\n\n @if (item()?.errorMessage) {\n <div class=\"text-sm rt-alert-danger whitespace-pre-wrap\">{{ item()?.errorMessage }}</div>\n }\n </div>\n\n <div class=\"rounded-2xl rt-panel p-4 space-y-3\">\n <div class=\"text-sm font-medium\">Input JSON</div>\n <pre class=\"text-xs rt-soft rounded-xl p-3 overflow-auto\">{{ inputPretty() }}</pre>\n @if (error()) {\n <div class=\"text-sm rt-alert-danger\">{{ error() }}</div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
447
+ }
448
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageExecutionDetail, decorators: [{
449
+ type: Component,
450
+ args: [{ selector: 'rolatech-automation-manage-execution-detail', imports: [RouterLink], template: "<div class=\"p-6 max-w-5xl space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Execution</h1>\n <div class=\"text-sm rt-muted font-mono\">{{ item()?.id ?? '\u2014' }}</div>\n </div>\n <div class=\"flex gap-2\">\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n <a class=\"rt-btn rt-btn-ghost\" [routerLink]=\"['log']\">Logs</a>\n <button class=\"rt-btn rt-btn-danger\" (click)=\"cancel()\" [disabled]=\"saving() || !canCancel()\">Cancel</button>\n </div>\n </div>\n\n @if (loading()) {\n <div class=\"text-sm rt-muted\">Loading...</div>\n } @else {\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-4\">\n <div class=\"lg:col-span-2 rounded-2xl rt-panel p-4 space-y-4\">\n <div class=\"flex items-center justify-between\">\n <span [class]=\"badgeClass(item()?.status)\">{{ item()?.status }}</span>\n <button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n </div>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-3 text-sm\">\n <div>\n <div class=\"text-xs rt-muted\">Definition</div>\n <div class=\"font-mono text-xs\">{{ item()?.definitionCode ?? item()?.definitionId }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Schedule</div>\n <div class=\"font-mono text-xs\">{{ item()?.scheduleId ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Queued</div>\n <div>{{ isoToLocal(item()?.queuedAt) }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Started</div>\n <div>{{ isoToLocal(item()?.startedAt) }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Finished</div>\n <div>{{ isoToLocal(item()?.finishedAt) }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Idempotency</div>\n <div class=\"font-mono text-xs\">{{ item()?.idempotencyKey ?? '\u2014' }}</div>\n </div>\n </div>\n\n <div>\n <div class=\"text-xs rt-muted mb-1\">Progress</div>\n <div class=\"text-sm\">{{ item()?.processed ?? 0 }} / {{ item()?.total ?? 0 }}</div>\n <div class=\"rt-progress mt-1\">\n <div class=\"bar\" [style.width.%]=\"progressPct()\"></div>\n </div>\n </div>\n\n @if (item()?.errorMessage) {\n <div class=\"text-sm rt-alert-danger whitespace-pre-wrap\">{{ item()?.errorMessage }}</div>\n }\n </div>\n\n <div class=\"rounded-2xl rt-panel p-4 space-y-3\">\n <div class=\"text-sm font-medium\">Input JSON</div>\n <pre class=\"text-xs rt-soft rounded-xl p-3 overflow-auto\">{{ inputPretty() }}</pre>\n @if (error()) {\n <div class=\"text-sm rt-alert-danger\">{{ error() }}</div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
451
+ }], ctorParameters: () => [] });
452
+
453
+ class AutomationManageExecutionLog {
454
+ svc = inject(AutomationService);
455
+ route = inject(ActivatedRoute);
456
+ destroyRef = inject(DestroyRef);
457
+ isoToLocal = isoToLocal;
458
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
459
+ logs = signal([], ...(ngDevMode ? [{ debugName: "logs" }] : []));
460
+ id() {
461
+ return this.route.snapshot.params['id'];
462
+ }
463
+ constructor() {
464
+ this.load();
465
+ }
466
+ levelClass(level) {
467
+ switch ((level ?? '').toUpperCase()) {
468
+ case 'ERROR':
469
+ return 'rt-badge rt-badge-danger';
470
+ case 'WARN':
471
+ return 'rt-badge rt-badge-warn';
472
+ case 'DEBUG':
473
+ return 'rt-badge rt-badge-muted';
474
+ default:
475
+ return 'rt-badge rt-badge-info';
476
+ }
477
+ }
478
+ load() {
479
+ this.loading.set(true);
480
+ this.svc
481
+ .listExecutionLogs(this.id(), { limit: 200 })
482
+ .pipe(takeUntilDestroyed(this.destroyRef))
483
+ .subscribe({
484
+ next: (res) => {
485
+ this.logs.set(res.data ?? []);
486
+ this.loading.set(false);
487
+ },
488
+ error: () => {
489
+ this.logs.set([]);
490
+ this.loading.set(false);
491
+ },
492
+ });
493
+ }
494
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageExecutionLog, deps: [], target: i0.ɵɵFactoryTarget.Component });
495
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageExecutionLog, isStandalone: true, selector: "rolatech-automation-manage-execution-log", ngImport: i0, template: "<div class=\"p-6 space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Execution Logs</h1>\n <div class=\"text-sm rt-muted font-mono\">{{ id() }}</div>\n </div>\n <div class=\"flex gap-2\">\n <a mat-stroked-button class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n <button mat-stroked-button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n </div>\n </div>\n\n <div class=\"rounded-2xl rt-panel overflow-hidden\">\n @if (loading()) {\n <div class=\"p-4 text-sm rt-muted\">Loading...</div>\n } @else {\n <div class=\"divide-y divide-[color:var(--rt-outline,rgba(0,0,0,0.08))]\">\n @for (l of logs(); track l.id) {\n <div class=\"p-4\">\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-2\">\n <span [class]=\"levelClass(l.level)\"> {{ l.level }} </span>\n <span class=\"text-xs rt-muted\">{{ isoToLocal(l.createdAt) }}</span>\n </div>\n <span class=\"text-xs rt-quiet font-mono\">{{ l.id }}</span>\n </div>\n <pre class=\"mt-2 text-xs rt-soft rounded-xl p-3 overflow-auto whitespace-pre-wrap\">{{ l.message }}</pre>\n </div>\n } @if (!logs().length) {\n <div class=\"p-4 text-sm rt-muted\">No logs.</div>\n }\n </div>\n }\n </div>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] });
496
+ }
497
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageExecutionLog, decorators: [{
498
+ type: Component,
499
+ args: [{ selector: 'rolatech-automation-manage-execution-log', imports: [RouterLink, MatButtonModule], template: "<div class=\"p-6 space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Execution Logs</h1>\n <div class=\"text-sm rt-muted font-mono\">{{ id() }}</div>\n </div>\n <div class=\"flex gap-2\">\n <a mat-stroked-button class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n <button mat-stroked-button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n </div>\n </div>\n\n <div class=\"rounded-2xl rt-panel overflow-hidden\">\n @if (loading()) {\n <div class=\"p-4 text-sm rt-muted\">Loading...</div>\n } @else {\n <div class=\"divide-y divide-[color:var(--rt-outline,rgba(0,0,0,0.08))]\">\n @for (l of logs(); track l.id) {\n <div class=\"p-4\">\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-2\">\n <span [class]=\"levelClass(l.level)\"> {{ l.level }} </span>\n <span class=\"text-xs rt-muted\">{{ isoToLocal(l.createdAt) }}</span>\n </div>\n <span class=\"text-xs rt-quiet font-mono\">{{ l.id }}</span>\n </div>\n <pre class=\"mt-2 text-xs rt-soft rounded-xl p-3 overflow-auto whitespace-pre-wrap\">{{ l.message }}</pre>\n </div>\n } @if (!logs().length) {\n <div class=\"p-4 text-sm rt-muted\">No logs.</div>\n }\n </div>\n }\n </div>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
500
+ }], ctorParameters: () => [] });
501
+
502
+ class AutomationManageScheduleIndex {
503
+ svc = inject(AutomationService);
504
+ destroyRef = inject(DestroyRef);
505
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
506
+ items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
507
+ options = signal([], ...(ngDevMode ? [{ debugName: "options" }] : []));
508
+ isoToLocal = isoToLocal;
509
+ constructor() {
510
+ this.loadOptions();
511
+ this.load();
512
+ }
513
+ loadOptions() {
514
+ this.svc
515
+ .scheduleOptions()
516
+ .pipe(takeUntilDestroyed(this.destroyRef))
517
+ .subscribe({ next: (o) => this.options.set(o ?? []), error: () => this.options.set([]) });
518
+ }
519
+ scheduleLabel(value) {
520
+ const m = this.options().find((x) => x.value === value);
521
+ return m ? `${m.label} — ${m.description}` : '';
522
+ }
523
+ load() {
524
+ this.loading.set(true);
525
+ this.svc
526
+ .listSchedules()
527
+ .pipe(takeUntilDestroyed(this.destroyRef))
528
+ .subscribe({
529
+ next: (res) => {
530
+ this.items.set(res.data ?? []);
531
+ this.loading.set(false);
532
+ },
533
+ error: () => {
534
+ this.items.set([]);
535
+ this.loading.set(false);
536
+ },
537
+ });
538
+ }
539
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageScheduleIndex, deps: [], target: i0.ɵɵFactoryTarget.Component });
540
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageScheduleIndex, isStandalone: true, selector: "rolatech-automation-manage-schedule-index", ngImport: i0, template: "<div class=\"p-6 space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Schedules</h1>\n <p class=\"text-sm rt-muted\">Enable/disable schedules and review next runs.</p>\n </div>\n <div class=\"flex gap-2\">\n <a mat-stroked-button class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations\">Back</a>\n <button mat-stroked-button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n <a mat-flat-button class=\"rt-btn rt-btn-primary\" routerLink=\"create\">Create</a>\n </div>\n </div>\n\n <div class=\"rounded-2xl rt-panel overflow-hidden\">\n <div class=\"overflow-auto\">\n <table class=\"min-w-[980px] w-full text-sm rt-table\">\n <thead>\n <tr>\n <th class=\"text-left p-3\">Name</th>\n <th class=\"text-left p-3\">Definition</th>\n <th class=\"text-left p-3\">Schedule</th>\n <th class=\"text-left p-3\">Enabled</th>\n <th class=\"text-left p-3\">Next Run</th>\n <th class=\"text-right p-3\">Action</th>\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">Loading...</td>\n </tr>\n } @else { @for (s of items(); track s.id) {\n <tr>\n <td class=\"p-3\">{{ s.name }}</td>\n <td class=\"p-3 font-mono text-xs\">{{ s.definitionCode ?? s.definitionId }}</td>\n <td class=\"p-3\">\n <div class=\"font-mono text-xs\">{{ s.schedule }}</div>\n <div class=\"text-xs rt-muted\">{{ scheduleLabel(s.schedule) }}</div>\n </td>\n <td class=\"p-3\">\n <span class=\"rt-badge\" [class]=\"s.enabled ? 'rt-badge-success' : 'rt-badge-muted'\">\n {{ s.enabled ? 'Enabled' : 'Disabled' }}\n </span>\n </td>\n <td class=\"p-3 rt-muted\">{{ isoToLocal(s.nextRunAt) }}</td>\n <td class=\"p-3 text-right\">\n <a class=\"rt-btn rt-btn-ghost\" [routerLink]=\"[s.id]\">Open</a>\n </td>\n </tr>\n } @if (!items().length) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">No schedules.</td>\n </tr>\n } }\n </tbody>\n </table>\n </div>\n </div>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] });
541
+ }
542
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageScheduleIndex, decorators: [{
543
+ type: Component,
544
+ args: [{ selector: 'rolatech-automation-manage-schedule-index', imports: [RouterLink, MatButtonModule], template: "<div class=\"p-6 space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Schedules</h1>\n <p class=\"text-sm rt-muted\">Enable/disable schedules and review next runs.</p>\n </div>\n <div class=\"flex gap-2\">\n <a mat-stroked-button class=\"rt-btn rt-btn-ghost\" routerLink=\"/automations\">Back</a>\n <button mat-stroked-button class=\"rt-btn rt-btn-ghost\" (click)=\"load()\">Refresh</button>\n <a mat-flat-button class=\"rt-btn rt-btn-primary\" routerLink=\"create\">Create</a>\n </div>\n </div>\n\n <div class=\"rounded-2xl rt-panel overflow-hidden\">\n <div class=\"overflow-auto\">\n <table class=\"min-w-[980px] w-full text-sm rt-table\">\n <thead>\n <tr>\n <th class=\"text-left p-3\">Name</th>\n <th class=\"text-left p-3\">Definition</th>\n <th class=\"text-left p-3\">Schedule</th>\n <th class=\"text-left p-3\">Enabled</th>\n <th class=\"text-left p-3\">Next Run</th>\n <th class=\"text-right p-3\">Action</th>\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">Loading...</td>\n </tr>\n } @else { @for (s of items(); track s.id) {\n <tr>\n <td class=\"p-3\">{{ s.name }}</td>\n <td class=\"p-3 font-mono text-xs\">{{ s.definitionCode ?? s.definitionId }}</td>\n <td class=\"p-3\">\n <div class=\"font-mono text-xs\">{{ s.schedule }}</div>\n <div class=\"text-xs rt-muted\">{{ scheduleLabel(s.schedule) }}</div>\n </td>\n <td class=\"p-3\">\n <span class=\"rt-badge\" [class]=\"s.enabled ? 'rt-badge-success' : 'rt-badge-muted'\">\n {{ s.enabled ? 'Enabled' : 'Disabled' }}\n </span>\n </td>\n <td class=\"p-3 rt-muted\">{{ isoToLocal(s.nextRunAt) }}</td>\n <td class=\"p-3 text-right\">\n <a class=\"rt-btn rt-btn-ghost\" [routerLink]=\"[s.id]\">Open</a>\n </td>\n </tr>\n } @if (!items().length) {\n <tr>\n <td class=\"p-3 rt-muted\" colspan=\"6\">No schedules.</td>\n </tr>\n } }\n </tbody>\n </table>\n </div>\n </div>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
545
+ }], ctorParameters: () => [] });
546
+
547
+ class AutomationManageScheduleDetail {
548
+ svc = inject(AutomationService);
549
+ route = inject(ActivatedRoute);
550
+ router = inject(Router);
551
+ fb = inject(FormBuilder);
552
+ destroyRef = inject(DestroyRef);
553
+ isoToLocal = isoToLocal;
554
+ trackByCode = trackByCode;
555
+ trackByStableId = trackByStableId;
556
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
557
+ saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : []));
558
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
559
+ item = signal(null, ...(ngDevMode ? [{ debugName: "item" }] : []));
560
+ options = signal([], ...(ngDevMode ? [{ debugName: "options" }] : []));
561
+ jsonPreview = signal('', ...(ngDevMode ? [{ debugName: "jsonPreview" }] : []));
562
+ // ✅ IMPORTANT: don’t use [disabled] in template. disable control here if needed.
563
+ form = this.fb.group({
564
+ name: ['', [Validators.required, Validators.maxLength(200)]],
565
+ schedule: this.fb.control({ value: '', disabled: true }, { validators: [Validators.required] }),
566
+ inputJson: [''],
567
+ enabled: [true],
568
+ });
569
+ /** compareWith for strings (works even if values become non-string later) */
570
+ compareSchedule = (a, b) => String(a ?? '') === String(b ?? '');
571
+ constructor() {
572
+ const id = this.route.snapshot.params['id'];
573
+ this.loadOptions();
574
+ this.load(id);
575
+ }
576
+ loadOptions() {
577
+ this.svc
578
+ .scheduleOptions()
579
+ .pipe(takeUntilDestroyed(this.destroyRef))
580
+ .subscribe({
581
+ next: (list) => {
582
+ this.options.set(list ?? []);
583
+ // enable schedule control once options exist
584
+ if ((list?.length ?? 0) > 0) {
585
+ this.form.controls.schedule.enable({ emitEvent: false });
586
+ }
587
+ },
588
+ error: () => {
589
+ this.options.set([]);
590
+ this.form.controls.schedule.disable({ emitEvent: false });
591
+ },
592
+ });
593
+ }
594
+ scheduleDesc() {
595
+ const code = String(this.form.controls.schedule.value ?? '').trim();
596
+ const m = this.options().find((x) => x.code === code);
597
+ return m ? m.description : '';
598
+ }
599
+ load(id) {
600
+ this.loading.set(true);
601
+ this.error.set(null);
602
+ this.svc
603
+ .getSchedule(id)
604
+ .pipe(takeUntilDestroyed(this.destroyRef))
605
+ .subscribe({
606
+ next: (s) => {
607
+ console.log(s);
608
+ this.item.set(s);
609
+ // patch values
610
+ this.form.patchValue({
611
+ name: s.name,
612
+ schedule: s.schedule, // ✅ string like "EVERY_5_MINUTES"
613
+ inputJson: s.inputJson ?? '',
614
+ enabled: s.enabled,
615
+ }, { emitEvent: false });
616
+ // if options not loaded yet, keep disabled; when options arrive, enabled
617
+ this.jsonPreview.set(safeJsonPretty(s.inputJson));
618
+ this.loading.set(false);
619
+ },
620
+ error: (e) => {
621
+ this.error.set(String(e?.error?.message ?? e?.message ?? e));
622
+ this.loading.set(false);
623
+ },
624
+ });
625
+ }
626
+ save() {
627
+ const s = this.item();
628
+ if (!s || this.form.invalid)
629
+ return;
630
+ const req = {
631
+ name: this.form.value.name ?? s.name,
632
+ schedule: this.form.value.schedule ?? s.schedule,
633
+ inputJson: this.form.value.inputJson ?? null,
634
+ enabled: !!this.form.value.enabled,
635
+ };
636
+ this.saving.set(true);
637
+ this.error.set(null);
638
+ this.svc
639
+ .updateSchedule(s.id, req)
640
+ .pipe(takeUntilDestroyed(this.destroyRef))
641
+ .subscribe({
642
+ next: (updated) => {
643
+ this.item.set(updated);
644
+ this.jsonPreview.set(safeJsonPretty(updated.inputJson));
645
+ this.saving.set(false);
646
+ },
647
+ error: (e) => {
648
+ this.saving.set(false);
649
+ this.error.set(String(e?.error?.message ?? e?.message ?? e));
650
+ },
651
+ });
652
+ }
653
+ toggle(enable) {
654
+ const s = this.item();
655
+ if (!s)
656
+ return;
657
+ this.saving.set(true);
658
+ this.error.set(null);
659
+ const call$ = enable ? this.svc.enableSchedule(s.id) : this.svc.disableSchedule(s.id);
660
+ call$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
661
+ next: (updated) => {
662
+ this.item.set(updated);
663
+ this.form.patchValue({ enabled: updated.enabled }, { emitEvent: false });
664
+ this.saving.set(false);
665
+ },
666
+ error: (e) => {
667
+ this.saving.set(false);
668
+ this.error.set(String(e?.error?.message ?? e?.message ?? e));
669
+ },
670
+ });
671
+ }
672
+ runNow() {
673
+ const s = this.item();
674
+ if (!s?.definitionCode)
675
+ return;
676
+ this.saving.set(true);
677
+ this.error.set(null);
678
+ this.svc
679
+ .runNowBySchedule(s.id, s.definitionCode, this.form.value.inputJson ?? s.inputJson ?? null)
680
+ .pipe(takeUntilDestroyed(this.destroyRef))
681
+ .subscribe({
682
+ next: (exec) => {
683
+ this.saving.set(false);
684
+ this.router.navigate(['/automations/executions', exec.id]);
685
+ },
686
+ error: (e) => {
687
+ this.saving.set(false);
688
+ this.error.set(String(e?.error?.message ?? e?.message ?? e));
689
+ },
690
+ });
691
+ }
692
+ remove() {
693
+ const s = this.item();
694
+ if (!s)
695
+ return;
696
+ this.saving.set(true);
697
+ this.error.set(null);
698
+ this.svc
699
+ .deleteSchedule(s.id)
700
+ .pipe(takeUntilDestroyed(this.destroyRef))
701
+ .subscribe({
702
+ next: () => {
703
+ this.saving.set(false);
704
+ this.router.navigate(['/automations/schedules']);
705
+ },
706
+ error: (e) => {
707
+ this.saving.set(false);
708
+ this.error.set(String(e?.error?.message ?? e?.message ?? e));
709
+ },
710
+ });
711
+ }
712
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageScheduleDetail, deps: [], target: i0.ɵɵFactoryTarget.Component });
713
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageScheduleDetail, isStandalone: true, selector: "rolatech-automation-manage-schedule-detail", ngImport: i0, template: "<div class=\"p-6 max-w-5xl space-y-4 rt-page\">\n <div class=\"flex items-center justify-between gap-3\">\n <div>\n <h1 class=\"text-xl font-semibold\">Schedule</h1>\n <p class=\"text-sm rt-muted\">{{ item()?.name ?? '\u2014' }}</p>\n </div>\n\n <div class=\"flex gap-2\">\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n\n <button\n mat-stroked-button\n class=\"rt-btn rt-btn-primary\"\n (click)=\"runNow()\"\n [disabled]=\"saving() || !item()?.definitionCode\"\n >\n Run now\n </button>\n\n <button mat-stroked-button class=\"rt-btn rt-btn-danger\" (click)=\"remove()\" [disabled]=\"saving() || !item()\">\n Delete\n </button>\n </div>\n </div>\n\n @if (loading()) {\n <div class=\"text-sm rt-muted\">Loading...</div>\n } @else {\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-4\">\n <!-- Form -->\n <div class=\"lg:col-span-2 rounded-2xl rt-panel p-4 space-y-4\">\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" class=\"space-y-4\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <div>\n <div class=\"text-xs rt-muted\">Definition</div>\n <div class=\"font-mono text-xs\">{{ item()?.definitionCode ?? item()?.definitionId }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Schedule ID</div>\n <div class=\"font-mono text-xs\">{{ item()?.id }}</div>\n </div>\n </div>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Name</div>\n <input class=\"w-full rt-input\" formControlName=\"name\" />\n </label>\n\n <!-- \u2705 mat-select, value = o.code -->\n <mat-form-field appearance=\"fill\" class=\"w-full\">\n <mat-label>Schedule</mat-label>\n\n <mat-select formControlName=\"schedule\">\n @for (o of options(); track trackByCode($index, o)) {\n <mat-option [value]=\"o.code\">\n <span class=\"text-sm\"> {{ o.label }}</span>\n </mat-option>\n }\n </mat-select>\n\n <mat-hint>{{ scheduleDesc() }}</mat-hint>\n\n @if (form.controls.schedule.invalid && form.controls.schedule.touched) {\n <mat-error>Schedule is required</mat-error>\n }\n </mat-form-field>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Input JSON</div>\n <textarea class=\"w-full rt-input font-mono text-xs min-h-[160px]\" formControlName=\"inputJson\"></textarea>\n </label>\n\n <mat-checkbox formControlName=\"enabled\">Enabled</mat-checkbox>\n\n <div class=\"flex items-center justify-end gap-2\">\n <button\n mat-stroked-button\n class=\"rt-btn rt-btn-ghost\"\n (click)=\"toggle(false)\"\n type=\"button\"\n [disabled]=\"saving() || !item()?.enabled\"\n >\n Disable\n </button>\n <button\n mat-stroked-button\n class=\"rt-btn rt-btn-primary\"\n (click)=\"toggle(true)\"\n type=\"button\"\n [disabled]=\"saving() || !!item()?.enabled\"\n >\n Enable\n </button>\n <button mat-flat-button class=\"rt-btn rt-btn-primary\" [disabled]=\"form.invalid || saving()\">\n {{ saving() ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n\n @if (error()) {\n <div class=\"text-sm rt-alert-danger\">{{ error() }}</div>\n }\n </form>\n </div>\n\n <!-- Side info -->\n <div class=\"rounded-2xl rt-panel p-4 space-y-3\">\n <div>\n <div class=\"text-xs rt-muted\">Next run</div>\n <div class=\"text-sm\">{{ isoToLocal(item()?.nextRunAt) }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Last run</div>\n <div class=\"text-sm\">{{ isoToLocal(item()?.lastRunAt) }}</div>\n </div>\n\n <div class=\"pt-2\">\n <div class=\"text-sm font-medium mb-1\">Input JSON (preview)</div>\n <pre class=\"text-xs rt-soft rounded-xl p-3 overflow-auto\">{{ jsonPreview() }}</pre>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }] });
714
+ }
715
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageScheduleDetail, decorators: [{
716
+ type: Component,
717
+ args: [{ selector: 'rolatech-automation-manage-schedule-detail', imports: [RouterLink, ReactiveFormsModule, MatFormFieldModule, MatSelectModule, MatButtonModule, MatCheckboxModule], template: "<div class=\"p-6 max-w-5xl space-y-4 rt-page\">\n <div class=\"flex items-center justify-between gap-3\">\n <div>\n <h1 class=\"text-xl font-semibold\">Schedule</h1>\n <p class=\"text-sm rt-muted\">{{ item()?.name ?? '\u2014' }}</p>\n </div>\n\n <div class=\"flex gap-2\">\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n\n <button\n mat-stroked-button\n class=\"rt-btn rt-btn-primary\"\n (click)=\"runNow()\"\n [disabled]=\"saving() || !item()?.definitionCode\"\n >\n Run now\n </button>\n\n <button mat-stroked-button class=\"rt-btn rt-btn-danger\" (click)=\"remove()\" [disabled]=\"saving() || !item()\">\n Delete\n </button>\n </div>\n </div>\n\n @if (loading()) {\n <div class=\"text-sm rt-muted\">Loading...</div>\n } @else {\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-4\">\n <!-- Form -->\n <div class=\"lg:col-span-2 rounded-2xl rt-panel p-4 space-y-4\">\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" class=\"space-y-4\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <div>\n <div class=\"text-xs rt-muted\">Definition</div>\n <div class=\"font-mono text-xs\">{{ item()?.definitionCode ?? item()?.definitionId }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Schedule ID</div>\n <div class=\"font-mono text-xs\">{{ item()?.id }}</div>\n </div>\n </div>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Name</div>\n <input class=\"w-full rt-input\" formControlName=\"name\" />\n </label>\n\n <!-- \u2705 mat-select, value = o.code -->\n <mat-form-field appearance=\"fill\" class=\"w-full\">\n <mat-label>Schedule</mat-label>\n\n <mat-select formControlName=\"schedule\">\n @for (o of options(); track trackByCode($index, o)) {\n <mat-option [value]=\"o.code\">\n <span class=\"text-sm\"> {{ o.label }}</span>\n </mat-option>\n }\n </mat-select>\n\n <mat-hint>{{ scheduleDesc() }}</mat-hint>\n\n @if (form.controls.schedule.invalid && form.controls.schedule.touched) {\n <mat-error>Schedule is required</mat-error>\n }\n </mat-form-field>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Input JSON</div>\n <textarea class=\"w-full rt-input font-mono text-xs min-h-[160px]\" formControlName=\"inputJson\"></textarea>\n </label>\n\n <mat-checkbox formControlName=\"enabled\">Enabled</mat-checkbox>\n\n <div class=\"flex items-center justify-end gap-2\">\n <button\n mat-stroked-button\n class=\"rt-btn rt-btn-ghost\"\n (click)=\"toggle(false)\"\n type=\"button\"\n [disabled]=\"saving() || !item()?.enabled\"\n >\n Disable\n </button>\n <button\n mat-stroked-button\n class=\"rt-btn rt-btn-primary\"\n (click)=\"toggle(true)\"\n type=\"button\"\n [disabled]=\"saving() || !!item()?.enabled\"\n >\n Enable\n </button>\n <button mat-flat-button class=\"rt-btn rt-btn-primary\" [disabled]=\"form.invalid || saving()\">\n {{ saving() ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n\n @if (error()) {\n <div class=\"text-sm rt-alert-danger\">{{ error() }}</div>\n }\n </form>\n </div>\n\n <!-- Side info -->\n <div class=\"rounded-2xl rt-panel p-4 space-y-3\">\n <div>\n <div class=\"text-xs rt-muted\">Next run</div>\n <div class=\"text-sm\">{{ isoToLocal(item()?.nextRunAt) }}</div>\n </div>\n <div>\n <div class=\"text-xs rt-muted\">Last run</div>\n <div class=\"text-sm\">{{ isoToLocal(item()?.lastRunAt) }}</div>\n </div>\n\n <div class=\"pt-2\">\n <div class=\"text-sm font-medium mb-1\">Input JSON (preview)</div>\n <pre class=\"text-xs rt-soft rounded-xl p-3 overflow-auto\">{{ jsonPreview() }}</pre>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
718
+ }], ctorParameters: () => [] });
719
+
720
+ class AutomationManageDefinitionCreate {
721
+ svc = inject(AutomationService);
722
+ fb = inject(FormBuilder);
723
+ router = inject(Router);
724
+ destroyRef = inject(DestroyRef);
725
+ saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : []));
726
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
727
+ form = this.fb.group({
728
+ code: ['', [Validators.required, Validators.maxLength(120)]],
729
+ name: ['', [Validators.required, Validators.maxLength(200)]],
730
+ description: [''],
731
+ handlerKey: ['', [Validators.required, Validators.maxLength(200)]],
732
+ defaultInputJson: [''],
733
+ enabled: [true],
734
+ });
735
+ submit() {
736
+ if (this.form.invalid)
737
+ return;
738
+ const req = {
739
+ code: this.form.value.code,
740
+ name: this.form.value.name,
741
+ description: this.form.value.description ?? null,
742
+ handlerKey: this.form.value.handlerKey,
743
+ defaultInputJson: this.form.value.defaultInputJson ?? null,
744
+ enabled: !!this.form.value.enabled,
745
+ };
746
+ this.saving.set(true);
747
+ this.error.set(null);
748
+ this.svc
749
+ .createDefinition(req)
750
+ .pipe(takeUntilDestroyed(this.destroyRef))
751
+ .subscribe({
752
+ next: (dto) => {
753
+ this.saving.set(false);
754
+ this.router.navigate(['../', dto.id], { relativeTo: undefined });
755
+ },
756
+ error: (e) => {
757
+ this.saving.set(false);
758
+ this.error.set(String(e?.error?.message ?? e?.message ?? e));
759
+ },
760
+ });
761
+ }
762
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageDefinitionCreate, deps: [], target: i0.ɵɵFactoryTarget.Component });
763
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageDefinitionCreate, isStandalone: true, selector: "rolatech-automation-manage-definition-create", ngImport: i0, template: "<div class=\"p-6 max-w-3xl space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Create Definition</h1>\n <p class=\"text-sm rt-muted\">Define a handler and default input JSON.</p>\n </div>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n </div>\n\n <form class=\"rounded-2xl rt-panel p-4 space-y-4\" [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <label class=\"space-y-1\">\n <div class=\"text-sm font-medium\">Code</div>\n <input class=\"w-full rt-input font-mono text-sm\" formControlName=\"code\" placeholder=\"PROPERTY_ALTO_SYNC\" />\n </label>\n\n <label class=\"space-y-1\">\n <div class=\"text-sm font-medium\">Name</div>\n <input class=\"w-full rt-input\" formControlName=\"name\" placeholder=\"Alto Sync\" />\n </label>\n </div>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Handler Key (Spring bean name)</div>\n <input class=\"w-full rt-input font-mono text-sm\" formControlName=\"handlerKey\" placeholder=\"altoSyncAutomationHandler\" />\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Description</div>\n <textarea class=\"w-full rt-input min-h-[80px]\" formControlName=\"description\"></textarea>\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Default Input JSON</div>\n <textarea\n class=\"w-full rt-input font-mono text-xs min-h-[160px]\"\n formControlName=\"defaultInputJson\"\n placeholder='{\"dryRun\":false}'\n ></textarea>\n </label>\n\n <div class=\"flex items-center justify-between\">\n <label class=\"flex items-center gap-2 text-sm\">\n <input type=\"checkbox\" class=\"rounded\" formControlName=\"enabled\" />\n Enabled\n </label>\n\n <button class=\"rt-btn rt-btn-primary\" [disabled]=\"form.invalid || saving()\">{{ saving() ? 'Saving\u2026' : 'Create' }}</button>\n </div>\n\n @if (error()) {\n <div class=\"text-sm rt-alert-danger\">{{ error() }}</div>\n }\n </form>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
764
+ }
765
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageDefinitionCreate, decorators: [{
766
+ type: Component,
767
+ args: [{ selector: 'rolatech-automation-manage-definition-create', imports: [RouterLink, ReactiveFormsModule], template: "<div class=\"p-6 max-w-3xl space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Create Definition</h1>\n <p class=\"text-sm rt-muted\">Define a handler and default input JSON.</p>\n </div>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n </div>\n\n <form class=\"rounded-2xl rt-panel p-4 space-y-4\" [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <label class=\"space-y-1\">\n <div class=\"text-sm font-medium\">Code</div>\n <input class=\"w-full rt-input font-mono text-sm\" formControlName=\"code\" placeholder=\"PROPERTY_ALTO_SYNC\" />\n </label>\n\n <label class=\"space-y-1\">\n <div class=\"text-sm font-medium\">Name</div>\n <input class=\"w-full rt-input\" formControlName=\"name\" placeholder=\"Alto Sync\" />\n </label>\n </div>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Handler Key (Spring bean name)</div>\n <input class=\"w-full rt-input font-mono text-sm\" formControlName=\"handlerKey\" placeholder=\"altoSyncAutomationHandler\" />\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Description</div>\n <textarea class=\"w-full rt-input min-h-[80px]\" formControlName=\"description\"></textarea>\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Default Input JSON</div>\n <textarea\n class=\"w-full rt-input font-mono text-xs min-h-[160px]\"\n formControlName=\"defaultInputJson\"\n placeholder='{\"dryRun\":false}'\n ></textarea>\n </label>\n\n <div class=\"flex items-center justify-between\">\n <label class=\"flex items-center gap-2 text-sm\">\n <input type=\"checkbox\" class=\"rounded\" formControlName=\"enabled\" />\n Enabled\n </label>\n\n <button class=\"rt-btn rt-btn-primary\" [disabled]=\"form.invalid || saving()\">{{ saving() ? 'Saving\u2026' : 'Create' }}</button>\n </div>\n\n @if (error()) {\n <div class=\"text-sm rt-alert-danger\">{{ error() }}</div>\n }\n </form>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
11
768
  }] });
12
769
 
770
+ class AutomationManageScheduleCreate {
771
+ svc = inject(AutomationService);
772
+ fb = inject(FormBuilder);
773
+ router = inject(Router);
774
+ destroyRef = inject(DestroyRef);
775
+ trackByStableId = trackByStableId;
776
+ trackByValue = trackByValue;
777
+ saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : []));
778
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
779
+ definitions = signal([], ...(ngDevMode ? [{ debugName: "definitions" }] : []));
780
+ options = signal([], ...(ngDevMode ? [{ debugName: "options" }] : []));
781
+ form = this.fb.group({
782
+ definitionId: ['', Validators.required],
783
+ name: ['', [Validators.required, Validators.maxLength(200)]],
784
+ schedule: ['', Validators.required],
785
+ inputJson: [''],
786
+ enabled: [true],
787
+ });
788
+ constructor() {
789
+ this.loadDefinitions();
790
+ this.loadOptions();
791
+ }
792
+ loadDefinitions() {
793
+ this.svc
794
+ .listDefinitions()
795
+ .pipe(takeUntilDestroyed(this.destroyRef))
796
+ .subscribe({ next: (d) => this.definitions.set(d.data ?? []), error: () => this.definitions.set([]) });
797
+ }
798
+ loadOptions() {
799
+ this.svc
800
+ .scheduleOptions()
801
+ .pipe(takeUntilDestroyed(this.destroyRef))
802
+ .subscribe({ next: (o) => this.options.set(o ?? []), error: () => this.options.set([]) });
803
+ }
804
+ scheduleDesc() {
805
+ const v = this.form.value.schedule ?? '';
806
+ const m = this.options().find((x) => x.value === v);
807
+ return m ? m.description : '';
808
+ }
809
+ submit() {
810
+ if (this.form.invalid)
811
+ return;
812
+ const req = {
813
+ definitionId: this.form.value.definitionId,
814
+ name: this.form.value.name,
815
+ schedule: this.form.value.schedule,
816
+ inputJson: this.form.value.inputJson ?? null,
817
+ enabled: !!this.form.value.enabled,
818
+ };
819
+ this.saving.set(true);
820
+ this.error.set(null);
821
+ this.svc
822
+ .createSchedule(req)
823
+ .pipe(takeUntilDestroyed(this.destroyRef))
824
+ .subscribe({
825
+ next: (created) => {
826
+ this.saving.set(false);
827
+ this.router.navigate(['/automations/schedules', created.id]);
828
+ },
829
+ error: (e) => {
830
+ this.saving.set(false);
831
+ this.error.set(String(e?.error?.message ?? e?.message ?? e));
832
+ },
833
+ });
834
+ }
835
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageScheduleCreate, deps: [], target: i0.ɵɵFactoryTarget.Component });
836
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AutomationManageScheduleCreate, isStandalone: true, selector: "rolatech-automation-manage-schedule-create", ngImport: i0, template: "<div class=\"p-6 max-w-3xl space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Create Schedule</h1>\n <p class=\"text-sm rt-muted\">Attach a definition to a schedule cadence.</p>\n </div>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n </div>\n\n <form class=\"rounded-2xl rt-panel p-4 space-y-4\" [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Definition</div>\n <select class=\"w-full rt-input font-mono text-sm\" formControlName=\"definitionId\">\n <option value=\"\" disabled>Select a definition</option>\n @for (d of definitions(); track trackByStableId($index, d)) {\n <option [value]=\"d.id\">{{ d.code }} \u2014 {{ d.name }}</option>\n }\n </select>\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Schedule name</div>\n <input class=\"w-full rt-input\" formControlName=\"name\" placeholder=\"Daily Alto Sync\" />\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Cron option</div>\n <select class=\"w-full rt-input font-mono text-sm\" formControlName=\"schedule\">\n <option value=\"\" disabled>Select schedule</option>\n @for (o of options(); track trackByValue($index, o)) {\n <option [value]=\"o.value\">{{ o.value }} \u2014 {{ o.label }}</option>\n }\n </select>\n <div class=\"text-xs rt-muted mt-1\">{{ scheduleDesc() }}</div>\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Input JSON (override)</div>\n <textarea\n class=\"w-full rt-input font-mono text-xs min-h-[160px]\"\n formControlName=\"inputJson\"\n placeholder='{\"dryRun\":false}'\n ></textarea>\n </label>\n\n <div class=\"flex items-center justify-between\">\n <label class=\"flex items-center gap-2 text-sm\">\n <input type=\"checkbox\" class=\"rounded\" formControlName=\"enabled\" />\n Enabled\n </label>\n\n <button class=\"rt-btn rt-btn-primary\" [disabled]=\"form.invalid || saving()\">{{ saving() ? 'Saving\u2026' : 'Create' }}</button>\n </div>\n\n @if (error()) {\n <div class=\"text-sm rt-alert-danger\">{{ error() }}</div>\n }\n </form>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
837
+ }
838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AutomationManageScheduleCreate, decorators: [{
839
+ type: Component,
840
+ args: [{ selector: 'rolatech-automation-manage-schedule-create', imports: [RouterLink, ReactiveFormsModule], template: "<div class=\"p-6 max-w-3xl space-y-4 rt-page\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-xl font-semibold\">Create Schedule</h1>\n <p class=\"text-sm rt-muted\">Attach a definition to a schedule cadence.</p>\n </div>\n <a class=\"rt-btn rt-btn-ghost\" routerLink=\"../\">Back</a>\n </div>\n\n <form class=\"rounded-2xl rt-panel p-4 space-y-4\" [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Definition</div>\n <select class=\"w-full rt-input font-mono text-sm\" formControlName=\"definitionId\">\n <option value=\"\" disabled>Select a definition</option>\n @for (d of definitions(); track trackByStableId($index, d)) {\n <option [value]=\"d.id\">{{ d.code }} \u2014 {{ d.name }}</option>\n }\n </select>\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Schedule name</div>\n <input class=\"w-full rt-input\" formControlName=\"name\" placeholder=\"Daily Alto Sync\" />\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Cron option</div>\n <select class=\"w-full rt-input font-mono text-sm\" formControlName=\"schedule\">\n <option value=\"\" disabled>Select schedule</option>\n @for (o of options(); track trackByValue($index, o)) {\n <option [value]=\"o.value\">{{ o.value }} \u2014 {{ o.label }}</option>\n }\n </select>\n <div class=\"text-xs rt-muted mt-1\">{{ scheduleDesc() }}</div>\n </label>\n\n <label class=\"space-y-1 block\">\n <div class=\"text-sm font-medium\">Input JSON (override)</div>\n <textarea\n class=\"w-full rt-input font-mono text-xs min-h-[160px]\"\n formControlName=\"inputJson\"\n placeholder='{\"dryRun\":false}'\n ></textarea>\n </label>\n\n <div class=\"flex items-center justify-between\">\n <label class=\"flex items-center gap-2 text-sm\">\n <input type=\"checkbox\" class=\"rounded\" formControlName=\"enabled\" />\n Enabled\n </label>\n\n <button class=\"rt-btn rt-btn-primary\" [disabled]=\"form.invalid || saving()\">{{ saving() ? 'Saving\u2026' : 'Create' }}</button>\n </div>\n\n @if (error()) {\n <div class=\"text-sm rt-alert-danger\">{{ error() }}</div>\n }\n </form>\n</div>\n", styles: [":host{color:var(--rt-text-primary, #0f0f0f)}.rt-page{min-height:100%;color:var(--rt-text-primary, #0f0f0f);background:var(--rt-base-background, #fff)}.rt-panel{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));box-shadow:0 16px 50px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent)}.rt-soft{background:color-mix(in srgb,var(--rt-raised-background, #fff) 80%,transparent);border:1px solid color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 60%,transparent)}.rt-muted{color:var(--rt-text-secondary, #606060)!important}.rt-quiet{color:color-mix(in srgb,var(--rt-text-secondary, #606060) 70%,transparent)!important}.rt-strong{color:var(--rt-text-primary, #0f0f0f)!important}.rt-ring{border-color:var(--rt-outline, rgba(0, 0, 0, .08))!important}.rt-pill{display:inline-flex;align-items:center;gap:6px;padding:.35rem .75rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-additive-background, rgba(0, 0, 0, .05));color:var(--rt-text-primary, #0f0f0f)}.rt-pill.brand{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 50%,transparent);color:#2b0a00}.rt-btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.55rem .95rem;border-radius:12px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));background:var(--rt-raised-background, #fff);color:var(--rt-text-primary, #0f0f0f);font-weight:600;transition:background .15s ease,border-color .15s ease,transform .15s ease,box-shadow .15s ease}.rt-btn:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,var(--rt-outline, rgba(0, 0, 0, .08)) 40%,transparent);transform:translateY(-1px);box-shadow:0 10px 30px color-mix(in srgb,var(--rt-base-background, #0f0f0f) 60%,transparent);text-decoration:none}.rt-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}.rt-btn-primary{background:var(--rt-static-brand-orange, #ea580b);border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,transparent);color:#fff}.rt-btn-primary:hover{background:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#000)}.rt-btn-ghost{background:transparent;color:var(--rt-text-primary, #0f0f0f)}.rt-btn-danger{background:color-mix(in srgb,#ef4444 20%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 42%,transparent);color:#7f1d1d}.rt-btn-danger:hover{background:color-mix(in srgb,#ef4444 32%,var(--rt-raised-background, #fff))}.rt-table{width:100%;background:var(--rt-raised-background, #fff);border-collapse:collapse;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table thead{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 85%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-table th,.rt-table td{border-bottom:1px solid var(--rt-outline, rgba(0, 0, 0, .08))}.rt-table tbody tr:hover{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 70%,var(--rt-raised-background, #fff))}.rt-badge{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .65rem;border-radius:999px;border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));font-size:.8rem;font-weight:700;letter-spacing:.01em}.rt-badge-success{background:color-mix(in srgb,#22c55e 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#22c55e 40%,transparent);color:#166534}.rt-badge-warn{background:color-mix(in srgb,#f59e0b 24%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#7c2d12}.rt-badge-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d}.rt-badge-info{background:color-mix(in srgb,#38bdf8 18%,var(--rt-raised-background, #fff));border-color:color-mix(in srgb,#38bdf8 40%,transparent);color:#0f172a}.rt-badge-muted{background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 90%,var(--rt-raised-background, #fff));color:var(--rt-text-secondary, #606060)}.rt-alert-danger{background:color-mix(in srgb,#ef4444 22%,var(--rt-raised-background, #fff));border:1px solid color-mix(in srgb,#ef4444 40%,transparent);color:#7f1d1d;border-radius:14px;padding:.85rem 1rem}.rt-input{background:var(--rt-raised-background, #fff);border:1px solid var(--rt-outline, rgba(0, 0, 0, .08));border-radius:12px;color:var(--rt-text-primary, #0f0f0f);padding:.65rem .85rem;transition:border-color .15s ease,box-shadow .15s ease}.rt-input:focus{outline:none;border-color:color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 18%,transparent)}.rt-progress{height:8px;border-radius:999px;background:color-mix(in srgb,var(--rt-additive-background, rgba(0, 0, 0, .05)) 80%,var(--rt-raised-background, #fff));overflow:hidden}.rt-progress .bar{height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 82%,#fff),color-mix(in srgb,var(--rt-static-brand-orange, #ea580b) 70%,#000))}\n"] }]
841
+ }], ctorParameters: () => [] });
842
+
843
+ const automationManageRoutes = [
844
+ { path: '', component: AutomationManageIndex },
845
+ { path: 'definitions', component: AutomationManageDefinitionIndex },
846
+ { path: 'definitions/create', component: AutomationManageDefinitionCreate },
847
+ { path: 'definitions/:id', component: AutomationManageDefinitionDetail },
848
+ { path: 'schedules', component: AutomationManageScheduleIndex },
849
+ { path: 'schedules/create', component: AutomationManageScheduleCreate },
850
+ { path: 'schedules/:id', component: AutomationManageScheduleDetail },
851
+ { path: 'executions', component: AutomationManageExecutionIndex },
852
+ { path: 'executions/:id', component: AutomationManageExecutionDetail },
853
+ { path: 'executions/:id/log', component: AutomationManageExecutionLog },
854
+ { path: ':id', component: AutomationManageDetail },
855
+ ];
856
+
857
+ // angular-automation/src/lib/models/automation.models.ts
858
+ const SCHEDULE_CRON_META = [
859
+ { value: 'EVERY_5_MINUTES', label: 'Every 5 minutes', description: 'Runs every 5 minutes' },
860
+ { value: 'EVERY_15_MINUTES', label: 'Every 15 minutes', description: 'Runs every 15 minutes' },
861
+ { value: 'HOURLY', label: 'Hourly', description: 'Runs once per hour' },
862
+ { value: 'DAILY', label: 'Daily', description: 'Runs once per day' },
863
+ { value: 'WEEKLY', label: 'Weekly', description: 'Runs once per week' },
864
+ ];
865
+
13
866
  /**
14
867
  * Generated bundle index. Do not edit.
15
868
  */
16
869
 
17
- export { AngularAutomation };
870
+ export { SCHEDULE_CRON_META, automationManageRoutes };
18
871
  //# sourceMappingURL=rolatech-angular-automation.mjs.map