mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-03-06 20:41:17 +01:00
@@ -62,6 +62,9 @@
|
||||
"users": "Users",
|
||||
"topics": "Topics",
|
||||
"posts": "Posts",
|
||||
"best": "Best",
|
||||
"upvoted": "Upvoted",
|
||||
"downvoted": "Downvoted",
|
||||
"views": "Views",
|
||||
"reputation": "Reputation",
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
"account/favourites": "%1's Favourite Posts",
|
||||
"account/settings": "User Settings",
|
||||
"account/watched": "Topics watched by %1",
|
||||
"account/upvoted": "Posts upvoted by %1",
|
||||
"account/downvoted": "Posts downvoted by %1",
|
||||
"account/best": "Best posts made by %1",
|
||||
|
||||
"maintenance.text": "%1 is currently undergoing maintenance. Please come back another time.",
|
||||
"maintenance.messageIntro": "Additionally, the administrator has left this message:",
|
||||
|
||||
@@ -83,6 +83,9 @@
|
||||
"has_no_posts": "This user hasn't posted anything yet.",
|
||||
"has_no_topics": "This user hasn't posted any topics yet.",
|
||||
"has_no_watched_topics": "This user hasn't watched any topics yet.",
|
||||
"has_no_upvoted_posts": "This user hasn't upvoted any posts yet.",
|
||||
"has_no_downvoted_posts": "This user hasn't downvoted any posts yet.",
|
||||
"has_no_voted_posts": "This user has no voted posts",
|
||||
|
||||
"email_hidden": "Email Hidden",
|
||||
"hidden": "hidden",
|
||||
|
||||
17
public/src/client/account/best.js
Normal file
17
public/src/client/account/best.js
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
/* globals define */
|
||||
|
||||
define('forum/account/best', ['forum/account/header', 'forum/account/posts'], function(header, posts) {
|
||||
var Best = {};
|
||||
|
||||
Best.init = function() {
|
||||
header.init();
|
||||
|
||||
$('[component="post/content"] img:not(.not-responsive)').addClass('img-responsive');
|
||||
|
||||
posts.handleInfiniteScroll('posts.loadMoreBestPosts', 'account/best');
|
||||
};
|
||||
|
||||
return Best;
|
||||
});
|
||||
17
public/src/client/account/downvoted.js
Normal file
17
public/src/client/account/downvoted.js
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
/* globals define */
|
||||
|
||||
define('forum/account/downvoted', ['forum/account/header', 'forum/account/posts'], function(header, posts) {
|
||||
var Downvoted = {};
|
||||
|
||||
Downvoted.init = function() {
|
||||
header.init();
|
||||
|
||||
$('[component="post/content"] img:not(.not-responsive)').addClass('img-responsive');
|
||||
|
||||
posts.handleInfiniteScroll('posts.loadMoreDownVotedPosts', 'account/downvoted');
|
||||
};
|
||||
|
||||
return Downvoted;
|
||||
});
|
||||
17
public/src/client/account/upvoted.js
Normal file
17
public/src/client/account/upvoted.js
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
/* globals define */
|
||||
|
||||
define('forum/account/upvoted', ['forum/account/header', 'forum/account/posts'], function(header, posts) {
|
||||
var Upvoted = {};
|
||||
|
||||
Upvoted.init = function() {
|
||||
header.init();
|
||||
|
||||
$('[component="post/content"] img:not(.not-responsive)').addClass('img-responsive');
|
||||
|
||||
posts.handleInfiniteScroll('posts.loadMoreUpVotedPosts', 'account/upvoted');
|
||||
};
|
||||
|
||||
return Upvoted;
|
||||
});
|
||||
@@ -14,22 +14,90 @@ var async = require('async'),
|
||||
var postsController = {};
|
||||
|
||||
postsController.getFavourites = function(req, res, next) {
|
||||
getFromUserSet('account/favourites', 'favourites', '[[user:favourites]]', posts.getPostSummariesFromSet, 'posts', req, res, next);
|
||||
var data = {
|
||||
template: 'account/favourites',
|
||||
set: 'favourites',
|
||||
type: 'posts',
|
||||
noItemsFoundKey: '[[topic:favourites.has_no_favourites]]',
|
||||
method: posts.getPostSummariesFromSet,
|
||||
crumb: '[[user:favourites]]'
|
||||
};
|
||||
getFromUserSet(data, req, res, next);
|
||||
};
|
||||
|
||||
postsController.getPosts = function(req, res, next) {
|
||||
getFromUserSet('account/posts', 'posts', '[[global:posts]]', posts.getPostSummariesFromSet, 'posts', req, res, next);
|
||||
var data = {
|
||||
template: 'account/posts',
|
||||
set: 'posts',
|
||||
type: 'posts',
|
||||
noItemsFoundKey: '[[user:has_no_posts]]',
|
||||
method: posts.getPostSummariesFromSet,
|
||||
crumb: '[[global:posts]]'
|
||||
};
|
||||
getFromUserSet(data, req, res, next);
|
||||
};
|
||||
|
||||
postsController.getUpVotedPosts = function(req, res, next) {
|
||||
var data = {
|
||||
template: 'account/upvoted',
|
||||
set: 'upvote',
|
||||
type: 'posts',
|
||||
noItemsFoundKey: '[[user:has_no_upvoted_posts]]',
|
||||
method: posts.getPostSummariesFromSet,
|
||||
crumb: '[[global:upvoted]]'
|
||||
};
|
||||
getFromUserSet(data, req, res, next);
|
||||
};
|
||||
|
||||
postsController.getDownVotedPosts = function(req, res, next) {
|
||||
var data = {
|
||||
template: 'account/downvoted',
|
||||
set: 'downvote',
|
||||
type: 'posts',
|
||||
noItemsFoundKey: '[[user:has_no_downvoted_posts]]',
|
||||
method: posts.getPostSummariesFromSet,
|
||||
crumb: '[[global:downvoted]]'
|
||||
};
|
||||
getFromUserSet(data, req, res, next);
|
||||
};
|
||||
|
||||
postsController.getBestPosts = function(req, res, next) {
|
||||
var data = {
|
||||
template: 'account/best',
|
||||
set: 'posts:votes',
|
||||
type: 'posts',
|
||||
noItemsFoundKey: '[[user:has_no_voted_posts]]',
|
||||
method: posts.getPostSummariesFromSet,
|
||||
crumb: '[[global:best]]'
|
||||
};
|
||||
getFromUserSet(data, req, res, next);
|
||||
};
|
||||
|
||||
postsController.getWatchedTopics = function(req, res, next) {
|
||||
getFromUserSet('account/watched', 'followed_tids', '[[user:watched]]',topics.getTopicsFromSet, 'topics', req, res, next);
|
||||
var data = {
|
||||
template: 'account/watched',
|
||||
set: 'followed_tids',
|
||||
type: 'topics',
|
||||
noItemsFoundKey: '[[user:has_no_watched_topics]]',
|
||||
method: topics.getTopicsFromSet,
|
||||
crumb: '[[user:watched]]'
|
||||
};
|
||||
getFromUserSet(data, req, res, next);
|
||||
};
|
||||
|
||||
postsController.getTopics = function(req, res, next) {
|
||||
getFromUserSet('account/topics', 'topics', '[[global:topics]]', topics.getTopicsFromSet, 'topics', req, res, next);
|
||||
var data = {
|
||||
template: 'account/topics',
|
||||
set: 'topics',
|
||||
type: 'topics',
|
||||
noItemsFoundKey: '[[user:has_no_topics]]',
|
||||
method: topics.getTopicsFromSet,
|
||||
crumb: '[[global:topics]]'
|
||||
};
|
||||
getFromUserSet(data, req, res, next);
|
||||
};
|
||||
|
||||
function getFromUserSet(tpl, set, crumb, method, type, req, res, next) {
|
||||
function getFromUserSet(data, req, res, next) {
|
||||
async.parallel({
|
||||
settings: function(next) {
|
||||
user.getSettings(req.uid, next);
|
||||
@@ -44,10 +112,10 @@ function getFromUserSet(tpl, set, crumb, method, type, req, res, next) {
|
||||
|
||||
var userData = results.userData;
|
||||
|
||||
var setName = 'uid:' + userData.uid + ':' + set;
|
||||
var setName = 'uid:' + userData.uid + ':' + data.set;
|
||||
|
||||
var page = Math.max(1, parseInt(req.query.page, 10) || 1);
|
||||
var itemsPerPage = (tpl === 'account/topics' || tpl === 'account/watched') ? results.settings.topicsPerPage : results.settings.postsPerPage;
|
||||
var itemsPerPage = (data.template === 'account/topics' || data.template === 'account/watched') ? results.settings.topicsPerPage : results.settings.postsPerPage;
|
||||
|
||||
async.parallel({
|
||||
itemCount: function(next) {
|
||||
@@ -60,23 +128,24 @@ function getFromUserSet(tpl, set, crumb, method, type, req, res, next) {
|
||||
data: function(next) {
|
||||
var start = (page - 1) * itemsPerPage;
|
||||
var stop = start + itemsPerPage - 1;
|
||||
method(setName, req.uid, start, stop, next);
|
||||
data.method(setName, req.uid, start, stop, next);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
userData[type] = results.data[type];
|
||||
userData[data.type] = results.data[data.type];
|
||||
userData.nextStart = results.data.nextStart;
|
||||
|
||||
var pageCount = Math.ceil(results.itemCount / itemsPerPage);
|
||||
userData.pagination = pagination.create(page, pageCount);
|
||||
|
||||
userData.title = '[[pages:' + tpl + ', ' + userData.username + ']]';
|
||||
userData.breadcrumbs = helpers.buildBreadcrumbs([{text: userData.username, url: '/user/' + userData.userslug}, {text: crumb}]);
|
||||
userData.noItemsFoundKey = data.noItemsFoundKey;
|
||||
userData.title = '[[pages:' + data.template + ', ' + userData.username + ']]';
|
||||
userData.breadcrumbs = helpers.buildBreadcrumbs([{text: userData.username, url: '/user/' + userData.userslug}, {text: data.crumb}]);
|
||||
|
||||
res.render(tpl, userData);
|
||||
res.render(data.template, userData);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
var async = require('async'),
|
||||
winston = require('winston'),
|
||||
db = require('./database'),
|
||||
posts = require('./posts'),
|
||||
user = require('./user'),
|
||||
plugins = require('./plugins'),
|
||||
meta = require('./meta');
|
||||
var async = require('async');
|
||||
var db = require('./database');
|
||||
var posts = require('./posts');
|
||||
var user = require('./user');
|
||||
var plugins = require('./plugins');
|
||||
var meta = require('./meta');
|
||||
|
||||
(function (Favourites) {
|
||||
|
||||
@@ -19,7 +18,7 @@ var async = require('async'),
|
||||
return callback(new Error('[[error:not-logged-in]]'));
|
||||
}
|
||||
|
||||
posts.getPostFields(pid, ['pid', 'uid'], function (err, postData) {
|
||||
posts.getPostFields(pid, ['pid', 'uid', 'tid'], function (err, postData) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
@@ -47,7 +46,7 @@ var async = require('async'),
|
||||
db.sortedSetAdd('users:reputation', newreputation, postData.uid);
|
||||
}
|
||||
|
||||
adjustPostVotes(pid, uid, type, unvote, function(err, votes) {
|
||||
adjustPostVotes(postData, uid, type, unvote, function(err, votes) {
|
||||
postData.votes = votes;
|
||||
callback(err, {
|
||||
user: {
|
||||
@@ -62,19 +61,19 @@ var async = require('async'),
|
||||
});
|
||||
}
|
||||
|
||||
function adjustPostVotes(pid, uid, type, unvote, callback) {
|
||||
function adjustPostVotes(postData, uid, type, unvote, callback) {
|
||||
var notType = (type === 'upvote' ? 'downvote' : 'upvote');
|
||||
|
||||
async.series([
|
||||
function(next) {
|
||||
if (unvote) {
|
||||
db.setRemove('pid:' + pid + ':' + type, uid, next);
|
||||
db.setRemove('pid:' + postData.pid + ':' + type, uid, next);
|
||||
} else {
|
||||
db.setAdd('pid:' + pid + ':' + type, uid, next);
|
||||
db.setAdd('pid:' + postData.pid + ':' + type, uid, next);
|
||||
}
|
||||
},
|
||||
function(next) {
|
||||
db.setRemove('pid:' + pid + ':' + notType, uid, next);
|
||||
db.setRemove('pid:' + postData.pid + ':' + notType, uid, next);
|
||||
}
|
||||
], function(err) {
|
||||
if (err) {
|
||||
@@ -83,18 +82,19 @@ var async = require('async'),
|
||||
|
||||
async.parallel({
|
||||
upvotes: function(next) {
|
||||
db.setCount('pid:' + pid + ':upvote', next);
|
||||
db.setCount('pid:' + postData.pid + ':upvote', next);
|
||||
},
|
||||
downvotes: function(next) {
|
||||
db.setCount('pid:' + pid + ':downvote', next);
|
||||
db.setCount('pid:' + postData.pid + ':downvote', next);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
var voteCount = parseInt(results.upvotes, 10) - parseInt(results.downvotes, 10);
|
||||
|
||||
posts.updatePostVoteCount(pid, voteCount, function(err) {
|
||||
console.log("WE ARE HERE")
|
||||
posts.updatePostVoteCount(postData, voteCount, function(err) {
|
||||
console.log("NOT HERE")
|
||||
callback(err, voteCount);
|
||||
});
|
||||
});
|
||||
|
||||
43
src/posts.js
43
src/posts.js
@@ -219,28 +219,37 @@ var async = require('async'),
|
||||
});
|
||||
};
|
||||
|
||||
Posts.updatePostVoteCount = function(pid, voteCount, callback) {
|
||||
Posts.updatePostVoteCount = function(postData, voteCount, callback) {
|
||||
if (!postData || !postData.pid || !postData.tid) {
|
||||
return callback();
|
||||
}
|
||||
async.parallel([
|
||||
function(next) {
|
||||
Posts.getPostField(pid, 'tid', function(err, tid) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
topics.getTopicField(tid, 'mainPid', function(err, mainPid) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
if (parseInt(mainPid, 10) === parseInt(pid, 10)) {
|
||||
function (next) {
|
||||
if (postData.uid) {
|
||||
db.sortedSetAdd('uid:' + postData.uid + ':posts:votes', voteCount, postData.pid, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
function (next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
topics.getTopicField(postData.tid, 'mainPid', next);
|
||||
},
|
||||
function (mainPid, next) {
|
||||
if (parseInt(mainPid, 10) === parseInt(postData.pid, 10)) {
|
||||
return next();
|
||||
}
|
||||
db.sortedSetAdd('tid:' + tid + ':posts:votes', voteCount, pid, next);
|
||||
});
|
||||
});
|
||||
db.sortedSetAdd('tid:' + postData.tid + ':posts:votes', voteCount, postData.pid, next);
|
||||
}
|
||||
], next);
|
||||
},
|
||||
function(next) {
|
||||
Posts.setPostField(pid, 'votes', voteCount, next);
|
||||
function (next) {
|
||||
Posts.setPostField(postData.pid, 'votes', voteCount, next);
|
||||
}
|
||||
], callback);
|
||||
], function(err) {
|
||||
callback(err);
|
||||
});
|
||||
};
|
||||
|
||||
}(exports));
|
||||
|
||||
@@ -12,10 +12,13 @@ module.exports = function (app, middleware, controllers) {
|
||||
setupPageRoute(app, '/user/:userslug/followers', middleware, middlewares, controllers.accounts.follow.getFollowers);
|
||||
setupPageRoute(app, '/user/:userslug/posts', middleware, middlewares, controllers.accounts.posts.getPosts);
|
||||
setupPageRoute(app, '/user/:userslug/topics', middleware, middlewares, controllers.accounts.posts.getTopics);
|
||||
setupPageRoute(app, '/user/:userslug/best', middleware, middlewares, controllers.accounts.posts.getBestPosts);
|
||||
setupPageRoute(app, '/user/:userslug/groups', middleware, middlewares, controllers.accounts.groups.get);
|
||||
|
||||
setupPageRoute(app, '/user/:userslug/favourites', middleware, accountMiddlewares, controllers.accounts.posts.getFavourites);
|
||||
setupPageRoute(app, '/user/:userslug/watched', middleware, accountMiddlewares, controllers.accounts.posts.getWatchedTopics);
|
||||
setupPageRoute(app, '/user/:userslug/upvoted', middleware, accountMiddlewares, controllers.accounts.posts.getUpVotedPosts);
|
||||
setupPageRoute(app, '/user/:userslug/downvoted', middleware, accountMiddlewares, controllers.accounts.posts.getDownVotedPosts);
|
||||
setupPageRoute(app, '/user/:userslug/edit', middleware, accountMiddlewares, controllers.accounts.edit.get);
|
||||
setupPageRoute(app, '/user/:userslug/edit/username', middleware, accountMiddlewares, controllers.accounts.edit.username);
|
||||
setupPageRoute(app, '/user/:userslug/edit/email', middleware, accountMiddlewares, controllers.accounts.edit.email);
|
||||
|
||||
@@ -85,6 +85,18 @@ SocketPosts.loadMoreUserPosts = function(socket, data, callback) {
|
||||
loadMorePosts('uid:' + data.uid + ':posts', socket.uid, data, callback);
|
||||
};
|
||||
|
||||
SocketPosts.loadMoreBestPosts = function(socket, data, callback) {
|
||||
loadMorePosts('uid:' + data.uid + ':posts:votes', socket.uid, data, callback);
|
||||
};
|
||||
|
||||
SocketPosts.loadMoreUpVotedPosts = function(socket, data, callback) {
|
||||
loadMorePosts('uid:' + data.uid + ':upvote', socket.uid, data, callback);
|
||||
};
|
||||
|
||||
SocketPosts.loadMoreDownVotedPosts = function(socket, data, callback) {
|
||||
loadMorePosts('uid:' + data.uid + ':downvote', socket.uid, data, callback);
|
||||
};
|
||||
|
||||
function loadMorePosts(set, uid, data, callback) {
|
||||
if (!data || !utils.isNumber(data.uid) || !utils.isNumber(data.after)) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
|
||||
@@ -10,7 +10,7 @@ var db = require('./database'),
|
||||
schemaDate, thisSchemaDate,
|
||||
|
||||
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema
|
||||
latestSchema = Date.UTC(2016, 0, 11);
|
||||
latestSchema = Date.UTC(2016, 0, 14);
|
||||
|
||||
Upgrade.check = function(callback) {
|
||||
db.get('schemaDate', function(err, value) {
|
||||
@@ -296,11 +296,45 @@ Upgrade.upgrade = function(callback) {
|
||||
|
||||
winston.info('[2015/12/23] Adding theme to active plugins sorted set done!');
|
||||
Upgrade.update(thisSchemaDate, next);
|
||||
})
|
||||
});
|
||||
} else {
|
||||
winston.info('[2015/12/23] Adding theme to active plugins sorted set skipped!');
|
||||
next();
|
||||
}
|
||||
},
|
||||
function(next) {
|
||||
thisSchemaDate = Date.UTC(2016, 0, 14);
|
||||
|
||||
if (schemaDate < thisSchemaDate || 1) {
|
||||
updatesMade = true;
|
||||
winston.info('[2016/01/14] Creating user best post sorted sets');
|
||||
|
||||
var batch = require('./batch');
|
||||
|
||||
batch.processSortedSet('posts:pid', function(ids, next) {
|
||||
async.eachSeries(ids, function(id, next) {
|
||||
db.getObjectFields('post:' + id, ['pid', 'uid', 'votes'], function(err, postData) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
if (!postData || !parseInt(postData.votes, 10) || !parseInt(postData.uid, 10)) {
|
||||
return next();
|
||||
}
|
||||
winston.info('processing pid: ' + postData.pid + ' uid: ' + postData.uid + ' votes: ' + postData.votes);
|
||||
db.sortedSetAdd('uid:' + postData.uid + ':posts:votes', postData.votes, postData.pid, next);
|
||||
});
|
||||
}, next);
|
||||
}, {}, function(err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
winston.info('[2016/01/14] Creating user best post sorted sets done!');
|
||||
Upgrade.update(thisSchemaDate, next);
|
||||
});
|
||||
} else {
|
||||
winston.info('[2016/01/14] Creating user best post sorted sets skipped!');
|
||||
next();
|
||||
}
|
||||
}
|
||||
// Add new schema updates here
|
||||
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 24!!!
|
||||
|
||||
Reference in New Issue
Block a user