Skip to content
This repository has been archived by the owner on Sep 6, 2024. It is now read-only.

Commit

Permalink
Add 'delete function' similar to delete table (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
xx-db authored Jul 29, 2024
1 parent d0e9119 commit d8d0acb
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 6 deletions.
63 changes: 63 additions & 0 deletions src/components/functions/FunctionActionsDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { DeleteOutlined, MoreOutlined } from '@ant-design/icons';
import { Button, Dropdown, MenuProps } from 'antd';
import { useMemo, useState } from 'react';
import { DeleteFunctionModal } from '../modals/DeleteFunctionModal';

interface FunctionActionDropdownProps {
catalog: string;
schema: string;
ucFunction: string;
}

enum FunctionActionsEnum {
Delete,
}

export default function FunctionActionsDropdown({
catalog,
schema,
ucFunction,
}: FunctionActionDropdownProps) {
const [dropdownVisible, setDropdownVisible] = useState<boolean>(false);
const [action, setAction] = useState<FunctionActionsEnum | null>(null);

const menuItems = useMemo(
(): MenuProps['items'] => [
{
key: 'deleteFunction',
label: 'Delete Function',
onClick: () => setAction(FunctionActionsEnum.Delete),
icon: <DeleteOutlined />,
danger: true,
},
],
[],
);

return (
<>
<Dropdown
menu={{ items: menuItems }}
trigger={['click']}
onOpenChange={() => setDropdownVisible(!dropdownVisible)}
>
<Button
type="text"
icon={
<MoreOutlined
rotate={dropdownVisible ? 90 : 0}
style={{ transition: 'transform 0.5s' }}
/>
}
/>
</Dropdown>
<DeleteFunctionModal
open={action === FunctionActionsEnum.Delete}
closeModal={() => setAction(null)}
catalog={catalog}
schema={schema}
ucFunction={ucFunction}
/>
</>
);
}
67 changes: 67 additions & 0 deletions src/components/modals/DeleteFunctionModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Modal, Typography } from 'antd';
import React, { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useDeleteFunction } from '../../hooks/functions';
import { useNotification } from '../../utils/NotificationContext';

interface DeleteFunctionModalProps {
open: boolean;
closeModal: () => void;
catalog: string;
schema: string;
ucFunction: string;
}

export function DeleteFunctionModal({
open,
closeModal,
catalog,
schema,
ucFunction,
}: DeleteFunctionModalProps) {
const navigate = useNavigate();
const { setNotification } = useNotification();
const mutation = useDeleteFunction({
onSuccessCallback: () => {
setNotification(`${ucFunction} function successfully deleted`, 'success');
navigate(`/data/${catalog}/${schema}`);
},
catalog,
schema,
});

const handleSubmit = useCallback(() => {
mutation.mutate(
{ catalog_name: catalog, schema_name: schema, name: ucFunction },
{
onError: (error: Error) => {
setNotification(error.message, 'error');
},
},
);
}, [mutation, ucFunction, setNotification]);

return (
<Modal
title={
<Typography.Title type={'danger'} level={4}>
Delete function
</Typography.Title>
}
okText="Delete"
okType="danger"
cancelText="Cancel"
open={open}
destroyOnClose
onCancel={closeModal}
onOk={handleSubmit}
okButtonProps={{ loading: mutation.isPending }}
>
<Typography.Text>
Are you sure you want to delete the function
</Typography.Text>
<Typography.Text strong>{` ${ucFunction}`}</Typography.Text>
<Typography.Text>? This operation cannot be undone.</Typography.Text>
</Modal>
);
}
57 changes: 54 additions & 3 deletions src/hooks/functions.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { useQuery, UseQueryOptions } from '@tanstack/react-query';
import {
useMutation,
useQuery,
useQueryClient,
UseQueryOptions,
} from '@tanstack/react-query';
import { UC_API_PREFIX } from '../utils/constants';

export interface FunctionInterface {
Expand Down Expand Up @@ -40,7 +45,7 @@ export function useListFunctions({
});

const response = await fetch(
`${UC_API_PREFIX}/functions?${searchParams.toString()}`
`${UC_API_PREFIX}/functions?${searchParams.toString()}`,
);
return response.json();
},
Expand All @@ -65,9 +70,55 @@ export function useGetFunction({
const fullFunctionName = [catalog, schema, ucFunction].join('.');

const response = await fetch(
`${UC_API_PREFIX}/functions/${fullFunctionName}`
`${UC_API_PREFIX}/functions/${fullFunctionName}`,
);
return response.json();
},
});
}

export interface DeleteFunctionMutationParams
extends Pick<FunctionInterface, 'catalog_name' | 'schema_name' | 'name'> {}

interface DeleteFunctionParams {
onSuccessCallback?: () => void;
catalog: string;
schema: string;
}

// Delete a function
export function useDeleteFunction({
onSuccessCallback,
catalog,
schema,
}: DeleteFunctionParams) {
const queryClient = useQueryClient();

return useMutation<void, Error, DeleteFunctionMutationParams>({
mutationFn: async ({
catalog_name,
schema_name,
name,
}: DeleteFunctionMutationParams) => {
const response = await fetch(
`${UC_API_PREFIX}/functions/${catalog_name}.${schema_name}.${name}`,
{
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
},
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to delete function');
}
},
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['listFunctions', catalog, schema],
});
onSuccessCallback?.();
},
});
}
14 changes: 11 additions & 3 deletions src/pages/FunctionDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import DescriptionBox from '../components/DescriptionBox';
import { Flex, Typography } from 'antd';
import { FunctionOutlined } from '@ant-design/icons';
import CodeBox from '../components/CodeBox';
import FunctionActionsDropdown from '../components/functions/FunctionActionsDropdown';

export default function FunctionDetails() {
const { catalog, schema, ucFunction } = useParams();
Expand All @@ -21,9 +22,16 @@ export default function FunctionDetails() {
return (
<DetailsLayout
title={
<Typography.Title level={3}>
<FunctionOutlined /> {ucFunction}
</Typography.Title>
<Flex justify="space-between" align="flex-start" gap="middle">
<Typography.Title level={3}>
<FunctionOutlined /> {ucFunction}
</Typography.Title>
<FunctionActionsDropdown
catalog={catalog}
schema={schema}
ucFunction={ucFunction}
/>
</Flex>
}
breadcrumbs={[
{ title: <Link to="/">Catalogs</Link>, key: '_home' },
Expand Down

0 comments on commit d8d0acb

Please sign in to comment.