DownloadSnippetModal.tsx133 lines · main
1import type { ModalProps } from '@ui/components/Modal/Modal'
2import { snakeCase } from 'lodash'
3import { ExternalLink } from 'lucide-react'
4import Link from 'next/link'
5import { useState } from 'react'
6import { Button, Modal, Tabs } from 'ui'
7import { CodeBlock } from 'ui-patterns/CodeBlock'
8
9import { Markdown } from '../Markdown'
10import {
11 generateFileCliCommand,
12 generateMigrationCliCommand,
13 generateSeedCliCommand,
14} from './SQLEditor.utils'
15import { TwoOptionToggle } from '@/components/ui/TwoOptionToggle'
16import { DOCS_URL } from '@/lib/constants'
17import { useSqlEditorV2StateSnapshot } from '@/state/sql-editor-v2'
18
19export interface DownloadSnippetModalProps extends ModalProps {
20 id: string
21}
22
23const DownloadSnippetModal = ({ id, ...props }: DownloadSnippetModalProps) => {
24 const snapV2 = useSqlEditorV2StateSnapshot()
25
26 const snippet = snapV2.snippets[id]?.snippet
27 const migrationName = snakeCase(snippet?.name)
28
29 const [selectedView, setSelectedView] = useState<'CLI' | 'NPM'>('CLI')
30
31 const SNIPPETS = [
32 {
33 id: 'migration',
34 label: 'Migration',
35 title: 'Download as migration',
36 description: `Download the snippet in a new migration named \`${migrationName}\``,
37 cli: generateMigrationCliCommand(id, migrationName),
38 npm: generateMigrationCliCommand(id, migrationName, true),
39 },
40 {
41 id: 'seed',
42 label: 'Seed file',
43 title: 'Download as seed file',
44 description:
45 'If your query consists of sample data, append the snippet to the end of `briven/seed.sql`',
46 cli: generateSeedCliCommand(id),
47 npm: generateSeedCliCommand(id, true),
48 },
49 {
50 id: 'sql',
51 label: 'SQL file',
52 title: 'Download as SQL file',
53 description: `Download the snippet directly into a new SQL file named \`${migrationName}.sql\``,
54 cli: generateFileCliCommand(id, migrationName),
55 npm: generateFileCliCommand(id, migrationName, true),
56 },
57 ]
58
59 return (
60 <Modal
61 hideFooter
62 showCloseButton
63 size="xlarge"
64 header={<p>Download snippet as local migration file via the Briven CLI.</p>}
65 {...props}
66 >
67 <div className="flex flex-col items-start justify-between gap-4 relative pt-2">
68 <Tabs type="underlined" listClassNames="pl-5">
69 {SNIPPETS.map((snippet) => {
70 return (
71 <Tabs.Panel key={snippet.id} id={snippet.id} label={snippet.label}>
72 <Modal.Content className="py-0!">
73 <div className="flex items-center justify-between mb-3">
74 <div className="flex flex-col gap-y-1">
75 <p className="text-base">{snippet.title}</p>
76 <Markdown
77 className="text-sm text-scale-1000 [&>p>code]:break-normal!"
78 content={snippet.description}
79 />
80 </div>
81 <TwoOptionToggle
82 width={50}
83 options={['CLI', 'NPM']}
84 activeOption={selectedView}
85 borderOverride="border-muted"
86 onClickOption={() =>
87 selectedView === 'CLI' ? setSelectedView('NPM') : setSelectedView('CLI')
88 }
89 />
90 </div>
91 <pre>
92 <CodeBlock
93 language="bash"
94 className="language-bash prose dark:prose-dark max-w-none"
95 >
96 {selectedView === 'CLI' ? snippet.cli : snippet.npm}
97 </CodeBlock>
98 </pre>
99 </Modal.Content>
100 </Tabs.Panel>
101 )
102 })}
103 </Tabs>
104 <Modal.Content className="w-full flex items-center justify-between pt-0">
105 <p className="text-xs text-lighter">Run this command from your project directory</p>
106 <div className="flex justify-between items-center gap-x-2">
107 <Button asChild type="default" icon={<ExternalLink strokeWidth={1.5} />}>
108 <Link
109 href={`${DOCS_URL}/guides/deployment/database-migrations`}
110 target="_blank"
111 rel="noreferrer"
112 >
113 About migrations
114 </Link>
115 </Button>
116
117 <Button asChild type="default" icon={<ExternalLink strokeWidth={1.5} />}>
118 <Link
119 href={`${DOCS_URL}/guides/cli/local-development`}
120 target="_blank"
121 rel="noreferrer"
122 >
123 About CLI
124 </Link>
125 </Button>
126 </div>
127 </Modal.Content>
128 </div>
129 </Modal>
130 )
131}
132
133export default DownloadSnippetModal