mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
feat(writeapi): post voting
This commit is contained in:
@@ -826,6 +826,110 @@ paths:
|
|||||||
$ref: '#/components/schemas/Status'
|
$ref: '#/components/schemas/Status'
|
||||||
response:
|
response:
|
||||||
$ref: components/schemas/PostsObject.yaml#/PostsObject
|
$ref: components/schemas/PostsObject.yaml#/PostsObject
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- posts
|
||||||
|
summary: Purge a post
|
||||||
|
description: This operation purges a post.
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Post successfully purged
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
response:
|
||||||
|
type: object
|
||||||
|
properties: {}
|
||||||
|
/posts/{pid}/state:
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- posts
|
||||||
|
summary: Restore a post
|
||||||
|
description: This operation restores a post.
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Topic successfully restored
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
response:
|
||||||
|
type: object
|
||||||
|
properties: {}
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- posts
|
||||||
|
summary: Deletes a post
|
||||||
|
description: This operation soft deletes a post.
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Post successfully deleted
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
response:
|
||||||
|
type: object
|
||||||
|
properties: {}
|
||||||
|
/posts/{pid}/vote:
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- posts
|
||||||
|
summary: Vote on a post
|
||||||
|
description: This operation casts a vote on a post.
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
delta:
|
||||||
|
type: number
|
||||||
|
description: Positive integer for upvote, negative integer for downvote (0 to unvote.)
|
||||||
|
example:
|
||||||
|
delta: 1
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Topic successfully upvoted
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
response:
|
||||||
|
type: object
|
||||||
|
properties: {}
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- posts
|
||||||
|
summary: Unvote a post
|
||||||
|
description: This operation removes a pre-cast vote on a post.
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Post successfully unvoted
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
response:
|
||||||
|
type: object
|
||||||
|
properties: {}
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
Status:
|
Status:
|
||||||
|
|||||||
@@ -109,11 +109,11 @@ define('forum/topic/postTools', [
|
|||||||
});
|
});
|
||||||
|
|
||||||
postContainer.on('click', '[component="post/upvote"]', function () {
|
postContainer.on('click', '[component="post/upvote"]', function () {
|
||||||
return votes.toggleVote($(this), '.upvoted', 'posts.upvote');
|
return votes.toggleVote($(this), '.upvoted', 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
postContainer.on('click', '[component="post/downvote"]', function () {
|
postContainer.on('click', '[component="post/downvote"]', function () {
|
||||||
return votes.toggleVote($(this), '.downvoted', 'posts.downvote');
|
return votes.toggleVote($(this), '.downvoted', -1);
|
||||||
});
|
});
|
||||||
|
|
||||||
postContainer.on('click', '[component="post/vote-count"]', function () {
|
postContainer.on('click', '[component="post/vote-count"]', function () {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
define('forum/topic/votes', ['components', 'translator', 'benchpress'], function (components, translator, Benchpress) {
|
define('forum/topic/votes', ['components', 'translator', 'benchpress', 'api'], function (components, translator, Benchpress, api) {
|
||||||
var Votes = {};
|
var Votes = {};
|
||||||
|
|
||||||
Votes.addVoteHandler = function () {
|
Votes.addVoteHandler = function () {
|
||||||
@@ -61,19 +61,17 @@ define('forum/topic/votes', ['components', 'translator', 'benchpress'], function
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Votes.toggleVote = function (button, className, method) {
|
Votes.toggleVote = function (button, className, delta) {
|
||||||
var post = button.closest('[data-pid]');
|
var post = button.closest('[data-pid]');
|
||||||
var currentState = post.find(className).length;
|
var currentState = post.find(className).length;
|
||||||
|
|
||||||
socket.emit(currentState ? 'posts.unvote' : method, {
|
const method = currentState ? 'del' : 'put';
|
||||||
pid: post.attr('data-pid'),
|
api[method](`/posts/${post.attr('data-pid')}/vote`, {
|
||||||
room_id: 'topic_' + ajaxify.data.tid,
|
delta: delta,
|
||||||
}, function (err) {
|
}, undefined, (err) => {
|
||||||
if (err) {
|
app.alertError(err.status.message);
|
||||||
app.alertError(err.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err && err.message === '[[error:not-logged-in]]') {
|
if (err.status.message === '[[error:not-logged-in]]') {
|
||||||
ajaxify.go('login');
|
ajaxify.go('login');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const utils = require('../../utils');
|
|||||||
|
|
||||||
const helpers = require('../helpers');
|
const helpers = require('../helpers');
|
||||||
const sockets = require('../../socket.io');
|
const sockets = require('../../socket.io');
|
||||||
|
const socketPostHelpers = require('../../socket.io/posts/helpers'); // eehhh...
|
||||||
const socketTopics = require('../../socket.io/topics'); // eehhh...
|
const socketTopics = require('../../socket.io/topics'); // eehhh...
|
||||||
|
|
||||||
const Posts = module.exports;
|
const Posts = module.exports;
|
||||||
@@ -145,6 +146,31 @@ Posts.delete = async (req, res) => {
|
|||||||
helpers.formatApiResponse(200, res);
|
helpers.formatApiResponse(200, res);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Posts.vote = async (req, res) => {
|
||||||
|
const tid = await posts.getPostField(req.params.pid, 'tid');
|
||||||
|
const data = { pid: req.params.pid, room_id: `topic_${tid}` };
|
||||||
|
const socketMock = { uid: req.user.uid };
|
||||||
|
|
||||||
|
if (req.body.delta > 0) {
|
||||||
|
await socketPostHelpers.postCommand(socketMock, 'upvote', 'voted', 'notifications:upvoted_your_post_in', data);
|
||||||
|
} else if (req.body.delta < 0) {
|
||||||
|
await socketPostHelpers.postCommand(socketMock, 'downvote', 'voted', '', data);
|
||||||
|
} else {
|
||||||
|
await socketPostHelpers.postCommand(socketMock, 'unvote', 'voted', '', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
helpers.formatApiResponse(200, res);
|
||||||
|
};
|
||||||
|
|
||||||
|
Posts.unvote = async (req, res) => {
|
||||||
|
const tid = await posts.getPostField(req.params.pid, 'tid');
|
||||||
|
const data = { pid: req.params.pid, room_id: `topic_${tid}` };
|
||||||
|
const socketMock = { uid: req.user.uid };
|
||||||
|
|
||||||
|
await socketPostHelpers.postCommand(socketMock, 'unvote', 'voted', '', data);
|
||||||
|
helpers.formatApiResponse(200, res);
|
||||||
|
};
|
||||||
|
|
||||||
async function isMainAndLastPost(pid) {
|
async function isMainAndLastPost(pid) {
|
||||||
const [isMain, topicData] = await Promise.all([
|
const [isMain, topicData] = await Promise.all([
|
||||||
posts.isMain(pid),
|
posts.isMain(pid),
|
||||||
|
|||||||
@@ -16,31 +16,8 @@ module.exports = function () {
|
|||||||
setupApiRoute(router, '/:pid/state', middleware, [...middlewares, middleware.assertPost], 'put', controllers.write.posts.restore);
|
setupApiRoute(router, '/:pid/state', middleware, [...middlewares, middleware.assertPost], 'put', controllers.write.posts.restore);
|
||||||
setupApiRoute(router, '/:pid/state', middleware, [...middlewares, middleware.assertPost], 'delete', controllers.write.posts.delete);
|
setupApiRoute(router, '/:pid/state', middleware, [...middlewares, middleware.assertPost], 'delete', controllers.write.posts.delete);
|
||||||
|
|
||||||
// app.route('/:pid/vote')
|
setupApiRoute(router, '/:pid/vote', middleware, [...middlewares, middleware.checkRequired.bind(null, ['delta']), middleware.assertPost], 'put', controllers.write.posts.vote);
|
||||||
// .post(apiMiddleware.requireUser, function(req, res) {
|
setupApiRoute(router, '/:pid/vote', middleware, [...middlewares, middleware.assertPost], 'delete', controllers.write.posts.unvote);
|
||||||
// if (!utils.checkRequired(['delta'], req, res)) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (req.body.delta > 0) {
|
|
||||||
// posts.upvote(req.params.pid, req.user.uid, function(err, data) {
|
|
||||||
// errorHandler.handle(err, res, data);
|
|
||||||
// })
|
|
||||||
// } else if (req.body.delta < 0) {
|
|
||||||
// posts.downvote(req.params.pid, req.user.uid, function(err, data) {
|
|
||||||
// errorHandler.handle(err, res, data);
|
|
||||||
// })
|
|
||||||
// } else {
|
|
||||||
// posts.unvote(req.params.pid, req.user.uid, function(err, data) {
|
|
||||||
// errorHandler.handle(err, res, data);
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// .delete(apiMiddleware.requireUser, function(req, res) {
|
|
||||||
// posts.unvote(req.params.pid, req.user.uid, function(err, data) {
|
|
||||||
// errorHandler.handle(err, res, data);
|
|
||||||
// })
|
|
||||||
// });
|
|
||||||
|
|
||||||
// app.route('/:pid/bookmark')
|
// app.route('/:pid/bookmark')
|
||||||
// .post(apiMiddleware.requireUser, function(req, res) {
|
// .post(apiMiddleware.requireUser, function(req, res) {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ const privileges = require('../../privileges');
|
|||||||
const meta = require('../../meta');
|
const meta = require('../../meta');
|
||||||
const helpers = require('./helpers');
|
const helpers = require('./helpers');
|
||||||
|
|
||||||
|
const sockets = require('..');
|
||||||
|
|
||||||
module.exports = function (SocketPosts) {
|
module.exports = function (SocketPosts) {
|
||||||
SocketPosts.getVoters = async function (socket, data) {
|
SocketPosts.getVoters = async function (socket, data) {
|
||||||
if (!data || !data.pid || !data.cid) {
|
if (!data || !data.pid || !data.cid) {
|
||||||
@@ -61,14 +63,17 @@ module.exports = function (SocketPosts) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
SocketPosts.upvote = async function (socket, data) {
|
SocketPosts.upvote = async function (socket, data) {
|
||||||
|
sockets.warnDeprecated(socket, 'PUT /api/v1/posts/:pid/vote');
|
||||||
return await helpers.postCommand(socket, 'upvote', 'voted', 'notifications:upvoted_your_post_in', data);
|
return await helpers.postCommand(socket, 'upvote', 'voted', 'notifications:upvoted_your_post_in', data);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketPosts.downvote = async function (socket, data) {
|
SocketPosts.downvote = async function (socket, data) {
|
||||||
|
sockets.warnDeprecated(socket, 'PUT /api/v1/posts/:pid/vote');
|
||||||
return await helpers.postCommand(socket, 'downvote', 'voted', '', data);
|
return await helpers.postCommand(socket, 'downvote', 'voted', '', data);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketPosts.unvote = async function (socket, data) {
|
SocketPosts.unvote = async function (socket, data) {
|
||||||
|
sockets.warnDeprecated(socket, 'DELETE /api/v1/posts/:pid/vote');
|
||||||
return await helpers.postCommand(socket, 'unvote', 'voted', '', data);
|
return await helpers.postCommand(socket, 'unvote', 'voted', '', data);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user