delete project
This commit is contained in:
@@ -26,8 +26,10 @@ app.use("/", indexRoute);
|
|||||||
// "/projects"
|
// "/projects"
|
||||||
const projectsIndexRoute = require('./routes/projects/index')(sequelize);
|
const projectsIndexRoute = require('./routes/projects/index')(sequelize);
|
||||||
const projectsNewRoute = require('./routes/projects/new')(sequelize);
|
const projectsNewRoute = require('./routes/projects/new')(sequelize);
|
||||||
|
const projectsDeleteRoute = require('./routes/projects/delete')(sequelize);
|
||||||
app.use('/projects', projectsIndexRoute);
|
app.use('/projects', projectsIndexRoute);
|
||||||
app.use('/projects', projectsNewRoute);
|
app.use('/projects', projectsNewRoute);
|
||||||
|
app.use('/projects', projectsDeleteRoute);
|
||||||
|
|
||||||
// "/folders"
|
// "/folders"
|
||||||
const foldersIndexRoute = require('./routes/folders/index')(sequelize);
|
const foldersIndexRoute = require('./routes/folders/index')(sequelize);
|
||||||
|
|||||||
29
backend/routes/projects/delete.js
Normal file
29
backend/routes/projects/delete.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
const defineProject = require("../../models/projects");
|
||||||
|
const { DataTypes } = require("sequelize");
|
||||||
|
|
||||||
|
module.exports = function (sequelize) {
|
||||||
|
const Project = defineProject(sequelize, DataTypes);
|
||||||
|
|
||||||
|
router.delete("/:projectId", async (req, res) => {
|
||||||
|
const projectId = req.params.projectId;
|
||||||
|
try {
|
||||||
|
const project = await Project.findOne({
|
||||||
|
where: {
|
||||||
|
id: projectId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!project) {
|
||||||
|
return res.status(404).send("Project not found");
|
||||||
|
}
|
||||||
|
await project.destroy();
|
||||||
|
res.status(204).send();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
res.status(500).send("Internal Server Error");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return router;
|
||||||
|
};
|
||||||
@@ -79,6 +79,27 @@ async function createProject(name, detail) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function deleteProject(projectId: number) {
|
||||||
|
const fetchOptions = {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const url = `${apiServer}/projects/${projectId}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, fetchOptions);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting project:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function ProjectsPage() {
|
export default function ProjectsPage() {
|
||||||
// projects
|
// projects
|
||||||
const [projects, setProjects] = useState([]);
|
const [projects, setProjects] = useState([]);
|
||||||
@@ -144,6 +165,15 @@ export default function ProjectsPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onDeleteClicked = async (projectId: number) => {
|
||||||
|
try {
|
||||||
|
await deleteProject(projectId);
|
||||||
|
setProjects(projects.filter((project) => project.id !== projectId));
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting project:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto max-w-7xl pt-16 px-6 flex-grow">
|
<div className="container mx-auto max-w-7xl pt-16 px-6 flex-grow">
|
||||||
<div className="flex h-full items-center">
|
<div className="flex h-full items-center">
|
||||||
@@ -157,15 +187,20 @@ export default function ProjectsPage() {
|
|||||||
{projects.map((project, index) => (
|
{projects.map((project, index) => (
|
||||||
<ProjectCard
|
<ProjectCard
|
||||||
key={index}
|
key={index}
|
||||||
projectName={project.name}
|
project={project}
|
||||||
projectDetail={project.detail}
|
onDeleteClicked={onDeleteClicked}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Modal isOpen={isCreateDialogOpen}>
|
<Modal
|
||||||
|
isOpen={isCreateDialogOpen}
|
||||||
|
onOpenChange={() => {
|
||||||
|
setIsCreateDialogOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ModalContent>
|
<ModalContent>
|
||||||
<ModalHeader className="flex flex-col gap-1">Modal Title</ModalHeader>
|
<ModalHeader className="flex flex-col gap-1">Project</ModalHeader>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -194,7 +229,7 @@ export default function ProjectsPage() {
|
|||||||
/>
|
/>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
<Button color="danger" variant="light" onPress={closeModal}>
|
<Button variant="light" onPress={closeModal}>
|
||||||
Close
|
Close
|
||||||
</Button>
|
</Button>
|
||||||
<Button color="primary" onPress={onCreateClicked}>
|
<Button color="primary" onPress={onCreateClicked}>
|
||||||
|
|||||||
@@ -1,34 +1,55 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
|
Link,
|
||||||
|
Button,
|
||||||
|
Dropdown,
|
||||||
|
DropdownTrigger,
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownItem,
|
||||||
Card,
|
Card,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardBody,
|
CardBody,
|
||||||
Divider,
|
Divider,
|
||||||
Image,
|
|
||||||
} from "@nextui-org/react";
|
} from "@nextui-org/react";
|
||||||
import NextLink from "next/link";
|
import { DotsIcon } from "@/components/icons";
|
||||||
|
|
||||||
export function ProjectCard({ projectName, projectDetail }) {
|
export function ProjectCard({ project, onDeleteClicked }) {
|
||||||
return (
|
return (
|
||||||
<NextLink href={`/projects/${1}/home`}>
|
<Card className="w-[250px]">
|
||||||
<Card className="w-[250px] bg-white hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-800">
|
<CardHeader className="flex gap-3 h-[50px] justify-between text-ellipsis overflow-hidden">
|
||||||
<CardHeader className="flex gap-3">
|
<div className="flex gap-5">
|
||||||
<Image
|
<div className="flex flex-col gap-1 items-start justify-center">
|
||||||
alt="nextui logo"
|
<Link href={`/projects/${project.id}/home`}>{project.name}</Link>
|
||||||
height={40}
|
|
||||||
radius="sm"
|
|
||||||
src="https://avatars.githubusercontent.com/u/86160567?s=200&v=4"
|
|
||||||
width={40}
|
|
||||||
/>
|
|
||||||
<div className="flex flex-col">
|
|
||||||
<p className="text-md">{projectName}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</div>
|
||||||
<Divider />
|
<Dropdown>
|
||||||
<CardBody>
|
<DropdownTrigger>
|
||||||
<p>{projectDetail}</p>
|
<Button
|
||||||
</CardBody>
|
isIconOnly
|
||||||
</Card>
|
variant="light"
|
||||||
</NextLink>
|
size="sm"
|
||||||
|
className="text-transparent hover:text-inherit"
|
||||||
|
>
|
||||||
|
<DotsIcon size={16} />
|
||||||
|
</Button>
|
||||||
|
</DropdownTrigger>
|
||||||
|
<DropdownMenu aria-label="Static Actions">
|
||||||
|
<DropdownItem key="edit">Edit project</DropdownItem>
|
||||||
|
<DropdownItem
|
||||||
|
key="delete"
|
||||||
|
className="text-danger"
|
||||||
|
color="danger"
|
||||||
|
onClick={() => onDeleteClicked(project.id)}
|
||||||
|
>
|
||||||
|
Delete project
|
||||||
|
</DropdownItem>
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
|
</CardHeader>
|
||||||
|
<Divider />
|
||||||
|
<CardBody className="h-[50px] text-ellipsis overflow-hidden">
|
||||||
|
<p>{project.detail}</p>
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,3 +284,22 @@ export const FolderIcon: React.FC<IconSvgProps> = ({
|
|||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DotsIcon: React.FC<IconSvgProps> = ({
|
||||||
|
size = 24,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
height={size || height}
|
||||||
|
width={size || height}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path d="M12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 12c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user