SQLTemplates.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // @ts-nocheck
  2. import { PermissionAction } from '@supabase/shared-types/out/constants'
  3. import { useParams } from 'common'
  4. import { partition } from 'lodash'
  5. import { useRouter } from 'next/router'
  6. import { toast } from 'sonner'
  7. import { cn, SQL_ICON } from 'ui'
  8. import { createSqlSnippetSkeletonV2 } from '../SQLEditor.utils'
  9. import { SQL_TEMPLATES } from '@/components/interfaces/SQLEditor/SQLEditor.queries'
  10. import { ActionCard } from '@/components/layouts/Tabs/ActionCard'
  11. import { useSendEventMutation } from '@/data/telemetry/send-event-mutation'
  12. import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
  13. import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
  14. import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
  15. import { useProfile } from '@/lib/profile'
  16. import { useSqlEditorV2StateSnapshot } from '@/state/sql-editor-v2'
  17. const SQLTemplates = () => {
  18. const router = useRouter()
  19. const { ref } = useParams()
  20. const { profile } = useProfile()
  21. const { data: project } = useSelectedProjectQuery()
  22. const { data: org } = useSelectedOrganizationQuery()
  23. const [sql] = partition(SQL_TEMPLATES, { type: 'template' })
  24. const snapV2 = useSqlEditorV2StateSnapshot()
  25. const { can: canCreateSQLSnippet } = useAsyncCheckPermissions(
  26. PermissionAction.CREATE,
  27. 'user_content',
  28. {
  29. resource: { type: 'sql', owner_id: profile?.id },
  30. subject: { id: profile?.id },
  31. }
  32. )
  33. const { mutate: sendEvent } = useSendEventMutation()
  34. const handleNewQuery = async (sql: string, name: string) => {
  35. if (!ref) return console.error('Project ref is required')
  36. if (!project) return console.error('Project is required')
  37. if (!profile) return console.error('Profile is required')
  38. if (!canCreateSQLSnippet) {
  39. return toast('Your queries will not be saved as you do not have sufficient permissions')
  40. }
  41. try {
  42. const snippet = createSqlSnippetSkeletonV2({
  43. name,
  44. sql,
  45. owner_id: profile?.id,
  46. project_id: project?.id,
  47. })
  48. snapV2.addSnippet({ projectRef: ref, snippet })
  49. snapV2.addNeedsSaving(snippet.id)
  50. router.push(`/project/${ref}/sql/${snippet.id}`)
  51. } catch (error: any) {
  52. toast.error(`Failed to create new query: ${error.message}`)
  53. }
  54. }
  55. return (
  56. <div className="block h-full space-y-8 overflow-y-auto p-6 px-10 bg-dash-sidebar dark:bg-surface-100">
  57. <div>
  58. <div className="mb-6">
  59. <h2 className="mb-1">Scripts</h2>
  60. <p className="text-foreground-light text-sm">Quick scripts to run on your database.</p>
  61. <p className="text-foreground-light text-sm">
  62. Click on any script to fill the query box, modify the script, then click
  63. <span className="text-code">Run</span>.
  64. </p>
  65. </div>
  66. <div className="grid gap-4 sm:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 ">
  67. {sql.map((x, i) => (
  68. <ActionCard
  69. key={`action-card-${i}`}
  70. title={x.title}
  71. description={x.description}
  72. bgColor="bg-alternative border"
  73. icon={<SQL_ICON className={cn('fill-foreground', 'w-4 h-4')} strokeWidth={1.5} />}
  74. onClick={() => {
  75. handleNewQuery(x.sql, x.title)
  76. sendEvent({
  77. action: 'sql_editor_template_clicked',
  78. properties: { templateName: x.title },
  79. groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
  80. })
  81. }}
  82. />
  83. ))}
  84. </div>
  85. </div>
  86. </div>
  87. )
  88. }
  89. export default SQLTemplates