MultiSelectActionBar.tsx 3.7 KB

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