MultiSelectActionBar.tsx109 lines · main
1import { Check, ChevronDown, Copy, X as XIcon } from 'lucide-react'
2import {
3 Button,
4 DropdownMenu,
5 DropdownMenuContent,
6 DropdownMenuItem,
7 DropdownMenuTrigger,
8} from 'ui'
9
10import type { LogData, QueryType } from './Logs.types'
11import { buildLogsPrompt } from './Logs.utils'
12import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
13import { AiAssistantDropdown } from '@/components/ui/AiAssistantDropdown'
14import { ShortcutBadge } from '@/components/ui/ShortcutBadge'
15import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state'
16import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
17import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
18
19export type LogCopyFormat = 'json' | 'markdown' | 'csv'
20
21interface MultiSelectActionBarProps {
22 selectedRows: Set<string>
23 selectedRowsData: LogData[]
24 copiedFormat: LogCopyFormat | null
25 onCopy: (format: LogCopyFormat) => void
26 onClear: () => void
27 queryType?: QueryType
28 sqlQuery?: string
29}
30
31export function MultiSelectActionBar({
32 selectedRows,
33 selectedRowsData,
34 copiedFormat,
35 onCopy,
36 onClear,
37 queryType,
38 sqlQuery,
39}: MultiSelectActionBarProps) {
40 const { openSidebar } = useSidebarManagerSnapshot()
41 const aiSnap = useAiAssistantStateSnapshot()
42
43 function handleOpenAiAssistant() {
44 const prompt = buildLogsPrompt(selectedRowsData, queryType, sqlQuery)
45 openSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
46 aiSnap.newChat({ initialMessage: prompt })
47 }
48 const count = selectedRows.size
49 if (count === 0) return null
50
51 return (
52 <div
53 className="flex items-center gap-2 px-3 py-1.5 border-b bg-surface-200 text-sm sticky top-0 z-10"
54 style={{ height: 40 }}
55 >
56 <span className="text-foreground-light font-mono text-xs">
57 {count} row{count !== 1 ? 's' : ''} selected
58 </span>
59
60 <div className="flex items-center gap-1 ml-auto">
61 <DropdownMenu>
62 <DropdownMenuTrigger asChild>
63 <Button
64 type="default"
65 size="tiny"
66 icon={copiedFormat ? <Check size={12} className="text-brand" /> : <Copy size={12} />}
67 iconRight={<ChevronDown size={11} />}
68 >
69 {copiedFormat ? 'Copied!' : 'Copy'}
70 </Button>
71 </DropdownMenuTrigger>
72 <DropdownMenuContent align="end" className="w-60">
73 <DropdownMenuItem onClick={() => onCopy('json')} className="gap-x-2">
74 <Copy size={13} />
75 <p>Copy as JSON</p>
76 <ShortcutBadge shortcutId={SHORTCUT_IDS.RESULTS_COPY_JSON} className="ml-auto" />
77 </DropdownMenuItem>
78 <DropdownMenuItem onClick={() => onCopy('markdown')} className="gap-x-2">
79 <Copy size={13} />
80 <p>Copy as Markdown</p>
81 <ShortcutBadge shortcutId={SHORTCUT_IDS.RESULTS_COPY_MARKDOWN} className="ml-auto" />
82 </DropdownMenuItem>
83 <DropdownMenuItem onClick={() => onCopy('csv')} className="gap-x-2">
84 <Copy size={13} />
85 <p>Copy as CSV</p>
86 <ShortcutBadge shortcutId={SHORTCUT_IDS.RESULTS_COPY_CSV} className="ml-auto" />
87 </DropdownMenuItem>
88 </DropdownMenuContent>
89 </DropdownMenu>
90
91 <AiAssistantDropdown
92 label="Explain with AI"
93 buildPrompt={() => buildLogsPrompt(selectedRowsData, queryType, sqlQuery)}
94 onOpenAssistant={handleOpenAiAssistant}
95 telemetrySource="log_explorer"
96 />
97
98 <Button
99 type="text"
100 size="tiny"
101 icon={<XIcon size={12} />}
102 onClick={onClear}
103 title="Clear selection"
104 className="text-foreground-lighter px-1.5 hover:text-foreground"
105 />
106 </div>
107 </div>
108 )
109}