CreateQueueSheet.tsx 4.9 KB

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