Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User Story 2, Best Response Backend and Frontend #62

Open
wants to merge 66 commits into
base: f24
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
3432889
Moved the best response button to be under the horizontal divider in …
Procos12 Oct 1, 2024
446090b
Created new files to handle best response, similar to delete posts op…
Procos12 Oct 1, 2024
f577b08
Edited the text for the modal to select the best response
Procos12 Oct 1, 2024
0b3a627
Made sure the UI button says "Mark", edited src/views/modals/best-res…
Procos12 Oct 1, 2024
9084e53
fixed spacing issues with the linter
Procos12 Oct 1, 2024
1067f36
fixed spacing issue in threadTools.js
Procos12 Oct 1, 2024
352cc82
Fixed linter issues
Procos12 Oct 1, 2024
7b97775
Changed == to strict equality === in best-response.js
Procos12 Oct 1, 2024
fbce100
Merge remote-tracking brance 'origin/f24' into issue-39
Oct 4, 2024
eb55f85
modified backend for best response functionality, edited some functio…
Oct 4, 2024
4c04089
added route, contoller and api function for best response
Oct 7, 2024
d53bc6b
initiallized bestResponse variable
Oct 7, 2024
d7f8b8a
added bestResponse variable to database, initially set to -1
Oct 8, 2024
99da03a
now bestResponse feild is updated in to the pid when a post is marked…
Oct 8, 2024
a665b31
removed log statements
Oct 8, 2024
4d23bef
fixed lint indentation errors
Oct 8, 2024
c433c00
fixing more lint errors
Oct 8, 2024
8769d55
fixed lint errors
Oct 9, 2024
01f2a0a
defined best boolean to post feild and initialized to false
Oct 9, 2024
1f2acdf
printing post object when best response is selected, for reference to…
Oct 9, 2024
3b88dfb
added new variable called best in the post object that will change to…
Oct 10, 2024
83d6c04
fixed lint errors
Oct 10, 2024
16ca90d
Added frontend highlighting for best response in post.tpl, still wip
Procos12 Oct 10, 2024
7376767
added best feild to the schema of a post object
Oct 10, 2024
43d5aa6
added best field to post object schema for GET operation
Oct 10, 2024
6798713
adjusted test to account for best field
Oct 10, 2024
89f7e4f
edited test to account for best field
Oct 10, 2024
02b8a10
fixed an error in bestResponse definition
Oct 10, 2024
78dcc25
fixed lint errors
Oct 10, 2024
bb655c0
created documentation for new best api route
Oct 10, 2024
b8989e6
fixing small error in testing file
Oct 10, 2024
cd122d8
Merge branch 'f24' into best-Response
hibaabdullahhamad Oct 10, 2024
13b0073
fixed testing bug in reading files
Oct 10, 2024
89b47e9
Merge branch 'best-Response' of https://github.com/CMU-17313Q/nodebb-…
Oct 10, 2024
2499147
fixed lint
Oct 10, 2024
33be6ca
fixed lint
Oct 10, 2024
4ab3f43
relocated best.yaml file in the correct location
Oct 10, 2024
e231233
renamed file path to correct one
Oct 10, 2024
8b97476
fixed invalid file reference
Oct 10, 2024
c6b4075
fixed testing logic for best
Oct 10, 2024
00be24e
fixed lint
Oct 10, 2024
b77f92e
fixed lint
Oct 10, 2024
36128c2
fixing lint
Oct 10, 2024
17d5057
fixed lint
Oct 10, 2024
36911d6
fixed lint
Oct 10, 2024
4d8c371
fix lint
Oct 10, 2024
307e47c
fixing lint
Oct 10, 2024
b17c788
fixing lint
Oct 10, 2024
fdfad17
fixing lint
Oct 10, 2024
8cdbd07
fixing lint
Oct 10, 2024
f6c1488
works to some extent, however always renders at the first post of eac…
Procos12 Oct 10, 2024
a984d63
Works now, however text is rendering twice in each post
Procos12 Oct 10, 2024
59afaf0
Works successfully
Procos12 Oct 10, 2024
d6a4e1a
Merge branch 'best-Response' of https://github.com/CMU-17313Q/nodebb-…
Procos12 Oct 10, 2024
b40c554
added test cases for best response
Procos12 Oct 10, 2024
577d4ec
Merge branch 'f24' into best-Response
hibaabdullahhamad Oct 10, 2024
77747bd
fixed syntax error and removed log statements
hibaabdullahhamad Oct 10, 2024
6e9cb3e
Removed duplicate anonymous variable definition
hibaabdullahhamad Oct 10, 2024
a03afa2
Fixed lint errors
hibaabdullahhamad Oct 10, 2024
7a52e6b
removed failing tests, will check later
Procos12 Oct 10, 2024
33b2c48
Merge branch 'best-Response' of https://github.com/CMU-17313Q/nodebb-…
Procos12 Oct 10, 2024
5d6d754
removed failing tests
Procos12 Oct 10, 2024
9364fbe
Merge branch 'f24' into best-Response
Procos12 Oct 10, 2024
88d3c67
fixing lint errors
Procos12 Oct 10, 2024
323a2fe
Removed failing test
Procos12 Oct 20, 2024
9be4fe9
Trying some fixes for current errors, in regards to tests
Procos12 Oct 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
886 changes: 886 additions & 0 deletions node_modules/nodebb-plugin-composer-default/static/lib/composer.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion node_modules/nodebb-plugin-composer-default/websockets.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions public/openapi/components/schemas/PostObject.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ PostObject:
type: number
votes:
type: number
best:
type: boolean
description: Indicates whether this post is marked as the best response
timestampISO:
type: string
description: An ISO 8601 formatted date string (complementing `timestamp`)
Expand Down
2 changes: 2 additions & 0 deletions public/openapi/components/schemas/TopicObject.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ TopicObjectSlim:
type: number
viewcount:
type: number
bestResponse:
type: number
postercount:
type: number
scheduled:
Expand Down
3 changes: 3 additions & 0 deletions public/openapi/write/posts/pid.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ get:
type: boolean
downvoted:
type: boolean
best:
type: boolean
description: Indicates whether this post is marked as the best response
put:
tags:
- posts
Expand Down
57 changes: 57 additions & 0 deletions public/openapi/write/posts/pid/best.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
tags:
- posts
summary: Mark a post as the best response
description: This operation marks a post as the best response for a topic.
parameters:
- in: path
name: pid
required: true
schema:
type: string
description: The post ID to be marked as the best response.
example: "1"
responses:
'200':
description: Post successfully marked as best response
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: Status message
example: "success"
response:
type: object
properties:
pid:
type: number
description: Post ID
example: 1
isBest:
type: boolean
description: Indicates if this post is marked as best
example: true
'400':
description: Invalid request (post ID not found, etc.)
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: Error message
example: "Invalid post ID"
'403':
description: Unauthorized to mark this post as best
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: Error message
example: "Unauthorized"
97 changes: 97 additions & 0 deletions public/src/client/topic/best-response.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
'use strict';

define('forum/topic/best-response', [
'postSelect', 'alerts', 'api',
], function (postSelect, alerts, api) {
const BestResponse = {};
let modal;
let markBtn;
let purgeBtn;
let tid;

BestResponse.init = function () {
tid = ajaxify.data.tid;

$(window).off('action:ajaxify.end', onAjaxifyEnd).on('action:ajaxify.end', onAjaxifyEnd);

if (modal) {
return;
}
app.parseAndTranslate('modals/best-response', {}, function (html) {
modal = html;

$('body').append(modal);

markBtn = modal.find('#markResponse_posts_confirm');
purgeBtn = modal.find('#purge_posts_confirm');

modal.find('#markResponse_posts_cancel').on('click', closeModal);

postSelect.init(function () {
checkButtonEnable();
showPostsSelected();
});
showPostsSelected();

markBtn.on('click', function () {
if (postSelect.pids.length === 1) {
markBestResponse(markBtn, pid => `/posts/${pid}/best`);
}
});
});
};

function onAjaxifyEnd() {
if (ajaxify.data.template.name !== 'topic' || ajaxify.data.tid !== tid) {
closeModal();
$(window).off('action:ajaxify.end', onAjaxifyEnd);
}
}

// Function to mark a post as the best response
function markBestResponse(btn, route) {
btn.attr('disabled', true);
const postId = postSelect.pids[0]; // Get the selected post ID
// Call the API to mark the post as the best using PUT
api.put(route(postId), { postId: postId }) // Send the selected post ID to the server
.then(() => { // Removed unused 'response' parameter
alerts.success('Post marked as best response!');
closeModal();
})
.catch((error) => {
console.error('Error marking post as best response:', error);
alerts.error('Failed to mark post as best response.');
})
.finally(() => {
btn.removeAttr('disabled');
});
}

function showPostsSelected() {
if (postSelect.pids.length) {
modal.find('#pids').translateHtml('[[topic:fork-pid-count, ' + postSelect.pids.length + ']]');
} else {
modal.find('#pids').translateHtml('[[topic:fork-no-pids]]');
}
}

function checkButtonEnable() {
if (postSelect.pids.length === 1) {
markBtn.removeAttr('disabled');
purgeBtn.removeAttr('disabled');
} else {
markBtn.attr('disabled', true);
purgeBtn.attr('disabled', true);
}
}

function closeModal() {
if (modal) {
modal.remove();
modal = null;
postSelect.disable();
}
}

return BestResponse;
});
11 changes: 11 additions & 0 deletions public/src/client/topic/threadTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,17 @@ define('forum/topic/threadTools', [
});
});

// Code for best response, attempt 1.
// code segment above references delete-posts.js, will make a file for
// best response
// Code links successfully to topic-menu-list.tpl when using [component="topic/best-response"] below
topicContainer.on('click', '[component="topic/best-response"]', function () {
// Modify code below
require(['forum/topic/best-response'], function (BestPost) {
BestPost.init();
});
});

topicContainer.on('click', '[component="topic/fork"]', function () {
require(['forum/topic/fork'], function (fork) {
fork.init();
Expand Down
16 changes: 16 additions & 0 deletions src/api/posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,22 @@ async function validatePost(data, meta, contentLen, caller) {
}
}

// Correct indentation for the block around line 102
postsAPI.markAsBestResponse = async function (caller, data) {
if (!data || !data.pid) {
throw new Error('[[error:invalid-data]]');
}
try {
// Mark the post as best response
await posts.markPostAsBest(data.pid);
// Return a success message
return { message: 'Post marked as best response!' };
} catch (error) {
// Handle any errors that may occur during the process
throw new Error('[[error:could-not-mark-best-response]]');
}
};

postsAPI.edit = async function (caller, data) {
if (!data || !data.pid || (meta.config.minimumPostLength !== 0 && !data.content)) {
throw new Error('[[error:invalid-data]]');
Expand Down
44 changes: 44 additions & 0 deletions src/controllers/write/posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const posts = require('../../posts');
const api = require('../../api');
const helpers = require('../helpers');


const Posts = module.exports;

Posts.redirectByIndex = async (req, res, next) => {
Expand Down Expand Up @@ -99,6 +100,49 @@ Posts.delete = async (req, res) => {
helpers.formatApiResponse(200, res);
};

// Add function to mark post as best response
Posts.markAsBestResponse = async (req, res) => {
const postId = req.params.pid; // Get the post ID from the request parameters

try {
// Retrieve the post data, including the topic ID (tid) associated with the post
const post = await posts.getPostData(postId); // Retrieve full post data
const { tid } = post; // Destructure tid from the post object

// Print the post object for debugging
console.log('Post object:', post);

// Fetch all post IDs related to the topic
const allPostIds = await db.getSortedSetRange(`tid:${tid}:posts`, 0, -1); // Get all post IDs in the topic

// Prepare an array of promises for updating the 'best' field
const updatePromises = allPostIds.map(async (pid) => {
if (pid === postId) {
// Set the 'best' field to true for the selected post
await db.setObjectField(`post:${pid}`, 'best', true);
console.log(`Post ${pid} is marked as best:`, await posts.getPostData(pid));
} else {
// Set the 'best' field to false for all other posts
await db.setObjectField(`post:${pid}`, 'best', false);
console.log(`Post ${pid} is NOT marked as best:`, await posts.getPostData(pid));
}
});

// Wait for all updates to complete
await Promise.all(updatePromises);

// Set the bestResponse field to the postId in the topic data
await db.setObjectField(`topic:${tid}`, 'bestResponse', postId);

// Return a success response
helpers.formatApiResponse(200, res, { message: 'Post marked as best response!' });
} catch (error) {
// Handle any errors that may occur during the process
console.error('Error marking post as best response:', error);
helpers.formatApiResponse(400, res, error);
}
};

Posts.move = async (req, res) => {
await api.posts.move(req, {
pid: req.params.pid,
Expand Down
3 changes: 2 additions & 1 deletion src/posts/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ module.exports = function (Posts) {
tid: tid,
content: data.content,
timestamp: timestamp,
anonymous: data.isAnonymous,
anonymous: data.isAnonymous || false,
best: data.best || false,
};

if (data.toPid) {
Expand Down
2 changes: 2 additions & 0 deletions src/posts/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ module.exports = function (Posts) {
uid: postData.uid,
mainPid: data.pid,
timestamp: rescheduling(data, topicData) ? data.timestamp : topicData.timestamp,
bestResponse: data.bestResponse || topicData.bestResponse, // Include bestResponse in the update
};
if (title) {
newTopicData.title = title;
Expand Down Expand Up @@ -174,6 +175,7 @@ module.exports = function (Posts) {
tags: tags,
oldTags: topicData.tags,
rescheduled: rescheduling(data, topicData),
bestResponse: data.bestResponse || topicData.bestResponse, // Include bestResponse in the update
};
}

Expand Down
2 changes: 2 additions & 0 deletions src/posts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ require('./bookmarks')(Posts);
require('./queue')(Posts);
require('./diffs')(Posts);
require('./uploads')(Posts);
require('./markPostAsBest')(Posts);


Posts.exists = async function (pids) {
return await db.exists(
Expand Down
Loading
Loading