diff --git a/ui/src/app/api/datasets/delete/route.tsx b/ui/src/app/api/datasets/delete/route.tsx new file mode 100644 index 00000000..a35b2182 --- /dev/null +++ b/ui/src/app/api/datasets/delete/route.tsx @@ -0,0 +1,24 @@ +import { NextResponse } from 'next/server'; +import fs from 'fs'; +import path from 'path'; +import { getDatasetsRoot } from '@/app/api/datasets/utils'; + +export async function POST(request: Request) { + try { + const body = await request.json(); + const { name } = body; + let datasetsPath = await getDatasetsRoot(); + let datasetPath = path.join(datasetsPath, name); + + // if folder doesnt exist, ignore + if (!fs.existsSync(datasetPath)) { + return NextResponse.json({ success: true }); + } + + // delete it and return success + fs.rmdirSync(datasetPath, { recursive: true }); + return NextResponse.json({ success: true }); + } catch (error) { + return NextResponse.json({ error: 'Failed to create dataset' }, { status: 500 }); + } +} diff --git a/ui/src/app/datasets/page.tsx b/ui/src/app/datasets/page.tsx index b5304c04..77851c18 100644 --- a/ui/src/app/datasets/page.tsx +++ b/ui/src/app/datasets/page.tsx @@ -1,11 +1,13 @@ 'use client'; import { useEffect, useState } from 'react'; -import Card from '@/components/Card'; import { Modal } from '@/components/Modal'; import Link from 'next/link'; import { TextInput } from '@/components/formInputs'; import useDatasetList from '@/hooks/useDatasetList'; +import { Button } from '@headlessui/react'; +import { FaRegTrashAlt } from 'react-icons/fa'; +import { openConfirm } from '@/components/ConfirmModal'; export default function Datasets() { const { datasets, status, refreshDatasets } = useDatasetList(); @@ -13,36 +15,70 @@ export default function Datasets() { const [isNewDatasetModalOpen, setIsNewDatasetModalOpen] = useState(false); return ( <> -
-
-
-

Datasets

-
-
- -
+
+
+

Datasets

- - {status === 'loading' &&

Loading...

} - {status === 'error' &&

Error fetching datasets

} - {status === 'success' && ( -
- {datasets.length === 0 &&

No datasets found

} - {datasets.map((dataset: string) => ( - - {dataset} - - ))} -
- )} -
+
+
+ +
+
+
+ {status === 'loading' &&

Loading...

} + {status === 'error' &&

Error fetching datasets

} + {status === 'success' && ( +
+ {datasets.length === 0 &&

No datasets found

} + {datasets.map((dataset: string) => ( +
+
+ + {dataset} + +
+
+
+ +
+
+ ))} +
+ )}
(null); +export const openConfirm = (confirmProps: ConfirmState) => { + confirmstate.set(confirmProps); +}; export default function ConfirmModal() { - const [confirm, setConfirm] = confirmstate.use(); - const open = confirm !== null; + const [isOpen, setIsOpen] = useState(false); + + useEffect(() => { + if (confirm) { + setIsOpen(true); + } + }, [confirm]); + + useEffect(() => { + if (!isOpen) { + // use timeout to allow the dialog to close before resetting the state + setTimeout(() => { + setConfirm(null); + }, 500); + } + }, [isOpen]); const onCancel = () => { if (confirm?.onCancel) { confirm.onCancel(); } - setConfirm(null); + setIsOpen(false); }; const onConfirm = () => { if (confirm?.onConfirm) { confirm.onConfirm(); } - setConfirm(null); + setIsOpen(false); }; let Icon = FaExclamationTriangle; @@ -46,45 +63,61 @@ export default function ConfirmModal() { // Color mapping for background colors const getBgColor = () => { switch (color) { - case 'danger': return 'bg-red-500'; - case 'warning': return 'bg-yellow-500'; - case 'info': return 'bg-blue-500'; - default: return 'bg-red-500'; + case 'danger': + return 'bg-red-500'; + case 'warning': + return 'bg-yellow-500'; + case 'info': + return 'bg-blue-500'; + default: + return 'bg-red-500'; } }; // Color mapping for text colors const getTextColor = () => { switch (color) { - case 'danger': return 'text-red-950'; - case 'warning': return 'text-yellow-950'; - case 'info': return 'text-blue-950'; - default: return 'text-red-950'; + case 'danger': + return 'text-red-950'; + case 'warning': + return 'text-yellow-950'; + case 'info': + return 'text-blue-950'; + default: + return 'text-red-950'; } }; // Color mapping for titles const getTitleColor = () => { switch (color) { - case 'danger': return 'text-red-500'; - case 'warning': return 'text-yellow-500'; - case 'info': return 'text-blue-500'; - default: return 'text-red-500'; + case 'danger': + return 'text-red-500'; + case 'warning': + return 'text-yellow-500'; + case 'info': + return 'text-blue-500'; + default: + return 'text-red-500'; } }; // Button background color mapping const getButtonBgColor = () => { switch (color) { - case 'danger': return 'bg-red-700 hover:bg-red-500'; - case 'warning': return 'bg-yellow-700 hover:bg-yellow-500'; - case 'info': return 'bg-blue-700 hover:bg-blue-500'; - default: return 'bg-red-700 hover:bg-red-500'; + case 'danger': + return 'bg-red-700 hover:bg-red-500'; + case 'warning': + return 'bg-yellow-700 hover:bg-yellow-500'; + case 'info': + return 'bg-blue-700 hover:bg-blue-500'; + default: + return 'bg-red-700 hover:bg-red-500'; } }; return ( - +
-
+
@@ -106,9 +141,7 @@ export default function ConfirmModal() { {confirm?.title}
-

- {confirm?.message} -

+

{confirm?.message}

@@ -116,7 +149,7 @@ export default function ConfirmModal() {
); -} \ No newline at end of file +}