Can mark a comment as the answer, some layout changes
This commit is contained in:
@@ -29,7 +29,7 @@ const ForumPost = sequelize.define('ForumPost', {
|
||||
defaultValue: 'general_discussion'
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.ENUM('open', 'solved', 'closed'),
|
||||
type: DataTypes.ENUM('open', 'answered', 'closed'),
|
||||
defaultValue: 'open'
|
||||
},
|
||||
viewCount: {
|
||||
@@ -43,6 +43,14 @@ const ForumPost = sequelize.define('ForumPost', {
|
||||
isPinned: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
acceptedAnswerId: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: 'ForumComments',
|
||||
key: 'id'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -156,9 +156,11 @@ router.get('/posts/:id', async (req, res) => {
|
||||
as: 'author',
|
||||
attributes: ['id', 'username', 'firstName', 'lastName']
|
||||
}
|
||||
],
|
||||
order: [['createdAt', 'ASC']]
|
||||
]
|
||||
}
|
||||
],
|
||||
order: [
|
||||
[{ model: ForumComment, as: 'comments' }, 'createdAt', 'ASC']
|
||||
]
|
||||
});
|
||||
|
||||
@@ -370,7 +372,7 @@ router.patch('/posts/:id/status', authenticateToken, async (req, res) => {
|
||||
return res.status(403).json({ error: 'Only the author can update post status' });
|
||||
}
|
||||
|
||||
if (!['open', 'solved', 'closed'].includes(status)) {
|
||||
if (!['open', 'answered', 'closed'].includes(status)) {
|
||||
return res.status(400).json({ error: 'Invalid status value' });
|
||||
}
|
||||
|
||||
@@ -411,6 +413,82 @@ router.patch('/posts/:id/status', authenticateToken, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// PATCH /api/forum/posts/:id/accept-answer - Mark/unmark comment as accepted answer
|
||||
router.patch('/posts/:id/accept-answer', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const { commentId } = req.body;
|
||||
const post = await ForumPost.findByPk(req.params.id);
|
||||
|
||||
if (!post) {
|
||||
return res.status(404).json({ error: 'Post not found' });
|
||||
}
|
||||
|
||||
if (post.authorId !== req.user.id) {
|
||||
return res.status(403).json({ error: 'Only the post author can mark answers' });
|
||||
}
|
||||
|
||||
// If commentId is provided, validate it
|
||||
if (commentId) {
|
||||
const comment = await ForumComment.findByPk(commentId);
|
||||
|
||||
if (!comment) {
|
||||
return res.status(404).json({ error: 'Comment not found' });
|
||||
}
|
||||
|
||||
if (comment.postId !== post.id) {
|
||||
return res.status(400).json({ error: 'Comment does not belong to this post' });
|
||||
}
|
||||
|
||||
if (comment.isDeleted) {
|
||||
return res.status(400).json({ error: 'Cannot mark deleted comment as answer' });
|
||||
}
|
||||
|
||||
if (comment.parentCommentId) {
|
||||
return res.status(400).json({ error: 'Only top-level comments can be marked as answers' });
|
||||
}
|
||||
}
|
||||
|
||||
// Update the post with accepted answer
|
||||
await post.update({
|
||||
acceptedAnswerId: commentId || null,
|
||||
status: commentId ? 'answered' : 'open'
|
||||
});
|
||||
|
||||
const updatedPost = await ForumPost.findByPk(post.id, {
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'author',
|
||||
attributes: ['id', 'username', 'firstName', 'lastName']
|
||||
},
|
||||
{
|
||||
model: PostTag,
|
||||
as: 'tags',
|
||||
attributes: ['tagName']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.info("Answer marked/unmarked", {
|
||||
postId: req.params.id,
|
||||
commentId: commentId || 'unmarked',
|
||||
authorId: req.user.id
|
||||
});
|
||||
|
||||
res.json(updatedPost);
|
||||
} catch (error) {
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.error("Mark answer failed", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
postId: req.params.id,
|
||||
authorId: req.user.id
|
||||
});
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/forum/posts/:id/comments - Add comment/reply
|
||||
router.post('/posts/:id/comments', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user