index.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // @ts-nocheck
  2. import { useParams } from 'common'
  3. import { useCallback, useEffect, useState } from 'react'
  4. import { EmptyRealtime } from './EmptyRealtime'
  5. import { Header } from './Header'
  6. import MessagesTable from './MessagesTable'
  7. import { SendMessageModal } from './SendMessageModal'
  8. import { useRealtimeInspectorShortcuts } from './useRealtimeInspectorShortcuts'
  9. import { RealtimeConfig, useRealtimeMessages } from './useRealtimeMessages'
  10. import { useDatabasePublicationsQuery } from '@/data/database-publications/database-publications-query'
  11. import { useSendEventMutation } from '@/data/telemetry/send-event-mutation'
  12. import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
  13. import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
  14. /**
  15. * Acts as a container component for the entire log display
  16. */
  17. export const RealtimeInspector = () => {
  18. const { ref } = useParams()
  19. const { data: org } = useSelectedOrganizationQuery()
  20. const { data: project } = useSelectedProjectQuery()
  21. // Check if realtime publications are available
  22. const { data: publications } = useDatabasePublicationsQuery({
  23. projectRef: project?.ref,
  24. connectionString: project?.connectionString,
  25. })
  26. const realtimePublication = (publications ?? []).find(
  27. (publication) => publication.name === 'briven_realtime'
  28. )
  29. const isRealtimeAvailable =
  30. !!realtimePublication &&
  31. ((realtimePublication?.tables ?? []).length > 0 || realtimePublication?.tables === null)
  32. const [sendMessageShown, setSendMessageShown] = useState(false)
  33. const [channelPopoverOpen, setChannelPopoverOpen] = useState(false)
  34. const [filterPopoverOpen, setFilterPopoverOpen] = useState(false)
  35. const [realtimeConfig, setRealtimeConfig] = useState<RealtimeConfig>({
  36. enabled: false,
  37. projectRef: ref!,
  38. channelName: '',
  39. logLevel: 'info',
  40. token: '', // will be filled out by RealtimeTokensPopover
  41. schema: 'public',
  42. table: '*',
  43. isChannelPrivate: false,
  44. filter: undefined,
  45. bearer: null,
  46. enablePresence: true,
  47. enableDbChanges: isRealtimeAvailable, // Initialize based on publications availability
  48. enableBroadcast: true,
  49. })
  50. const { mutate: sendEvent } = useSendEventMutation()
  51. const { logData, sendMessage } = useRealtimeMessages(realtimeConfig, setRealtimeConfig)
  52. const hasChannel = realtimeConfig.channelName.length > 0
  53. const isListening = realtimeConfig.enabled
  54. const handleJoinChannel = useCallback(() => {
  55. if (!hasChannel) {
  56. setChannelPopoverOpen(true)
  57. }
  58. }, [hasChannel])
  59. const handleToggleFilters = useCallback(() => {
  60. if (hasChannel) {
  61. setFilterPopoverOpen(true)
  62. }
  63. }, [hasChannel])
  64. const handleBroadcast = useCallback(() => {
  65. if (isListening) {
  66. setSendMessageShown(true)
  67. }
  68. }, [isListening])
  69. useRealtimeInspectorShortcuts({
  70. hasChannel,
  71. isListening,
  72. onJoinChannel: handleJoinChannel,
  73. onToggleFilters: handleToggleFilters,
  74. onBroadcast: handleBroadcast,
  75. })
  76. // Update enableDbChanges when publications change
  77. useEffect(() => {
  78. setRealtimeConfig((prev) => ({ ...prev, enableDbChanges: isRealtimeAvailable }))
  79. }, [isRealtimeAvailable])
  80. return (
  81. <div className="flex flex-col grow h-full">
  82. <Header
  83. config={realtimeConfig}
  84. onChangeConfig={setRealtimeConfig}
  85. channelPopoverOpen={channelPopoverOpen}
  86. onChannelPopoverChange={setChannelPopoverOpen}
  87. filterPopoverOpen={filterPopoverOpen}
  88. onFilterPopoverChange={setFilterPopoverOpen}
  89. />
  90. <div className="relative flex flex-col grow">
  91. <div className="flex grow">
  92. {(logData ?? []).length > 0 ? (
  93. <MessagesTable
  94. hasChannelSet={hasChannel}
  95. enabled={isListening}
  96. data={logData}
  97. showSendMessage={() => setSendMessageShown(true)}
  98. />
  99. ) : (
  100. <EmptyRealtime projectRef={ref!} />
  101. )}
  102. </div>
  103. </div>
  104. <SendMessageModal
  105. visible={sendMessageShown}
  106. onSelectCancel={() => setSendMessageShown(false)}
  107. onSelectConfirm={(v) => {
  108. sendEvent({
  109. action: 'realtime_inspector_broadcast_sent',
  110. groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
  111. })
  112. sendMessage(v.message, v.payload, () => setSendMessageShown(false))
  113. }}
  114. />
  115. </div>
  116. )
  117. }