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

Commit

Permalink
Add 'delete volume' similar to delete table (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
xx-db authored Jul 30, 2024
1 parent d8d0acb commit b0edba9
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 6 deletions.
67 changes: 67 additions & 0 deletions src/components/modals/DeleteVolumeModal.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 { useDeleteVolume } from '../../hooks/volumes';
import { useNotification } from '../../utils/NotificationContext';

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

export function DeleteVolumeModal({
open,
closeModal,
catalog,
schema,
volume,
}: DeleteVolumeModalProps) {
const navigate = useNavigate();
const { setNotification } = useNotification();
const mutation = useDeleteVolume({
onSuccessCallback: () => {
setNotification(`${volume} volume successfully deleted`, 'success');
navigate(`/data/${catalog}/${schema}`);
},
catalog,
schema,
});

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

return (
<Modal
title={
<Typography.Title type={'danger'} level={4}>
Delete volume
</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 volume
</Typography.Text>
<Typography.Text strong>{` ${volume}`}</Typography.Text>
<Typography.Text>? This operation cannot be undone.</Typography.Text>
</Modal>
);
}
63 changes: 63 additions & 0 deletions src/components/volumes/VolumeActionsDropdown.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 { DeleteVolumeModal } from '../modals/DeleteVolumeModal';

interface VolumeActionDropdownProps {
catalog: string;
schema: string;
volume: string;
}

enum VolumeActionsEnum {
Delete,
}

export default function VolumeActionsDropdown({
catalog,
schema,
volume,
}: VolumeActionDropdownProps) {
const [dropdownVisible, setDropdownVisible] = useState<boolean>(false);
const [action, setAction] = useState<VolumeActionsEnum | null>(null);

const menuItems = useMemo(
(): MenuProps['items'] => [
{
key: 'deleteVolume',
label: 'Delete Volume',
onClick: () => setAction(VolumeActionsEnum.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>
<DeleteVolumeModal
open={action === VolumeActionsEnum.Delete}
closeModal={() => setAction(null)}
catalog={catalog}
schema={schema}
volume={volume}
/>
</>
);
}
58 changes: 55 additions & 3 deletions src/hooks/volumes.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { useQuery, UseQueryOptions } from '@tanstack/react-query';
import {
useQuery,
useMutation,
useQueryClient,
UseQueryOptions,
} from '@tanstack/react-query';
import { UC_API_PREFIX } from '../utils/constants';

export interface VolumeInterface {
Expand All @@ -11,6 +16,7 @@ export interface VolumeInterface {
created_at: number;
updated_at: number | null;
}

interface ListVolumesResponse {
volumes: VolumeInterface[];
next_page_token: string | null;
Expand All @@ -36,7 +42,7 @@ export function useListVolumes({
});

const response = await fetch(
`${UC_API_PREFIX}/volumes?${searchParams.toString()}`
`${UC_API_PREFIX}/volumes?${searchParams.toString()}`,
);
return response.json();
},
Expand All @@ -57,9 +63,55 @@ export function useGetVolume({ catalog, schema, volume }: GetVolumeParams) {
const fullVolumeName = [catalog, schema, volume].join('.');

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

export interface DeleteVolumeMutationParams
extends Pick<VolumeInterface, 'catalog_name' | 'schema_name' | 'name'> {}

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

// Delete a volume
export function useDeleteVolume({
onSuccessCallback,
catalog,
schema,
}: DeleteVolumeParams) {
const queryClient = useQueryClient();

return useMutation<void, Error, DeleteVolumeMutationParams>({
mutationFn: async ({
catalog_name,
schema_name,
name,
}: DeleteVolumeMutationParams) => {
const response = await fetch(
`${UC_API_PREFIX}/volumes/${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 volume');
}
},
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['listVolumes', catalog, schema],
});
onSuccessCallback?.();
},
});
}
14 changes: 11 additions & 3 deletions src/pages/VolumeDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import DescriptionBox from '../components/DescriptionBox';
import { useGetVolume } from '../hooks/volumes';
import VolumeSidebar from '../components/volumes/VolumeSidebar';
import { FolderOutlined } from '@ant-design/icons';
import VolumeActionsDropdown from '../components/volumes/VolumeActionsDropdown';

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

0 comments on commit b0edba9

Please sign in to comment.