diff --git a/apps/studio/components/interfaces/Replication/DeleteSinkModal.tsx b/apps/studio/components/interfaces/Replication/DeleteSinkModal.tsx new file mode 100644 index 00000000000..813c35e05fd --- /dev/null +++ b/apps/studio/components/interfaces/Replication/DeleteSinkModal.tsx @@ -0,0 +1,46 @@ +import { useParams } from 'common' +import { useDeleteSinkMutation } from 'data/replication/delete-sink-mutation' +import { toast } from 'sonner' +import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' + +export type DeleteSinkModalProps = { + visible: boolean + title: string + sinkId: number + onClose: () => void +} + +export const DeleteSinkModal = ({ visible, title, sinkId, onClose }: DeleteSinkModalProps) => { + const { ref } = useParams() + const { mutate: deleteSink, isLoading: isCreating } = useDeleteSinkMutation({ + onSuccess: (res) => { + toast.success('Successfully deleted sink') + onClose() + }, + }) + const onConfirm = () => { + deleteSink({ + projectRef: ref!, + sinkId, + }) + } + return ( + { + onClose() + }} + onConfirm={onConfirm} + > + + + Are you sure you want to delete the selected sink? This action cannot be undone. + + + + ) +} diff --git a/apps/studio/components/interfaces/Replication/Sinks.tsx b/apps/studio/components/interfaces/Replication/Sinks.tsx index 7ce7170e08a..8bfb84dd225 100644 --- a/apps/studio/components/interfaces/Replication/Sinks.tsx +++ b/apps/studio/components/interfaces/Replication/Sinks.tsx @@ -9,6 +9,7 @@ import { useState } from 'react' import CreateSinkModal from './CreateSinkModal' import { Button } from 'ui' import { toast } from 'sonner' +import { DeleteSinkModal } from './DeleteSinkModal' export const ReplicationSinks = () => { const { ref } = useParams() @@ -16,6 +17,8 @@ export const ReplicationSinks = () => { projectRef: ref, }) const [showCreateSinkModal, setShowCreateSinkModal] = useState(false) + const [showDeleteSinkModal, setShowDeleteSinkModal] = useState(false) + const [sinkIdToDelete, setSinkIdToDelete] = useState(-1) const sinks = sinks_data ?? [] @@ -73,7 +76,8 @@ export const ReplicationSinks = () => { { - toast.info('Deleting a sink is not yet implemented') + setSinkIdToDelete(sink.id) + setShowDeleteSinkModal(true) }} > Delete @@ -93,6 +97,12 @@ export const ReplicationSinks = () => { visible={showCreateSinkModal} onClose={() => setShowCreateSinkModal(false)} /> + setShowDeleteSinkModal(false)} + /> > ) } diff --git a/apps/studio/data/replication/delete-sink-mutation.ts b/apps/studio/data/replication/delete-sink-mutation.ts new file mode 100644 index 00000000000..101d56255dd --- /dev/null +++ b/apps/studio/data/replication/delete-sink-mutation.ts @@ -0,0 +1,54 @@ +import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' +import { toast } from 'sonner' + +import type { ResponseError } from 'types' +import { replicationKeys } from './keys' +import { handleError, del } from 'data/fetchers' + +export type DeleteSinkParams = { + projectRef: string + sinkId: number +} + +async function deleteSink({ projectRef, sinkId }: DeleteSinkParams, signal?: AbortSignal) { + if (!projectRef) throw new Error('projectRef is required') + + const { data, error } = await del('/platform/replication/{ref}/sinks/{sink_id}', { + params: { path: { ref: projectRef, sink_id: sinkId } }, + signal, + }) + if (error) { + handleError(error) + } + + return data +} + +type DeleteSinkData = Awaited> + +export const useDeleteSinkMutation = ({ + onSuccess, + onError, + ...options +}: Omit< + UseMutationOptions, + 'mutationFn' +> = {}) => { + const queryClient = useQueryClient() + + return useMutation((vars) => deleteSink(vars), { + async onSuccess(data, variables, context) { + const { projectRef, sinkId } = variables + await queryClient.invalidateQueries(replicationKeys.sinks(projectRef)) + await onSuccess?.(data, variables, context) + }, + async onError(data, variables, context) { + if (onError === undefined) { + toast.error(`Failed to delete sink: ${data.message}`) + } else { + onError(data, variables, context) + } + }, + ...options, + }) +} diff --git a/packages/api-types/types/api.d.ts b/packages/api-types/types/api.d.ts index 23ec6ab7f65..87d0edf71d0 100644 --- a/packages/api-types/types/api.d.ts +++ b/packages/api-types/types/api.d.ts @@ -3325,6 +3325,10 @@ export interface paths { /** Creates a sink */ post: operations['ReplicationSinksController_createSink'] } + '/platform/replication/{ref}/sinks/{sink_id}': { + /** Deletes a sink */ + delete: operations['ReplicationSinksController_deleteSink'] + } '/platform/replication/{ref}/sources': { /** Gets replication sources */ get: operations['ReplicationSourcesController_getSources'] @@ -21673,6 +21677,26 @@ export interface operations { } } } + /** Deletes a sink */ + ReplicationSinksController_deleteSink: { + parameters: { + path: { + /** @description Project ref */ + ref: string + /** @description Sink id */ + sink_id: number + } + } + responses: { + 200: { + content: never + } + /** @description Failed to delete sink */ + 500: { + content: never + } + } + } /** Gets replication sources */ ReplicationSourcesController_getSources: { parameters: {
+ Are you sure you want to delete the selected sink? This action cannot be undone. +