@burdenoff/microfe-vibecontrols 2026.602.9 → 2026.608.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/actions/ActionForm.js +260 -252
- package/dist/components/actions/ActionForm.js.map +1 -1
- package/dist/components/ai/InstructionFilesManager.js +138 -135
- package/dist/components/ai/InstructionFilesManager.js.map +1 -1
- package/dist/components/aliases/AliasManager.js +225 -224
- package/dist/components/aliases/AliasManager.js.map +1 -1
- package/dist/components/common/ActionAgentTargetNotice.js +125 -0
- package/dist/components/common/ActionAgentTargetNotice.js.map +1 -0
- package/dist/components/common/CommandEditor.js +49 -0
- package/dist/components/common/CommandEditor.js.map +1 -0
- package/dist/components/common/actionAgentTarget.js +55 -0
- package/dist/components/common/actionAgentTarget.js.map +1 -0
- package/dist/components/common/commandHighlight.js +190 -0
- package/dist/components/common/commandHighlight.js.map +1 -0
- package/dist/components/vibecalendar/ScheduleTaskModal.js +151 -149
- package/dist/components/vibecalendar/ScheduleTaskModal.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckButtonForm.js +231 -219
- package/dist/components/vibedeck/VibeDeckButtonForm.js.map +1 -1
- package/dist/pages/ActionsPage.js +233 -224
- package/dist/pages/ActionsPage.js.map +1 -1
- package/dist/pages/AgentDetailsPage.js +490 -489
- package/dist/pages/AgentDetailsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,159 +1,160 @@
|
|
|
1
1
|
import { useListActionsQuery as e } from "../../generated/wspace-operations.js";
|
|
2
2
|
import { useTr as t } from "../../shared/hooks/useTr.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { ActionAgentTargetNotice as n } from "../common/ActionAgentTargetNotice.js";
|
|
4
|
+
import { useMemo as r, useState as i } from "react";
|
|
5
|
+
import { Search as a, X as o, Zap as s } from "lucide-react";
|
|
6
|
+
import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
6
7
|
//#region src/components/vibecalendar/ScheduleTaskModal.tsx
|
|
7
|
-
var
|
|
8
|
-
function
|
|
9
|
-
let
|
|
8
|
+
var d = "w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-lg text-sm text-text-primary placeholder-text-placeholder focus:outline-none focus:border-border-primary", f = `${d} font-mono`, p = "block text-sm font-medium text-text-secondary mb-1";
|
|
9
|
+
function m({ isOpen: m, onClose: h, onSubmit: g, loading: _, prefillActionId: v }) {
|
|
10
|
+
let y = t(), [b, x] = i(v ?? ""), [S, C] = i(""), [w, T] = i(""), [E, D] = i(""), [O, k] = i("ONE_TIME"), [A, j] = i(""), [M, N] = i(""), [P, F] = i(60), [I, L] = i("minutes"), [R, z] = i(Intl.DateTimeFormat().resolvedOptions().timeZone), { data: B, loading: V } = e({
|
|
10
11
|
variables: { pagination: { limit: 100 } },
|
|
11
|
-
skip: !
|
|
12
|
+
skip: !m,
|
|
12
13
|
fetchPolicy: "cache-and-network"
|
|
13
|
-
}),
|
|
14
|
-
if (!
|
|
15
|
-
let e =
|
|
16
|
-
return
|
|
17
|
-
}, [
|
|
18
|
-
if (!
|
|
19
|
-
let
|
|
20
|
-
return /* @__PURE__ */
|
|
14
|
+
}), H = r(() => B?.actions?.items ?? [], [B?.actions?.items]), U = r(() => {
|
|
15
|
+
if (!S.trim()) return H;
|
|
16
|
+
let e = S.trim().toLowerCase();
|
|
17
|
+
return H.filter((t) => t.name?.toLowerCase().includes(e) || t.displayName?.toLowerCase().includes(e) || t.description?.toLowerCase().includes(e));
|
|
18
|
+
}, [H, S]), W = r(() => H.find((e) => e.id === b), [H, b]);
|
|
19
|
+
if (!m) return null;
|
|
20
|
+
let G = !!v, K = !!b && !_;
|
|
21
|
+
return /* @__PURE__ */ u("div", {
|
|
21
22
|
className: "fixed inset-0 z-50 flex items-center justify-center",
|
|
22
|
-
children: [/* @__PURE__ */
|
|
23
|
+
children: [/* @__PURE__ */ l("div", {
|
|
23
24
|
role: "button",
|
|
24
25
|
tabIndex: 0,
|
|
25
26
|
onKeyDown: (e) => {
|
|
26
|
-
(e.key === "Enter" || e.key === " ") && (e.preventDefault(),
|
|
27
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), h());
|
|
27
28
|
},
|
|
28
29
|
className: "absolute inset-0 bg-bg-overlay",
|
|
29
|
-
onClick:
|
|
30
|
-
}), /* @__PURE__ */
|
|
30
|
+
onClick: h
|
|
31
|
+
}), /* @__PURE__ */ u("div", {
|
|
31
32
|
className: "relative bg-bg-surface border border-border-default rounded-xl shadow-xl w-full max-w-lg max-h-[90vh] overflow-y-auto",
|
|
32
|
-
children: [/* @__PURE__ */
|
|
33
|
+
children: [/* @__PURE__ */ u("div", {
|
|
33
34
|
className: "flex items-center justify-between px-6 py-4 border-b border-border-default",
|
|
34
|
-
children: [/* @__PURE__ */
|
|
35
|
+
children: [/* @__PURE__ */ l("h2", {
|
|
35
36
|
className: "text-lg font-semibold text-text-primary",
|
|
36
|
-
children:
|
|
37
|
-
}), /* @__PURE__ */
|
|
37
|
+
children: G ? y("vibecontrols.calendar.schedule.addActionToCalendar", "Add Action to Calendar") : y("vibecontrols.calendar.schedule.scheduleActionOnCalendar", "Schedule Action on Calendar")
|
|
38
|
+
}), /* @__PURE__ */ l("button", {
|
|
38
39
|
type: "button",
|
|
39
|
-
onClick:
|
|
40
|
+
onClick: h,
|
|
40
41
|
className: "p-1 rounded hover:bg-bg-secondary",
|
|
41
|
-
children: /* @__PURE__ */
|
|
42
|
+
children: /* @__PURE__ */ l(o, { size: 18 })
|
|
42
43
|
})]
|
|
43
|
-
}), /* @__PURE__ */
|
|
44
|
+
}), /* @__PURE__ */ u("form", {
|
|
44
45
|
onSubmit: (e) => {
|
|
45
|
-
e.preventDefault(),
|
|
46
|
+
e.preventDefault(), b && g({
|
|
46
47
|
calendarId: "",
|
|
47
|
-
title:
|
|
48
|
-
description:
|
|
49
|
-
scheduleType:
|
|
50
|
-
scheduledAt:
|
|
51
|
-
cronExpression:
|
|
52
|
-
interval:
|
|
53
|
-
intervalUnit:
|
|
54
|
-
timezone:
|
|
55
|
-
actionId:
|
|
48
|
+
title: w,
|
|
49
|
+
description: E || void 0,
|
|
50
|
+
scheduleType: O,
|
|
51
|
+
scheduledAt: O === "ONE_TIME" ? new Date(A).toISOString() : void 0,
|
|
52
|
+
cronExpression: O === "CRON" ? M : void 0,
|
|
53
|
+
interval: O === "FIXED_INTERVAL" ? P : void 0,
|
|
54
|
+
intervalUnit: O === "FIXED_INTERVAL" ? I : void 0,
|
|
55
|
+
timezone: R,
|
|
56
|
+
actionId: b
|
|
56
57
|
});
|
|
57
58
|
},
|
|
58
59
|
className: "px-6 py-4 space-y-4",
|
|
59
60
|
children: [
|
|
60
|
-
/* @__PURE__ */
|
|
61
|
+
/* @__PURE__ */ u("div", {
|
|
61
62
|
className: "space-y-2",
|
|
62
63
|
children: [
|
|
63
|
-
/* @__PURE__ */
|
|
64
|
-
className:
|
|
65
|
-
children: [
|
|
64
|
+
/* @__PURE__ */ u("label", {
|
|
65
|
+
className: p,
|
|
66
|
+
children: [y("vibecontrols.calendar.schedule.actionToSchedule", "Action to Schedule"), " *"]
|
|
66
67
|
}),
|
|
67
|
-
/* @__PURE__ */
|
|
68
|
+
/* @__PURE__ */ l("p", {
|
|
68
69
|
className: "text-xs text-text-tertiary -mt-1",
|
|
69
70
|
children: "Calendar entries trigger VibeControls Actions. Agent, command, and webhook details come from the Action definition."
|
|
70
71
|
}),
|
|
71
|
-
|
|
72
|
+
G && W && /* @__PURE__ */ u("div", {
|
|
72
73
|
className: "flex items-start gap-3 p-3 rounded-lg border border-border-default bg-bg-secondary",
|
|
73
|
-
children: [/* @__PURE__ */
|
|
74
|
+
children: [/* @__PURE__ */ l("div", {
|
|
74
75
|
className: "p-1.5 rounded-md bg-primary/10 text-primary flex-shrink-0",
|
|
75
|
-
children: /* @__PURE__ */
|
|
76
|
-
}), /* @__PURE__ */
|
|
76
|
+
children: /* @__PURE__ */ l(s, { size: 16 })
|
|
77
|
+
}), /* @__PURE__ */ u("div", {
|
|
77
78
|
className: "flex-1 min-w-0",
|
|
78
79
|
children: [
|
|
79
|
-
/* @__PURE__ */
|
|
80
|
+
/* @__PURE__ */ l("p", {
|
|
80
81
|
className: "text-sm font-medium text-text-primary",
|
|
81
|
-
children:
|
|
82
|
+
children: W.displayName || W.name
|
|
82
83
|
}),
|
|
83
|
-
/* @__PURE__ */
|
|
84
|
+
/* @__PURE__ */ u("p", {
|
|
84
85
|
className: "text-xs text-text-secondary mt-0.5",
|
|
85
86
|
children: [
|
|
86
|
-
|
|
87
|
+
W.actionType,
|
|
87
88
|
" · ",
|
|
88
|
-
|
|
89
|
+
W.triggerType
|
|
89
90
|
]
|
|
90
91
|
}),
|
|
91
|
-
|
|
92
|
+
W.description && /* @__PURE__ */ l("p", {
|
|
92
93
|
className: "text-xs text-text-tertiary mt-1 line-clamp-2",
|
|
93
|
-
children:
|
|
94
|
+
children: W.description
|
|
94
95
|
})
|
|
95
96
|
]
|
|
96
97
|
})]
|
|
97
98
|
}),
|
|
98
|
-
|
|
99
|
+
G && !W && V && /* @__PURE__ */ l("div", {
|
|
99
100
|
className: "p-3 rounded-lg border border-border-default bg-bg-secondary text-xs text-text-secondary",
|
|
100
101
|
children: "Loading action…"
|
|
101
102
|
}),
|
|
102
|
-
|
|
103
|
+
G && !W && !V && /* @__PURE__ */ l("div", {
|
|
103
104
|
className: "p-3 rounded-lg border border-status-error-border bg-status-error-bg-subtle text-xs text-status-error-text",
|
|
104
105
|
children: "Action not found. It may have been deleted."
|
|
105
106
|
}),
|
|
106
|
-
!
|
|
107
|
+
!G && /* @__PURE__ */ u(c, { children: [/* @__PURE__ */ u("div", {
|
|
107
108
|
className: "relative",
|
|
108
|
-
children: [/* @__PURE__ */
|
|
109
|
+
children: [/* @__PURE__ */ l(a, {
|
|
109
110
|
size: 16,
|
|
110
111
|
className: "absolute left-3 top-1/2 -translate-y-1/2 text-text-tertiary"
|
|
111
|
-
}), /* @__PURE__ */
|
|
112
|
+
}), /* @__PURE__ */ l("input", {
|
|
112
113
|
"aria-label": "Search actions by name…",
|
|
113
114
|
type: "text",
|
|
114
|
-
value:
|
|
115
|
-
onChange: (e) =>
|
|
115
|
+
value: S,
|
|
116
|
+
onChange: (e) => C(e.target.value),
|
|
116
117
|
placeholder: "Search actions by name…",
|
|
117
|
-
className: `${
|
|
118
|
+
className: `${d} pl-9`
|
|
118
119
|
})]
|
|
119
|
-
}), /* @__PURE__ */
|
|
120
|
+
}), /* @__PURE__ */ u("div", {
|
|
120
121
|
className: "max-h-40 overflow-y-auto border border-border-default rounded-lg divide-y divide-border-default",
|
|
121
122
|
children: [
|
|
122
|
-
|
|
123
|
+
V && H.length === 0 && /* @__PURE__ */ l("div", {
|
|
123
124
|
className: "px-3 py-4 text-xs text-text-secondary text-center",
|
|
124
125
|
children: "Loading actions…"
|
|
125
126
|
}),
|
|
126
|
-
!
|
|
127
|
+
!V && H.length === 0 && /* @__PURE__ */ l("div", {
|
|
127
128
|
className: "px-3 py-4 text-xs text-text-secondary text-center",
|
|
128
129
|
children: "No actions yet. Create an Action in VibeControls first, then come back to schedule it."
|
|
129
130
|
}),
|
|
130
|
-
!
|
|
131
|
+
!V && H.length > 0 && U.length === 0 && /* @__PURE__ */ u("div", {
|
|
131
132
|
className: "px-3 py-4 text-xs text-text-secondary text-center",
|
|
132
133
|
children: [
|
|
133
134
|
"No actions match \"",
|
|
134
|
-
|
|
135
|
+
S,
|
|
135
136
|
"\"."
|
|
136
137
|
]
|
|
137
138
|
}),
|
|
138
|
-
|
|
139
|
-
let t = e.id ===
|
|
140
|
-
return /* @__PURE__ */
|
|
139
|
+
U.map((e) => {
|
|
140
|
+
let t = e.id === b;
|
|
141
|
+
return /* @__PURE__ */ l("button", {
|
|
141
142
|
type: "button",
|
|
142
|
-
onClick: () =>
|
|
143
|
+
onClick: () => x(e.id),
|
|
143
144
|
className: `w-full text-left px-3 py-2.5 hover:bg-bg-secondary transition-colors ${t ? "bg-primary/5" : ""}`,
|
|
144
|
-
children: /* @__PURE__ */
|
|
145
|
+
children: /* @__PURE__ */ u("div", {
|
|
145
146
|
className: "flex items-start gap-2.5",
|
|
146
147
|
children: [
|
|
147
|
-
/* @__PURE__ */
|
|
148
|
+
/* @__PURE__ */ l("div", {
|
|
148
149
|
className: `p-1 rounded-md flex-shrink-0 ${t ? "bg-primary/10 text-primary" : "bg-bg-sunken text-text-tertiary"}`,
|
|
149
|
-
children: /* @__PURE__ */
|
|
150
|
+
children: /* @__PURE__ */ l(s, { size: 14 })
|
|
150
151
|
}),
|
|
151
|
-
/* @__PURE__ */
|
|
152
|
+
/* @__PURE__ */ u("div", {
|
|
152
153
|
className: "flex-1 min-w-0",
|
|
153
|
-
children: [/* @__PURE__ */
|
|
154
|
+
children: [/* @__PURE__ */ l("p", {
|
|
154
155
|
className: "text-sm font-medium text-text-primary truncate",
|
|
155
156
|
children: e.displayName || e.name
|
|
156
|
-
}), /* @__PURE__ */
|
|
157
|
+
}), /* @__PURE__ */ u("p", {
|
|
157
158
|
className: "text-xs text-text-tertiary mt-0.5",
|
|
158
159
|
children: [
|
|
159
160
|
e.actionType,
|
|
@@ -162,7 +163,7 @@ function p({ isOpen: p, onClose: m, onSubmit: h, loading: g, prefillActionId: _
|
|
|
162
163
|
]
|
|
163
164
|
})]
|
|
164
165
|
}),
|
|
165
|
-
t && /* @__PURE__ */
|
|
166
|
+
t && /* @__PURE__ */ l("span", {
|
|
166
167
|
className: "text-xs font-medium text-primary flex-shrink-0",
|
|
167
168
|
children: "Selected"
|
|
168
169
|
})
|
|
@@ -171,122 +172,123 @@ function p({ isOpen: p, onClose: m, onSubmit: h, loading: g, prefillActionId: _
|
|
|
171
172
|
}, e.id);
|
|
172
173
|
})
|
|
173
174
|
]
|
|
174
|
-
})] })
|
|
175
|
+
})] }),
|
|
176
|
+
W && /* @__PURE__ */ l(n, { action: W })
|
|
175
177
|
]
|
|
176
178
|
}),
|
|
177
|
-
/* @__PURE__ */
|
|
178
|
-
className:
|
|
179
|
-
children:
|
|
180
|
-
}), /* @__PURE__ */
|
|
179
|
+
/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("label", {
|
|
180
|
+
className: p,
|
|
181
|
+
children: y("vibecontrols.calendar.schedule.title", "Title")
|
|
182
|
+
}), /* @__PURE__ */ l("input", {
|
|
181
183
|
"aria-label": "e.g. Run test suite",
|
|
182
184
|
type: "text",
|
|
183
|
-
value:
|
|
184
|
-
onChange: (e) =>
|
|
185
|
+
value: w,
|
|
186
|
+
onChange: (e) => T(e.target.value),
|
|
185
187
|
placeholder: "e.g. Run test suite",
|
|
186
|
-
className:
|
|
188
|
+
className: d,
|
|
187
189
|
required: !0
|
|
188
190
|
})] }),
|
|
189
|
-
/* @__PURE__ */
|
|
190
|
-
className:
|
|
191
|
-
children:
|
|
192
|
-
}), /* @__PURE__ */
|
|
191
|
+
/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("label", {
|
|
192
|
+
className: p,
|
|
193
|
+
children: y("vibecontrols.calendar.schedule.description", "Description")
|
|
194
|
+
}), /* @__PURE__ */ l("input", {
|
|
193
195
|
"aria-label": "Optional description",
|
|
194
196
|
type: "text",
|
|
195
|
-
value:
|
|
196
|
-
onChange: (e) =>
|
|
197
|
+
value: E,
|
|
198
|
+
onChange: (e) => D(e.target.value),
|
|
197
199
|
placeholder: "Optional description",
|
|
198
|
-
className:
|
|
200
|
+
className: d
|
|
199
201
|
})] }),
|
|
200
|
-
/* @__PURE__ */
|
|
201
|
-
className:
|
|
202
|
-
children:
|
|
203
|
-
}), /* @__PURE__ */
|
|
204
|
-
value:
|
|
205
|
-
onChange: (e) =>
|
|
206
|
-
className:
|
|
202
|
+
/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("label", {
|
|
203
|
+
className: p,
|
|
204
|
+
children: y("vibecontrols.calendar.schedule.schedule", "Schedule")
|
|
205
|
+
}), /* @__PURE__ */ u("select", {
|
|
206
|
+
value: O,
|
|
207
|
+
onChange: (e) => k(e.target.value),
|
|
208
|
+
className: d,
|
|
207
209
|
children: [
|
|
208
|
-
/* @__PURE__ */
|
|
210
|
+
/* @__PURE__ */ l("option", {
|
|
209
211
|
value: "ONE_TIME",
|
|
210
212
|
children: "One Time"
|
|
211
213
|
}),
|
|
212
|
-
/* @__PURE__ */
|
|
214
|
+
/* @__PURE__ */ l("option", {
|
|
213
215
|
value: "CRON",
|
|
214
216
|
children: "Cron Expression"
|
|
215
217
|
}),
|
|
216
|
-
/* @__PURE__ */
|
|
218
|
+
/* @__PURE__ */ l("option", {
|
|
217
219
|
value: "FIXED_INTERVAL",
|
|
218
220
|
children: "Fixed Interval"
|
|
219
221
|
})
|
|
220
222
|
]
|
|
221
223
|
})] }),
|
|
222
|
-
|
|
223
|
-
className:
|
|
224
|
-
children:
|
|
225
|
-
}), /* @__PURE__ */
|
|
224
|
+
O === "ONE_TIME" && /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("label", {
|
|
225
|
+
className: p,
|
|
226
|
+
children: y("vibecontrols.calendar.schedule.runAt", "Run At")
|
|
227
|
+
}), /* @__PURE__ */ l("input", {
|
|
226
228
|
"aria-label": "control",
|
|
227
229
|
type: "datetime-local",
|
|
228
|
-
value:
|
|
229
|
-
onChange: (e) =>
|
|
230
|
-
className:
|
|
230
|
+
value: A,
|
|
231
|
+
onChange: (e) => j(e.target.value),
|
|
232
|
+
className: d,
|
|
231
233
|
required: !0
|
|
232
234
|
})] }),
|
|
233
|
-
|
|
235
|
+
O === "CRON" && /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("label", {
|
|
234
236
|
htmlFor: "scheduletaskmodal-40",
|
|
235
|
-
className:
|
|
237
|
+
className: p,
|
|
236
238
|
children: "Cron Expression"
|
|
237
|
-
}), /* @__PURE__ */
|
|
239
|
+
}), /* @__PURE__ */ l("input", {
|
|
238
240
|
id: "scheduletaskmodal-40",
|
|
239
241
|
"aria-label": "*/5 * * * * (every 5 minutes)",
|
|
240
242
|
type: "text",
|
|
241
|
-
value:
|
|
242
|
-
onChange: (e) =>
|
|
243
|
+
value: M,
|
|
244
|
+
onChange: (e) => N(e.target.value),
|
|
243
245
|
placeholder: "*/5 * * * * (every 5 minutes)",
|
|
244
|
-
className:
|
|
246
|
+
className: f,
|
|
245
247
|
required: !0
|
|
246
248
|
})] }),
|
|
247
|
-
|
|
249
|
+
O === "FIXED_INTERVAL" && /* @__PURE__ */ u("div", {
|
|
248
250
|
className: "flex gap-2",
|
|
249
|
-
children: [/* @__PURE__ */
|
|
251
|
+
children: [/* @__PURE__ */ u("div", {
|
|
250
252
|
className: "flex-1",
|
|
251
|
-
children: [/* @__PURE__ */
|
|
253
|
+
children: [/* @__PURE__ */ l("label", {
|
|
252
254
|
htmlFor: "scheduletaskmodal-39",
|
|
253
|
-
className:
|
|
255
|
+
className: p,
|
|
254
256
|
children: "Every"
|
|
255
|
-
}), /* @__PURE__ */
|
|
257
|
+
}), /* @__PURE__ */ l("input", {
|
|
256
258
|
id: "scheduletaskmodal-39",
|
|
257
259
|
"aria-label": "control",
|
|
258
260
|
type: "number",
|
|
259
|
-
value:
|
|
260
|
-
onChange: (e) =>
|
|
261
|
+
value: P,
|
|
262
|
+
onChange: (e) => F(Number(e.target.value)),
|
|
261
263
|
min: 1,
|
|
262
|
-
className:
|
|
264
|
+
className: d,
|
|
263
265
|
required: !0
|
|
264
266
|
})]
|
|
265
|
-
}), /* @__PURE__ */
|
|
267
|
+
}), /* @__PURE__ */ u("div", {
|
|
266
268
|
className: "flex-1",
|
|
267
|
-
children: [/* @__PURE__ */
|
|
269
|
+
children: [/* @__PURE__ */ l("label", {
|
|
268
270
|
htmlFor: "scheduletaskmodal-38",
|
|
269
|
-
className:
|
|
271
|
+
className: p,
|
|
270
272
|
children: "Unit"
|
|
271
|
-
}), /* @__PURE__ */
|
|
273
|
+
}), /* @__PURE__ */ u("select", {
|
|
272
274
|
id: "scheduletaskmodal-38",
|
|
273
|
-
value:
|
|
274
|
-
onChange: (e) =>
|
|
275
|
-
className:
|
|
275
|
+
value: I,
|
|
276
|
+
onChange: (e) => L(e.target.value),
|
|
277
|
+
className: d,
|
|
276
278
|
children: [
|
|
277
|
-
/* @__PURE__ */
|
|
279
|
+
/* @__PURE__ */ l("option", {
|
|
278
280
|
value: "seconds",
|
|
279
281
|
children: "Seconds"
|
|
280
282
|
}),
|
|
281
|
-
/* @__PURE__ */
|
|
283
|
+
/* @__PURE__ */ l("option", {
|
|
282
284
|
value: "minutes",
|
|
283
285
|
children: "Minutes"
|
|
284
286
|
}),
|
|
285
|
-
/* @__PURE__ */
|
|
287
|
+
/* @__PURE__ */ l("option", {
|
|
286
288
|
value: "hours",
|
|
287
289
|
children: "Hours"
|
|
288
290
|
}),
|
|
289
|
-
/* @__PURE__ */
|
|
291
|
+
/* @__PURE__ */ l("option", {
|
|
290
292
|
value: "days",
|
|
291
293
|
children: "Days"
|
|
292
294
|
})
|
|
@@ -294,29 +296,29 @@ function p({ isOpen: p, onClose: m, onSubmit: h, loading: g, prefillActionId: _
|
|
|
294
296
|
})]
|
|
295
297
|
})]
|
|
296
298
|
}),
|
|
297
|
-
/* @__PURE__ */
|
|
298
|
-
className:
|
|
299
|
-
children:
|
|
300
|
-
}), /* @__PURE__ */
|
|
299
|
+
/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("label", {
|
|
300
|
+
className: p,
|
|
301
|
+
children: y("vibecontrols.calendar.schedule.timezone", "Timezone")
|
|
302
|
+
}), /* @__PURE__ */ l("input", {
|
|
301
303
|
"aria-label": "control",
|
|
302
304
|
type: "text",
|
|
303
|
-
value:
|
|
304
|
-
onChange: (e) =>
|
|
305
|
-
className:
|
|
305
|
+
value: R,
|
|
306
|
+
onChange: (e) => z(e.target.value),
|
|
307
|
+
className: d
|
|
306
308
|
})] }),
|
|
307
|
-
/* @__PURE__ */
|
|
309
|
+
/* @__PURE__ */ u("div", {
|
|
308
310
|
className: "flex items-center justify-end gap-3 pt-4 border-t border-border-default",
|
|
309
|
-
children: [/* @__PURE__ */
|
|
311
|
+
children: [/* @__PURE__ */ l("button", {
|
|
310
312
|
type: "button",
|
|
311
|
-
onClick:
|
|
313
|
+
onClick: h,
|
|
312
314
|
className: "px-4 py-2 text-sm text-text-secondary hover:text-text-primary transition-colors",
|
|
313
|
-
children:
|
|
314
|
-
}), /* @__PURE__ */
|
|
315
|
+
children: y("vibecontrols.calendar.schedule.cancel", "Cancel")
|
|
316
|
+
}), /* @__PURE__ */ l("button", {
|
|
315
317
|
type: "submit",
|
|
316
|
-
disabled: !
|
|
318
|
+
disabled: !K,
|
|
317
319
|
className: "px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed",
|
|
318
|
-
title:
|
|
319
|
-
children:
|
|
320
|
+
title: b ? void 0 : y("vibecontrols.calendar.schedule.selectActionFirst", "Select an Action first"),
|
|
321
|
+
children: _ ? y("vibecontrols.calendar.schedule.creating", "Creating...") : y("vibecontrols.calendar.schedule.scheduleBtn", "Schedule")
|
|
320
322
|
})]
|
|
321
323
|
})
|
|
322
324
|
]
|
|
@@ -325,6 +327,6 @@ function p({ isOpen: p, onClose: m, onSubmit: h, loading: g, prefillActionId: _
|
|
|
325
327
|
});
|
|
326
328
|
}
|
|
327
329
|
//#endregion
|
|
328
|
-
export {
|
|
330
|
+
export { m as ScheduleTaskModal };
|
|
329
331
|
|
|
330
332
|
//# sourceMappingURL=ScheduleTaskModal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScheduleTaskModal.js","names":[],"sources":["../../../src/components/vibecalendar/ScheduleTaskModal.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { X, Zap, Search } from 'lucide-react';\nimport { useListActionsQuery } from '@/generated/wspace-operations';\nimport type { Action } from '@/generated/wspace-types';\nimport { useTr } from '../../shared/hooks/useTr';\n\ntype ActionPickItem = Pick<\n Action,\n 'id' | 'name' | 'displayName' | 'description' | 'actionType' | 'triggerType'\n>;\n\ninterface ScheduleTaskModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSubmit: (input: ScheduleTaskInput) => void;\n // Legacy prop kept for compatibility; unused in Action-only mode.\n agents?: Array<{ id: string; name: string }>;\n loading?: boolean;\n // When provided, the picker is locked to this action (user navigated\n // in from \"Add to calendar\" on the Actions page). Otherwise the user\n // picks from a searchable dropdown of their actions.\n prefillActionId?: string;\n}\n\n/**\n * Calendar entries always delegate execution to a VibeControls Action.\n * Agent, command, script, and webhook fields come from the Action\n * definition at execution time — this modal only collects the calendar\n * metadata and the schedule.\n */\nexport interface ScheduleTaskInput {\n calendarId: string;\n title: string;\n description?: string;\n scheduleType: 'ONE_TIME' | 'CRON' | 'RRULE' | 'FIXED_INTERVAL';\n scheduledAt?: string;\n cronExpression?: string;\n rrule?: string;\n interval?: number;\n intervalUnit?: string;\n timezone: string;\n actionId: string;\n}\n\nconst INPUT_CLASS =\n 'w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-lg text-sm text-text-primary placeholder-text-placeholder focus:outline-none focus:border-border-primary';\nconst MONO_INPUT_CLASS = `${INPUT_CLASS} font-mono`;\nconst LABEL_CLASS = 'block text-sm font-medium text-text-secondary mb-1';\n\nexport function ScheduleTaskModal({\n isOpen,\n onClose,\n onSubmit,\n loading,\n prefillActionId,\n}: ScheduleTaskModalProps) {\n const tr = useTr();\n const [selectedActionId, setSelectedActionId] = useState<string>(prefillActionId ?? '');\n const [actionSearch, setActionSearch] = useState('');\n const [title, setTitle] = useState('');\n const [description, setDescription] = useState('');\n const [scheduleType, setScheduleType] = useState<\n 'ONE_TIME' | 'CRON' | 'RRULE' | 'FIXED_INTERVAL'\n >('ONE_TIME');\n const [scheduledAt, setScheduledAt] = useState('');\n const [cronExpression, setCronExpression] = useState('');\n const [interval, setInterval] = useState(60);\n const [intervalUnit, setIntervalUnit] = useState('minutes');\n const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone);\n\n const { data: actionsData, loading: actionsLoading } = useListActionsQuery({\n variables: { pagination: { limit: 100 } },\n skip: !isOpen,\n fetchPolicy: 'cache-and-network',\n });\n\n const allActions = useMemo<ActionPickItem[]>(\n () => (actionsData?.actions?.items ?? []) as ActionPickItem[],\n [actionsData?.actions?.items]\n );\n\n const filteredActions = useMemo(() => {\n if (!actionSearch.trim()) return allActions;\n const q = actionSearch.trim().toLowerCase();\n return allActions.filter(\n (a: ActionPickItem) =>\n a.name?.toLowerCase().includes(q) ||\n a.displayName?.toLowerCase().includes(q) ||\n a.description?.toLowerCase().includes(q)\n );\n }, [allActions, actionSearch]);\n\n const selectedAction = useMemo(\n () => allActions.find((a: ActionPickItem) => a.id === selectedActionId),\n [allActions, selectedActionId]\n );\n\n if (!isOpen) return null;\n\n const isActionLocked = Boolean(prefillActionId);\n const canSubmit = Boolean(selectedActionId) && !loading;\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!selectedActionId) return;\n onSubmit({\n calendarId: '',\n title,\n description: description || undefined,\n scheduleType,\n scheduledAt: scheduleType === 'ONE_TIME' ? new Date(scheduledAt).toISOString() : undefined,\n cronExpression: scheduleType === 'CRON' ? cronExpression : undefined,\n interval: scheduleType === 'FIXED_INTERVAL' ? interval : undefined,\n intervalUnit: scheduleType === 'FIXED_INTERVAL' ? intervalUnit : undefined,\n timezone,\n actionId: selectedActionId,\n });\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (onClose as (...a: unknown[]) => unknown)();\n }\n }}\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={onClose}\n />\n <div className=\"relative bg-bg-surface border border-border-default rounded-xl shadow-xl w-full max-w-lg max-h-[90vh] overflow-y-auto\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {isActionLocked\n ? tr('vibecontrols.calendar.schedule.addActionToCalendar', 'Add Action to Calendar')\n : tr(\n 'vibecontrols.calendar.schedule.scheduleActionOnCalendar',\n 'Schedule Action on Calendar'\n )}\n </h2>\n <button type=\"button\" onClick={onClose} className=\"p-1 rounded hover:bg-bg-secondary\">\n <X size={18} />\n </button>\n </div>\n\n {/* Form */}\n <form onSubmit={handleSubmit} className=\"px-6 py-4 space-y-4\">\n {/* Action Picker — always required */}\n <div className=\"space-y-2\">\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.actionToSchedule', 'Action to Schedule')} *\n </label>\n <p className=\"text-xs text-text-tertiary -mt-1\">\n Calendar entries trigger VibeControls Actions. Agent, command, and webhook details\n come from the Action definition.\n </p>\n\n {isActionLocked && selectedAction && (\n <div className=\"flex items-start gap-3 p-3 rounded-lg border border-border-default bg-bg-secondary\">\n <div className=\"p-1.5 rounded-md bg-primary/10 text-primary flex-shrink-0\">\n <Zap size={16} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {selectedAction.displayName || selectedAction.name}\n </p>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {selectedAction.actionType} · {selectedAction.triggerType}\n </p>\n {selectedAction.description && (\n <p className=\"text-xs text-text-tertiary mt-1 line-clamp-2\">\n {selectedAction.description}\n </p>\n )}\n </div>\n </div>\n )}\n\n {isActionLocked && !selectedAction && actionsLoading && (\n <div className=\"p-3 rounded-lg border border-border-default bg-bg-secondary text-xs text-text-secondary\">\n Loading action…\n </div>\n )}\n\n {isActionLocked && !selectedAction && !actionsLoading && (\n <div className=\"p-3 rounded-lg border border-status-error-border bg-status-error-bg-subtle text-xs text-status-error-text\">\n Action not found. It may have been deleted.\n </div>\n )}\n\n {!isActionLocked && (\n <>\n <div className=\"relative\">\n <Search\n size={16}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-tertiary\"\n />\n <input\n aria-label=\"Search actions by name…\"\n type=\"text\"\n value={actionSearch}\n onChange={(e) => setActionSearch(e.target.value)}\n placeholder=\"Search actions by name…\"\n className={`${INPUT_CLASS} pl-9`}\n />\n </div>\n\n <div className=\"max-h-40 overflow-y-auto border border-border-default rounded-lg divide-y divide-border-default\">\n {actionsLoading && allActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n Loading actions…\n </div>\n )}\n {!actionsLoading && allActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n No actions yet. Create an Action in VibeControls first, then come back to\n schedule it.\n </div>\n )}\n {!actionsLoading && allActions.length > 0 && filteredActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n No actions match \"{actionSearch}\".\n </div>\n )}\n {filteredActions.map((action: ActionPickItem) => {\n const isSelected = action.id === selectedActionId;\n return (\n <button\n key={action.id}\n type=\"button\"\n onClick={() => setSelectedActionId(action.id)}\n className={`w-full text-left px-3 py-2.5 hover:bg-bg-secondary transition-colors ${\n isSelected ? 'bg-primary/5' : ''\n }`}\n >\n <div className=\"flex items-start gap-2.5\">\n <div\n className={`p-1 rounded-md flex-shrink-0 ${\n isSelected\n ? 'bg-primary/10 text-primary'\n : 'bg-bg-sunken text-text-tertiary'\n }`}\n >\n <Zap size={14} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary truncate\">\n {action.displayName || action.name}\n </p>\n <p className=\"text-xs text-text-tertiary mt-0.5\">\n {action.actionType} · {action.triggerType}\n </p>\n </div>\n {isSelected && (\n <span className=\"text-xs font-medium text-primary flex-shrink-0\">\n Selected\n </span>\n )}\n </div>\n </button>\n );\n })}\n </div>\n </>\n )}\n </div>\n\n {/* Title */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.title', 'Title')}\n </label>\n <input\n aria-label=\"e.g. Run test suite\"\n type=\"text\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. Run test suite\"\n className={INPUT_CLASS}\n required\n />\n </div>\n\n {/* Description */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.description', 'Description')}\n </label>\n <input\n aria-label=\"Optional description\"\n type=\"text\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Optional description\"\n className={INPUT_CLASS}\n />\n </div>\n\n {/* Schedule Type */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.schedule', 'Schedule')}\n </label>\n <select\n value={scheduleType}\n onChange={(e) => setScheduleType(e.target.value as typeof scheduleType)}\n className={INPUT_CLASS}\n >\n <option value=\"ONE_TIME\">One Time</option>\n <option value=\"CRON\">Cron Expression</option>\n <option value=\"FIXED_INTERVAL\">Fixed Interval</option>\n </select>\n </div>\n\n {/* Schedule-specific fields */}\n {scheduleType === 'ONE_TIME' && (\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.runAt', 'Run At')}\n </label>\n <input\n aria-label=\"control\"\n type=\"datetime-local\"\n value={scheduledAt}\n onChange={(e) => setScheduledAt(e.target.value)}\n className={INPUT_CLASS}\n required\n />\n </div>\n )}\n\n {scheduleType === 'CRON' && (\n <div>\n <label htmlFor=\"scheduletaskmodal-40\" className={LABEL_CLASS}>\n Cron Expression\n </label>\n <input\n id=\"scheduletaskmodal-40\"\n aria-label=\"*/5 * * * * (every 5 minutes)\"\n type=\"text\"\n value={cronExpression}\n onChange={(e) => setCronExpression(e.target.value)}\n placeholder=\"*/5 * * * * (every 5 minutes)\"\n className={MONO_INPUT_CLASS}\n required\n />\n </div>\n )}\n\n {scheduleType === 'FIXED_INTERVAL' && (\n <div className=\"flex gap-2\">\n <div className=\"flex-1\">\n <label htmlFor=\"scheduletaskmodal-39\" className={LABEL_CLASS}>\n Every\n </label>\n <input\n id=\"scheduletaskmodal-39\"\n aria-label=\"control\"\n type=\"number\"\n value={interval}\n onChange={(e) => setInterval(Number(e.target.value))}\n min={1}\n className={INPUT_CLASS}\n required\n />\n </div>\n <div className=\"flex-1\">\n <label htmlFor=\"scheduletaskmodal-38\" className={LABEL_CLASS}>\n Unit\n </label>\n <select\n id=\"scheduletaskmodal-38\"\n value={intervalUnit}\n onChange={(e) => setIntervalUnit(e.target.value)}\n className={INPUT_CLASS}\n >\n <option value=\"seconds\">Seconds</option>\n <option value=\"minutes\">Minutes</option>\n <option value=\"hours\">Hours</option>\n <option value=\"days\">Days</option>\n </select>\n </div>\n </div>\n )}\n\n {/* Timezone */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.timezone', 'Timezone')}\n </label>\n <input\n aria-label=\"control\"\n type=\"text\"\n value={timezone}\n onChange={(e) => setTimezone(e.target.value)}\n className={INPUT_CLASS}\n />\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center justify-end gap-3 pt-4 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr('vibecontrols.calendar.schedule.cancel', 'Cancel')}\n </button>\n <button\n type=\"submit\"\n disabled={!canSubmit}\n className=\"px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed\"\n title={\n !selectedActionId\n ? tr('vibecontrols.calendar.schedule.selectActionFirst', 'Select an Action first')\n : undefined\n }\n >\n {loading\n ? tr('vibecontrols.calendar.schedule.creating', 'Creating...')\n : tr('vibecontrols.calendar.schedule.scheduleBtn', 'Schedule')}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ScheduleTaskModal.js","names":[],"sources":["../../../src/components/vibecalendar/ScheduleTaskModal.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { X, Zap, Search } from 'lucide-react';\nimport { useListActionsQuery } from '@/generated/wspace-operations';\nimport type { Action } from '@/generated/wspace-types';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { ActionAgentTargetNotice } from '../common/ActionAgentTargetNotice';\n\ntype ActionPickItem = Pick<\n Action,\n | 'id'\n | 'name'\n | 'displayName'\n | 'description'\n | 'actionType'\n | 'triggerType'\n | 'targetAgentId'\n | 'targetPlatformFilter'\n>;\n\ninterface ScheduleTaskModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSubmit: (input: ScheduleTaskInput) => void;\n // Legacy prop kept for compatibility; unused in Action-only mode.\n agents?: Array<{ id: string; name: string }>;\n loading?: boolean;\n // When provided, the picker is locked to this action (user navigated\n // in from \"Add to calendar\" on the Actions page). Otherwise the user\n // picks from a searchable dropdown of their actions.\n prefillActionId?: string;\n}\n\n/**\n * Calendar entries always delegate execution to a VibeControls Action.\n * Agent, command, script, and webhook fields come from the Action\n * definition at execution time — this modal only collects the calendar\n * metadata and the schedule.\n */\nexport interface ScheduleTaskInput {\n calendarId: string;\n title: string;\n description?: string;\n scheduleType: 'ONE_TIME' | 'CRON' | 'RRULE' | 'FIXED_INTERVAL';\n scheduledAt?: string;\n cronExpression?: string;\n rrule?: string;\n interval?: number;\n intervalUnit?: string;\n timezone: string;\n actionId: string;\n}\n\nconst INPUT_CLASS =\n 'w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-lg text-sm text-text-primary placeholder-text-placeholder focus:outline-none focus:border-border-primary';\nconst MONO_INPUT_CLASS = `${INPUT_CLASS} font-mono`;\nconst LABEL_CLASS = 'block text-sm font-medium text-text-secondary mb-1';\n\nexport function ScheduleTaskModal({\n isOpen,\n onClose,\n onSubmit,\n loading,\n prefillActionId,\n}: ScheduleTaskModalProps) {\n const tr = useTr();\n const [selectedActionId, setSelectedActionId] = useState<string>(prefillActionId ?? '');\n const [actionSearch, setActionSearch] = useState('');\n const [title, setTitle] = useState('');\n const [description, setDescription] = useState('');\n const [scheduleType, setScheduleType] = useState<\n 'ONE_TIME' | 'CRON' | 'RRULE' | 'FIXED_INTERVAL'\n >('ONE_TIME');\n const [scheduledAt, setScheduledAt] = useState('');\n const [cronExpression, setCronExpression] = useState('');\n const [interval, setInterval] = useState(60);\n const [intervalUnit, setIntervalUnit] = useState('minutes');\n const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone);\n\n const { data: actionsData, loading: actionsLoading } = useListActionsQuery({\n variables: { pagination: { limit: 100 } },\n skip: !isOpen,\n fetchPolicy: 'cache-and-network',\n });\n\n const allActions = useMemo<ActionPickItem[]>(\n () => (actionsData?.actions?.items ?? []) as ActionPickItem[],\n [actionsData?.actions?.items]\n );\n\n const filteredActions = useMemo(() => {\n if (!actionSearch.trim()) return allActions;\n const q = actionSearch.trim().toLowerCase();\n return allActions.filter(\n (a: ActionPickItem) =>\n a.name?.toLowerCase().includes(q) ||\n a.displayName?.toLowerCase().includes(q) ||\n a.description?.toLowerCase().includes(q)\n );\n }, [allActions, actionSearch]);\n\n const selectedAction = useMemo(\n () => allActions.find((a: ActionPickItem) => a.id === selectedActionId),\n [allActions, selectedActionId]\n );\n\n if (!isOpen) return null;\n\n const isActionLocked = Boolean(prefillActionId);\n const canSubmit = Boolean(selectedActionId) && !loading;\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!selectedActionId) return;\n onSubmit({\n calendarId: '',\n title,\n description: description || undefined,\n scheduleType,\n scheduledAt: scheduleType === 'ONE_TIME' ? new Date(scheduledAt).toISOString() : undefined,\n cronExpression: scheduleType === 'CRON' ? cronExpression : undefined,\n interval: scheduleType === 'FIXED_INTERVAL' ? interval : undefined,\n intervalUnit: scheduleType === 'FIXED_INTERVAL' ? intervalUnit : undefined,\n timezone,\n actionId: selectedActionId,\n });\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (onClose as (...a: unknown[]) => unknown)();\n }\n }}\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={onClose}\n />\n <div className=\"relative bg-bg-surface border border-border-default rounded-xl shadow-xl w-full max-w-lg max-h-[90vh] overflow-y-auto\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {isActionLocked\n ? tr('vibecontrols.calendar.schedule.addActionToCalendar', 'Add Action to Calendar')\n : tr(\n 'vibecontrols.calendar.schedule.scheduleActionOnCalendar',\n 'Schedule Action on Calendar'\n )}\n </h2>\n <button type=\"button\" onClick={onClose} className=\"p-1 rounded hover:bg-bg-secondary\">\n <X size={18} />\n </button>\n </div>\n\n {/* Form */}\n <form onSubmit={handleSubmit} className=\"px-6 py-4 space-y-4\">\n {/* Action Picker — always required */}\n <div className=\"space-y-2\">\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.actionToSchedule', 'Action to Schedule')} *\n </label>\n <p className=\"text-xs text-text-tertiary -mt-1\">\n Calendar entries trigger VibeControls Actions. Agent, command, and webhook details\n come from the Action definition.\n </p>\n\n {isActionLocked && selectedAction && (\n <div className=\"flex items-start gap-3 p-3 rounded-lg border border-border-default bg-bg-secondary\">\n <div className=\"p-1.5 rounded-md bg-primary/10 text-primary flex-shrink-0\">\n <Zap size={16} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {selectedAction.displayName || selectedAction.name}\n </p>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {selectedAction.actionType} · {selectedAction.triggerType}\n </p>\n {selectedAction.description && (\n <p className=\"text-xs text-text-tertiary mt-1 line-clamp-2\">\n {selectedAction.description}\n </p>\n )}\n </div>\n </div>\n )}\n\n {isActionLocked && !selectedAction && actionsLoading && (\n <div className=\"p-3 rounded-lg border border-border-default bg-bg-secondary text-xs text-text-secondary\">\n Loading action…\n </div>\n )}\n\n {isActionLocked && !selectedAction && !actionsLoading && (\n <div className=\"p-3 rounded-lg border border-status-error-border bg-status-error-bg-subtle text-xs text-status-error-text\">\n Action not found. It may have been deleted.\n </div>\n )}\n\n {!isActionLocked && (\n <>\n <div className=\"relative\">\n <Search\n size={16}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-tertiary\"\n />\n <input\n aria-label=\"Search actions by name…\"\n type=\"text\"\n value={actionSearch}\n onChange={(e) => setActionSearch(e.target.value)}\n placeholder=\"Search actions by name…\"\n className={`${INPUT_CLASS} pl-9`}\n />\n </div>\n\n <div className=\"max-h-40 overflow-y-auto border border-border-default rounded-lg divide-y divide-border-default\">\n {actionsLoading && allActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n Loading actions…\n </div>\n )}\n {!actionsLoading && allActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n No actions yet. Create an Action in VibeControls first, then come back to\n schedule it.\n </div>\n )}\n {!actionsLoading && allActions.length > 0 && filteredActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n No actions match \"{actionSearch}\".\n </div>\n )}\n {filteredActions.map((action: ActionPickItem) => {\n const isSelected = action.id === selectedActionId;\n return (\n <button\n key={action.id}\n type=\"button\"\n onClick={() => setSelectedActionId(action.id)}\n className={`w-full text-left px-3 py-2.5 hover:bg-bg-secondary transition-colors ${\n isSelected ? 'bg-primary/5' : ''\n }`}\n >\n <div className=\"flex items-start gap-2.5\">\n <div\n className={`p-1 rounded-md flex-shrink-0 ${\n isSelected\n ? 'bg-primary/10 text-primary'\n : 'bg-bg-sunken text-text-tertiary'\n }`}\n >\n <Zap size={14} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary truncate\">\n {action.displayName || action.name}\n </p>\n <p className=\"text-xs text-text-tertiary mt-0.5\">\n {action.actionType} · {action.triggerType}\n </p>\n </div>\n {isSelected && (\n <span className=\"text-xs font-medium text-primary flex-shrink-0\">\n Selected\n </span>\n )}\n </div>\n </button>\n );\n })}\n </div>\n </>\n )}\n\n {/* Tell the user which agent this action runs on, and warn if that\n agent is unhealthy or gone — before the schedule is created. */}\n {selectedAction && <ActionAgentTargetNotice action={selectedAction} />}\n </div>\n\n {/* Title */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.title', 'Title')}\n </label>\n <input\n aria-label=\"e.g. Run test suite\"\n type=\"text\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. Run test suite\"\n className={INPUT_CLASS}\n required\n />\n </div>\n\n {/* Description */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.description', 'Description')}\n </label>\n <input\n aria-label=\"Optional description\"\n type=\"text\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Optional description\"\n className={INPUT_CLASS}\n />\n </div>\n\n {/* Schedule Type */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.schedule', 'Schedule')}\n </label>\n <select\n value={scheduleType}\n onChange={(e) => setScheduleType(e.target.value as typeof scheduleType)}\n className={INPUT_CLASS}\n >\n <option value=\"ONE_TIME\">One Time</option>\n <option value=\"CRON\">Cron Expression</option>\n <option value=\"FIXED_INTERVAL\">Fixed Interval</option>\n </select>\n </div>\n\n {/* Schedule-specific fields */}\n {scheduleType === 'ONE_TIME' && (\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.runAt', 'Run At')}\n </label>\n <input\n aria-label=\"control\"\n type=\"datetime-local\"\n value={scheduledAt}\n onChange={(e) => setScheduledAt(e.target.value)}\n className={INPUT_CLASS}\n required\n />\n </div>\n )}\n\n {scheduleType === 'CRON' && (\n <div>\n <label htmlFor=\"scheduletaskmodal-40\" className={LABEL_CLASS}>\n Cron Expression\n </label>\n <input\n id=\"scheduletaskmodal-40\"\n aria-label=\"*/5 * * * * (every 5 minutes)\"\n type=\"text\"\n value={cronExpression}\n onChange={(e) => setCronExpression(e.target.value)}\n placeholder=\"*/5 * * * * (every 5 minutes)\"\n className={MONO_INPUT_CLASS}\n required\n />\n </div>\n )}\n\n {scheduleType === 'FIXED_INTERVAL' && (\n <div className=\"flex gap-2\">\n <div className=\"flex-1\">\n <label htmlFor=\"scheduletaskmodal-39\" className={LABEL_CLASS}>\n Every\n </label>\n <input\n id=\"scheduletaskmodal-39\"\n aria-label=\"control\"\n type=\"number\"\n value={interval}\n onChange={(e) => setInterval(Number(e.target.value))}\n min={1}\n className={INPUT_CLASS}\n required\n />\n </div>\n <div className=\"flex-1\">\n <label htmlFor=\"scheduletaskmodal-38\" className={LABEL_CLASS}>\n Unit\n </label>\n <select\n id=\"scheduletaskmodal-38\"\n value={intervalUnit}\n onChange={(e) => setIntervalUnit(e.target.value)}\n className={INPUT_CLASS}\n >\n <option value=\"seconds\">Seconds</option>\n <option value=\"minutes\">Minutes</option>\n <option value=\"hours\">Hours</option>\n <option value=\"days\">Days</option>\n </select>\n </div>\n </div>\n )}\n\n {/* Timezone */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.timezone', 'Timezone')}\n </label>\n <input\n aria-label=\"control\"\n type=\"text\"\n value={timezone}\n onChange={(e) => setTimezone(e.target.value)}\n className={INPUT_CLASS}\n />\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center justify-end gap-3 pt-4 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr('vibecontrols.calendar.schedule.cancel', 'Cancel')}\n </button>\n <button\n type=\"submit\"\n disabled={!canSubmit}\n className=\"px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed\"\n title={\n !selectedActionId\n ? tr('vibecontrols.calendar.schedule.selectActionFirst', 'Select an Action first')\n : undefined\n }\n >\n {loading\n ? tr('vibecontrols.calendar.schedule.creating', 'Creating...')\n : tr('vibecontrols.calendar.schedule.scheduleBtn', 'Schedule')}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|