Skip to content

Commit db97de2

Browse files
authored
Merge pull request #3255 from odedd/feat/all-timezones-support
feat(schedules): add support for all IANA timezones
2 parents dc7af1b + c045c53 commit db97de2

File tree

2 files changed

+529
-43
lines changed

2 files changed

+529
-43
lines changed

apps/dokploy/components/dashboard/application/schedules/handle-schedules.tsx

Lines changed: 71 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { zodResolver } from "@hookform/resolvers/zod";
22
import {
3+
CheckIcon,
4+
ChevronsUpDown,
35
DatabaseZap,
46
Info,
57
PenBoxIcon,
@@ -13,6 +15,14 @@ import { z } from "zod";
1315
import { AlertBlock } from "@/components/shared/alert-block";
1416
import { CodeEditor } from "@/components/shared/code-editor";
1517
import { Button } from "@/components/ui/button";
18+
import {
19+
Command,
20+
CommandEmpty,
21+
CommandGroup,
22+
CommandInput,
23+
CommandItem,
24+
CommandList,
25+
} from "@/components/ui/command";
1626
import {
1727
Dialog,
1828
DialogContent,
@@ -31,6 +41,12 @@ import {
3141
FormMessage,
3242
} from "@/components/ui/form";
3343
import { Input } from "@/components/ui/input";
44+
import {
45+
Popover,
46+
PopoverContent,
47+
PopoverTrigger,
48+
} from "@/components/ui/popover";
49+
import { ScrollArea } from "@/components/ui/scroll-area";
3450
import {
3551
Select,
3652
SelectContent,
@@ -48,6 +64,7 @@ import {
4864
import { cn } from "@/lib/utils";
4965
import { api } from "@/utils/api";
5066
import type { CacheType } from "../domains/handle-domain";
67+
import { getTimezoneLabel, TIMEZONES } from "./timezones";
5168

5269
export const commonCronExpressions = [
5370
{ label: "Every minute", value: "* * * * *" },
@@ -60,30 +77,6 @@ export const commonCronExpressions = [
6077
{ label: "Custom", value: "custom" },
6178
];
6279

63-
export const commonTimezones = [
64-
{ label: "UTC (Coordinated Universal Time)", value: "UTC" },
65-
{ label: "America/New_York (Eastern Time)", value: "America/New_York" },
66-
{ label: "America/Chicago (Central Time)", value: "America/Chicago" },
67-
{ label: "America/Denver (Mountain Time)", value: "America/Denver" },
68-
{ label: "America/Los_Angeles (Pacific Time)", value: "America/Los_Angeles" },
69-
{
70-
label: "America/Mexico_City (Central Mexico)",
71-
value: "America/Mexico_City",
72-
},
73-
{ label: "America/Sao_Paulo (Brasilia Time)", value: "America/Sao_Paulo" },
74-
{ label: "Europe/London (Greenwich Mean Time)", value: "Europe/London" },
75-
{ label: "Europe/Paris (Central European Time)", value: "Europe/Paris" },
76-
{ label: "Europe/Berlin (Central European Time)", value: "Europe/Berlin" },
77-
{ label: "Asia/Tokyo (Japan Standard Time)", value: "Asia/Tokyo" },
78-
{ label: "Asia/Shanghai (China Standard Time)", value: "Asia/Shanghai" },
79-
{ label: "Asia/Dubai (Gulf Standard Time)", value: "Asia/Dubai" },
80-
{ label: "Asia/Kolkata (India Standard Time)", value: "Asia/Kolkata" },
81-
{
82-
label: "Australia/Sydney (Australian Eastern Time)",
83-
value: "Australia/Sydney",
84-
},
85-
];
86-
8780
const formSchema = z
8881
.object({
8982
name: z.string().min(1, "Name is required"),
@@ -512,25 +505,60 @@ export const HandleSchedules = ({ id, scheduleId, scheduleType }: Props) => {
512505
</Tooltip>
513506
</TooltipProvider>
514507
</FormLabel>
515-
<Select
516-
onValueChange={(value) => {
517-
field.onChange(value);
518-
}}
519-
value={field.value}
520-
>
521-
<FormControl>
522-
<SelectTrigger>
523-
<SelectValue placeholder="UTC (default)" />
524-
</SelectTrigger>
525-
</FormControl>
526-
<SelectContent>
527-
{commonTimezones.map((tz) => (
528-
<SelectItem key={tz.value} value={tz.value}>
529-
{tz.label}
530-
</SelectItem>
531-
))}
532-
</SelectContent>
533-
</Select>
508+
<Popover>
509+
<PopoverTrigger asChild>
510+
<FormControl>
511+
<Button
512+
variant="outline"
513+
className={cn(
514+
"w-full justify-between !bg-input",
515+
!field.value && "text-muted-foreground",
516+
)}
517+
>
518+
{getTimezoneLabel(field.value)}
519+
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
520+
</Button>
521+
</FormControl>
522+
</PopoverTrigger>
523+
<PopoverContent className="w-[400px] p-0" align="start">
524+
<Command>
525+
<CommandInput
526+
placeholder="Search timezone..."
527+
className="h-9"
528+
/>
529+
<CommandList>
530+
<CommandEmpty>No timezone found.</CommandEmpty>
531+
<ScrollArea className="h-72">
532+
{Object.entries(TIMEZONES).map(
533+
([region, zones]) => (
534+
<CommandGroup key={region} heading={region}>
535+
{zones.map((tz) => (
536+
<CommandItem
537+
key={tz.value}
538+
value={`${region} ${tz.label} ${tz.value}`}
539+
onSelect={() => {
540+
field.onChange(tz.value);
541+
}}
542+
>
543+
{tz.value}
544+
<CheckIcon
545+
className={cn(
546+
"ml-auto h-4 w-4",
547+
field.value === tz.value
548+
? "opacity-100"
549+
: "opacity-0",
550+
)}
551+
/>
552+
</CommandItem>
553+
))}
554+
</CommandGroup>
555+
),
556+
)}
557+
</ScrollArea>
558+
</CommandList>
559+
</Command>
560+
</PopoverContent>
561+
</Popover>
534562
<FormDescription>
535563
Optional: Choose a timezone for the schedule execution time
536564
</FormDescription>

0 commit comments

Comments
 (0)