diff --git a/public/src/admin/manage/flags.js b/public/src/admin/manage/flags.js index a686c4a07e..8885d7b8a5 100644 --- a/public/src/admin/manage/flags.js +++ b/public/src/admin/manage/flags.js @@ -4,8 +4,9 @@ define('admin/manage/flags', [ 'forum/infinitescroll', 'autocomplete', - 'Chart' -], function(infinitescroll, autocomplete, Chart) { + 'Chart', + 'components' +], function(infinitescroll, autocomplete, Chart, components) { var Flags = {}; @@ -21,6 +22,7 @@ define('admin/manage/flags', [ handleDelete(); handleInfiniteScroll(); handleGraphs(); + handleFormActions(); }; function handleDismiss() { @@ -150,5 +152,19 @@ define('admin/manage/flags', [ }); } + function handleFormActions() { + components.get('posts/flag').find('[component="posts/flag/update"]').on('click', function() { + var pid = $(this).parents('[component="posts/flag"]').attr('data-pid'); + var formData = $($(this).parents('form').get(0)).serializeArray(); + + socket.emit('posts.updateFlag', { + pid: pid, + data: formData + }, function(err) { + console.log(arguments); + }); + }); + } + return Flags; }); \ No newline at end of file diff --git a/src/controllers/admin/flags.js b/src/controllers/admin/flags.js index 340eda0a9d..f21cc773ad 100644 --- a/src/controllers/admin/flags.js +++ b/src/controllers/admin/flags.js @@ -2,6 +2,7 @@ var async = require('async'); var posts = require('../../posts'); +var user = require('../../user'); var analytics = require('../../analytics'); var flagsController = {}; @@ -25,15 +26,32 @@ flagsController.get = function(req, res, next) { }, analytics: function(next) { analytics.getDailyStatsForSet('analytics:flags', Date.now(), 30, next); - } + }, + assignees: async.apply(user.getAdminsandGlobalMods) }, next); } ], function (err, results) { if (err) { return next(err); } + + // Minimise data set for assignees so tjs does less work + results.assignees = results.assignees.map(function(userObj) { + var keep = ['uid', 'username']; + for(var prop in userObj) { + if (userObj.hasOwnProperty(prop)) { + if (keep.indexOf(prop) === -1) { + delete userObj[prop]; + } + } + } + + return userObj; + }); + var data = { posts: results.posts, + assignees: results.assignees, analytics: results.analytics, next: stop + 1, byUsername: byUsername, diff --git a/src/posts/flags.js b/src/posts/flags.js index dcc2f32f1d..ba0196bedf 100644 --- a/src/posts/flags.js +++ b/src/posts/flags.js @@ -226,4 +226,38 @@ module.exports = function(Posts) { } ], callback); }; + + Posts.updateFlagData = function(pid, flagObj, callback) { + // Retrieve existing flag data to compare for history-saving purposes + var changes = []; + var changeset = {}; + var prop; + Posts.getPostData(pid, function(err, postData) { + // Track new additions + for(prop in flagObj) { + if (flagObj.hasOwnProperty(prop) && !postData.hasOwnProperty('flag:' + prop)) { + changes.push(prop); + } + + // Generate changeset for object modification + if (flagObj.hasOwnProperty(prop)) { + changeset['flag:' + prop] = flagObj[prop]; + } + } + + // Track changed items + for(prop in postData) { + if ( + postData.hasOwnProperty(prop) && prop.startsWith('flag:') && + flagObj.hasOwnProperty(prop.slice(5)) && + postData[prop] !== flagObj[prop.slice(5)] + ) { + changes.push(prop.slice(5)); + } + } + + // Save flag data into post hash + Posts.setPostFields(pid, changeset, callback); + }); + }; }; diff --git a/src/socket.io/posts/flag.js b/src/socket.io/posts/flag.js index 2ad5dcd2b8..6ebf9c05d8 100644 --- a/src/socket.io/posts/flag.js +++ b/src/socket.io/posts/flag.js @@ -163,7 +163,35 @@ module.exports = function(SocketPosts) { }, function (posts, next) { next(null, {posts: posts, next: stop + 1}); - }, + } ], callback); }; + + SocketPosts.updateFlag = function(socket, data, callback) { + if (!data || !(data.pid && data.data)) { + return callback('[[error:invalid-data]]'); + } + + var payload = {}; + + async.waterfall([ + function (next) { + user.isAdminOrGlobalMod(socket.uid, next); + }, + function (isAdminOrGlobalModerator, next) { + if (!isAdminOrGlobalModerator) { + return next(new Error('[[no-privileges]]')); + } + + // Translate form data into object + payload = data.data.reduce(function(memo, cur) { + memo[cur.name] = cur.value; + return memo; + }, payload); + + next(null, data.pid, payload); + }, + async.apply(posts.updateFlagData) + ], callback); + } }; diff --git a/src/user.js b/src/user.js index d04b7c8cce..48abf3f28c 100644 --- a/src/user.js +++ b/src/user.js @@ -2,6 +2,7 @@ var async = require('async'); +var groups = require('./groups'); var plugins = require('./plugins'); var db = require('./database'); var topics = require('./topics'); @@ -260,6 +261,19 @@ var utils = require('../public/src/utils'); }); }; + User.getAdminsandGlobalMods = function(callback) { + async.parallel({ + admins: async.apply(groups.getMembers, 'administrators', 0, -1), + mods: async.apply(groups.getMembers, 'Global Moderators', 0, -1) + }, function(err, results) { + if (err) { + return callback(err); + } + + User.getUsersData(results.admins.concat(results.mods), callback); + }); + }; + User.addInterstitials = function(callback) { plugins.registerHook('core', { hook: 'filter:register.interstitial', diff --git a/src/views/admin/manage/flags.tpl b/src/views/admin/manage/flags.tpl index 1e12d5c51a..04e7d86d1f 100644 --- a/src/views/admin/manage/flags.tpl +++ b/src/views/admin/manage/flags.tpl @@ -44,7 +44,7 @@