import { useParams } from 'common' import { ArrowUpRight } from 'lucide-react' import Link from 'next/link' import { parseAsInteger, parseAsStringEnum, useQueryState } from 'nuqs' import { useEffect, useRef } from 'react' import { toast } from 'sonner' import { Button, cn, DialogSectionSeparator, Sheet, SheetContent, SheetDescription, SheetHeader, SheetSection, SheetTitle, } from 'ui' import { Admonition } from 'ui-patterns/Admonition' import { EnablePipelinesCallout } from '../EnablePipelinesCallout' import { PipelineStatusName } from '../Replication.constants' import { useDestinationInformation } from '../useDestinationInformation' import { useIsETLPrivateAlpha } from '../useIsETLPrivateAlpha' import { DestinationForm } from './DestinationForm' import { DestinationType } from './DestinationPanel.types' import { DestinationTypeSelection } from './DestinationTypeSelection' import { DiscardChangesConfirmationDialog } from '@/components/ui-patterns/Dialogs/DiscardChangesConfirmationDialog' import { DocsButton } from '@/components/ui/DocsButton' import { useReplicationDestinationsQuery } from '@/data/replication/destinations-query' import { checkLocalETLNotSetUp } from '@/data/replication/utils' import { useConfirmOnClose } from '@/hooks/ui/useConfirmOnClose' import { DOCS_URL } from '@/lib/constants' export const DestinationPanel = () => { const { ref: projectRef } = useParams() const enablePgReplicate = useIsETLPrivateAlpha() const { error: destinationsError } = useReplicationDestinationsQuery({ projectRef }) const isLocalETLNotSetUp = checkLocalETLNotSetUp(destinationsError) const [urlDestinationType, setDestinationType] = useQueryState( 'destinationType', parseAsStringEnum([ 'BigQuery', 'Analytics Bucket', 'DuckLake', 'Snowflake', 'ClickHouse', ]).withOptions({ history: 'push', clearOnDefault: true, }) ) const [edit, setEdit] = useQueryState( 'edit', parseAsInteger.withOptions({ history: 'push', clearOnDefault: true, }) ) const visible = urlDestinationType !== null || edit !== null const editMode = edit !== null const { sourceId, pipeline, statusName, replicationNotEnabled, type: existingDestinationType, destinationFetcher, } = useDestinationInformation({ id: edit }) const destinationType = existingDestinationType ?? urlDestinationType const invalidExistingDestination = destinationFetcher.error?.code === 404 const existingDestination = editMode ? { sourceId, destinationId: edit, pipelineId: pipeline?.id, statusName, enabled: statusName === PipelineStatusName.STARTED || statusName === PipelineStatusName.FAILED, } : undefined const checkIsDirtyRef = useRef<() => boolean>(() => false) const onClose = () => { checkIsDirtyRef.current = () => false setDestinationType(null) setEdit(null) } const { confirmOnClose, handleOpenChange, modalProps } = useConfirmOnClose({ checkIsDirty: () => checkIsDirtyRef.current(), onClose, }) const docsUrl = destinationType === 'BigQuery' ? `${DOCS_URL}/guides/database/replication/bigquery#configure-bigquery-as-a-destination` : `${DOCS_URL}/guides/database/replication/pipelines#step-3-configure-a-destination` useEffect(() => { if (edit !== null && invalidExistingDestination) { toast(`Unable to find destination ID ${edit}`) setEdit(null) } }, [edit, invalidExistingDestination, setEdit]) const typeSelection = ( <> ) const pipelinesTypeSelection = ( <> {typeSelection} {destinationType != null && isLocalETLNotSetUp && ( )} ) return ( <>
{editMode ? 'Edit destination' : 'Add destination'} {editMode ? 'Update the configuration for this destination.' : 'Connect an external destination for analytics workloads.'}
{!enablePgReplicate ? (
{pipelinesTypeSelection}

Request Pipelines access

Pipelines is in public alpha and being rolled out gradually. Request access below to join the waitlist.

) : replicationNotEnabled ? (
{pipelinesTypeSelection}
) : ( )}
) }