MessageSelection.tsx128 lines · main
1// @ts-nocheck
2import { useParams } from 'common'
3import { X } from 'lucide-react'
4import { useMemo } from 'react'
5import { toast } from 'sonner'
6import { Button, cn, copyToClipboard } from 'ui'
7
8import type { LogData } from './Messages.types'
9import { SelectedRealtimeMessagePanel } from './SelectedRealtimeMessagePanel'
10import CopyButton from '@/components/ui/CopyButton'
11import { ShortcutTooltip } from '@/components/ui/ShortcutTooltip'
12import { useSendEventMutation } from '@/data/telemetry/send-event-mutation'
13import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
14import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
15import { useShortcut } from '@/state/shortcuts/useShortcut'
16
17export interface MessageSelectionProps {
18 log: LogData | null
19 onClose: () => void
20}
21
22const MessageSelection = ({ log, onClose }: MessageSelectionProps) => {
23 const selectionText = useMemo(() => {
24 return JSON.stringify(log, null, 2)
25 }, [log])
26
27 const { ref } = useParams()
28 const { data: org } = useSelectedOrganizationQuery()
29 const { mutate: sendEvent } = useSendEventMutation()
30
31 const handleCopy = () => {
32 if (!log) return
33 copyToClipboard(selectionText)
34 toast.success('Message copied to clipboard')
35 }
36
37 useShortcut(SHORTCUT_IDS.INSPECTOR_COPY_MESSAGE, handleCopy, {
38 enabled: !!log,
39 ignoreInputs: true,
40 registerInCommandMenu: true,
41 })
42
43 const copyButton = (
44 <CopyButton
45 text={selectionText}
46 type="default"
47 title="Copy log to clipboard"
48 onClick={() => {
49 sendEvent({
50 action: 'realtime_inspector_copy_message_clicked',
51 groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
52 })
53 }}
54 />
55 )
56
57 return (
58 <div className={cn('relative flex h-full grow flex-col border-l overflow-y-scroll bg-200')}>
59 <div
60 className={cn(
61 'absolute flex h-full w-full flex-col items-center justify-center gap-2 bg-200 text-center opacity-0 transition-all',
62 log ? 'z-0 opacity-0' : 'z-10 opacity-100'
63 )}
64 >
65 <div
66 className={cn(
67 'flex w-full max-w-sm scale-95 flex-col items-center justify-center gap-6 text-center opacity-0 transition-all delay-300 duration-500',
68 log ? 'mt-0 scale-95 opacity-0' : 'mt-8 scale-100 opacity-100'
69 )}
70 >
71 <div className="relative flex h-4 w-32 items-center rounded-sm border border-default px-2">
72 <div className="h-0.5 w-2/3 rounded-full bg-overlay-hover"></div>
73 <div className="absolute right-1 -bottom-4">
74 <svg
75 xmlns="http://www.w3.org/2000/svg"
76 className="h-6 w-6"
77 fill="none"
78 viewBox="0 0 24 24"
79 stroke="currentColor"
80 strokeWidth="1"
81 >
82 <path
83 strokeLinecap="round"
84 strokeLinejoin="round"
85 d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
86 />
87 </svg>
88 </div>
89 </div>
90 <div className="flex flex-col gap-1">
91 <h3 className="text-sm text-foreground">Select a message</h3>
92 <p className="text-xs text-foreground-lighter">
93 Click on a message on the left to view details.
94 </p>
95 </div>
96 </div>
97 </div>
98 <div className="relative h-px grow">
99 <div className="pt-4 flex flex-col gap-4">
100 <div className="px-4 flex flex-row justify-between items-center">
101 <div className="transition">
102 {log ? (
103 <ShortcutTooltip shortcutId={SHORTCUT_IDS.INSPECTOR_COPY_MESSAGE} side="bottom">
104 {copyButton}
105 </ShortcutTooltip>
106 ) : (
107 copyButton
108 )}
109 </div>
110 <Button
111 type="text"
112 className="cursor-pointer transition hover:text-scale-1200 h-8 w-8 px-0 py-0 flex items-center justify-center"
113 onClick={onClose}
114 >
115 <X size={14} strokeWidth={2} className="text-scale-900" />
116 </Button>
117 </div>
118 <div className="h-px w-full bg-scale-600 rounded-sm" />
119 </div>
120 <div className="flex flex-col space-y-6 py-4">
121 {log && <SelectedRealtimeMessagePanel log={log} />}
122 </div>
123 </div>
124 </div>
125 )
126}
127
128export default MessageSelection