Skip to content

Commit 154c0c3

Browse files
committed
feat(loops): friendly schedule frequency picker, subtitle and wizard copy
1 parent 991edd1 commit 154c0c3

1 file changed

Lines changed: 9 additions & 74 deletions

File tree

packages/ui/src/features/loops/components/LoopTriggerEditor.tsx

Lines changed: 9 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,7 @@ import { Switch } from "@posthog/quill";
1010
import { CopyButton } from "@posthog/ui/features/agent-applications/components/CopyButton";
1111
import { SettingsOptionSelect } from "@posthog/ui/features/settings/SettingsOptionSelect";
1212
import { Button } from "@posthog/ui/primitives/Button";
13-
import {
14-
Box,
15-
Checkbox,
16-
Flex,
17-
IconButton,
18-
Text,
19-
TextField,
20-
} from "@radix-ui/themes";
21-
import { useState } from "react";
13+
import { Box, Checkbox, Flex, IconButton, Text } from "@radix-ui/themes";
2214
import {
2315
emptyLoopApiTriggerConfig,
2416
emptyLoopGithubTriggerConfig,
@@ -223,21 +215,14 @@ function TriggerCard({
223215
);
224216
}
225217

226-
type ScheduleFrequency =
227-
| "hourly"
228-
| "daily"
229-
| "weekdays"
230-
| "weekly"
231-
| "once"
232-
| "custom";
218+
type ScheduleFrequency = "hourly" | "daily" | "weekdays" | "weekly" | "once";
233219

234220
const FREQUENCY_OPTIONS: { value: ScheduleFrequency; label: string }[] = [
235221
{ value: "hourly", label: "Hourly" },
236222
{ value: "daily", label: "Daily" },
237223
{ value: "weekdays", label: "Weekdays" },
238224
{ value: "weekly", label: "Weekly" },
239225
{ value: "once", label: "Once" },
240-
{ value: "custom", label: "Custom (cron)" },
241226
];
242227

243228
const WEEKDAY_OPTIONS = [
@@ -266,7 +251,7 @@ interface ParsedRecurringSchedule {
266251
weekday: string;
267252
}
268253

269-
/** Reads the simple shapes the frequency picker writes; anything else is custom. */
254+
/** Reads the shapes the frequency picker writes; anything else falls back to daily. */
270255
function parseCronSchedule(
271256
cron: string | null | undefined,
272257
): ParsedRecurringSchedule | null {
@@ -321,17 +306,9 @@ function ScheduleTriggerFields({
321306
onChange: (config: LoopSchemas.LoopScheduleTriggerConfig) => void;
322307
}) {
323308
const parsed = parseCronSchedule(config.cron_expression);
324-
// Custom is sticky UI state: "0 9 * * *" typed by hand still parses as
325-
// daily, so deriving the mode from the config alone would bounce the user
326-
// out of the cron editor while they type.
327-
const [customMode, setCustomMode] = useState(
328-
() => !config.run_at && !!config.cron_expression && !parsed,
329-
);
330309
const frequency: ScheduleFrequency = config.run_at
331310
? "once"
332-
: customMode
333-
? "custom"
334-
: (parsed?.frequency ?? "daily");
311+
: (parsed?.frequency ?? "daily");
335312
const time = parsed?.time ?? DEFAULT_TIME;
336313
const weekday = parsed?.weekday ?? "1";
337314
const timezone = config.timezone || localTimezone();
@@ -354,21 +331,10 @@ function ScheduleTriggerFields({
354331
const handleFrequencyChange = (value: string) => {
355332
const next = value as ScheduleFrequency;
356333
if (next === "once") {
357-
setCustomMode(false);
358-
onChange({ run_at: new Date().toISOString() });
334+
// The backend rejects run_at values in the past; default an hour out.
335+
onChange({ run_at: new Date(Date.now() + 60 * 60 * 1000).toISOString() });
359336
return;
360337
}
361-
if (next === "custom") {
362-
setCustomMode(true);
363-
onChange({
364-
cron_expression:
365-
config.cron_expression ??
366-
emptyLoopScheduleTriggerConfig().cron_expression,
367-
timezone,
368-
});
369-
return;
370-
}
371-
setCustomMode(false);
372338
setRecurring(next, time, weekday);
373339
};
374340

@@ -379,13 +345,9 @@ function ScheduleTriggerFields({
379345
value={time}
380346
className="h-8 rounded-(--radius-2) border border-border bg-(--color-panel-solid) px-2 text-[12.5px] text-gray-12"
381347
onChange={(e) => {
382-
if (!e.target.value || frequency === "custom" || frequency === "once")
348+
if (!e.target.value || frequency === "once" || frequency === "hourly")
383349
return;
384-
setRecurring(
385-
frequency as "daily" | "weekdays" | "weekly",
386-
e.target.value,
387-
weekday,
388-
);
350+
setRecurring(frequency, e.target.value, weekday);
389351
}}
390352
/>
391353
);
@@ -438,34 +400,7 @@ function ScheduleTriggerFields({
438400
) : null}
439401
</Flex>
440402

441-
{frequency === "custom" ? (
442-
<Flex gap="2" wrap="wrap">
443-
<Flex direction="column" gap="1" className="min-w-[160px] flex-1">
444-
<Text className="text-[12px] text-gray-10">Cron expression</Text>
445-
<TextField.Root
446-
size="2"
447-
value={config.cron_expression ?? ""}
448-
placeholder="0 9 * * *"
449-
disabled={disabled}
450-
onChange={(e) =>
451-
onChange({ ...config, cron_expression: e.target.value })
452-
}
453-
/>
454-
</Flex>
455-
<Flex direction="column" gap="1" className="min-w-[160px] flex-1">
456-
<Text className="text-[12px] text-gray-10">Timezone</Text>
457-
<TextField.Root
458-
size="2"
459-
value={config.timezone ?? ""}
460-
placeholder="UTC"
461-
disabled={disabled}
462-
onChange={(e) =>
463-
onChange({ ...config, timezone: e.target.value })
464-
}
465-
/>
466-
</Flex>
467-
</Flex>
468-
) : frequency !== "once" ? (
403+
{frequency !== "once" ? (
469404
<Text className="text-[11px] text-gray-9">Times in {timezone}</Text>
470405
) : null}
471406
</Flex>

0 commit comments

Comments
 (0)