@stigmer/react 3.5.3 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/AgentPicker.d.ts +10 -1
- package/agent/AgentPicker.d.ts.map +1 -1
- package/agent/AgentPicker.js +2 -2
- package/agent/AgentPicker.js.map +1 -1
- package/channel/AgentChannelsPanel.d.ts.map +1 -1
- package/channel/AgentChannelsPanel.js +22 -5
- package/channel/AgentChannelsPanel.js.map +1 -1
- package/channel/ChannelTemplatesDialog.d.ts +53 -0
- package/channel/ChannelTemplatesDialog.d.ts.map +1 -0
- package/channel/ChannelTemplatesDialog.js +150 -0
- package/channel/ChannelTemplatesDialog.js.map +1 -0
- package/channel/index.d.ts +8 -0
- package/channel/index.d.ts.map +1 -1
- package/channel/index.js +4 -0
- package/channel/index.js.map +1 -1
- package/channel/providers.d.ts +12 -0
- package/channel/providers.d.ts.map +1 -1
- package/channel/providers.js +14 -2
- package/channel/providers.js.map +1 -1
- package/channel/templatePresentation.d.ts +37 -0
- package/channel/templatePresentation.d.ts.map +1 -0
- package/channel/templatePresentation.js +69 -0
- package/channel/templatePresentation.js.map +1 -0
- package/channel/useChannelTemplateList.d.ts +64 -0
- package/channel/useChannelTemplateList.d.ts.map +1 -0
- package/channel/useChannelTemplateList.js +69 -0
- package/channel/useChannelTemplateList.js.map +1 -0
- package/channel/useChannelTemplateReadiness.d.ts +53 -0
- package/channel/useChannelTemplateReadiness.d.ts.map +1 -0
- package/channel/useChannelTemplateReadiness.js +42 -0
- package/channel/useChannelTemplateReadiness.js.map +1 -0
- package/dashboard/useDashboardFailedRuns.d.ts.map +1 -1
- package/dashboard/useDashboardFailedRuns.js +2 -0
- package/dashboard/useDashboardFailedRuns.js.map +1 -1
- package/index.d.ts +4 -2
- package/index.d.ts.map +1 -1
- package/index.js +9 -1
- package/index.js.map +1 -1
- package/library/useExportResource.d.ts +4 -3
- package/library/useExportResource.d.ts.map +1 -1
- package/library/useExportResource.js +1 -1
- package/library/useExportResource.js.map +1 -1
- package/organization/OrgProvider.d.ts +11 -4
- package/organization/OrgProvider.d.ts.map +1 -1
- package/organization/OrgProvider.js +28 -4
- package/organization/OrgProvider.js.map +1 -1
- package/package.json +4 -4
- package/resource-detail/useDeleteResource.d.ts +1 -1
- package/resource-detail/useDeleteResource.d.ts.map +1 -1
- package/resource-detail/useDeleteResource.js +5 -0
- package/resource-detail/useDeleteResource.js.map +1 -1
- package/resource-workbench/components/ResourceWorkbench.d.ts +10 -1
- package/resource-workbench/components/ResourceWorkbench.d.ts.map +1 -1
- package/resource-workbench/components/ResourceWorkbench.js +6 -2
- package/resource-workbench/components/ResourceWorkbench.js.map +1 -1
- package/resource-workbench/hooks/useResourceCollection.d.ts +8 -0
- package/resource-workbench/hooks/useResourceCollection.d.ts.map +1 -1
- package/resource-workbench/hooks/useResourceCollection.js +2 -2
- package/resource-workbench/hooks/useResourceCollection.js.map +1 -1
- package/schedule/CadenceField.d.ts +31 -0
- package/schedule/CadenceField.d.ts.map +1 -0
- package/schedule/CadenceField.js +116 -0
- package/schedule/CadenceField.js.map +1 -0
- package/schedule/ScheduleDetailView.d.ts +58 -0
- package/schedule/ScheduleDetailView.d.ts.map +1 -0
- package/schedule/ScheduleDetailView.js +236 -0
- package/schedule/ScheduleDetailView.js.map +1 -0
- package/schedule/ScheduleForm.d.ts +43 -0
- package/schedule/ScheduleForm.d.ts.map +1 -0
- package/schedule/ScheduleForm.js +129 -0
- package/schedule/ScheduleForm.js.map +1 -0
- package/schedule/ScheduleRowActions.d.ts +20 -0
- package/schedule/ScheduleRowActions.d.ts.map +1 -0
- package/schedule/ScheduleRowActions.js +54 -0
- package/schedule/ScheduleRowActions.js.map +1 -0
- package/schedule/TimeZoneField.d.ts +32 -0
- package/schedule/TimeZoneField.d.ts.map +1 -0
- package/schedule/TimeZoneField.js +104 -0
- package/schedule/TimeZoneField.js.map +1 -0
- package/schedule/cadence.d.ts +95 -0
- package/schedule/cadence.d.ts.map +1 -0
- package/schedule/cadence.js +242 -0
- package/schedule/cadence.js.map +1 -0
- package/schedule/index.d.ts +31 -0
- package/schedule/index.d.ts.map +1 -0
- package/schedule/index.js +16 -0
- package/schedule/index.js.map +1 -0
- package/schedule/scheduleColumns.d.ts +26 -0
- package/schedule/scheduleColumns.d.ts.map +1 -0
- package/schedule/scheduleColumns.js +77 -0
- package/schedule/scheduleColumns.js.map +1 -0
- package/schedule/scheduleListFn.d.ts +50 -0
- package/schedule/scheduleListFn.d.ts.map +1 -0
- package/schedule/scheduleListFn.js +65 -0
- package/schedule/scheduleListFn.js.map +1 -0
- package/schedule/scheduleState.d.ts +43 -0
- package/schedule/scheduleState.d.ts.map +1 -0
- package/schedule/scheduleState.js +67 -0
- package/schedule/scheduleState.js.map +1 -0
- package/schedule/useCreateSchedule.d.ts +57 -0
- package/schedule/useCreateSchedule.d.ts.map +1 -0
- package/schedule/useCreateSchedule.js +61 -0
- package/schedule/useCreateSchedule.js.map +1 -0
- package/schedule/useResumeSchedule.d.ts +30 -0
- package/schedule/useResumeSchedule.d.ts.map +1 -0
- package/schedule/useResumeSchedule.js +45 -0
- package/schedule/useResumeSchedule.js.map +1 -0
- package/schedule/useSchedule.d.ts +39 -0
- package/schedule/useSchedule.d.ts.map +1 -0
- package/schedule/useSchedule.js +44 -0
- package/schedule/useSchedule.js.map +1 -0
- package/schedule/useScheduleCount.d.ts +38 -0
- package/schedule/useScheduleCount.d.ts.map +1 -0
- package/schedule/useScheduleCount.js +30 -0
- package/schedule/useScheduleCount.js.map +1 -0
- package/schedule/useScheduleList.d.ts +48 -0
- package/schedule/useScheduleList.d.ts.map +1 -0
- package/schedule/useScheduleList.js +43 -0
- package/schedule/useScheduleList.js.map +1 -0
- package/schedule/useSetScheduleEnabled.d.ts +31 -0
- package/schedule/useSetScheduleEnabled.d.ts.map +1 -0
- package/schedule/useSetScheduleEnabled.js +53 -0
- package/schedule/useSetScheduleEnabled.js.map +1 -0
- package/schedule/useTriggerSchedule.d.ts +28 -0
- package/schedule/useTriggerSchedule.d.ts.map +1 -0
- package/schedule/useTriggerSchedule.js +43 -0
- package/schedule/useTriggerSchedule.js.map +1 -0
- package/search/useResourceCount.d.ts +2 -1
- package/search/useResourceCount.d.ts.map +1 -1
- package/search/useResourceCount.js +6 -1
- package/search/useResourceCount.js.map +1 -1
- package/src/agent/AgentPicker.tsx +13 -1
- package/src/channel/AgentChannelsPanel.tsx +43 -1
- package/src/channel/ChannelTemplatesDialog.tsx +433 -0
- package/src/channel/__tests__/AgentChannelsPanel.test.tsx +73 -0
- package/src/channel/__tests__/ChannelTemplatesDialog.test.tsx +292 -0
- package/src/channel/__tests__/providers.test.ts +9 -0
- package/src/channel/__tests__/templatePresentation.test.ts +96 -0
- package/src/channel/__tests__/useChannelTemplateList.test.tsx +216 -0
- package/src/channel/__tests__/useChannelTemplateReadiness.test.tsx +124 -0
- package/src/channel/index.ts +15 -0
- package/src/channel/providers.ts +26 -2
- package/src/channel/templatePresentation.ts +82 -0
- package/src/channel/useChannelTemplateList.ts +123 -0
- package/src/channel/useChannelTemplateReadiness.ts +69 -0
- package/src/dashboard/__tests__/useDashboardFailedRuns.test.tsx +106 -0
- package/src/dashboard/useDashboardFailedRuns.ts +2 -0
- package/src/index.ts +65 -0
- package/src/library/useExportResource.ts +4 -3
- package/src/organization/OrgProvider.tsx +29 -4
- package/src/organization/__tests__/OrgProvider.orgSwitch.test.tsx +89 -0
- package/src/resource-detail/useDeleteResource.ts +11 -1
- package/src/resource-workbench/__tests__/ResourceWorkbench.test.tsx +112 -0
- package/src/resource-workbench/components/ResourceWorkbench.tsx +32 -15
- package/src/resource-workbench/hooks/useResourceCollection.ts +11 -1
- package/src/schedule/CadenceField.tsx +365 -0
- package/src/schedule/ScheduleDetailView.tsx +583 -0
- package/src/schedule/ScheduleForm.tsx +405 -0
- package/src/schedule/ScheduleRowActions.tsx +124 -0
- package/src/schedule/TimeZoneField.tsx +199 -0
- package/src/schedule/__tests__/ScheduleDetailView.test.tsx +260 -0
- package/src/schedule/__tests__/cadence.test.ts +278 -0
- package/src/schedule/__tests__/scheduleColumnsRowActions.test.tsx +176 -0
- package/src/schedule/__tests__/scheduleCreation.test.tsx +340 -0
- package/src/schedule/__tests__/scheduleHooks.test.tsx +312 -0
- package/src/schedule/__tests__/scheduleListFn.test.ts +128 -0
- package/src/schedule/__tests__/scheduleState.test.ts +133 -0
- package/src/schedule/cadence.ts +298 -0
- package/src/schedule/index.ts +57 -0
- package/src/schedule/scheduleColumns.tsx +118 -0
- package/src/schedule/scheduleListFn.ts +108 -0
- package/src/schedule/scheduleState.ts +96 -0
- package/src/schedule/useCreateSchedule.ts +88 -0
- package/src/schedule/useResumeSchedule.ts +67 -0
- package/src/schedule/useSchedule.ts +67 -0
- package/src/schedule/useScheduleCount.ts +57 -0
- package/src/schedule/useScheduleList.ts +83 -0
- package/src/schedule/useSetScheduleEnabled.ts +84 -0
- package/src/schedule/useTriggerSchedule.ts +65 -0
- package/src/search/__tests__/useResourceCount.test.tsx +89 -0
- package/src/search/useResourceCount.ts +8 -2
- package/src/workflow/WorkflowDashboard.tsx +1 -0
- package/src/workflow/useWorkflowExecutionList.ts +13 -2
- package/styles.css +1 -1
- package/workflow/CanvasTransitionEdge.d.ts +1 -1
- package/workflow/WorkflowDashboard.d.ts.map +1 -1
- package/workflow/WorkflowDashboard.js +1 -0
- package/workflow/WorkflowDashboard.js.map +1 -1
- package/workflow/useWorkflowExecutionList.d.ts +10 -0
- package/workflow/useWorkflowExecutionList.d.ts.map +1 -1
- package/workflow/useWorkflowExecutionList.js +3 -2
- package/workflow/useWorkflowExecutionList.js.map +1 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { getUserMessage } from "@stigmer/sdk";
|
|
6
|
+
import { Popover } from "@base-ui/react/popover";
|
|
7
|
+
import { AgentPicker } from "../agent/AgentPicker.js";
|
|
8
|
+
import { Switch } from "../switch/Switch.js";
|
|
9
|
+
import { useStigmerPortalContainer } from "../portal-container.js";
|
|
10
|
+
import { CadenceField } from "./CadenceField.js";
|
|
11
|
+
import { TimeZoneField, browserTimeZone } from "./TimeZoneField.js";
|
|
12
|
+
import { useCreateSchedule } from "./useCreateSchedule.js";
|
|
13
|
+
import { cadenceToCron, validateCron } from "./cadence.js";
|
|
14
|
+
/** spec.proto pins AgentTarget.message to 8192 characters. */
|
|
15
|
+
const MESSAGE_MAX_LEN = 8192;
|
|
16
|
+
/** Show the remaining-characters counter once within this margin. */
|
|
17
|
+
const MESSAGE_COUNTER_THRESHOLD = 500;
|
|
18
|
+
/**
|
|
19
|
+
* Single-page form for creating a {@link Schedule}.
|
|
20
|
+
*
|
|
21
|
+
* Collects the four things a user decides about a schedule — which
|
|
22
|
+
* agent, what message, when ({@link CadenceField}, generating the cron
|
|
23
|
+
* expression from human-friendly presets), and whether it starts
|
|
24
|
+
* enabled — then creates it via {@link useCreateSchedule}.
|
|
25
|
+
*
|
|
26
|
+
* Enabled defaults to OFF, deliberately: it matches the proto/YAML
|
|
27
|
+
* default (an omitted `enabled` is false) and the platform's
|
|
28
|
+
* recommended workflow — create staged-disabled, validate with
|
|
29
|
+
* "Run now" on the detail page, then enable.
|
|
30
|
+
*
|
|
31
|
+
* Creation only. Editing an existing schedule must not flow through
|
|
32
|
+
* this form's curated input — see the note on {@link useCreateSchedule}.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* <ScheduleForm
|
|
37
|
+
* org="acme"
|
|
38
|
+
* onComplete={(s) => navigate(`/library/schedules/${s.metadata?.org}/${s.metadata?.slug}`)}
|
|
39
|
+
* onCancel={() => navigate("/library/schedules")}
|
|
40
|
+
* />
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export function ScheduleForm({ org, onComplete, onCancel, className, }) {
|
|
44
|
+
const { create, isCreating, error, clearError } = useCreateSchedule();
|
|
45
|
+
const [name, setName] = useState("");
|
|
46
|
+
const [agentRef, setAgentRef] = useState(null);
|
|
47
|
+
const [agentName, setAgentName] = useState(null);
|
|
48
|
+
const [message, setMessage] = useState("");
|
|
49
|
+
const [cadence, setCadence] = useState({
|
|
50
|
+
kind: "daily",
|
|
51
|
+
hour: 9,
|
|
52
|
+
minute: 0,
|
|
53
|
+
});
|
|
54
|
+
const [timeZone, setTimeZone] = useState(browserTimeZone);
|
|
55
|
+
const [enabled, setEnabled] = useState(false);
|
|
56
|
+
const [pickerOpen, setPickerOpen] = useState(false);
|
|
57
|
+
const trimmedName = name.trim();
|
|
58
|
+
const trimmedMessage = message.trim();
|
|
59
|
+
const cron = cadenceToCron(cadence).trim();
|
|
60
|
+
const cronValid = cron !== "" && validateCron(cron) === null;
|
|
61
|
+
const canSubmit = trimmedName !== "" &&
|
|
62
|
+
agentRef !== null &&
|
|
63
|
+
trimmedMessage !== "" &&
|
|
64
|
+
cronValid &&
|
|
65
|
+
!isCreating;
|
|
66
|
+
const handleAgentChange = useCallback((ref) => {
|
|
67
|
+
setAgentRef(ref);
|
|
68
|
+
if (ref === null)
|
|
69
|
+
setAgentName(null);
|
|
70
|
+
setPickerOpen(false);
|
|
71
|
+
}, []);
|
|
72
|
+
const handleSubmit = useCallback(async (e) => {
|
|
73
|
+
e.preventDefault();
|
|
74
|
+
if (!canSubmit || !agentRef)
|
|
75
|
+
return;
|
|
76
|
+
clearError();
|
|
77
|
+
try {
|
|
78
|
+
const schedule = await create({
|
|
79
|
+
name: trimmedName,
|
|
80
|
+
org,
|
|
81
|
+
cron,
|
|
82
|
+
timeZone,
|
|
83
|
+
enabled,
|
|
84
|
+
agent: { agentRef, message: trimmedMessage },
|
|
85
|
+
});
|
|
86
|
+
onComplete?.(schedule);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// error state is managed by useCreateSchedule
|
|
90
|
+
}
|
|
91
|
+
}, [
|
|
92
|
+
canSubmit,
|
|
93
|
+
agentRef,
|
|
94
|
+
clearError,
|
|
95
|
+
create,
|
|
96
|
+
trimmedName,
|
|
97
|
+
org,
|
|
98
|
+
cron,
|
|
99
|
+
timeZone,
|
|
100
|
+
enabled,
|
|
101
|
+
trimmedMessage,
|
|
102
|
+
onComplete,
|
|
103
|
+
]);
|
|
104
|
+
const remaining = MESSAGE_MAX_LEN - message.length;
|
|
105
|
+
return (_jsxs("form", { onSubmit: handleSubmit, className: cn("max-w-2xl space-y-5", className), "aria-label": "New schedule", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("label", { htmlFor: "stgm-new-schedule-name", className: labelClasses, children: "Name" }), _jsx("input", { id: "stgm-new-schedule-name", type: "text", value: name, onChange: (e) => setName(e.target.value), placeholder: "e.g. daily-fee-reminders", disabled: isCreating, autoFocus: true, required: true, className: inputClasses })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("span", { id: "stgm-new-schedule-agent-label", className: labelClasses, children: "Agent to run" }), _jsxs(Popover.Root, { open: pickerOpen, onOpenChange: setPickerOpen, children: [_jsxs(Popover.Trigger, { disabled: isCreating, "aria-labelledby": "stgm-new-schedule-agent-label", className: cn("flex w-full items-center justify-between rounded-md border border-input bg-background px-2.5 py-1.5 text-left text-xs", "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", "disabled:pointer-events-none disabled:opacity-50", agentRef ? "text-foreground" : "text-muted-foreground"), children: [_jsx("span", { className: "truncate", children: agentRef
|
|
106
|
+
? (agentName ?? `${agentRef.org}/${agentRef.slug}`)
|
|
107
|
+
: "Choose an agent…" }), _jsx(ChevronIcon, {})] }), _jsx(AgentPickerPopup, { org: org, value: agentRef, onChange: handleAgentChange, onDisplayNameResolved: (_key, resolvedName) => setAgentName(resolvedName), disabled: isCreating })] }), _jsxs("p", { className: hintClasses, children: ["Each fire runs this agent unattended in a fresh session. Only agents in ", _jsx("span", { className: "font-medium", children: org }), " can be scheduled."] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("label", { htmlFor: "stgm-new-schedule-message", className: labelClasses, children: "Message" }), _jsx("textarea", { id: "stgm-new-schedule-message", value: message, onChange: (e) => setMessage(e.target.value), placeholder: "The instruction the agent receives on every fire \u2014 write it for a run with no human present.", disabled: isCreating, required: true, rows: 5, maxLength: MESSAGE_MAX_LEN, className: cn(inputClasses, "resize-y") }), remaining <= MESSAGE_COUNTER_THRESHOLD && (_jsxs("p", { className: hintClasses, children: [remaining, " characters left"] }))] }), _jsxs("div", { className: "space-y-1", children: [_jsx("span", { className: labelClasses, children: "Runs" }), _jsx(CadenceField, { value: cadence, onChange: setCadence, timeZone: timeZone, disabled: isCreating })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("label", { htmlFor: "stgm-new-schedule-tz", className: labelClasses, children: "Time zone" }), _jsx(TimeZoneField, { id: "stgm-new-schedule-tz", value: timeZone, onChange: setTimeZone, disabled: isCreating })] }), _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(Switch, { id: "stgm-new-schedule-enabled", checked: enabled, onCheckedChange: setEnabled, disabled: isCreating, "aria-labelledby": "stgm-new-schedule-enabled-label" }), _jsxs("div", { className: "space-y-0.5", children: [_jsx("label", { id: "stgm-new-schedule-enabled-label", htmlFor: "stgm-new-schedule-enabled", className: labelClasses, children: "Enabled" }), _jsx("p", { className: hintClasses, children: "Leave off to create the schedule staged: validate it with \u201CRun now\u201D on the schedule page, then enable it there." })] })] }), error && (_jsx("p", { className: "text-xs text-destructive", role: "alert", children: getUserMessage(error) })), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { type: "submit", disabled: !canSubmit, className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium", "bg-primary text-primary-foreground hover:bg-primary-hover", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "disabled:pointer-events-none disabled:opacity-40"), children: [isCreating && _jsx(SpinnerIcon, {}), "Create schedule"] }), onCancel && (_jsx("button", { type: "button", onClick: onCancel, disabled: isCreating, className: cn("rounded-md px-3 py-1.5 text-sm", "text-muted-foreground hover:bg-accent-hover hover:text-foreground", "disabled:pointer-events-none disabled:opacity-50"), children: "Cancel" }))] })] }));
|
|
108
|
+
}
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
// Private helpers
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
const labelClasses = "block text-xs font-medium text-foreground";
|
|
113
|
+
const hintClasses = "text-[0.65rem] text-muted-foreground";
|
|
114
|
+
const inputClasses = cn("w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-xs text-foreground", "placeholder:text-muted-foreground", "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", "disabled:pointer-events-none disabled:opacity-50");
|
|
115
|
+
function AgentPickerPopup({ org, value, onChange, onDisplayNameResolved, disabled, }) {
|
|
116
|
+
const portalContainer = useStigmerPortalContainer();
|
|
117
|
+
return (_jsx(Popover.Portal, { container: portalContainer, children: _jsx(Popover.Positioner, { sideOffset: 4, align: "start", children: _jsx(Popover.Popup, { className: cn("z-popover overflow-x-hidden overflow-y-auto rounded-lg border border-border", "bg-popover p-3 text-popover-foreground shadow-md", "max-h-[60vh]"), children: _jsx(AgentPicker, { org: org, value: value, onChange: onChange, onDisplayNameResolved: onDisplayNameResolved,
|
|
118
|
+
// Schedules are org-local: the server rejects a target
|
|
119
|
+
// agent outside the schedule's org, so cross-org browsing
|
|
120
|
+
// could only offer choices that fail at submit.
|
|
121
|
+
scope: "org", showScopeToggle: false, disabled: disabled }) }) }) }));
|
|
122
|
+
}
|
|
123
|
+
function ChevronIcon() {
|
|
124
|
+
return (_jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: "shrink-0 text-muted-foreground", "aria-hidden": "true", children: _jsx("path", { d: "M4 6l4 4 4-4" }) }));
|
|
125
|
+
}
|
|
126
|
+
function SpinnerIcon() {
|
|
127
|
+
return (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", className: "animate-spin", "aria-hidden": "true", children: _jsx("path", { d: "M8 2a6 6 0 1 0 6 6" }) }));
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=ScheduleForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScheduleForm.js","sourceRoot":"","sources":["../../src/schedule/ScheduleForm.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Schedule } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
|
|
2
|
+
/** Props for {@link ScheduleRowActions}. */
|
|
3
|
+
export interface ScheduleRowActionsProps {
|
|
4
|
+
/** The schedule this row represents. */
|
|
5
|
+
readonly schedule: Schedule;
|
|
6
|
+
/** Called after a successful action so the list can refetch. */
|
|
7
|
+
readonly onChanged?: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Compact per-row actions for a schedule list: **Run now** on an active
|
|
11
|
+
* schedule (confirmation-gated — it starts a real, billable execution)
|
|
12
|
+
* and **Resume** on a platform-paused one. Exactly one action renders
|
|
13
|
+
* at a time — the one that is currently meaningful; an owner-disabled
|
|
14
|
+
* schedule renders neither (its remedy lives on the detail page).
|
|
15
|
+
*
|
|
16
|
+
* Shared by every console's schedule workbench via `renderItemAction`
|
|
17
|
+
* so row behavior never diverges between apps (DD-016).
|
|
18
|
+
*/
|
|
19
|
+
export declare function ScheduleRowActions({ schedule, onChanged, }: ScheduleRowActionsProps): import("react/jsx-runtime").JSX.Element | null;
|
|
20
|
+
//# sourceMappingURL=ScheduleRowActions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScheduleRowActions.d.ts","sourceRoot":"","sources":["../../src/schedule/ScheduleRowActions.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uDAAuD,CAAC;AAOtF,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,gEAAgE;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,SAAS,GACV,EAAE,uBAAuB,kDA+DzB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from "@stigmer/theme";
|
|
4
|
+
import { ConfirmDialog } from "../resource-detail/ConfirmDialog.js";
|
|
5
|
+
import { useConfirmAction } from "../resource-detail/useConfirmAction.js";
|
|
6
|
+
import { deriveScheduleState } from "./scheduleState.js";
|
|
7
|
+
import { useResumeSchedule } from "./useResumeSchedule.js";
|
|
8
|
+
import { useTriggerSchedule } from "./useTriggerSchedule.js";
|
|
9
|
+
/**
|
|
10
|
+
* Compact per-row actions for a schedule list: **Run now** on an active
|
|
11
|
+
* schedule (confirmation-gated — it starts a real, billable execution)
|
|
12
|
+
* and **Resume** on a platform-paused one. Exactly one action renders
|
|
13
|
+
* at a time — the one that is currently meaningful; an owner-disabled
|
|
14
|
+
* schedule renders neither (its remedy lives on the detail page).
|
|
15
|
+
*
|
|
16
|
+
* Shared by every console's schedule workbench via `renderItemAction`
|
|
17
|
+
* so row behavior never diverges between apps (DD-016).
|
|
18
|
+
*/
|
|
19
|
+
export function ScheduleRowActions({ schedule, onChanged, }) {
|
|
20
|
+
const { resumeSchedule, isResuming } = useResumeSchedule();
|
|
21
|
+
const { triggerSchedule, isTriggering } = useTriggerSchedule();
|
|
22
|
+
const { confirmState, confirm, handleConfirm, handleCancel } = useConfirmAction();
|
|
23
|
+
const info = deriveScheduleState(schedule.spec, schedule.status);
|
|
24
|
+
const scheduleId = schedule.metadata?.id ?? "";
|
|
25
|
+
const name = schedule.metadata?.name || schedule.metadata?.slug || "schedule";
|
|
26
|
+
const handleTrigger = async () => {
|
|
27
|
+
const confirmed = await confirm({
|
|
28
|
+
title: "Run this schedule now?",
|
|
29
|
+
description: `"${name}" starts a real agent execution immediately, outside ` +
|
|
30
|
+
"the cron cadence.",
|
|
31
|
+
confirmLabel: "Start run",
|
|
32
|
+
variant: "default",
|
|
33
|
+
});
|
|
34
|
+
if (!confirmed)
|
|
35
|
+
return;
|
|
36
|
+
await triggerSchedule(scheduleId);
|
|
37
|
+
onChanged?.();
|
|
38
|
+
};
|
|
39
|
+
const handleResume = async () => {
|
|
40
|
+
await resumeSchedule(scheduleId);
|
|
41
|
+
onChanged?.();
|
|
42
|
+
};
|
|
43
|
+
if (info.state === "disabled")
|
|
44
|
+
return null;
|
|
45
|
+
return (
|
|
46
|
+
// Row actions must never bubble into the row's navigate-to-detail
|
|
47
|
+
// click handler. The span is a non-interactive event fence — the
|
|
48
|
+
// real interactive element (with keyboard support) is the button.
|
|
49
|
+
_jsxs("span", { onClick: (e) => e.stopPropagation(), children: [info.state === "active" ? (_jsx(RowActionButton, { label: `Run ${name} now`, busy: isTriggering, onClick: () => void handleTrigger(), children: "Run now" })) : (_jsx(RowActionButton, { label: `Resume ${name}`, busy: isResuming, onClick: () => void handleResume(), children: "Resume" })), confirmState && (_jsx(ConfirmDialog, { state: confirmState, onConfirm: handleConfirm, onCancel: handleCancel }))] }));
|
|
50
|
+
}
|
|
51
|
+
function RowActionButton({ label, busy, onClick, children, }) {
|
|
52
|
+
return (_jsx("button", { type: "button", "aria-label": label, onClick: onClick, disabled: busy, className: cn("rounded-md border border-input bg-background px-2 py-1 text-xs font-medium text-foreground", "hover:bg-accent hover:text-accent-foreground", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "disabled:pointer-events-none disabled:opacity-50"), children: children }));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=ScheduleRowActions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScheduleRowActions.js","sourceRoot":"","sources":["../../src/schedule/ScheduleRowActions.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Props for {@link TimeZoneField}. */
|
|
2
|
+
export interface TimeZoneFieldProps {
|
|
3
|
+
/** Element ID, for association with an external `<label htmlFor>`. */
|
|
4
|
+
readonly id?: string;
|
|
5
|
+
/** The selected IANA time zone name. */
|
|
6
|
+
readonly value: string;
|
|
7
|
+
/** Called with the new zone when the user picks one. */
|
|
8
|
+
readonly onChange: (timeZone: string) => void;
|
|
9
|
+
/** Prevents interaction when `true`. */
|
|
10
|
+
readonly disabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Searchable IANA time zone selector for the schedule form.
|
|
14
|
+
*
|
|
15
|
+
* The IANA database has ~400 zones — far too many for a plain
|
|
16
|
+
* `<select>` — so this follows the SDK's searchable-picker idiom
|
|
17
|
+
* (search input + listbox, as in `AgentPicker`): the input shows the
|
|
18
|
+
* selected zone; typing filters the list; Enter or click selects.
|
|
19
|
+
*
|
|
20
|
+
* The zone list comes from the runtime's own tz database
|
|
21
|
+
* (`Intl.supportedValuesOf`), which is also what {@link validateTimeZone}
|
|
22
|
+
* checks against — the offered choices and the accepted choices cannot
|
|
23
|
+
* drift.
|
|
24
|
+
*
|
|
25
|
+
* Internal to the schedule folder by design: public API surface is a
|
|
26
|
+
* contract, and this earns a barrel export only when a second consumer
|
|
27
|
+
* appears.
|
|
28
|
+
*/
|
|
29
|
+
export declare function TimeZoneField({ id, value, onChange, disabled, }: TimeZoneFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
/** The browser's own IANA time zone — the form's default. */
|
|
31
|
+
export declare function browserTimeZone(): string;
|
|
32
|
+
//# sourceMappingURL=TimeZoneField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimeZoneField.d.ts","sourceRoot":"","sources":["../../src/schedule/TimeZoneField.tsx"],"names":[],"mappings":"AAWA,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,EAAE,EACF,KAAK,EACL,QAAQ,EACR,QAAQ,GACT,EAAE,kBAAkB,2CAsIpB;AAaD,6DAA6D;AAC7D,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useMemo, useRef, useState, } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
const LIST_ID = "stgm-timezone-list";
|
|
6
|
+
const MAX_VISIBLE = 100;
|
|
7
|
+
/**
|
|
8
|
+
* Searchable IANA time zone selector for the schedule form.
|
|
9
|
+
*
|
|
10
|
+
* The IANA database has ~400 zones — far too many for a plain
|
|
11
|
+
* `<select>` — so this follows the SDK's searchable-picker idiom
|
|
12
|
+
* (search input + listbox, as in `AgentPicker`): the input shows the
|
|
13
|
+
* selected zone; typing filters the list; Enter or click selects.
|
|
14
|
+
*
|
|
15
|
+
* The zone list comes from the runtime's own tz database
|
|
16
|
+
* (`Intl.supportedValuesOf`), which is also what {@link validateTimeZone}
|
|
17
|
+
* checks against — the offered choices and the accepted choices cannot
|
|
18
|
+
* drift.
|
|
19
|
+
*
|
|
20
|
+
* Internal to the schedule folder by design: public API surface is a
|
|
21
|
+
* contract, and this earns a barrel export only when a second consumer
|
|
22
|
+
* appears.
|
|
23
|
+
*/
|
|
24
|
+
export function TimeZoneField({ id, value, onChange, disabled, }) {
|
|
25
|
+
const zones = useMemo(() => allTimeZones(), []);
|
|
26
|
+
const [query, setQuery] = useState(null);
|
|
27
|
+
const [focusIndex, setFocusIndex] = useState(-1);
|
|
28
|
+
const listRef = useRef(null);
|
|
29
|
+
const isOpen = query !== null;
|
|
30
|
+
const filtered = useMemo(() => {
|
|
31
|
+
if (query === null)
|
|
32
|
+
return [];
|
|
33
|
+
const needle = query.trim().toLowerCase().replace(/\s+/g, "_");
|
|
34
|
+
const matches = needle
|
|
35
|
+
? zones.filter((z) => z.toLowerCase().includes(needle))
|
|
36
|
+
: zones;
|
|
37
|
+
return matches.slice(0, MAX_VISIBLE);
|
|
38
|
+
}, [zones, query]);
|
|
39
|
+
const close = useCallback(() => {
|
|
40
|
+
setQuery(null);
|
|
41
|
+
setFocusIndex(-1);
|
|
42
|
+
}, []);
|
|
43
|
+
const select = useCallback((zone) => {
|
|
44
|
+
onChange(zone);
|
|
45
|
+
close();
|
|
46
|
+
}, [onChange, close]);
|
|
47
|
+
const handleKeyDown = useCallback((e) => {
|
|
48
|
+
if (e.key === "Escape") {
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
close();
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (!isOpen)
|
|
54
|
+
return;
|
|
55
|
+
if (e.key === "ArrowDown") {
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
setFocusIndex((prev) => (prev < filtered.length - 1 ? prev + 1 : prev));
|
|
58
|
+
}
|
|
59
|
+
else if (e.key === "ArrowUp") {
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
setFocusIndex((prev) => (prev > 0 ? prev - 1 : -1));
|
|
62
|
+
}
|
|
63
|
+
else if (e.key === "Enter") {
|
|
64
|
+
e.preventDefault();
|
|
65
|
+
if (focusIndex >= 0 && focusIndex < filtered.length) {
|
|
66
|
+
select(filtered[focusIndex]);
|
|
67
|
+
}
|
|
68
|
+
else if (filtered.length === 1) {
|
|
69
|
+
select(filtered[0]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}, [isOpen, filtered, focusIndex, select, close]);
|
|
73
|
+
return (_jsxs("div", { className: "relative", children: [_jsx("input", { id: id, type: "text", role: "combobox", "aria-expanded": isOpen, "aria-controls": LIST_ID, "aria-activedescendant": focusIndex >= 0 ? `stgm-timezone-${focusIndex}` : undefined, "aria-label": "Time zone", placeholder: "Search time zones\u2026", value: query ?? value, onChange: (e) => {
|
|
74
|
+
setQuery(e.target.value);
|
|
75
|
+
setFocusIndex(-1);
|
|
76
|
+
}, onFocus: () => setQuery(""),
|
|
77
|
+
// Closing on blur reverts the input to the committed value —
|
|
78
|
+
// free-typed text is never submitted, only list selections.
|
|
79
|
+
onBlur: close, onKeyDown: handleKeyDown, disabled: disabled, className: cn("w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-xs text-foreground", "placeholder:text-muted-foreground", "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", "disabled:pointer-events-none disabled:opacity-50") }), isOpen && (_jsx("div", { ref: listRef, id: LIST_ID, role: "listbox", "aria-label": "Time zones", className: cn("absolute z-popover mt-1 max-h-52 w-full overflow-y-auto rounded-md border border-border", "bg-popover p-1 text-popover-foreground shadow-md"), children: filtered.length === 0 ? (_jsx("div", { className: "py-3 text-center text-xs text-muted-foreground", children: "No time zones match" })) : (filtered.map((zone, idx) => (_jsx("button", { id: `stgm-timezone-${idx}`, type: "button", role: "option", "aria-selected": zone === value,
|
|
80
|
+
// Runs before the input's blur, so selection wins over
|
|
81
|
+
// the close-on-blur revert.
|
|
82
|
+
onMouseDown: (e) => {
|
|
83
|
+
e.preventDefault();
|
|
84
|
+
select(zone);
|
|
85
|
+
}, className: cn("flex w-full items-center rounded-sm px-2 py-1.5 text-left text-xs transition-colors", idx === focusIndex
|
|
86
|
+
? "bg-accent text-foreground"
|
|
87
|
+
: "text-popover-foreground hover:bg-accent-hover", zone === value && "font-medium"), children: zone }, zone)))) }))] }));
|
|
88
|
+
}
|
|
89
|
+
function allTimeZones() {
|
|
90
|
+
try {
|
|
91
|
+
return Intl.supportedValuesOf("timeZone");
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Pre-2022 runtimes without supportedValuesOf: offer the browser's
|
|
95
|
+
// own zone plus UTC rather than an empty list.
|
|
96
|
+
const own = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
97
|
+
return own && own !== "UTC" ? [own, "UTC"] : ["UTC"];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/** The browser's own IANA time zone — the form's default. */
|
|
101
|
+
export function browserTimeZone() {
|
|
102
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=TimeZoneField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimeZoneField.js","sourceRoot":"","sources":["../../src/schedule/TimeZoneField.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The cadence model behind {@link CadenceField} — a pure, dependency-free
|
|
3
|
+
* bridge between human-friendly schedule presets and the 5-field cron
|
|
4
|
+
* grammar the Schedule spec stores.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately NOT a cron parser. The platform owns no cron parsing in
|
|
7
|
+
* either edition — calendar and DST semantics live in the Temporal server
|
|
8
|
+
* (see stigmer-server's schedule/controller/cron.go, DD-008 D2). This
|
|
9
|
+
* module only:
|
|
10
|
+
*
|
|
11
|
+
* 1. GENERATES cron strings from presets (`cadenceToCron`) — trivial
|
|
12
|
+
* string construction, always valid by construction.
|
|
13
|
+
* 2. RECOGNIZES the exact shapes the builder emits (`cronToCadence`)
|
|
14
|
+
* so a stored cron round-trips back into the preset UI; anything
|
|
15
|
+
* else falls back to the `custom` preset showing the raw string.
|
|
16
|
+
* 3. MIRRORS the server's purely lexical validation (`validateCron`,
|
|
17
|
+
* `validateTimeZone`) with the same user-facing wording, so the
|
|
18
|
+
* form can reject bad input instantly. The server remains the
|
|
19
|
+
* authority — its errors surface verbatim on submit.
|
|
20
|
+
*/
|
|
21
|
+
/** A human-friendly cadence, convertible to/from a cron expression. */
|
|
22
|
+
export type CadencePreset = {
|
|
23
|
+
readonly kind: "hourly";
|
|
24
|
+
readonly minute: number;
|
|
25
|
+
} | {
|
|
26
|
+
readonly kind: "daily";
|
|
27
|
+
readonly hour: number;
|
|
28
|
+
readonly minute: number;
|
|
29
|
+
} | {
|
|
30
|
+
readonly kind: "weekly";
|
|
31
|
+
/** Days of week, cron numbering: 0 = Sunday … 6 = Saturday. */
|
|
32
|
+
readonly days: readonly number[];
|
|
33
|
+
readonly hour: number;
|
|
34
|
+
readonly minute: number;
|
|
35
|
+
} | {
|
|
36
|
+
readonly kind: "monthly";
|
|
37
|
+
/** Day of month, 1–31. Days 29–31 skip months without that day. */
|
|
38
|
+
readonly day: number;
|
|
39
|
+
readonly hour: number;
|
|
40
|
+
readonly minute: number;
|
|
41
|
+
} | {
|
|
42
|
+
readonly kind: "custom";
|
|
43
|
+
readonly cron: string;
|
|
44
|
+
};
|
|
45
|
+
/** Discriminant of {@link CadencePreset}. */
|
|
46
|
+
export type CadenceKind = CadencePreset["kind"];
|
|
47
|
+
/** Day-of-week labels indexed by cron numbering (0 = Sunday). */
|
|
48
|
+
export declare const WEEKDAY_LABELS: readonly ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
49
|
+
/**
|
|
50
|
+
* Build the 5-field cron expression for a preset.
|
|
51
|
+
*
|
|
52
|
+
* Output is always valid by construction: numeric fields only,
|
|
53
|
+
* day-of-week in cron numbering (0 = Sunday). For `custom`, the raw
|
|
54
|
+
* string is returned as-is — validate it with {@link validateCron}.
|
|
55
|
+
*/
|
|
56
|
+
export declare function cadenceToCron(preset: CadencePreset): string;
|
|
57
|
+
/**
|
|
58
|
+
* Recognize a cron expression as one of the builder's presets.
|
|
59
|
+
*
|
|
60
|
+
* Only the exact shapes {@link cadenceToCron} emits (plus the
|
|
61
|
+
* calendar shorthands `@hourly`/`@daily`/`@weekly`/`@monthly`) map to a
|
|
62
|
+
* structured preset. Everything else — ranges, steps, names, `@yearly`
|
|
63
|
+
* — is a perfectly valid schedule that this UI simply cannot decompose,
|
|
64
|
+
* so it round-trips as `custom` with the raw string intact.
|
|
65
|
+
*/
|
|
66
|
+
export declare function cronToCadence(cron: string): CadencePreset;
|
|
67
|
+
/**
|
|
68
|
+
* Human-readable summary of a cadence, e.g.
|
|
69
|
+
* `"Every day at 09:00 (Asia/Kolkata)"`.
|
|
70
|
+
*
|
|
71
|
+
* This is a description of the chosen preset, not a computed fire-time
|
|
72
|
+
* forecast — the platform's next fire time is published by the server
|
|
73
|
+
* as `status.next_fire_at` after apply.
|
|
74
|
+
*/
|
|
75
|
+
export declare function describeCadence(preset: CadencePreset, timeZone?: string): string;
|
|
76
|
+
/** `9, 5` → `"09:05"` (24-hour clock, zero-padded). */
|
|
77
|
+
export declare function formatTime(hour: number, minute: number): string;
|
|
78
|
+
/**
|
|
79
|
+
* Validate a cron expression against the platform's lexical grammar.
|
|
80
|
+
*
|
|
81
|
+
* Returns the user-facing error message (identical wording to the
|
|
82
|
+
* server's) or `null` when the expression is acceptable. Purely
|
|
83
|
+
* lexical — it does not evaluate calendar semantics.
|
|
84
|
+
*/
|
|
85
|
+
export declare function validateCron(cron: string): string | null;
|
|
86
|
+
/**
|
|
87
|
+
* Validate an IANA time zone name using the runtime's own tz database
|
|
88
|
+
* (`Intl`), mirroring the server's check against the platform tz
|
|
89
|
+
* database. Returns the user-facing error message or `null`.
|
|
90
|
+
*
|
|
91
|
+
* `"Local"` is rejected explicitly for the same reason the server
|
|
92
|
+
* rejects it: it is host-dependent, not a zone.
|
|
93
|
+
*/
|
|
94
|
+
export declare function validateTimeZone(timeZone: string): string | null;
|
|
95
|
+
//# sourceMappingURL=cadence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cadence.d.ts","sourceRoot":"","sources":["../../src/schedule/cadence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,uEAAuE;AACvE,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1E;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,mEAAmE;IACnE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,6CAA6C;AAC7C,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;AAEhD,iEAAiE;AACjE,eAAO,MAAM,cAAc,yFAQjB,CAAC;AAMX;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAiB3D;AAWD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAsDzD;AAcD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAoBR;AAED,uDAAuD;AACvD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE/D;AA2BD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiCxD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAShE"}
|