Files
AutoGPT/autogpt_platform/frontend/src/components/cron-scheduler.tsx
Bently 61f17e5b97 feat(scheduler): Remove Schedule "Every Minute" Option (#10706)
This simply removes the schedule "every minute" option from the schedule
tasks UI, Its still possible to set a every minute schedule via the
custom option

### Checklist 📋

#### For code changes:
- [x] I have clearly listed my changes in the PR description
- [x] I have made a test plan
- [x] I have tested my changes according to the test plan:
  <!-- Put your test plan here: -->
- [x] Check the Schedule Tasks UI to see there is no more "Every Minute"
option
- [x] Check you can still set a schedule a agent to run every minute
using the custom option
2025-08-24 21:15:11 +00:00

338 lines
11 KiB
TypeScript

import React, { useEffect, useState } from "react";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { CronFrequency, makeCronExpression } from "@/lib/cron-expression-utils";
const weekDays = [
{ label: "Su", value: 0 },
{ label: "Mo", value: 1 },
{ label: "Tu", value: 2 },
{ label: "We", value: 3 },
{ label: "Th", value: 4 },
{ label: "Fr", value: 5 },
{ label: "Sa", value: 6 },
];
const months = [
{ label: "Jan", value: "January" },
{ label: "Feb", value: "February" },
{ label: "Mar", value: "March" },
{ label: "Apr", value: "April" },
{ label: "May", value: "May" },
{ label: "Jun", value: "June" },
{ label: "Jul", value: "July" },
{ label: "Aug", value: "August" },
{ label: "Sep", value: "September" },
{ label: "Oct", value: "October" },
{ label: "Nov", value: "November" },
{ label: "Dec", value: "December" },
];
type CronSchedulerProps = {
onCronExpressionChange: (cronExpression: string) => void;
};
export function CronScheduler({
onCronExpressionChange,
}: CronSchedulerProps): React.ReactElement {
const [frequency, setFrequency] = useState<CronFrequency>("daily");
const [selectedMinute, setSelectedMinute] = useState<string>("0");
const [selectedTime, setSelectedTime] = useState<string>("09:00");
const [selectedWeekDays, setSelectedWeekDays] = useState<number[]>([]);
const [selectedMonthDays, setSelectedMonthDays] = useState<number[]>([]);
const [selectedMonths, setSelectedMonths] = useState<number[]>([]);
const [customInterval, setCustomInterval] = useState<{
value: number;
unit: "minutes" | "hours" | "days";
}>({ value: 1, unit: "minutes" });
const [showCustomDays, setShowCustomDays] = useState<boolean>(false);
useEffect(() => {
const cronExpr = makeCronExpression({
frequency,
minute:
frequency === "hourly"
? parseInt(selectedMinute)
: parseInt(selectedTime.split(":")[1]),
hour: parseInt(selectedTime.split(":")[0]),
days:
frequency === "weekly"
? selectedWeekDays
: frequency === "monthly"
? selectedMonthDays
: [],
months: frequency === "yearly" ? selectedMonths : [],
customInterval:
frequency === "custom" ? customInterval : { unit: "minutes", value: 1 },
});
onCronExpressionChange(cronExpr);
}, [
frequency,
selectedMinute,
selectedTime,
selectedWeekDays,
selectedMonthDays,
selectedMonths,
customInterval,
onCronExpressionChange,
]);
return (
<div className="max-w-md space-y-6">
<div className="space-y-4">
<Label className="text-base font-medium">Repeat</Label>
<Select
value={frequency}
onValueChange={(value: CronFrequency) => setFrequency(value)}
>
<SelectTrigger>
<SelectValue placeholder="Select frequency" />
</SelectTrigger>
<SelectContent>
<SelectItem value="hourly">Every Hour</SelectItem>
<SelectItem value="daily">Daily</SelectItem>
<SelectItem value="weekly">Weekly</SelectItem>
<SelectItem value="monthly">Monthly</SelectItem>
<SelectItem value="yearly">Yearly</SelectItem>
<SelectItem value="custom">Custom</SelectItem>
</SelectContent>
</Select>
{frequency === "hourly" && (
<div className="flex items-center gap-2">
<Label>At minute</Label>
<Select value={selectedMinute} onValueChange={setSelectedMinute}>
<SelectTrigger className="w-24">
<SelectValue placeholder="Select minute" />
</SelectTrigger>
<SelectContent>
{[0, 15, 30, 45].map((min) => (
<SelectItem key={min} value={min.toString()}>
{min}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
)}
{frequency === "custom" && (
<div className="flex items-center gap-2">
<Label>Every</Label>
<Input
type="number"
min="1"
className="w-20"
value={customInterval.value}
onChange={(e) =>
setCustomInterval({
...customInterval,
value: parseInt(e.target.value),
})
}
/>
<Select
value={customInterval.unit}
onValueChange={(value: any) =>
setCustomInterval({ ...customInterval, unit: value })
}
>
<SelectTrigger className="w-32">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="minutes">Minutes</SelectItem>
<SelectItem value="hours">Hours</SelectItem>
<SelectItem value="days">Days</SelectItem>
</SelectContent>
</Select>
</div>
)}
</div>
{frequency === "weekly" && (
<div className="space-y-2">
<div className="flex items-center gap-2">
<Label>On</Label>
<Button
variant="outline"
className="h-8 px-2 py-1 text-xs"
onClick={() => {
if (selectedWeekDays.length === weekDays.length) {
setSelectedWeekDays([]);
} else {
setSelectedWeekDays(weekDays.map((day) => day.value));
}
}}
>
{selectedWeekDays.length === weekDays.length
? "Deselect All"
: "Select All"}
</Button>
<Button
variant="outline"
className="h-8 px-2 py-1 text-xs"
onClick={() => setSelectedWeekDays([1, 2, 3, 4, 5])}
>
Weekdays
</Button>
<Button
variant="outline"
className="h-8 px-2 py-1 text-xs"
onClick={() => setSelectedWeekDays([0, 6])}
>
Weekends
</Button>
</div>
<div className="flex flex-wrap gap-2">
{weekDays.map((day) => (
<Button
key={day.value}
variant={
selectedWeekDays.includes(day.value) ? "default" : "outline"
}
className="h-10 w-10 p-0"
onClick={() => {
setSelectedWeekDays((prev) =>
prev.includes(day.value)
? prev.filter((d) => d !== day.value)
: [...prev, day.value],
);
}}
>
{day.label}
</Button>
))}
</div>
</div>
)}
{frequency === "monthly" && (
<div className="space-y-4">
<Label>Days of Month</Label>
<div className="flex gap-2">
<Button
variant={!showCustomDays ? "default" : "outline"}
onClick={() => {
setShowCustomDays(false);
setSelectedMonthDays(
Array.from({ length: 31 }, (_, i) => i + 1),
);
}}
>
All Days
</Button>
<Button
variant={showCustomDays ? "default" : "outline"}
onClick={() => {
setShowCustomDays(true);
setSelectedMonthDays([]);
}}
>
Customize
</Button>
<Button
variant="outline"
onClick={() => setSelectedMonthDays([15])}
>
15th
</Button>
<Button
variant="outline"
onClick={() => setSelectedMonthDays([31])}
>
Last Day
</Button>
</div>
{showCustomDays && (
<div className="flex flex-wrap gap-2">
{Array.from({ length: 31 }, (_, i) => (
<Button
key={i + 1}
variant={
selectedMonthDays.includes(i + 1) ? "default" : "outline"
}
className="h-10 w-10 p-0"
onClick={() => {
setSelectedMonthDays((prev) =>
prev.includes(i + 1)
? prev.filter((d) => d !== i + 1)
: [...prev, i + 1],
);
}}
>
{i + 1}
</Button>
))}
</div>
)}
</div>
)}
{frequency === "yearly" && (
<div className="space-y-4">
<Label>Months</Label>
<div className="flex gap-2">
<Button
variant="outline"
className="h-8 px-2 py-1 text-xs"
onClick={() => {
if (selectedMonths.length === months.length) {
setSelectedMonths([]);
} else {
setSelectedMonths(Array.from({ length: 12 }, (_, i) => i));
}
}}
>
{selectedMonths.length === months.length
? "Deselect All"
: "Select All"}
</Button>
</div>
<div className="flex flex-wrap gap-2">
{months.map((month, i) => {
const monthNumber = i + 1;
return (
<Button
key={i}
variant={
selectedMonths.includes(monthNumber) ? "default" : "outline"
}
className="px-2 py-1"
onClick={() => {
setSelectedMonths((prev) =>
prev.includes(monthNumber)
? prev.filter((m) => m !== monthNumber)
: [...prev, monthNumber],
);
}}
>
{month.label}
</Button>
);
})}
</div>
</div>
)}
{frequency !== "hourly" && (
<div className="flex items-center gap-4 space-y-2">
<Label className="pt-2">At</Label>
<Input
type="time"
value={selectedTime}
onChange={(e) => setSelectedTime(e.target.value)}
/>
</div>
)}
</div>
);
}