diff --git a/frontend/src/components/queues/QueueTable/QueueTable.jsx b/frontend/src/components/queues/QueueTable/QueueTable.jsx index ac2455b..d4296ff 100644 --- a/frontend/src/components/queues/QueueTable/QueueTable.jsx +++ b/frontend/src/components/queues/QueueTable/QueueTable.jsx @@ -1,9 +1,11 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { TableContainer, Table, TableBody, Paper, + TableRow, + TableCell, useTheme, alpha, } from "@mui/material"; @@ -23,12 +25,20 @@ const QueueTable = ({ uniqueStates, handleFilterClose, setAnchorEl, - handleDelete, + onQueueUpdate, }) => { const theme = useTheme(); + + const [queues, setQueues] = useState([]); + + useEffect(() => { + setQueues(sortedQueues); + }, [sortedQueues]); + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); const [queueToDelete, setQueueToDelete] = useState(null); - + const [deleteError, setDeleteError] = useState(null); + const [isDeleting, setIsDeleting] = useState(false); const handleOpenDeleteDialog = (queueName) => { setQueueToDelete(queueName); setOpenDeleteDialog(true); @@ -37,13 +47,77 @@ const QueueTable = ({ const handleCloseDeleteDialog = () => { setOpenDeleteDialog(false); setQueueToDelete(null); + setDeleteError(null); + setIsDeleting(false); }; - const confirmDelete = () => { - if (handleDelete && queueToDelete) { - handleDelete(queueToDelete); + const handleDelete = async () => { + try { + setIsDeleting(true); + + const response = await fetch( + `/api/queues/${encodeURIComponent(queueToDelete)}`, + { + method: "DELETE", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + }, + ); + + let data = {}; + const contentType = response.headers.get("content-type"); + const text = await response.text(); + + let isJsonResponse = false; + try { + if ( + (contentType && contentType.includes("application/json")) || + (text && !text.trim().startsWith("<")) + ) { + data = text ? JSON.parse(text) : {}; + isJsonResponse = true; + } + } catch (parseError) { + console.warn("Failed to parse response as JSON:", parseError); + } + + if (!response.ok) { + let customMessage = `queues.scheduling.volcano.sh "${queueToDelete}" is forbidden.`; + let errorType = "UnknownError"; + + if ( + isJsonResponse && + typeof data === "object" && + (data.message || data.details) + ) { + customMessage = data.message || data.details; + if (customMessage.toLowerCase().includes("denied")) { + errorType = "ValidationError"; + } else { + errorType = "KubernetesError"; + } + } + + const fullMessage = `Cannot delete "${queueToDelete}". Error message: ${customMessage}`; + const error = new Error(fullMessage); + error.type = errorType; + error.status = response.status; + throw error; + } + + // Success + setQueues((prev) => + prev.filter((queue) => queue.metadata.name !== queueToDelete), + ); + handleCloseDeleteDialog(); + } catch (error) { + console.error("Error deleting queue:", error); + setDeleteError(error.message || "An unexpected error occurred."); + } finally { + setIsDeleting(false); } - handleCloseDeleteDialog(); }; return ( @@ -94,23 +168,39 @@ const QueueTable = ({ setAnchorEl={setAnchorEl} /> - {sortedQueues.map((queue) => ( - - ))} + {queues.length === 0 ? ( + + + No queues found. + + + ) : ( + queues.map((queue) => ( + + )) + )} );