Skip to content

Commit

Permalink
admin can now delete comments (#61)
Browse files Browse the repository at this point in the history
* admin can now delete comments

* made delete button red

* :refactored

* minor changes
  • Loading branch information
o-bm authored Apr 19, 2024
1 parent ee6ee40 commit a963528
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 81 deletions.
1 change: 1 addition & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Solution from "./pages/Solution.tsx";
import Profile from "./pages/Profile.tsx"
import Editor from "./pages/Editor.tsx";


const NAV_CONFIG = {
brand: "UML Mentor",
routes: [
Expand Down
23 changes: 23 additions & 0 deletions client/src/hooks/useCheckRole.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useState, useEffect } from 'react';

const useCheckRole = () => {
const [isAdmin, setIsAdmin] = useState(false);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
fetch("/api/users/whoami")
.then(response => response.json())
.then(data => {
setIsAdmin(data.role === 'admin');
setIsLoading(false);
})
.catch(error => {
console.error("Error fetching user role:", error);
setIsLoading(false);
});
}, []);

return { isAdmin, isLoading };
};

export default useCheckRole;
127 changes: 47 additions & 80 deletions client/src/pages/Solution.tsx
Original file line number Diff line number Diff line change
@@ -1,79 +1,31 @@
import React, { useState, useEffect } from "react";
import { Container, Row, Col, Form } from "react-bootstrap";
import { Container, Row, Col, Card } from "react-bootstrap";
import { useParams } from "react-router-dom";
import { SolutionData } from "../types/SolutionData.ts";
import { CommentData } from "../types/CommentData.ts";
import Card from "react-bootstrap/Card";
import Button from "../components/Button.tsx";
import Comment from "../components/Comment.tsx";
import useCheckRole from '../hooks/useCheckRole'; // Make sure the path is correct

function loadSolution(
id: string,
setter: React.Dispatch<React.SetStateAction<SolutionData | undefined>>,
) {
function loadSolution(id, setter) {
fetch(`/api/solutions/${id}`)
.then((resp) => resp.json())
.then((data: SolutionData) => {
setter(data);
})
.catch((err) => {
console.error(err);
});
.then(resp => resp.json())
.then(data => setter(data))
.catch(err => console.error(err));
}

function loadComments(
id: string,
setter: React.Dispatch<React.SetStateAction<CommentData[] | undefined>>,
) {
function loadComments(id, setter) {
fetch(`/api/comments/${id}`)
.then((resp) => resp.json())
.then((data: CommentData[]) => {
setter(data);
})
.catch((err) => {
console.error(err);
});
.then(resp => resp.json())
.then(data => setter(data))
.catch(err => console.error(err));
}

const Solution = () => {
const { id } = useParams(); // Id is the solution id
const [solutionData, setSolutionData] = useState<SolutionData>();
const [comments, setComments] = useState<CommentData[]>();

const handleSubmit = (parentId: number, text: string) => {
let promise = null;
if (parentId) {
promise = fetch(`/api/comments/reply/${parentId}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
solutionId: solutionData?.id,
text,
}),
});
} else {
promise = fetch(`/api/comments/${solutionData?.id}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
solutionId: solutionData?.id,
text,
}),
});
}

promise
.then(() => {
loadComments(id, setComments);
})
.catch((err) => {
console.error(err);
});
};
const { id } = useParams();
const [solutionData, setSolutionData] = useState(null);
const [comments, setComments] = useState([]);
const { isAdmin, isLoading } = useCheckRole();

useEffect(() => {
if (id) {
Expand All @@ -82,9 +34,31 @@ const Solution = () => {
}
}, [id]);

if (isLoading) {
return <div>Loading...</div>;
}

const handleDelete = (commentId) => {
if (!isAdmin) return;
fetch(`/api/comments/${commentId}`, { method: 'DELETE' })
.then(() => setComments(comments => comments.filter(comment => comment.id !== commentId)))
.catch(err => console.error('Failed to delete comment', err));
};

const handleSubmit = (parentId, text) => {
const endpoint = parentId ? `/api/comments/reply/${parentId}` : `/api/comments/${solutionData.id}`;
fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ solutionId: solutionData.id, text })
})
.then(() => loadComments(id, setComments))
.catch(err => console.error(err));
};

return (
<Container className={"my-5"} fluid={"sm"}>
<Row md={12} className={"justify-content-center"}>
<Container className="my-5" fluid="sm">
<Row className="justify-content-center">
<Col md={6}>
<h2>Solution</h2>
{solutionData && (
Expand All @@ -93,30 +67,23 @@ const Solution = () => {
<Card.Title>{solutionData.title}</Card.Title>
<Card.Text>{solutionData.description}</Card.Text>
{solutionData.diagram && (
<Card.Img
variant="bottom"
src={`/api/solutions/diagrams/${solutionData.diagram}`}
alt="Solution Diagram"
/>
<Card.Img variant="bottom" src={`/api/solutions/diagrams/${solutionData.diagram}`} alt="Solution Diagram" />
)}
</Card.Body>
</Card>
)}
</Col>
</Row>
<Row className={"mt-5 justify-content-center"} md={12}>
<Row className="mt-5 justify-content-center">
<Col md={6}>
<h2>Comments</h2>
<Comment editable={true} onSubmit={handleSubmit} />
{comments &&
comments.map((comment) => (
<Comment
key={comment.id}
comment={comment}
editable={false}
onSubmit={handleSubmit}
/>
))}
<Comment editable={true} onSubmit={handleSubmit} />ç
{comments.map(comment => (
<div key={comment.id}>
<Comment comment={comment} editable={false} onSubmit={handleSubmit} />
{isAdmin && <Button variant="danger" onClick={() => handleDelete(comment.id)}>Delete</Button>}
</div>
))}
</Col>
</Row>
</Container>
Expand Down
21 changes: 20 additions & 1 deletion server/controllers/UserController.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,28 @@ const db = require("../models/index");
const User = db.User;
//change
exports.getMe = async (req, res) => {
res.status(200).json({ username: req.headers.utorid });
try {
const username = req.headers.utorid;
if (!username) {
return res.status(401).send('Authentication required');
}

const user = await db.User.findOne({ where: { username: username } });
if (user) {
// Sending response after checking user existence and fetching role
res.status(200).json({ username: user.username, role: user.role });
} else {
// Sending not authorized if no user is found
res.status(403).send('Not authorized');
}
} catch (error) {
console.error('Error checking user role:', error);
// Sending server error response
res.status(500).send('Server error');
}
};


exports.get = async (req, res) => {
const { username } = req.params;

Expand Down

0 comments on commit a963528

Please sign in to comment.