InsertButton.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // @ts-nocheck
  2. import { PermissionAction } from '@supabase/shared-types/out/constants'
  3. import { useParams } from 'common'
  4. import { ArrowUp, ChevronDown, FileText } from 'lucide-react'
  5. import {
  6. Button,
  7. cn,
  8. DropdownMenu,
  9. DropdownMenuContent,
  10. DropdownMenuItem,
  11. DropdownMenuTrigger,
  12. } from 'ui'
  13. import { ShortcutBadge } from '@/components/ui/ShortcutBadge'
  14. import { useSendEventMutation } from '@/data/telemetry/send-event-mutation'
  15. import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
  16. import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
  17. import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
  18. import { useShortcut } from '@/state/shortcuts/useShortcut'
  19. import { useTableEditorStateSnapshot } from '@/state/table-editor'
  20. import { useTableEditorTableStateSnapshot } from '@/state/table-editor-table'
  21. export const InsertButton = () => {
  22. const { ref: projectRef } = useParams()
  23. const { data: org } = useSelectedOrganizationQuery()
  24. const snap = useTableEditorTableStateSnapshot()
  25. const tableEditorSnap = useTableEditorStateSnapshot()
  26. const { can: canCreateColumns } = useAsyncCheckPermissions(
  27. PermissionAction.TENANT_SQL_ADMIN_WRITE,
  28. 'columns'
  29. )
  30. const { mutate: sendEvent } = useSendEventMutation()
  31. const onAddRow =
  32. snap.editable && (snap.table.columns ?? []).length > 0 ? tableEditorSnap.onAddRow : undefined
  33. const onAddColumn = snap.editable ? tableEditorSnap.onAddColumn : undefined
  34. const onImportData = snap.editable ? tableEditorSnap.onImportData : undefined
  35. const canAddNew = onAddRow !== undefined || onAddColumn !== undefined
  36. useShortcut(SHORTCUT_IDS.TABLE_EDITOR_INSERT_ROW, () => onAddRow?.(), {
  37. registerInCommandMenu: true,
  38. enabled: onAddRow !== undefined && canAddNew && canCreateColumns,
  39. })
  40. useShortcut(SHORTCUT_IDS.TABLE_EDITOR_INSERT_COLUMN, () => onAddColumn?.(), {
  41. registerInCommandMenu: true,
  42. enabled: onAddColumn !== undefined && canAddNew && canCreateColumns,
  43. })
  44. useShortcut(SHORTCUT_IDS.TABLE_EDITOR_IMPORT_CSV, () => onImportData?.(), {
  45. registerInCommandMenu: true,
  46. enabled: onImportData !== undefined && canAddNew && canCreateColumns,
  47. })
  48. if (!canAddNew || !canCreateColumns) return null
  49. return (
  50. <DropdownMenu>
  51. <DropdownMenuTrigger asChild>
  52. <Button
  53. data-testid="table-editor-insert-new-row"
  54. type="primary"
  55. size="tiny"
  56. icon={<ChevronDown strokeWidth={1.5} />}
  57. >
  58. Insert
  59. </Button>
  60. </DropdownMenuTrigger>
  61. <DropdownMenuContent side="bottom" align="end">
  62. {[
  63. ...(onAddRow !== undefined
  64. ? [
  65. <DropdownMenuItem
  66. key="add-row"
  67. className="flex items-center group gap-x-3"
  68. onClick={onAddRow}
  69. >
  70. <div className="shrink-0 w-4">
  71. <div className="border border-foreground-lighter w-[15px] h-[4px]" />
  72. <div className="border border-foreground-lighter w-[15px] h-[4px] my-[2px]" />
  73. <div
  74. className={cn([
  75. 'border border-foreground-light w-[15px] h-[4px] translate-x-0.5',
  76. 'transition duration-200 group-data-highlighted:border-brand group-data-highlighted:translate-x-0',
  77. ])}
  78. />
  79. </div>
  80. <p className="flex-1 min-w-0 pr-4">Insert row</p>
  81. <ShortcutBadge
  82. shortcutId={SHORTCUT_IDS.TABLE_EDITOR_INSERT_ROW}
  83. className="shrink-0"
  84. />
  85. </DropdownMenuItem>,
  86. ]
  87. : []),
  88. ...(onAddColumn !== undefined
  89. ? [
  90. <DropdownMenuItem key="add-column" className="group gap-x-3" onClick={onAddColumn}>
  91. <div className="flex shrink-0 w-4">
  92. <div className="border border-foreground-lighter w-[4px] h-[15px]" />
  93. <div className="border border-foreground-lighter w-[4px] h-[15px] mx-[2px]" />
  94. <div
  95. className={cn([
  96. 'border border-foreground-light w-[4px] h-[15px] -translate-y-0.5',
  97. 'transition duration-200 group-data-highlighted:border-brand group-data-highlighted:translate-y-0',
  98. ])}
  99. />
  100. </div>
  101. <p className="flex-1 min-w-0 pr-4">Insert column</p>
  102. <ShortcutBadge
  103. shortcutId={SHORTCUT_IDS.TABLE_EDITOR_INSERT_COLUMN}
  104. className="shrink-0"
  105. />
  106. </DropdownMenuItem>,
  107. ]
  108. : []),
  109. ...(onImportData !== undefined
  110. ? [
  111. <DropdownMenuItem
  112. key="import-data"
  113. className="group gap-x-3"
  114. onClick={() => {
  115. onImportData()
  116. sendEvent({
  117. action: 'import_data_button_clicked',
  118. properties: { tableType: 'Existing Table' },
  119. groups: {
  120. project: projectRef ?? 'Unknown',
  121. organization: org?.slug ?? 'Unknown',
  122. },
  123. })
  124. }}
  125. >
  126. <div className="relative shrink-0 w-4">
  127. <FileText size={18} strokeWidth={1.5} className="translate-x-[-2px]" />
  128. <ArrowUp
  129. className={cn(
  130. 'transition duration-200 absolute bottom-0 right-0 translate-y-1 opacity-0 bg-brand-400 rounded-full',
  131. 'group-data-highlighted:translate-y-0 group-data-highlighted:text-brand group-data-highlighted:opacity-100'
  132. )}
  133. strokeWidth={3}
  134. size={12}
  135. />
  136. </div>
  137. <p className="flex-1 min-w-0 pr-4">Import data from CSV</p>
  138. <ShortcutBadge
  139. shortcutId={SHORTCUT_IDS.TABLE_EDITOR_IMPORT_CSV}
  140. className="shrink-0"
  141. />
  142. </DropdownMenuItem>,
  143. ]
  144. : []),
  145. ]}
  146. </DropdownMenuContent>
  147. </DropdownMenu>
  148. )
  149. }