import { useParams } from 'common' import { ChevronDown } from 'lucide-react' import { toast } from 'sonner' import { Collapsible, CollapsibleContent, CollapsibleTrigger, DialogSectionSeparator } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { getStatusName } from './Pipeline.utils' import { PipelineStatusName, STATUS_REFRESH_FREQUENCY_MS } from './Replication.constants' import { useReplicationPipelineStatusQuery } from '@/data/replication/pipeline-status-query' import { useReplicationPipelineVersionQuery } from '@/data/replication/pipeline-version-query' import { Pipeline } from '@/data/replication/pipelines-query' import { useRestartPipelineHelper } from '@/data/replication/restart-pipeline-helper' import { useUpdatePipelineVersionMutation } from '@/data/replication/update-pipeline-version-mutation' import { PipelineStatusRequestStatus, usePipelineRequestStatus, } from '@/state/replication-pipeline-request-status' import { type ResponseError } from '@/types' interface UpdateVersionModalProps { visible: boolean pipeline?: Pipeline confirmLabel?: string confirmLabelLoading?: string onClose: () => void } export const UpdateVersionModal = ({ visible, pipeline, confirmLabel, confirmLabelLoading = 'Updating', onClose, }: UpdateVersionModalProps) => { const { ref: projectRef } = useParams() const { setRequestStatus } = usePipelineRequestStatus() const { data: pipelineStatusData } = useReplicationPipelineStatusQuery( { projectRef, pipelineId: pipeline?.id }, { refetchInterval: STATUS_REFRESH_FREQUENCY_MS } ) const pipelineStatus = pipelineStatusData?.status const statusName = getStatusName(pipelineStatus) const isStopped = statusName === PipelineStatusName.STOPPED const { data: versionData, isPending: isLoadingVersion } = useReplicationPipelineVersionQuery({ projectRef, pipelineId: pipeline?.id, }) const currentVersionName = versionData?.version?.name const newVersionName = versionData?.new_version?.name const { mutateAsync: updatePipelineVersion } = useUpdatePipelineVersionMutation() const { restartPipeline } = useRestartPipelineHelper() const onConfirmUpdate = async () => { if (!projectRef || !pipeline?.id) return const versionId = versionData?.new_version?.id if (!versionId) return // Step 1: Update to the new version try { await updatePipelineVersion({ projectRef, pipelineId: pipeline.id, versionId }) } catch (e) { // 404: default changed; version cache will refresh via mutation onError. Keep dialog open. if ((e as ResponseError)?.code === 404) return // Other errors are already toasted by the mutation; do not double-toast here. return } // Step 2: Reflect optimistic restart (only if not stopped) and close any panels if (!isStopped) { setRequestStatus(pipeline.id, PipelineStatusRequestStatus.RestartRequested, statusName) // Step 3: Restart the pipeline (stop + start) try { await restartPipeline({ projectRef, pipelineId: pipeline.id }) toast.success('Pipeline successfully updated and is currently restarting') } catch (e) { // Clear optimistic state and surface a single concise error setRequestStatus(pipeline.id, PipelineStatusRequestStatus.None) toast.error(`Failed to restart pipeline: ${(e as ResponseError).message}`) } } else { toast.success('Pipeline successfully updated') } onClose() } return (

A new pipeline image is available with improvements and bug fixes. Proceed to update?

{!isStopped && (

The pipeline will automatically restart when updating. Replication will continue from where it left off.

)}

View version update details

Current version:

{' '} {isLoadingVersion ? 'Loading...' : (currentVersionName ?? 'Unknown')}

New version:

{' '} {isLoadingVersion ? 'Loading...' : (newVersionName ?? 'Unknown')}
) }