From 640df0379e3e3b818c9398da5a26b2585de550fd Mon Sep 17 00:00:00 2001
From: Julian Lam <julian@nodebb.org>
Date: Fri, 25 Nov 2016 12:43:10 -0500
Subject: [PATCH] flag list page (#5232)

---
 public/language/en-GB/flags.json |   6 ++
 src/controllers/mods.js          |   9 ++-
 src/flags.js                     | 101 ++++++++++++++++++++++---------
 src/routes/index.js              |   2 +-
 4 files changed, 87 insertions(+), 31 deletions(-)
 create mode 100644 public/language/en-GB/flags.json

diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json
new file mode 100644
index 0000000000..de083196e7
--- /dev/null
+++ b/public/language/en-GB/flags.json
@@ -0,0 +1,6 @@
+{
+    "quick-filters": "Quick Filters",
+    "reporter": "Reporter",
+    "reported-at": "Reported At",
+    "no-flags": "Hooray! No flags found."
+}
\ No newline at end of file
diff --git a/src/controllers/mods.js b/src/controllers/mods.js
index 0079412f87..2a1aad09dc 100644
--- a/src/controllers/mods.js
+++ b/src/controllers/mods.js
@@ -3,7 +3,8 @@
 var async = require('async');
 
 var user = require('../user');
-var adminFlagsController = require('./admin/flags');
+var flags = require('../flags');
+// var adminFlagsController = require('./admin/flags');
 
 var modsController = {};
 
@@ -20,7 +21,11 @@ modsController.flagged = function (req, res, next) {
 			res.locals.cids = results.moderatedCids;
 		}
 
-		adminFlagsController.get(req, res, next);
+		flags.list({}, function(err, flags) {
+			res.render('flags', {
+				flags: flags
+			});
+		});
 	});
 };
 
diff --git a/src/flags.js b/src/flags.js
index 89f42337d4..bdf1ac37bb 100644
--- a/src/flags.js
+++ b/src/flags.js
@@ -13,10 +13,71 @@ var utils = require('../public/src/utils');
 
 var Flags = {
 	_defaults: {
-		state: 'open'
+		state: 'open',
+		assignee: null
 	}
 };
 
+Flags.list = function (filters, callback) {
+	if (typeof filters === 'function' && !callback) {
+		callback = filters;
+		filters = {};
+	}
+
+	async.waterfall([
+		async.apply(db.getSortedSetRevRange.bind(db), 'flags:datetime', 0, 19),
+		function (flagIds, next) {
+			async.map(flagIds, function (flagId, next) {
+				async.waterfall([
+					async.apply(db.getObject, 'flag:' + flagId),
+					function (flagObj, next) {
+						user.getUserFields(flagObj.uid, ['username', 'picture'], function (err, userObj) {
+							next(err, Object.assign(flagObj, {
+								user: {
+									username: userObj.username,
+									picture: userObj.picture,
+									'icon:bgColor': userObj['icon:bgColor'],
+									'icon:text': userObj['icon:text']
+								}
+							}));
+						})
+					}
+				], function (err, flagObj) {
+					if (err) {
+						return next(err);
+					}
+
+					switch(flagObj.state) {
+						case 'open':
+							flagObj.labelClass = 'info';
+							break;
+						case 'wip':
+							flagObj.labelClass = 'warning';
+							break;
+						case 'resolved':
+							flagObj.labelClass = 'success';
+							break;
+						case 'rejected':
+							flagObj.labelClass = 'danger';
+							break;
+					}
+
+					next(null, Object.assign(flagObj, {
+						target_readable: flagObj.type.charAt(0).toUpperCase() + flagObj.type.slice(1) + ' ' + flagObj.id,
+						datetimeISO: new Date(parseInt(flagObj.datetime, 10)).toISOString()
+					}));
+				});
+			},  next);
+		}
+	], function (err, flags) {
+		if (err) {
+			return callback(err);
+		}
+
+		return callback(null, flags);
+	});
+};
+
 Flags.create = function (type, id, uid, reason, callback) {
 	async.waterfall([
 		function (next) {
@@ -38,23 +99,22 @@ Flags.create = function (type, id, uid, reason, callback) {
 			var flagId = utils.generateUUID();
 
 			async.parallel([
-				async.apply(db.setObject.bind(db), 'flag:' + flagId, _.defaults({
-					description: reason
-				}), Flags._defaults),
-				async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', now, flagId)
-			], function (err) {
-				if (err) {
-					return next(err);
-				}
-			});
+				async.apply(db.setObject.bind(db), 'flag:' + flagId, Object.assign({}, Flags._defaults, {
+					type: type,
+					id: id,
+					description: reason,
+					uid: uid,
+					datetime: Date.now()
+				})),
+				async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', Date.now(), flagId)
+			], next);
 		}
 	], function (err) {
 		if (err) {
 			return callback(err);
 		}
 
-		console.log('done', arguments);
-		process.exit();
+		callback();
 	});
 	// if (!parseInt(uid, 10) || !reason) {
 	// 	return callback();
@@ -107,7 +167,7 @@ Flags.create = function (type, id, uid, reason, callback) {
 	// 		], next);
 	// 	},
 	// 	function (data, next) {
-	// 		openNewFlag(post.pid, uid, next);
+	// 		openNewFlag(post.pid, uid, next);		// removed, used to just update flag to open state if new flag
 	// 	}
 	// ], function (err) {
 	// 	if (err) {
@@ -118,21 +178,6 @@ Flags.create = function (type, id, uid, reason, callback) {
 	// });
 };
 
-function openNewFlag(pid, uid, callback) {
-	db.sortedSetScore('posts:flags:count', pid, function (err, count) {
-		if (err) {
-			return callback(err);
-		}
-		if (count === 1) {	// Only update state on new flag
-			Flags.update(uid, pid, {
-				state: 'open'
-			}, callback);
-		} else {
-			callback();
-		}
-	});
-}
-
 Flags.exists = function (type, id, uid, callback) {
 	db.isObjectField('flagHash:flagId', [type, id, uid].join(':'), callback);
 };
diff --git a/src/routes/index.js b/src/routes/index.js
index f36ad1468a..0273160745 100644
--- a/src/routes/index.js
+++ b/src/routes/index.js
@@ -40,7 +40,7 @@ function mainRoutes(app, middleware, controllers) {
 }
 
 function modRoutes(app, middleware, controllers) {
-	setupPageRoute(app, '/posts/flags', middleware, [], controllers.mods.flagged);
+	setupPageRoute(app, '/flags', middleware, [], controllers.mods.flagged);
 }
 
 function globalModRoutes(app, middleware, controllers) {