diff --git a/dump.rdb b/dump.rdb new file mode 100644 index 0000000000..9bac1ef759 Binary files /dev/null and b/dump.rdb differ diff --git a/src/controllers/topics.js b/src/controllers/topics.js index d83ce8e602..ef57326eb3 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -22,6 +22,22 @@ const relative_path = nconf.get('relative_path'); const upload_url = nconf.get('upload_url'); const validSorts = ['oldest_to_newest', 'newest_to_oldest', 'most_votes']; +// Assisted by Copilot +topicsController.updateAnsweredStatus = async function (req, res) { + const { pid } = req.params; // Updated with destructuring // Post ID from URL params + const { isAnswered } = req.body; // Extract the 'isAnswered' value from the request body + if (!req.loggedIn) { + return res.status(403).json({ error: 'User not logged in.' }); + } + try { + await topics.setPostAnsweredStatus(pid, isAnswered); + res.status(200).json({ message: 'Post answered status updated successfully.' }); + } catch (error) { // Corrected brace-style + console.error(`Failed to update answered status: ${error.message}`); + res.status(500).json({ error: 'Failed to update answered status.' }); + } +}; + topicsController.get = async function getTopic(req, res, next) { const tid = req.params.topic_id; if ( diff --git a/src/posts/edit.js b/src/posts/edit.js index a63f34cc48..c97ad9a162 100644 --- a/src/posts/edit.js +++ b/src/posts/edit.js @@ -38,6 +38,11 @@ module.exports = function (Posts) { const oldContent = postData.content; // for diffing purposes const editPostData = getEditPostData(data, topicData, postData); + // Logic to handle `isAnswered` + if (data.hasOwnProperty('isAnswered')) { + editPostData.isAnswered = data.isAnswered; + } + if (data.handle) { editPostData.handle = data.handle; } @@ -197,6 +202,14 @@ module.exports = function (Posts) { editor: data.uid, }; + if (data.hasOwnProperty('isAnswered')) { + editPostData.isAnswered = data.isAnswered; + } + + if (data.hasOwnProperty('isAnswered')) { + editPostData.isAnswered = data.isAnswered; + } + // For posts in scheduled topics, if edited before, use edit timestamp editPostData.edited = topicData.scheduled ? (postData.edited || postData.timestamp) + 1 : Date.now(); diff --git a/src/posts/topics.js b/src/posts/topics.js index 8e94db3017..33b221196f 100644 --- a/src/posts/topics.js +++ b/src/posts/topics.js @@ -1,4 +1,4 @@ - +// Assisted by Copilot 'use strict'; const topics = require('../topics'); @@ -9,6 +9,10 @@ module.exports = function (Posts) { Posts.getPostsFromSet = async function (set, start, stop, uid, reverse) { const pids = await Posts.getPidsFromSet(set, start, stop, reverse); const posts = await Posts.getPostsByPids(pids, uid); + // Logic to retrieve the `isAnswered` field + posts.forEach((post) => { + post.isAnswered = post.isAnswered || false; // Default to false if not set + }); return await user.blocks.filter(uid, posts); }; @@ -21,6 +25,11 @@ module.exports = function (Posts) { return isArray ? result : result[0]; }; + Posts.setPostAnsweredStatus = async function (pid, isAnswered) { + // Store the answered status for the post + await Posts.setPostField(pid, 'isAnswered', isAnswered); + }; + Posts.getTopicFields = async function (pid, fields) { const tid = await Posts.getPostField(pid, 'tid'); return await topics.getTopicFields(tid, fields); diff --git a/src/routes/api.js b/src/routes/api.js index 0fe575a326..9bfff0a334 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -3,6 +3,7 @@ const express = require('express'); const uploadsController = require('../controllers/uploads'); +const topicsController = require('../controllers/topics'); // topics controller added const helpers = require('./helpers'); module.exports = function (app, middleware, controllers) { @@ -32,7 +33,7 @@ module.exports = function (app, middleware, controllers) { middleware.uploads.ratelimit, middleware.applyCSRF, ]; - + router.get('/post/:pid/answered', [...middlewares, middleware.ensureLoggedIn], helpers.tryRoute(topicsController.updateAnsweredStatus)); router.post('/post/upload', postMiddlewares, helpers.tryRoute(uploadsController.uploadPost)); router.post('/user/:userslug/uploadpicture', [ ...middlewares, diff --git a/test/topics.js b/test/topics.js index 8a32e445f5..94a2a1de92 100644 --- a/test/topics.js +++ b/test/topics.js @@ -2506,6 +2506,45 @@ describe('Topic\'s', () => { }); }); +describe('isAnswered', () => { + let testTopic; + let replyPid; + let fooUid; + + before(async () => { + fooUid = await User.create({ username: 'foo_test_user', password: '123456' }); + + const testCategory = await categories.create({ + name: 'Answered Test Category', + description: 'Category for testing the isAnswered feature', + }); + + const topicResponse = await topics.post({ + uid: fooUid, + title: 'Test Topic for isAnswered', + content: 'Initial content of the test topic', + cid: testCategory.cid, + }); + testTopic = topicResponse.topicData; + it('should default to isAnswered as false for a new topic', async () => { + const topicData = await topics.getTopicData(testTopic.tid); + assert.strictEqual(topicData.isAnswered, false, 'New topics should have isAnswered set to false by default'); + }); + + it('should correctly set isAnswered to true when a post is marked as an answer', async () => { + await topics.setIsAnswered(testTopic.tid, replyPid, true); + const topicData = await topics.getTopicData(testTopic.tid); + assert.strictEqual(topicData.isAnswered, true, 'isAnswered should be set to true when an answer is marked'); + }); + + it('should correctly set isAnswered back to false when the answer is unmarked', async () => { + await topics.setIsAnswered(testTopic.tid, replyPid, false); + const topicData = await topics.getTopicData(testTopic.tid); + assert.strictEqual(topicData.isAnswered, false, 'isAnswered should be set to false when the answer is unmarked'); + }); + }); +}); + describe('Topics\'', async () => { let files;