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