mirror of
https://github.com/supabase/supabase.git
synced 2026-07-04 18:34:26 +08:00
* add dummy sinks and pipelines pages * update api types * show empty sources state * show empty replication state at /replication * create source when enable replication button is clicked * improve replication page when replication is enabled * replace sources page with publications page * publications table * show publications in table * create publication wip * show toast error instead of throwing an exception * user can now delete a publication * show empty sinks page * create and list sinks * add ui to delete a sink * show pipelines on the pipelines page * add ui to create and delete pipelines * get pipeline status wip * show pipeline status wip * show correct label on action buttons * start and stop pipelines * remove a couple of console.logs * fix error when deleting a pipeline * only consider replication enabled when a source with name = ref is present * add source and sink names * correct colspan for 'no pipelines' row * hide 'supabase_realtime' publication on ui * move filtering to fetch query * show sink name in ui * show source/sink names on pipelines page * fix start/stop status shown on ui * fix prettier formatting * update api types * extract pipeline action button as a separate component * fix a crashing page * fixed publications page crash * update to match with changes in api * add new replication page under database * hide replication page behind feature flag * update types * update api types * show destinations empty state * add destinations table * factor out components from Destinations table * show status dot * move pipeline fetch query to parent component * add ability to enable/disable a pipeline * show loader when starting or stopping a pipeline * fix a bug in which loading & empty states were shown together * fix a bug in which error & empty states were shown together * wrap in default layout * add new destination panel * add type field * fix a forwardRef error * fix layout * create destination * delete destination * add ability to create or delete destinations with pipelines * create source if missing * show only a single error * add an enable switch * new layout * add subsections * comment out unused code * show enabled switch only in the header * close panel when destination is created * disable buttons when api requests in flight * reduce panel size * remove commented out code * treat max size and max fill secs as numbers * use drop down to show publications * simpler vertical layout * add separators * add form validation * remove publications drop down padding * add new publication button * hide advanced settings behind an accordion * add some margin between icon and text * show publications panel on clicking new publication button * add header to new publication panel * fix validation not running for publication drop down * create publication in the new publication panel * add table selector in new publication panel * update api types * remove old code * update platform.d.ts * update navigation bar utils * remove a redirect from replication page to publications page * ask user for confirmation before deleting destination * edit destination panel * edit destination panel values fixed * bug fixes * fix prettier formatting * enable/disable pipeline after editing * rename snake_case params to camelCase * loading button when editing * remove merge markers * update api types * add max_staleness parameter in sinks for bigquery * add read replicas flow diagram to replication page * remove an unused import * Revert "add read replicas flow diagram to replication page" This reverts commit 8852d7847b457885603dba786141a8aaf8e99350. * add panel to warn users about additional cost before creating a destination * hide replication page contents behind a feature flag * fix merge conflicts * styling changes * revert static flag * styling updates * fixes * fix switch * copy * fix layout --------- Co-authored-by: Saxon Fletcher <saxonafletcher@gmail.com>
207 lines
6.4 KiB
TypeScript
207 lines
6.4 KiB
TypeScript
import Table from 'components/to-be-cleaned/Table'
|
|
import AlertError from 'components/ui/AlertError'
|
|
import { ReplicationPipelinesData } from 'data/replication/pipelines-query'
|
|
import { ResponseError } from 'types'
|
|
import ShimmeringLoader from 'ui-patterns/ShimmeringLoader'
|
|
import RowMenu from './RowMenu'
|
|
import PipelineStatus from './PipelineStatus'
|
|
import { useParams } from 'common'
|
|
import { useReplicationPipelineStatusQuery } from 'data/replication/pipeline-status-query'
|
|
import { useState } from 'react'
|
|
import { toast } from 'sonner'
|
|
import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation'
|
|
import { useStopPipelineMutation } from 'data/replication/stop-pipeline-mutation'
|
|
import { useDeleteSinkMutation } from 'data/replication/delete-sink-mutation'
|
|
import { useDeletePipelineMutation } from 'data/replication/delete-pipeline-mutation'
|
|
import DeleteDestination from './DeleteDestination'
|
|
import DestinationPanel from './DestinationPanel'
|
|
|
|
export type Pipeline = ReplicationPipelinesData['pipelines'][0]
|
|
|
|
interface DestinationRowProps {
|
|
sourceId: number | undefined
|
|
sinkId: number
|
|
sinkName: string
|
|
type: string
|
|
pipeline: Pipeline | undefined
|
|
error: ResponseError | null
|
|
isLoading: boolean
|
|
isError: boolean
|
|
isSuccess: boolean
|
|
}
|
|
|
|
const DestinationRow = ({
|
|
sourceId,
|
|
sinkId,
|
|
sinkName,
|
|
type,
|
|
pipeline,
|
|
error: pipelineError,
|
|
isLoading: isPipelineLoading,
|
|
isError: isPipelineError,
|
|
isSuccess: isPipelineSuccess,
|
|
}: DestinationRowProps) => {
|
|
const { ref: projectRef } = useParams()
|
|
const [refetchInterval, setRefetchInterval] = useState<number | false>(false)
|
|
const [showDeleteDestinationForm, setShowDeleteDestinationForm] = useState(false)
|
|
const [showEditDestinationPanel, setShowEditDestinationPanel] = useState(false)
|
|
|
|
const {
|
|
data: pipelineStatusData,
|
|
error: pipelineStatusError,
|
|
isLoading: isPipelineStatusLoading,
|
|
isError: isPipelineStatusError,
|
|
isSuccess: isPipelineStatusSuccess,
|
|
} = useReplicationPipelineStatusQuery(
|
|
{
|
|
projectRef,
|
|
pipelineId: pipeline?.id,
|
|
},
|
|
{ refetchInterval }
|
|
)
|
|
const [requestStatus, setRequestStatus] = useState<
|
|
'None' | 'EnableRequested' | 'DisableRequested'
|
|
>('None')
|
|
const { mutateAsync: startPipeline } = useStartPipelineMutation()
|
|
const { mutateAsync: stopPipeline } = useStopPipelineMutation()
|
|
const pipelineStatus = pipelineStatusData?.status
|
|
if (
|
|
(requestStatus === 'EnableRequested' && pipelineStatus === 'Started') ||
|
|
(requestStatus === 'DisableRequested' && pipelineStatus === 'Stopped')
|
|
) {
|
|
setRefetchInterval(false)
|
|
setRequestStatus('None')
|
|
}
|
|
|
|
const onEnableClick = async () => {
|
|
if (!projectRef) {
|
|
console.error('Project ref is required')
|
|
return
|
|
}
|
|
if (!pipeline) {
|
|
toast.error('No pipeline found')
|
|
return
|
|
}
|
|
|
|
try {
|
|
await startPipeline({ projectRef, pipelineId: pipeline.id })
|
|
} catch (error) {
|
|
toast.error('Failed to enable destination')
|
|
}
|
|
setRequestStatus('EnableRequested')
|
|
setRefetchInterval(5000)
|
|
}
|
|
const onDisableClick = async () => {
|
|
if (!projectRef) {
|
|
console.error('Project ref is required')
|
|
return
|
|
}
|
|
if (!pipeline) {
|
|
toast.error('No pipeline found')
|
|
return
|
|
}
|
|
|
|
try {
|
|
await stopPipeline({ projectRef, pipelineId: pipeline.id })
|
|
} catch (error) {
|
|
toast.error('Failed to disable destination')
|
|
}
|
|
setRequestStatus('DisableRequested')
|
|
setRefetchInterval(5000)
|
|
}
|
|
const { mutateAsync: deleteSink } = useDeleteSinkMutation({})
|
|
const { mutateAsync: deletePipeline } = useDeletePipelineMutation({
|
|
onSuccess: (_res: any) => {
|
|
toast.success('Successfully deleted destination')
|
|
},
|
|
})
|
|
|
|
const onDeleteClick = async () => {
|
|
if (!projectRef) {
|
|
console.error('Project ref is required')
|
|
return
|
|
}
|
|
if (!pipeline) {
|
|
toast.error('No pipeline found')
|
|
return
|
|
}
|
|
|
|
try {
|
|
await stopPipeline({ projectRef, pipelineId: pipeline.id })
|
|
await deletePipeline({ projectRef, pipelineId: pipeline.id })
|
|
await deleteSink({ projectRef, sinkId })
|
|
} catch (error) {
|
|
toast.error('Failed to delete destination')
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{isPipelineError && (
|
|
<AlertError error={pipelineError} subject="Failed to retrieve pipeline" />
|
|
)}
|
|
{isPipelineSuccess && (
|
|
<Table.tr>
|
|
<Table.td>
|
|
{isPipelineLoading ? <ShimmeringLoader></ShimmeringLoader> : sinkName}
|
|
</Table.td>
|
|
<Table.td>{isPipelineLoading ? <ShimmeringLoader></ShimmeringLoader> : type}</Table.td>
|
|
<Table.td>
|
|
{isPipelineLoading || !pipeline ? (
|
|
<ShimmeringLoader></ShimmeringLoader>
|
|
) : (
|
|
<PipelineStatus
|
|
pipelineStatus={pipelineStatusData?.status}
|
|
error={pipelineStatusError}
|
|
isLoading={isPipelineStatusLoading}
|
|
isError={isPipelineStatusError}
|
|
isSuccess={isPipelineStatusSuccess}
|
|
requestStatus={requestStatus}
|
|
></PipelineStatus>
|
|
)}
|
|
</Table.td>
|
|
<Table.td>
|
|
{isPipelineLoading || !pipeline ? (
|
|
<ShimmeringLoader></ShimmeringLoader>
|
|
) : (
|
|
pipeline.publication_name
|
|
)}
|
|
</Table.td>
|
|
<Table.td>
|
|
<RowMenu
|
|
pipelineStatus={pipelineStatusData?.status}
|
|
error={pipelineStatusError}
|
|
isLoading={isPipelineStatusLoading}
|
|
isError={isPipelineStatusError}
|
|
onEnableClick={onEnableClick}
|
|
onDisableClick={onDisableClick}
|
|
onDeleteClick={() => setShowDeleteDestinationForm(true)}
|
|
onEditClick={() => setShowEditDestinationPanel(true)}
|
|
></RowMenu>
|
|
</Table.td>
|
|
</Table.tr>
|
|
)}
|
|
<DeleteDestination
|
|
visible={showDeleteDestinationForm}
|
|
setVisible={setShowDeleteDestinationForm}
|
|
onDelete={onDeleteClick}
|
|
isLoading={isPipelineStatusLoading}
|
|
name={sinkName}
|
|
/>
|
|
<DestinationPanel
|
|
visible={showEditDestinationPanel}
|
|
onClose={() => setShowEditDestinationPanel(false)}
|
|
sourceId={sourceId}
|
|
existingDestination={{
|
|
sourceId,
|
|
sinkId,
|
|
pipelineId: pipeline?.id,
|
|
enabled: pipelineStatusData?.status === 'Started',
|
|
}}
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default DestinationRow
|