From eeeade074588ad6e200c13929b81fd084108c982 Mon Sep 17 00:00:00 2001 From: Andrew Davison Date: Fri, 26 Jan 2024 11:35:44 +0100 Subject: [PATCH] Allow users to delete jobs (actually just hidden, they still appear in statistics, and can be recovered by an admin if necessary). --- src/components/ConfirmationDialog.jsx | 26 ++++++++++++++++++++ src/components/JobDetail.jsx | 34 ++++++++++++++++++++++++--- src/datastore.js | 15 ++++++++++++ 3 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 src/components/ConfirmationDialog.jsx diff --git a/src/components/ConfirmationDialog.jsx b/src/components/ConfirmationDialog.jsx new file mode 100644 index 0000000..2a1c8e0 --- /dev/null +++ b/src/components/ConfirmationDialog.jsx @@ -0,0 +1,26 @@ +import React from "react"; +import Button from "@mui/material/Button"; +import Dialog from "@mui/material/Dialog"; +import DialogActions from "@mui/material/DialogActions"; +import DialogContent from "@mui/material/DialogContent"; +import DialogContentText from "@mui/material/DialogContentText"; + +export default function AlertDialog(props) { + return ( + + props.onClose(false)}> + + {props.content} + + + + + + + + ); +} diff --git a/src/components/JobDetail.jsx b/src/components/JobDetail.jsx index 7273cfe..539d963 100644 --- a/src/components/JobDetail.jsx +++ b/src/components/JobDetail.jsx @@ -1,9 +1,10 @@ -import { useContext, useEffect } from "react"; -import { Link as RouterLink, useRevalidator } from "react-router-dom"; +import { useContext, useEffect, useState } from "react"; +import { Link as RouterLink, useRevalidator, useNavigate } from "react-router-dom"; import { Box, IconButton, Tooltip, Typography } from "@mui/material"; import { ArrowBack, + Delete as DeleteIcon, Launch as LaunchIcon, LocationOn as LocationOnIcon, DeveloperBoard as DeveloperBoardIcon, @@ -11,7 +12,7 @@ import { } from "@mui/icons-material"; import { timeFormat, isEmpty, jobIsIncomplete } from "../utils"; -import { addTag, deleteTag } from "../datastore"; +import { addTag, deleteTag, hideJob } from "../datastore"; import { AuthContext } from "../context"; import StatusChip from "./StatusChip"; import Panel from "./Panel"; @@ -21,11 +22,14 @@ import LogPanel from "./LogPanel"; import CommentsPanel from "./CommentsPanel"; import KeyValueTable from "./KeyValueTable"; import TagDisplay from "./TagDisplay"; +import ConfirmationDialog from "./ConfirmationDialog"; function JobDetail(props) { const { job, collab } = props; const revalidator = useRevalidator(); const auth = useContext(AuthContext); + const navigate = useNavigate(); + const [dialogOpen, setDialogOpen] = useState(false); useEffect(() => { if (jobIsIncomplete(job) && revalidator.state === "idle") { @@ -57,6 +61,18 @@ function JobDetail(props) { } }; + const handleRequestHideJob = () => { + setDialogOpen(true); + }; + + const handleConfirmHideJob = async (confirmed) => { + setDialogOpen(false); + if (confirmed) { + await hideJob(collab, job.id, auth); + navigate(`/${collab}/jobs/`); + } + }; + return ( @@ -64,11 +80,17 @@ function JobDetail(props) { Job #{job.id} +   + + + + + @@ -124,6 +146,12 @@ function JobDetail(props) { + + ); } diff --git a/src/datastore.js b/src/datastore.js index 402fc28..f16f6da 100644 --- a/src/datastore.js +++ b/src/datastore.js @@ -127,6 +127,20 @@ async function createJob(collabId, jobData, auth) { } } +async function hideJob(collabId, jobId, auth) { + const url = jobQueueServer + "/jobs/" + jobId; + let config = getRequestConfig(auth); + config.method = "DELETE"; + const response = await fetch(url, config); + if (response.ok) { + // remove from cache + delete cache.jobs[collabId][jobId]; + return "success"; + } else { + throw new Error("hiding job was not successful"); + } +} + async function getLog(jobId, auth) { if (!(jobId in cache.logs)) { let url = jobQueueServer + "/jobs/" + jobId + "/log"; @@ -309,6 +323,7 @@ export { queryTags, getJob, createJob, + hideJob, getLog, getComments, createComment,