RealtimeToggleDialog.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import { useParams } from 'common'
  2. import { toast } from 'sonner'
  3. import {
  4. Button,
  5. Dialog,
  6. DialogContent,
  7. DialogFooter,
  8. DialogHeader,
  9. DialogSection,
  10. DialogSectionSeparator,
  11. DialogTitle,
  12. } from 'ui'
  13. import { InlineLink } from '@/components/ui/InlineLink'
  14. import { useDatabasePublicationsQuery } from '@/data/database-publications/database-publications-query'
  15. import { useDatabasePublicationUpdateMutation } from '@/data/database-publications/database-publications-update-mutation'
  16. import { Entity } from '@/data/table-editor/table-editor-types'
  17. import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
  18. import { useTrack } from '@/lib/telemetry/track'
  19. export const RealtimeToggleDialog = ({
  20. table,
  21. open,
  22. setOpen,
  23. }: {
  24. table: Entity
  25. open: boolean
  26. setOpen: (value: boolean) => void
  27. }) => {
  28. const track = useTrack()
  29. const { ref } = useParams()
  30. const { data: project } = useSelectedProjectQuery()
  31. const { data: publications } = useDatabasePublicationsQuery({
  32. projectRef: project?.ref,
  33. connectionString: project?.connectionString,
  34. })
  35. const realtimePublication = (publications ?? []).find(
  36. (publication) => publication.name === 'briven_realtime'
  37. )
  38. const realtimeEnabledTables = realtimePublication?.tables ?? []
  39. const isRealtimeEnabled = realtimeEnabledTables.some((t) => t.id === table?.id)
  40. const { mutate: updatePublications, isPending: isTogglingRealtime } =
  41. useDatabasePublicationUpdateMutation({
  42. onSuccess: () => {
  43. setOpen(false)
  44. track(isRealtimeEnabled ? 'table_realtime_disabled' : 'table_realtime_enabled', {
  45. method: 'ui',
  46. schema_name: table.schema,
  47. table_name: table.name,
  48. })
  49. },
  50. onError: (error) => {
  51. toast.error(`Failed to toggle realtime for ${table.name}: ${error.message}`)
  52. },
  53. })
  54. const toggleRealtime = async () => {
  55. if (!project || !realtimePublication) return
  56. const exists = realtimeEnabledTables.some((x) => x.id === table.id)
  57. const tables = !exists
  58. ? [`${table.schema}.${table.name}`].concat(
  59. realtimeEnabledTables.map((t) => `${t.schema}.${t.name}`)
  60. )
  61. : realtimeEnabledTables.filter((x) => x.id !== table.id).map((x) => `${x.schema}.${x.name}`)
  62. track('realtime_toggle_table_clicked', {
  63. newState: exists ? 'disabled' : 'enabled',
  64. origin: 'tableGridHeader',
  65. })
  66. updatePublications({
  67. projectRef: project?.ref,
  68. connectionString: project?.connectionString,
  69. id: realtimePublication.id,
  70. tables,
  71. })
  72. }
  73. return (
  74. <Dialog open={open} onOpenChange={setOpen}>
  75. <DialogContent size="small" aria-describedby={undefined}>
  76. <DialogHeader>
  77. <DialogTitle>
  78. {isRealtimeEnabled ? 'Disable' : 'Enable'} realtime for {table.name}
  79. </DialogTitle>
  80. </DialogHeader>
  81. <DialogSectionSeparator />
  82. <DialogSection>
  83. <div className="space-y-2">
  84. <p className="text-sm">
  85. Once realtime has been {isRealtimeEnabled ? 'disabled' : 'enabled'}, the table will{' '}
  86. {isRealtimeEnabled ? 'no longer ' : ''}broadcast any changes to authorized
  87. subscribers.
  88. </p>
  89. {!isRealtimeEnabled && (
  90. <p className="text-sm">
  91. You may also select which events to broadcast to subscribers on the{' '}
  92. <InlineLink href={`/project/${ref}/database/publications`}>
  93. database publications
  94. </InlineLink>{' '}
  95. settings.
  96. </p>
  97. )}
  98. </div>
  99. </DialogSection>
  100. <DialogFooter>
  101. <Button type="default" disabled={isTogglingRealtime} onClick={() => setOpen(false)}>
  102. Cancel
  103. </Button>
  104. <Button type="primary" loading={isTogglingRealtime} onClick={toggleRealtime}>
  105. {isRealtimeEnabled ? 'Disable' : 'Enable'} realtime
  106. </Button>
  107. </DialogFooter>
  108. </DialogContent>
  109. </Dialog>
  110. )
  111. }