From f6f6ca7f7667701370389eac484ec0393a5b0800 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 7 Oct 2014 16:21:12 -0400 Subject: [PATCH] closes #2132 --- public/less/admin/admin.less | 10 +++- public/less/admin/manage/flags.less | 1 + public/src/forum/admin/manage/flags.js | 68 ++++++++++++++++++++++++++ src/controllers/admin.js | 13 +++++ src/posts.js | 6 ++- src/posts/flags.js | 45 +++++++++++++++++ src/routes/admin.js | 2 + src/socket.io/admin.js | 19 +++++++ src/socket.io/posts.js | 3 ++ src/views/admin/header.tpl | 1 + src/views/admin/manage/flags.tpl | 46 +++++++++++++++++ 11 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 public/less/admin/manage/flags.less create mode 100644 public/src/forum/admin/manage/flags.js create mode 100644 src/posts/flags.js create mode 100644 src/views/admin/manage/flags.tpl diff --git a/public/less/admin/admin.less b/public/less/admin/admin.less index 98279e2755..581415c4a0 100644 --- a/public/less/admin/admin.less +++ b/public/less/admin/admin.less @@ -5,6 +5,7 @@ @import "./manage/categories"; @import "./manage/groups"; @import "./manage/tags"; +@import "./manage/flags"; @import "./manage/users"; @import "./appearance/customise"; @import "./appearance/themes"; @@ -23,6 +24,11 @@ padding: 0px 15px; } + .user-img { + width:24px; + height:24px; + } + .nodebb-logo { img { height: 31px; @@ -44,7 +50,7 @@ width: 200px; height: 100%; - + -webkit-transform: translateX(-190px); transform: translateX(-190px); @@ -81,7 +87,7 @@ max-height: 100%; cursor: pointer; max-height: 38px; - + &.open { max-height: 500px; } diff --git a/public/less/admin/manage/flags.less b/public/less/admin/manage/flags.less new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/public/less/admin/manage/flags.less @@ -0,0 +1 @@ + diff --git a/public/src/forum/admin/manage/flags.js b/public/src/forum/admin/manage/flags.js new file mode 100644 index 0000000000..fc2e300d74 --- /dev/null +++ b/public/src/forum/admin/manage/flags.js @@ -0,0 +1,68 @@ +"use strict"; +/*global define, socket, app, admin, utils, bootbox, RELATIVE_PATH*/ + +define('forum/admin/manage/flags', ['forum/infinitescroll', 'admin/selectable'], function(infinitescroll, selectable) { + var Flags = {}; + + Flags.init = function() { + handleDismiss(); + handleDelete(); + handleInfiniteScroll(); + }; + + function handleDismiss() { + $('.flags').on('click', '.dismiss', function() { + var btn = $(this); + var pid = btn.siblings('[data-pid]').attr('data-pid'); + + socket.emit('admin.dismissFlag', pid, function(err) { + done(err, btn); + }); + }); + } + + function handleDelete() { + $('.flags').on('click', '.delete', function() { + var btn = $(this); + var pid = btn.siblings('[data-pid]').attr('data-pid'); + var tid = btn.siblings('[data-pid]').attr('data-tid'); + socket.emit('posts.delete', {pid: pid, tid: tid}, function(err) { + done(err, btn); + }); + }); + } + + function done(err, btn) { + if (err) { + return app.alertError(err.messaage); + } + btn.parent().fadeOut(function() { + btn.remove(); + }); + if (!$('.flags [data-pid]').length) { + $('.post-container').text('No flagged posts!'); + } + } + + function handleInfiniteScroll() { + infinitescroll.init(function(direction) { + if (direction < 0 && !$('.flags').length) { + return; + } + + infinitescroll.loadMore('admin.getMoreFlags', $('[data-next]').attr('data-next'), function(data, done) { + if (data.posts && data.posts.length) { + infinitescroll.parseAndTranslate('admin/manage/flags', 'posts', {posts: data.posts}, function(html) { + $('[data-next]').attr('data-next', data.next); + $('.post-container').append(html); + done(); + }); + } else { + done(); + } + }); + }); + } + + return Flags; +}); \ No newline at end of file diff --git a/src/controllers/admin.js b/src/controllers/admin.js index f8c31856bc..c438c4de94 100644 --- a/src/controllers/admin.js +++ b/src/controllers/admin.js @@ -6,6 +6,7 @@ var async = require('async'), user = require('../user'), categories = require('../categories'), + posts = require('../posts'), topics = require('../topics'), meta = require('../meta'), db = require('../database'), @@ -21,6 +22,7 @@ var async = require('async'), var adminController = { categories: {}, tags: {}, + flags: {}, topics: {}, groups: {}, appearance: {}, @@ -154,6 +156,17 @@ adminController.tags.get = function(req, res, next) { }); }; +adminController.flags.get = function(req, res, next) { + var uid = req.user ? parseInt(req.user.uid, 10) : 0; + posts.getFlags(uid, 0, 19, function(err, posts) { + if (err) { + return next(err); + } + + res.render('admin/manage/flags', {posts: posts, next: 20}); + }); +}; + adminController.database.get = function(req, res, next) { db.info(function (err, data) { res.render('admin/advanced/database', data); diff --git a/src/posts.js b/src/posts.js index dad45bc196..762f7bf4fc 100644 --- a/src/posts.js +++ b/src/posts.js @@ -28,6 +28,7 @@ var async = require('async'), (function(Posts) { require('./posts/recent')(Posts); require('./posts/delete')(Posts); + require('./posts/flags')(Posts); Posts.create = function(data, callback) { var uid = data.uid, @@ -237,6 +238,7 @@ var async = require('async'), Posts.getPostSummaryByPids = function(pids, uid, options, callback) { options.stripTags = options.hasOwnProperty('stripTags') ? options.stripTags : false; options.parse = options.hasOwnProperty('parse') ? options.parse : true; + options.extraFields = options.hasOwnProperty('extraFields') ? options.extraFields : []; if (!Array.isArray(pids) || !pids.length) { return callback(null, []); @@ -246,7 +248,9 @@ var async = require('async'), return 'post:' + pid; }); - db.getObjectsFields(keys, ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'], function(err, posts) { + var fields = ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'].concat(options.extraFields); + + db.getObjectsFields(keys, fields, function(err, posts) { if (err) { return callback(err); } diff --git a/src/posts/flags.js b/src/posts/flags.js new file mode 100644 index 0000000000..20614b75be --- /dev/null +++ b/src/posts/flags.js @@ -0,0 +1,45 @@ + + +'use strict'; + +var async = require('async'), + db = require('../database'); + + +module.exports = function(Posts) { + Posts.flag = function(pid, callback) { + async.parallel([ + function(next) { + db.sortedSetAdd('posts:flagged', Date.now(), pid, next); + }, + function(next) { + db.incrObjectField('post:' + pid, 'flags', next); + } + ], function(err, results) { + callback(err); + }); + }; + + Posts.dismissFlag = function(pid, callback) { + async.parallel([ + function(next) { + db.sortedSetRemove('posts:flagged', pid, next); + }, + function(next) { + db.deleteObjectField('post:' + pid, 'flags', next); + } + ], function(err, results) { + callback(err); + }); + }; + + Posts.getFlags = function(uid, start, end, callback) { + db.getSortedSetRevRange('posts:flagged', start, end, function(err, pids) { + if (err) { + return callback(err); + } + + Posts.getPostSummaryByPids(pids, uid, {stripTags: false, extraFields: ['flags']}, callback); + }); + }; +}; diff --git a/src/routes/admin.js b/src/routes/admin.js index 3a64902b93..73482537b3 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -46,6 +46,8 @@ function addRoutes(router, middleware, controllers) { router.get('/manage/tags', controllers.admin.tags.get); + router.get('/manage/flags', controllers.admin.flags.get); + router.get('/manage/users', controllers.admin.users.sortByJoinDate); router.get('/manage/users/search', controllers.admin.users.search); router.get('/manage/users/latest', controllers.admin.users.sortByJoinDate); diff --git a/src/socket.io/admin.js b/src/socket.io/admin.js index 46252c1ae0..e0af07fdb5 100644 --- a/src/socket.io/admin.js +++ b/src/socket.io/admin.js @@ -12,6 +12,7 @@ var async = require('async'), widgets = require('../widgets'), user = require('../user'), topics = require('../topics'), + posts = require('../posts'), categories = require('../categories'), logger = require('../logger'), events = require('../events'), @@ -249,4 +250,22 @@ SocketAdmin.getMoreEvents = function(socket, next, callback) { }; +SocketAdmin.dismissFlag = function(socket, pid, callback) { + if (!pid) { + return callback('[[error:invalid-data]]'); + } + + posts.dismissFlag(pid, callback); +}; + +SocketAdmin.getMoreFlags = function(socket, after, callback) { + if (!parseInt(after, 10)) { + return callback('[[error:invalid-data]]'); + } + after = parseInt(after, 10); + posts.getFlags(socket.uid, after, after + 19, function(err, posts) { + callback(err, {posts: posts, next: after + 20}); + }); +}; + module.exports = SocketAdmin; diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index 1ee33baad8..b445a3eefe 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -322,6 +322,9 @@ SocketPosts.flag = function(socket, pid, callback) { notifications.push(notification, adminGroup.members, next); }); }, + function(next) { + posts.flag(pid, next); + }, function(next) { if (!parseInt(post.uid, 10)) { return next(); diff --git a/src/views/admin/header.tpl b/src/views/admin/header.tpl index d393adf6b8..b464908dac 100644 --- a/src/views/admin/header.tpl +++ b/src/views/admin/header.tpl @@ -106,6 +106,7 @@
  • Tags
  • Users
  • Groups
  • +
  • Flags