CreateQueueSheet.tsx161 lines · main
1import { zodResolver } from '@hookform/resolvers/zod'
2import { useRouter } from 'next/router'
3import { useEffect, useMemo } from 'react'
4import { SubmitHandler, useForm } from 'react-hook-form'
5import { toast } from 'sonner'
6import {
7 Button,
8 Form,
9 Separator,
10 Sheet,
11 SheetContent,
12 SheetFooter,
13 SheetHeader,
14 SheetTitle,
15} from 'ui'
16
17import { usePgPartmanStatus } from '../usePgPartmanStatus'
18import { CreateQueueForm, FormSchema } from './CreateQueueSheet.schema'
19import { PartitionConfigFields } from './PartitionConfigFields'
20import { PgPartmanCallout } from './PgPartmanCallout'
21import { QueueNameField } from './QueueNameField'
22import { QueueTypeSelector } from './QueueTypeSelector'
23import { RlsSection } from './RlsSection'
24import { DiscardChangesConfirmationDialog } from '@/components/ui-patterns/Dialogs/DiscardChangesConfirmationDialog'
25import { useDatabaseQueueCreateMutation } from '@/data/database-queues/database-queues-create-mutation'
26import { useQueuesExposePostgrestStatusQuery } from '@/data/database-queues/database-queues-expose-postgrest-status-query'
27import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
28import { useConfirmOnClose } from '@/hooks/ui/useConfirmOnClose'
29
30export interface CreateQueueSheetProps {
31 visible: boolean
32 onClose: () => void
33}
34
35const FORM_ID = 'create-queue-sidepanel'
36
37export const CreateQueueSheet = ({ visible, onClose }: CreateQueueSheetProps) => {
38 const router = useRouter()
39 const { data: project } = useSelectedProjectQuery()
40
41 const { data: isExposed } = useQueuesExposePostgrestStatusQuery({
42 projectRef: project?.ref,
43 connectionString: project?.connectionString,
44 })
45
46 const { mutate: createQueue, isPending } = useDatabaseQueueCreateMutation()
47 const { isInstalled: pgPartmanInstalled } = usePgPartmanStatus()
48
49 const defaultValues: CreateQueueForm = useMemo(
50 () =>
51 pgPartmanInstalled
52 ? {
53 name: '',
54 enableRls: true,
55 values: { type: 'partitioned', partitionInterval: 10000, retentionInterval: 100000 },
56 }
57 : { name: '', enableRls: true, values: { type: 'basic' } },
58 [pgPartmanInstalled]
59 )
60
61 const form = useForm<CreateQueueForm>({
62 resolver: zodResolver(FormSchema as any),
63 defaultValues,
64 })
65
66 useEffect(() => {
67 if (visible) {
68 form.reset(defaultValues)
69 }
70 }, [form, defaultValues, visible])
71
72 const checkIsDirty = () => form.formState.isDirty
73
74 const { confirmOnClose, handleOpenChange, modalProps } = useConfirmOnClose({
75 checkIsDirty,
76 onClose,
77 })
78
79 const onSubmit: SubmitHandler<CreateQueueForm> = async ({ name, enableRls, values }) => {
80 if (!project?.ref) {
81 toast.error('Project not found')
82 return
83 }
84
85 createQueue(
86 {
87 projectRef: project.ref,
88 connectionString: project?.connectionString,
89 name,
90 enableRls,
91 type: values.type,
92 configuration:
93 values.type === 'partitioned'
94 ? {
95 partitionInterval: values.partitionInterval,
96 retentionInterval: values.retentionInterval,
97 }
98 : undefined,
99 },
100 {
101 onSuccess: () => {
102 toast.success(`Successfully created queue ${name}`)
103 router.push(`/project/${project?.ref}/integrations/queues/queues/${name}`)
104 onClose()
105 },
106 }
107 )
108 }
109
110 return (
111 <Sheet open={visible} onOpenChange={handleOpenChange}>
112 <SheetContent size="default" className="w-[35%]" tabIndex={undefined}>
113 <div className="flex flex-col h-full" tabIndex={-1}>
114 <SheetHeader>
115 <SheetTitle>Create a new queue</SheetTitle>
116 </SheetHeader>
117
118 <div className="overflow-auto grow">
119 <Form {...form}>
120 <form
121 id={FORM_ID}
122 className="grow overflow-auto"
123 onSubmit={form.handleSubmit(onSubmit)}
124 >
125 <QueueNameField form={form} />
126 <Separator />
127 <PgPartmanCallout />
128 <QueueTypeSelector form={form} />
129 <Separator />
130 <PartitionConfigFields form={form} />
131 <RlsSection form={form} isExposed={isExposed} projectRef={project?.ref} />
132 </form>
133 </Form>
134 </div>
135 <SheetFooter>
136 <Button
137 size="tiny"
138 type="default"
139 htmlType="button"
140 onClick={confirmOnClose}
141 disabled={isPending}
142 >
143 Cancel
144 </Button>
145 <Button
146 size="tiny"
147 type="primary"
148 form={FORM_ID}
149 htmlType="submit"
150 loading={isPending}
151 disabled={!project?.ref}
152 >
153 Create queue
154 </Button>
155 </SheetFooter>
156 </div>
157 <DiscardChangesConfirmationDialog {...modalProps} />
158 </SheetContent>
159 </Sheet>
160 )
161}