ShareSnippetModal.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { useParams } from 'common'
  2. import { Eye, Unlock } from 'lucide-react'
  3. import { toast } from 'sonner'
  4. import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
  5. import { getContentById } from '@/data/content/content-id-query'
  6. import { useContentUpsertMutation } from '@/data/content/content-upsert-mutation'
  7. import { Snippet } from '@/data/content/sql-folders-query'
  8. import { useSqlEditorV2StateSnapshot } from '@/state/sql-editor-v2'
  9. import type { SqlSnippets } from '@/types'
  10. export const ShareSnippetModal = ({
  11. snippet,
  12. onClose,
  13. onSuccess,
  14. }: {
  15. snippet?: Snippet
  16. onClose: () => void
  17. onSuccess?: () => void
  18. }) => {
  19. const { ref: projectRef } = useParams()
  20. const snapV2 = useSqlEditorV2StateSnapshot()
  21. const { mutate: upsertContent, isPending: isUpserting } = useContentUpsertMutation({
  22. onError: (error) => {
  23. toast.error(`Failed to update query: ${error.message}`)
  24. },
  25. })
  26. const onShareSnippet = async () => {
  27. if (!projectRef) return console.error('Project ref is required')
  28. if (!snippet) return console.error('Snippet ID is required')
  29. const storeSnippet = snapV2.snippets[snippet.id]
  30. let snippetContent = storeSnippet?.snippet?.content
  31. if (snippetContent === undefined) {
  32. const { content } = await getContentById({ projectRef, id: snippet.id })
  33. snippetContent = content as unknown as SqlSnippets.Content
  34. }
  35. // [Joshen] Just as a final check - to ensure that the content is minimally there (empty string is fine)
  36. if (snippetContent === undefined) {
  37. return toast.error('Unable to update snippet visibility: Content is missing')
  38. }
  39. upsertContent(
  40. {
  41. projectRef,
  42. payload: {
  43. ...snippet,
  44. visibility: 'project',
  45. folder_id: null,
  46. content: snippetContent,
  47. },
  48. },
  49. {
  50. onSuccess: () => {
  51. snapV2.updateSnippet({
  52. id: snippet.id,
  53. snippet: { visibility: 'project', folder_id: null },
  54. skipSave: true,
  55. })
  56. toast.success('Snippet is now shared to the project')
  57. onSuccess?.()
  58. onClose()
  59. },
  60. }
  61. )
  62. }
  63. return (
  64. <ConfirmationModal
  65. size="medium"
  66. loading={isUpserting}
  67. title={`Confirm to share query: ${snippet?.name}`}
  68. confirmLabel="Share query"
  69. confirmLabelLoading="Sharing query"
  70. visible={snippet !== undefined}
  71. onCancel={() => onClose()}
  72. onConfirm={() => onShareSnippet()}
  73. alert={{
  74. title: 'This SQL query will become public to all team members',
  75. description: 'Anyone with access to the project can view it',
  76. }}
  77. >
  78. <ul className="text-sm text-foreground-light space-y-5">
  79. <li className="flex gap-3 items-center">
  80. <Eye size={16} />
  81. <span>Project members will have read-only access to this query.</span>
  82. </li>
  83. <li className="flex gap-3 items-center">
  84. <Unlock size={16} />
  85. <span>Anyone will be able to duplicate it to their personal snippets.</span>
  86. </li>
  87. </ul>
  88. </ConfirmationModal>
  89. )
  90. }