implemented bulk deletion of cases
This commit is contained in:
@@ -55,11 +55,13 @@ const casesShowRoute = require("./routes/cases/show")(sequelize);
|
||||
const casesNewRoute = require("./routes/cases/new")(sequelize);
|
||||
const casesEditRoute = require("./routes/cases/edit")(sequelize);
|
||||
const casesDeleteRoute = require("./routes/cases/delete")(sequelize);
|
||||
const casesBulkDeleteRoute = require("./routes/cases/bulkDelete")(sequelize);
|
||||
app.use("/cases", casesIndexRoute);
|
||||
app.use("/cases", casesShowRoute);
|
||||
app.use("/cases", casesNewRoute);
|
||||
app.use("/cases", casesEditRoute);
|
||||
app.use("/cases", casesDeleteRoute);
|
||||
app.use("/cases", casesBulkDeleteRoute);
|
||||
|
||||
// "/steps"
|
||||
const stepsNewRoute = require("./routes/steps/new")(sequelize);
|
||||
|
||||
25
backend/routes/cases/bulkDelete.js
Normal file
25
backend/routes/cases/bulkDelete.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const defineCase = require("../../models/cases");
|
||||
const { DataTypes } = require("sequelize");
|
||||
|
||||
module.exports = function (sequelize) {
|
||||
const Case = defineCase(sequelize, DataTypes);
|
||||
|
||||
router.post("/bulkdelete", async (req, res) => {
|
||||
const { caseIds } = req.body;
|
||||
if (!caseIds || !Array.isArray(caseIds)) {
|
||||
return res.status(400).send("Invalid caseIds array");
|
||||
}
|
||||
|
||||
try {
|
||||
await Case.destroy({ where: { id: caseIds } });
|
||||
res.status(204).send();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).send("Internal Server Error");
|
||||
}
|
||||
});
|
||||
|
||||
return router;
|
||||
};
|
||||
@@ -89,6 +89,28 @@ async function fetchDeleteCase(caseId: number) {
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchDeleteCases(deleteCases: string[]) {
|
||||
const fetchOptions = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ caseIds: deleteCases }),
|
||||
};
|
||||
|
||||
const url = `${apiServer}/cases/bulkdelete`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, fetchOptions);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error deleting cases:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export default function Page({
|
||||
params,
|
||||
}: {
|
||||
@@ -123,6 +145,12 @@ export default function Page({
|
||||
setCases(data);
|
||||
};
|
||||
|
||||
const handleDeleteCases = async (deleteCases: string[]) => {
|
||||
await fetchDeleteCases(deleteCases);
|
||||
const data = await fetchCases(url);
|
||||
setCases(data);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TestCaseTable
|
||||
@@ -130,6 +158,7 @@ export default function Page({
|
||||
cases={cases}
|
||||
onCreateCase={() => handleCreateCase(params.folderId)}
|
||||
onDeleteCase={handleDeleteCase}
|
||||
onDeleteCases={handleDeleteCases}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
SortDescriptor,
|
||||
Link,
|
||||
} from "@nextui-org/react";
|
||||
import { Plus, MoreVertical } from "lucide-react";
|
||||
import { Plus, MoreVertical, Trash } from "lucide-react";
|
||||
|
||||
const headerColumns = [
|
||||
{ name: "ID", uid: "id", sortable: true },
|
||||
@@ -48,9 +48,16 @@ type Props = {
|
||||
cases: Case[];
|
||||
onCreateCase: () => void;
|
||||
onDeleteCase: (caseId: number) => void;
|
||||
onDeleteCases: (selectedCases: string[]) => void;
|
||||
};
|
||||
|
||||
export default function TestCaseTable({ projectId, cases, onCreateCase, onDeleteCase }: Props) {
|
||||
export default function TestCaseTable({
|
||||
projectId,
|
||||
cases,
|
||||
onCreateCase,
|
||||
onDeleteCase,
|
||||
onDeleteCases,
|
||||
}: Props) {
|
||||
const [selectedKeys, setSelectedKeys] = useState<Selection>(new Set([]));
|
||||
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
|
||||
column: "id",
|
||||
@@ -102,7 +109,10 @@ export default function TestCaseTable({ projectId, cases, onCreateCase, onDelete
|
||||
</Button>
|
||||
</DropdownTrigger>
|
||||
<DropdownMenu aria-label="test case actions">
|
||||
<DropdownItem className="text-danger" onClick={() => onDeleteCase(testCase.id)}>
|
||||
<DropdownItem
|
||||
className="text-danger"
|
||||
onClick={() => onDeleteCase(testCase.id)}
|
||||
>
|
||||
Delete test case
|
||||
</DropdownItem>
|
||||
</DropdownMenu>
|
||||
@@ -132,12 +142,27 @@ export default function TestCaseTable({ projectId, cases, onCreateCase, onDelete
|
||||
[]
|
||||
);
|
||||
|
||||
const onDeleteCasesClick = async() => {
|
||||
setSelectedKeys(new Set([]));
|
||||
onDeleteCases([...selectedKeys])
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="border-b-1 dark:border-neutral-700 w-full p-3 flex items-center justify-between">
|
||||
<h3 className="font-bold">
|
||||
Cases
|
||||
</h3>
|
||||
<h3 className="font-bold">Cases</h3>
|
||||
<div>
|
||||
{selectedKeys.size > 0 && (
|
||||
<Button
|
||||
startContent={<Trash size={16} />}
|
||||
size="sm"
|
||||
color="danger"
|
||||
className="me-2"
|
||||
onClick={onDeleteCasesClick}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
startContent={<Plus size={16} />}
|
||||
size="sm"
|
||||
@@ -147,6 +172,7 @@ export default function TestCaseTable({ projectId, cases, onCreateCase, onDelete
|
||||
New Test Case
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Table
|
||||
isCompact
|
||||
|
||||
Reference in New Issue
Block a user