add ui to create and delete pipelines

This commit is contained in:
Raminder Singh committed 2025-02-06 16:48:49 +05:30
1 parent 1bd90502ed
commit 88726fc5e3
5 files changed
+339

No files matched your search

@@ -0,0 +1,144 @@
import { useParams } from 'common'
import { useCreatePipelineMutation } from 'data/replication/create-pipeline-mutation'
import { toast } from 'sonner'
import { Button, Form, Input, Modal } from 'ui'
export interface CreatePipelineModalProps {
visible: boolean
onClose: () => void
}
const CreatePipelineModal = ({ visible, onClose }: CreatePipelineModalProps) => {
const { ref } = useParams()
const { mutate: createPipeline, isLoading: isCreating } = useCreatePipelineMutation({
onSuccess: (res) => {
toast.success('Successfully created pipeline')
onClose()
},
})
const validate = (values: any) => {
const errors = {} as any
if (!values.source_id) {
errors.source_id = 'Please enter a Source Id for your sink'
}
if (!values.sink_id) {
errors.sink_id = 'Please enter a Sink Id for your sink'
}
if (!values.publication_name) {
errors.publication_name = 'Please enter a Publication Name for your sink'
}
if (!values.max_size) {
errors.max_size = 'Please enter a Max Size for your sink'
}
if (!values.max_fill_secs) {
errors.max_size = 'Please enter a Max Fill Seconds for your sink'
}
return errors
}
const onSubmit = (values: any) => {
console.log('onSubmit')
createPipeline({
projectRef: ref!,
source_id: Number(values.source_id),
sink_id: Number(values.sink_id),
publication_name: values.publication_name,
config: {
config: { max_size: Number(values.max_size), max_fill_secs: Number(values.max_fill_secs) },
},
})
}
const initialValues = {
source_id: '',
sink_id: '',
publication_name: '',
max_size: 10000,
max_fill_secs: 10,
}
return (
<Modal
hideFooter
visible={visible}
header="Create pipeline"
size="xlarge"
onCancel={() => onClose()}
>
<Form onSubmit={onSubmit} initialValues={initialValues} validate={validate}>
{({ values }: { values: any }) => {
return (
<>
<Modal.Content>
<Input
id="source_id"
name="source_id"
type="text"
className="w-full"
layout="vertical"
label="Source Id"
/>
</Modal.Content>
<Modal.Content>
<Input
id="sink_id"
name="sink_id"
type="text"
className="w-full"
layout="vertical"
label="Sink Id"
/>
</Modal.Content>
<Modal.Content>
<Input
id="publication_name"
name="publication_name"
type="text"
className="w-full"
layout="vertical"
label="Publication Name"
></Input>
</Modal.Content>
<Modal.Content>
<Input
id="max_size"
name="max_size"
type="text"
className="w-full"
layout="vertical"
label="Max Size"
></Input>
</Modal.Content>
<Modal.Content>
<Input
id="max_fill_secs"
name="max_fill_secs"
type="text"
className="w-full"
layout="vertical"
label="Max Fill Secs"
></Input>
</Modal.Content>
<Modal.Separator />
<Modal.Content className="flex items-center space-x-2 justify-end">
<Button
type="default"
htmlType="button"
disabled={isCreating}
onClick={() => onClose()}
>
Cancel
</Button>
<Button type="primary" htmlType="submit" loading={isCreating} disabled={isCreating}>
Create
</Button>
</Modal.Content>
</>
)
}}
</Form>
</Modal>
)
}
export default CreatePipelineModal
@@ -0,0 +1,51 @@
import { useParams } from 'common'
import { useDeletePipelineMutation } from 'data/replication/delete-pipeline-mutation'
import { toast } from 'sonner'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
export type DeletePipelineModalProps = {
visible: boolean
title: string
pipelineId: number
onClose: () => void
}
export const DeletePipelineModal = ({
visible,
title,
pipelineId,
onClose,
}: DeletePipelineModalProps) => {
const { ref } = useParams()
const { mutate: deletePipeline, isLoading: isCreating } = useDeletePipelineMutation({
onSuccess: (res) => {
toast.success('Successfully deleted pipeline')
onClose()
},
})
const onConfirm = () => {
deletePipeline({
projectRef: ref!,
pipelineId,
})
}
return (
<ConfirmationModal
variant="destructive"
visible={visible}
title={title}
confirmLabel="Delete"
confirmLabelLoading="Deleting"
onCancel={() => {
onClose()
}}
onConfirm={onConfirm}
>
<div className="space-y-4">
<p className="text-sm text-foreground-light">
Are you sure you want to delete the selected pipeline? This action cannot be undone.
</p>
</div>
</ConfirmationModal>
)
}
@@ -8,6 +8,8 @@ import Table from 'components/to-be-cleaned/Table'
import { useState } from 'react'
import { toast } from 'sonner'
import { Button } from 'ui'
import { DeletePipelineModal } from './DeletePipepineModal'
import CreatePipelineModal from './CreatePipelineModal'
export const ReplicationPipelines = () => {
const { ref } = useParams()
@@ -94,6 +96,16 @@ export const ReplicationPipelines = () => {
</div>
</ScaffoldSection>
</ScaffoldContainer>
<CreatePipelineModal
visible={showCreatePipelineModal}
onClose={() => setShowCreatePipelineModal(false)}
/>
<DeletePipelineModal
visible={showDeletePipelineModal}
title={`Delete pipeline with id ${pipelineIdToDelete}?`}
pipelineId={pipelineIdToDelete}
onClose={() => setShowDeletePipelineModal(false)}
/>
</>
)
}
@@ -0,0 +1,72 @@
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import type { ResponseError } from 'types'
import { replicationKeys } from './keys'
import { handleError, post } from 'data/fetchers'
export type CreatePipelineParams = {
projectRef: string
source_id: number
sink_id: number
publication_name: string
config: { config: { max_size: number; max_fill_secs: number } }
}
async function createPipeline(
{
projectRef,
source_id,
sink_id,
publication_name,
config: {
config: { max_size, max_fill_secs },
},
}: CreatePipelineParams,
signal?: AbortSignal
) {
if (!projectRef) throw new Error('projectRef is required')
const { data, error } = await post('/platform/replication/{ref}/pipelines', {
params: { path: { ref: projectRef } },
body: { source_id, sink_id, publication_name, config: { config: { max_size, max_fill_secs } } },
signal,
})
if (error) {
handleError(error)
}
return data
}
type CreatePipelineData = Awaited<ReturnType<typeof createPipeline>>
export const useCreatePipelineMutation = ({
onSuccess,
onError,
...options
}: Omit<
UseMutationOptions<CreatePipelineData, ResponseError, CreatePipelineParams>,
'mutationFn'
> = {}) => {
const queryClient = useQueryClient()
return useMutation<CreatePipelineData, ResponseError, CreatePipelineParams>(
(vars) => createPipeline(vars),
{
async onSuccess(data, variables, context) {
const { projectRef } = variables
await queryClient.invalidateQueries(replicationKeys.pipelines(projectRef))
await onSuccess?.(data, variables, context)
},
async onError(data, variables, context) {
if (onError === undefined) {
toast.error(`Failed to create pipeline: ${data.message}`)
} else {
onError(data, variables, context)
}
},
...options,
}
)
}
@@ -0,0 +1,60 @@
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 DeletePipelineParams = {
projectRef: string
pipelineId: number
}
async function deletePipeline(
{ projectRef, pipelineId }: DeletePipelineParams,
signal?: AbortSignal
) {
if (!projectRef) throw new Error('projectRef is required')
const { data, error } = await del('/platform/replication/{ref}/pipelines/{pipeline_id}', {
params: { path: { ref: projectRef, pipeline_id: pipelineId } },
signal,
})
if (error) {
handleError(error)
}
return data
}
type DeletePipelineData = Awaited<ReturnType<typeof deletePipeline>>
export const useDeletePipelineMutation = ({
onSuccess,
onError,
...options
}: Omit<
UseMutationOptions<DeletePipelineData, ResponseError, DeletePipelineParams>,
'mutationFn'
> = {}) => {
const queryClient = useQueryClient()
return useMutation<DeletePipelineData, ResponseError, DeletePipelineParams>(
(vars) => deletePipeline(vars),
{
async onSuccess(data, variables, context) {
const { projectRef } = variables
await queryClient.invalidateQueries(replicationKeys.pipelines(projectRef))
await onSuccess?.(data, variables, context)
},
async onError(data, variables, context) {
if (onError === undefined) {
toast.error(`Failed to delete pipeline: ${data.message}`)
} else {
onError(data, variables, context)
}
},
...options,
}
)
}