Skip to content

Commit

Permalink
feat(writeapi): post voting
Browse files Browse the repository at this point in the history
  • Loading branch information
julianlam committed Oct 8, 2020
1 parent 5e2a3ea commit 9942c24
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 37 deletions.
104 changes: 104 additions & 0 deletions public/openapi/write.yaml
Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions public/src/client/topic/postTools.js
Expand Up @@ -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 () {
Expand Down
18 changes: 8 additions & 10 deletions public/src/client/topic/votes.js
@@ -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 () {
Expand Down Expand Up @@ -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');
}
});
Expand Down
26 changes: 26 additions & 0 deletions src/controllers/write/posts.js
Expand Up @@ -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;
Expand Down Expand Up @@ -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),
Expand Down
27 changes: 2 additions & 25 deletions src/routes/write/posts.js
Expand Up @@ -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) {
Expand Down
5 changes: 5 additions & 0 deletions src/socket.io/posts/votes.js
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
};
};

0 comments on commit 9942c24

Please sign in to comment.