@@ -11,19 +11,24 @@ import {
1111 PackagePlus ,
1212 Pencil ,
1313 Trash2 ,
14+ Upload ,
1415} from 'lucide-react'
1516import Link from 'next/link'
1617import { useParams , useRouter } from 'next/navigation'
1718import { useState } from 'react'
1819import { Button } from '~/components/ui/button'
20+ import { Dialog , DialogContent , DialogHeader , DialogTitle } from '~/components/ui/dialog'
1921import { Popover , PopoverContent , PopoverTrigger } from '~/components/ui/popover'
2022import { Tooltip , TooltipContent , TooltipTrigger } from '~/components/ui/tooltip'
2123import { useDatabaseDeleteMutation } from '~/data/databases/database-delete-mutation'
2224import { useDatabaseUpdateMutation } from '~/data/databases/database-update-mutation'
2325import { useDatabasesQuery } from '~/data/databases/databases-query'
26+ import { usePublishWaitlistCreateMutation } from '~/data/publish-waitlist/publish-waitlist-create-mutation'
27+ import { useIsOnPublishWaitlistQuery } from '~/data/publish-waitlist/publish-waitlist-query'
2428import { Database } from '~/lib/db'
2529import { cn } from '~/lib/utils'
2630import { useApp } from './app-provider'
31+ import { CodeBlock } from './code-block'
2732
2833export default function Sidebar ( ) {
2934 const { user, signOut } = useApp ( )
@@ -203,117 +208,192 @@ type DatabaseMenuItemProps = {
203208
204209function DatabaseMenuItem ( { database, isActive } : DatabaseMenuItemProps ) {
205210 const router = useRouter ( )
211+ const { user } = useApp ( )
206212 const [ isPopoverOpen , setIsPopoverOpen ] = useState ( false )
207213 const { mutateAsync : deleteDatabase } = useDatabaseDeleteMutation ( )
208214 const { mutateAsync : updateDatabase } = useDatabaseUpdateMutation ( )
209215
210216 const [ isRenaming , setIsRenaming ] = useState ( false )
217+ const [ isPublishDialogOpen , setIsPublishDialogOpen ] = useState ( false )
218+
219+ const { data : isOnPublishWaitlist } = useIsOnPublishWaitlistQuery ( )
220+ const { mutateAsync : joinPublishWaitlist } = usePublishWaitlistCreateMutation ( )
211221
212222 return (
213- < Link
214- data-active = { isActive || isPopoverOpen }
215- className = { cn (
216- 'group text-sm w-full relative bg-inherit justify-start bg-neutral-100 hover:bg-neutral-200 flex gap-3 p-3 rounded-md overflow-hidden data-[active=true]:bg-neutral-200'
217- ) }
218- href = { `/db/${ database . id } ` }
219- >
220- < span className = "text-nowrap" > { database . name ?? 'My database' } </ span >
221- < div
222- className = { cn (
223- 'absolute right-0 top-0 bottom-0' ,
224- 'w-8 bg-gradient-to-l from-neutral-100 from-0%' ,
225- 'group-hover:w-16 group-hover:from-neutral-200 group-hover:from-50%' ,
226- 'group-data-[active=true]:w-16 group-data-[active=true]:from-neutral-200 group-data-[active=true]:from-50%'
227- ) }
228- />
229- < Popover
223+ < >
224+ < Dialog
225+ open = { isPublishDialogOpen }
230226 onOpenChange = { ( open ) => {
231- setIsPopoverOpen ( open )
232- if ( ! open ) {
233- setIsRenaming ( false )
234- }
227+ setIsPublishDialogOpen ( open )
235228 } }
236- open = { isPopoverOpen }
237229 >
238- < PopoverTrigger
239- asChild
240- onClick = { ( e ) => {
241- e . preventDefault ( )
242- setIsPopoverOpen ( true )
230+ < DialogContent className = "max-w-2xl" >
231+ < DialogHeader >
232+ < DialogTitle > Database publishing is in Private Alpha</ DialogTitle >
233+ < div className = "py-2 border-b" />
234+ </ DialogHeader >
235+ < h2 className = "font-medium" > What is database publishing?</ h2 >
236+ < p >
237+ Publish your database so that it can be accessed outside the browser using any Postgres
238+ client:
239+ </ p >
240+ < CodeBlock
241+ className = "language-curl bg-neutral-800"
242+ language = "curl"
243+ hideLineNumbers
244+ theme = "dark"
245+ >
246+ { `psql "postgres://postgres:<password>@<your-unique-server>/postgres"` }
247+ </ CodeBlock >
248+ < div className = "flex justify-center items-center mt-3" >
249+ < AnimatePresence initial = { false } >
250+ { ! isOnPublishWaitlist ? (
251+ < button
252+ className = "px-4 py-3 bg-black text-white rounded-md"
253+ onClick = { async ( ) => {
254+ await joinPublishWaitlist ( )
255+ } }
256+ >
257+ Join Private Alpha
258+ </ button >
259+ ) : (
260+ < m . div
261+ className = "px-4 py-3 border-2 rounded-md text-center border-dashed"
262+ variants = { {
263+ hidden : { scale : 0 } ,
264+ show : { scale : 1 } ,
265+ } }
266+ initial = "hidden"
267+ animate = "show"
268+ >
269+ < h3 className = "font-medium mb-2" > 🎉 You're on the list!</ h3 >
270+ < p > We'll let you know when you have access to publish.</ p >
271+ </ m . div >
272+ ) }
273+ </ AnimatePresence >
274+ </ div >
275+ </ DialogContent >
276+ </ Dialog >
277+
278+ < Link
279+ data-active = { isActive || isPopoverOpen }
280+ className = { cn (
281+ 'group text-sm w-full relative bg-inherit justify-start bg-neutral-100 hover:bg-neutral-200 flex gap-3 p-3 rounded-md overflow-hidden data-[active=true]:bg-neutral-200'
282+ ) }
283+ href = { `/db/${ database . id } ` }
284+ >
285+ < span className = "text-nowrap" > { database . name ?? 'My database' } </ span >
286+ < div
287+ className = { cn (
288+ 'absolute right-0 top-0 bottom-0' ,
289+ 'w-8 bg-gradient-to-l from-neutral-100 from-0%' ,
290+ 'group-hover:w-16 group-hover:from-neutral-200 group-hover:from-50%' ,
291+ 'group-data-[active=true]:w-16 group-data-[active=true]:from-neutral-200 group-data-[active=true]:from-50%'
292+ ) }
293+ />
294+ < Popover
295+ onOpenChange = { ( open ) => {
296+ setIsPopoverOpen ( open )
297+ if ( ! open ) {
298+ setIsRenaming ( false )
299+ }
243300 } }
301+ open = { isPopoverOpen }
244302 >
245- < div
246- className = { cn (
247- 'hidden group-hover:flex absolute right-0 top-0 bottom-0 p-2 opacity-50 items-center' ,
248- isActive || isPopoverOpen ? 'flex' : undefined
249- ) }
303+ < PopoverTrigger
304+ asChild
305+ onClick = { ( e ) => {
306+ e . preventDefault ( )
307+ setIsPopoverOpen ( true )
308+ } }
250309 >
251- < CircleEllipsis size = { 24 } />
252- </ div >
253- </ PopoverTrigger >
310+ < div
311+ className = { cn (
312+ 'hidden group-hover:flex absolute right-0 top-0 bottom-0 p-2 opacity-50 items-center' ,
313+ isActive || isPopoverOpen ? 'flex' : undefined
314+ ) }
315+ >
316+ < CircleEllipsis size = { 24 } />
317+ </ div >
318+ </ PopoverTrigger >
254319
255- < PopoverContent className = "p-2 flex flex-col overflow-hidden w-auto" portal >
256- { isRenaming ? (
257- < form
258- className = "w-72"
259- onSubmit = { async ( e ) => {
260- e . preventDefault ( )
320+ < PopoverContent className = "p-2 flex flex-col overflow-hidden w-auto" portal >
321+ { isRenaming ? (
322+ < form
323+ className = "w-72"
324+ onSubmit = { async ( e ) => {
325+ e . preventDefault ( )
261326
262- if ( e . target instanceof HTMLFormElement ) {
263- const formData = new FormData ( e . target )
264- const name = formData . get ( 'name' )
327+ if ( e . target instanceof HTMLFormElement ) {
328+ const formData = new FormData ( e . target )
329+ const name = formData . get ( 'name' )
265330
266- if ( typeof name === 'string' ) {
267- await updateDatabase ( { ...database , name } )
331+ if ( typeof name === 'string' ) {
332+ await updateDatabase ( { ...database , name } )
333+ }
268334 }
269- }
270335
271- setIsPopoverOpen ( false )
272- setIsRenaming ( false )
273- } }
274- >
275- < input
276- name = "name"
277- className = "flex-grow w-full border-none focus-visible:ring-0 text-base bg-inherit placeholder:text-neutral-400"
278- placeholder = { `Rename ${ database . name } ` }
279- defaultValue = { database . name ?? undefined }
280- autoComplete = "off"
281- autoFocus
282- />
283- </ form >
284- ) : (
285- < div className = "flex flex-col items-stretch w-32" >
286- < Button
287- className = "bg-inherit justify-start hover:bg-neutral-200 flex gap-3"
288- onClick = { async ( e ) => {
289- e . preventDefault ( )
290- setIsRenaming ( true )
336+ setIsPopoverOpen ( false )
337+ setIsRenaming ( false )
291338 } }
292339 >
293- < Pencil size = { 16 } strokeWidth = { 2 } className = "flex-shrink-0" />
340+ < input
341+ name = "name"
342+ className = "flex-grow w-full border-none focus-visible:ring-0 text-base bg-inherit placeholder:text-neutral-400"
343+ placeholder = { `Rename ${ database . name } ` }
344+ defaultValue = { database . name ?? undefined }
345+ autoComplete = "off"
346+ autoFocus
347+ />
348+ </ form >
349+ ) : (
350+ < div className = "flex flex-col items-stretch w-32" >
351+ < Button
352+ className = "bg-inherit justify-start hover:bg-neutral-200 flex gap-3"
353+ onClick = { async ( e ) => {
354+ e . preventDefault ( )
355+ setIsRenaming ( true )
356+ } }
357+ >
358+ < Pencil size = { 16 } strokeWidth = { 2 } className = "flex-shrink-0" />
294359
295- < span > Rename</ span >
296- </ Button >
297- < Button
298- className = "bg-inherit text-destructive-600 justify-start hover:bg-neutral-200 flex gap-3"
299- onClick = { async ( e ) => {
300- e . preventDefault ( )
301- setIsPopoverOpen ( false )
302- await deleteDatabase ( { id : database . id } )
360+ < span > Rename</ span >
361+ </ Button >
362+ < Button
363+ className = "bg-inherit justify-start hover:bg-neutral-200 flex gap-3"
364+ onClick = { async ( e ) => {
365+ e . preventDefault ( )
303366
304- if ( isActive ) {
305- router . push ( '/' )
306- }
307- } }
308- >
309- < Trash2 size = { 16 } strokeWidth = { 2 } className = "flex-shrink-0" />
367+ setIsPublishDialogOpen ( true )
368+ setIsPopoverOpen ( false )
369+ } }
370+ disabled = { user === undefined }
371+ >
372+ < Upload size = { 16 } strokeWidth = { 2 } className = "flex-shrink-0" />
310373
311- < span > Delete</ span >
312- </ Button >
313- </ div >
314- ) }
315- </ PopoverContent >
316- </ Popover >
317- </ Link >
374+ < span > Publish</ span >
375+ </ Button >
376+ < Button
377+ className = "bg-inherit text-destructive-600 justify-start hover:bg-neutral-200 flex gap-3"
378+ onClick = { async ( e ) => {
379+ e . preventDefault ( )
380+ setIsPopoverOpen ( false )
381+ await deleteDatabase ( { id : database . id } )
382+
383+ if ( isActive ) {
384+ router . push ( '/' )
385+ }
386+ } }
387+ >
388+ < Trash2 size = { 16 } strokeWidth = { 2 } className = "flex-shrink-0" />
389+
390+ < span > Delete</ span >
391+ </ Button >
392+ </ div >
393+ ) }
394+ </ PopoverContent >
395+ </ Popover >
396+ </ Link >
397+ </ >
318398 )
319399}
0 commit comments