Enhance schedule management with shell type selection

- Added a new `shellType` field to the schedule form, allowing users to select between 'bash' and 'sh' for command execution.
- Updated the `HandleSchedules` component to include the `shellType` in the form and reset logic.
- Modified the `ShowSchedules` component to display the selected shell type for each schedule.
- Ensured proper handling of the new field in the API for schedule creation and updates.
This commit is contained in:
Mauricio Siu
2025-05-02 16:00:05 -06:00
parent 2c90103823
commit fafa14c10a
2 changed files with 54 additions and 12 deletions

View File

@@ -51,6 +51,7 @@ const commonCronExpressions = [
const formSchema = z.object({ const formSchema = z.object({
name: z.string().min(1, "Name is required"), name: z.string().min(1, "Name is required"),
cronExpression: z.string().min(1, "Cron expression is required"), cronExpression: z.string().min(1, "Cron expression is required"),
shellType: z.enum(["bash", "sh"]).default("bash"),
command: z.string().min(1, "Command is required"), command: z.string().min(1, "Command is required"),
enabled: z.boolean().default(true), enabled: z.boolean().default(true),
}); });
@@ -68,6 +69,7 @@ export const HandleSchedules = ({ applicationId, scheduleId }: Props) => {
defaultValues: { defaultValues: {
name: "", name: "",
cronExpression: "", cronExpression: "",
shellType: "bash",
command: "", command: "",
enabled: true, enabled: true,
}, },
@@ -79,25 +81,28 @@ export const HandleSchedules = ({ applicationId, scheduleId }: Props) => {
); );
useEffect(() => { useEffect(() => {
if (scheduleId) { if (scheduleId && schedule) {
form.reset({ form.reset({
name: schedule?.name, name: schedule.name,
cronExpression: schedule?.cronExpression, cronExpression: schedule.cronExpression,
command: schedule?.command, shellType: schedule.shellType,
enabled: schedule?.enabled, command: schedule.command,
enabled: schedule.enabled,
}); });
} }
}, [form, form.reset, schedule]); }, [form, schedule, scheduleId]);
const { mutateAsync, isLoading } = scheduleId const { mutateAsync, isLoading } = scheduleId
? api.schedule.update.useMutation() ? api.schedule.update.useMutation()
: api.schedule.create.useMutation(); : api.schedule.create.useMutation();
const onSubmit = async (values: z.infer<typeof formSchema>) => { const onSubmit = async (values: z.infer<typeof formSchema>) => {
if (!applicationId && !scheduleId) return;
await mutateAsync({ await mutateAsync({
...values, ...values,
...(scheduleId && { scheduleId }), scheduleId: scheduleId || "",
...(applicationId && { applicationId }), applicationId: applicationId || "",
}) })
.then(() => { .then(() => {
toast.success( toast.success(
@@ -120,19 +125,18 @@ export const HandleSchedules = ({ applicationId, scheduleId }: Props) => {
<Button <Button
variant="ghost" variant="ghost"
size="icon" size="icon"
className="group hover:bg-blue-500/10 " className="group hover:bg-blue-500/10"
> >
<PenBoxIcon className="size-3.5 text-primary group-hover:text-blue-500" /> <PenBoxIcon className="size-3.5 text-primary group-hover:text-blue-500" />
</Button> </Button>
) : ( ) : (
<Button> <Button>
<PlusCircle className="w-4 h-4" /> <PlusCircle className="w-4 h-4 mr-2" />
Add Schedule Add Schedule
</Button> </Button>
)} )}
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>
{scheduleId}
<DialogHeader> <DialogHeader>
<DialogTitle>{scheduleId ? "Edit" : "Create"} Schedule</DialogTitle> <DialogTitle>{scheduleId ? "Edit" : "Create"} Schedule</DialogTitle>
</DialogHeader> </DialogHeader>
@@ -214,6 +218,37 @@ export const HandleSchedules = ({ applicationId, scheduleId }: Props) => {
)} )}
/> />
<FormField
control={form.control}
name="shellType"
render={({ field }) => (
<FormItem>
<FormLabel className="flex items-center gap-2">
<Terminal className="w-4 h-4" />
Shell Type
</FormLabel>
<Select
onValueChange={field.onChange}
defaultValue={field.value}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select shell type" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="bash">Bash</SelectItem>
<SelectItem value="sh">Sh</SelectItem>
</SelectContent>
</Select>
<FormDescription>
Choose the shell to execute your command
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField <FormField
control={form.control} control={form.control}
name="command" name="command"
@@ -252,6 +287,7 @@ export const HandleSchedules = ({ applicationId, scheduleId }: Props) => {
</FormItem> </FormItem>
)} )}
/> />
<Button type="submit" disabled={isLoading} className="w-full"> <Button type="submit" disabled={isLoading} className="w-full">
{isLoading ? ( {isLoading ? (
<> <>

View File

@@ -68,6 +68,7 @@ export const ShowSchedules = ({ applicationId }: Props) => {
<TableRow> <TableRow>
<TableHead>Task Name</TableHead> <TableHead>Task Name</TableHead>
<TableHead>Schedule</TableHead> <TableHead>Schedule</TableHead>
<TableHead>Shell</TableHead>
<TableHead>Command</TableHead> <TableHead>Command</TableHead>
<TableHead>Status</TableHead> <TableHead>Status</TableHead>
<TableHead className="text-right">Actions</TableHead> <TableHead className="text-right">Actions</TableHead>
@@ -87,6 +88,11 @@ export const ShowSchedules = ({ applicationId }: Props) => {
{schedule.cronExpression} {schedule.cronExpression}
</Badge> </Badge>
</TableCell> </TableCell>
<TableCell>
<Badge variant="secondary" className="font-mono">
{schedule.shellType}
</Badge>
</TableCell>
<TableCell> <TableCell>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Terminal className="w-4 h-4 text-muted-foreground" /> <Terminal className="w-4 h-4 text-muted-foreground" />