AddRowOperationItem.tsx103 lines · main
1import { useQueryClient } from '@tanstack/react-query'
2import { Undo2 } from 'lucide-react'
3import { Card, CardContent, CardHeader } from 'ui'
4
5import { formatOperationItemValue } from './OperationQueueSidePanel.utils'
6import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
7import { tableRowKeys } from '@/data/table-rows/keys'
8import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
9import { useTableEditorStateSnapshot } from '@/state/table-editor'
10import { AddRowPayload } from '@/state/table-editor-operation-queue.types'
11
12interface AddRowOperationItemProps {
13 operationId: string
14 tableId: number
15 content: AddRowPayload
16}
17
18export const AddRowOperationItem = ({
19 operationId,
20 tableId,
21 content,
22}: AddRowOperationItemProps) => {
23 const { table, rowData } = content
24 const tableSchema = table.schema
25 const tableName = table.name
26
27 const queryClient = useQueryClient()
28 const { data: project } = useSelectedProjectQuery()
29 const snap = useTableEditorStateSnapshot()
30
31 const fullTableName = `${tableSchema}.${tableName}`
32
33 // Get first 3 column values for preview
34 const columns = Object.entries(rowData).filter(([key]) => !key.startsWith('__') && key !== 'idx')
35 const previewColumns = columns.slice(0, 3)
36 const remainingCount = columns.length - previewColumns.length
37
38 const handleDelete = () => {
39 // Remove the operation from the queue
40 snap.removeOperation(operationId)
41
42 // Invalidate the query to revert the optimistic update
43 if (project) {
44 queryClient.invalidateQueries({
45 queryKey: tableRowKeys.tableRowsAndCount(project.ref, tableId),
46 })
47 }
48 }
49
50 return (
51 <Card className="overflow-hidden">
52 <CardHeader className="py-2 px-3 flex flex-row gap-2 space-y-0 items-center">
53 <div className="min-w-0 flex-1 flex items-start gap-2">
54 <div className="min-w-0 flex-1">
55 <code className="text-code-inline dark:bg-surface-300 dark:border-foreground-muted/50">
56 {fullTableName}
57 </code>
58 <div className="text-xs text-foreground mt-1 ml-0.5">
59 <span>New row</span>
60 </div>
61 </div>
62 </div>
63 <ButtonTooltip
64 type="text"
65 aria-label="Discard change"
66 className="w-7"
67 icon={<Undo2 />}
68 onClick={handleDelete}
69 tooltip={{
70 content: {
71 side: 'left',
72 align: 'end',
73 text: 'Discard change',
74 },
75 }}
76 />
77 </CardHeader>
78
79 <CardContent className="py-2 px-3 font-mono text-xs text-brand-link">
80 {previewColumns.length === 0 && (
81 <span className="text-foreground-light">
82 No data provided, default values will be used
83 </span>
84 )}
85 {previewColumns.map(([key, value]) => (
86 <div key={key} className="flex gap-2 py-0.5">
87 <span className="text-brand-link select-none font-medium">+</span>
88 <span className="shrink-0">{key}:</span>
89 <span className="truncate min-w-0" title={formatOperationItemValue(value)}>
90 {formatOperationItemValue(value)}
91 </span>
92 </div>
93 ))}
94 {remainingCount > 0 && (
95 <div className="flex gap-2 py-0.5">
96 <span className="text-brand-link select-none font-medium">+</span>
97 <span>+{remainingCount} more column(s)</span>
98 </div>
99 )}
100 </CardContent>
101 </Card>
102 )
103}