import { ArrowUpCircle, Edit, MoreVertical, Pause, Play, RotateCcw, Trash } from 'lucide-react' import { toast } from 'sonner' import { useParams } from 'common' import AlertError from 'components/ui/AlertError' import { ReplicationPipelineStatusData } from 'data/replication/pipeline-status-query' import { Pipeline } from 'data/replication/pipelines-query' import { useRestartPipelineHelper } from 'data/replication/restart-pipeline-helper' import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation' import { useStopPipelineMutation } from 'data/replication/stop-pipeline-mutation' import { PipelineStatusRequestStatus, usePipelineRequestStatus, } from 'state/replication-pipeline-request-status' import type { ResponseError } from 'types' import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from 'ui' import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' import { PIPELINE_ACTIONABLE_STATES, PIPELINE_DISABLE_ALLOWED_FROM, PIPELINE_ENABLE_ALLOWED_FROM, PIPELINE_ERROR_MESSAGES, getStatusName, } from './Pipeline.utils' import { PipelineStatusName } from './Replication.constants' interface RowMenuProps { pipeline: Pipeline | undefined pipelineStatus?: ReplicationPipelineStatusData['status'] error: ResponseError | null isLoading: boolean isError: boolean onEditClick: () => void onDeleteClick: () => void hasUpdate?: boolean onUpdateClick?: () => void } export const RowMenu = ({ pipeline, pipelineStatus, error, isLoading, isError, onEditClick, onDeleteClick, hasUpdate = false, onUpdateClick, }: RowMenuProps) => { const { ref: projectRef } = useParams() const statusName = getStatusName(pipelineStatus) const { mutateAsync: startPipeline } = useStartPipelineMutation() const { mutateAsync: stopPipeline } = useStopPipelineMutation() const { restartPipeline } = useRestartPipelineHelper() const { getRequestStatus, setRequestStatus: setGlobalRequestStatus } = usePipelineRequestStatus() const requestStatus = pipeline?.id ? getRequestStatus(pipeline.id) : PipelineStatusRequestStatus.None // Show actions when not in a transitional state const canPerformActions = requestStatus === PipelineStatusRequestStatus.None && statusName !== PipelineStatusName.STARTING && [PipelineStatusName.STOPPED, PipelineStatusName.STARTED, PipelineStatusName.FAILED].includes( statusName as PipelineStatusName ) // Show both stop and restart for started/failed states const showStopAndRestart = canPerformActions && (statusName === PipelineStatusName.STARTED || statusName === PipelineStatusName.FAILED) // Show only start for stopped state const showStart = canPerformActions && statusName === PipelineStatusName.STOPPED const onEnablePipeline = async () => { if (!projectRef) return console.error('Project ref is required') if (!pipeline) return toast.error(PIPELINE_ERROR_MESSAGES.NO_PIPELINE_FOUND) try { // Only show 'enabling' when transitioning from allowed states if (PIPELINE_ENABLE_ALLOWED_FROM.includes(statusName as any)) { setGlobalRequestStatus(pipeline.id, PipelineStatusRequestStatus.StartRequested, statusName) } await startPipeline({ projectRef, pipelineId: pipeline.id }) } catch (error) { setGlobalRequestStatus(pipeline.id, PipelineStatusRequestStatus.None) toast.error(PIPELINE_ERROR_MESSAGES.ENABLE_DESTINATION) } } const onDisablePipeline = async () => { if (!projectRef) return console.error('Project ref is required') if (!pipeline) return toast.error(PIPELINE_ERROR_MESSAGES.NO_PIPELINE_FOUND) try { // Only show 'disabling' when transitioning from allowed states if (PIPELINE_DISABLE_ALLOWED_FROM.includes(statusName as any)) { setGlobalRequestStatus(pipeline.id, PipelineStatusRequestStatus.StopRequested, statusName) } await stopPipeline({ projectRef, pipelineId: pipeline.id }) } catch (error) { setGlobalRequestStatus(pipeline.id, PipelineStatusRequestStatus.None) toast.error(PIPELINE_ERROR_MESSAGES.DISABLE_DESTINATION) } } const onRestartPipeline = async () => { if (!projectRef) return console.error('Project ref is required') if (!pipeline) return toast.error(PIPELINE_ERROR_MESSAGES.NO_PIPELINE_FOUND) try { setGlobalRequestStatus(pipeline.id, PipelineStatusRequestStatus.RestartRequested, statusName) await restartPipeline({ projectRef, pipelineId: pipeline.id }) } catch (error) { setGlobalRequestStatus(pipeline.id, PipelineStatusRequestStatus.None) toast.error(PIPELINE_ERROR_MESSAGES.ENABLE_DESTINATION) } } return (
Update available
Start pipeline
Restart pipeline
Stop pipeline
Edit destination
Delete destination