mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 11:05:54 +01:00 
			
		
		
		
	feat(writeapi): post voting
This commit is contained in:
		| @@ -826,6 +826,110 @@ paths: | ||||
|                     $ref: '#/components/schemas/Status' | ||||
|                   response: | ||||
|                     $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: | ||||
|   schemas: | ||||
|     Status: | ||||
|   | ||||
| @@ -109,11 +109,11 @@ define('forum/topic/postTools', [ | ||||
| 		}); | ||||
|  | ||||
| 		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 () { | ||||
| 			return votes.toggleVote($(this), '.downvoted', 'posts.downvote'); | ||||
| 			return votes.toggleVote($(this), '.downvoted', -1); | ||||
| 		}); | ||||
|  | ||||
| 		postContainer.on('click', '[component="post/vote-count"]', function () { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| '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 = {}; | ||||
|  | ||||
| 	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 currentState = post.find(className).length; | ||||
|  | ||||
| 		socket.emit(currentState ? 'posts.unvote' : method, { | ||||
| 			pid: post.attr('data-pid'), | ||||
| 			room_id: 'topic_' + ajaxify.data.tid, | ||||
| 		}, function (err) { | ||||
| 			if (err) { | ||||
| 				app.alertError(err.message); | ||||
| 			} | ||||
| 		const method = currentState ? 'del' : 'put'; | ||||
| 		api[method](`/posts/${post.attr('data-pid')}/vote`, { | ||||
| 			delta: delta, | ||||
| 		}, undefined, (err) => { | ||||
| 			app.alertError(err.status.message); | ||||
|  | ||||
| 			if (err && err.message === '[[error:not-logged-in]]') { | ||||
| 			if (err.status.message === '[[error:not-logged-in]]') { | ||||
| 				ajaxify.go('login'); | ||||
| 			} | ||||
| 		}); | ||||
|   | ||||
| @@ -13,6 +13,7 @@ const utils = require('../../utils'); | ||||
|  | ||||
| const helpers = require('../helpers'); | ||||
| const sockets = require('../../socket.io'); | ||||
| const socketPostHelpers = require('../../socket.io/posts/helpers');	// eehhh... | ||||
| const socketTopics = require('../../socket.io/topics');	// eehhh... | ||||
|  | ||||
| const Posts = module.exports; | ||||
| @@ -145,6 +146,31 @@ Posts.delete = async (req, 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) { | ||||
| 	const [isMain, topicData] = await Promise.all([ | ||||
| 		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], 'delete', controllers.write.posts.delete); | ||||
|  | ||||
| 	// app.route('/:pid/vote') | ||||
| 	// 	.post(apiMiddleware.requireUser, function(req, res) { | ||||
| 	// 		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); | ||||
| 	// 		}) | ||||
| 	// 	}); | ||||
| 	setupApiRoute(router, '/:pid/vote', middleware, [...middlewares, middleware.checkRequired.bind(null, ['delta']), middleware.assertPost], 'put', controllers.write.posts.vote); | ||||
| 	setupApiRoute(router, '/:pid/vote', middleware, [...middlewares, middleware.assertPost], 'delete', controllers.write.posts.unvote); | ||||
|  | ||||
| 	// app.route('/:pid/bookmark') | ||||
| 	// 	.post(apiMiddleware.requireUser, function(req, res) { | ||||
|   | ||||
| @@ -7,6 +7,8 @@ const privileges = require('../../privileges'); | ||||
| const meta = require('../../meta'); | ||||
| const helpers = require('./helpers'); | ||||
|  | ||||
| const sockets = require('..'); | ||||
|  | ||||
| module.exports = function (SocketPosts) { | ||||
| 	SocketPosts.getVoters = async function (socket, data) { | ||||
| 		if (!data || !data.pid || !data.cid) { | ||||
| @@ -61,14 +63,17 @@ module.exports = function (SocketPosts) { | ||||
| 	}; | ||||
|  | ||||
| 	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); | ||||
| 	}; | ||||
|  | ||||
| 	SocketPosts.downvote = async function (socket, data) { | ||||
| 		sockets.warnDeprecated(socket, 'PUT /api/v1/posts/:pid/vote'); | ||||
| 		return await helpers.postCommand(socket, 'downvote', 'voted', '', data); | ||||
| 	}; | ||||
|  | ||||
| 	SocketPosts.unvote = async function (socket, data) { | ||||
| 		sockets.warnDeprecated(socket, 'DELETE /api/v1/posts/:pid/vote'); | ||||
| 		return await helpers.postCommand(socket, 'unvote', 'voted', '', data); | ||||
| 	}; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user