From 1aa70c57eb60daa51bf1181335f37e5a46ffbb72 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 23 Nov 2016 19:41:35 -0500 Subject: [PATCH 001/122] WIP --- src/controllers/admin/flags.js | 3 +- src/flags.js | 484 +++++++++++++++++++++++++++++++++ src/posts.js | 1 - src/posts/delete.js | 3 +- src/posts/flags.js | 417 ---------------------------- src/socket.io/posts/flag.js | 9 +- src/upgrade.js | 7 +- src/user/admin.js | 3 +- 8 files changed, 499 insertions(+), 428 deletions(-) create mode 100644 src/flags.js delete mode 100644 src/posts/flags.js diff --git a/src/controllers/admin/flags.js b/src/controllers/admin/flags.js index 1b31a95ff4..80c31ba60a 100644 --- a/src/controllers/admin/flags.js +++ b/src/controllers/admin/flags.js @@ -5,6 +5,7 @@ var validator = require('validator'); var posts = require('../../posts'); var user = require('../../user'); +var flags = require('../../flags'); var categories = require('../../categories'); var analytics = require('../../analytics'); var pagination = require('../../pagination'); @@ -94,7 +95,7 @@ function getFlagData(req, res, callback) { sets.push('uid:' + uid + ':flag:pids'); } - posts.getFlags(sets, cid, req.uid, start, stop, next); + flags.get(sets, cid, req.uid, start, stop, next); } ], callback); } diff --git a/src/flags.js b/src/flags.js new file mode 100644 index 0000000000..1e6294aecb --- /dev/null +++ b/src/flags.js @@ -0,0 +1,484 @@ + + +'use strict'; + +var async = require('async'); +var winston = require('winston'); +var db = require('./database'); +var user = require('./user'); +var analytics = require('./analytics'); +var topics = require('./topics'); +var posts = require('./posts'); +var utils = require('../public/src/utils'); + +var Flags = { + _defaults: { + state: 'open' + } +}; + +Flags.create = function (type, id, uid, reason, callback) { + async.waterfall([ + function (next) { + // Sanity checks + async.parallel([ + async.apply(Flags.exists, type, id, uid), + async.apply(Flags.targetExists, type, id) + ], function (err, checks) { + if (checks[0]) { + return next(new Error('[[error:already-flagged]]')); + } else if (!checks[1]) { + return next(new Error('[[error:invalid-data]]')); + } else { + next(); + } + }); + }, + function (next) { + 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); + } + }); + } + ], function (err) { + if (err) { + return callback(err); + } + + console.log('done', arguments); + process.exit(); + }); + // if (!parseInt(uid, 10) || !reason) { + // return callback(); + // } + + // async.waterfall([ + // function (next) { + // async.parallel({ + // hasFlagged: async.apply(Flags.isFlaggedByUser, post.pid, uid), + // exists: async.apply(Posts.exists, post.pid) + // }, next); + // }, + // function (results, next) { + // if (!results.exists) { + // return next(new Error('[[error:no-post]]')); + // } + + // if (results.hasFlagged) { + // return next(new Error('[[error:already-flagged]]')); + // } + + // var now = Date.now(); + // async.parallel([ + // function (next) { + // db.sortedSetAdd('posts:flagged', now, post.pid, next); + // }, + // function (next) { + // db.sortedSetIncrBy('posts:flags:count', 1, post.pid, next); + // }, + // function (next) { + // db.incrObjectField('post:' + post.pid, 'flags', next); + // }, + // function (next) { + // db.sortedSetAdd('pid:' + post.pid + ':flag:uids', now, uid, next); + // }, + // function (next) { + // db.sortedSetAdd('pid:' + post.pid + ':flag:uid:reason', 0, uid + ':' + reason, next); + // }, + // function (next) { + // if (parseInt(post.uid, 10)) { + // async.parallel([ + // async.apply(db.sortedSetIncrBy, 'users:flags', 1, post.uid), + // async.apply(db.incrObjectField, 'user:' + post.uid, 'flags'), + // async.apply(db.sortedSetAdd, 'uid:' + post.uid + ':flag:pids', now, post.pid) + // ], next); + // } else { + // next(); + // } + // } + // ], next); + // }, + // function (data, next) { + // openNewFlag(post.pid, uid, next); + // } + // ], function (err) { + // if (err) { + // return callback(err); + // } + // analytics.increment('flags'); + // 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); +}; + +Flags.targetExists = function (type, id, callback) { + switch (type) { + case 'topic': + topics.exists(id, callback); + break; + + case 'post': + posts.exists(id, callback); + break; + } +}; + +/* new signature (type, id, uid, callback) */ +Flags.isFlaggedByUser = function (pid, uid, callback) { + db.isSortedSetMember('pid:' + pid + ':flag:uids', uid, callback); +}; + +Flags.dismiss = function (pid, callback) { + async.waterfall([ + function (next) { + db.getObjectFields('post:' + pid, ['pid', 'uid', 'flags'], next); + }, + function (postData, next) { + if (!postData.pid) { + return callback(); + } + async.parallel([ + function (next) { + if (parseInt(postData.uid, 10)) { + if (parseInt(postData.flags, 10) > 0) { + async.parallel([ + async.apply(db.sortedSetIncrBy, 'users:flags', -postData.flags, postData.uid), + async.apply(db.incrObjectFieldBy, 'user:' + postData.uid, 'flags', -postData.flags) + ], next); + } else { + next(); + } + } else { + next(); + } + }, + function (next) { + db.sortedSetsRemove([ + 'posts:flagged', + 'posts:flags:count', + 'uid:' + postData.uid + ':flag:pids' + ], pid, next); + }, + function (next) { + async.series([ + function (next) { + db.getSortedSetRange('pid:' + pid + ':flag:uids', 0, -1, function (err, uids) { + if (err) { + return next(err); + } + + async.each(uids, function (uid, next) { + var nid = 'post_flag:' + pid + ':uid:' + uid; + async.parallel([ + async.apply(db.delete, 'notifications:' + nid), + async.apply(db.sortedSetRemove, 'notifications', 'post_flag:' + pid + ':uid:' + uid) + ], next); + }, next); + }); + }, + async.apply(db.delete, 'pid:' + pid + ':flag:uids') + ], next); + }, + async.apply(db.deleteObjectField, 'post:' + pid, 'flags'), + async.apply(db.delete, 'pid:' + pid + ':flag:uid:reason'), + async.apply(db.deleteObjectFields, 'post:' + pid, ['flag:state', 'flag:assignee', 'flag:notes', 'flag:history']) + ], next); + }, + function (results, next) { + db.sortedSetsRemoveRangeByScore(['users:flags'], '-inf', 0, next); + } + ], callback); +}; + +// Pretty sure we don't need this method... +Flags.dismissAll = function (callback) { + db.getSortedSetRange('posts:flagged', 0, -1, function (err, pids) { + if (err) { + return callback(err); + } + async.eachSeries(pids, Flags.dismiss, callback); + }); +}; + +Flags.dismissByUid = function (uid, callback) { + db.getSortedSetRange('uid:' + uid + ':flag:pids', 0, -1, function (err, pids) { + if (err) { + return callback(err); + } + async.eachSeries(pids, Flags.dismiss, callback); + }); +}; + +Flags.get = function (set, cid, uid, start, stop, callback) { + async.waterfall([ + function (next) { + if (Array.isArray(set)) { + db.getSortedSetRevIntersect({sets: set, start: start, stop: -1, aggregate: 'MAX'}, next); + } else { + db.getSortedSetRevRange(set, start, -1, next); + } + }, + function (pids, next) { + if (cid) { + Posts.filterPidsByCid(pids, cid, next); + } else { + process.nextTick(next, null, pids); + } + }, + function (pids, next) { + getFlaggedPostsWithReasons(pids, uid, next); + }, + function (posts, next) { + var count = posts.length; + var end = stop - start + 1; + next(null, {posts: posts.slice(0, stop === -1 ? undefined : end), count: count}); + } + ], callback); +}; + +function getFlaggedPostsWithReasons(pids, uid, callback) { + async.waterfall([ + function (next) { + async.parallel({ + uidsReasons: function (next) { + async.map(pids, function (pid, next) { + db.getSortedSetRange('pid:' + pid + ':flag:uid:reason', 0, -1, next); + }, next); + }, + posts: function (next) { + Posts.getPostSummaryByPids(pids, uid, {stripTags: false, extraFields: ['flags', 'flag:assignee', 'flag:state', 'flag:notes', 'flag:history']}, next); + } + }, next); + }, + function (results, next) { + async.map(results.uidsReasons, function (uidReasons, next) { + async.map(uidReasons, function (uidReason, next) { + var uid = uidReason.split(':')[0]; + var reason = uidReason.substr(uidReason.indexOf(':') + 1); + user.getUserFields(uid, ['username', 'userslug', 'picture'], function (err, userData) { + next(err, {user: userData, reason: reason}); + }); + }, next); + }, function (err, reasons) { + if (err) { + return callback(err); + } + + results.posts.forEach(function (post, index) { + if (post) { + post.flagReasons = reasons[index]; + } + }); + + next(null, results.posts); + }); + }, + async.apply(Posts.expandFlagHistory), + function (posts, next) { + // Parse out flag data into its own object inside each post hash + async.map(posts, function (postObj, next) { + for(var prop in postObj) { + postObj.flagData = postObj.flagData || {}; + + if (postObj.hasOwnProperty(prop) && prop.startsWith('flag:')) { + postObj.flagData[prop.slice(5)] = postObj[prop]; + + if (prop === 'flag:state') { + switch(postObj[prop]) { + case 'open': + postObj.flagData.labelClass = 'info'; + break; + case 'wip': + postObj.flagData.labelClass = 'warning'; + break; + case 'resolved': + postObj.flagData.labelClass = 'success'; + break; + case 'rejected': + postObj.flagData.labelClass = 'danger'; + break; + } + } + + delete postObj[prop]; + } + } + + if (postObj.flagData.assignee) { + user.getUserFields(parseInt(postObj.flagData.assignee, 10), ['username', 'picture'], function (err, userData) { + if (err) { + return next(err); + } + + postObj.flagData.assigneeUser = userData; + next(null, postObj); + }); + } else { + setImmediate(next.bind(null, null, postObj)); + } + }, next); + } + ], callback); +} + +// New method signature (type, id, flagObj, callback) and name (.update()) +// uid used in history string, which should be rewritten too. +Flags.update = function (uid, 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) { + if (err) { + return callback(err); + } + + // Track new additions + for(prop in flagObj) { + if (flagObj.hasOwnProperty(prop) && !postData.hasOwnProperty('flag:' + prop) && flagObj[prop].length) { + changes.push(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)); + } + } + + changeset = changes.reduce(function (memo, prop) { + memo['flag:' + prop] = flagObj[prop]; + return memo; + }, {}); + + // Append changes to history string + if (changes.length) { + try { + var history = JSON.parse(postData['flag:history'] || '[]'); + + changes.forEach(function (property) { + switch(property) { + case 'assignee': // intentional fall-through + case 'state': + history.unshift({ + uid: uid, + type: property, + value: flagObj[property], + timestamp: Date.now() + }); + break; + + case 'notes': + history.unshift({ + uid: uid, + type: property, + timestamp: Date.now() + }); + } + }); + + changeset['flag:history'] = JSON.stringify(history); + } catch (e) { + winston.warn('[flags/update] Unable to deserialise post flag history, likely malformed data'); + } + } + + // Save flag data into post hash + if (changes.length) { + Posts.setPostFields(pid, changeset, callback); + } else { + setImmediate(callback); + } + }); +}; + +// To be rewritten and deprecated +Flags.expandFlagHistory = function (posts, callback) { + // Expand flag history + async.map(posts, function (post, next) { + var history; + try { + history = JSON.parse(post['flag:history'] || '[]'); + } catch (e) { + winston.warn('[flags/get] Unable to deserialise post flag history, likely malformed data'); + return callback(e); + } + + async.map(history, function (event, next) { + event.timestampISO = new Date(event.timestamp).toISOString(); + + async.parallel([ + function (next) { + user.getUserFields(event.uid, ['username', 'picture'], function (err, userData) { + if (err) { + return next(err); + } + + event.user = userData; + next(); + }); + }, + function (next) { + if (event.type === 'assignee') { + user.getUserField(parseInt(event.value, 10), 'username', function (err, username) { + if (err) { + return next(err); + } + + event.label = username || 'Unknown user'; + next(null); + }); + } else if (event.type === 'state') { + event.label = '[[topic:flag_manage_state_' + event.value + ']]'; + setImmediate(next); + } else { + setImmediate(next); + } + } + ], function (err) { + next(err, event); + }); + }, function (err, history) { + if (err) { + return next(err); + } + + post['flag:history'] = history; + next(null, post); + }); + }, callback); +}; + +module.exports = Flags; \ No newline at end of file diff --git a/src/posts.js b/src/posts.js index 047917cb5f..b476b84414 100644 --- a/src/posts.js +++ b/src/posts.js @@ -21,7 +21,6 @@ var plugins = require('./plugins'); require('./posts/category')(Posts); require('./posts/summary')(Posts); require('./posts/recent')(Posts); - require('./posts/flags')(Posts); require('./posts/tools')(Posts); require('./posts/votes')(Posts); require('./posts/bookmarks')(Posts); diff --git a/src/posts/delete.js b/src/posts/delete.js index 7a1d3d0cc8..ebf902aef2 100644 --- a/src/posts/delete.js +++ b/src/posts/delete.js @@ -8,6 +8,7 @@ var topics = require('../topics'); var user = require('../user'); var notifications = require('../notifications'); var plugins = require('../plugins'); +var flags = require('../flags'); module.exports = function (Posts) { @@ -145,7 +146,7 @@ module.exports = function (Posts) { db.sortedSetsRemove(['posts:pid', 'posts:flagged'], pid, next); }, function (next) { - Posts.dismissFlag(pid, next); + flags.dismiss(pid, next); } ], function (err) { if (err) { diff --git a/src/posts/flags.js b/src/posts/flags.js deleted file mode 100644 index e81da20f95..0000000000 --- a/src/posts/flags.js +++ /dev/null @@ -1,417 +0,0 @@ - - -'use strict'; - -var async = require('async'); -var winston = require('winston'); -var db = require('../database'); -var user = require('../user'); -var analytics = require('../analytics'); - -module.exports = function (Posts) { - - Posts.flag = function (post, uid, reason, callback) { - if (!parseInt(uid, 10) || !reason) { - return callback(); - } - - async.waterfall([ - function (next) { - async.parallel({ - hasFlagged: async.apply(Posts.isFlaggedByUser, post.pid, uid), - exists: async.apply(Posts.exists, post.pid) - }, next); - }, - function (results, next) { - if (!results.exists) { - return next(new Error('[[error:no-post]]')); - } - - if (results.hasFlagged) { - return next(new Error('[[error:already-flagged]]')); - } - - var now = Date.now(); - async.parallel([ - function (next) { - db.sortedSetAdd('posts:flagged', now, post.pid, next); - }, - function (next) { - db.sortedSetIncrBy('posts:flags:count', 1, post.pid, next); - }, - function (next) { - db.incrObjectField('post:' + post.pid, 'flags', next); - }, - function (next) { - db.sortedSetAdd('pid:' + post.pid + ':flag:uids', now, uid, next); - }, - function (next) { - db.sortedSetAdd('pid:' + post.pid + ':flag:uid:reason', 0, uid + ':' + reason, next); - }, - function (next) { - if (parseInt(post.uid, 10)) { - async.parallel([ - async.apply(db.sortedSetIncrBy, 'users:flags', 1, post.uid), - async.apply(db.incrObjectField, 'user:' + post.uid, 'flags'), - async.apply(db.sortedSetAdd, 'uid:' + post.uid + ':flag:pids', now, post.pid) - ], next); - } else { - next(); - } - } - ], next); - }, - function (data, next) { - openNewFlag(post.pid, uid, next); - } - ], function (err) { - if (err) { - return callback(err); - } - analytics.increment('flags'); - 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 - Posts.updateFlagData(uid, pid, { - state: 'open' - }, callback); - } else { - callback(); - } - }); - } - - Posts.isFlaggedByUser = function (pid, uid, callback) { - db.isSortedSetMember('pid:' + pid + ':flag:uids', uid, callback); - }; - - Posts.dismissFlag = function (pid, callback) { - async.waterfall([ - function (next) { - db.getObjectFields('post:' + pid, ['pid', 'uid', 'flags'], next); - }, - function (postData, next) { - if (!postData.pid) { - return callback(); - } - async.parallel([ - function (next) { - if (parseInt(postData.uid, 10)) { - if (parseInt(postData.flags, 10) > 0) { - async.parallel([ - async.apply(db.sortedSetIncrBy, 'users:flags', -postData.flags, postData.uid), - async.apply(db.incrObjectFieldBy, 'user:' + postData.uid, 'flags', -postData.flags) - ], next); - } else { - next(); - } - } else { - next(); - } - }, - function (next) { - db.sortedSetsRemove([ - 'posts:flagged', - 'posts:flags:count', - 'uid:' + postData.uid + ':flag:pids' - ], pid, next); - }, - function (next) { - async.series([ - function (next) { - db.getSortedSetRange('pid:' + pid + ':flag:uids', 0, -1, function (err, uids) { - if (err) { - return next(err); - } - - async.each(uids, function (uid, next) { - var nid = 'post_flag:' + pid + ':uid:' + uid; - async.parallel([ - async.apply(db.delete, 'notifications:' + nid), - async.apply(db.sortedSetRemove, 'notifications', 'post_flag:' + pid + ':uid:' + uid) - ], next); - }, next); - }); - }, - async.apply(db.delete, 'pid:' + pid + ':flag:uids') - ], next); - }, - async.apply(db.deleteObjectField, 'post:' + pid, 'flags'), - async.apply(db.delete, 'pid:' + pid + ':flag:uid:reason'), - async.apply(db.deleteObjectFields, 'post:' + pid, ['flag:state', 'flag:assignee', 'flag:notes', 'flag:history']) - ], next); - }, - function (results, next) { - db.sortedSetsRemoveRangeByScore(['users:flags'], '-inf', 0, next); - } - ], callback); - }; - - Posts.dismissAllFlags = function (callback) { - db.getSortedSetRange('posts:flagged', 0, -1, function (err, pids) { - if (err) { - return callback(err); - } - async.eachSeries(pids, Posts.dismissFlag, callback); - }); - }; - - Posts.dismissUserFlags = function (uid, callback) { - db.getSortedSetRange('uid:' + uid + ':flag:pids', 0, -1, function (err, pids) { - if (err) { - return callback(err); - } - async.eachSeries(pids, Posts.dismissFlag, callback); - }); - }; - - Posts.getFlags = function (set, cid, uid, start, stop, callback) { - async.waterfall([ - function (next) { - if (Array.isArray(set)) { - db.getSortedSetRevIntersect({sets: set, start: start, stop: -1, aggregate: 'MAX'}, next); - } else { - db.getSortedSetRevRange(set, start, -1, next); - } - }, - function (pids, next) { - if (cid) { - Posts.filterPidsByCid(pids, cid, next); - } else { - process.nextTick(next, null, pids); - } - }, - function (pids, next) { - getFlaggedPostsWithReasons(pids, uid, next); - }, - function (posts, next) { - var count = posts.length; - var end = stop - start + 1; - next(null, {posts: posts.slice(0, stop === -1 ? undefined : end), count: count}); - } - ], callback); - }; - - function getFlaggedPostsWithReasons(pids, uid, callback) { - async.waterfall([ - function (next) { - async.parallel({ - uidsReasons: function (next) { - async.map(pids, function (pid, next) { - db.getSortedSetRange('pid:' + pid + ':flag:uid:reason', 0, -1, next); - }, next); - }, - posts: function (next) { - Posts.getPostSummaryByPids(pids, uid, {stripTags: false, extraFields: ['flags', 'flag:assignee', 'flag:state', 'flag:notes', 'flag:history']}, next); - } - }, next); - }, - function (results, next) { - async.map(results.uidsReasons, function (uidReasons, next) { - async.map(uidReasons, function (uidReason, next) { - var uid = uidReason.split(':')[0]; - var reason = uidReason.substr(uidReason.indexOf(':') + 1); - user.getUserFields(uid, ['username', 'userslug', 'picture'], function (err, userData) { - next(err, {user: userData, reason: reason}); - }); - }, next); - }, function (err, reasons) { - if (err) { - return callback(err); - } - - results.posts.forEach(function (post, index) { - if (post) { - post.flagReasons = reasons[index]; - } - }); - - next(null, results.posts); - }); - }, - async.apply(Posts.expandFlagHistory), - function (posts, next) { - // Parse out flag data into its own object inside each post hash - async.map(posts, function (postObj, next) { - for(var prop in postObj) { - postObj.flagData = postObj.flagData || {}; - - if (postObj.hasOwnProperty(prop) && prop.startsWith('flag:')) { - postObj.flagData[prop.slice(5)] = postObj[prop]; - - if (prop === 'flag:state') { - switch(postObj[prop]) { - case 'open': - postObj.flagData.labelClass = 'info'; - break; - case 'wip': - postObj.flagData.labelClass = 'warning'; - break; - case 'resolved': - postObj.flagData.labelClass = 'success'; - break; - case 'rejected': - postObj.flagData.labelClass = 'danger'; - break; - } - } - - delete postObj[prop]; - } - } - - if (postObj.flagData.assignee) { - user.getUserFields(parseInt(postObj.flagData.assignee, 10), ['username', 'picture'], function (err, userData) { - if (err) { - return next(err); - } - - postObj.flagData.assigneeUser = userData; - next(null, postObj); - }); - } else { - setImmediate(next.bind(null, null, postObj)); - } - }, next); - } - ], callback); - } - - Posts.updateFlagData = function (uid, 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) { - if (err) { - return callback(err); - } - - // Track new additions - for(prop in flagObj) { - if (flagObj.hasOwnProperty(prop) && !postData.hasOwnProperty('flag:' + prop) && flagObj[prop].length) { - changes.push(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)); - } - } - - changeset = changes.reduce(function (memo, prop) { - memo['flag:' + prop] = flagObj[prop]; - return memo; - }, {}); - - // Append changes to history string - if (changes.length) { - try { - var history = JSON.parse(postData['flag:history'] || '[]'); - - changes.forEach(function (property) { - switch(property) { - case 'assignee': // intentional fall-through - case 'state': - history.unshift({ - uid: uid, - type: property, - value: flagObj[property], - timestamp: Date.now() - }); - break; - - case 'notes': - history.unshift({ - uid: uid, - type: property, - timestamp: Date.now() - }); - } - }); - - changeset['flag:history'] = JSON.stringify(history); - } catch (e) { - winston.warn('[posts/updateFlagData] Unable to deserialise post flag history, likely malformed data'); - } - } - - // Save flag data into post hash - if (changes.length) { - Posts.setPostFields(pid, changeset, callback); - } else { - setImmediate(callback); - } - }); - }; - - Posts.expandFlagHistory = function (posts, callback) { - // Expand flag history - async.map(posts, function (post, next) { - var history; - try { - history = JSON.parse(post['flag:history'] || '[]'); - } catch (e) { - winston.warn('[posts/getFlags] Unable to deserialise post flag history, likely malformed data'); - return callback(e); - } - - async.map(history, function (event, next) { - event.timestampISO = new Date(event.timestamp).toISOString(); - - async.parallel([ - function (next) { - user.getUserFields(event.uid, ['username', 'picture'], function (err, userData) { - if (err) { - return next(err); - } - - event.user = userData; - next(); - }); - }, - function (next) { - if (event.type === 'assignee') { - user.getUserField(parseInt(event.value, 10), 'username', function (err, username) { - if (err) { - return next(err); - } - - event.label = username || 'Unknown user'; - next(null); - }); - } else if (event.type === 'state') { - event.label = '[[topic:flag_manage_state_' + event.value + ']]'; - setImmediate(next); - } else { - setImmediate(next); - } - } - ], function (err) { - next(err, event); - }); - }, function (err, history) { - if (err) { - return next(err); - } - - post['flag:history'] = history; - next(null, post); - }); - }, callback); - }; -}; diff --git a/src/socket.io/posts/flag.js b/src/socket.io/posts/flag.js index 077b88bfc9..88b47058d1 100644 --- a/src/socket.io/posts/flag.js +++ b/src/socket.io/posts/flag.js @@ -12,6 +12,7 @@ var notifications = require('../../notifications'); var plugins = require('../../plugins'); var meta = require('../../meta'); var utils = require('../../../public/src/utils'); +var flags = require('../../flags'); module.exports = function (SocketPosts) { @@ -64,7 +65,7 @@ module.exports = function (SocketPosts) { flaggingUser = user.userData; flaggingUser.uid = socket.uid; - posts.flag(post, socket.uid, data.reason, next); + flags.create('post', post.pid, socket.uid, data.reason, next); }, function (next) { async.parallel({ @@ -119,7 +120,7 @@ module.exports = function (SocketPosts) { if (!isAdminOrGlobalModerator) { return next(new Error('[[no-privileges]]')); } - posts.dismissFlag(pid, next); + flags.dismiss(pid, next); } ], callback); }; @@ -133,7 +134,7 @@ module.exports = function (SocketPosts) { if (!isAdminOrGlobalModerator) { return next(new Error('[[no-privileges]]')); } - posts.dismissAllFlags(next); + flags.dismissAll(next); } ], callback); }; @@ -165,7 +166,7 @@ module.exports = function (SocketPosts) { return memo; }, payload); - posts.updateFlagData(socket.uid, data.pid, payload, next); + flags.update(socket.uid, data.pid, payload, next); } ], callback); }; diff --git a/src/upgrade.js b/src/upgrade.js index 79ffa6b5ee..2a605e84f9 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -462,8 +462,9 @@ Upgrade.upgrade = function (callback) { updatesMade = true; winston.info('[2016/04/29] Dismiss flags from deleted topics'); - var posts = require('./posts'), - topics = require('./topics'); + var posts = require('./posts'); + var topics = require('./topics'); + var flags = require('./flags'); var pids, tids; @@ -486,7 +487,7 @@ Upgrade.upgrade = function (callback) { }).filter(Boolean); winston.info('[2016/04/29] ' + toDismiss.length + ' dismissable flags found'); - async.each(toDismiss, posts.dismissFlag, next); + async.each(toDismiss, flags.dismiss, next); } ], function (err) { if (err) { diff --git a/src/user/admin.js b/src/user/admin.js index 8b5a6ebef4..5d2215980c 100644 --- a/src/user/admin.js +++ b/src/user/admin.js @@ -6,6 +6,7 @@ var db = require('../database'); var posts = require('../posts'); var plugins = require('../plugins'); var winston = require('winston'); +var flags = require('../flags'); module.exports = function (User) { @@ -62,7 +63,7 @@ module.exports = function (User) { } async.eachSeries(uids, function (uid, next) { - posts.dismissUserFlags(uid, next); + flags.dismissByUid(uid, next); }, callback); }; }; From 106502952a79ce18a7f0d1ce54ff036527ee955f Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 24 Nov 2016 11:56:57 -0500 Subject: [PATCH 002/122] fixed crash in flags page for now --- src/flags.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/flags.js b/src/flags.js index 1e6294aecb..89f42337d4 100644 --- a/src/flags.js +++ b/src/flags.js @@ -246,7 +246,7 @@ Flags.get = function (set, cid, uid, start, stop, callback) { }, function (pids, next) { if (cid) { - Posts.filterPidsByCid(pids, cid, next); + posts.filterPidsByCid(pids, cid, next); } else { process.nextTick(next, null, pids); } @@ -272,7 +272,7 @@ function getFlaggedPostsWithReasons(pids, uid, callback) { }, next); }, posts: function (next) { - Posts.getPostSummaryByPids(pids, uid, {stripTags: false, extraFields: ['flags', 'flag:assignee', 'flag:state', 'flag:notes', 'flag:history']}, next); + posts.getPostSummaryByPids(pids, uid, {stripTags: false, extraFields: ['flags', 'flag:assignee', 'flag:state', 'flag:notes', 'flag:history']}, next); } }, next); }, @@ -299,7 +299,7 @@ function getFlaggedPostsWithReasons(pids, uid, callback) { next(null, results.posts); }); }, - async.apply(Posts.expandFlagHistory), + async.apply(Flags.expandFlagHistory), function (posts, next) { // Parse out flag data into its own object inside each post hash async.map(posts, function (postObj, next) { @@ -355,7 +355,7 @@ Flags.update = function (uid, pid, flagObj, callback) { var changeset = {}; var prop; - Posts.getPostData(pid, function (err, postData) { + posts.getPostData(pid, function (err, postData) { if (err) { return callback(err); } @@ -417,7 +417,7 @@ Flags.update = function (uid, pid, flagObj, callback) { // Save flag data into post hash if (changes.length) { - Posts.setPostFields(pid, changeset, callback); + posts.setPostFields(pid, changeset, callback); } else { setImmediate(callback); } From 640df0379e3e3b818c9398da5a26b2585de550fd Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 25 Nov 2016 12:43:10 -0500 Subject: [PATCH 003/122] 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) { From 98a104564b511155cbf24a78406905b07f96ae74 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 25 Nov 2016 14:17:51 -0500 Subject: [PATCH 004/122] some light refactoring, details API (#5232) --- public/language/en-GB/flags.json | 1 + src/controllers/mods.js | 28 ++++++++-- src/flags.js | 92 ++++++++++++++++++++------------ src/routes/index.js | 3 +- 4 files changed, 86 insertions(+), 38 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index de083196e7..ad8456ebf6 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -1,5 +1,6 @@ { "quick-filters": "Quick Filters", + "state": "State", "reporter": "Reporter", "reported-at": "Reported At", "no-flags": "Hooray! No flags found." diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 2a1aad09dc..f5a6e9b06d 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -6,15 +6,19 @@ var user = require('../user'); var flags = require('../flags'); // var adminFlagsController = require('./admin/flags'); -var modsController = {}; +var modsController = { + flags: {} +}; -modsController.flagged = function (req, res, next) { +modsController.flags.list = function (req, res, next) { async.parallel({ isAdminOrGlobalMod: async.apply(user.isAdminOrGlobalMod, req.uid), moderatedCids: async.apply(user.getModeratedCids, req.uid) }, function (err, results) { - if (err || !(results.isAdminOrGlobalMod || !!results.moderatedCids.length)) { + if (err) { return next(err); + } else if (!(results.isAdminOrGlobalMod || !!results.moderatedCids.length)) { + return next(new Error('[[error:no-privileges]]')); } if (!results.isAdminOrGlobalMod && results.moderatedCids.length) { @@ -22,11 +26,27 @@ modsController.flagged = function (req, res, next) { } flags.list({}, function(err, flags) { - res.render('flags', { + res.render('flags/list', { flags: flags }); }); }); }; +modsController.flags.detail = function (req, res, next) { + async.parallel({ + isAdminOrGlobalMod: async.apply(user.isAdminOrGlobalMod, req.uid), + moderatedCids: async.apply(user.getModeratedCids, req.uid), + flagData: async.apply(flags.get, req.params.flagId) + }, function (err, results) { + if (err || !results.flagData) { + return next(err || new Error('[[error:invalid-data]]')); + } else if (!(results.isAdminOrGlobalMod || !!results.moderatedCids.length)) { + return next(new Error('[[error:no-privileges]]')); + } + + res.render('flags/detail', results.flagData); + }); +}; + module.exports = modsController; diff --git a/src/flags.js b/src/flags.js index bdf1ac37bb..8734f811a8 100644 --- a/src/flags.js +++ b/src/flags.js @@ -18,6 +18,30 @@ var Flags = { } }; +Flags.get = function (flagId, callback) { + async.waterfall([ + async.apply(async.parallel, { + base: async.apply(db.getObject.bind(db), 'flag:' + flagId), + history: async.apply(db.getSortedSetRevRange.bind(db), 'flag:' + flagId + ':history', 0, -1), + notes: async.apply(db.getSortedSetRevRange.bind(db), 'flag:' + flagId + ':notes', 0, -1) + }), + function (data, next) { + user.getUserFields(data.base.uid, ['username', 'picture'], function (err, userObj) { + next(err, Object.assign(data.base, { + history: data.history, + notes: data.notes, + reporter: { + username: userObj.username, + picture: userObj.picture, + 'icon:bgColor': userObj['icon:bgColor'], + 'icon:text': userObj['icon:text'] + } + })); + }); + } + ], callback); +}; + Flags.list = function (filters, callback) { if (typeof filters === 'function' && !callback) { callback = filters; @@ -33,7 +57,7 @@ Flags.list = function (filters, callback) { function (flagObj, next) { user.getUserFields(flagObj.uid, ['username', 'picture'], function (err, userObj) { next(err, Object.assign(flagObj, { - user: { + reporter: { username: userObj.username, picture: userObj.picture, 'icon:bgColor': userObj['icon:bgColor'], @@ -63,7 +87,7 @@ Flags.list = function (filters, callback) { } next(null, Object.assign(flagObj, { - target_readable: flagObj.type.charAt(0).toUpperCase() + flagObj.type.slice(1) + ' ' + flagObj.id, + target_readable: flagObj.type.charAt(0).toUpperCase() + flagObj.type.slice(1) + ' ' + flagObj.targetId, datetimeISO: new Date(parseInt(flagObj.datetime, 10)).toISOString() })); }); @@ -95,18 +119,19 @@ Flags.create = function (type, id, uid, reason, callback) { } }); }, - function (next) { - var flagId = utils.generateUUID(); - + async.apply(db.incrObjectField, 'global', 'nextFlagId'), + function (flagId, next) { async.parallel([ async.apply(db.setObject.bind(db), 'flag:' + flagId, Object.assign({}, Flags._defaults, { + flagId: flagId, type: type, - id: id, + targetId: id, description: reason, uid: uid, datetime: Date.now() })), - async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', Date.now(), flagId) + async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', Date.now(), flagId), + async.apply(db.setObjectField.bind(db), 'flagHash:flagId', [type, id, uid].join(':'), flagId) ], next); } ], function (err) { @@ -280,32 +305,33 @@ Flags.dismissByUid = function (uid, callback) { }); }; -Flags.get = function (set, cid, uid, start, stop, callback) { - async.waterfall([ - function (next) { - if (Array.isArray(set)) { - db.getSortedSetRevIntersect({sets: set, start: start, stop: -1, aggregate: 'MAX'}, next); - } else { - db.getSortedSetRevRange(set, start, -1, next); - } - }, - function (pids, next) { - if (cid) { - posts.filterPidsByCid(pids, cid, next); - } else { - process.nextTick(next, null, pids); - } - }, - function (pids, next) { - getFlaggedPostsWithReasons(pids, uid, next); - }, - function (posts, next) { - var count = posts.length; - var end = stop - start + 1; - next(null, {posts: posts.slice(0, stop === -1 ? undefined : end), count: count}); - } - ], callback); -}; +// This is the old method to get list of flags, supercede by Flags.list(); +// Flags.get = function (set, cid, uid, start, stop, callback) { +// async.waterfall([ +// function (next) { +// if (Array.isArray(set)) { +// db.getSortedSetRevIntersect({sets: set, start: start, stop: -1, aggregate: 'MAX'}, next); +// } else { +// db.getSortedSetRevRange(set, start, -1, next); +// } +// }, +// function (pids, next) { +// if (cid) { +// posts.filterPidsByCid(pids, cid, next); +// } else { +// process.nextTick(next, null, pids); +// } +// }, +// function (pids, next) { +// getFlaggedPostsWithReasons(pids, uid, next); +// }, +// function (posts, next) { +// var count = posts.length; +// var end = stop - start + 1; +// next(null, {posts: posts.slice(0, stop === -1 ? undefined : end), count: count}); +// } +// ], callback); +// }; function getFlaggedPostsWithReasons(pids, uid, callback) { async.waterfall([ diff --git a/src/routes/index.js b/src/routes/index.js index 0273160745..f71eac2c62 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -40,7 +40,8 @@ function mainRoutes(app, middleware, controllers) { } function modRoutes(app, middleware, controllers) { - setupPageRoute(app, '/flags', middleware, [], controllers.mods.flagged); + setupPageRoute(app, '/flags', middleware, [], controllers.mods.flags.list); + setupPageRoute(app, '/flags/:flagId', middleware, [], controllers.mods.flags.detail); } function globalModRoutes(app, middleware, controllers) { From 9f7c4befea24d4af92bfb60fecc065125f6b5ffe Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 25 Nov 2016 15:09:52 -0500 Subject: [PATCH 005/122] omg tests (#5232), and .create returns flag data now --- src/controllers/mods.js | 6 ++- src/flags.js | 23 +++++---- test/flags.js | 107 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 test/flags.js diff --git a/src/controllers/mods.js b/src/controllers/mods.js index f5a6e9b06d..7ebb70d888 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -25,7 +25,11 @@ modsController.flags.list = function (req, res, next) { res.locals.cids = results.moderatedCids; } - flags.list({}, function(err, flags) { + flags.list({}, function (err, flags) { + if (err) { + return next(err); + } + res.render('flags/list', { flags: flags }); diff --git a/src/flags.js b/src/flags.js index 8734f811a8..d9f6aa136f 100644 --- a/src/flags.js +++ b/src/flags.js @@ -64,7 +64,7 @@ Flags.list = function (filters, callback) { 'icon:text': userObj['icon:text'] } })); - }) + }); } ], function (err, flagObj) { if (err) { @@ -110,6 +110,10 @@ Flags.create = function (type, id, uid, reason, callback) { async.apply(Flags.exists, type, id, uid), async.apply(Flags.targetExists, type, id) ], function (err, checks) { + if (err) { + return next(err); + } + if (checks[0]) { return next(new Error('[[error:already-flagged]]')); } else if (!checks[1]) { @@ -132,15 +136,16 @@ Flags.create = function (type, id, uid, reason, callback) { })), async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', Date.now(), flagId), async.apply(db.setObjectField.bind(db), 'flagHash:flagId', [type, id, uid].join(':'), flagId) - ], next); - } - ], function (err) { - if (err) { - return callback(err); - } + ], function (err, data) { + if (err) { + return next(err); + } - callback(); - }); + next(null, flagId); + }); + }, + async.apply(Flags.get) + ], callback); // if (!parseInt(uid, 10) || !reason) { // return callback(); // } diff --git a/test/flags.js b/test/flags.js new file mode 100644 index 0000000000..ed879fba49 --- /dev/null +++ b/test/flags.js @@ -0,0 +1,107 @@ +'use strict'; +/*globals require, before, after, describe, it*/ + +var assert = require('assert'); +var async = require('async'); + +var db = require('./mocks/databasemock'); +var Flags = require('../src/flags'); +var Categories = require('../src/categories'); +var Topics = require('../src/topics'); +var User = require('../src/user'); + +describe('Flags', function () { + before(function (done) { + // Create some stuff to flag + async.waterfall([ + async.apply(User.create, {username: 'testUser', password: 'abcdef', email: 'b@c.com'}), + function (uid, next) { + Categories.create({ + name: 'test category' + }, function (err, category) { + if (err) { + return done(err); + } + + Topics.post({ + cid: category.cid, + uid: uid, + title: 'Topic to flag', + content: 'This is flaggable content' + }, next); + }); + } + ], done); + }); + + describe('.create()', function () { + it('should create a flag and return its data', function (done) { + Flags.create('post', 1, 1, 'Test flag', function (err, flagData) { + assert.ifError(err); + var compare = { + flagId: 1, + uid: 1, + targetId: 1, + type: 'post', + description: 'Test flag', + state: 'open' + }; + + for(var key in compare) { + if (compare.hasOwnProperty(key)) { + assert.ok(flagData[key]); + assert.strictEqual(flagData[key], compare[key]); + } + } + + done(); + }); + }); + }); + + describe('.get()', function () { + it('should retrieve and display a flag\'s data', function (done) { + Flags.get(1, function (err, flagData) { + assert.ifError(err); + var compare = { + flagId: 1, + uid: 1, + targetId: 1, + type: 'post', + description: 'Test flag', + state: 'open' + }; + + for(var key in compare) { + if (compare.hasOwnProperty(key)) { + assert.ok(flagData[key]); + assert.strictEqual(flagData[key], compare[key]); + } + } + + done(); + }); + }); + }); + + describe('.list()', function () { + it('should show a list of flags (with one item)', function (done) { + Flags.list({}, function (err, flags) { + assert.ifError(err); + assert.ok(Array.isArray(flags)); + assert.equal(flags.length, 1); + + Flags.get(flags[0].flagId, function (err, flagData) { + assert.ifError(err); + assert.equal(flags[0].flagId, flagData.flagId); + assert.equal(flags[0].description, flagData.description); + done(); + }); + }); + }); + }); + + after(function (done) { + db.emptydb(done); + }); +}); From fceb5cc86b600087bff8b2adc983e70c3fbb725e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 29 Nov 2016 22:10:51 -0500 Subject: [PATCH 006/122] more work on flags detail pages (#5232) --- public/language/en-GB/flags.json | 16 +++++++++----- public/language/en-GB/topic.json | 5 ----- src/flags.js | 38 +++++++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index ad8456ebf6..bf22e68df6 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -1,7 +1,13 @@ { - "quick-filters": "Quick Filters", - "state": "State", - "reporter": "Reporter", - "reported-at": "Reported At", - "no-flags": "Hooray! No flags found." + "quick-filters": "Quick Filters", + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "no-flags": "Hooray! No flags found.", + + "state": "State", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected" } \ No newline at end of file diff --git a/public/language/en-GB/topic.json b/public/language/en-GB/topic.json index 29a85c15cc..885afe5d62 100644 --- a/public/language/en-GB/topic.json +++ b/public/language/en-GB/topic.json @@ -41,11 +41,6 @@ "flag_manage_history": "Action History", "flag_manage_no_history": "No event history to report", "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", "flag_manage_notes": "Shared Notes", "flag_manage_update": "Update Flag Status", "flag_manage_history_assignee": "Assigned to %1", diff --git a/src/flags.js b/src/flags.js index d9f6aa136f..65ab029e2a 100644 --- a/src/flags.js +++ b/src/flags.js @@ -20,21 +20,30 @@ var Flags = { Flags.get = function (flagId, callback) { async.waterfall([ + // First stage async.apply(async.parallel, { base: async.apply(db.getObject.bind(db), 'flag:' + flagId), history: async.apply(db.getSortedSetRevRange.bind(db), 'flag:' + flagId + ':history', 0, -1), notes: async.apply(db.getSortedSetRevRange.bind(db), 'flag:' + flagId + ':notes', 0, -1) }), function (data, next) { - user.getUserFields(data.base.uid, ['username', 'picture'], function (err, userObj) { + // Second stage + async.parallel({ + userObj: async.apply(user.getUserFields, data.base.uid, ['username', 'picture']), + targetObj: async.apply(Flags.getTarget, data.base.type, data.base.targetId, data.base.uid) + }, function (err, payload) { + // Final object return construction next(err, Object.assign(data.base, { + datetimeISO: new Date(data.base.datetime).toISOString(), + target_readable: data.base.type.charAt(0).toUpperCase() + data.base.type.slice(1) + ' ' + data.base.targetId, + target: payload.targetObj, history: data.history, notes: data.notes, reporter: { - username: userObj.username, - picture: userObj.picture, - 'icon:bgColor': userObj['icon:bgColor'], - 'icon:text': userObj['icon:text'] + username: payload.userObj.username, + picture: payload.userObj.picture, + 'icon:bgColor': payload.userObj['icon:bgColor'], + 'icon:text': payload.userObj['icon:text'] } })); }); @@ -102,6 +111,25 @@ Flags.list = function (filters, callback) { }); }; +Flags.getTarget = function (type, id, uid, callback) { + switch (type) { + case 'post': + async.waterfall([ + async.apply(posts.getPostsByPids, [id], uid), + function (posts, next) { + topics.addPostData(posts, uid, next); + } + ], function (err, posts) { + callback(err, posts[0]); + }); + break; + + case 'user': + user.getUsersData(id, callback); + break; + } +}; + Flags.create = function (type, id, uid, reason, callback) { async.waterfall([ function (next) { From 77809b2b52002d62babde09b10067e93c845a1fe Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 30 Nov 2016 20:26:45 -0500 Subject: [PATCH 007/122] added avatar-xl size --- public/less/generics.less | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/less/generics.less b/public/less/generics.less index 8533dd33b9..5b3c8eff4e 100644 --- a/public/less/generics.less +++ b/public/less/generics.less @@ -107,6 +107,12 @@ } &.avatar-lg { + width: 64px; + height: 64px; + .user-icon-style(64px, 4rem); + } + + &.avatar-xl { width: 128px; height: 128px; .user-icon-style(128px, 7.5rem); From c5c2d27180a5ab39edd87d3fd83a0b86a4ff85a3 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 30 Nov 2016 20:34:06 -0500 Subject: [PATCH 008/122] flag assignees, state, notes WIP, #5232 --- public/language/en-GB/flags.json | 7 +++++- public/language/en-GB/topic.json | 4 ---- src/controllers/mods.js | 7 ++++-- src/flags.js | 40 +++++++++++++++++++++++++++++++- src/user/data.js | 13 +++++++++++ 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index bf22e68df6..d266e2c4db 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -4,10 +4,15 @@ "reporter": "Reporter", "reported-at": "Reported At", "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "notes": "Flag Notes", + "add-note": "Add Note", "state": "State", "state-open": "New/Open", "state-wip": "Work in Progress", "state-resolved": "Resolved", - "state-rejected": "Rejected" + "state-rejected": "Rejected", + "no-assignee": "Not Assigned" } \ No newline at end of file diff --git a/public/language/en-GB/topic.json b/public/language/en-GB/topic.json index 885afe5d62..ce7f35f816 100644 --- a/public/language/en-GB/topic.json +++ b/public/language/en-GB/topic.json @@ -37,12 +37,8 @@ "flag_title": "Flag this post for moderation", "flag_success": "This post has been flagged for moderation.", - "flag_manage_title": "Flagged post in %1", "flag_manage_history": "Action History", "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", "flag_manage_history_assignee": "Assigned to %1", "flag_manage_history_state": "Updated state to %1", "flag_manage_history_notes": "Updated flag notes", diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 7ebb70d888..012ffde3c6 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -41,7 +41,8 @@ modsController.flags.detail = function (req, res, next) { async.parallel({ isAdminOrGlobalMod: async.apply(user.isAdminOrGlobalMod, req.uid), moderatedCids: async.apply(user.getModeratedCids, req.uid), - flagData: async.apply(flags.get, req.params.flagId) + flagData: async.apply(flags.get, req.params.flagId), + assignees: async.apply(user.getAdminsandGlobalModsandModerators) }, function (err, results) { if (err || !results.flagData) { return next(err || new Error('[[error:invalid-data]]')); @@ -49,7 +50,9 @@ modsController.flags.detail = function (req, res, next) { return next(new Error('[[error:no-privileges]]')); } - res.render('flags/detail', results.flagData); + res.render('flags/detail', Object.assign(results.flagData, { + assignees: results.assignees + })); }); }; diff --git a/src/flags.js b/src/flags.js index 65ab029e2a..b88dac6b2f 100644 --- a/src/flags.js +++ b/src/flags.js @@ -10,6 +10,7 @@ var analytics = require('./analytics'); var topics = require('./topics'); var posts = require('./posts'); var utils = require('../public/src/utils'); +var _ = require('underscore'); var Flags = { _defaults: { @@ -24,7 +25,7 @@ Flags.get = function (flagId, callback) { async.apply(async.parallel, { base: async.apply(db.getObject.bind(db), 'flag:' + flagId), history: async.apply(db.getSortedSetRevRange.bind(db), 'flag:' + flagId + ':history', 0, -1), - notes: async.apply(db.getSortedSetRevRange.bind(db), 'flag:' + flagId + ':notes', 0, -1) + notes: async.apply(Flags.getNotes, flagId) }), function (data, next) { // Second stage @@ -130,6 +131,43 @@ Flags.getTarget = function (type, id, uid, callback) { } }; +Flags.getNotes = function (flagId, callback) { + async.waterfall([ + async.apply(db.getSortedSetRevRangeWithScores.bind(db), 'flag:' + flagId + ':notes', 0, -1), + function (notes, next) { + var uids = []; + var noteObj; + notes = notes.map(function (note) { + try { + noteObj = JSON.parse(note.value); + uids.push(noteObj[0]); + return { + uid: noteObj[0], + content: noteObj[1], + datetime: note.score, + datetimeISO: new Date(note.score).toISOString() + }; + } catch (e) { + return next(e); + } + }); + next(null, notes, uids); + }, + function (notes, uids, next) { + user.getUsersData(uids, function (err, users) { + if (err) { + return next(err); + } + + next(null, notes.map(function (note, idx) { + note.user = users[idx]; + return note; + })); + }); + } + ], callback); +}; + Flags.create = function (type, id, uid, reason, callback) { async.waterfall([ function (next) { diff --git a/src/user/data.js b/src/user/data.js index cbaf066ded..1e10704c73 100644 --- a/src/user/data.js +++ b/src/user/data.js @@ -80,6 +80,15 @@ module.exports = function (User) { return callback(null, []); } + // Eliminate duplicates and build ref table + uids = uids.filter(function (uid, index) { + return index === uids.indexOf(uid); + }); + var ref = uids.reduce(function (memo, cur, idx) { + memo[cur] = idx; + return memo; + }, {}); + var keys = uids.map(function (uid) { return 'user:' + uid; }); @@ -89,6 +98,10 @@ module.exports = function (User) { return callback(err); } + users = uids.map(function (uid) { + return users[ref[uid]]; + }); + modifyUserData(users, [], callback); }); }; From e9ff605a2024006bd7c8c451b057981cea58bb2f Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 1 Dec 2016 09:24:49 -0500 Subject: [PATCH 009/122] some more tests for #5232 --- src/flags.js | 4 +++- test/flags.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/flags.js b/src/flags.js index b88dac6b2f..8be774b467 100644 --- a/src/flags.js +++ b/src/flags.js @@ -126,7 +126,9 @@ Flags.getTarget = function (type, id, uid, callback) { break; case 'user': - user.getUsersData(id, callback); + user.getUsersData([id], function (err, users) { + callback(err, users ? users[0] : undefined); + }); break; } }; diff --git a/test/flags.js b/test/flags.js index ed879fba49..c5e69aa973 100644 --- a/test/flags.js +++ b/test/flags.js @@ -101,6 +101,48 @@ describe('Flags', function () { }); }); + describe('.getTarget()', function() { + it('should return a post\'s data if queried with type "post"', function (done) { + Flags.getTarget('post', 1, 1, function (err, data) { + assert.ifError(err); + var compare = { + uid: 1, + pid: 1, + content: 'This is flaggable content' + }; + + for(var key in compare) { + if (compare.hasOwnProperty(key)) { + assert.ok(data[key]); + assert.strictEqual(data[key], compare[key]); + } + } + + done(); + }); + }); + + it('should return a user\'s data if queried with type "user"', function (done) { + Flags.getTarget('user', 1, 1, function (err, data) { + assert.ifError(err); + var compare = { + uid: 1, + username: 'testUser', + email: 'b@c.com' + }; + + for(var key in compare) { + if (compare.hasOwnProperty(key)) { + assert.ok(data[key]); + assert.strictEqual(data[key], compare[key]); + } + } + + done(); + }); + }); + });; + after(function (done) { db.emptydb(done); }); From 888c120e08e7c725c820a302aac5d0e766254114 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 1 Dec 2016 09:42:24 -0500 Subject: [PATCH 010/122] removed some unneeded methods for #5232 --- src/flags.js | 118 --------------------------------------------------- 1 file changed, 118 deletions(-) diff --git a/src/flags.js b/src/flags.js index 8be774b467..99039aa175 100644 --- a/src/flags.js +++ b/src/flags.js @@ -292,11 +292,6 @@ Flags.targetExists = function (type, id, callback) { } }; -/* new signature (type, id, uid, callback) */ -Flags.isFlaggedByUser = function (pid, uid, callback) { - db.isSortedSetMember('pid:' + pid + ':flag:uids', uid, callback); -}; - Flags.dismiss = function (pid, callback) { async.waterfall([ function (next) { @@ -378,119 +373,6 @@ Flags.dismissByUid = function (uid, callback) { }); }; -// This is the old method to get list of flags, supercede by Flags.list(); -// Flags.get = function (set, cid, uid, start, stop, callback) { -// async.waterfall([ -// function (next) { -// if (Array.isArray(set)) { -// db.getSortedSetRevIntersect({sets: set, start: start, stop: -1, aggregate: 'MAX'}, next); -// } else { -// db.getSortedSetRevRange(set, start, -1, next); -// } -// }, -// function (pids, next) { -// if (cid) { -// posts.filterPidsByCid(pids, cid, next); -// } else { -// process.nextTick(next, null, pids); -// } -// }, -// function (pids, next) { -// getFlaggedPostsWithReasons(pids, uid, next); -// }, -// function (posts, next) { -// var count = posts.length; -// var end = stop - start + 1; -// next(null, {posts: posts.slice(0, stop === -1 ? undefined : end), count: count}); -// } -// ], callback); -// }; - -function getFlaggedPostsWithReasons(pids, uid, callback) { - async.waterfall([ - function (next) { - async.parallel({ - uidsReasons: function (next) { - async.map(pids, function (pid, next) { - db.getSortedSetRange('pid:' + pid + ':flag:uid:reason', 0, -1, next); - }, next); - }, - posts: function (next) { - posts.getPostSummaryByPids(pids, uid, {stripTags: false, extraFields: ['flags', 'flag:assignee', 'flag:state', 'flag:notes', 'flag:history']}, next); - } - }, next); - }, - function (results, next) { - async.map(results.uidsReasons, function (uidReasons, next) { - async.map(uidReasons, function (uidReason, next) { - var uid = uidReason.split(':')[0]; - var reason = uidReason.substr(uidReason.indexOf(':') + 1); - user.getUserFields(uid, ['username', 'userslug', 'picture'], function (err, userData) { - next(err, {user: userData, reason: reason}); - }); - }, next); - }, function (err, reasons) { - if (err) { - return callback(err); - } - - results.posts.forEach(function (post, index) { - if (post) { - post.flagReasons = reasons[index]; - } - }); - - next(null, results.posts); - }); - }, - async.apply(Flags.expandFlagHistory), - function (posts, next) { - // Parse out flag data into its own object inside each post hash - async.map(posts, function (postObj, next) { - for(var prop in postObj) { - postObj.flagData = postObj.flagData || {}; - - if (postObj.hasOwnProperty(prop) && prop.startsWith('flag:')) { - postObj.flagData[prop.slice(5)] = postObj[prop]; - - if (prop === 'flag:state') { - switch(postObj[prop]) { - case 'open': - postObj.flagData.labelClass = 'info'; - break; - case 'wip': - postObj.flagData.labelClass = 'warning'; - break; - case 'resolved': - postObj.flagData.labelClass = 'success'; - break; - case 'rejected': - postObj.flagData.labelClass = 'danger'; - break; - } - } - - delete postObj[prop]; - } - } - - if (postObj.flagData.assignee) { - user.getUserFields(parseInt(postObj.flagData.assignee, 10), ['username', 'picture'], function (err, userData) { - if (err) { - return next(err); - } - - postObj.flagData.assigneeUser = userData; - next(null, postObj); - }); - } else { - setImmediate(next.bind(null, null, postObj)); - } - }, next); - } - ], callback); -} - // New method signature (type, id, flagObj, callback) and name (.update()) // uid used in history string, which should be rewritten too. Flags.update = function (uid, pid, flagObj, callback) { From 709a7ff7f00df8fd70c5308337f9bd774d05f759 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 1 Dec 2016 11:04:37 -0500 Subject: [PATCH 011/122] fixed issue with getUsersData not actually returning the same number of elements as was passed-in --- src/user/data.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/user/data.js b/src/user/data.js index 1e10704c73..2e5bfb2218 100644 --- a/src/user/data.js +++ b/src/user/data.js @@ -81,15 +81,15 @@ module.exports = function (User) { } // Eliminate duplicates and build ref table - uids = uids.filter(function (uid, index) { + var uniqueUids = uids.filter(function (uid, index) { return index === uids.indexOf(uid); }); - var ref = uids.reduce(function (memo, cur, idx) { + var ref = uniqueUids.reduce(function (memo, cur, idx) { memo[cur] = idx; return memo; }, {}); - var keys = uids.map(function (uid) { + var keys = uniqueUids.map(function (uid) { return 'user:' + uid; }); From d9d60c20bd743abd0a027efef474916278e3d793 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 1 Dec 2016 11:42:06 -0500 Subject: [PATCH 012/122] flag updating and note appending, #5232 --- public/language/en-GB/flags.json | 4 +- public/src/client/flags/detail.js | 60 +++++++++++ public/src/client/topic/flag.js | 2 +- src/flags.js | 166 +++++++--------------------- src/socket.io/flags.js | 167 ++++++++++++++++++++++++++++ src/socket.io/index.js | 6 +- src/socket.io/posts.js | 1 - src/socket.io/posts/flag.js | 173 ------------------------------ 8 files changed, 275 insertions(+), 304 deletions(-) create mode 100644 public/src/client/flags/detail.js create mode 100644 src/socket.io/flags.js delete mode 100644 src/socket.io/posts/flag.js diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index d266e2c4db..0c1f32b88e 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -14,5 +14,7 @@ "state-wip": "Work in Progress", "state-resolved": "Resolved", "state-rejected": "Rejected", - "no-assignee": "Not Assigned" + "no-assignee": "Not Assigned", + "updated": "Flag Details Updated", + "note-added": "Note Added" } \ No newline at end of file diff --git a/public/src/client/flags/detail.js b/public/src/client/flags/detail.js new file mode 100644 index 0000000000..d23a1941b5 --- /dev/null +++ b/public/src/client/flags/detail.js @@ -0,0 +1,60 @@ +'use strict'; + +/* globals define */ + +define('forum/flags/detail', ['components'], function (components) { + var Flags = {}; + + Flags.init = function () { + // Update attributes + $('#state').val(ajaxify.data.state).removeAttr('disabled'); + $('#assignee').val(ajaxify.data.assignee).removeAttr('disabled'); + + $('[data-action]').on('click', function () { + var action = this.getAttribute('data-action'); + + switch (action) { + case 'update': + socket.emit('flags.update', { + flagId: ajaxify.data.flagId, + data: $('#attributes').serializeArray() + }, function (err) { + if (err) { + return app.alertError(err.message); + } else { + app.alertSuccess('[[flags:updated]]'); + } + }); + break; + + case 'appendNote': + socket.emit('flags.appendNote', { + flagId: ajaxify.data.flagId, + note: document.getElementById('note').value + }, function (err, notes) { + if (err) { + return app.alertError(err.message); + } else { + app.alertSuccess('[[flags:note-added]]'); + Flags.reloadNotes(notes); + } + }); + break; + } + }); + }; + + Flags.reloadNotes = function (notes) { + templates.parse('flags/detail', 'notes', { + notes: notes + }, function (html) { + var wrapperEl = components.get('flag/notes'); + wrapperEl.empty(); + wrapperEl.html(html); + wrapperEl.find('span.timeago').timeago(); + document.getElementById('note').value = ''; + }); + }; + + return Flags; +}); diff --git a/public/src/client/topic/flag.js b/public/src/client/topic/flag.js index 78b1dd5d2a..046585ae68 100644 --- a/public/src/client/topic/flag.js +++ b/public/src/client/topic/flag.js @@ -48,7 +48,7 @@ define('forum/topic/flag', [], function () { if (!pid || !reason) { return; } - socket.emit('posts.flag', {pid: pid, reason: reason}, function (err) { + socket.emit('flags.create', {pid: pid, reason: reason}, function (err) { if (err) { return app.alertError(err.message); } diff --git a/src/flags.js b/src/flags.js index 99039aa175..323a2a1e07 100644 --- a/src/flags.js +++ b/src/flags.js @@ -373,138 +373,52 @@ Flags.dismissByUid = function (uid, callback) { }); }; -// New method signature (type, id, flagObj, callback) and name (.update()) -// uid used in history string, which should be rewritten too. -Flags.update = function (uid, pid, flagObj, callback) { +Flags.update = function (flagId, uid, changeset, callback) { // Retrieve existing flag data to compare for history-saving purposes - var changes = []; - var changeset = {}; - var prop; + var fields = ['state', 'assignee']; - posts.getPostData(pid, function (err, postData) { - if (err) { - return callback(err); - } - - // Track new additions - for(prop in flagObj) { - if (flagObj.hasOwnProperty(prop) && !postData.hasOwnProperty('flag:' + prop) && flagObj[prop].length) { - changes.push(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)); - } - } - - changeset = changes.reduce(function (memo, prop) { - memo['flag:' + prop] = flagObj[prop]; - return memo; - }, {}); - - // Append changes to history string - if (changes.length) { - try { - var history = JSON.parse(postData['flag:history'] || '[]'); - - changes.forEach(function (property) { - switch(property) { - case 'assignee': // intentional fall-through - case 'state': - history.unshift({ - uid: uid, - type: property, - value: flagObj[property], - timestamp: Date.now() - }); - break; - - case 'notes': - history.unshift({ - uid: uid, - type: property, - timestamp: Date.now() - }); - } - }); - - changeset['flag:history'] = JSON.stringify(history); - } catch (e) { - winston.warn('[flags/update] Unable to deserialise post flag history, likely malformed data'); - } - } - - // Save flag data into post hash - if (changes.length) { - posts.setPostFields(pid, changeset, callback); - } else { - setImmediate(callback); - } - }); -}; - -// To be rewritten and deprecated -Flags.expandFlagHistory = function (posts, callback) { - // Expand flag history - async.map(posts, function (post, next) { - var history; - try { - history = JSON.parse(post['flag:history'] || '[]'); - } catch (e) { - winston.warn('[flags/get] Unable to deserialise post flag history, likely malformed data'); - return callback(e); - } - - async.map(history, function (event, next) { - event.timestampISO = new Date(event.timestamp).toISOString(); - - async.parallel([ - function (next) { - user.getUserFields(event.uid, ['username', 'picture'], function (err, userData) { - if (err) { - return next(err); - } - - event.user = userData; - next(); - }); - }, - function (next) { - if (event.type === 'assignee') { - user.getUserField(parseInt(event.value, 10), 'username', function (err, username) { - if (err) { - return next(err); - } - - event.label = username || 'Unknown user'; - next(null); - }); - } else if (event.type === 'state') { - event.label = '[[topic:flag_manage_state_' + event.value + ']]'; - setImmediate(next); - } else { - setImmediate(next); + async.waterfall([ + async.apply(db.getObjectFields.bind(db), 'flag:' + flagId, fields), + function (current, next) { + for(var prop in changeset) { + if (changeset.hasOwnProperty(prop)) { + if (current[prop] === changeset[prop]) { + delete changeset[prop]; } } - ], function (err) { - next(err, event); - }); - }, function (err, history) { - if (err) { - return next(err); } - post['flag:history'] = history; - next(null, post); - }); - }, callback); + if (!Object.keys(changeset).length) { + // No changes + return next(); + } + + async.parallel([ + // Save new object to db (upsert) + async.apply(db.setObject, 'flag:' + flagId, changeset), + // Append history + async.apply(Flags.appendHistory, flagId, uid, Object.keys(changeset)) + ], next); + } + ], callback); +}; + +Flags.appendHistory = function (flagId, uid, changeset, callback) { + return callback(); +}; + +Flags.appendNote = function (flagId, uid, note, callback) { + var payload; + try { + payload = JSON.stringify([uid, note]); + } catch (e) { + return callback(e); + } + + async.waterfall([ + async.apply(db.sortedSetAdd, 'flag:' + flagId + ':notes', Date.now(), payload), + async.apply(Flags.getNotes, flagId) + ], callback); }; module.exports = Flags; \ No newline at end of file diff --git a/src/socket.io/flags.js b/src/socket.io/flags.js new file mode 100644 index 0000000000..28db7551a6 --- /dev/null +++ b/src/socket.io/flags.js @@ -0,0 +1,167 @@ +'use strict'; + +var async = require('async'); +var S = require('string'); + +var user = require('../user'); +var groups = require('../groups'); +var posts = require('../posts'); +var topics = require('../topics'); +var privileges = require('../privileges'); +var notifications = require('../notifications'); +var plugins = require('../plugins'); +var meta = require('../meta'); +var utils = require('../../public/src/utils'); +var flags = require('../flags'); + +var SocketFlags = {}; + +SocketFlags.create = function (socket, data, callback) { + if (!socket.uid) { + return callback(new Error('[[error:not-logged-in]]')); + } + + if (!data || !data.pid || !data.reason) { + return callback(new Error('[[error:invalid-data]]')); + } + + var flaggingUser = {}; + var post; + + async.waterfall([ + function (next) { + posts.getPostFields(data.pid, ['pid', 'tid', 'uid', 'content', 'deleted'], next); + }, + function (postData, next) { + if (parseInt(postData.deleted, 10) === 1) { + return next(new Error('[[error:post-deleted]]')); + } + + post = postData; + topics.getTopicFields(post.tid, ['title', 'cid'], next); + }, + function (topicData, next) { + post.topic = topicData; + + async.parallel({ + isAdminOrMod: function (next) { + privileges.categories.isAdminOrMod(post.topic.cid, socket.uid, next); + }, + userData: function (next) { + user.getUserFields(socket.uid, ['username', 'reputation', 'banned'], next); + } + }, next); + }, + function (user, next) { + var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1; + if (!user.isAdminOrMod && parseInt(user.userData.reputation, 10) < minimumReputation) { + return next(new Error('[[error:not-enough-reputation-to-flag]]')); + } + + if (parseInt(user.banned, 10) === 1) { + return next(new Error('[[error:user-banned]]')); + } + + flaggingUser = user.userData; + flaggingUser.uid = socket.uid; + + flags.create('post', post.pid, socket.uid, data.reason, next); + }, + function (next) { + async.parallel({ + post: function (next) { + posts.parsePost(post, next); + }, + admins: function (next) { + groups.getMembers('administrators', 0, -1, next); + }, + globalMods: function (next) { + groups.getMembers('Global Moderators', 0, -1, next); + }, + moderators: function (next) { + groups.getMembers('cid:' + post.topic.cid + ':privileges:mods', 0, -1, next); + } + }, next); + }, + function (results, next) { + var title = S(post.topic.title).decodeHTMLEntities().s; + var titleEscaped = title.replace(/%/g, '%').replace(/,/g, ','); + + notifications.create({ + bodyShort: '[[notifications:user_flagged_post_in, ' + flaggingUser.username + ', ' + titleEscaped + ']]', + bodyLong: post.content, + pid: data.pid, + path: '/post/' + data.pid, + nid: 'post_flag:' + data.pid + ':uid:' + socket.uid, + from: socket.uid, + mergeId: 'notifications:user_flagged_post_in|' + data.pid, + topicTitle: post.topic.title + }, function (err, notification) { + if (err || !notification) { + return next(err); + } + + plugins.fireHook('action:post.flag', {post: post, reason: data.reason, flaggingUser: flaggingUser}); + notifications.push(notification, results.admins.concat(results.moderators).concat(results.globalMods), next); + }); + } + ], callback); +}; + +SocketFlags.update = function (socket, data, callback) { + if (!data || !(data.flagId && data.data)) { + return callback(new Error('[[error:invalid-data]]')); + } + + var payload = {}; + + async.waterfall([ + function (next) { + async.parallel([ + async.apply(user.isAdminOrGlobalMod, socket.uid), + async.apply(user.isModeratorOfAnyCategory, socket.uid) + ], function (err, results) { + next(err, results[0] || results[1]); + }); + }, + function (allowed, next) { + if (!allowed) { + 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); + + flags.update(data.flagId, socket.uid, payload, next); + } + ], callback); +}; + +SocketFlags.appendNote = function (socket, data, callback) { + if (!data || !(data.flagId && data.note)) { + return callback(new Error('[[error:invalid-data]]')); + } + + async.waterfall([ + function (next) { + async.parallel([ + async.apply(user.isAdminOrGlobalMod, socket.uid), + async.apply(user.isModeratorOfAnyCategory, socket.uid) + ], function (err, results) { + next(err, results[0] || results[1]); + }); + }, + function (allowed, next) { + if (!allowed) { + return next(new Error('[[no-privileges]]')); + } + + flags.appendNote(data.flagId, socket.uid, data.note, next); + } + ], callback); +}; + +module.exports = SocketFlags; diff --git a/src/socket.io/index.js b/src/socket.io/index.js index 38e73c1cc1..43157f19ad 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -123,8 +123,10 @@ var ratelimit = require('../middleware/ratelimit'); } function requireModules() { - var modules = ['admin', 'categories', 'groups', 'meta', 'modules', - 'notifications', 'plugins', 'posts', 'topics', 'user', 'blacklist' + var modules = [ + 'admin', 'categories', 'groups', 'meta', 'modules', + 'notifications', 'plugins', 'posts', 'topics', 'user', + 'blacklist', 'flags' ]; modules.forEach(function (module) { diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index fe729a5c11..b5309dd3cf 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -20,7 +20,6 @@ require('./posts/move')(SocketPosts); require('./posts/votes')(SocketPosts); require('./posts/bookmarks')(SocketPosts); require('./posts/tools')(SocketPosts); -require('./posts/flag')(SocketPosts); SocketPosts.reply = function (socket, data, callback) { if (!data || !data.tid || !data.content) { diff --git a/src/socket.io/posts/flag.js b/src/socket.io/posts/flag.js deleted file mode 100644 index 88b47058d1..0000000000 --- a/src/socket.io/posts/flag.js +++ /dev/null @@ -1,173 +0,0 @@ -'use strict'; - -var async = require('async'); -var S = require('string'); - -var user = require('../../user'); -var groups = require('../../groups'); -var posts = require('../../posts'); -var topics = require('../../topics'); -var privileges = require('../../privileges'); -var notifications = require('../../notifications'); -var plugins = require('../../plugins'); -var meta = require('../../meta'); -var utils = require('../../../public/src/utils'); -var flags = require('../../flags'); - -module.exports = function (SocketPosts) { - - SocketPosts.flag = function (socket, data, callback) { - if (!socket.uid) { - return callback(new Error('[[error:not-logged-in]]')); - } - - if (!data || !data.pid || !data.reason) { - return callback(new Error('[[error:invalid-data]]')); - } - - var flaggingUser = {}; - var post; - - async.waterfall([ - function (next) { - posts.getPostFields(data.pid, ['pid', 'tid', 'uid', 'content', 'deleted'], next); - }, - function (postData, next) { - if (parseInt(postData.deleted, 10) === 1) { - return next(new Error('[[error:post-deleted]]')); - } - - post = postData; - topics.getTopicFields(post.tid, ['title', 'cid'], next); - }, - function (topicData, next) { - post.topic = topicData; - - async.parallel({ - isAdminOrMod: function (next) { - privileges.categories.isAdminOrMod(post.topic.cid, socket.uid, next); - }, - userData: function (next) { - user.getUserFields(socket.uid, ['username', 'reputation', 'banned'], next); - } - }, next); - }, - function (user, next) { - var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1; - if (!user.isAdminOrMod && parseInt(user.userData.reputation, 10) < minimumReputation) { - return next(new Error('[[error:not-enough-reputation-to-flag]]')); - } - - if (parseInt(user.banned, 10) === 1) { - return next(new Error('[[error:user-banned]]')); - } - - flaggingUser = user.userData; - flaggingUser.uid = socket.uid; - - flags.create('post', post.pid, socket.uid, data.reason, next); - }, - function (next) { - async.parallel({ - post: function (next) { - posts.parsePost(post, next); - }, - admins: function (next) { - groups.getMembers('administrators', 0, -1, next); - }, - globalMods: function (next) { - groups.getMembers('Global Moderators', 0, -1, next); - }, - moderators: function (next) { - groups.getMembers('cid:' + post.topic.cid + ':privileges:mods', 0, -1, next); - } - }, next); - }, - function (results, next) { - var title = S(post.topic.title).decodeHTMLEntities().s; - var titleEscaped = title.replace(/%/g, '%').replace(/,/g, ','); - - notifications.create({ - bodyShort: '[[notifications:user_flagged_post_in, ' + flaggingUser.username + ', ' + titleEscaped + ']]', - bodyLong: post.content, - pid: data.pid, - path: '/post/' + data.pid, - nid: 'post_flag:' + data.pid + ':uid:' + socket.uid, - from: socket.uid, - mergeId: 'notifications:user_flagged_post_in|' + data.pid, - topicTitle: post.topic.title - }, function (err, notification) { - if (err || !notification) { - return next(err); - } - - plugins.fireHook('action:post.flag', {post: post, reason: data.reason, flaggingUser: flaggingUser}); - notifications.push(notification, results.admins.concat(results.moderators).concat(results.globalMods), next); - }); - } - ], callback); - }; - - SocketPosts.dismissFlag = function (socket, pid, callback) { - if (!pid || !socket.uid) { - return callback(new Error('[[error:invalid-data]]')); - } - async.waterfall([ - function (next) { - user.isAdminOrGlobalMod(socket.uid, next); - }, - function (isAdminOrGlobalModerator, next) { - if (!isAdminOrGlobalModerator) { - return next(new Error('[[no-privileges]]')); - } - flags.dismiss(pid, next); - } - ], callback); - }; - - SocketPosts.dismissAllFlags = function (socket, data, callback) { - async.waterfall([ - function (next) { - user.isAdminOrGlobalMod(socket.uid, next); - }, - function (isAdminOrGlobalModerator, next) { - if (!isAdminOrGlobalModerator) { - return next(new Error('[[no-privileges]]')); - } - flags.dismissAll(next); - } - ], callback); - }; - - SocketPosts.updateFlag = function (socket, data, callback) { - if (!data || !(data.pid && data.data)) { - return callback(new Error('[[error:invalid-data]]')); - } - - var payload = {}; - - async.waterfall([ - function (next) { - async.parallel([ - async.apply(user.isAdminOrGlobalMod, socket.uid), - async.apply(user.isModeratorOfAnyCategory, socket.uid) - ], function (err, results) { - next(err, results[0] || results[1]); - }); - }, - function (allowed, next) { - if (!allowed) { - 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); - - flags.update(socket.uid, data.pid, payload, next); - } - ], callback); - }; -}; From f1d144f15e5461769e266cd69a116148df2eb021 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 1 Dec 2016 16:22:10 -0500 Subject: [PATCH 013/122] history appending, finished up notes, #5232 --- public/language/en-GB/flags.json | 3 ++ public/src/client/flags/detail.js | 23 +++++++++--- src/flags.js | 58 ++++++++++++++++++++++++++++--- src/socket.io/flags.js | 9 ++++- src/user/data.js | 17 +++++++-- 5 files changed, 98 insertions(+), 12 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index 0c1f32b88e..7b9193680f 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -6,8 +6,11 @@ "no-flags": "Hooray! No flags found.", "assignee": "Assignee", "update": "Update", + "updated": "Updated", "notes": "Flag Notes", "add-note": "Add Note", + "history": "Flag History", + "back": "Back to Flags List", "state": "State", "state-open": "New/Open", diff --git a/public/src/client/flags/detail.js b/public/src/client/flags/detail.js index d23a1941b5..aef21ec925 100644 --- a/public/src/client/flags/detail.js +++ b/public/src/client/flags/detail.js @@ -2,7 +2,7 @@ /* globals define */ -define('forum/flags/detail', ['components'], function (components) { +define('forum/flags/detail', ['components', 'translator'], function (components, translator) { var Flags = {}; Flags.init = function () { @@ -18,11 +18,12 @@ define('forum/flags/detail', ['components'], function (components) { socket.emit('flags.update', { flagId: ajaxify.data.flagId, data: $('#attributes').serializeArray() - }, function (err) { + }, function (err, history) { if (err) { return app.alertError(err.message); } else { app.alertSuccess('[[flags:updated]]'); + Flags.reloadHistory(history); } }); break; @@ -31,12 +32,13 @@ define('forum/flags/detail', ['components'], function (components) { socket.emit('flags.appendNote', { flagId: ajaxify.data.flagId, note: document.getElementById('note').value - }, function (err, notes) { + }, function (err, payload) { if (err) { return app.alertError(err.message); } else { app.alertSuccess('[[flags:note-added]]'); - Flags.reloadNotes(notes); + Flags.reloadNotes(payload.notes); + Flags.reloadHistory(payload.history); } }); break; @@ -56,5 +58,18 @@ define('forum/flags/detail', ['components'], function (components) { }); }; + Flags.reloadHistory = function (history) { + templates.parse('flags/detail', 'history', { + history: history + }, function (html) { + translator.translate(html, function (translated) { + var wrapperEl = components.get('flag/history'); + wrapperEl.empty(); + wrapperEl.html(translated); + wrapperEl.find('span.timeago').timeago(); + }); + }); + }; + return Flags; }); diff --git a/src/flags.js b/src/flags.js index 323a2a1e07..3dc1e51f32 100644 --- a/src/flags.js +++ b/src/flags.js @@ -24,7 +24,7 @@ Flags.get = function (flagId, callback) { // First stage async.apply(async.parallel, { base: async.apply(db.getObject.bind(db), 'flag:' + flagId), - history: async.apply(db.getSortedSetRevRange.bind(db), 'flag:' + flagId + ':history', 0, -1), + history: async.apply(Flags.getHistory, flagId), notes: async.apply(Flags.getNotes, flagId) }), function (data, next) { @@ -156,7 +156,7 @@ Flags.getNotes = function (flagId, callback) { next(null, notes, uids); }, function (notes, uids, next) { - user.getUsersData(uids, function (err, users) { + user.getUsersFields(uids, ['username', 'userslug', 'picture'], function (err, users) { if (err) { return next(err); } @@ -398,13 +398,61 @@ Flags.update = function (flagId, uid, changeset, callback) { async.apply(db.setObject, 'flag:' + flagId, changeset), // Append history async.apply(Flags.appendHistory, flagId, uid, Object.keys(changeset)) - ], next); + ], function (err, data) { + return next(err); + }); } ], callback); }; +Flags.getHistory = function (flagId, callback) { + var history; + var uids = []; + async.waterfall([ + async.apply(db.getSortedSetRevRangeWithScores.bind(db), 'flag:' + flagId + ':history', 0, -1), + function (_history, next) { + history = _history.map(function (entry) { + try { + entry.value = JSON.parse(entry.value); + } catch (e) { + return callback(e); + } + + uids.push(entry.value[0]); + + return { + uid: entry.value[0], + fields: entry.value[1], + datetime: entry.score, + datetimeISO: new Date(entry.score).toISOString() + }; + }); + + user.getUsersFields(uids, ['username', 'userslug', 'picture'], next); + } + ], function (err, users) { + if (err) { + return callback(err); + } + + history = history.map(function (event, idx) { + event.user = users[idx]; + return event; + }); + + callback(null, history); + }); +}; + Flags.appendHistory = function (flagId, uid, changeset, callback) { - return callback(); + var payload; + try { + payload = JSON.stringify([uid, changeset, Date.now()]); + } catch (e) { + return callback(e); + } + + db.sortedSetAdd('flag:' + flagId + ':history', Date.now(), payload, callback); }; Flags.appendNote = function (flagId, uid, note, callback) { @@ -417,7 +465,7 @@ Flags.appendNote = function (flagId, uid, note, callback) { async.waterfall([ async.apply(db.sortedSetAdd, 'flag:' + flagId + ':notes', Date.now(), payload), - async.apply(Flags.getNotes, flagId) + async.apply(Flags.appendHistory, flagId, uid, ['notes']) ], callback); }; diff --git a/src/socket.io/flags.js b/src/socket.io/flags.js index 28db7551a6..8b66dd094c 100644 --- a/src/socket.io/flags.js +++ b/src/socket.io/flags.js @@ -136,7 +136,8 @@ SocketFlags.update = function (socket, data, callback) { }, payload); flags.update(data.flagId, socket.uid, payload, next); - } + }, + async.apply(flags.getHistory, data.flagId) ], callback); }; @@ -160,6 +161,12 @@ SocketFlags.appendNote = function (socket, data, callback) { } flags.appendNote(data.flagId, socket.uid, data.note, next); + }, + function (next) { + async.parallel({ + "notes": async.apply(flags.getNotes, data.flagId), + "history": async.apply(flags.getHistory, data.flagId) + }, next); } ], callback); }; diff --git a/src/user/data.js b/src/user/data.js index 2e5bfb2218..5716208ae5 100644 --- a/src/user/data.js +++ b/src/user/data.js @@ -34,11 +34,20 @@ module.exports = function (User) { } } - if (!Array.isArray(uids) || !uids.length) { + // Eliminate duplicates and build ref table + var uniqueUids = uids.filter(function (uid, index) { + return index === uids.indexOf(uid); + }); + var ref = uniqueUids.reduce(function (memo, cur, idx) { + memo[cur] = idx; + return memo; + }, {}); + + if (!Array.isArray(uniqueUids) || !uniqueUids.length) { return callback(null, []); } - var keys = uids.map(function (uid) { + var keys = uniqueUids.map(function (uid) { return 'user:' + uid; }); @@ -60,6 +69,10 @@ module.exports = function (User) { return callback(err); } + users = uids.map(function (uid) { + return users[ref[uid]]; + }); + modifyUserData(users, fieldsToRemove, callback); }); }; From 22eeabc5c73050385eb45254eb2b2099a9781d98 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 1 Dec 2016 16:36:30 -0500 Subject: [PATCH 014/122] new strings for empty notes or history, #5232 --- public/language/en-GB/flags.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index 7b9193680f..cb1f513deb 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -7,10 +7,14 @@ "assignee": "Assignee", "update": "Update", "updated": "Updated", + "notes": "Flag Notes", "add-note": "Add Note", + "no-notes": "No shared notes.", + "history": "Flag History", "back": "Back to Flags List", + "no-history": "No flag history.", "state": "State", "state-open": "New/Open", From 839a0efc0a056905e7a6b0a94a21af24e33315c2 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 2 Dec 2016 09:49:25 -0500 Subject: [PATCH 015/122] one more language string for #5232 --- public/language/en-GB/flags.json | 1 + 1 file changed, 1 insertion(+) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index cb1f513deb..5f989cd4d0 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -3,6 +3,7 @@ "state": "State", "reporter": "Reporter", "reported-at": "Reported At", + "description": "Description", "no-flags": "Hooray! No flags found.", "assignee": "Assignee", "update": "Update", From 20fa8ebf76bb702fc8277a577f0e239185dfca20 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 2 Dec 2016 11:24:12 -0500 Subject: [PATCH 016/122] simplified flags.get a tad --- src/flags.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/flags.js b/src/flags.js index 3dc1e51f32..6022750f73 100644 --- a/src/flags.js +++ b/src/flags.js @@ -30,7 +30,7 @@ Flags.get = function (flagId, callback) { function (data, next) { // Second stage async.parallel({ - userObj: async.apply(user.getUserFields, data.base.uid, ['username', 'picture']), + userObj: async.apply(user.getUserFields, data.base.uid, ['username', 'userslug', 'picture']), targetObj: async.apply(Flags.getTarget, data.base.type, data.base.targetId, data.base.uid) }, function (err, payload) { // Final object return construction @@ -40,12 +40,7 @@ Flags.get = function (flagId, callback) { target: payload.targetObj, history: data.history, notes: data.notes, - reporter: { - username: payload.userObj.username, - picture: payload.userObj.picture, - 'icon:bgColor': payload.userObj['icon:bgColor'], - 'icon:text': payload.userObj['icon:text'] - } + reporter: payload.userObj })); }); } From 0724bee6c65b5e2e0dcb71628f0ce573da62aaf7 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 2 Dec 2016 12:10:19 -0500 Subject: [PATCH 017/122] removed deprecated dismiss methods --- src/flags.js | 81 ---------------------------------------------------- 1 file changed, 81 deletions(-) diff --git a/src/flags.js b/src/flags.js index 6022750f73..54f6f0bd30 100644 --- a/src/flags.js +++ b/src/flags.js @@ -287,87 +287,6 @@ Flags.targetExists = function (type, id, callback) { } }; -Flags.dismiss = function (pid, callback) { - async.waterfall([ - function (next) { - db.getObjectFields('post:' + pid, ['pid', 'uid', 'flags'], next); - }, - function (postData, next) { - if (!postData.pid) { - return callback(); - } - async.parallel([ - function (next) { - if (parseInt(postData.uid, 10)) { - if (parseInt(postData.flags, 10) > 0) { - async.parallel([ - async.apply(db.sortedSetIncrBy, 'users:flags', -postData.flags, postData.uid), - async.apply(db.incrObjectFieldBy, 'user:' + postData.uid, 'flags', -postData.flags) - ], next); - } else { - next(); - } - } else { - next(); - } - }, - function (next) { - db.sortedSetsRemove([ - 'posts:flagged', - 'posts:flags:count', - 'uid:' + postData.uid + ':flag:pids' - ], pid, next); - }, - function (next) { - async.series([ - function (next) { - db.getSortedSetRange('pid:' + pid + ':flag:uids', 0, -1, function (err, uids) { - if (err) { - return next(err); - } - - async.each(uids, function (uid, next) { - var nid = 'post_flag:' + pid + ':uid:' + uid; - async.parallel([ - async.apply(db.delete, 'notifications:' + nid), - async.apply(db.sortedSetRemove, 'notifications', 'post_flag:' + pid + ':uid:' + uid) - ], next); - }, next); - }); - }, - async.apply(db.delete, 'pid:' + pid + ':flag:uids') - ], next); - }, - async.apply(db.deleteObjectField, 'post:' + pid, 'flags'), - async.apply(db.delete, 'pid:' + pid + ':flag:uid:reason'), - async.apply(db.deleteObjectFields, 'post:' + pid, ['flag:state', 'flag:assignee', 'flag:notes', 'flag:history']) - ], next); - }, - function (results, next) { - db.sortedSetsRemoveRangeByScore(['users:flags'], '-inf', 0, next); - } - ], callback); -}; - -// Pretty sure we don't need this method... -Flags.dismissAll = function (callback) { - db.getSortedSetRange('posts:flagged', 0, -1, function (err, pids) { - if (err) { - return callback(err); - } - async.eachSeries(pids, Flags.dismiss, callback); - }); -}; - -Flags.dismissByUid = function (uid, callback) { - db.getSortedSetRange('uid:' + uid + ':flag:pids', 0, -1, function (err, pids) { - if (err) { - return callback(err); - } - async.eachSeries(pids, Flags.dismiss, callback); - }); -}; - Flags.update = function (flagId, uid, changeset, callback) { // Retrieve existing flag data to compare for history-saving purposes var fields = ['state', 'assignee']; From 169defd19476648c769a56fe2bbc6b062597f99b Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 2 Dec 2016 12:34:58 -0500 Subject: [PATCH 018/122] #5232, update flag history to save new value --- src/flags.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/flags.js b/src/flags.js index 54f6f0bd30..893bba4442 100644 --- a/src/flags.js +++ b/src/flags.js @@ -290,14 +290,18 @@ Flags.targetExists = function (type, id, callback) { Flags.update = function (flagId, uid, changeset, callback) { // Retrieve existing flag data to compare for history-saving purposes var fields = ['state', 'assignee']; + var history = []; async.waterfall([ async.apply(db.getObjectFields.bind(db), 'flag:' + flagId, fields), function (current, next) { - for(var prop in changeset) { + for (var prop in changeset) { if (changeset.hasOwnProperty(prop)) { if (current[prop] === changeset[prop]) { delete changeset[prop]; + } else { + // Append to history payload + history.push(prop + ':' + changeset[prop]); } } } @@ -311,7 +315,7 @@ Flags.update = function (flagId, uid, changeset, callback) { // Save new object to db (upsert) async.apply(db.setObject, 'flag:' + flagId, changeset), // Append history - async.apply(Flags.appendHistory, flagId, uid, Object.keys(changeset)) + async.apply(Flags.appendHistory, flagId, uid, history) ], function (err, data) { return next(err); }); @@ -334,9 +338,18 @@ Flags.getHistory = function (flagId, callback) { uids.push(entry.value[0]); + // Deserialise field object + var fields = entry.value[1].map(function (field) { + field = field.toString().split(':'); + return { + "attribute": field[0], + "value": field[1] === undefined ? null : field[1] + }; + }); + return { uid: entry.value[0], - fields: entry.value[1], + fields: fields, datetime: entry.score, datetimeISO: new Date(entry.score).toISOString() }; @@ -349,6 +362,7 @@ Flags.getHistory = function (flagId, callback) { return callback(err); } + // Append user data to each history event history = history.map(function (event, idx) { event.user = users[idx]; return event; From 9129597811ab10f2d5d8775ed1f8bc9bd1e7dae8 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 2 Dec 2016 12:51:39 -0500 Subject: [PATCH 019/122] #5232 some tweaks to flag history saving --- public/language/en-GB/flags.json | 1 - src/flags.js | 12 +++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index 5f989cd4d0..0cdc3fbfb9 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -23,6 +23,5 @@ "state-resolved": "Resolved", "state-rejected": "Rejected", "no-assignee": "Not Assigned", - "updated": "Flag Details Updated", "note-added": "Note Added" } \ No newline at end of file diff --git a/src/flags.js b/src/flags.js index 893bba4442..58b230af06 100644 --- a/src/flags.js +++ b/src/flags.js @@ -341,9 +341,19 @@ Flags.getHistory = function (flagId, callback) { // Deserialise field object var fields = entry.value[1].map(function (field) { field = field.toString().split(':'); + + switch (field[0]) { + case 'state': + field[1] = field[1] === undefined ? null : '[[flags:state-' + field[1] + ']]'; + break; + + default: + field[1] = field[1] === undefined ? null : field[1]; + break; + } return { "attribute": field[0], - "value": field[1] === undefined ? null : field[1] + "value": field[1] }; }); From 753d4b0275e3927560d9f7c2c8217f6273d4715e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 2 Dec 2016 15:28:28 -0500 Subject: [PATCH 020/122] wrapped up basic functionality of list and detail for flags, filter support. #5232 --- public/language/en-GB/flags.json | 7 ++ public/language/en-GB/topic.json | 6 -- public/src/admin/manage/flags.js | 172 ------------------------------ public/src/client/flags/detail.js | 4 +- public/src/client/flags/list.js | 28 +++++ src/controllers/admin.js | 1 - src/controllers/admin/flags.js | 104 ------------------ src/controllers/mods.js | 12 ++- src/flags.js | 31 +++++- src/routes/admin.js | 1 - src/socket.io/flags.js | 2 +- 11 files changed, 78 insertions(+), 290 deletions(-) delete mode 100644 public/src/admin/manage/flags.js create mode 100644 public/src/client/flags/list.js delete mode 100644 src/controllers/admin/flags.js diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index 0cdc3fbfb9..cdc3c4069e 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -9,6 +9,13 @@ "update": "Update", "updated": "Updated", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "apply-filters": "Apply Filters", + "notes": "Flag Notes", "add-note": "Add Note", "no-notes": "No shared notes.", diff --git a/public/language/en-GB/topic.json b/public/language/en-GB/topic.json index ce7f35f816..4ae208076e 100644 --- a/public/language/en-GB/topic.json +++ b/public/language/en-GB/topic.json @@ -37,12 +37,6 @@ "flag_title": "Flag this post for moderation", "flag_success": "This post has been flagged for moderation.", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "This topic has been deleted. Only users with topic management privileges can see it.", diff --git a/public/src/admin/manage/flags.js b/public/src/admin/manage/flags.js deleted file mode 100644 index fb8b32d602..0000000000 --- a/public/src/admin/manage/flags.js +++ /dev/null @@ -1,172 +0,0 @@ -"use strict"; -/*global define, socket, app, utils, bootbox, ajaxify*/ - -define('admin/manage/flags', [ - 'autocomplete', - 'Chart', - 'components' -], function (autocomplete, Chart, components) { - - var Flags = {}; - - Flags.init = function () { - $('.post-container .content img:not(.not-responsive)').addClass('img-responsive'); - - autocomplete.user($('#byUsername')); - - handleDismiss(); - handleDismissAll(); - handleDelete(); - handleGraphs(); - - updateFlagDetails(ajaxify.data.posts); - - components.get('posts/flags').on('click', '[component="posts/flag/update"]', updateFlag); - - // Open flag as indicated in location bar - if (window.location.hash.startsWith('#flag-pid-')) { - $(window.location.hash).collapse('toggle'); - } - }; - - function handleDismiss() { - $('.flags').on('click', '.dismiss', function () { - var btn = $(this); - var pid = btn.parents('[data-pid]').attr('data-pid'); - - socket.emit('posts.dismissFlag', pid, function (err) { - done(err, btn); - }); - }); - } - - function handleDismissAll() { - $('#dismissAll').on('click', function () { - socket.emit('posts.dismissAllFlags', function (err) { - if (err) { - return app.alertError(err.message); - } - - ajaxify.refresh(); - }); - return false; - }); - } - - function handleDelete() { - $('.flags').on('click', '.delete', function () { - var btn = $(this); - bootbox.confirm('Do you really want to delete this post?', function (confirm) { - if (!confirm) { - return; - } - var pid = btn.parents('[data-pid]').attr('data-pid'); - var tid = btn.parents('[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.parents('[data-pid]').fadeOut(function () { - $(this).remove(); - if (!$('.flags [data-pid]').length) { - $('.post-container').text('No flagged posts!'); - } - }); - } - - function handleGraphs() { - var dailyCanvas = document.getElementById('flags:daily'); - var dailyLabels = utils.getDaysArray().map(function (text, idx) { - return idx % 3 ? '' : text; - }); - - if (utils.isMobile()) { - Chart.defaults.global.tooltips.enabled = false; - } - var data = { - 'flags:daily': { - labels: dailyLabels, - datasets: [ - { - label: "", - backgroundColor: "rgba(151,187,205,0.2)", - borderColor: "rgba(151,187,205,1)", - pointBackgroundColor: "rgba(151,187,205,1)", - pointHoverBackgroundColor: "#fff", - pointBorderColor: "#fff", - pointHoverBorderColor: "rgba(151,187,205,1)", - data: ajaxify.data.analytics - } - ] - } - }; - - dailyCanvas.width = $(dailyCanvas).parent().width(); - new Chart(dailyCanvas.getContext('2d'), { - type: 'line', - data: data['flags:daily'], - options: { - responsive: true, - animation: false, - legend: { - display: false - }, - scales: { - yAxes: [{ - ticks: { - beginAtZero: true - } - }] - } - } - }); - } - - function updateFlagDetails(source) { - // As the flag details are returned in the API, update the form controls to show the correct data - - // Create reference hash for use in this method - source = source.reduce(function (memo, cur) { - memo[cur.pid] = cur.flagData; - return memo; - }, {}); - - components.get('posts/flag').each(function (idx, el) { - var pid = el.getAttribute('data-pid'); - var el = $(el); - - if (source[pid]) { - for(var prop in source[pid]) { - if (source[pid].hasOwnProperty(prop)) { - el.find('[name="' + prop + '"]').val(source[pid][prop]); - } - } - } - }); - } - - function updateFlag() { - 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) { - if (err) { - return app.alertError(err.message); - } else { - app.alertSuccess('[[topic:flag_manage_saved]]'); - } - }); - } - - return Flags; -}); \ No newline at end of file diff --git a/public/src/client/flags/detail.js b/public/src/client/flags/detail.js index aef21ec925..e20f05dba9 100644 --- a/public/src/client/flags/detail.js +++ b/public/src/client/flags/detail.js @@ -2,7 +2,7 @@ /* globals define */ -define('forum/flags/detail', ['components', 'translator'], function (components, translator) { +define('forum/flags/detail', ['forum/flags/list', 'components', 'translator'], function (FlagsList, components, translator) { var Flags = {}; Flags.init = function () { @@ -44,6 +44,8 @@ define('forum/flags/detail', ['components', 'translator'], function (components, break; } }); + + FlagsList.enableFilterForm(); }; Flags.reloadNotes = function (notes) { diff --git a/public/src/client/flags/list.js b/public/src/client/flags/list.js new file mode 100644 index 0000000000..6111372150 --- /dev/null +++ b/public/src/client/flags/list.js @@ -0,0 +1,28 @@ +'use strict'; + +/* globals define */ + +define('forum/flags/list', ['components'], function (components) { + var Flags = {}; + + Flags.init = function () { + Flags.enableFilterForm(); + }; + + Flags.enableFilterForm = function () { + var filtersEl = components.get('flags/filters'); + + filtersEl.find('button').on('click', function () { + var payload = filtersEl.serializeArray(); + var qs = payload.map(function (filter) { + if (filter.value) { + return filter.name + '=' + filter.value; + } + }).filter(Boolean).join('&'); + + ajaxify.go('flags?' + qs); + }) + }; + + return Flags; +}); diff --git a/src/controllers/admin.js b/src/controllers/admin.js index 7f622466cd..c58def03cf 100644 --- a/src/controllers/admin.js +++ b/src/controllers/admin.js @@ -4,7 +4,6 @@ var adminController = { dashboard: require('./admin/dashboard'), categories: require('./admin/categories'), tags: require('./admin/tags'), - flags: require('./admin/flags'), blacklist: require('./admin/blacklist'), groups: require('./admin/groups'), appearance: require('./admin/appearance'), diff --git a/src/controllers/admin/flags.js b/src/controllers/admin/flags.js deleted file mode 100644 index 80c31ba60a..0000000000 --- a/src/controllers/admin/flags.js +++ /dev/null @@ -1,104 +0,0 @@ -"use strict"; - -var async = require('async'); -var validator = require('validator'); - -var posts = require('../../posts'); -var user = require('../../user'); -var flags = require('../../flags'); -var categories = require('../../categories'); -var analytics = require('../../analytics'); -var pagination = require('../../pagination'); - -var flagsController = {}; - -var itemsPerPage = 20; - -flagsController.get = function (req, res, next) { - var byUsername = req.query.byUsername || ''; - var cid = req.query.cid || 0; - var sortBy = req.query.sortBy || 'count'; - var page = parseInt(req.query.page, 10) || 1; - - async.parallel({ - categories: function (next) { - categories.buildForSelect(req.uid, next); - }, - flagData: function (next) { - getFlagData(req, res, next); - }, - analytics: function (next) { - analytics.getDailyStatsForSet('analytics:flags', Date.now(), 30, next); - }, - assignees: async.apply(user.getAdminsandGlobalModsandModerators) - }, 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) { - return { - uid: userObj.uid, - username: userObj.username - }; - }); - - // If res.locals.cids is populated, then slim down the categories list - if (res.locals.cids) { - results.categories = results.categories.filter(function (category) { - return res.locals.cids.indexOf(String(category.cid)) !== -1; - }); - } - - var pageCount = Math.max(1, Math.ceil(results.flagData.count / itemsPerPage)); - - results.categories.forEach(function (category) { - category.selected = parseInt(category.cid, 10) === parseInt(cid, 10); - }); - - var data = { - posts: results.flagData.posts, - assignees: results.assignees, - analytics: results.analytics, - categories: results.categories, - byUsername: validator.escape(String(byUsername)), - sortByCount: sortBy === 'count', - sortByTime: sortBy === 'time', - pagination: pagination.create(page, pageCount, req.query), - title: '[[pages:flagged-posts]]' - }; - res.render('admin/manage/flags', data); - }); -}; - -function getFlagData(req, res, callback) { - var sortBy = req.query.sortBy || 'count'; - var byUsername = req.query.byUsername || ''; - var cid = req.query.cid || res.locals.cids || 0; - var page = parseInt(req.query.page, 10) || 1; - var start = (page - 1) * itemsPerPage; - var stop = start + itemsPerPage - 1; - - var sets = [sortBy === 'count' ? 'posts:flags:count' : 'posts:flagged']; - - async.waterfall([ - function (next) { - if (byUsername) { - user.getUidByUsername(byUsername, next); - } else { - process.nextTick(next, null, 0); - } - }, - function (uid, next) { - if (uid) { - sets.push('uid:' + uid + ':flag:pids'); - } - - flags.get(sets, cid, req.uid, start, stop, next); - } - ], callback); -} - - -module.exports = flagsController; diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 012ffde3c6..759de90ef1 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -25,7 +25,17 @@ modsController.flags.list = function (req, res, next) { res.locals.cids = results.moderatedCids; } - flags.list({}, function (err, flags) { + // Parse query string params for filters + var valid = ['reporterId', 'type']; + var filters = valid.reduce(function (memo, cur) { + if (req.query.hasOwnProperty(cur)) { + memo[cur] = req.query[cur]; + } + + return memo; + }, {}); + + flags.list(filters, function (err, flags) { if (err) { return next(err); } diff --git a/src/flags.js b/src/flags.js index 58b230af06..6744d8ad59 100644 --- a/src/flags.js +++ b/src/flags.js @@ -53,8 +53,31 @@ Flags.list = function (filters, callback) { filters = {}; } + var sets = []; + if (Object.keys(filters).length > 0) { + for (var type in filters) { + switch (type) { + case 'type': + sets.push('flags:byType:' + filters[type]); + break; + + case 'reporterId': + sets.push('flags:byReporter:' + filters[type]); + break; + } + } + + } + sets = sets.length ? sets : ['flags:datetime']; // No filter default + async.waterfall([ - async.apply(db.getSortedSetRevRange.bind(db), 'flags:datetime', 0, 19), + function (next) { + if (sets.length === 1) { + db.getSortedSetRevRange(sets[0], 0, 19, next); + } else { + db.getSortedSetRevIntersect({sets: sets, start: 0, stop: -1, aggregate: 'MAX'}, next); + } + }, function (flagIds, next) { async.map(flagIds, function (flagId, next) { async.waterfall([ @@ -197,8 +220,10 @@ Flags.create = function (type, id, uid, reason, callback) { uid: uid, datetime: Date.now() })), - async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', Date.now(), flagId), - async.apply(db.setObjectField.bind(db), 'flagHash:flagId', [type, id, uid].join(':'), flagId) + async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', Date.now(), flagId), // by time, the default + async.apply(db.sortedSetAdd.bind(db), 'flags:byReporter:' + uid, Date.now(), flagId), // by reporter + async.apply(db.sortedSetAdd.bind(db), 'flags:byType:' + type, Date.now(), flagId), // by flag type + async.apply(db.setObjectField.bind(db), 'flagHash:flagId', [type, id, uid].join(':'), flagId) // save hash for existence checking ], function (err, data) { if (err) { return next(err); diff --git a/src/routes/admin.js b/src/routes/admin.js index 0611eede70..53b12fc4b8 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -56,7 +56,6 @@ function addRoutes(router, middleware, controllers) { router.get('/manage/categories/:category_id/analytics', middlewares, controllers.admin.categories.getAnalytics); router.get('/manage/tags', middlewares, controllers.admin.tags.get); - router.get('/manage/flags', middlewares, controllers.admin.flags.get); router.get('/manage/ip-blacklist', middlewares, controllers.admin.blacklist.get); router.get('/manage/users', middlewares, controllers.admin.users.sortByJoinDate); diff --git a/src/socket.io/flags.js b/src/socket.io/flags.js index 8b66dd094c..e6fb0be116 100644 --- a/src/socket.io/flags.js +++ b/src/socket.io/flags.js @@ -67,7 +67,7 @@ SocketFlags.create = function (socket, data, callback) { flags.create('post', post.pid, socket.uid, data.reason, next); }, - function (next) { + function (flagObj, next) { async.parallel({ post: function (next) { posts.parsePost(post, next); From 8e1d441e20d70e61d12a13ec66c48c8c029f3470 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 5 Dec 2016 12:40:25 -0500 Subject: [PATCH 021/122] Added some quick filters, #5232 --- public/language/en-GB/flags.json | 5 +++- public/src/client/flags/list.js | 5 ++++ src/controllers/mods.js | 8 ++++--- src/flags.js | 39 ++++++++++++++++++++++++-------- 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index cdc3c4069e..fbe32a812e 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -1,5 +1,4 @@ { - "quick-filters": "Quick Filters", "state": "State", "reporter": "Reporter", "reported-at": "Reported At", @@ -9,11 +8,15 @@ "update": "Update", "updated": "Updated", + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", "filters": "Filter Options", "filter-reporterId": "Reporter UID", "filter-type": "Flag Type", "filter-type-all": "All Content", "filter-type-post": "Post", + "filter-quick-mine": "Assigned to me", "apply-filters": "Apply Filters", "notes": "Flag Notes", diff --git a/public/src/client/flags/list.js b/public/src/client/flags/list.js index 6111372150..2994e7fcf9 100644 --- a/public/src/client/flags/list.js +++ b/public/src/client/flags/list.js @@ -12,6 +12,11 @@ define('forum/flags/list', ['components'], function (components) { Flags.enableFilterForm = function () { var filtersEl = components.get('flags/filters'); + // Parse ajaxify data to set form values to reflect current filters + for(var filter in ajaxify.data.filters) { + filtersEl.find('[name="' + filter + '"]').val(ajaxify.data.filters[filter]); + } + filtersEl.find('button').on('click', function () { var payload = filtersEl.serializeArray(); var qs = payload.map(function (filter) { diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 759de90ef1..f15b1a6b1a 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -26,7 +26,7 @@ modsController.flags.list = function (req, res, next) { } // Parse query string params for filters - var valid = ['reporterId', 'type']; + var valid = ['reporterId', 'type', 'quick']; var filters = valid.reduce(function (memo, cur) { if (req.query.hasOwnProperty(cur)) { memo[cur] = req.query[cur]; @@ -35,13 +35,15 @@ modsController.flags.list = function (req, res, next) { return memo; }, {}); - flags.list(filters, function (err, flags) { + flags.list(filters, req.uid, function (err, flags) { if (err) { return next(err); } res.render('flags/list', { - flags: flags + flags: flags, + hasFilter: !!Object.keys(filters).length, + filters: filters }); }); }); diff --git a/src/flags.js b/src/flags.js index 6744d8ad59..492e1faa43 100644 --- a/src/flags.js +++ b/src/flags.js @@ -47,7 +47,7 @@ Flags.get = function (flagId, callback) { ], callback); }; -Flags.list = function (filters, callback) { +Flags.list = function (filters, uid, callback) { if (typeof filters === 'function' && !callback) { callback = filters; filters = {}; @@ -64,16 +64,23 @@ Flags.list = function (filters, callback) { case 'reporterId': sets.push('flags:byReporter:' + filters[type]); break; + + case 'quick': + switch (filters.quick) { + case 'mine': + sets.push('flags:byAssignee:' + uid); + break; + } + break; } } - } sets = sets.length ? sets : ['flags:datetime']; // No filter default async.waterfall([ function (next) { if (sets.length === 1) { - db.getSortedSetRevRange(sets[0], 0, 19, next); + db.getSortedSetRevRange(sets[0], 0, -1, next); } else { db.getSortedSetRevIntersect({sets: sets, start: 0, stop: -1, aggregate: 'MAX'}, next); } @@ -316,6 +323,8 @@ Flags.update = function (flagId, uid, changeset, callback) { // Retrieve existing flag data to compare for history-saving purposes var fields = ['state', 'assignee']; var history = []; + var tasks = []; + var now = Date.now(); async.waterfall([ async.apply(db.getObjectFields.bind(db), 'flag:' + flagId, fields), @@ -325,6 +334,18 @@ Flags.update = function (flagId, uid, changeset, callback) { if (current[prop] === changeset[prop]) { delete changeset[prop]; } else { + // Add tasks as necessary + switch (prop) { + case 'state': + tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byState:' + changeset[prop], now, flagId)); + tasks.push(async.apply(db.sortedSetRemove.bind(db), 'flags:byState:' + current[prop], flagId)); + break; + + case 'assignee': + tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byAssignee:' + changeset[prop], now, flagId)); + break; + } + // Append to history payload history.push(prop + ':' + changeset[prop]); } @@ -336,12 +357,12 @@ Flags.update = function (flagId, uid, changeset, callback) { return next(); } - async.parallel([ - // Save new object to db (upsert) - async.apply(db.setObject, 'flag:' + flagId, changeset), - // Append history - async.apply(Flags.appendHistory, flagId, uid, history) - ], function (err, data) { + // Save new object to db (upsert) + tasks.push(async.apply(db.setObject, 'flag:' + flagId, changeset)); + // Append history + tasks.push(async.apply(Flags.appendHistory, flagId, uid, history)) + + async.parallel(tasks, function (err, data) { return next(err); }); } From 88958049ebce7abc17a40ba5223d5edcbeabea92 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 5 Dec 2016 15:32:58 -0500 Subject: [PATCH 022/122] added some more filters, and appending event to history on flag creation issue #5232 --- public/language/en-GB/flags.json | 2 ++ public/src/client/flags/list.js | 4 ++-- src/controllers/mods.js | 2 +- src/flags.js | 9 +++++++++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index fbe32a812e..5d9799de50 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -16,6 +16,8 @@ "filter-type": "Flag Type", "filter-type-all": "All Content", "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", "filter-quick-mine": "Assigned to me", "apply-filters": "Apply Filters", diff --git a/public/src/client/flags/list.js b/public/src/client/flags/list.js index 2994e7fcf9..a5277f98df 100644 --- a/public/src/client/flags/list.js +++ b/public/src/client/flags/list.js @@ -13,7 +13,7 @@ define('forum/flags/list', ['components'], function (components) { var filtersEl = components.get('flags/filters'); // Parse ajaxify data to set form values to reflect current filters - for(var filter in ajaxify.data.filters) { + for (var filter in ajaxify.data.filters) { filtersEl.find('[name="' + filter + '"]').val(ajaxify.data.filters[filter]); } @@ -26,7 +26,7 @@ define('forum/flags/list', ['components'], function (components) { }).filter(Boolean).join('&'); ajaxify.go('flags?' + qs); - }) + }); }; return Flags; diff --git a/src/controllers/mods.js b/src/controllers/mods.js index f15b1a6b1a..512ad32222 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -26,7 +26,7 @@ modsController.flags.list = function (req, res, next) { } // Parse query string params for filters - var valid = ['reporterId', 'type', 'quick']; + var valid = ['assignee', 'state', 'reporterId', 'type', 'quick']; var filters = valid.reduce(function (memo, cur) { if (req.query.hasOwnProperty(cur)) { memo[cur] = req.query[cur]; diff --git a/src/flags.js b/src/flags.js index 492e1faa43..a8bca052d1 100644 --- a/src/flags.js +++ b/src/flags.js @@ -60,11 +60,19 @@ Flags.list = function (filters, uid, callback) { case 'type': sets.push('flags:byType:' + filters[type]); break; + + case 'state': + sets.push('flags:byState:' + filters[type]); + break; case 'reporterId': sets.push('flags:byReporter:' + filters[type]); break; + case 'assignee': + sets.push('flags:byAssignee:' + filters[type]); + break; + case 'quick': switch (filters.quick) { case 'mine': @@ -236,6 +244,7 @@ Flags.create = function (type, id, uid, reason, callback) { return next(err); } + Flags.appendHistory(flagId, uid, ['created']); next(null, flagId); }); }, From cd3002e812a1c41aea190d72b5941f3d6634505f Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 5 Dec 2016 15:52:01 -0500 Subject: [PATCH 023/122] removed user flag reset method and associated socket call from ACP --- public/src/admin/manage/users.js | 9 --------- src/socket.io/admin/user.js | 8 -------- src/views/admin/manage/users.tpl | 1 - 3 files changed, 18 deletions(-) diff --git a/public/src/admin/manage/users.js b/public/src/admin/manage/users.js index b8fb8d5de6..2f344e37c7 100644 --- a/public/src/admin/manage/users.js +++ b/public/src/admin/manage/users.js @@ -128,15 +128,6 @@ define('admin/manage/users', ['translator'], function (translator) { socket.emit('admin.user.resetLockouts', uids, done('Lockout(s) reset!')); }); - $('.reset-flags').on('click', function () { - var uids = getSelectedUids(); - if (!uids.length) { - return; - } - - socket.emit('admin.user.resetFlags', uids, done('Flags(s) reset!')); - }); - $('.admin-user').on('click', function () { var uids = getSelectedUids(); if (!uids.length) { diff --git a/src/socket.io/admin/user.js b/src/socket.io/admin/user.js index 4a77c224a7..272a13f7f7 100644 --- a/src/socket.io/admin/user.js +++ b/src/socket.io/admin/user.js @@ -68,14 +68,6 @@ User.resetLockouts = function (socket, uids, callback) { async.each(uids, user.auth.resetLockout, callback); }; -User.resetFlags = function (socket, uids, callback) { - if (!Array.isArray(uids)) { - return callback(new Error('[[error:invalid-data]]')); - } - - user.resetFlags(uids, callback); -}; - User.validateEmail = function (socket, uids, callback) { if (!Array.isArray(uids)) { return callback(new Error('[[error:invalid-data]]')); diff --git a/src/views/admin/manage/users.tpl b/src/views/admin/manage/users.tpl index de0cd15e62..b43d66af8a 100644 --- a/src/views/admin/manage/users.tpl +++ b/src/views/admin/manage/users.tpl @@ -19,7 +19,6 @@
  • Ban User(s) Temporarily
  • Unban User(s)
  • Reset Lockout
  • -
  • Reset Flags
  • Delete User(s)
  • Delete User(s) and Content
  • From 9f9051026b89b41d6028e8c0b59f6fa9a6e7336e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 6 Dec 2016 16:11:56 -0500 Subject: [PATCH 024/122] more work on #5232 --- public/language/en-GB/flags.json | 8 ++ public/src/client/flags/list.js | 7 ++ public/src/client/topic/flag.js | 2 +- src/controllers/mods.js | 2 +- src/flags.js | 143 +++++++++++++++++++++++++++---- src/socket.io/flags.js | 85 ++---------------- 6 files changed, 153 insertions(+), 94 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index 5d9799de50..6b4e96f4fb 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -13,6 +13,7 @@ "filter-reset": "Remove Filters", "filters": "Filter Options", "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", "filter-type": "Flag Type", "filter-type-all": "All Content", "filter-type-post": "Post", @@ -21,6 +22,13 @@ "filter-quick-mine": "Assigned to me", "apply-filters": "Apply Filters", + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "reporter": "Reporting User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + "notes": "Flag Notes", "add-note": "Add Note", "no-notes": "No shared notes.", diff --git a/public/src/client/flags/list.js b/public/src/client/flags/list.js index a5277f98df..cbdaf94f24 100644 --- a/public/src/client/flags/list.js +++ b/public/src/client/flags/list.js @@ -7,6 +7,7 @@ define('forum/flags/list', ['components'], function (components) { Flags.init = function () { Flags.enableFilterForm(); + Flags.enableChatButtons(); }; Flags.enableFilterForm = function () { @@ -29,5 +30,11 @@ define('forum/flags/list', ['components'], function (components) { }); }; + Flags.enableChatButtons = function () { + $('[data-chat]').on('click', function () { + app.newChat(this.getAttribute('data-chat')); + }); + }; + return Flags; }); diff --git a/public/src/client/topic/flag.js b/public/src/client/topic/flag.js index 046585ae68..6b3440da54 100644 --- a/public/src/client/topic/flag.js +++ b/public/src/client/topic/flag.js @@ -48,7 +48,7 @@ define('forum/topic/flag', [], function () { if (!pid || !reason) { return; } - socket.emit('flags.create', {pid: pid, reason: reason}, function (err) { + socket.emit('flags.create', {type: 'post', id: pid, reason: reason}, function (err) { if (err) { return app.alertError(err.message); } diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 512ad32222..788294a01e 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -26,7 +26,7 @@ modsController.flags.list = function (req, res, next) { } // Parse query string params for filters - var valid = ['assignee', 'state', 'reporterId', 'type', 'quick']; + var valid = ['assignee', 'state', 'reporterId', 'type', 'targetUid', 'quick']; var filters = valid.reduce(function (memo, cur) { if (req.query.hasOwnProperty(cur)) { memo[cur] = req.query[cur]; diff --git a/src/flags.js b/src/flags.js index a8bca052d1..45aae2502e 100644 --- a/src/flags.js +++ b/src/flags.js @@ -1,23 +1,22 @@ - - 'use strict'; var async = require('async'); var winston = require('winston'); var db = require('./database'); var user = require('./user'); +var groups = require('./groups'); +var meta = require('./meta'); +var notifications = require('./notifications'); var analytics = require('./analytics'); var topics = require('./topics'); var posts = require('./posts'); +var privileges = require('./privileges'); +var plugins = require('./plugins'); var utils = require('../public/src/utils'); var _ = require('underscore'); +var S = require('string'); -var Flags = { - _defaults: { - state: 'open', - assignee: null - } -}; +var Flags = {}; Flags.get = function (flagId, callback) { async.waterfall([ @@ -72,6 +71,10 @@ Flags.list = function (filters, uid, callback) { case 'assignee': sets.push('flags:byAssignee:' + filters[type]); break; + + case 'targetUid': + sets.push('flags:byTargetUid:' + filters[type]); + break; case 'quick': switch (filters.quick) { @@ -145,6 +148,43 @@ Flags.list = function (filters, uid, callback) { }); }; +Flags.validate = function (payload, callback) { + async.parallel({ + targetExists: async.apply(Flags.targetExists, payload.type, payload.id), + target: async.apply(Flags.getTarget, payload.type, payload.id, payload.uid), + reporter: async.apply(user.getUserData, payload.uid) + }, function (err, data) { + if (err) { + return callback(err); + } + + if (data.target.deleted) { + return callback(new Error('[[error:post-deleted]]')); + } else if (data.reporter.banned) { + return callback(new Error('[[error:user-banned]]')); + } + + switch (payload.type) { + case 'post': + async.parallel({ + privileges: async.apply(privileges.posts.get, [payload.id], payload.uid) + }, function (err, subdata) { + if (err) { + return callback(err); + } + + var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1; + if (!subdata.privileges[0].isAdminOrMod && parseInt(data.reporter.reputation, 10) < minimumReputation) { + return callback(new Error('[[error:not-enough-reputation-to-flag]]')); + } + + callback(); + }); + break; + } + }); +}; + Flags.getTarget = function (type, id, uid, callback) { switch (type) { case 'post': @@ -204,17 +244,22 @@ Flags.getNotes = function (flagId, callback) { }; Flags.create = function (type, id, uid, reason, callback) { + var targetUid; + async.waterfall([ function (next) { // Sanity checks async.parallel([ async.apply(Flags.exists, type, id, uid), - async.apply(Flags.targetExists, type, id) + async.apply(Flags.targetExists, type, id), + async.apply(Flags.getTargetUid, type, id) ], function (err, checks) { if (err) { return next(err); } + targetUid = checks[2] || null; + if (checks[0]) { return next(new Error('[[error:already-flagged]]')); } else if (!checks[1]) { @@ -226,25 +271,31 @@ Flags.create = function (type, id, uid, reason, callback) { }, async.apply(db.incrObjectField, 'global', 'nextFlagId'), function (flagId, next) { - async.parallel([ - async.apply(db.setObject.bind(db), 'flag:' + flagId, Object.assign({}, Flags._defaults, { + var tasks = [ + async.apply(db.setObject.bind(db), 'flag:' + flagId, { flagId: flagId, type: type, targetId: id, description: reason, uid: uid, datetime: Date.now() - })), + }), async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', Date.now(), flagId), // by time, the default async.apply(db.sortedSetAdd.bind(db), 'flags:byReporter:' + uid, Date.now(), flagId), // by reporter async.apply(db.sortedSetAdd.bind(db), 'flags:byType:' + type, Date.now(), flagId), // by flag type async.apply(db.setObjectField.bind(db), 'flagHash:flagId', [type, id, uid].join(':'), flagId) // save hash for existence checking - ], function (err, data) { + ]; + + if (targetUid) { + tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byTargetUid:' + targetUid, Date.now(), flagId)); // by target uid + } + + async.parallel(tasks, function (err, data) { if (err) { return next(err); } - Flags.appendHistory(flagId, uid, ['created']); + Flags.update(flagId, uid, { "state": "open" }); next(null, flagId); }); }, @@ -318,7 +369,7 @@ Flags.exists = function (type, id, uid, callback) { Flags.targetExists = function (type, id, callback) { switch (type) { - case 'topic': + case 'topic': // just an example... topics.exists(id, callback); break; @@ -328,6 +379,14 @@ Flags.targetExists = function (type, id, callback) { } }; +Flags.getTargetUid = function (type, id, callback) { + switch (type) { + case 'post': + posts.getPostField(id, 'uid', callback); + break; + } +}; + Flags.update = function (flagId, uid, changeset, callback) { // Retrieve existing flag data to compare for history-saving purposes var fields = ['state', 'assignee']; @@ -369,7 +428,7 @@ Flags.update = function (flagId, uid, changeset, callback) { // Save new object to db (upsert) tasks.push(async.apply(db.setObject, 'flag:' + flagId, changeset)); // Append history - tasks.push(async.apply(Flags.appendHistory, flagId, uid, history)) + tasks.push(async.apply(Flags.appendHistory, flagId, uid, history)); async.parallel(tasks, function (err, data) { return next(err); @@ -462,4 +521,56 @@ Flags.appendNote = function (flagId, uid, note, callback) { ], callback); }; +Flags.notify = function (flagObj, uid, callback) { + // Notify administrators, mods, and other associated people + switch (flagObj.type) { + case 'post': + async.parallel({ + post: function (next) { + async.waterfall([ + async.apply(posts.getPostData, flagObj.targetId), + async.apply(posts.parsePost) + ], next); + }, + title: async.apply(topics.getTitleByPid, flagObj.targetId), + admins: async.apply(groups.getMembers, 'administrators', 0, -1), + globalMods: async.apply(groups.getMembers, 'Global Moderators', 0, -1), + moderators: function (next) { + async.waterfall([ + async.apply(posts.getCidByPid, flagObj.targetId), + function (cid, next) { + groups.getMembers('cid:' + cid + ':privileges:mods', 0, -1, next); + } + ], next); + } + }, function (err, results) { + if (err) { + return callback(err); + } + + var title = S(results.title).decodeHTMLEntities().s; + var titleEscaped = title.replace(/%/g, '%').replace(/,/g, ','); + + notifications.create({ + bodyShort: '[[notifications:user_flagged_post_in, ' + flagObj.reporter.username + ', ' + titleEscaped + ']]', + bodyLong: results.post.content, + pid: flagObj.targetId, + path: '/post/' + flagObj.targetId, + nid: 'flag:post:' + flagObj.targetId + ':uid:' + uid, + from: uid, + mergeId: 'notifications:user_flagged_post_in|' + flagObj.targetId, + topicTitle: results.title + }, function (err, notification) { + if (err || !notification) { + return callback(err); + } + + plugins.fireHook('action:post.flag', {post: results.post, reason: flagObj.description, flaggingUser: flagObj.reporter}); + notifications.push(notification, results.admins.concat(results.moderators).concat(results.globalMods), callback); + }); + }); + break; + } +}; + module.exports = Flags; \ No newline at end of file diff --git a/src/socket.io/flags.js b/src/socket.io/flags.js index e6fb0be116..ce148faa87 100644 --- a/src/socket.io/flags.js +++ b/src/socket.io/flags.js @@ -21,89 +21,22 @@ SocketFlags.create = function (socket, data, callback) { return callback(new Error('[[error:not-logged-in]]')); } - if (!data || !data.pid || !data.reason) { + if (!data || !data.type || !data.id || !data.reason) { return callback(new Error('[[error:invalid-data]]')); } - var flaggingUser = {}; - var post; - async.waterfall([ + async.apply(flags.validate, { + uid: socket.uid, + type: data.type, + id: data.id + }), function (next) { - posts.getPostFields(data.pid, ['pid', 'tid', 'uid', 'content', 'deleted'], next); - }, - function (postData, next) { - if (parseInt(postData.deleted, 10) === 1) { - return next(new Error('[[error:post-deleted]]')); - } - - post = postData; - topics.getTopicFields(post.tid, ['title', 'cid'], next); - }, - function (topicData, next) { - post.topic = topicData; - - async.parallel({ - isAdminOrMod: function (next) { - privileges.categories.isAdminOrMod(post.topic.cid, socket.uid, next); - }, - userData: function (next) { - user.getUserFields(socket.uid, ['username', 'reputation', 'banned'], next); - } - }, next); - }, - function (user, next) { - var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1; - if (!user.isAdminOrMod && parseInt(user.userData.reputation, 10) < minimumReputation) { - return next(new Error('[[error:not-enough-reputation-to-flag]]')); - } - - if (parseInt(user.banned, 10) === 1) { - return next(new Error('[[error:user-banned]]')); - } - - flaggingUser = user.userData; - flaggingUser.uid = socket.uid; - - flags.create('post', post.pid, socket.uid, data.reason, next); + // If we got here, then no errors occurred + flags.create(data.type, data.id, socket.uid, data.reason, next); }, function (flagObj, next) { - async.parallel({ - post: function (next) { - posts.parsePost(post, next); - }, - admins: function (next) { - groups.getMembers('administrators', 0, -1, next); - }, - globalMods: function (next) { - groups.getMembers('Global Moderators', 0, -1, next); - }, - moderators: function (next) { - groups.getMembers('cid:' + post.topic.cid + ':privileges:mods', 0, -1, next); - } - }, next); - }, - function (results, next) { - var title = S(post.topic.title).decodeHTMLEntities().s; - var titleEscaped = title.replace(/%/g, '%').replace(/,/g, ','); - - notifications.create({ - bodyShort: '[[notifications:user_flagged_post_in, ' + flaggingUser.username + ', ' + titleEscaped + ']]', - bodyLong: post.content, - pid: data.pid, - path: '/post/' + data.pid, - nid: 'post_flag:' + data.pid + ':uid:' + socket.uid, - from: socket.uid, - mergeId: 'notifications:user_flagged_post_in|' + data.pid, - topicTitle: post.topic.title - }, function (err, notification) { - if (err || !notification) { - return next(err); - } - - plugins.fireHook('action:post.flag', {post: post, reason: data.reason, flaggingUser: flaggingUser}); - notifications.push(notification, results.admins.concat(results.moderators).concat(results.globalMods), next); - }); + flags.notify(flagObj, socket.uid, next); } ], callback); }; From 57fcb92bbcc14f265e238348e82d18e5ea357431 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 6 Dec 2016 20:28:54 -0500 Subject: [PATCH 025/122] added a smattering of tests for #5232 --- test/flags.js | 188 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 183 insertions(+), 5 deletions(-) diff --git a/test/flags.js b/test/flags.js index c5e69aa973..ee735afd60 100644 --- a/test/flags.js +++ b/test/flags.js @@ -8,7 +8,9 @@ var db = require('./mocks/databasemock'); var Flags = require('../src/flags'); var Categories = require('../src/categories'); var Topics = require('../src/topics'); +var Posts = require('../src/posts'); var User = require('../src/user'); +var Meta = require('../src/meta'); describe('Flags', function () { before(function (done) { @@ -43,8 +45,7 @@ describe('Flags', function () { uid: 1, targetId: 1, type: 'post', - description: 'Test flag', - state: 'open' + description: 'Test flag' }; for(var key in compare) { @@ -86,7 +87,7 @@ describe('Flags', function () { describe('.list()', function () { it('should show a list of flags (with one item)', function (done) { - Flags.list({}, function (err, flags) { + Flags.list({}, 1, function (err, flags) { assert.ifError(err); assert.ok(Array.isArray(flags)); assert.equal(flags.length, 1); @@ -101,7 +102,49 @@ describe('Flags', function () { }); }); - describe('.getTarget()', function() { + describe('.update()', function () { + it('should alter a flag\'s various attributes and persist them to the database', function (done) { + Flags.update(1, 1, { + "state": "wip", + "assignee": 1 + }, function (err) { + assert.ifError(err); + db.getObjectFields('flag:1', ['state', 'assignee'], function (err, data) { + if (err) { + throw err; + } + + assert.strictEqual('wip', data.state); + assert.strictEqual(1, data.assignee); + done(); + }); + }); + }); + + it('should persist to the flag\'s history', function (done) { + Flags.getHistory(1, function (err, history) { + if (err) { + throw err; + } + + history.forEach(function (change) { + switch (change.attribute) { + case 'state': + assert.strictEqual('[[flags:state-wip]]', change.value); + break; + + case 'assignee': + assert.strictEqual(1, change.value); + break; + } + }); + + done(); + }); + }); + }); + + describe('.getTarget()', function () { it('should return a post\'s data if queried with type "post"', function (done) { Flags.getTarget('post', 1, 1, function (err, data) { assert.ifError(err); @@ -141,7 +184,142 @@ describe('Flags', function () { done(); }); }); - });; + }); + + describe('.validate()', function () { + it('should error out if type is post and post is deleted', function (done) { + Posts.delete(1, 1, function (err) { + if (err) { + throw err; + } + + Flags.validate({ + type: 'post', + id: 1, + uid: 1 + }, function (err) { + assert.ok(err); + assert.strictEqual('[[error:post-deleted]]', err.message); + Posts.restore(1, 1, done); + }); + }); + }); + + it('should not pass validation if flag threshold is set and user rep does not meet it', function (done) { + Meta.configs.set('privileges:flag', '50', function (err) { + assert.ifError(err); + + Flags.validate({ + type: 'post', + id: 1, + uid: 1 + }, function (err) { + assert.ok(err); + assert.strictEqual('[[error:not-enough-reputation-to-flag]]', err.message); + Meta.configs.set('privileges:flag', 0, done); + }); + }); + }); + }); + + describe('.appendNote()', function () { + it('should add a note to a flag', function (done) { + Flags.appendNote(1, 1, 'this is my note', function (err) { + assert.ifError(err); + + db.getSortedSetRange('flag:1:notes', 0, -1, function (err, notes) { + if (err) { + throw err; + } + + assert.strictEqual('[1,"this is my note"]', notes[0]); + done(); + }); + }); + }); + + it('should be a JSON string', function (done) { + db.getSortedSetRange('flag:1:notes', 0, -1, function (err, notes) { + if (err) { + throw err; + } + + try { + JSON.parse(notes[0]); + } catch (e) { + assert.ifError(e); + } + + done(); + }); + }); + }); + + describe('.getNotes()', function () { + before(function (done) { + // Add a second note + Flags.appendNote(1, 1, 'this is the second note', done); + }); + + it('return should match a predefined spec', function (done) { + Flags.getNotes(1, function (err, notes) { + assert.ifError(err); + var compare = { + uid: 1, + content: 'this is my note' + }; + + var data = notes[1]; + for(var key in compare) { + if (compare.hasOwnProperty(key)) { + assert.ok(data[key]); + assert.strictEqual(data[key], compare[key]); + } + } + + done(); + }); + }); + + it('should retrieve a list of notes, from newest to oldest', function (done) { + Flags.getNotes(1, function (err, notes) { + assert.ifError(err); + assert(notes[0].datetime > notes[1].datetime); + assert.strictEqual('this is the second note', notes[0].content); + done(); + }); + }); + }); + + describe('.appendHistory()', function () { + var entries; + before(function (done) { + db.sortedSetCard('flag:1:history', function (err, count) { + entries = count; + done(err); + }); + }); + + it('should add a new entry into a flag\'s history', function (done) { + Flags.appendHistory(1, 1, ['state:rejected'], function (err) { + assert.ifError(err); + + Flags.getHistory(1, function (err, history) { + assert.strictEqual(entries + 1, history.length); + done(); + }); + }); + }); + }); + + describe('.getHistory()', function () { + it('should retrieve a flag\'s history', function (done) { + Flags.getHistory(1, function (err, history) { + assert.strictEqual(history[0].fields[0].value, '[[flags:state-rejected]]'); + done(); + }); + }); + }); after(function (done) { db.emptydb(done); From 5dd892bd010e126b2c8f13a47460144c3a77bdcf Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 7 Dec 2016 12:07:22 -0500 Subject: [PATCH 026/122] a bunch of changes here... allowing user profiles to be flagged, #5232 --- public/language/en-GB/flags.json | 13 +++- public/language/en-GB/notifications.json | 3 + public/language/en-GB/topic.json | 9 +-- public/language/en-GB/user.json | 1 + public/src/client/account/header.js | 10 +++ public/src/client/flags/list.js | 2 + public/src/client/topic/postTools.js | 9 ++- .../topic/flag.js => modules/flags.js} | 25 +++--- src/controllers/mods.js | 6 +- src/flags.js | 76 +++++++++++++++++-- src/meta/js.js | 4 +- src/notifications.js | 2 + test/flags.js | 12 ++- 13 files changed, 133 insertions(+), 39 deletions(-) rename public/src/{client/topic/flag.js => modules/flags.js} (62%) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index 6b4e96f4fb..a9272897ca 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -29,6 +29,9 @@ "start-new-chat": "Start New Chat", "go-to-target": "View Flag Target", + "user-view": "View Profile", + "user-edit": "Edit Profile", + "notes": "Flag Notes", "add-note": "Add Note", "no-notes": "No shared notes.", @@ -43,5 +46,13 @@ "state-resolved": "Resolved", "state-rejected": "Rejected", "no-assignee": "Not Assigned", - "note-added": "Note Added" + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." } \ No newline at end of file diff --git a/public/language/en-GB/notifications.json b/public/language/en-GB/notifications.json index 5a2ed58908..0838ca17eb 100644 --- a/public/language/en-GB/notifications.json +++ b/public/language/en-GB/notifications.json @@ -21,6 +21,9 @@ "user_flagged_post_in": "%1 flagged a post in %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to" : "%1 has posted a reply to: %2", "user_posted_to_dual" : "%1 and %2 have posted replies to: %3", "user_posted_to_multiple" : "%1 and %2 others have posted replies to: %3", diff --git a/public/language/en-GB/topic.json b/public/language/en-GB/topic.json index 4ae208076e..5571292dda 100644 --- a/public/language/en-GB/topic.json +++ b/public/language/en-GB/topic.json @@ -28,7 +28,6 @@ "link": "Link", "share": "Share", "tools": "Tools", - "flag": "Flag", "locked": "Locked", "pinned": "Pinned", "moved": "Moved", @@ -36,7 +35,6 @@ "bookmark_instructions" : "Click here to return to the last read post in this thread.", "flag_title": "Flag this post for moderation", - "flag_success": "This post has been flagged for moderation.", "deleted_message": "This topic has been deleted. Only users with topic management privileges can see it.", @@ -138,10 +136,5 @@ "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)\n\n", - - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" - + "link_back": "Re: [%1](%2)\n\n" } diff --git a/public/language/en-GB/user.json b/public/language/en-GB/user.json index f0cb35f615..0725f208a3 100644 --- a/public/language/en-GB/user.json +++ b/public/language/en-GB/user.json @@ -35,6 +35,7 @@ "chat": "Chat", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Follow", "unfollow": "Unfollow", "more": "More", diff --git a/public/src/client/account/header.js b/public/src/client/account/header.js index d225e2cae1..b53cbb2be4 100644 --- a/public/src/client/account/header.js +++ b/public/src/client/account/header.js @@ -49,6 +49,7 @@ define('forum/account/header', [ components.get('account/ban').on('click', banAccount); components.get('account/unban').on('click', unbanAccount); components.get('account/delete').on('click', deleteAccount); + components.get('account/flag').on('click', flagAccount); }; function hidePrivateLinks() { @@ -167,6 +168,15 @@ define('forum/account/header', [ }); } + function flagAccount() { + require(['flags'], function (flags) { + flags.showFlagModal({ + type: 'user', + id: ajaxify.data.uid + }); + }); + } + function removeCover() { socket.emit('user.removeCover', { uid: ajaxify.data.uid diff --git a/public/src/client/flags/list.js b/public/src/client/flags/list.js index cbdaf94f24..bf8b4bc1a8 100644 --- a/public/src/client/flags/list.js +++ b/public/src/client/flags/list.js @@ -23,6 +23,8 @@ define('forum/flags/list', ['components'], function (components) { var qs = payload.map(function (filter) { if (filter.value) { return filter.name + '=' + filter.value; + } else { + return; } }).filter(Boolean).join('&'); diff --git a/public/src/client/topic/postTools.js b/public/src/client/topic/postTools.js index faa0567878..5618e692db 100644 --- a/public/src/client/topic/postTools.js +++ b/public/src/client/topic/postTools.js @@ -167,10 +167,11 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator postContainer.on('click', '[component="post/flag"]', function () { var pid = getData($(this), 'data-pid'); - var username = getData($(this), 'data-username'); - var userslug = getData($(this), 'data-userslug'); - require(['forum/topic/flag'], function (flag) { - flag.showFlagModal(pid, username, userslug); + require(['flags'], function (flags) { + flags.showFlagModal({ + type: 'post', + id: pid + }); }); }); diff --git a/public/src/client/topic/flag.js b/public/src/modules/flags.js similarity index 62% rename from public/src/client/topic/flag.js rename to public/src/modules/flags.js index 6b3440da54..cc9fd5103a 100644 --- a/public/src/client/topic/flag.js +++ b/public/src/modules/flags.js @@ -2,18 +2,13 @@ /* globals define, app, socket, templates */ -define('forum/topic/flag', [], function () { - +define('flags', [], function () { var Flag = {}, flagModal, flagCommit; - Flag.showFlagModal = function (pid, username, userslug) { - parseModal({ - pid: pid, - username: username, - userslug: userslug - }, function (html) { + Flag.showFlagModal = function (data) { + parseModal(data, function (html) { flagModal = $(html); flagModal.on('hidden.bs.modal', function () { @@ -23,11 +18,11 @@ define('forum/topic/flag', [], function () { flagCommit = flagModal.find('#flag-post-commit'); flagModal.on('click', '.flag-reason', function () { - flagPost(pid, $(this).text()); + createFlag(data.type, data.id, $(this).text()); }); flagCommit.on('click', function () { - flagPost(pid, flagModal.find('#flag-reason-custom').val()); + createFlag(data.type, data.id, flagModal.find('#flag-reason-custom').val()); }); flagModal.modal('show'); @@ -37,24 +32,24 @@ define('forum/topic/flag', [], function () { }; function parseModal(tplData, callback) { - templates.parse('partials/modals/flag_post_modal', tplData, function (html) { + templates.parse('partials/modals/flag_modal', tplData, function (html) { require(['translator'], function (translator) { translator.translate(html, callback); }); }); } - function flagPost(pid, reason) { - if (!pid || !reason) { + function createFlag(type, id, reason) { + if (!type || !id || !reason) { return; } - socket.emit('flags.create', {type: 'post', id: pid, reason: reason}, function (err) { + socket.emit('flags.create', {type: type, id: id, reason: reason}, function (err) { if (err) { return app.alertError(err.message); } flagModal.modal('hide'); - app.alertSuccess('[[topic:flag_success]]'); + app.alertSuccess('[[flags:modal-submit-success]]'); }); } diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 788294a01e..656605f277 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -63,7 +63,11 @@ modsController.flags.detail = function (req, res, next) { } res.render('flags/detail', Object.assign(results.flagData, { - assignees: results.assignees + assignees: results.assignees, + type_bool: ['post', 'user'].reduce(function (memo, cur) { + memo[cur] = results.flagData.type === cur; + return memo; + }, {}) })); }); }; diff --git a/src/flags.js b/src/flags.js index 45aae2502e..9f121f81bf 100644 --- a/src/flags.js +++ b/src/flags.js @@ -167,20 +167,44 @@ Flags.validate = function (payload, callback) { switch (payload.type) { case 'post': async.parallel({ - privileges: async.apply(privileges.posts.get, [payload.id], payload.uid) + editable: async.apply(privileges.posts.canEdit, payload.id, payload.uid) }, function (err, subdata) { if (err) { return callback(err); } var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1; - if (!subdata.privileges[0].isAdminOrMod && parseInt(data.reporter.reputation, 10) < minimumReputation) { + // Check if reporter meets rep threshold (or can edit the target post, in which case threshold does not apply) + if (!subdata.editable.flag && parseInt(data.reporter.reputation, 10) < minimumReputation) { return callback(new Error('[[error:not-enough-reputation-to-flag]]')); } callback(); }); break; + + case 'user': + async.parallel({ + editable: async.apply(privileges.users.canEdit, payload.uid, payload.id) + }, function (err, subdata) { + if (err) { + return callback(err); + } + + + var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1; + // Check if reporter meets rep threshold (or can edit the target user, in which case threshold does not apply) + if (!subdata.editable && parseInt(data.reporter.reputation, 10) < minimumReputation) { + return callback(new Error('[[error:not-enough-reputation-to-flag]]')); + } + + callback(); + }); + break; + + default: + callback(new Error('[[error:invalid-data]]')); + break; } }); }; @@ -369,13 +393,17 @@ Flags.exists = function (type, id, uid, callback) { Flags.targetExists = function (type, id, callback) { switch (type) { - case 'topic': // just an example... - topics.exists(id, callback); - break; - case 'post': posts.exists(id, callback); break; + + case 'user': + user.exists(id, callback); + break; + + default: + callback(new Error('[[error:invalid-data]]')); + break; } }; @@ -384,6 +412,10 @@ Flags.getTargetUid = function (type, id, callback) { case 'post': posts.getPostField(id, 'uid', callback); break; + + case 'user': + setImmediate(callback, null, id); + break; } }; @@ -553,7 +585,7 @@ Flags.notify = function (flagObj, uid, callback) { notifications.create({ bodyShort: '[[notifications:user_flagged_post_in, ' + flagObj.reporter.username + ', ' + titleEscaped + ']]', - bodyLong: results.post.content, + bodyLong: flagObj.description, pid: flagObj.targetId, path: '/post/' + flagObj.targetId, nid: 'flag:post:' + flagObj.targetId + ':uid:' + uid, @@ -570,6 +602,36 @@ Flags.notify = function (flagObj, uid, callback) { }); }); break; + + case 'user': + async.parallel({ + admins: async.apply(groups.getMembers, 'administrators', 0, -1), + globalMods: async.apply(groups.getMembers, 'Global Moderators', 0, -1), + }, function (err, results) { + if (err) { + return callback(err); + } + + notifications.create({ + bodyShort: '[[notifications:user_flagged_user, ' + flagObj.reporter.username + ', ' + flagObj.target.username + ']]', + bodyLong: flagObj.description, + path: '/uid/' + flagObj.targetId, + nid: 'flag:user:' + flagObj.targetId + ':uid:' + uid, + from: uid, + mergeId: 'notifications:user_flagged_user|' + flagObj.targetId + }, function (err, notification) { + if (err || !notification) { + return callback(err); + } + + notifications.push(notification, results.admins.concat(results.globalMods), callback); + }); + }); + break; + + default: + callback(new Error('[[error:invalid-data]]')); + break; } }; diff --git a/src/meta/js.js b/src/meta/js.js index 626fa0ecd8..947550f37e 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -49,7 +49,6 @@ module.exports = function (Meta) { 'public/src/client/unread.js', 'public/src/client/topic.js', 'public/src/client/topic/events.js', - 'public/src/client/topic/flag.js', 'public/src/client/topic/fork.js', 'public/src/client/topic/move.js', 'public/src/client/topic/posts.js', @@ -72,7 +71,8 @@ module.exports = function (Meta) { 'public/src/modules/taskbar.js', 'public/src/modules/helpers.js', 'public/src/modules/sounds.js', - 'public/src/modules/string.js' + 'public/src/modules/string.js', + 'public/src/modules/flags.js' ], // modules listed below are routed through express (/src/modules) so they can be defined anonymously diff --git a/src/notifications.js b/src/notifications.js index b99700be01..0fb1e1ace3 100644 --- a/src/notifications.js +++ b/src/notifications.js @@ -415,6 +415,7 @@ var utils = require('../public/src/utils'); 'notifications:user_started_following_you', 'notifications:user_posted_to', 'notifications:user_flagged_post_in', + 'notifications:user_flagged_user', 'new_register' ], isolated, differentiators, differentiator, modifyIndex, set; @@ -462,6 +463,7 @@ var utils = require('../public/src/utils'); case 'notifications:user_started_following_you': case 'notifications:user_posted_to': case 'notifications:user_flagged_post_in': + case 'notifications:user_flagged_user': var usernames = set.map(function (notifObj) { return notifObj && notifObj.user && notifObj.user.username; }).filter(function (username, idx, array) { diff --git a/test/flags.js b/test/flags.js index ee735afd60..14bb1e65c6 100644 --- a/test/flags.js +++ b/test/flags.js @@ -32,6 +32,11 @@ describe('Flags', function () { content: 'This is flaggable content' }, next); }); + }, + function (topicData, next) { + User.create({ + username: 'testUser2', password: 'abcdef', email: 'c@d.com' + }, next); } ], done); }); @@ -212,7 +217,7 @@ describe('Flags', function () { Flags.validate({ type: 'post', id: 1, - uid: 1 + uid: 2 }, function (err) { assert.ok(err); assert.strictEqual('[[error:not-enough-reputation-to-flag]]', err.message); @@ -305,6 +310,10 @@ describe('Flags', function () { assert.ifError(err); Flags.getHistory(1, function (err, history) { + if (err) { + throw err; + } + assert.strictEqual(entries + 1, history.length); done(); }); @@ -315,6 +324,7 @@ describe('Flags', function () { describe('.getHistory()', function () { it('should retrieve a flag\'s history', function (done) { Flags.getHistory(1, function (err, history) { + assert.ifError(err); assert.strictEqual(history[0].fields[0].value, '[[flags:state-rejected]]'); done(); }); From a5fb4825b4c92a481e7da04246cb307b56f40bd0 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 7 Dec 2016 13:06:55 -0500 Subject: [PATCH 027/122] deprecating old hook for #5232 --- public/language/en-GB/pages.json | 2 +- src/flags.js | 7 ++++++- src/plugins/hooks.js | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/public/language/en-GB/pages.json b/public/language/en-GB/pages.json index 801b28edea..104e2249f2 100644 --- a/public/language/en-GB/pages.json +++ b/public/language/en-GB/pages.json @@ -6,7 +6,7 @@ "popular-month": "Popular topics this month", "popular-alltime": "All time popular topics", "recent": "Recent Topics", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online Users", diff --git a/src/flags.js b/src/flags.js index 9f121f81bf..bfbe80992a 100644 --- a/src/flags.js +++ b/src/flags.js @@ -597,7 +597,9 @@ Flags.notify = function (flagObj, uid, callback) { return callback(err); } - plugins.fireHook('action:post.flag', {post: results.post, reason: flagObj.description, flaggingUser: flagObj.reporter}); + plugins.fireHook('action:flag.create', { + flag: flagObj + }); notifications.push(notification, results.admins.concat(results.moderators).concat(results.globalMods), callback); }); }); @@ -624,6 +626,9 @@ Flags.notify = function (flagObj, uid, callback) { return callback(err); } + plugins.fireHook('action:flag.create', { + flag: flagObj + }); notifications.push(notification, results.admins.concat(results.globalMods), callback); }); }); diff --git a/src/plugins/hooks.js b/src/plugins/hooks.js index b8e5af0e46..b5a32ba1b7 100644 --- a/src/plugins/hooks.js +++ b/src/plugins/hooks.js @@ -7,7 +7,8 @@ module.exports = function (Plugins) { Plugins.deprecatedHooks = { 'filter:user.custom_fields': null, // remove in v1.1.0 'filter:post.save': 'filter:post.create', - 'filter:user.profileLinks': 'filter:user.profileMenu' + 'filter:user.profileLinks': 'filter:user.profileMenu', + 'action:post.flag': 'action:flag.create' }; /* `data` is an object consisting of (* is required): From e40eb75f8f66a04811d64943426e1ff18c3f453c Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 7 Dec 2016 15:13:40 -0500 Subject: [PATCH 028/122] change history saving to append an object not a serialised array, #5232 --- src/flags.js | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/src/flags.js b/src/flags.js index bfbe80992a..1655361b0e 100644 --- a/src/flags.js +++ b/src/flags.js @@ -422,7 +422,6 @@ Flags.getTargetUid = function (type, id, callback) { Flags.update = function (flagId, uid, changeset, callback) { // Retrieve existing flag data to compare for history-saving purposes var fields = ['state', 'assignee']; - var history = []; var tasks = []; var now = Date.now(); @@ -445,9 +444,6 @@ Flags.update = function (flagId, uid, changeset, callback) { tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byAssignee:' + changeset[prop], now, flagId)); break; } - - // Append to history payload - history.push(prop + ':' + changeset[prop]); } } } @@ -460,7 +456,7 @@ Flags.update = function (flagId, uid, changeset, callback) { // Save new object to db (upsert) tasks.push(async.apply(db.setObject, 'flag:' + flagId, changeset)); // Append history - tasks.push(async.apply(Flags.appendHistory, flagId, uid, history)); + tasks.push(async.apply(Flags.appendHistory, flagId, uid, changeset)); async.parallel(tasks, function (err, data) { return next(err); @@ -484,28 +480,21 @@ Flags.getHistory = function (flagId, callback) { uids.push(entry.value[0]); - // Deserialise field object - var fields = entry.value[1].map(function (field) { - field = field.toString().split(':'); - - switch (field[0]) { - case 'state': - field[1] = field[1] === undefined ? null : '[[flags:state-' + field[1] + ']]'; - break; - - default: - field[1] = field[1] === undefined ? null : field[1]; - break; - } - return { - "attribute": field[0], - "value": field[1] - }; - }); + // Deserialise changeset + var changeset = entry.value[1]; + if (changeset.hasOwnProperty('state')) { + changeset.state = changeset.state === undefined ? '' : '[[flags:state-' + changeset.state + ']]'; + } + if (changeset.hasOwnProperty('assignee')) { + changeset.assignee = changeset.assignee || ''; + } + if (changeset.hasOwnProperty('notes')) { + changeset.notes = changeset.notes || ''; + } return { uid: entry.value[0], - fields: fields, + fields: changeset, datetime: entry.score, datetimeISO: new Date(entry.score).toISOString() }; @@ -549,7 +538,9 @@ Flags.appendNote = function (flagId, uid, note, callback) { async.waterfall([ async.apply(db.sortedSetAdd, 'flag:' + flagId + ':notes', Date.now(), payload), - async.apply(Flags.appendHistory, flagId, uid, ['notes']) + async.apply(Flags.appendHistory, flagId, uid, { + notes: null + }) ], callback); }; From 6533fa066d219c05ad295a884d526e8fabf586ce Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 7 Dec 2016 15:42:47 -0500 Subject: [PATCH 029/122] removed unneeded fixes #5232 --- src/flags.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/flags.js b/src/flags.js index 1655361b0e..aafae593e0 100644 --- a/src/flags.js +++ b/src/flags.js @@ -485,12 +485,6 @@ Flags.getHistory = function (flagId, callback) { if (changeset.hasOwnProperty('state')) { changeset.state = changeset.state === undefined ? '' : '[[flags:state-' + changeset.state + ']]'; } - if (changeset.hasOwnProperty('assignee')) { - changeset.assignee = changeset.assignee || ''; - } - if (changeset.hasOwnProperty('notes')) { - changeset.notes = changeset.notes || ''; - } return { uid: entry.value[0], From 31996f9377a8142ec9be92164905f182ab0bcc45 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 7 Dec 2016 15:51:05 -0500 Subject: [PATCH 030/122] added page titles --- public/language/en-GB/pages.json | 3 +++ src/controllers/mods.js | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/public/language/en-GB/pages.json b/public/language/en-GB/pages.json index 104e2249f2..5efa686fc3 100644 --- a/public/language/en-GB/pages.json +++ b/public/language/en-GB/pages.json @@ -32,6 +32,9 @@ "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", + "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 656605f277..62f7b6dd07 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -43,7 +43,8 @@ modsController.flags.list = function (req, res, next) { res.render('flags/list', { flags: flags, hasFilter: !!Object.keys(filters).length, - filters: filters + filters: filters, + title: '[[pages:flags]]' }); }); }); @@ -67,7 +68,8 @@ modsController.flags.detail = function (req, res, next) { type_bool: ['post', 'user'].reduce(function (memo, cur) { memo[cur] = results.flagData.type === cur; return memo; - }, {}) + }, {}), + title: '[[pages:flag-details, ' + req.params.flagId + ']]' })); }); }; From ebc9abd7730bac3366dd4599b5a365c58a7c5697 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 9 Dec 2016 14:33:59 -0500 Subject: [PATCH 031/122] upgrade script and graphs for #5232 --- public/src/client/flags/list.js | 51 +++++++- src/controllers/mods.js | 9 +- src/flags.js | 49 +++++--- src/upgrade.js | 87 +++++++++++++- src/views/admin/manage/flags.tpl | 196 ------------------------------- 5 files changed, 177 insertions(+), 215 deletions(-) delete mode 100644 src/views/admin/manage/flags.tpl diff --git a/public/src/client/flags/list.js b/public/src/client/flags/list.js index bf8b4bc1a8..7647e1db6d 100644 --- a/public/src/client/flags/list.js +++ b/public/src/client/flags/list.js @@ -2,12 +2,13 @@ /* globals define */ -define('forum/flags/list', ['components'], function (components) { +define('forum/flags/list', ['components', 'Chart'], function (components, Chart) { var Flags = {}; Flags.init = function () { Flags.enableFilterForm(); Flags.enableChatButtons(); + Flags.handleGraphs(); }; Flags.enableFilterForm = function () { @@ -38,5 +39,53 @@ define('forum/flags/list', ['components'], function (components) { }); }; + Flags.handleGraphs = function () { + var dailyCanvas = document.getElementById('flags:daily'); + var dailyLabels = utils.getDaysArray().map(function (text, idx) { + return idx % 3 ? '' : text; + }); + + if (utils.isMobile()) { + Chart.defaults.global.tooltips.enabled = false; + } + var data = { + 'flags:daily': { + labels: dailyLabels, + datasets: [ + { + label: "", + backgroundColor: "rgba(151,187,205,0.2)", + borderColor: "rgba(151,187,205,1)", + pointBackgroundColor: "rgba(151,187,205,1)", + pointHoverBackgroundColor: "#fff", + pointBorderColor: "#fff", + pointHoverBorderColor: "rgba(151,187,205,1)", + data: ajaxify.data.analytics + } + ] + } + }; + + dailyCanvas.width = $(dailyCanvas).parent().width(); + new Chart(dailyCanvas.getContext('2d'), { + type: 'line', + data: data['flags:daily'], + options: { + responsive: true, + animation: false, + legend: { + display: false + }, + scales: { + yAxes: [{ + ticks: { + beginAtZero: true + } + }] + } + } + }); + }; + return Flags; }); diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 62f7b6dd07..39820e60a6 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -4,6 +4,7 @@ var async = require('async'); var user = require('../user'); var flags = require('../flags'); +var analytics = require('../analytics'); // var adminFlagsController = require('./admin/flags'); var modsController = { @@ -35,13 +36,17 @@ modsController.flags.list = function (req, res, next) { return memo; }, {}); - flags.list(filters, req.uid, function (err, flags) { + async.parallel({ + flags: async.apply(flags.list, filters, req.uid), + analytics: async.apply(analytics.getDailyStatsForSet, 'analytics:flags', Date.now(), 30) + }, function (err, data) { if (err) { return next(err); } res.render('flags/list', { - flags: flags, + flags: data.flags, + analytics: data.analytics, hasFilter: !!Object.keys(filters).length, filters: filters, title: '[[pages:flags]]' diff --git a/src/flags.js b/src/flags.js index aafae593e0..7c56ba4fb5 100644 --- a/src/flags.js +++ b/src/flags.js @@ -267,8 +267,16 @@ Flags.getNotes = function (flagId, callback) { ], callback); }; -Flags.create = function (type, id, uid, reason, callback) { +Flags.create = function (type, id, uid, reason, timestamp, callback) { var targetUid; + var doHistoryAppend = false; + + // timestamp is optional + if (typeof timestamp === 'function' && !callback) { + callback = timestamp; + timestamp = Date.now(); + doHistoryAppend = true; + } async.waterfall([ function (next) { @@ -302,16 +310,17 @@ Flags.create = function (type, id, uid, reason, callback) { targetId: id, description: reason, uid: uid, - datetime: Date.now() + datetime: timestamp }), - async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', Date.now(), flagId), // by time, the default - async.apply(db.sortedSetAdd.bind(db), 'flags:byReporter:' + uid, Date.now(), flagId), // by reporter - async.apply(db.sortedSetAdd.bind(db), 'flags:byType:' + type, Date.now(), flagId), // by flag type - async.apply(db.setObjectField.bind(db), 'flagHash:flagId', [type, id, uid].join(':'), flagId) // save hash for existence checking + async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', timestamp, flagId), // by time, the default + async.apply(db.sortedSetAdd.bind(db), 'flags:byReporter:' + uid, timestamp, flagId), // by reporter + async.apply(db.sortedSetAdd.bind(db), 'flags:byType:' + type, timestamp, flagId), // by flag type + async.apply(db.setObjectField.bind(db), 'flagHash:flagId', [type, id, uid].join(':'), flagId), // save hash for existence checking + async.apply(analytics.increment, 'flags') // some fancy analytics ]; if (targetUid) { - tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byTargetUid:' + targetUid, Date.now(), flagId)); // by target uid + tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byTargetUid:' + targetUid, timestamp, flagId)); // by target uid } async.parallel(tasks, function (err, data) { @@ -319,7 +328,10 @@ Flags.create = function (type, id, uid, reason, callback) { return next(err); } - Flags.update(flagId, uid, { "state": "open" }); + if (doHistoryAppend) { + Flags.update(flagId, uid, { "state": "open" }); + } + next(null, flagId); }); }, @@ -423,7 +435,7 @@ Flags.update = function (flagId, uid, changeset, callback) { // Retrieve existing flag data to compare for history-saving purposes var fields = ['state', 'assignee']; var tasks = []; - var now = Date.now(); + var now = changeset.datetime || Date.now(); async.waterfall([ async.apply(db.getObjectFields.bind(db), 'flag:' + flagId, fields), @@ -513,16 +525,24 @@ Flags.getHistory = function (flagId, callback) { Flags.appendHistory = function (flagId, uid, changeset, callback) { var payload; + var datetime = changeset.datetime || Date.now(); + delete changeset.datetime; + try { - payload = JSON.stringify([uid, changeset, Date.now()]); + payload = JSON.stringify([uid, changeset, datetime]); } catch (e) { return callback(e); } - db.sortedSetAdd('flag:' + flagId + ':history', Date.now(), payload, callback); + db.sortedSetAdd('flag:' + flagId + ':history', datetime, payload, callback); }; -Flags.appendNote = function (flagId, uid, note, callback) { +Flags.appendNote = function (flagId, uid, note, datetime, callback) { + if (typeof datetime === 'function' && !callback) { + callback = datetime; + datetime = Date.now(); + } + var payload; try { payload = JSON.stringify([uid, note]); @@ -531,9 +551,10 @@ Flags.appendNote = function (flagId, uid, note, callback) { } async.waterfall([ - async.apply(db.sortedSetAdd, 'flag:' + flagId + ':notes', Date.now(), payload), + async.apply(db.sortedSetAdd, 'flag:' + flagId + ':notes', datetime, payload), async.apply(Flags.appendHistory, flagId, uid, { - notes: null + notes: null, + datetime: datetime }) ], callback); }; diff --git a/src/upgrade.js b/src/upgrade.js index 2a605e84f9..29b806d4a7 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -12,7 +12,7 @@ var db = require('./database'), schemaDate, thisSchemaDate, // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema - latestSchema = Date.UTC(2016, 10, 22); + latestSchema = Date.UTC(2016, 11, 7); Upgrade.check = function (callback) { db.get('schemaDate', function (err, value) { @@ -1023,7 +1023,7 @@ Upgrade.upgrade = function (callback) { if (schemaDate < thisSchemaDate) { updatesMade = true; - winston.info('[2016/11/25] Creating sorted sets for pinned topcis'); + winston.info('[2016/11/25] Creating sorted sets for pinned topics'); var topics = require('./topics'); var batch = require('./batch'); @@ -1060,6 +1060,89 @@ Upgrade.upgrade = function (callback) { next(); } }, + function (next) { + thisSchemaDate = Date.UTC(2016, 11, 7); + + if (schemaDate < thisSchemaDate) { + updatesMade = true; + winston.info('[2016/12/07] Migrating flags to new schema (#5232)'); + + var batch = require('./batch'); + var posts = require('./posts'); + var flags = require('./flags'); + var migrated = 0; + + batch.processSortedSet('posts:pid', function (ids, next) { + posts.getPostsByPids(ids, 1, function (err, posts) { + if (err) { + return next(err); + } + + posts = posts.filter(function (post) { + return post.hasOwnProperty('flags'); + }); + + async.each(posts, function (post, next) { + async.parallel({ + uids: async.apply(db.getSortedSetRangeWithScores, 'pid:' + post.pid + ':flag:uids', 0, -1), + reasons: async.apply(db.getSortedSetRange, 'pid:' + post.pid + ':flag:uid:reason', 0, -1) + }, function (err, data) { + if (err) { + return next(err); + } + + // Just take the first entry + var datetime = data.uids[0].score; + var reason = data.reasons[0].split(':')[1]; + var flagObj; + + async.waterfall([ + async.apply(flags.create, 'post', post.pid, data.uids[0].value, reason, datetime), + function (_flagObj, next) { + flagObj = _flagObj; + if (post['flag:state'] || post['flag:assignee']) { + flags.update(flagObj.flagId, 1, { + state: post['flag:state'], + assignee: post['flag:assignee'], + datetime: datetime + }, next); + } else { + setImmediate(next); + } + }, + function (next) { + if (post.hasOwnProperty('flag:notes') && post['flag:notes'].length) { + try { + var history = JSON.parse(post['flag:history']); + history = history.filter(function (event) { + return event.type === 'notes'; + })[0]; + + flags.appendNote(flagObj.flagId, history.uid, post['flag:notes'], history.timestamp, next); + } catch (e) { + next(e); + } + } else { + setImmediate(next); + } + } + ], next); + }); + }, next); + }); + }, function (err) { + if (err) { + return next(err); + } + + winston.info('[2016/12/07] Migrating flags to new schema (#5232) - done'); + Upgrade.update(thisSchemaDate, next); + }); + } else { + winston.info('[2016/12/07] Migrating flags to new schema (#5232) - skipped!'); + next(); + } + } // Add new schema updates here // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 24!!! ], function (err) { diff --git a/src/views/admin/manage/flags.tpl b/src/views/admin/manage/flags.tpl deleted file mode 100644 index a14348ba42..0000000000 --- a/src/views/admin/manage/flags.tpl +++ /dev/null @@ -1,196 +0,0 @@ -
    - -
    - -
    -
    -
    -
    -

    - -

    -
    - -
    -
    - - - -
    - -
    - -
    - -
    - No flagged posts! -
    - - - -
    - -
    -
    -
    -
    -
    - - - - -
    {../user.icon:text}
    - -
    - - - {../user.username} - -
    -

    {posts.content}

    -
    - - - Posted in {posts.category.name}, • - Read More - - -
    -
    -
    - This post has been flagged {posts.flags} time(s): -
    - -
    -
    - - -
    -
    -
    -
    -
    -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    - -
    -
    -
    -
    [[topic:flag_manage_history]]
    - -
    [[topic:flag_manage_no_history]]
    - -
      - -
    • -
      - - - -
      {../user.icon:text}
      - - [[topic:flag_manage_history_{posts.flagData.history.type}, {posts.flagData.history.label}]] -
    • - -
    - -
    -
    -
    -
    -
    - - -
    -
    -
    -
    From 9ada35cfb982ca332e9c097e06588bb0e986046f Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 9 Dec 2016 14:39:31 -0500 Subject: [PATCH 032/122] allowing Analytics.increment to have a callback --- src/analytics.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/analytics.js b/src/analytics.js index 6b248057da..9151bd6ce7 100644 --- a/src/analytics.js +++ b/src/analytics.js @@ -20,13 +20,17 @@ new cronJob('*/10 * * * *', function () { Analytics.writeData(); }, null, true); -Analytics.increment = function (keys) { +Analytics.increment = function (keys, callback) { keys = Array.isArray(keys) ? keys : [keys]; keys.forEach(function (key) { counters[key] = counters[key] || 0; ++counters[key]; }); + + if (typeof callback === 'function') { + callback(); + } }; Analytics.pageView = function (payload) { From 47530423066c778983d7d00caa0073a1fb72d5c9 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 9 Dec 2016 14:53:49 -0500 Subject: [PATCH 033/122] lowered analytics disk writes to every ten seconds, because why every 10 minutes? :shipit: --- src/analytics.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analytics.js b/src/analytics.js index 9151bd6ce7..c6cfbeba7e 100644 --- a/src/analytics.js +++ b/src/analytics.js @@ -16,7 +16,7 @@ var uniquevisitors = 0; var isCategory = /^(?:\/api)?\/category\/(\d+)/; -new cronJob('*/10 * * * *', function () { +new cronJob('*/10 * * * * *', function () { Analytics.writeData(); }, null, true); From aaec71bc0ca1d3613a07f6906b8d951ae4e60fab Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 9 Dec 2016 14:59:23 -0500 Subject: [PATCH 034/122] added stepSize to flags chart, #5232 --- public/src/client/flags/list.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/src/client/flags/list.js b/public/src/client/flags/list.js index 7647e1db6d..255c7176f1 100644 --- a/public/src/client/flags/list.js +++ b/public/src/client/flags/list.js @@ -79,7 +79,8 @@ define('forum/flags/list', ['components', 'Chart'], function (components, Chart) scales: { yAxes: [{ ticks: { - beginAtZero: true + beginAtZero: true, + stepSize: 1 } }] } From 01969970995810602d26ff25ebc9ea8e38760a3e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 13 Dec 2016 09:36:46 -0500 Subject: [PATCH 035/122] fixing issues as found by @barisusakli re: #5232 and #5282 --- src/flags.js | 89 +++++++--------------------------------------------- 1 file changed, 11 insertions(+), 78 deletions(-) diff --git a/src/flags.js b/src/flags.js index 7c56ba4fb5..1fb2986d2b 100644 --- a/src/flags.js +++ b/src/flags.js @@ -139,13 +139,7 @@ Flags.list = function (filters, uid, callback) { }); }, next); } - ], function (err, flags) { - if (err) { - return callback(err); - } - - return callback(null, flags); - }); + ], callback); }; Flags.validate = function (payload, callback) { @@ -166,16 +160,14 @@ Flags.validate = function (payload, callback) { switch (payload.type) { case 'post': - async.parallel({ - editable: async.apply(privileges.posts.canEdit, payload.id, payload.uid) - }, function (err, subdata) { + privileges.posts.canEdit(payload.id, payload.uid, function (err, editable) { if (err) { return callback(err); } var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1; // Check if reporter meets rep threshold (or can edit the target post, in which case threshold does not apply) - if (!subdata.editable.flag && parseInt(data.reporter.reputation, 10) < minimumReputation) { + if (!editable.flag && parseInt(data.reporter.reputation, 10) < minimumReputation) { return callback(new Error('[[error:not-enough-reputation-to-flag]]')); } @@ -184,17 +176,14 @@ Flags.validate = function (payload, callback) { break; case 'user': - async.parallel({ - editable: async.apply(privileges.users.canEdit, payload.uid, payload.id) - }, function (err, subdata) { + privileges.users.canEdit(payload.uid, payload.id, function (err, editable) { if (err) { return callback(err); } - var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1; // Check if reporter meets rep threshold (or can edit the target user, in which case threshold does not apply) - if (!subdata.editable && parseInt(data.reporter.reputation, 10) < minimumReputation) { + if (!editable && parseInt(data.reporter.reputation, 10) < minimumReputation) { return callback(new Error('[[error:not-enough-reputation-to-flag]]')); } @@ -227,6 +216,10 @@ Flags.getTarget = function (type, id, uid, callback) { callback(err, users ? users[0] : undefined); }); break; + + default: + callback(new Error('[[error:invalid-data]]')); + break; } }; @@ -315,7 +308,7 @@ Flags.create = function (type, id, uid, reason, timestamp, callback) { async.apply(db.sortedSetAdd.bind(db), 'flags:datetime', timestamp, flagId), // by time, the default async.apply(db.sortedSetAdd.bind(db), 'flags:byReporter:' + uid, timestamp, flagId), // by reporter async.apply(db.sortedSetAdd.bind(db), 'flags:byType:' + type, timestamp, flagId), // by flag type - async.apply(db.setObjectField.bind(db), 'flagHash:flagId', [type, id, uid].join(':'), flagId), // save hash for existence checking + async.apply(db.sortedSetAdd.bind(db), 'flags:hash', flagId, [type, id, uid].join(':')), // save zset for duplicate checking async.apply(analytics.increment, 'flags') // some fancy analytics ]; @@ -337,70 +330,10 @@ Flags.create = function (type, id, uid, reason, timestamp, callback) { }, async.apply(Flags.get) ], callback); - // if (!parseInt(uid, 10) || !reason) { - // return callback(); - // } - - // async.waterfall([ - // function (next) { - // async.parallel({ - // hasFlagged: async.apply(Flags.isFlaggedByUser, post.pid, uid), - // exists: async.apply(Posts.exists, post.pid) - // }, next); - // }, - // function (results, next) { - // if (!results.exists) { - // return next(new Error('[[error:no-post]]')); - // } - - // if (results.hasFlagged) { - // return next(new Error('[[error:already-flagged]]')); - // } - - // var now = Date.now(); - // async.parallel([ - // function (next) { - // db.sortedSetAdd('posts:flagged', now, post.pid, next); - // }, - // function (next) { - // db.sortedSetIncrBy('posts:flags:count', 1, post.pid, next); - // }, - // function (next) { - // db.incrObjectField('post:' + post.pid, 'flags', next); - // }, - // function (next) { - // db.sortedSetAdd('pid:' + post.pid + ':flag:uids', now, uid, next); - // }, - // function (next) { - // db.sortedSetAdd('pid:' + post.pid + ':flag:uid:reason', 0, uid + ':' + reason, next); - // }, - // function (next) { - // if (parseInt(post.uid, 10)) { - // async.parallel([ - // async.apply(db.sortedSetIncrBy, 'users:flags', 1, post.uid), - // async.apply(db.incrObjectField, 'user:' + post.uid, 'flags'), - // async.apply(db.sortedSetAdd, 'uid:' + post.uid + ':flag:pids', now, post.pid) - // ], next); - // } else { - // next(); - // } - // } - // ], next); - // }, - // function (data, next) { - // openNewFlag(post.pid, uid, next); // removed, used to just update flag to open state if new flag - // } - // ], function (err) { - // if (err) { - // return callback(err); - // } - // analytics.increment('flags'); - // callback(); - // }); }; Flags.exists = function (type, id, uid, callback) { - db.isObjectField('flagHash:flagId', [type, id, uid].join(':'), callback); + db.isSortedSetMember('flags:hash', [type, id, uid].join(':'), callback); }; Flags.targetExists = function (type, id, callback) { From 831c2064a0435eb07c5bb3d010753dc0416e6166 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 13 Dec 2016 12:11:51 -0500 Subject: [PATCH 036/122] For #5232, added tests and returning flag data on socket flag creation --- src/flags.js | 4 + src/socket.io/flags.js | 12 +- test/flags.js | 558 +++++++++++++++++++++++------------------ 3 files changed, 331 insertions(+), 243 deletions(-) diff --git a/src/flags.js b/src/flags.js index 1fb2986d2b..1ae5a84ed8 100644 --- a/src/flags.js +++ b/src/flags.js @@ -494,6 +494,10 @@ Flags.appendNote = function (flagId, uid, note, datetime, callback) { Flags.notify = function (flagObj, uid, callback) { // Notify administrators, mods, and other associated people + if (!callback) { + callback = function () {}; + } + switch (flagObj.type) { case 'post': async.parallel({ diff --git a/src/socket.io/flags.js b/src/socket.io/flags.js index ce148faa87..c25bd662fa 100644 --- a/src/socket.io/flags.js +++ b/src/socket.io/flags.js @@ -34,11 +34,15 @@ SocketFlags.create = function (socket, data, callback) { function (next) { // If we got here, then no errors occurred flags.create(data.type, data.id, socket.uid, data.reason, next); - }, - function (flagObj, next) { - flags.notify(flagObj, socket.uid, next); } - ], callback); + ], function (err, flagObj) { + if (err) { + return callback(err); + } + + flags.notify(flagObj, socket.uid); + callback(null, flagObj); + }); }; SocketFlags.update = function (socket, data, callback) { diff --git a/test/flags.js b/test/flags.js index 14bb1e65c6..8d359c6930 100644 --- a/test/flags.js +++ b/test/flags.js @@ -10,6 +10,7 @@ var Categories = require('../src/categories'); var Topics = require('../src/topics'); var Posts = require('../src/posts'); var User = require('../src/user'); +var Groups = require('../src/groups'); var Meta = require('../src/meta'); describe('Flags', function () { @@ -37,296 +38,375 @@ describe('Flags', function () { User.create({ username: 'testUser2', password: 'abcdef', email: 'c@d.com' }, next); + }, + function (uid, next) { + Groups.join('administrators', uid, next); } ], done); }); - describe('.create()', function () { - it('should create a flag and return its data', function (done) { - Flags.create('post', 1, 1, 'Test flag', function (err, flagData) { - assert.ifError(err); - var compare = { - flagId: 1, - uid: 1, - targetId: 1, - type: 'post', - description: 'Test flag' - }; + // describe('.create()', function () { + // it('should create a flag and return its data', function (done) { + // Flags.create('post', 1, 1, 'Test flag', function (err, flagData) { + // assert.ifError(err); + // var compare = { + // flagId: 1, + // uid: 1, + // targetId: 1, + // type: 'post', + // description: 'Test flag' + // }; - for(var key in compare) { - if (compare.hasOwnProperty(key)) { - assert.ok(flagData[key]); - assert.strictEqual(flagData[key], compare[key]); - } - } + // for(var key in compare) { + // if (compare.hasOwnProperty(key)) { + // assert.ok(flagData[key]); + // assert.strictEqual(flagData[key], compare[key]); + // } + // } - done(); - }); - }); - }); + // done(); + // }); + // }); + // }); - describe('.get()', function () { - it('should retrieve and display a flag\'s data', function (done) { - Flags.get(1, function (err, flagData) { - assert.ifError(err); - var compare = { - flagId: 1, - uid: 1, - targetId: 1, - type: 'post', - description: 'Test flag', - state: 'open' - }; + // describe('.get()', function () { + // it('should retrieve and display a flag\'s data', function (done) { + // Flags.get(1, function (err, flagData) { + // assert.ifError(err); + // var compare = { + // flagId: 1, + // uid: 1, + // targetId: 1, + // type: 'post', + // description: 'Test flag', + // state: 'open' + // }; - for(var key in compare) { - if (compare.hasOwnProperty(key)) { - assert.ok(flagData[key]); - assert.strictEqual(flagData[key], compare[key]); - } - } + // for(var key in compare) { + // if (compare.hasOwnProperty(key)) { + // assert.ok(flagData[key]); + // assert.strictEqual(flagData[key], compare[key]); + // } + // } - done(); - }); - }); - }); + // done(); + // }); + // }); + // }); - describe('.list()', function () { - it('should show a list of flags (with one item)', function (done) { - Flags.list({}, 1, function (err, flags) { - assert.ifError(err); - assert.ok(Array.isArray(flags)); - assert.equal(flags.length, 1); + // describe('.list()', function () { + // it('should show a list of flags (with one item)', function (done) { + // Flags.list({}, 1, function (err, flags) { + // assert.ifError(err); + // assert.ok(Array.isArray(flags)); + // assert.equal(flags.length, 1); - Flags.get(flags[0].flagId, function (err, flagData) { - assert.ifError(err); - assert.equal(flags[0].flagId, flagData.flagId); - assert.equal(flags[0].description, flagData.description); - done(); - }); - }); - }); - }); + // Flags.get(flags[0].flagId, function (err, flagData) { + // assert.ifError(err); + // assert.equal(flags[0].flagId, flagData.flagId); + // assert.equal(flags[0].description, flagData.description); + // done(); + // }); + // }); + // }); + // }); - describe('.update()', function () { - it('should alter a flag\'s various attributes and persist them to the database', function (done) { - Flags.update(1, 1, { - "state": "wip", - "assignee": 1 - }, function (err) { - assert.ifError(err); - db.getObjectFields('flag:1', ['state', 'assignee'], function (err, data) { - if (err) { - throw err; - } + // describe('.update()', function () { + // it('should alter a flag\'s various attributes and persist them to the database', function (done) { + // Flags.update(1, 1, { + // "state": "wip", + // "assignee": 1 + // }, function (err) { + // assert.ifError(err); + // db.getObjectFields('flag:1', ['state', 'assignee'], function (err, data) { + // if (err) { + // throw err; + // } - assert.strictEqual('wip', data.state); - assert.strictEqual(1, data.assignee); - done(); - }); - }); - }); + // assert.strictEqual('wip', data.state); + // assert.strictEqual(1, data.assignee); + // done(); + // }); + // }); + // }); - it('should persist to the flag\'s history', function (done) { - Flags.getHistory(1, function (err, history) { - if (err) { - throw err; - } + // it('should persist to the flag\'s history', function (done) { + // Flags.getHistory(1, function (err, history) { + // if (err) { + // throw err; + // } - history.forEach(function (change) { - switch (change.attribute) { - case 'state': - assert.strictEqual('[[flags:state-wip]]', change.value); - break; + // history.forEach(function (change) { + // switch (change.attribute) { + // case 'state': + // assert.strictEqual('[[flags:state-wip]]', change.value); + // break; - case 'assignee': - assert.strictEqual(1, change.value); - break; - } - }); + // case 'assignee': + // assert.strictEqual(1, change.value); + // break; + // } + // }); - done(); - }); - }); - }); + // done(); + // }); + // }); + // }); - describe('.getTarget()', function () { - it('should return a post\'s data if queried with type "post"', function (done) { - Flags.getTarget('post', 1, 1, function (err, data) { - assert.ifError(err); - var compare = { - uid: 1, - pid: 1, - content: 'This is flaggable content' - }; + // describe('.getTarget()', function () { + // it('should return a post\'s data if queried with type "post"', function (done) { + // Flags.getTarget('post', 1, 1, function (err, data) { + // assert.ifError(err); + // var compare = { + // uid: 1, + // pid: 1, + // content: 'This is flaggable content' + // }; - for(var key in compare) { - if (compare.hasOwnProperty(key)) { - assert.ok(data[key]); - assert.strictEqual(data[key], compare[key]); - } - } + // for(var key in compare) { + // if (compare.hasOwnProperty(key)) { + // assert.ok(data[key]); + // assert.strictEqual(data[key], compare[key]); + // } + // } - done(); - }); - }); + // done(); + // }); + // }); - it('should return a user\'s data if queried with type "user"', function (done) { - Flags.getTarget('user', 1, 1, function (err, data) { - assert.ifError(err); - var compare = { - uid: 1, - username: 'testUser', - email: 'b@c.com' - }; + // it('should return a user\'s data if queried with type "user"', function (done) { + // Flags.getTarget('user', 1, 1, function (err, data) { + // assert.ifError(err); + // var compare = { + // uid: 1, + // username: 'testUser', + // email: 'b@c.com' + // }; - for(var key in compare) { - if (compare.hasOwnProperty(key)) { - assert.ok(data[key]); - assert.strictEqual(data[key], compare[key]); - } - } + // for(var key in compare) { + // if (compare.hasOwnProperty(key)) { + // assert.ok(data[key]); + // assert.strictEqual(data[key], compare[key]); + // } + // } - done(); - }); - }); - }); + // done(); + // }); + // }); + // }); - describe('.validate()', function () { - it('should error out if type is post and post is deleted', function (done) { - Posts.delete(1, 1, function (err) { - if (err) { - throw err; - } + // describe('.validate()', function () { + // it('should error out if type is post and post is deleted', function (done) { + // Posts.delete(1, 1, function (err) { + // if (err) { + // throw err; + // } - Flags.validate({ - type: 'post', - id: 1, - uid: 1 - }, function (err) { - assert.ok(err); - assert.strictEqual('[[error:post-deleted]]', err.message); - Posts.restore(1, 1, done); - }); - }); - }); + // Flags.validate({ + // type: 'post', + // id: 1, + // uid: 1 + // }, function (err) { + // assert.ok(err); + // assert.strictEqual('[[error:post-deleted]]', err.message); + // Posts.restore(1, 1, done); + // }); + // }); + // }); - it('should not pass validation if flag threshold is set and user rep does not meet it', function (done) { - Meta.configs.set('privileges:flag', '50', function (err) { - assert.ifError(err); + // it('should not pass validation if flag threshold is set and user rep does not meet it', function (done) { + // Meta.configs.set('privileges:flag', '50', function (err) { + // assert.ifError(err); - Flags.validate({ - type: 'post', - id: 1, - uid: 2 - }, function (err) { - assert.ok(err); - assert.strictEqual('[[error:not-enough-reputation-to-flag]]', err.message); - Meta.configs.set('privileges:flag', 0, done); - }); - }); - }); - }); + // Flags.validate({ + // type: 'post', + // id: 1, + // uid: 2 + // }, function (err) { + // assert.ok(err); + // assert.strictEqual('[[error:not-enough-reputation-to-flag]]', err.message); + // Meta.configs.set('privileges:flag', 0, done); + // }); + // }); + // }); + // }); - describe('.appendNote()', function () { - it('should add a note to a flag', function (done) { - Flags.appendNote(1, 1, 'this is my note', function (err) { - assert.ifError(err); + // describe('.appendNote()', function () { + // it('should add a note to a flag', function (done) { + // Flags.appendNote(1, 1, 'this is my note', function (err) { + // assert.ifError(err); - db.getSortedSetRange('flag:1:notes', 0, -1, function (err, notes) { - if (err) { - throw err; - } + // db.getSortedSetRange('flag:1:notes', 0, -1, function (err, notes) { + // if (err) { + // throw err; + // } - assert.strictEqual('[1,"this is my note"]', notes[0]); - done(); - }); - }); - }); + // assert.strictEqual('[1,"this is my note"]', notes[0]); + // done(); + // }); + // }); + // }); - it('should be a JSON string', function (done) { - db.getSortedSetRange('flag:1:notes', 0, -1, function (err, notes) { - if (err) { - throw err; - } + // it('should be a JSON string', function (done) { + // db.getSortedSetRange('flag:1:notes', 0, -1, function (err, notes) { + // if (err) { + // throw err; + // } - try { - JSON.parse(notes[0]); - } catch (e) { - assert.ifError(e); - } + // try { + // JSON.parse(notes[0]); + // } catch (e) { + // assert.ifError(e); + // } - done(); - }); - }); - }); + // done(); + // }); + // }); + // }); - describe('.getNotes()', function () { - before(function (done) { - // Add a second note - Flags.appendNote(1, 1, 'this is the second note', done); - }); + // describe('.getNotes()', function () { + // before(function (done) { + // // Add a second note + // Flags.appendNote(1, 1, 'this is the second note', done); + // }); - it('return should match a predefined spec', function (done) { - Flags.getNotes(1, function (err, notes) { - assert.ifError(err); - var compare = { - uid: 1, - content: 'this is my note' - }; + // it('return should match a predefined spec', function (done) { + // Flags.getNotes(1, function (err, notes) { + // assert.ifError(err); + // var compare = { + // uid: 1, + // content: 'this is my note' + // }; - var data = notes[1]; - for(var key in compare) { - if (compare.hasOwnProperty(key)) { - assert.ok(data[key]); - assert.strictEqual(data[key], compare[key]); - } - } + // var data = notes[1]; + // for(var key in compare) { + // if (compare.hasOwnProperty(key)) { + // assert.ok(data[key]); + // assert.strictEqual(data[key], compare[key]); + // } + // } - done(); - }); - }); + // done(); + // }); + // }); - it('should retrieve a list of notes, from newest to oldest', function (done) { - Flags.getNotes(1, function (err, notes) { - assert.ifError(err); - assert(notes[0].datetime > notes[1].datetime); - assert.strictEqual('this is the second note', notes[0].content); - done(); - }); - }); - }); + // it('should retrieve a list of notes, from newest to oldest', function (done) { + // Flags.getNotes(1, function (err, notes) { + // assert.ifError(err); + // assert(notes[0].datetime > notes[1].datetime); + // assert.strictEqual('this is the second note', notes[0].content); + // done(); + // }); + // }); + // }); + + // describe('.appendHistory()', function () { + // var entries; + // before(function (done) { + // db.sortedSetCard('flag:1:history', function (err, count) { + // entries = count; + // done(err); + // }); + // }); + + // it('should add a new entry into a flag\'s history', function (done) { + // Flags.appendHistory(1, 1, ['state:rejected'], function (err) { + // assert.ifError(err); + + // Flags.getHistory(1, function (err, history) { + // if (err) { + // throw err; + // } + + // assert.strictEqual(entries + 1, history.length); + // done(); + // }); + // }); + // }); + // }); + + // describe('.getHistory()', function () { + // it('should retrieve a flag\'s history', function (done) { + // Flags.getHistory(1, function (err, history) { + // assert.ifError(err); + // assert.strictEqual(history[0].fields[0].value, '[[flags:state-rejected]]'); + // done(); + // }); + // }); + // }); + + describe('(websockets)', function () { + var SocketFlags = require('../src/socket.io/flags.js'); + var tid, pid, flag; - describe('.appendHistory()', function () { - var entries; before(function (done) { - db.sortedSetCard('flag:1:history', function (err, count) { - entries = count; + Topics.post({ + cid: 1, + uid: 1, + title: 'Another topic', + content: 'This is flaggable content' + }, function (err, topic) { + tid = topic.postData.tid; + pid = topic.postData.pid; + done(err); }); }); - it('should add a new entry into a flag\'s history', function (done) { - Flags.appendHistory(1, 1, ['state:rejected'], function (err) { - assert.ifError(err); + describe('.create()', function () { + it('should create a flag with no errors', function (done) { + SocketFlags.create({ uid: 2 }, { + type: 'post', + id: pid, + reason: 'foobar' + }, function (err, flagObj) { + flag = flagObj; + assert.ifError(err); - Flags.getHistory(1, function (err, history) { - if (err) { - throw err; - } + Flags.exists('post', pid, 1, function (err, exists) { + assert.ifError(err); + assert(true); + done(); + }); + }); + }); + }); - assert.strictEqual(entries + 1, history.length); + describe('.update()', function () { + it('should update a flag\'s properties', function (done) { + SocketFlags.update({ uid: 2 }, { + flagId: flag.flagId, + data: [{ + name: 'state', + value: 'wip' + }] + }, function (err, history) { + assert.ifError(err); + assert(Array.isArray(history)); + assert(history[0].fields.hasOwnProperty('state')); + assert.strictEqual('[[flags:state-wip]]', history[0].fields.state); done(); }); }); }); - }); - describe('.getHistory()', function () { - it('should retrieve a flag\'s history', function (done) { - Flags.getHistory(1, function (err, history) { - assert.ifError(err); - assert.strictEqual(history[0].fields[0].value, '[[flags:state-rejected]]'); - done(); + describe('.appendNote()', function () { + it('should append a note to the flag', function (done) { + SocketFlags.appendNote({ uid: 2 }, { + flagId: flag.flagId, + note: 'lorem ipsum dolor sit amet' + }, function (err, data) { + assert(data.hasOwnProperty('notes')); + assert(Array.isArray(data.notes)); + assert.strictEqual('lorem ipsum dolor sit amet', data.notes[0].content); + assert.strictEqual(2, data.notes[0].uid); + + assert(data.hasOwnProperty('history')); + assert(Array.isArray(data.history)); + assert.strictEqual(1, Object.keys(data.history[0].fields).length); + assert(data.history[0].fields.hasOwnProperty('notes')); + done(); + }); }); }); }); From 380ebf67ee84f34907d1f59d8d8985bdaa66ea6b Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 13 Dec 2016 14:24:09 -0500 Subject: [PATCH 037/122] oops, uncommenting all the other tests for flags --- test/flags.js | 500 +++++++++++++++++++++++++------------------------- 1 file changed, 250 insertions(+), 250 deletions(-) diff --git a/test/flags.js b/test/flags.js index 8d359c6930..7b0252086a 100644 --- a/test/flags.js +++ b/test/flags.js @@ -45,295 +45,295 @@ describe('Flags', function () { ], done); }); - // describe('.create()', function () { - // it('should create a flag and return its data', function (done) { - // Flags.create('post', 1, 1, 'Test flag', function (err, flagData) { - // assert.ifError(err); - // var compare = { - // flagId: 1, - // uid: 1, - // targetId: 1, - // type: 'post', - // description: 'Test flag' - // }; + describe('.create()', function () { + it('should create a flag and return its data', function (done) { + Flags.create('post', 1, 1, 'Test flag', function (err, flagData) { + assert.ifError(err); + var compare = { + flagId: 1, + uid: 1, + targetId: 1, + type: 'post', + description: 'Test flag' + }; - // for(var key in compare) { - // if (compare.hasOwnProperty(key)) { - // assert.ok(flagData[key]); - // assert.strictEqual(flagData[key], compare[key]); - // } - // } + for(var key in compare) { + if (compare.hasOwnProperty(key)) { + assert.ok(flagData[key]); + assert.strictEqual(flagData[key], compare[key]); + } + } - // done(); - // }); - // }); - // }); + done(); + }); + }); + }); - // describe('.get()', function () { - // it('should retrieve and display a flag\'s data', function (done) { - // Flags.get(1, function (err, flagData) { - // assert.ifError(err); - // var compare = { - // flagId: 1, - // uid: 1, - // targetId: 1, - // type: 'post', - // description: 'Test flag', - // state: 'open' - // }; + describe('.get()', function () { + it('should retrieve and display a flag\'s data', function (done) { + Flags.get(1, function (err, flagData) { + assert.ifError(err); + var compare = { + flagId: 1, + uid: 1, + targetId: 1, + type: 'post', + description: 'Test flag', + state: 'open' + }; - // for(var key in compare) { - // if (compare.hasOwnProperty(key)) { - // assert.ok(flagData[key]); - // assert.strictEqual(flagData[key], compare[key]); - // } - // } + for(var key in compare) { + if (compare.hasOwnProperty(key)) { + assert.ok(flagData[key]); + assert.strictEqual(flagData[key], compare[key]); + } + } - // done(); - // }); - // }); - // }); + done(); + }); + }); + }); - // describe('.list()', function () { - // it('should show a list of flags (with one item)', function (done) { - // Flags.list({}, 1, function (err, flags) { - // assert.ifError(err); - // assert.ok(Array.isArray(flags)); - // assert.equal(flags.length, 1); + describe('.list()', function () { + it('should show a list of flags (with one item)', function (done) { + Flags.list({}, 1, function (err, flags) { + assert.ifError(err); + assert.ok(Array.isArray(flags)); + assert.equal(flags.length, 1); - // Flags.get(flags[0].flagId, function (err, flagData) { - // assert.ifError(err); - // assert.equal(flags[0].flagId, flagData.flagId); - // assert.equal(flags[0].description, flagData.description); - // done(); - // }); - // }); - // }); - // }); + Flags.get(flags[0].flagId, function (err, flagData) { + assert.ifError(err); + assert.equal(flags[0].flagId, flagData.flagId); + assert.equal(flags[0].description, flagData.description); + done(); + }); + }); + }); + }); - // describe('.update()', function () { - // it('should alter a flag\'s various attributes and persist them to the database', function (done) { - // Flags.update(1, 1, { - // "state": "wip", - // "assignee": 1 - // }, function (err) { - // assert.ifError(err); - // db.getObjectFields('flag:1', ['state', 'assignee'], function (err, data) { - // if (err) { - // throw err; - // } + describe('.update()', function () { + it('should alter a flag\'s various attributes and persist them to the database', function (done) { + Flags.update(1, 1, { + "state": "wip", + "assignee": 1 + }, function (err) { + assert.ifError(err); + db.getObjectFields('flag:1', ['state', 'assignee'], function (err, data) { + if (err) { + throw err; + } - // assert.strictEqual('wip', data.state); - // assert.strictEqual(1, data.assignee); - // done(); - // }); - // }); - // }); + assert.strictEqual('wip', data.state); + assert.strictEqual(1, data.assignee); + done(); + }); + }); + }); - // it('should persist to the flag\'s history', function (done) { - // Flags.getHistory(1, function (err, history) { - // if (err) { - // throw err; - // } + it('should persist to the flag\'s history', function (done) { + Flags.getHistory(1, function (err, history) { + if (err) { + throw err; + } - // history.forEach(function (change) { - // switch (change.attribute) { - // case 'state': - // assert.strictEqual('[[flags:state-wip]]', change.value); - // break; + history.forEach(function (change) { + switch (change.attribute) { + case 'state': + assert.strictEqual('[[flags:state-wip]]', change.value); + break; - // case 'assignee': - // assert.strictEqual(1, change.value); - // break; - // } - // }); + case 'assignee': + assert.strictEqual(1, change.value); + break; + } + }); - // done(); - // }); - // }); - // }); + done(); + }); + }); + }); - // describe('.getTarget()', function () { - // it('should return a post\'s data if queried with type "post"', function (done) { - // Flags.getTarget('post', 1, 1, function (err, data) { - // assert.ifError(err); - // var compare = { - // uid: 1, - // pid: 1, - // content: 'This is flaggable content' - // }; + describe('.getTarget()', function () { + it('should return a post\'s data if queried with type "post"', function (done) { + Flags.getTarget('post', 1, 1, function (err, data) { + assert.ifError(err); + var compare = { + uid: 1, + pid: 1, + content: 'This is flaggable content' + }; - // for(var key in compare) { - // if (compare.hasOwnProperty(key)) { - // assert.ok(data[key]); - // assert.strictEqual(data[key], compare[key]); - // } - // } + for(var key in compare) { + if (compare.hasOwnProperty(key)) { + assert.ok(data[key]); + assert.strictEqual(data[key], compare[key]); + } + } - // done(); - // }); - // }); + done(); + }); + }); - // it('should return a user\'s data if queried with type "user"', function (done) { - // Flags.getTarget('user', 1, 1, function (err, data) { - // assert.ifError(err); - // var compare = { - // uid: 1, - // username: 'testUser', - // email: 'b@c.com' - // }; + it('should return a user\'s data if queried with type "user"', function (done) { + Flags.getTarget('user', 1, 1, function (err, data) { + assert.ifError(err); + var compare = { + uid: 1, + username: 'testUser', + email: 'b@c.com' + }; - // for(var key in compare) { - // if (compare.hasOwnProperty(key)) { - // assert.ok(data[key]); - // assert.strictEqual(data[key], compare[key]); - // } - // } + for(var key in compare) { + if (compare.hasOwnProperty(key)) { + assert.ok(data[key]); + assert.strictEqual(data[key], compare[key]); + } + } - // done(); - // }); - // }); - // }); + done(); + }); + }); + }); - // describe('.validate()', function () { - // it('should error out if type is post and post is deleted', function (done) { - // Posts.delete(1, 1, function (err) { - // if (err) { - // throw err; - // } + describe('.validate()', function () { + it('should error out if type is post and post is deleted', function (done) { + Posts.delete(1, 1, function (err) { + if (err) { + throw err; + } - // Flags.validate({ - // type: 'post', - // id: 1, - // uid: 1 - // }, function (err) { - // assert.ok(err); - // assert.strictEqual('[[error:post-deleted]]', err.message); - // Posts.restore(1, 1, done); - // }); - // }); - // }); + Flags.validate({ + type: 'post', + id: 1, + uid: 1 + }, function (err) { + assert.ok(err); + assert.strictEqual('[[error:post-deleted]]', err.message); + Posts.restore(1, 1, done); + }); + }); + }); - // it('should not pass validation if flag threshold is set and user rep does not meet it', function (done) { - // Meta.configs.set('privileges:flag', '50', function (err) { - // assert.ifError(err); + it('should not pass validation if flag threshold is set and user rep does not meet it', function (done) { + Meta.configs.set('privileges:flag', '50', function (err) { + assert.ifError(err); - // Flags.validate({ - // type: 'post', - // id: 1, - // uid: 2 - // }, function (err) { - // assert.ok(err); - // assert.strictEqual('[[error:not-enough-reputation-to-flag]]', err.message); - // Meta.configs.set('privileges:flag', 0, done); - // }); - // }); - // }); - // }); + Flags.validate({ + type: 'post', + id: 1, + uid: 2 + }, function (err) { + assert.ok(err); + assert.strictEqual('[[error:not-enough-reputation-to-flag]]', err.message); + Meta.configs.set('privileges:flag', 0, done); + }); + }); + }); + }); - // describe('.appendNote()', function () { - // it('should add a note to a flag', function (done) { - // Flags.appendNote(1, 1, 'this is my note', function (err) { - // assert.ifError(err); + describe('.appendNote()', function () { + it('should add a note to a flag', function (done) { + Flags.appendNote(1, 1, 'this is my note', function (err) { + assert.ifError(err); - // db.getSortedSetRange('flag:1:notes', 0, -1, function (err, notes) { - // if (err) { - // throw err; - // } + db.getSortedSetRange('flag:1:notes', 0, -1, function (err, notes) { + if (err) { + throw err; + } - // assert.strictEqual('[1,"this is my note"]', notes[0]); - // done(); - // }); - // }); - // }); + assert.strictEqual('[1,"this is my note"]', notes[0]); + done(); + }); + }); + }); - // it('should be a JSON string', function (done) { - // db.getSortedSetRange('flag:1:notes', 0, -1, function (err, notes) { - // if (err) { - // throw err; - // } + it('should be a JSON string', function (done) { + db.getSortedSetRange('flag:1:notes', 0, -1, function (err, notes) { + if (err) { + throw err; + } - // try { - // JSON.parse(notes[0]); - // } catch (e) { - // assert.ifError(e); - // } + try { + JSON.parse(notes[0]); + } catch (e) { + assert.ifError(e); + } - // done(); - // }); - // }); - // }); + done(); + }); + }); + }); - // describe('.getNotes()', function () { - // before(function (done) { - // // Add a second note - // Flags.appendNote(1, 1, 'this is the second note', done); - // }); + describe('.getNotes()', function () { + before(function (done) { + // Add a second note + Flags.appendNote(1, 1, 'this is the second note', done); + }); - // it('return should match a predefined spec', function (done) { - // Flags.getNotes(1, function (err, notes) { - // assert.ifError(err); - // var compare = { - // uid: 1, - // content: 'this is my note' - // }; + it('return should match a predefined spec', function (done) { + Flags.getNotes(1, function (err, notes) { + assert.ifError(err); + var compare = { + uid: 1, + content: 'this is my note' + }; - // var data = notes[1]; - // for(var key in compare) { - // if (compare.hasOwnProperty(key)) { - // assert.ok(data[key]); - // assert.strictEqual(data[key], compare[key]); - // } - // } + var data = notes[1]; + for(var key in compare) { + if (compare.hasOwnProperty(key)) { + assert.ok(data[key]); + assert.strictEqual(data[key], compare[key]); + } + } - // done(); - // }); - // }); + done(); + }); + }); - // it('should retrieve a list of notes, from newest to oldest', function (done) { - // Flags.getNotes(1, function (err, notes) { - // assert.ifError(err); - // assert(notes[0].datetime > notes[1].datetime); - // assert.strictEqual('this is the second note', notes[0].content); - // done(); - // }); - // }); - // }); + it('should retrieve a list of notes, from newest to oldest', function (done) { + Flags.getNotes(1, function (err, notes) { + assert.ifError(err); + assert(notes[0].datetime > notes[1].datetime); + assert.strictEqual('this is the second note', notes[0].content); + done(); + }); + }); + }); - // describe('.appendHistory()', function () { - // var entries; - // before(function (done) { - // db.sortedSetCard('flag:1:history', function (err, count) { - // entries = count; - // done(err); - // }); - // }); + describe('.appendHistory()', function () { + var entries; + before(function (done) { + db.sortedSetCard('flag:1:history', function (err, count) { + entries = count; + done(err); + }); + }); - // it('should add a new entry into a flag\'s history', function (done) { - // Flags.appendHistory(1, 1, ['state:rejected'], function (err) { - // assert.ifError(err); + it('should add a new entry into a flag\'s history', function (done) { + Flags.appendHistory(1, 1, ['state:rejected'], function (err) { + assert.ifError(err); - // Flags.getHistory(1, function (err, history) { - // if (err) { - // throw err; - // } + Flags.getHistory(1, function (err, history) { + if (err) { + throw err; + } - // assert.strictEqual(entries + 1, history.length); - // done(); - // }); - // }); - // }); - // }); + assert.strictEqual(entries + 1, history.length); + done(); + }); + }); + }); + }); - // describe('.getHistory()', function () { - // it('should retrieve a flag\'s history', function (done) { - // Flags.getHistory(1, function (err, history) { - // assert.ifError(err); - // assert.strictEqual(history[0].fields[0].value, '[[flags:state-rejected]]'); - // done(); - // }); - // }); - // }); + describe('.getHistory()', function () { + it('should retrieve a flag\'s history', function (done) { + Flags.getHistory(1, function (err, history) { + assert.ifError(err); + assert.strictEqual(history[0].fields[0].value, '[[flags:state-rejected]]'); + done(); + }); + }); + }); describe('(websockets)', function () { var SocketFlags = require('../src/socket.io/flags.js'); From e6768ab57286749821eec15cb69e39641139577a Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 14 Dec 2016 10:03:39 -0500 Subject: [PATCH 038/122] some more fixes to flags, simplifying qs manipulation in flags search re: #5232 --- public/language/en-GB/flags.json | 1 + public/src/client/flags/list.js | 14 ++++---------- src/controllers/mods.js | 1 - 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index a9272897ca..f1fd71bf27 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -41,6 +41,7 @@ "no-history": "No flag history.", "state": "State", + "state-all": "All states", "state-open": "New/Open", "state-wip": "Work in Progress", "state-resolved": "Resolved", diff --git a/public/src/client/flags/list.js b/public/src/client/flags/list.js index 255c7176f1..12cc19093f 100644 --- a/public/src/client/flags/list.js +++ b/public/src/client/flags/list.js @@ -20,16 +20,10 @@ define('forum/flags/list', ['components', 'Chart'], function (components, Chart) } filtersEl.find('button').on('click', function () { - var payload = filtersEl.serializeArray(); - var qs = payload.map(function (filter) { - if (filter.value) { - return filter.name + '=' + filter.value; - } else { - return; - } - }).filter(Boolean).join('&'); - - ajaxify.go('flags?' + qs); + var payload = filtersEl.serializeArray().filter(function (item) { + return !!item.value; + }); + ajaxify.go('flags?' + $.param(payload)); }); }; diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 39820e60a6..666f449316 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -5,7 +5,6 @@ var async = require('async'); var user = require('../user'); var flags = require('../flags'); var analytics = require('../analytics'); -// var adminFlagsController = require('./admin/flags'); var modsController = { flags: {} From ebffc4460011178f2745a27f78d2aeaca6559d9a Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 14 Dec 2016 15:00:41 -0500 Subject: [PATCH 039/122] fix tests, #5232 --- src/flags.js | 2 +- test/flags.js | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/flags.js b/src/flags.js index 1ae5a84ed8..995e880801 100644 --- a/src/flags.js +++ b/src/flags.js @@ -47,7 +47,7 @@ Flags.get = function (flagId, callback) { }; Flags.list = function (filters, uid, callback) { - if (typeof filters === 'function' && !callback) { + if (typeof filters === 'function' && !uid && !callback) { callback = filters; filters = {}; } diff --git a/test/flags.js b/test/flags.js index 7b0252086a..607b807db3 100644 --- a/test/flags.js +++ b/test/flags.js @@ -41,6 +41,11 @@ describe('Flags', function () { }, function (uid, next) { Groups.join('administrators', uid, next); + }, + function (next) { + User.create({ + username: 'unprivileged', password: 'abcdef', email: 'd@e.com' + }, next); } ], done); }); @@ -109,6 +114,15 @@ describe('Flags', function () { }); }); }); + + it('should return a filtered list of flags if said filters are passed in', function (done) { + Flags.list({ + state: 'open' + }, 1, function (err, flags) { + assert.ifError(err); + done(); + }); + }); }); describe('.update()', function () { @@ -221,7 +235,7 @@ describe('Flags', function () { Flags.validate({ type: 'post', id: 1, - uid: 2 + uid: 3 }, function (err) { assert.ok(err); assert.strictEqual('[[error:not-enough-reputation-to-flag]]', err.message); @@ -310,7 +324,9 @@ describe('Flags', function () { }); it('should add a new entry into a flag\'s history', function (done) { - Flags.appendHistory(1, 1, ['state:rejected'], function (err) { + Flags.appendHistory(1, 1, { + state: 'rejected' + }, function (err) { assert.ifError(err); Flags.getHistory(1, function (err, history) { @@ -329,7 +345,7 @@ describe('Flags', function () { it('should retrieve a flag\'s history', function (done) { Flags.getHistory(1, function (err, history) { assert.ifError(err); - assert.strictEqual(history[0].fields[0].value, '[[flags:state-rejected]]'); + assert.strictEqual(history[0].fields.state, '[[flags:state-rejected]]'); done(); }); }); From 0927d54c9877f8b024abd167121602b0e4aff2a5 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 14 Dec 2016 15:53:57 -0500 Subject: [PATCH 040/122] ability to filter flags by cid, #5232, more tests --- public/language/en-GB/flags.json | 2 ++ src/controllers/mods.js | 13 ++++++-- src/flags.js | 32 +++++++++++++++--- test/flags.js | 57 ++++++++++++++++++++++++++++---- 4 files changed, 92 insertions(+), 12 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index f1fd71bf27..2a1bf919f8 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -19,7 +19,9 @@ "filter-type-post": "Post", "filter-state": "State", "filter-assignee": "Assignee UID", + "filter-cid": "Category", "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", "apply-filters": "Apply Filters", "quick-links": "Quick Links", diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 666f449316..cae9ade1ed 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -3,6 +3,7 @@ var async = require('async'); var user = require('../user'); +var categories = require('../categories'); var flags = require('../flags'); var analytics = require('../analytics'); @@ -26,7 +27,7 @@ modsController.flags.list = function (req, res, next) { } // Parse query string params for filters - var valid = ['assignee', 'state', 'reporterId', 'type', 'targetUid', 'quick']; + var valid = ['assignee', 'state', 'reporterId', 'type', 'targetUid', 'cid', 'quick']; var filters = valid.reduce(function (memo, cur) { if (req.query.hasOwnProperty(cur)) { memo[cur] = req.query[cur]; @@ -37,15 +38,23 @@ modsController.flags.list = function (req, res, next) { async.parallel({ flags: async.apply(flags.list, filters, req.uid), - analytics: async.apply(analytics.getDailyStatsForSet, 'analytics:flags', Date.now(), 30) + analytics: async.apply(analytics.getDailyStatsForSet, 'analytics:flags', Date.now(), 30), + categories: async.apply(categories.buildForSelect, req.uid) }, function (err, data) { if (err) { return next(err); } + // Minimal returned set for templates.js + data.categories = data.categories.reduce(function (memo, cur) { + memo[cur.cid] = cur.name; + return memo; + }, {}); + res.render('flags/list', { flags: data.flags, analytics: data.analytics, + categories: data.categories, hasFilter: !!Object.keys(filters).length, filters: filters, title: '[[pages:flags]]' diff --git a/src/flags.js b/src/flags.js index 995e880801..81b97ee408 100644 --- a/src/flags.js +++ b/src/flags.js @@ -71,11 +71,15 @@ Flags.list = function (filters, uid, callback) { case 'assignee': sets.push('flags:byAssignee:' + filters[type]); break; - + case 'targetUid': sets.push('flags:byTargetUid:' + filters[type]); break; + case 'cid': + sets.push('flags:byCid:' + filters[type]); + break; + case 'quick': switch (filters.quick) { case 'mine': @@ -262,6 +266,7 @@ Flags.getNotes = function (flagId, callback) { Flags.create = function (type, id, uid, reason, timestamp, callback) { var targetUid; + var targetCid; var doHistoryAppend = false; // timestamp is optional @@ -273,17 +278,21 @@ Flags.create = function (type, id, uid, reason, timestamp, callback) { async.waterfall([ function (next) { - // Sanity checks async.parallel([ + // Sanity checks async.apply(Flags.exists, type, id, uid), async.apply(Flags.targetExists, type, id), - async.apply(Flags.getTargetUid, type, id) + + // Extra data for zset insertion + async.apply(Flags.getTargetUid, type, id), + async.apply(Flags.getTargetCid, type, id) ], function (err, checks) { if (err) { return next(err); } targetUid = checks[2] || null; + targetCid = checks[3] || null; if (checks[0]) { return next(new Error('[[error:already-flagged]]')); @@ -315,6 +324,9 @@ Flags.create = function (type, id, uid, reason, timestamp, callback) { if (targetUid) { tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byTargetUid:' + targetUid, timestamp, flagId)); // by target uid } + if (targetCid) { + tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byCid:' + targetCid, timestamp, flagId)); // by target uid + } async.parallel(tasks, function (err, data) { if (err) { @@ -358,12 +370,24 @@ Flags.getTargetUid = function (type, id, callback) { posts.getPostField(id, 'uid', callback); break; - case 'user': + default: setImmediate(callback, null, id); break; } }; +Flags.getTargetCid = function (type, id, callback) { + switch (type) { + case 'post': + posts.getCidByPid(id, callback); + break; + + default: + setImmediate(callback, null, id); + break; + } +}; + Flags.update = function (flagId, uid, changeset, callback) { // Retrieve existing flag data to compare for history-saving purposes var fields = ['state', 'assignee']; diff --git a/test/flags.js b/test/flags.js index 607b807db3..c46ac0bcef 100644 --- a/test/flags.js +++ b/test/flags.js @@ -72,6 +72,14 @@ describe('Flags', function () { done(); }); }); + + it('should add the flag to the byCid zset for category 1 if it is of type post', function (done) { + db.isSortedSetMember('flags:byCid:' + 1, 1, function (err, isMember) { + assert.ifError(err); + assert.ok(isMember); + done(); + }); + }); }); describe('.get()', function () { @@ -115,12 +123,49 @@ describe('Flags', function () { }); }); - it('should return a filtered list of flags if said filters are passed in', function (done) { - Flags.list({ - state: 'open' - }, 1, function (err, flags) { - assert.ifError(err); - done(); + describe('(with filters)', function () { + it('should return a filtered list of flags if said filters are passed in', function (done) { + Flags.list({ + state: 'open' + }, 1, function (err, flags) { + assert.ifError(err); + assert.ok(Array.isArray(flags)); + assert.strictEqual(1, flags[0].flagId); + done(); + }); + }); + + it('should return no flags if a filter with no matching flags is used', function (done) { + Flags.list({ + state: 'rejected' + }, 1, function (err, flags) { + assert.ifError(err); + assert.ok(Array.isArray(flags)); + assert.strictEqual(0, flags.length); + done(); + }); + }); + + it('should return a flag when filtered by cid 1', function (done) { + Flags.list({ + cid: 1 + }, 1, function (err, flags) { + assert.ifError(err); + assert.ok(Array.isArray(flags)); + assert.strictEqual(1, flags.length); + done(); + }); + }); + + it('shouldn\'t return a flag when filtered by cid 2', function (done) { + Flags.list({ + cid: 2 + }, 1, function (err, flags) { + assert.ifError(err); + assert.ok(Array.isArray(flags)); + assert.strictEqual(0, flags.length); + done(); + }); }); }); }); From 7b471b76db69c3fc5eb0ea5fca17b177e07f8c93 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 19 Dec 2016 09:50:46 -0500 Subject: [PATCH 041/122] fixing tests for #5232 --- test/flags.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/flags.js b/test/flags.js index c46ac0bcef..cc8a0425e3 100644 --- a/test/flags.js +++ b/test/flags.js @@ -457,6 +457,7 @@ describe('Flags', function () { flagId: flag.flagId, note: 'lorem ipsum dolor sit amet' }, function (err, data) { + assert.ifError(err); assert(data.hasOwnProperty('notes')); assert(Array.isArray(data.notes)); assert.strictEqual('lorem ipsum dolor sit amet', data.notes[0].content); From ad633aad4583546bad9302ca1cbef9ad052c131e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 19 Dec 2016 11:16:03 -0500 Subject: [PATCH 042/122] additional tests and proper handling for purged flag targets, #5232 --- public/language/en-GB/flags.json | 1 + src/controllers/mods.js | 9 +++-- src/flags.js | 60 +++++++++++++++++++------------- src/posts/delete.js | 3 -- src/upgrade.js | 47 ------------------------- src/user/admin.js | 10 ------ test/flags.js | 44 +++++++++++++++++++++++ 7 files changed, 87 insertions(+), 87 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index 2a1bf919f8..66b9acc92a 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -7,6 +7,7 @@ "assignee": "Assignee", "update": "Update", "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", "quick-filters": "Quick Filters", "filter-active": "There are one or more filters active in this list of flags", diff --git a/src/controllers/mods.js b/src/controllers/mods.js index cae9ade1ed..242d68d708 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -78,8 +78,13 @@ modsController.flags.detail = function (req, res, next) { res.render('flags/detail', Object.assign(results.flagData, { assignees: results.assignees, - type_bool: ['post', 'user'].reduce(function (memo, cur) { - memo[cur] = results.flagData.type === cur; + type_bool: ['post', 'user', 'empty'].reduce(function (memo, cur) { + if (cur !== 'empty') { + memo[cur] = results.flagData.type === cur && !!Object.keys(results.flagData.target).length; + } else { + memo[cur] = !Object.keys(results.flagData.target).length; + } + return memo; }, {}), title: '[[pages:flag-details, ' + req.params.flagId + ']]' diff --git a/src/flags.js b/src/flags.js index 81b97ee408..61b7a1746d 100644 --- a/src/flags.js +++ b/src/flags.js @@ -202,31 +202,6 @@ Flags.validate = function (payload, callback) { }); }; -Flags.getTarget = function (type, id, uid, callback) { - switch (type) { - case 'post': - async.waterfall([ - async.apply(posts.getPostsByPids, [id], uid), - function (posts, next) { - topics.addPostData(posts, uid, next); - } - ], function (err, posts) { - callback(err, posts[0]); - }); - break; - - case 'user': - user.getUsersData([id], function (err, users) { - callback(err, users ? users[0] : undefined); - }); - break; - - default: - callback(new Error('[[error:invalid-data]]')); - break; - } -}; - Flags.getNotes = function (flagId, callback) { async.waterfall([ async.apply(db.getSortedSetRevRangeWithScores.bind(db), 'flag:' + flagId + ':notes', 0, -1), @@ -348,6 +323,41 @@ Flags.exists = function (type, id, uid, callback) { db.isSortedSetMember('flags:hash', [type, id, uid].join(':'), callback); }; +Flags.getTarget = function (type, id, uid, callback) { + async.waterfall([ + async.apply(Flags.targetExists, type, id), + function (exists, next) { + if (exists) { + switch (type) { + case 'post': + async.waterfall([ + async.apply(posts.getPostsByPids, [id], uid), + function (posts, next) { + topics.addPostData(posts, uid, next); + } + ], function (err, posts) { + next(err, posts[0]); + }); + break; + + case 'user': + user.getUsersData([id], function (err, users) { + next(err, users ? users[0] : undefined); + }); + break; + + default: + next(new Error('[[error:invalid-data]]')); + break; + } + } else { + // Target used to exist (otherwise flag creation'd fail), but no longer + next(null, {}); + } + } + ], callback); +}; + Flags.targetExists = function (type, id, callback) { switch (type) { case 'post': diff --git a/src/posts/delete.js b/src/posts/delete.js index ebf902aef2..32ee6b6f41 100644 --- a/src/posts/delete.js +++ b/src/posts/delete.js @@ -144,9 +144,6 @@ module.exports = function (Posts) { }, function (next) { db.sortedSetsRemove(['posts:pid', 'posts:flagged'], pid, next); - }, - function (next) { - flags.dismiss(pid, next); } ], function (err) { if (err) { diff --git a/src/upgrade.js b/src/upgrade.js index 29b806d4a7..1815d1e560 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -455,53 +455,6 @@ Upgrade.upgrade = function (callback) { next(); } }, - function (next) { - thisSchemaDate = Date.UTC(2016, 3, 29); - - if (schemaDate < thisSchemaDate) { - updatesMade = true; - winston.info('[2016/04/29] Dismiss flags from deleted topics'); - - var posts = require('./posts'); - var topics = require('./topics'); - var flags = require('./flags'); - - var pids, tids; - - async.waterfall([ - async.apply(db.getSortedSetRange, 'posts:flagged', 0, -1), - function (_pids, next) { - pids = _pids; - posts.getPostsFields(pids, ['tid'], next); - }, - function (_tids, next) { - tids = _tids.map(function (a) { - return a.tid; - }); - - topics.getTopicsFields(tids, ['deleted'], next); - }, - function (state, next) { - var toDismiss = state.map(function (a, idx) { - return parseInt(a.deleted, 10) === 1 ? pids[idx] : null; - }).filter(Boolean); - - winston.info('[2016/04/29] ' + toDismiss.length + ' dismissable flags found'); - async.each(toDismiss, flags.dismiss, next); - } - ], function (err) { - if (err) { - return next(err); - } - - winston.info('[2016/04/29] Dismiss flags from deleted topics done'); - Upgrade.update(thisSchemaDate, next); - }); - } else { - winston.info('[2016/04/29] Dismiss flags from deleted topics skipped!'); - next(); - } - }, function (next) { thisSchemaDate = Date.UTC(2016, 4, 28); diff --git a/src/user/admin.js b/src/user/admin.js index 5d2215980c..4f7ecf66fb 100644 --- a/src/user/admin.js +++ b/src/user/admin.js @@ -56,14 +56,4 @@ module.exports = function (User) { } ], callback); }; - - User.resetFlags = function (uids, callback) { - if (!Array.isArray(uids) || !uids.length) { - return callback(); - } - - async.eachSeries(uids, function (uid, next) { - flags.dismissByUid(uid, next); - }, callback); - }; }; diff --git a/test/flags.js b/test/flags.js index cc8a0425e3..58250fb27f 100644 --- a/test/flags.js +++ b/test/flags.js @@ -82,6 +82,42 @@ describe('Flags', function () { }); }); + describe('.exists()', function () { + it('should return Boolean True if a flag matching the flag hash already exists', function (done) { + Flags.exists('post', 1, 1, function (err, exists) { + assert.ifError(err); + assert.strictEqual(true, exists); + done(); + }); + }); + + it('should return Boolean False if a flag matching the flag hash does not already exists', function (done) { + Flags.exists('post', 1, 2, function (err, exists) { + assert.ifError(err); + assert.strictEqual(false, exists); + done(); + }); + }); + }); + + describe('.targetExists()', function () { + it('should return Boolean True if the targeted element exists', function (done) { + Flags.targetExists('post', 1, function (err, exists) { + assert.ifError(err); + assert.strictEqual(true, exists); + done(); + }); + }); + + it('should return Boolean False if the targeted element does not exist', function (done) { + Flags.targetExists('post', 15, function (err, exists) { + assert.ifError(err); + assert.strictEqual(false, exists); + done(); + }); + }); + }); + describe('.get()', function () { it('should retrieve and display a flag\'s data', function (done) { Flags.get(1, function (err, flagData) { @@ -252,6 +288,14 @@ describe('Flags', function () { done(); }); }); + + it('should return a plain object with no properties if the target no longer exists', function (done) { + Flags.getTarget('user', 15, 1, function (err, data) { + assert.ifError(err); + assert.strictEqual(0, Object.keys(data).length); + done(); + }); + }); }); describe('.validate()', function () { From 47c9c936936f50cc0fa4494d5ae2164f5f219fee Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 19 Dec 2016 11:54:52 -0500 Subject: [PATCH 043/122] removed old flagging tests --- test/posts.js | 215 -------------------------------------------------- 1 file changed, 215 deletions(-) diff --git a/test/posts.js b/test/posts.js index 1ddbd83399..090edd3ca1 100644 --- a/test/posts.js +++ b/test/posts.js @@ -418,221 +418,6 @@ describe('Post\'s', function () { }); }); - describe('flagging a post', function () { - var meta = require('../src/meta'); - var socketPosts = require('../src/socket.io/posts'); - it('should fail to flag a post due to low reputation', function (done) { - meta.config['privileges:flag'] = 10; - flagPost(function (err) { - assert.equal(err.message, '[[error:not-enough-reputation-to-flag]]'); - done(); - }); - }); - - it('should flag a post', function (done) { - meta.config['privileges:flag'] = -1; - flagPost(function (err) { - assert.ifError(err); - done(); - }); - }); - - it('should return nothing without a uid or a reason', function (done) { - socketPosts.flag({uid: 0}, {pid: postData.pid, reason: 'reason'}, function (err) { - assert.equal(err.message, '[[error:not-logged-in]]'); - socketPosts.flag({uid: voteeUid}, {}, function (err) { - assert.equal(err.message, '[[error:invalid-data]]'); - done(); - }); - }); - }); - - it('should return an error without an existing post', function (done) { - socketPosts.flag({uid: voteeUid}, {pid: 12312312, reason: 'reason'}, function (err) { - assert.equal(err.message, '[[error:no-post]]'); - done(); - }); - }); - - it('should return an error if the flag already exists', function (done) { - socketPosts.flag({uid: voteeUid}, {pid: postData.pid, reason: 'reason'}, function (err) { - assert.equal(err.message, '[[error:already-flagged]]'); - done(); - }); - }); - }); - - function flagPost(next) { - var socketPosts = require('../src/socket.io/posts'); - socketPosts.flag({uid: voteeUid}, {pid: postData.pid, reason: 'reason'}, next); - } - - describe('get flag data', function () { - it('should see the flagged post', function (done) { - posts.isFlaggedByUser(postData.pid, voteeUid, function (err, hasFlagged) { - assert.ifError(err); - assert(hasFlagged); - done(); - }); - }); - - it('should return the flagged post data', function (done) { - posts.getFlags('posts:flagged', cid, voteeUid, 0, -1, function (err, flagData) { - assert.ifError(err); - assert(flagData.posts); - assert(flagData.count); - assert.equal(flagData.count, 1); - assert.equal(flagData.posts.length, 1); - assert(flagData.posts[0].flagReasons); - assert.equal(flagData.posts[0].flagReasons.length, 1); - assert.strictEqual(flagData.posts[0].flagReasons[0].reason, 'reason'); - assert(flagData.posts[0].flagData); - assert.strictEqual(flagData.posts[0].flagData.state, 'open'); - done(); - }); - }); - }); - - describe('updating a flag', function () { - var socketPosts = require('../src/socket.io/posts'); - - it('should update a flag', function (done) { - async.waterfall([ - function (next) { - socketPosts.updateFlag({uid: globalModUid}, { - pid: postData.pid, - data: [ - {name: 'assignee', value: `${globalModUid}`}, - {name: 'notes', value: 'notes'} - ] - }, function (err) { - assert.ifError(err); - posts.getFlags('posts:flagged', cid, globalModUid, 0, -1, function (err, flagData) { - assert.ifError(err); - assert(flagData.posts); - assert.equal(flagData.posts.length, 1); - assert.deepEqual({ - assignee: flagData.posts[0].flagData.assignee, - notes: flagData.posts[0].flagData.notes, - state: flagData.posts[0].flagData.state, - labelClass: flagData.posts[0].flagData.labelClass - }, { - assignee: `${globalModUid}`, - notes: 'notes', - state: 'open', - labelClass: 'info' - }); - next(); - }); - }); - }, function (next) { - posts.updateFlagData(globalModUid, postData.pid, { - state: 'rejected' - }, function (err) { - assert.ifError(err); - posts.getFlags('posts:flagged', cid, globalModUid, 0, -1, function (err, flagData) { - assert.ifError(err); - assert(flagData.posts); - assert.equal(flagData.posts.length, 1); - assert.deepEqual({ - state: flagData.posts[0].flagData.state, - labelClass: flagData.posts[0].flagData.labelClass - }, { - state: 'rejected', - labelClass: 'danger' - }); - next(); - }); - }); - }, function (next) { - posts.updateFlagData(globalModUid, postData.pid, { - state: 'wip' - }, function (err) { - assert.ifError(err); - posts.getFlags('posts:flagged', cid, globalModUid, 0, -1, function (err, flagData) { - assert.ifError(err); - assert(flagData.posts); - assert.equal(flagData.posts.length, 1); - assert.deepEqual({ - state: flagData.posts[0].flagData.state, - labelClass: flagData.posts[0].flagData.labelClass - }, { - state: 'wip', - labelClass: 'warning' - }); - next(); - }); - }); - }, function (next) { - posts.updateFlagData(globalModUid, postData.pid, { - state: 'resolved' - }, function (err) { - assert.ifError(err); - posts.getFlags('posts:flagged', cid, globalModUid, 0, -1, function (err, flagData) { - assert.ifError(err); - assert(flagData.posts); - assert.equal(flagData.posts.length, 1); - assert.deepEqual({ - state: flagData.posts[0].flagData.state, - labelClass: flagData.posts[0].flagData.labelClass - }, { - state: 'resolved', - labelClass: 'success' - }); - next(); - }); - }); - } - ], done); - }); - }); - - describe('dismissing a flag', function () { - var socketPosts = require('../src/socket.io/posts'); - - it('should dismiss a flag', function (done) { - socketPosts.dismissFlag({uid: globalModUid}, postData.pid, function (err) { - assert.ifError(err); - posts.isFlaggedByUser(postData.pid, voteeUid, function (err, hasFlagged) { - assert.ifError(err); - assert(!hasFlagged); - flagPost(function (err) { - assert.ifError(err); - done(); - }); - }); - }); - }); - - it('should dismiss all of a user\'s flags', function (done) { - posts.dismissUserFlags(voteeUid, function (err) { - assert.ifError(err); - posts.isFlaggedByUser(postData.pid, voteeUid, function (err, hasFlagged) { - assert.ifError(err); - assert(!hasFlagged); - flagPost(function (err) { - assert.ifError(err); - done(); - }); - }); - }); - }); - - it('should dismiss all flags', function (done) { - socketPosts.dismissAllFlags({uid: globalModUid}, {}, function (err) { - assert.ifError(err); - posts.isFlaggedByUser(postData.pid, voteeUid, function (err, hasFlagged) { - assert.ifError(err); - assert(!hasFlagged); - flagPost(function (err) { - assert.ifError(err); - done(); - }); - }); - }); - }); - }); - describe('getPostSummaryByPids', function () { it('should return empty array for empty pids', function (done) { posts.getPostSummaryByPids([], 0, {}, function (err, data) { From 5e52cfdf86ed709d122fbaf73bd6379c7745f308 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 19 Dec 2016 12:01:00 -0500 Subject: [PATCH 044/122] removed one more old flag test for #5232 --- test/socket.io.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/socket.io.js b/test/socket.io.js index ddb136d3b0..3928dc64c4 100644 --- a/test/socket.io.js +++ b/test/socket.io.js @@ -245,16 +245,6 @@ describe('socket.io', function () { }); }); - it('should reset flags', function (done) { - var socketAdmin = require('../src/socket.io/admin'); - socketAdmin.user.resetFlags({uid: adminUid}, [regularUid], function (err) { - assert.ifError(err); - done(); - }); - }); - - - describe('validation emails', function () { var socketAdmin = require('../src/socket.io/admin'); var meta = require('../src/meta'); From 2ea63f3d4259407045d9d586a4bbf8b4343a23fb Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 19 Dec 2016 12:13:36 -0500 Subject: [PATCH 045/122] how much fun is it to fix tests when stack traces don't work? lots. :shipit: --- src/flags.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/flags.js b/src/flags.js index 61b7a1746d..d3735671b2 100644 --- a/src/flags.js +++ b/src/flags.js @@ -34,7 +34,7 @@ Flags.get = function (flagId, callback) { }, function (err, payload) { // Final object return construction next(err, Object.assign(data.base, { - datetimeISO: new Date(data.base.datetime).toISOString(), + datetimeISO: new Date(parseInt(data.base.datetime, 10)).toISOString(), target_readable: data.base.type.charAt(0).toUpperCase() + data.base.type.slice(1) + ' ' + data.base.targetId, target: payload.targetObj, history: data.history, @@ -216,7 +216,7 @@ Flags.getNotes = function (flagId, callback) { uid: noteObj[0], content: noteObj[1], datetime: note.score, - datetimeISO: new Date(note.score).toISOString() + datetimeISO: new Date(parseInt(note.score, 10)).toISOString() }; } catch (e) { return next(e); @@ -469,7 +469,7 @@ Flags.getHistory = function (flagId, callback) { uid: entry.value[0], fields: changeset, datetime: entry.score, - datetimeISO: new Date(entry.score).toISOString() + datetimeISO: new Date(parseInt(entry.score, 10)).toISOString() }; }); From 07ac7dce841d2d9ed96229dd7df02bf21fa20145 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 19 Dec 2016 12:31:55 -0500 Subject: [PATCH 046/122] minor tweaks to test to be redis-compatible --- test/flags.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/test/flags.js b/test/flags.js index 58250fb27f..dfa6f1a773 100644 --- a/test/flags.js +++ b/test/flags.js @@ -65,7 +65,7 @@ describe('Flags', function () { for(var key in compare) { if (compare.hasOwnProperty(key)) { assert.ok(flagData[key]); - assert.strictEqual(flagData[key], compare[key]); + assert.equal(flagData[key], compare[key]); } } @@ -134,7 +134,7 @@ describe('Flags', function () { for(var key in compare) { if (compare.hasOwnProperty(key)) { assert.ok(flagData[key]); - assert.strictEqual(flagData[key], compare[key]); + assert.equal(flagData[key], compare[key]); } } @@ -166,7 +166,7 @@ describe('Flags', function () { }, 1, function (err, flags) { assert.ifError(err); assert.ok(Array.isArray(flags)); - assert.strictEqual(1, flags[0].flagId); + assert.strictEqual(1, parseInt(flags[0].flagId, 10)); done(); }); }); @@ -219,7 +219,8 @@ describe('Flags', function () { } assert.strictEqual('wip', data.state); - assert.strictEqual(1, data.assignee); + assert.ok(!isNaN(parseInt(data.assignee, 10))); + assert.strictEqual(1, parseInt(data.assignee, 10)); done(); }); }); @@ -261,7 +262,7 @@ describe('Flags', function () { for(var key in compare) { if (compare.hasOwnProperty(key)) { assert.ok(data[key]); - assert.strictEqual(data[key], compare[key]); + assert.equal(data[key], compare[key]); } } @@ -281,7 +282,7 @@ describe('Flags', function () { for(var key in compare) { if (compare.hasOwnProperty(key)) { assert.ok(data[key]); - assert.strictEqual(data[key], compare[key]); + assert.equal(data[key], compare[key]); } } @@ -480,7 +481,7 @@ describe('Flags', function () { describe('.update()', function () { it('should update a flag\'s properties', function (done) { SocketFlags.update({ uid: 2 }, { - flagId: flag.flagId, + flagId: 2, data: [{ name: 'state', value: 'wip' @@ -498,7 +499,7 @@ describe('Flags', function () { describe('.appendNote()', function () { it('should append a note to the flag', function (done) { SocketFlags.appendNote({ uid: 2 }, { - flagId: flag.flagId, + flagId: 2, note: 'lorem ipsum dolor sit amet' }, function (err, data) { assert.ifError(err); From babafde7268c2d334457a12d23022af24ef5d6ab Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 19 Dec 2016 12:40:33 -0500 Subject: [PATCH 047/122] once more for good measure! --- src/flags.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flags.js b/src/flags.js index d3735671b2..7825f5603d 100644 --- a/src/flags.js +++ b/src/flags.js @@ -156,9 +156,9 @@ Flags.validate = function (payload, callback) { return callback(err); } - if (data.target.deleted) { + if (parseInt(data.target.deleted, 10)) { return callback(new Error('[[error:post-deleted]]')); - } else if (data.reporter.banned) { + } else if (parseInt(data.reporter.banned, 10)) { return callback(new Error('[[error:user-banned]]')); } From 283ae564f2771459592e8a36a46e09e4bcafc1d1 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 19 Dec 2016 12:52:47 -0500 Subject: [PATCH 048/122] removing incorrect parseInt --- src/flags.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flags.js b/src/flags.js index 7825f5603d..ecc5a84e3e 100644 --- a/src/flags.js +++ b/src/flags.js @@ -156,7 +156,7 @@ Flags.validate = function (payload, callback) { return callback(err); } - if (parseInt(data.target.deleted, 10)) { + if (data.target.deleted) { return callback(new Error('[[error:post-deleted]]')); } else if (parseInt(data.reporter.banned, 10)) { return callback(new Error('[[error:user-banned]]')); From 7c7cb8cfe65118ed12eb60f2057ff2da1578603d Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 20 Dec 2016 13:30:41 -0500 Subject: [PATCH 049/122] remove flag translations from development branch --- public/language/ar/admin/manage/flags.json | 19 ------------------- public/language/bg/admin/manage/flags.json | 19 ------------------- public/language/bn/admin/manage/flags.json | 19 ------------------- public/language/cs/admin/manage/flags.json | 19 ------------------- public/language/da/admin/manage/flags.json | 19 ------------------- public/language/de/admin/manage/flags.json | 19 ------------------- public/language/el/admin/manage/flags.json | 19 ------------------- public/language/en-GB/admin/manage/flags.json | 19 ------------------- public/language/en-US/admin/manage/flags.json | 19 ------------------- .../en-x-pirate/admin/manage/flags.json | 19 ------------------- public/language/es/admin/manage/flags.json | 19 ------------------- public/language/et/admin/manage/flags.json | 19 ------------------- public/language/fa-IR/admin/manage/flags.json | 19 ------------------- public/language/fi/admin/manage/flags.json | 19 ------------------- public/language/fr/admin/manage/flags.json | 19 ------------------- public/language/gl/admin/manage/flags.json | 19 ------------------- public/language/he/admin/manage/flags.json | 19 ------------------- public/language/hu/admin/manage/flags.json | 19 ------------------- public/language/id/admin/manage/flags.json | 19 ------------------- public/language/it/admin/manage/flags.json | 19 ------------------- public/language/ja/admin/manage/flags.json | 19 ------------------- public/language/ko/admin/manage/flags.json | 19 ------------------- public/language/lt/admin/manage/flags.json | 19 ------------------- public/language/ms/admin/manage/flags.json | 19 ------------------- public/language/nb/admin/manage/flags.json | 19 ------------------- public/language/nl/admin/manage/flags.json | 19 ------------------- public/language/pl/admin/manage/flags.json | 19 ------------------- public/language/pt-BR/admin/manage/flags.json | 19 ------------------- public/language/pt-PT/admin/manage/flags.json | 19 ------------------- public/language/ro/admin/manage/flags.json | 19 ------------------- public/language/ru/admin/manage/flags.json | 19 ------------------- public/language/rw/admin/manage/flags.json | 19 ------------------- public/language/sc/admin/manage/flags.json | 19 ------------------- public/language/sk/admin/manage/flags.json | 19 ------------------- public/language/sl/admin/manage/flags.json | 19 ------------------- public/language/sr/admin/manage/flags.json | 19 ------------------- public/language/sv/admin/manage/flags.json | 19 ------------------- public/language/th/admin/manage/flags.json | 19 ------------------- public/language/tr/admin/manage/flags.json | 19 ------------------- public/language/vi/admin/manage/flags.json | 19 ------------------- public/language/zh-CN/admin/manage/flags.json | 19 ------------------- public/language/zh-TW/admin/manage/flags.json | 19 ------------------- 42 files changed, 798 deletions(-) delete mode 100644 public/language/ar/admin/manage/flags.json delete mode 100644 public/language/bg/admin/manage/flags.json delete mode 100644 public/language/bn/admin/manage/flags.json delete mode 100644 public/language/cs/admin/manage/flags.json delete mode 100644 public/language/da/admin/manage/flags.json delete mode 100644 public/language/de/admin/manage/flags.json delete mode 100644 public/language/el/admin/manage/flags.json delete mode 100644 public/language/en-GB/admin/manage/flags.json delete mode 100644 public/language/en-US/admin/manage/flags.json delete mode 100644 public/language/en-x-pirate/admin/manage/flags.json delete mode 100644 public/language/es/admin/manage/flags.json delete mode 100644 public/language/et/admin/manage/flags.json delete mode 100644 public/language/fa-IR/admin/manage/flags.json delete mode 100644 public/language/fi/admin/manage/flags.json delete mode 100644 public/language/fr/admin/manage/flags.json delete mode 100644 public/language/gl/admin/manage/flags.json delete mode 100644 public/language/he/admin/manage/flags.json delete mode 100644 public/language/hu/admin/manage/flags.json delete mode 100644 public/language/id/admin/manage/flags.json delete mode 100644 public/language/it/admin/manage/flags.json delete mode 100644 public/language/ja/admin/manage/flags.json delete mode 100644 public/language/ko/admin/manage/flags.json delete mode 100644 public/language/lt/admin/manage/flags.json delete mode 100644 public/language/ms/admin/manage/flags.json delete mode 100644 public/language/nb/admin/manage/flags.json delete mode 100644 public/language/nl/admin/manage/flags.json delete mode 100644 public/language/pl/admin/manage/flags.json delete mode 100644 public/language/pt-BR/admin/manage/flags.json delete mode 100644 public/language/pt-PT/admin/manage/flags.json delete mode 100644 public/language/ro/admin/manage/flags.json delete mode 100644 public/language/ru/admin/manage/flags.json delete mode 100644 public/language/rw/admin/manage/flags.json delete mode 100644 public/language/sc/admin/manage/flags.json delete mode 100644 public/language/sk/admin/manage/flags.json delete mode 100644 public/language/sl/admin/manage/flags.json delete mode 100644 public/language/sr/admin/manage/flags.json delete mode 100644 public/language/sv/admin/manage/flags.json delete mode 100644 public/language/th/admin/manage/flags.json delete mode 100644 public/language/tr/admin/manage/flags.json delete mode 100644 public/language/vi/admin/manage/flags.json delete mode 100644 public/language/zh-CN/admin/manage/flags.json delete mode 100644 public/language/zh-TW/admin/manage/flags.json diff --git a/public/language/ar/admin/manage/flags.json b/public/language/ar/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/ar/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/bg/admin/manage/flags.json b/public/language/bg/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/bg/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/bn/admin/manage/flags.json b/public/language/bn/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/bn/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/cs/admin/manage/flags.json b/public/language/cs/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/cs/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/da/admin/manage/flags.json b/public/language/da/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/da/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/de/admin/manage/flags.json b/public/language/de/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/de/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/el/admin/manage/flags.json b/public/language/el/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/el/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/en-GB/admin/manage/flags.json b/public/language/en-GB/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/en-GB/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/en-US/admin/manage/flags.json b/public/language/en-US/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/en-US/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/en-x-pirate/admin/manage/flags.json b/public/language/en-x-pirate/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/en-x-pirate/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/es/admin/manage/flags.json b/public/language/es/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/es/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/et/admin/manage/flags.json b/public/language/et/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/et/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/fa-IR/admin/manage/flags.json b/public/language/fa-IR/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/fa-IR/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/fi/admin/manage/flags.json b/public/language/fi/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/fi/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/fr/admin/manage/flags.json b/public/language/fr/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/fr/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/gl/admin/manage/flags.json b/public/language/gl/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/gl/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/he/admin/manage/flags.json b/public/language/he/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/he/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/hu/admin/manage/flags.json b/public/language/hu/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/hu/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/id/admin/manage/flags.json b/public/language/id/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/id/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/it/admin/manage/flags.json b/public/language/it/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/it/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/ja/admin/manage/flags.json b/public/language/ja/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/ja/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/ko/admin/manage/flags.json b/public/language/ko/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/ko/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/lt/admin/manage/flags.json b/public/language/lt/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/lt/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/ms/admin/manage/flags.json b/public/language/ms/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/ms/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/nb/admin/manage/flags.json b/public/language/nb/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/nb/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/nl/admin/manage/flags.json b/public/language/nl/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/nl/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/pl/admin/manage/flags.json b/public/language/pl/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/pl/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/pt-BR/admin/manage/flags.json b/public/language/pt-BR/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/pt-BR/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/pt-PT/admin/manage/flags.json b/public/language/pt-PT/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/pt-PT/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/ro/admin/manage/flags.json b/public/language/ro/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/ro/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/ru/admin/manage/flags.json b/public/language/ru/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/ru/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/rw/admin/manage/flags.json b/public/language/rw/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/rw/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/sc/admin/manage/flags.json b/public/language/sc/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/sc/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/sk/admin/manage/flags.json b/public/language/sk/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/sk/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/sl/admin/manage/flags.json b/public/language/sl/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/sl/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/sr/admin/manage/flags.json b/public/language/sr/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/sr/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/sv/admin/manage/flags.json b/public/language/sv/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/sv/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/th/admin/manage/flags.json b/public/language/th/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/th/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/tr/admin/manage/flags.json b/public/language/tr/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/tr/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/vi/admin/manage/flags.json b/public/language/vi/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/vi/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/zh-CN/admin/manage/flags.json b/public/language/zh-CN/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/zh-CN/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file diff --git a/public/language/zh-TW/admin/manage/flags.json b/public/language/zh-TW/admin/manage/flags.json deleted file mode 100644 index bfc488a409..0000000000 --- a/public/language/zh-TW/admin/manage/flags.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "daily": "Daily flags", - "by-user": "Flags by user", - "by-user-search": "Search flagged posts by username", - "category": "Category", - "sort-by": "Sort By", - "sort-by.most-flags": "Most Flags", - "sort-by.most-recent": "Most Recent", - "search": "Search", - "dismiss-all": "Dismiss All", - "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", - "read-more": "Read More", - "flagged-x-times": "This post has been flagged %1 time(s):", - "dismiss": "Dismiss this Flag", - "delete-post": "Delete the Post", - - "alerts.confirm-delete-post": "Do you really want to delete this post?" -} \ No newline at end of file From 3ea927fa658c9fde56b938d5613b3c1e33dc311c Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 27 Dec 2016 15:29:46 -0500 Subject: [PATCH 050/122] fix minSchemaDate in upgrade.js --- src/upgrade.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/upgrade.js b/src/upgrade.js index 48e552dabe..89fe87f8d7 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -8,7 +8,7 @@ var winston = require('winston'); var Upgrade = {}; -var minSchemaDate = Date.UTC(2015, 10, 6); // This value gets updated every new MAJOR version +var minSchemaDate = Date.UTC(2016, 8, 7); // This value gets updated every new MAJOR version var schemaDate; var thisSchemaDate; From 05fdd358187d619cc6845544bc73dba6f8826ab5 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 27 Dec 2016 15:33:55 -0500 Subject: [PATCH 051/122] removed menu item for flags management in ACP --- public/language/en-GB/admin/menu.json | 1 - src/views/admin/partials/menu.tpl | 2 -- 2 files changed, 3 deletions(-) diff --git a/public/language/en-GB/admin/menu.json b/public/language/en-GB/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/en-GB/admin/menu.json +++ b/public/language/en-GB/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/src/views/admin/partials/menu.tpl b/src/views/admin/partials/menu.tpl index 9ab06ed811..a92d1b5f2e 100644 --- a/src/views/admin/partials/menu.tpl +++ b/src/views/admin/partials/menu.tpl @@ -19,7 +19,6 @@
  • [[admin/menu:manage/users]]
  • [[admin/menu:manage/registration]]
  • [[admin/menu:manage/groups]]
  • -
  • [[admin/menu:manage/flags]]
  • [[admin/menu:manage/ip-blacklist]]
  • @@ -192,7 +191,6 @@
  • [[admin/menu:manage/users]]
  • [[admin/menu:manage/registration]]
  • [[admin/menu:manage/groups]]
  • -
  • [[admin/menu:manage/flags]]
  • [[admin/menu:manage/ip-blacklist]]
  • From ec544518e8d3610bcd4f20e6c32447322f32770a Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Mon, 2 Jan 2017 22:23:17 -0700 Subject: [PATCH 052/122] Use async v2 --- minifier.js | 14 +++++++++++--- package.json | 2 +- src/file.js | 20 ++++++++++++++------ src/meta/dependencies.js | 25 ++++++++++++++++--------- src/meta/themes.js | 18 ++++++++++++++---- src/plugins.js | 12 ++++++++---- src/plugins/load.js | 4 +--- src/privileges/helpers.js | 8 ++------ src/rewards/index.js | 10 ++++++---- 9 files changed, 73 insertions(+), 40 deletions(-) diff --git a/minifier.js b/minifier.js index 25c0177175..a83069ab85 100644 --- a/minifier.js +++ b/minifier.js @@ -17,13 +17,21 @@ Minifier.js.minify = function (scripts, minify, callback) { }); async.filter(scripts, function (script, next) { - file.exists(script, function (exists) { + file.exists(script, function (err, exists) { + if (err) { + return next(err); + } + if (!exists) { console.warn('[minifier] file not found, ' + script); } - next(exists); + next(null, exists); }); - }, function (scripts) { + }, function (err, scripts) { + if (err) { + return callback(err); + } + if (minify) { minifyScripts(scripts, callback); } else { diff --git a/package.json b/package.json index a9dbdfb82b..f80a1b12c9 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "coveralls": "istanbul cover _mocha --report lcovonly -- -R dot && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage" }, "dependencies": { - "async": "~1.5.0", + "async": "^2.1.4", "autoprefixer": "^6.2.3", "bcryptjs": "~2.3.0", "body-parser": "^1.9.0", diff --git a/src/file.js b/src/file.js index df820cc47f..a231ddd01d 100644 --- a/src/file.js +++ b/src/file.js @@ -87,19 +87,27 @@ file.allowedExtensions = function () { file.exists = function (path, callback) { fs.stat(path, function (err, stat) { - callback(!err && stat); + if (err) { + if (err.code === 'ENOENT') { + return callback(null, false); + } + return callback(err); + } + return callback(null, true); }); }; file.existsSync = function (path) { - var exists = false; try { - exists = fs.statSync(path); - } catch(err) { - exists = false; + fs.statSync(path); + } catch (err) { + if (err.code === 'ENOENT') { + return false; + } + throw err; } - return !!exists; + return true; }; module.exports = file; diff --git a/src/meta/dependencies.js b/src/meta/dependencies.js index 3f892c37ab..fdfa755198 100644 --- a/src/meta/dependencies.js +++ b/src/meta/dependencies.js @@ -19,14 +19,17 @@ module.exports = function (Meta) { winston.verbose('Checking dependencies for outdated modules'); - async.every(modules, function (module, next) { + async.each(modules, function (module, next) { fs.readFile(path.join(__dirname, '../../node_modules/', module, 'package.json'), { encoding: 'utf-8' }, function (err, pkgData) { - // If a bundled plugin/theme is not present, skip the dep check (#3384) - if (err && err.code === 'ENOENT' && (module === 'nodebb-rewards-essentials' || module.startsWith('nodebb-plugin') || module.startsWith('nodebb-theme'))) { - winston.warn('[meta/dependencies] Bundled plugin ' + module + ' not found, skipping dependency check.'); - return next(true); + if (err) { + // If a bundled plugin/theme is not present, skip the dep check (#3384) + if (err.code === 'ENOENT' && (module === 'nodebb-rewards-essentials' || module.startsWith('nodebb-plugin') || module.startsWith('nodebb-theme'))) { + winston.warn('[meta/dependencies] Bundled plugin ' + module + ' not found, skipping dependency check.'); + return next(); + } + return next(err); } try { @@ -34,20 +37,24 @@ module.exports = function (Meta) { } catch(e) { process.stdout.write('[' + 'missing'.red + '] ' + module.bold + ' is a required dependency but could not be found\n'); depsMissing = true; - return next(true); + return next(); } var ok = !semver.validRange(pkg.dependencies[module]) || semver.satisfies(pkgData.version, pkg.dependencies[module]); if (ok || (pkgData._resolved && pkgData._resolved.indexOf('//github.com') !== -1)) { - next(true); + next(); } else { process.stdout.write('[' + 'outdated'.yellow + '] ' + module.bold + ' installed v' + pkgData.version + ', package.json requires ' + pkg.dependencies[module] + '\n'); depsOutdated = true; - next(true); + next(); } }); - }, function (ok) { + }, function (err) { + if (err) { + return callback(err); + } + if (depsMissing) { callback(new Error('dependencies-missing')); } else if (depsOutdated) { diff --git a/src/meta/themes.js b/src/meta/themes.js index be48d1e70d..777e1af5df 100644 --- a/src/meta/themes.js +++ b/src/meta/themes.js @@ -27,18 +27,28 @@ module.exports = function (Meta) { async.filter(files, function (file, next) { fs.stat(path.join(themePath, file), function (err, fileStat) { if (err) { - return next(false); + if (err.code === 'ENOENT') { + return next(null, false); + } + return next(err); } - next((fileStat.isDirectory() && file.slice(0, 13) === 'nodebb-theme-')); + next(null, (fileStat.isDirectory() && file.slice(0, 13) === 'nodebb-theme-')); }); - }, function (themes) { + }, function (err, themes) { + if (err) { + return callback(err); + } + async.map(themes, function (theme, next) { var config = path.join(themePath, theme, 'theme.json'); fs.readFile(config, function (err, file) { if (err) { - return next(); + if (err.code === 'ENOENT') { + return next(null, null); + } + return next(err); } try { var configObj = JSON.parse(file.toString()); diff --git a/src/plugins.js b/src/plugins.js index b8ddbdc0fe..52378e7f38 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -161,9 +161,7 @@ var middleware; }); // Filter out plugins with invalid paths - async.filter(paths, file.exists, function (paths) { - next(null, paths); - }); + async.filter(paths, file.exists, next); }, function (paths, next) { async.map(paths, Plugins.loadPluginInfo, next); @@ -346,7 +344,13 @@ var middleware; async.filter(dirs, function (dir, callback) { fs.stat(dir, function (err, stats) { - callback(!err && stats.isDirectory()); + if (err) { + if (err.code === 'ENOENT') { + return callback(null, false); + } + return callback(err); + } + callback(null, stats.isDirectory()); }); }, function (plugins) { next(null, plugins); diff --git a/src/plugins/load.js b/src/plugins/load.js index 60d584f99f..98a470f914 100644 --- a/src/plugins/load.js +++ b/src/plugins/load.js @@ -31,9 +31,7 @@ module.exports = function (Plugins) { return path.join(__dirname, '../../node_modules/', plugin); }); - async.filter(plugins, file.exists, function (plugins) { - next(null, plugins); - }); + async.filter(plugins, file.exists, next); }, ], callback); }; diff --git a/src/privileges/helpers.js b/src/privileges/helpers.js index 9df9d8cd7b..02e1bed879 100644 --- a/src/privileges/helpers.js +++ b/src/privileges/helpers.js @@ -8,12 +8,8 @@ var helpers = {}; helpers.some = function (tasks, callback) { async.some(tasks, function (task, next) { - task(function (err, result) { - next(!err && result); - }); - }, function (result) { - callback(null, result); - }); + task(next); + }, callback); }; helpers.isUserAllowedTo = function (privilege, uid, cid, callback) { diff --git a/src/rewards/index.js b/src/rewards/index.js index 4ba403fce8..398abfb8f3 100644 --- a/src/rewards/index.js +++ b/src/rewards/index.js @@ -37,12 +37,14 @@ rewards.checkConditionAndRewardUser = function (uid, condition, method, callback function (rewards, next) { async.filter(rewards, function (reward, next) { if (!reward) { - return next(false); + return next(null, false); } - checkCondition(reward, method, next); - }, function (eligible) { - if (!eligible) { + checkCondition(reward, method, function (result) { + next(null, result); + }); + }, function (err, eligible) { + if (err || !eligible) { return next(false); } From 11f7cc416363b7fb116feae135ffecf721acd62f Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Mon, 2 Jan 2017 23:03:34 -0700 Subject: [PATCH 053/122] Pass tests --- public/logo.png | Bin 7189 -> 3680 bytes src/controllers/admin/themes.js | 6 +++--- src/plugins.js | 4 +--- src/plugins/load.js | 4 ++-- src/webserver.js | 4 ++-- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/public/logo.png b/public/logo.png index 6a6c184126221ac0b44a53d08ef3fe012ed73b45..d8dcba4638cbdf043ad23c7426a73f0743dadd0d 100644 GIT binary patch literal 3680 zcmc(idpMifzQ?;~`pk5u7o>_26_=2-gerBb%cg=vYY0LUYQ*jkks6~)wWO!5OT=ZW zN$5;MiwsH_(^by}s`mET ze7?zag!b#1wPI`QYl(WDRYzex&gYEOwHvUkql~9) z+l9Bhh`5S_*G`j%hKX%szTgj6q`x%`{F@&MR;(X#lZ>c#q^tzL>Y zqc%%ZDx^(63Bypak2na4B;BFn{jK@lT9-EqFAh)l8}Ew`AJJCxjun2M*YeTiOS_gy z{hg z)~uMIEcCACpVSh1R@;I!-ME9EPL;N@7Qr;ju|n+m#G3kjRUsr{SrMMJAs(>_By~a{OQK5d~ zy!DP)IareLrmyw82w*g9bp+n{3a@WdR@-()oRV*s!qK$SXjNew!{uPJfx6GrS~vn> zDj&6GUZSiA>+NjT*_RAT1Udo_{EWkjJYeUa%4cOboF>vA7sH8;243F%j8 z?yR`kcz=WI2FbUM@+T_*Km6U0QA1to$Q(aEK$C;?2P26@e;XS*Qw!;@s%!EkA{32U z%HzT1N9Uhitbl9>4ZM`thDbpJKWxs9|8Za65A4>PhX~*P`Hk85iQfECMq`DoZ^kK-ckxj)@T~S>KxZwTccPIAEUIu!!!A5Lgi$MZJqN3%;DNNj2)Iz7r%TH zT991C6#N}OL#tlYbFSiRnYn4uN79}%;x?~k);W`ILoJ{RPclDodltrGtoyHifwaV&YNrP2D8fe*8wf?e(6UCMs@9! z4Uh&+B%t1ZJyrc`Cq(2#{AHa>>02Z|WX40XokDp;O1-!F3`ul3g$%Jxl16QS;jEoLv zByrB8|D|6X9#0;k z0_kpnGt1tUP79$_6|N(U%pb(!KNai?AMX#8d>nQp`ioQFcQ3ccp$K4e@_#|Ko=z@T zhhIriMnXX(Bo5TMv~wyfG;vkw%5!RsD5^~M>-S8T?u+4i`;ic6d5h@f$@bW2k1V?^ z-D%lB=dQWFm2{?^(asd($ifa8C(8W7#}+_WLrlS+4Dimdg5SEhB8O?#V|2|J!sn5# zvs3jIh;K_88sBHH9HKUZ%z{{9${V<2iu)#2}tP4J)$t>`-`3V8a7_N`dbI;nFh8Pk|9=JEX{h=Gxx5q_4R8`oGvXQ$B>#y z9s&{{fBD0irPRgo^Q`OnOpypMWDy7OWVT3D3eUy><}3yrYvsRde8>Ma@L3#-?YOzI zWWVuYho@uJ@d+^?lwNV#cx2xui8i@}0ZeX1B>HrfBgwmdM^-VK>QuQRh(tir&^|Cg z1ONg`?OhYr8RJ*h7a+Lu4xNG_Eg$@BZ-2mr>pL^-qp3F}=~?^v8ejy*ExiB$fXod^ zDl5`~=kgotY%xNhr`jsfo_E|@hdqg^MpM277+r zQ-j|9hIa6AlDmo&K&R9O7cIdTkiC)uy2=T>#EzOww$+SaKsJvf15h!Kqoll#(m%IG8S4pOFHA{3M;4|xzKnl8^*sE_yWFT; zEJ$rY)e}j-r2#xwn#GVjBZVh!rCWyN;LMqTd%4{XNFMe$R`;OdK9jCx@}M4ri#$Lx z&#?j^Bh_sv9&BCjyObtxP}h#(K(Vp~X(k&I+F;*W#f9oKIfxSo76MX+^yZ$z6*Mg` zL(b>mEDAex06I_d7<(T`aOF3%`O;`U;~RG_eJ?Ug#ZWGfA>VhYnytJR|H>t*7vNk2r-(PmB!~!2b(}#g4fs+{CRKBXgI(tq z-o@`u!R(oizYu^@i!w6JsVm*j*br$YpNTsrUzd-+ldpy++GaXbsE$wIoMuUn<1{&s z084TcMN|S72Fx!1M^65!8Jnn4myH|2#T!vJXX#8|&5Nuj=1~n$#cv1zpcbRszk-8Z zy<~qwy2}Q=C~b3`{HB!ou0y>SPK+qN{|eD#6ILolqbi%!;{wqz_du?VH2rkfnylcC zHvzF&mHzn2^pv#XsOyGZ;#D>Pz`+g~f9X7Hl#Xhsn}+~-MnL=dnf;{oq0Q? zit)8n9Ry|{3SU3mMmIN6oIsGN7sC^__?9Vi&J@Ug97)mi(y09BXp7-}il&hL^`aQ# zdMvmeQ)kBI4@L95yF*Q}MsDgLAqOUCX7M2vw%2(AuMv=Wixm z+dQ~@I4~920;d@5kET(vc!Vh$#(i~!FTt20kFhTU!%IWK*l;rcq6&AH30U8_#^u6R z(q93Q2T)G2ZA@>%y@dRy%guSdEmUf$CN~#HB9g_PL^2(qaM7Tsbdlt*i6mAraApX0 z(I+98?uLV*fmk0F;!ZoJNmQ!djb=psyuoQ(MEP;GW2a!O-k$^r1xKo4luCf58=P}j z3&EA7*7pN|2Q-PHYqi(-YH~P-?+T!_qau){MN*1Zy+0nNH{V(5DkjqELP!_I3!BA5zsn+@W)*x8&8;e;|O{^%`J9ECC@A1w@YV>{};ZuY5e@TO6PK zaoCfP6Op4@ZV8@?w9v9YRDJkuw*J;|c>i5X(tNF8`(c4j1Zefd#`>5Hvm* zg!;#0x(C37dNNZG2ud=!BTN^J)o>et4Mjm?H5b@bG#4a40#=CehEy`2_okrnC)FG0 zP@&QDqjX{4O-_jwYIEl&p@r^$WJmP>HfA3wNX|;e<5uYvV9U4%h4l5Pb^q?>e*+Ug BPY?hA literal 7189 zcmeHM_fr!<(~gKrQ+g5Uy(3k6Cp0lMLApq4nZxnHWhMpP8O$#G&io2PU`s!K+003g#|B+iE<*Gq9iwuFJRMd5HPU>j>57I*OBpJEhmZ5fv4#AHIj|!-zRo!wr2qq|`{{Lj)8!+0-zk`+$UJ zarcY@HIyP@w9B{X3aBWH@lhcFZT_FP|7-Gp@{3W+;={dLf@@bpL;y9CC7WQn1KrQD zuwklfkyv#uPAxHZ!lgr>Bel}4Ey{#;P=b^E(*s?>fO?)oJvK@MyY#TiP-H<_pOev% zU>zw;Jh6)}W_#`6=jZAs`V-m#t;buipwpfZbCRQH`M1i5kMJtaL7#d19lbXPy(~on zxSCZEKAHn1cv=`*q&zBv#&}9=_icrQm$>7&UFY9bOQz#mH#;|Yw4+rHqqDomc;iCX zd2Kkg(6At1oeWgj`ybFIQS~0)rLfq5XequPo|BCGuRu_WE_F) z(cC3Zu|C1D=xdZKAfBQ_3Tmqww)t1wSD1$0uyZEB%$Sq7iW%s(eTP$#3^5hv5=zK~ z1;=3rMz!sE_L91whsVi9fW9)&XYYe_CAv1EMts|8AGo;Th-KAActK#{MW0uDLJ~uK zxez4!YSi)j=u@;qGhYf16@DB$=TTS@w<6|_H1_ud|rau`t7M5LX zuwWZP7R(NzF6~)m?A_r%TNXF?7wgB z%6p+VDUl(mZA_PK=rTL|!B6*Lq1CSf`+o+3*(y;238M!rjfy0(qzOA})zYQKZ<8xJ z;)X^8_Vr(Pb3GL8DzyRT{hXlH?}R!Np?Ss{X+J`fH1%;g*>x93?6_xk8S@Xcn?9!7 zNY|cs4m*xpEyN~$z&{9Yc^5iM`is}am|TN5VN%=jIwg1S{aCgDq`i&?rB~T8>@3H_54L zDqmcogr`^Fh3o8aC4u*Xg?9-83M0EpPr+UP69~JjZDAz*tGGF8evNUNe!6J7KZHH^ zklAFh#v}3XN3zAxlLn^f`{fO(JVt@ZRk2sUmiy#rAMW}EETjQZMFvjQbHICxoCkW1 z448;5dEjeuI%VMYk9FkmE8j2~ySE<352j+1PQS||q`vH>mxZUS7o9V~YSlYs1W+0# z5(`e^7(W$RwSE-dJ(1wb5S zR45BKDm-EW04ejk@u{v2l7o?*rP(7P7qegfvIy#6Zms5RhnM&J#7Qn`@+CKQ#1Lkl zP$!{!-ZPovz~lXtuaRrod7$1QMaq|Y@UqKSVA>_D46*vhEN|wL)$OK8&&3~=&5;YH z5pfvq;ivgA&!i)mOR+@nu7}#k-gKy89BFb0+YLK?FL*K)l(&knx;xaX8&sfYTol!5 z7Sx*TF?nLKEq7AAKZ?I+8y}+u8e6igF%o@Q{koN&C7i?1<{h}HiQ&?53*&(wXcHtl#{f0>mzc=82d3;Z5Bc+GB>iun?- zvQ^Lh0H6)hv;Rl;t=?|uT>`j;l{bb}dZNS9a^{PQ-WZX~!sz9T33dB>PU}y(m7exj zTvaX_a6t|$5U6XokY=aURG>xNJ8TG7%~8)GmUr-c2BNC_H76}I zLEmzfnxCk;A3RA>;!3}k(JlAEzD^!dktsZu!F}ZNTSV)gKogm^1yyMcSIopF-7uFe z;witzc#pAD*5HfVqSizBnkp$RWceD+!i2sYN0K6K?0K8H4n@L;Dof=_+XiV%=l1&9 zpK-WS!WT%k`_)fV8I-3x-RCu$>qzc5UB3HUU?<3z;!?SXg>5MP0Z>L9cyn*zRNW8poW3A}~A#<|(~oe zhcdojf%kaEonGAP(I}(0rERs+8p?i-8ucYb=$zVEH3(K@&=iafJAD5b!Tv+5i&CMo z?SdQ7(6Q-fR)QzfAQ^{jR=%E`$JA*AKwXcAF^ZuotVM-pe=XzeL*{Lf@(7>LSz~E2 z24|KD1z}H&=^Re$K(NENjN74l^=4dQA%_Xa(?mtlxIVd0pbXZO}iIVhkz-{41=G)($BqK@}S{%0Na#sZrW@Ng$mJZ`qm~J_v#!OwbrJ&)L z^9tLnGVU{>n-{sGx_2a(CSHRrq6vJ;&(Gq}@3?|PSl$yor_i3H()c?y^k_;kl={li z?@)r;j=o31NxG3&79Mf%@Cc;x{$*`6VcwJEqKW!}tnnt8_a6L{Fz-S1ejMVA-CFwz zHj|+v%WDT*UV_*U9G8pkjDJq7q4rZVJbibVqsc8FU)x4x>G>fdG-zongyP+rpgfYI zaeXeH>BpS)qQ=PlyEyjypI03PQ17Uw!NHE~^4udTJ> ziEx__GUjkuDI+M-eJon}C|!xSVhvgAXk4%pJkolQLIPAC@O}&PtjsKHJG_epUt3Si z-p@$%G;?uQZ*8wk7ytFV(;>$^3c>R|_vth#k-nwZIx6bPsHD#3AXZEAS{l*%Zf5?` z5bi2G7AA~mbylbPd$#?r>vGV76N$HZKKHae%v;ohp3Z#ls|o5EMW491g5~Y@%^V-F%gXoD{8@tZcz z!G&`h{-QMV`l92u*IBREp&rm;Hrf+>4OvuwO)URL$rFW%v;zZ3A?xDX!Wz5}?D#4| z&HEI%b6@7(LC79;EKJczSf7g6&D*|bZb!yTyd$Y|KfrPNZB;#gc8RQCdfytp0Kvoj zu~6D%8u@x+NP*)YjUKD=uJifhf#o4MDy1##!IE&X!e$fiXmX$G%hTV=Sumds#;BGZ8W zUUXjBzc&pX?+9*-rgXV9@v^&w&V}}64(p1d1t}F(S#n#pNWne{l17QG*>E<*IAs z5YpP|BC+SS1w4n~b;xnG7oHK(*Q4cgBwbZrA2c8&+LI%(`R%7aTx%Q7!fGT@#J^>5 z)tlSsF=^AKLv#Qad`#9op;3z5lg(AN3x57=Kw57h01ZDLL0gd*@T(>clJ=~@ zwgB40B?j$&8!5Gl5uI$!WItI`behP)^rLZB1MheYU60TpMxTm5p{2aW##lXYKYb$+ zA9ed*tx@Ge!L91{PbwS%FH`Qa8w;R-eCHK)kW0-R@N?n%`u44b7UB88X11^7&%|Q( ze5<6$s@M$r-wQ`0E- z)NXylq^%>B*vpHbhbwIBHYs()WlY0-${6RiEx@}@29Np8%HtaDY0HcPJJH~TG@c7e zC{Oq=6EX1(pa=7QP;)(p^}TYI=8H=`E|2Dn-%+zSP`X*c?h}+9Hgh|4Mz%X0M}-8X zEdHulTf~=u(Cas+U;RaYf?Od|m5R-dG1I3~bgbuYP{?%?b-YWfO@}Sdm_8plaXQVX z*|vm}9?!~N#OIk^zz3d)?sI;sKa3wIpter4qOt-QiENkF_{N%qJ!Apg&F~b}+JDrRQD z&leuKdD-;r67W*Aa!UQy!V(bha7#-znK?W;c#&n&5Ox6u@ z4-YpH#mGa|buet0Yk3`!Ho(kiNnRS_6>7XZZEr!VD%|1^aH`I5N(!y_>Tp)NK7mis ztAWo~hSb$g{9Q209%8Si?0{_nQp%}DfkXgD%os^!OqW+I7g3ehxJ!0`Ar^Z7-emcmgxVBA)*_-qT)7fwqWd zGv=V{4+|B>uQDOmg!Y;GGJYjXAISN#H2YQ4N;+uspB8&inh3Zw?olv;<0BTtH_Vj_XVo(qe9thC&OLNl-nf>8aEW(fR%!~#DL3LJ zIEgoc7c^>HVvHf>1g1Am)v1+j%WZ#2lkgJn^YLmbVQ};}!^br*lUq(0*|#hJj;cCG z1Fx&}oHgC2hfRL(zd5B1Ew6qbzDyXx?zFCZX*a{dXVkvzSESRnGAJ*Wjm>^B%7Q0u z51zjquLJJAN3lK48+ntZpLdmw+QjxQ$tY7Vb@j$ z+ww^{`0r^k5^s$1?B|7WsqBTfL1$B3qA$(Po|4JTd9L%g>q;e8RoE-;+%hPbECdy zOHJ5_n{(FmD3@M4F%C*7)b!31LJLXbbOH!6*PTYvK?}?|EAHGxe0jRtw^yCTX|CBG zdsWlP4i6g8dp{zIgjGmGI*hPo?%H|*?TbpmyIj%4Lds;;=I7;W4y<`fsJ%vX~3trmB$y@o&)&srPLd(VmxW{teXU_G_Iw0sJDe>FOf27Ky*-_{U1^mm;9|vFib4m zK;a&f#GhRsI_VK>Ik4yN@wNrXs^_q zC-cUi=N{Gs1}=FY;Q2q?R*Ts0U3lN&E(kA2!f<-Ii8NsuEX8=i7JEzUW z+mupQblhpf=#@G>F~=8k$vf6F3|X=s>H#WWMPE6tlQWg1UM~b6827?kgo3AaE0isaG;ls=`+$r0tq8v5r=?d@=PbO8NNB&+0(wCr{pX|iBHc6 ze|th&AqoqUoL|%j(&;4&8PC0Aj-6Xu4zxvlF3EGR?8_X#|LNtaNZvZ{HItf-c6O^g zmKpy*Yewh|(GX{_h+wfmkBNwxj$#R2cjhdi)RJy%4Y)U4!zWar)-a!ouao|8qrm8s zg;PJ=nNEYg54~L;$n!;`mznj?o>83fZhQR6&gsZjTl5URai2<;-s~+*K(aJ&n%1>Z zV(XlnDcybaPL}~GHw}nJ{tsc89> zLQ1Q)li#Ff6jdc97$!T{Rm<>CS5qj=I55_{yWX2H`1~jjzV3ot@{TH_NWHr0xS7-O@8BjLrWlSzE8>ycS^;0_fZpH5_9A8jd#YdrRRvkM(O4?-xen5B_D?zkv8GtUb$7Jhpf&i`qa2VK>6NN61oYGMJY zmgUC&1Ua@js#?qDp9}UUqHJf9o*X*Nr5R*fgt-B23)$@F`|6b=XHK5~o^O*q)NxIb zq_b5gd24jy`wFL;QJ%}{o-D=SkyzH)=Vub>tr&n5-1*+62q`$Ont1>g89yv7lotub zfRt!X!th-c)4{6Jj*9AX(UZ@pdKb<;cA^;~J5rV2!fpd;!O&C1N}LZ;UaK(yK4?L& z(lkY5{71iVR*RY576jW`2o7zBliPD}#y|f%#S-$* znChB_^pMLx#Pr^jtja{h>XAKrd~9=Pk{)f39(a1u zw|D7v#+BW1Z-IT0R5T7~fBa91%5D&}vnti8DYbsE%tmP57LHk^n~Q>ZPT6VCF|{Yg zK50)nDflN=+r#zutqjfp*1`?5B6}3!buNy!P%rd4?tZ32mjWm}w^A0{1yeQ#r2ZK^btC%=yVy>sGOVLWY zCjH~@D?xe{Ca;qAVEW`1i;>ogl@Ru&OIt<#ofug5N8Os>abEOod9~_`4!2-vXxai_3?d<7S@rt>0bxcK>0L_=t?~N^tucki~Y}&`= z9T4<3p=;FxvUFhz0tAXrpAY7T$>4S?C@a3$= ' + staticDir + '\' not found.'); } - callback(); + callback(err); }); } } diff --git a/src/webserver.js b/src/webserver.js index fec42974c6..43e3c4b324 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -262,11 +262,11 @@ module.exports.testSocket = function (socketPath, callback) { var file = require('./file'); async.series([ function (next) { - file.exists(socketPath, function (exists) { + file.exists(socketPath, function (err, exists) { if (exists) { next(); } else { - callback(); + callback(err); } }); }, From 541f51e947abfac5f3aa7b8c1138907df42f7803 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 3 Jan 2017 13:38:06 -0500 Subject: [PATCH 054/122] restrict flags interface so that moderators only see flags from cids they can actually moderate --- src/controllers/mods.js | 39 +++++++++++++++++++++++++++++-- src/flags.js | 52 ++++++++++++++++++++++++++++++++++------- test/flags.js | 35 +++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 10 deletions(-) diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 242d68d708..8056b8c5b5 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -27,6 +27,7 @@ modsController.flags.list = function (req, res, next) { } // Parse query string params for filters + var hasFilter = false; var valid = ['assignee', 'state', 'reporterId', 'type', 'targetUid', 'cid', 'quick']; var filters = valid.reduce(function (memo, cur) { if (req.query.hasOwnProperty(cur)) { @@ -35,6 +36,24 @@ modsController.flags.list = function (req, res, next) { return memo; }, {}); + hasFilter = !!Object.keys(filters).length; + + if (res.locals.cids) { + if (!filters.cid) { + // If mod and no cid filter, add filter for their modded categories + filters.cid = res.locals.cids; + } else { + // Remove cids they do not moderate + if (Array.isArray(filters.cid)) { + filters.cid = filters.cid.filter(function (cid) { + return res.locals.cids.indexOf(String(cid)) !== -1; + }); + } else if (res.locals.cids.indexOf(String(filters.cid)) === -1) { + filters.cid = res.locals.cids; + hasFilter = false; + } + } + } async.parallel({ flags: async.apply(flags.list, filters, req.uid), @@ -45,9 +64,25 @@ modsController.flags.list = function (req, res, next) { return next(err); } + // If res.locals.cids is populated, then slim down the categories list + if (res.locals.cids) { + data.categories = data.categories.filter(function (category) { + return res.locals.cids.indexOf(String(category.cid)) !== -1; + }); + } + // Minimal returned set for templates.js data.categories = data.categories.reduce(function (memo, cur) { - memo[cur.cid] = cur.name; + if (!res.locals.cids) { + memo[cur.cid] = cur.name; + return memo; + } + + // If mod, remove categories they can't moderate + if (res.locals.cids.indexOf(String(cur.cid)) !== -1) { + memo[cur.cid] = cur.name; + } + return memo; }, {}); @@ -55,7 +90,7 @@ modsController.flags.list = function (req, res, next) { flags: data.flags, analytics: data.analytics, categories: data.categories, - hasFilter: !!Object.keys(filters).length, + hasFilter: hasFilter, filters: filters, title: '[[pages:flags]]' }); diff --git a/src/flags.js b/src/flags.js index ecc5a84e3e..168eb5a11e 100644 --- a/src/flags.js +++ b/src/flags.js @@ -53,31 +53,45 @@ Flags.list = function (filters, uid, callback) { } var sets = []; + var orSets = []; + var prepareSets = function (setPrefix, value) { + if (!Array.isArray(value)) { + sets.push(setPrefix + value); + } else if (value.length) { + value.forEach(function (x) { + orSets.push(setPrefix + x); + }); + } else { + // Empty array, do nothing + return; + } + }; + if (Object.keys(filters).length > 0) { for (var type in filters) { switch (type) { case 'type': - sets.push('flags:byType:' + filters[type]); + prepareSets('flags:byType:', filters[type]); break; case 'state': - sets.push('flags:byState:' + filters[type]); + prepareSets('flags:byState:', filters[type]); break; case 'reporterId': - sets.push('flags:byReporter:' + filters[type]); + prepareSets('flags:byReporter:', filters[type]); break; case 'assignee': - sets.push('flags:byAssignee:' + filters[type]); + prepareSets('flags:byAssignee:', filters[type]); break; case 'targetUid': - sets.push('flags:byTargetUid:' + filters[type]); + prepareSets('flags:byTargetUid:', filters[type]); break; case 'cid': - sets.push('flags:byCid:' + filters[type]); + prepareSets('flags:byCid:', filters[type]); break; case 'quick': @@ -90,14 +104,36 @@ Flags.list = function (filters, uid, callback) { } } } - sets = sets.length ? sets : ['flags:datetime']; // No filter default + sets = (sets.length || orSets.length) ? sets : ['flags:datetime']; // No filter default async.waterfall([ function (next) { if (sets.length === 1) { db.getSortedSetRevRange(sets[0], 0, -1, next); + } else if (sets.length > 1) { + db.getSortedSetRevIntersect({ sets: sets, start: 0, stop: -1, aggregate: 'MAX' }, next); } else { - db.getSortedSetRevIntersect({sets: sets, start: 0, stop: -1, aggregate: 'MAX'}, next); + next(null, []); + } + }, + function (flagIds, next) { + // Find flags according to "or" rules, if any + if (orSets.length) { + db.getSortedSetRevUnion({ sets: orSets, start: 0, stop: -1, aggregate: 'MAX' }, function (err, _flagIds) { + if (err) { + return next(err); + } + + if (sets.length) { + // If flag ids are already present, return a subset of flags that are in both sets + next(null, _.intersection(flagIds, _flagIds)); + } else { + // Otherwise, return all flags returned via orSets + next(null, _.union(flagIds, _flagIds)); + } + }); + } else { + setImmediate(next, null, flagIds); } }, function (flagIds, next) { diff --git a/test/flags.js b/test/flags.js index dfa6f1a773..9df1a11a2b 100644 --- a/test/flags.js +++ b/test/flags.js @@ -203,6 +203,41 @@ describe('Flags', function () { done(); }); }); + + it('should return a flag when filtered by both cid 1 and 2', function (done) { + Flags.list({ + cid: [1, 2] + }, 1, function (err, flags) { + assert.ifError(err); + assert.ok(Array.isArray(flags)); + assert.strictEqual(1, flags.length); + done(); + }); + }); + + it('should return one flag if filtered by both cid 1 and 2 and open state', function (done) { + Flags.list({ + cid: [1, 2], + state: 'open' + }, 1, function (err, flags) { + assert.ifError(err); + assert.ok(Array.isArray(flags)); + assert.strictEqual(1, flags.length); + done(); + }); + }); + + it('should return no flag if filtered by both cid 1 and 2 and non-open state', function (done) { + Flags.list({ + cid: [1, 2], + state: 'resolved' + }, 1, function (err, flags) { + assert.ifError(err); + assert.ok(Array.isArray(flags)); + assert.strictEqual(0, flags.length); + done(); + }); + }); }); }); From cc96e329705bf2c61804fb631b3d6694d450702f Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 9 Jan 2017 18:16:48 +0300 Subject: [PATCH 055/122] closes #5352 --- src/topics/tools.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/topics/tools.js b/src/topics/tools.js index c69b0692ab..5363650a1e 100644 --- a/src/topics/tools.js +++ b/src/topics/tools.js @@ -56,9 +56,9 @@ module.exports = function (Topics) { topicData.deleted = isDelete ? 1 : 0; if (isDelete) { - plugins.fireHook('action:topic.delete', topicData); + plugins.fireHook('action:topic.delete', {topic: topicData, uid: uid}); } else { - plugins.fireHook('action:topic.restore', topicData); + plugins.fireHook('action:topic.restore', {topic: topicData, uid: uid}); } var data = { @@ -225,7 +225,7 @@ module.exports = function (Topics) { var uniqueCids = _.unique(topicData.map(function (topicData) { return topicData && parseInt(topicData.cid, 10); })); - + if (uniqueCids.length > 1 || !uniqueCids.length || !uniqueCids[0]) { return next(new Error('[[error:invalid-data]]')); } @@ -249,7 +249,7 @@ module.exports = function (Topics) { setImmediate(next); } } - ], next); + ], next); }, next); } ], callback); From ca7f834f53efcf439603b41470591deb7be87c65 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 9 Jan 2017 16:20:33 -0500 Subject: [PATCH 056/122] updating tx assets --- .tx/config | 94 +++++++++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/.tx/config b/.tx/config index a745278980..1621a4181f 100644 --- a/.tx/config +++ b/.tx/config @@ -753,6 +753,53 @@ trans.zh_CN = public/language/zh-CN/error.json trans.zh_TW = public/language/zh-TW/error.json type = KEYVALUEJSON +[nodebb.flags] +file_filter = public/language//flags.json +source_file = public/language/en-GB/flags.json +source_lang = en_GB +trans.ar = public/language/ar/flags.json +trans.bn = public/language/bn/flags.json +trans.bg = public/language/bg/flags.json +trans.cs = public/language/cs/flags.json +trans.da = public/language/da/flags.json +trans.de = public/language/de/flags.json +trans.el = public/language/el/flags.json +trans.en_US = public/language/en-US/flags.json +trans.en@pirate = public/language/en-x-pirate/flags.json +trans.es = public/language/es/flags.json +trans.et = public/language/et/flags.json +trans.fa_IR = public/language/fa-IR/flags.json +trans.fi = public/language/fi/flags.json +trans.fr = public/language/fr/flags.json +trans.gl = public/language/gl/flags.json +trans.he = public/language/he/flags.json +trans.hu = public/language/hu/flags.json +trans.id = public/language/id/flags.json +trans.it = public/language/it/flags.json +trans.ja = public/language/ja/flags.json +trans.ko = public/language/ko/flags.json +trans.lt = public/language/lt/flags.json +trans.ms = public/language/ms/flags.json +trans.nb = public/language/nb/flags.json +trans.nl = public/language/nl/flags.json +trans.pl = public/language/pl/flags.json +trans.pt_BR = public/language/pt-BR/flags.json +trans.pt_PT = public/language/pt-PT/flags.json +trans.ru = public/language/ru/flags.json +trans.ro = public/language/ro/flags.json +trans.rw = public/language/rw/flags.json +trans.sc = public/language/sc/flags.json +trans.sk = public/language/sk/flags.json +trans.sl = public/language/sl/flags.json +trans.sr = public/language/sr/flags.json +trans.sv = public/language/sv/flags.json +trans.th = public/language/th/flags.json +trans.tr = public/language/tr/flags.json +trans.vi = public/language/vi/flags.json +trans.zh_CN = public/language/zh-CN/flags.json +trans.zh_TW = public/language/zh-TW/flags.json +type = KEYVALUEJSON + [nodebb.tags] file_filter = public/language//tags.json source_file = public/language/en-GB/tags.json @@ -2022,53 +2069,6 @@ trans.zh_CN = public/language/zh-CN/admin/manage/categories.json trans.zh_TW = public/language/zh-TW/admin/manage/categories.json type = KEYVALUEJSON -[nodebb.admin-manage-flags] -file_filter = public/language//admin/manage/flags.json -source_file = public/language/en-GB/admin/manage/flags.json -source_lang = en_GB -trans.ar = public/language/ar/admin/manage/flags.json -trans.bn = public/language/bn/admin/manage/flags.json -trans.bg = public/language/bg/admin/manage/flags.json -trans.cs = public/language/cs/admin/manage/flags.json -trans.da = public/language/da/admin/manage/flags.json -trans.de = public/language/de/admin/manage/flags.json -trans.el = public/language/el/admin/manage/flags.json -trans.en_US = public/language/en-US/admin/manage/flags.json -trans.en@pirate = public/language/en-x-pirate/admin/manage/flags.json -trans.es = public/language/es/admin/manage/flags.json -trans.et = public/language/et/admin/manage/flags.json -trans.fa_IR = public/language/fa-IR/admin/manage/flags.json -trans.fi = public/language/fi/admin/manage/flags.json -trans.fr = public/language/fr/admin/manage/flags.json -trans.gl = public/language/gl/admin/manage/flags.json -trans.he = public/language/he/admin/manage/flags.json -trans.hu = public/language/hu/admin/manage/flags.json -trans.id = public/language/id/admin/manage/flags.json -trans.it = public/language/it/admin/manage/flags.json -trans.ja = public/language/ja/admin/manage/flags.json -trans.ko = public/language/ko/admin/manage/flags.json -trans.lt = public/language/lt/admin/manage/flags.json -trans.ms = public/language/ms/admin/manage/flags.json -trans.nb = public/language/nb/admin/manage/flags.json -trans.nl = public/language/nl/admin/manage/flags.json -trans.pl = public/language/pl/admin/manage/flags.json -trans.pt_BR = public/language/pt-BR/admin/manage/flags.json -trans.pt_PT = public/language/pt-PT/admin/manage/flags.json -trans.ru = public/language/ru/admin/manage/flags.json -trans.ro = public/language/ro/admin/manage/flags.json -trans.rw = public/language/rw/admin/manage/flags.json -trans.sc = public/language/sc/admin/manage/flags.json -trans.sk = public/language/sk/admin/manage/flags.json -trans.sl = public/language/sl/admin/manage/flags.json -trans.sr = public/language/sr/admin/manage/flags.json -trans.sv = public/language/sv/admin/manage/flags.json -trans.th = public/language/th/admin/manage/flags.json -trans.tr = public/language/tr/admin/manage/flags.json -trans.vi = public/language/vi/admin/manage/flags.json -trans.zh_CN = public/language/zh-CN/admin/manage/flags.json -trans.zh_TW = public/language/zh-TW/admin/manage/flags.json -type = KEYVALUEJSON - [nodebb.admin-manage-groups] file_filter = public/language//admin/manage/groups.json source_file = public/language/en-GB/admin/manage/groups.json From 1a0e4db466d5d7bdd25afbc4adef6cc34ee72df4 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 9 Jan 2017 16:22:55 -0500 Subject: [PATCH 057/122] removing duplicate strings from flags language file --- public/language/en-GB/flags.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/public/language/en-GB/flags.json b/public/language/en-GB/flags.json index 66b9acc92a..c4bfed6f23 100644 --- a/public/language/en-GB/flags.json +++ b/public/language/en-GB/flags.json @@ -27,7 +27,6 @@ "quick-links": "Quick Links", "flagged-user": "Flagged User", - "reporter": "Reporting User", "view-profile": "View Profile", "start-new-chat": "Start New Chat", "go-to-target": "View Flag Target", @@ -43,7 +42,6 @@ "back": "Back to Flags List", "no-history": "No flag history.", - "state": "State", "state-all": "All states", "state-open": "New/Open", "state-wip": "Work in Progress", From 611be77361e4d8e6a5cb01d3c826a403090d8ad3 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 10 Jan 2017 15:16:39 +0300 Subject: [PATCH 058/122] closes #5353 --- src/posts/edit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/posts/edit.js b/src/posts/edit.js index b989b24f8f..a538d3c695 100644 --- a/src/posts/edit.js +++ b/src/posts/edit.js @@ -66,7 +66,7 @@ module.exports = function (Posts) { postData.cid = results.topic.cid; postData.topic = results.topic; - plugins.fireHook('action:post.edit', _.clone(postData)); + plugins.fireHook('action:post.edit', {post: _.clone(postData), uid: data.uid}); cache.del(String(postData.pid)); pubsub.publish('post:edit', String(postData.pid)); @@ -137,7 +137,7 @@ module.exports = function (Posts) { function (tags, next) { topicData.tags = data.tags; topicData.oldTitle = results.topic.title; - plugins.fireHook('action:topic.edit', topicData); + plugins.fireHook('action:topic.edit', {topic: topicData, uid: data.uid}); next(null, { tid: tid, cid: results.topic.cid, From 1e9fabc5db03bf3f8c9da5ef6c83d92003ae98e6 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 10 Jan 2017 15:45:07 +0300 Subject: [PATCH 059/122] closes #5354 --- src/topics/fork.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/topics/fork.js b/src/topics/fork.js index d882cddf00..403331f902 100644 --- a/src/topics/fork.js +++ b/src/topics/fork.js @@ -2,15 +2,13 @@ 'use strict'; var async = require('async'); -var winston = require('winston'); + var db = require('../database'); -var user = require('../user'); var posts = require('../posts'); var privileges = require('../privileges'); var plugins = require('../plugins'); var meta = require('../meta'); - module.exports = function (Topics) { Topics.createTopicFromPosts = function (uid, title, pids, fromTid, callback) { @@ -55,11 +53,14 @@ module.exports = function (Topics) { } Topics.create({uid: results.postData.uid, title: title, cid: cid}, next); }, - function (results, next) { - Topics.updateTopicBookmarks(fromTid, pids, function () { next( null, results );} ); + function (_tid, next) { + Topics.updateTopicBookmarks(fromTid, pids, function (err) { + next(err, _tid); + }); }, function (_tid, next) { - function move(pid, next) { + tid = _tid; + async.eachSeries(pids, function (pid, next) { privileges.posts.canEdit(pid, uid, function (err, canEdit) { if (err || !canEdit.flag) { return next(err || new Error(canEdit.message)); @@ -67,14 +68,13 @@ module.exports = function (Topics) { Topics.movePostToTopic(pid, tid, next); }); - } - tid = _tid; - async.eachSeries(pids, move, next); + }, next); }, function (next) { Topics.updateTimestamp(tid, Date.now(), next); }, function (next) { + plugins.fireHook('action:topic.fork', {tid: tid, fromTid: fromTid, uid: uid}); Topics.getTopicData(tid, next); } ], callback); From dd9e286633ebcb4a0a6e309b63afa8e46c619639 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 10 Jan 2017 18:31:08 +0300 Subject: [PATCH 060/122] closes #5355 --- src/posts/delete.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/posts/delete.js b/src/posts/delete.js index 32ee6b6f41..d3f02a95da 100644 --- a/src/posts/delete.js +++ b/src/posts/delete.js @@ -42,7 +42,7 @@ module.exports = function (Posts) { ], next); }, function (results, next) { - plugins.fireHook('action:post.delete', pid); + plugins.fireHook('action:post.delete', {pid: pid, uid: uid}); next(null, postData); } ], callback); @@ -79,7 +79,7 @@ module.exports = function (Posts) { ], next); }, function (results, next) { - plugins.fireHook('action:post.restore', _.clone(postData)); + plugins.fireHook('action:post.restore', {post: _.clone(postData), uid: uid}); next(null, postData); } ], callback); @@ -149,7 +149,7 @@ module.exports = function (Posts) { if (err) { return next(err); } - plugins.fireHook('action:post.purge', pid); + plugins.fireHook('action:post.purge', {pid: pid, uid: uid}); db.delete('post:' + pid, next); }); } From 37bb6e9b6dec11cc15a3b1df047789ddafba2650 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 11 Jan 2017 13:59:27 +0300 Subject: [PATCH 061/122] action:user.removeUploadedPicture --- src/socket.io/user/picture.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/socket.io/user/picture.js b/src/socket.io/user/picture.js index eacc5197aa..0d8a57dd24 100644 --- a/src/socket.io/user/picture.js +++ b/src/socket.io/user/picture.js @@ -99,6 +99,9 @@ module.exports = function (SocketUser) { uploadedpicture: '', picture: userData.uploadedpicture === userData.picture ? '' : userData.picture // if current picture is uploaded picture, reset to user icon }, next); + }, + function (next) { + plugins.fireHook('action:user.removeUploadedPicture', {callerUid: socket.uid, uid: data.uid}); } ], callback); }; From 0c8aa599a0b66ef19667c6aaa2aea73d2b1e5bb8 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 11 Jan 2017 14:40:52 +0300 Subject: [PATCH 062/122] closes #5357 --- src/socket.io/user/profile.js | 2 +- src/user/profile.js | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/socket.io/user/profile.js b/src/socket.io/user/profile.js index 8a59fbbff2..fbd9632ed6 100644 --- a/src/socket.io/user/profile.js +++ b/src/socket.io/user/profile.js @@ -148,7 +148,7 @@ module.exports = function (SocketUser) { data.email = oldUserData.email; } - user.updateProfile(data.uid, data, next); + user.updateProfile(socket.uid, data, next); }, function (userData, next) { function log(type, eventData) { diff --git a/src/user/profile.js b/src/user/profile.js index 37b280612f..01caa931cf 100644 --- a/src/user/profile.js +++ b/src/user/profile.js @@ -16,6 +16,9 @@ module.exports = function (User) { var fields = ['username', 'email', 'fullname', 'website', 'location', 'groupTitle', 'birthday', 'signature', 'aboutme']; + var updateUid = data.uid; + var oldData; + async.waterfall([ function (next) { plugins.fireHook('filter:user.updateProfile', {uid: uid, data: data, fields: fields}, next); @@ -27,14 +30,18 @@ module.exports = function (User) { async.series([ async.apply(isAboutMeValid, data), async.apply(isSignatureValid, data), - async.apply(isEmailAvailable, data, uid), - async.apply(isUsernameAvailable, data, uid), + async.apply(isEmailAvailable, data, updateUid), + async.apply(isUsernameAvailable, data, updateUid), async.apply(isGroupTitleValid, data) ], function (err) { next(err); }); }, function (next) { + User.getUserFields(updateUid, fields, next); + }, + function (_oldData, next) { + oldData = _oldData; async.each(fields, function (field, next) { if (!(data[field] !== undefined && typeof data[field] === 'string')) { return next(); @@ -43,21 +50,20 @@ module.exports = function (User) { data[field] = data[field].trim(); if (field === 'email') { - return updateEmail(uid, data.email, next); + return updateEmail(updateUid, data.email, next); } else if (field === 'username') { - return updateUsername(uid, data.username, next); + return updateUsername(updateUid, data.username, next); } else if (field === 'fullname') { - return updateFullname(uid, data.fullname, next); + return updateFullname(updateUid, data.fullname, next); } else if (field === 'signature') { data[field] = S(data[field]).stripTags().s; } - User.setUserField(uid, field, data[field], next); + User.setUserField(updateUid, field, data[field], next); }, next); }, function (next) { - plugins.fireHook('action:user.updateProfile', {data: data, uid: uid}); - User.getUserFields(uid, ['email', 'username', 'userslug', 'picture', 'icon:text', 'icon:bgColor'], next); + User.getUserFields(updateUid, ['email', 'username', 'userslug', 'picture', 'icon:text', 'icon:bgColor'], next); } ], callback); }; From 367078056e89666b05aae60f0c518160bb735162 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 11 Jan 2017 14:41:31 +0300 Subject: [PATCH 063/122] add hook --- src/user/profile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/user/profile.js b/src/user/profile.js index 01caa931cf..c25dd3bf83 100644 --- a/src/user/profile.js +++ b/src/user/profile.js @@ -63,6 +63,7 @@ module.exports = function (User) { }, next); }, function (next) { + plugins.fireHook('action:user.updateProfile', {uid: uid, data: data, fields: fields, oldData: oldData}); User.getUserFields(updateUid, ['email', 'username', 'userslug', 'picture', 'icon:text', 'icon:bgColor'], next); } ], callback); From a13c6f8c65acf44fefa32f0d4119b2d8b01b0999 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 11 Jan 2017 09:43:22 -0500 Subject: [PATCH 064/122] adding a safeguard into flags upgrade script @baris --- src/upgrade.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/upgrade.js b/src/upgrade.js index 89fe87f8d7..b860a642ba 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -345,6 +345,11 @@ Upgrade.upgrade = function (callback) { return next(err); } + // Adding in another check here in case a post was improperly dismissed (flag count > 1 but no flags in db) + if (!data.uids.length || !data.reasons.length) { + setInterval(next); + } + // Just take the first entry var datetime = data.uids[0].score; var reason = data.reasons[0].split(':')[1]; From bbc02dcc5d678546be920a4fc37ca4e917e4887b Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 11 Jan 2017 09:44:54 -0500 Subject: [PATCH 065/122] lol wtf --- src/upgrade.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/upgrade.js b/src/upgrade.js index b860a642ba..8dce35b901 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -347,7 +347,7 @@ Upgrade.upgrade = function (callback) { // Adding in another check here in case a post was improperly dismissed (flag count > 1 but no flags in db) if (!data.uids.length || !data.reasons.length) { - setInterval(next); + return setImmediate(next); } // Just take the first entry From 7bbb05637ceee51d7fa9ab0c7883df7214326d3c Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 11 Jan 2017 13:20:26 -0500 Subject: [PATCH 066/122] flag translations and fallbacks --- public/language/ar/flags.json | 60 ++++++++++++++++++++++++++ public/language/bg/flags.json | 60 ++++++++++++++++++++++++++ public/language/bn/flags.json | 60 ++++++++++++++++++++++++++ public/language/cs/flags.json | 60 ++++++++++++++++++++++++++ public/language/da/flags.json | 60 ++++++++++++++++++++++++++ public/language/de/flags.json | 60 ++++++++++++++++++++++++++ public/language/el/flags.json | 60 ++++++++++++++++++++++++++ public/language/en-US/flags.json | 60 ++++++++++++++++++++++++++ public/language/en-x-pirate/flags.json | 60 ++++++++++++++++++++++++++ public/language/es/flags.json | 60 ++++++++++++++++++++++++++ public/language/et/flags.json | 60 ++++++++++++++++++++++++++ public/language/fa-IR/flags.json | 60 ++++++++++++++++++++++++++ public/language/fi/flags.json | 60 ++++++++++++++++++++++++++ public/language/fr/flags.json | 60 ++++++++++++++++++++++++++ public/language/gl/flags.json | 60 ++++++++++++++++++++++++++ public/language/he/flags.json | 60 ++++++++++++++++++++++++++ public/language/hu/flags.json | 60 ++++++++++++++++++++++++++ public/language/id/flags.json | 60 ++++++++++++++++++++++++++ public/language/it/flags.json | 60 ++++++++++++++++++++++++++ public/language/ja/flags.json | 60 ++++++++++++++++++++++++++ public/language/ko/flags.json | 60 ++++++++++++++++++++++++++ public/language/lt/flags.json | 60 ++++++++++++++++++++++++++ public/language/ms/flags.json | 60 ++++++++++++++++++++++++++ public/language/nb/flags.json | 60 ++++++++++++++++++++++++++ public/language/nl/flags.json | 60 ++++++++++++++++++++++++++ public/language/pl/flags.json | 60 ++++++++++++++++++++++++++ public/language/pt-BR/flags.json | 60 ++++++++++++++++++++++++++ public/language/pt-PT/flags.json | 60 ++++++++++++++++++++++++++ public/language/ro/flags.json | 60 ++++++++++++++++++++++++++ public/language/ru/flags.json | 60 ++++++++++++++++++++++++++ public/language/rw/flags.json | 60 ++++++++++++++++++++++++++ public/language/sc/flags.json | 60 ++++++++++++++++++++++++++ public/language/sk/flags.json | 60 ++++++++++++++++++++++++++ public/language/sl/flags.json | 60 ++++++++++++++++++++++++++ public/language/sr/flags.json | 60 ++++++++++++++++++++++++++ public/language/sv/flags.json | 60 ++++++++++++++++++++++++++ public/language/th/flags.json | 60 ++++++++++++++++++++++++++ public/language/tr/flags.json | 60 ++++++++++++++++++++++++++ public/language/vi/flags.json | 60 ++++++++++++++++++++++++++ public/language/zh-CN/flags.json | 60 ++++++++++++++++++++++++++ public/language/zh-TW/flags.json | 60 ++++++++++++++++++++++++++ 41 files changed, 2460 insertions(+) create mode 100644 public/language/ar/flags.json create mode 100644 public/language/bg/flags.json create mode 100644 public/language/bn/flags.json create mode 100644 public/language/cs/flags.json create mode 100644 public/language/da/flags.json create mode 100644 public/language/de/flags.json create mode 100644 public/language/el/flags.json create mode 100644 public/language/en-US/flags.json create mode 100644 public/language/en-x-pirate/flags.json create mode 100644 public/language/es/flags.json create mode 100644 public/language/et/flags.json create mode 100644 public/language/fa-IR/flags.json create mode 100644 public/language/fi/flags.json create mode 100644 public/language/fr/flags.json create mode 100644 public/language/gl/flags.json create mode 100644 public/language/he/flags.json create mode 100644 public/language/hu/flags.json create mode 100644 public/language/id/flags.json create mode 100644 public/language/it/flags.json create mode 100644 public/language/ja/flags.json create mode 100644 public/language/ko/flags.json create mode 100644 public/language/lt/flags.json create mode 100644 public/language/ms/flags.json create mode 100644 public/language/nb/flags.json create mode 100644 public/language/nl/flags.json create mode 100644 public/language/pl/flags.json create mode 100644 public/language/pt-BR/flags.json create mode 100644 public/language/pt-PT/flags.json create mode 100644 public/language/ro/flags.json create mode 100644 public/language/ru/flags.json create mode 100644 public/language/rw/flags.json create mode 100644 public/language/sc/flags.json create mode 100644 public/language/sk/flags.json create mode 100644 public/language/sl/flags.json create mode 100644 public/language/sr/flags.json create mode 100644 public/language/sv/flags.json create mode 100644 public/language/th/flags.json create mode 100644 public/language/tr/flags.json create mode 100644 public/language/vi/flags.json create mode 100644 public/language/zh-CN/flags.json create mode 100644 public/language/zh-TW/flags.json diff --git a/public/language/ar/flags.json b/public/language/ar/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/ar/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/bg/flags.json b/public/language/bg/flags.json new file mode 100644 index 0000000000..138feac5c5 --- /dev/null +++ b/public/language/bg/flags.json @@ -0,0 +1,60 @@ +{ + "state": "Състояние", + "reporter": "Докладвал", + "reported-at": "Докладвано на", + "description": "Описание", + "no-flags": "Ура! Няма намерени доклади.", + "assignee": "Назначен", + "update": "Обновяване", + "updated": "Обновено", + "target-purged": "Съдържанието, за което се отнася този доклад, е било изтрито и вече не е налично.", + + "quick-filters": "Бързи филтри", + "filter-active": "В този списък с доклади има един или повече филтри", + "filter-reset": "Премахване на филтрите", + "filters": "Настройки на филтрите", + "filter-reporterId": "Потр. ид. на докладвалия", + "filter-targetUid": "Потр. ид. на докладвания", + "filter-type": "Вид на доклада", + "filter-type-all": "Всичко", + "filter-type-post": "Публикация", + "filter-state": "Състояние", + "filter-assignee": "Потр. ид. на назначения", + "filter-cid": "Категория", + "filter-quick-mine": "Назначени на мен", + "filter-cid-all": "Всички категории", + "apply-filters": "Прилагане на филтрите", + + "quick-links": "Бързи връзки", + "flagged-user": "Докладван потребител", + "view-profile": "Преглед на профила", + "start-new-chat": "Започване на нов разговор", + "go-to-target": "Преглед на целта на доклада", + + "user-view": "Преглед на профила", + "user-edit": "Редактиране на профила", + + "notes": "Бележки към доклада", + "add-note": "Добавяне на бележка", + "no-notes": "Няма споделени бележки.", + + "history": "История на доклада", + "back": "Обратно към списъка с доклади", + "no-history": "Няма история на доклада.", + + "state-all": "Всички състояния", + "state-open": "Нов/отворен", + "state-wip": "В процес на работа", + "state-resolved": "Разрешен", + "state-rejected": "Отхвърлен", + "no-assignee": "Без назначение", + "note-added": "Бележката е добавена", + + "modal-title": "Докладване на неуместно съдържание", + "modal-body": "Моля, посочете причината за докладването на %1 %2 за преглед. Или използвайте някой от бутоните за бързо докладване, ако са приложими.", + "modal-reason-spam": "Спам", + "modal-reason-offensive": "Обидно", + "modal-reason-custom": "Причина за докладването на това съдържание…", + "modal-submit": "Изпращане на доклада", + "modal-submit-success": "Съдържанието беше докладвано на модераторите." +} \ No newline at end of file diff --git a/public/language/bn/flags.json b/public/language/bn/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/bn/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/cs/flags.json b/public/language/cs/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/cs/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/da/flags.json b/public/language/da/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/da/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/de/flags.json b/public/language/de/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/de/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/el/flags.json b/public/language/el/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/el/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/en-US/flags.json b/public/language/en-US/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/en-US/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/en-x-pirate/flags.json b/public/language/en-x-pirate/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/en-x-pirate/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/es/flags.json b/public/language/es/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/es/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/et/flags.json b/public/language/et/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/et/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/fa-IR/flags.json b/public/language/fa-IR/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/fa-IR/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/fi/flags.json b/public/language/fi/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/fi/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/fr/flags.json b/public/language/fr/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/fr/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/gl/flags.json b/public/language/gl/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/gl/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/he/flags.json b/public/language/he/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/he/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/hu/flags.json b/public/language/hu/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/hu/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/id/flags.json b/public/language/id/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/id/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/it/flags.json b/public/language/it/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/it/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/ja/flags.json b/public/language/ja/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/ja/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/ko/flags.json b/public/language/ko/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/ko/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/lt/flags.json b/public/language/lt/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/lt/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/ms/flags.json b/public/language/ms/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/ms/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/nb/flags.json b/public/language/nb/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/nb/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/nl/flags.json b/public/language/nl/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/nl/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/pl/flags.json b/public/language/pl/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/pl/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/pt-BR/flags.json b/public/language/pt-BR/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/pt-BR/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/pt-PT/flags.json b/public/language/pt-PT/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/pt-PT/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/ro/flags.json b/public/language/ro/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/ro/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/ru/flags.json b/public/language/ru/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/ru/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/rw/flags.json b/public/language/rw/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/rw/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/sc/flags.json b/public/language/sc/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/sc/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/sk/flags.json b/public/language/sk/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/sk/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/sl/flags.json b/public/language/sl/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/sl/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/sr/flags.json b/public/language/sr/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/sr/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/sv/flags.json b/public/language/sv/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/sv/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/th/flags.json b/public/language/th/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/th/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/tr/flags.json b/public/language/tr/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/tr/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/vi/flags.json b/public/language/vi/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/vi/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/zh-CN/flags.json b/public/language/zh-CN/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/zh-CN/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file diff --git a/public/language/zh-TW/flags.json b/public/language/zh-TW/flags.json new file mode 100644 index 0000000000..c4bfed6f23 --- /dev/null +++ b/public/language/zh-TW/flags.json @@ -0,0 +1,60 @@ +{ + "state": "State", + "reporter": "Reporter", + "reported-at": "Reported At", + "description": "Description", + "no-flags": "Hooray! No flags found.", + "assignee": "Assignee", + "update": "Update", + "updated": "Updated", + "target-purged": "The content this flag referred to has been purged and is no longer available.", + + "quick-filters": "Quick Filters", + "filter-active": "There are one or more filters active in this list of flags", + "filter-reset": "Remove Filters", + "filters": "Filter Options", + "filter-reporterId": "Reporter UID", + "filter-targetUid": "Flagged UID", + "filter-type": "Flag Type", + "filter-type-all": "All Content", + "filter-type-post": "Post", + "filter-state": "State", + "filter-assignee": "Assignee UID", + "filter-cid": "Category", + "filter-quick-mine": "Assigned to me", + "filter-cid-all": "All categories", + "apply-filters": "Apply Filters", + + "quick-links": "Quick Links", + "flagged-user": "Flagged User", + "view-profile": "View Profile", + "start-new-chat": "Start New Chat", + "go-to-target": "View Flag Target", + + "user-view": "View Profile", + "user-edit": "Edit Profile", + + "notes": "Flag Notes", + "add-note": "Add Note", + "no-notes": "No shared notes.", + + "history": "Flag History", + "back": "Back to Flags List", + "no-history": "No flag history.", + + "state-all": "All states", + "state-open": "New/Open", + "state-wip": "Work in Progress", + "state-resolved": "Resolved", + "state-rejected": "Rejected", + "no-assignee": "Not Assigned", + "note-added": "Note Added", + + "modal-title": "Report Inappropriate Content", + "modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.", + "modal-reason-spam": "Spam", + "modal-reason-offensive": "Offensive", + "modal-reason-custom": "Reason for reporting this content...", + "modal-submit": "Submit Report", + "modal-submit-success": "Content has been flagged for moderation." +} \ No newline at end of file From 20d035bdac7da51f856a40d5d2f05e1f66431d30 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 11 Jan 2017 14:33:51 -0500 Subject: [PATCH 067/122] hotfix to utils.isRelativeUrl to handle null or undefined first argument --- public/src/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/utils.js b/public/src/utils.js index 42d4b6f3ad..5836e5f04b 100644 --- a/public/src/utils.js +++ b/public/src/utils.js @@ -193,7 +193,7 @@ }, isRelativeUrl: function (url) { - var firstChar = url.slice(0, 1); + var firstChar = String(url || '').charAt(0); return (firstChar === '.' || firstChar === '/'); }, From 8eb47e1987739690680c80dc66a83e5993e70287 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 11 Jan 2017 14:43:56 -0500 Subject: [PATCH 068/122] added back missing next(), @baris --- src/socket.io/user/picture.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/socket.io/user/picture.js b/src/socket.io/user/picture.js index 0d8a57dd24..eded1102c9 100644 --- a/src/socket.io/user/picture.js +++ b/src/socket.io/user/picture.js @@ -101,7 +101,7 @@ module.exports = function (SocketUser) { }, next); }, function (next) { - plugins.fireHook('action:user.removeUploadedPicture', {callerUid: socket.uid, uid: data.uid}); + plugins.fireHook('action:user.removeUploadedPicture', {callerUid: socket.uid, uid: data.uid}, next); } ], callback); }; From d29361f4c9fcdcf74469f476ced8739b90fcb4fb Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 11 Jan 2017 15:06:28 -0500 Subject: [PATCH 069/122] added additional visibility masks for profile menu hook, also added isPrivileged user method, closes #5306 --- src/controllers/accounts/helpers.js | 35 +++++++++++++++++++++++++---- src/middleware/index.js | 24 ++++++++++++++++++++ src/user.js | 10 +++++++++ 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/controllers/accounts/helpers.js b/src/controllers/accounts/helpers.js index 2ef476a4ef..e2bc008de8 100644 --- a/src/controllers/accounts/helpers.js +++ b/src/controllers/accounts/helpers.js @@ -119,7 +119,13 @@ helpers.getUserDataByUserSlug = function (userslug, callerUID, callback) { userData['reputation:disabled'] = parseInt(meta.config['reputation:disabled'], 10) === 1; userData['downvote:disabled'] = parseInt(meta.config['downvote:disabled'], 10) === 1; userData['email:confirmed'] = !!parseInt(userData['email:confirmed'], 10); - userData.profile_links = filterLinks(results.profile_links.concat(results.profile_menu.links), isSelf); + userData.profile_links = filterLinks(results.profile_links.concat(results.profile_menu.links), { + self: isSelf, + other: !isSelf, + moderator: isModerator, + globalMod: isGlobalModerator, + admin: isAdmin + }); userData.sso = results.sso.associations; userData.status = user.getStatus(userData); @@ -154,9 +160,30 @@ helpers.getBaseUser = function (userslug, callerUID, callback) { helpers.getUserDataByUserSlug(userslug, callerUID, callback); }; -function filterLinks(links, self) { - return links.filter(function (link) { - return link && (link.public || self); +function filterLinks(links, states) { + return links.filter(function (link, index) { + // "public" is the old property, if visibility is defined, discard `public` + if (link.hasOwnProperty('public') && !link.hasOwnProperty('visibility')) { + winston.warn('[account/profileMenu (' + link.id + ')] Use of the `.public` property is deprecated, use `visibility` now'); + return link && (link.public || states.self); + } + + // Default visibility + link.visibility = Object.assign({ + self: true, + other: true, + moderator: true, + globalMod: true, + admin: true + }, link.visibility); + + // Iterate through states and permit if every test passes (or is not defined) + var permit = Object.keys(states).some(function (state) { + return states[state] === link.visibility[state]; + }); + + links[index].public = permit; + return permit; }); } diff --git a/src/middleware/index.js b/src/middleware/index.js index f48aaef748..85e29a879a 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -73,6 +73,30 @@ middleware.ensureSelfOrGlobalPrivilege = function (req, res, next) { } }; +middleware.ensureSelfOrPrivileged = function (req, res, next) { + /* + The "self" part of this middleware hinges on you having used + middleware.exposeUid prior to invoking this middleware. + */ + if (req.user) { + if (req.user.uid === res.locals.uid) { + return next(); + } + + user.isPrivileged(req.uid, function (err, ok) { + if (err) { + return next(err); + } else if (ok) { + return next(); + } else { + controllers.helpers.notAllowed(req, res); + } + }); + } else { + controllers.helpers.notAllowed(req, res); + } +}; + middleware.pageView = function (req, res, next) { analytics.pageView({ ip: req.ip, diff --git a/src/user.js b/src/user.js index 00e5824690..2ae5a4baf5 100644 --- a/src/user.js +++ b/src/user.js @@ -256,6 +256,16 @@ var meta = require('./meta'); privileges.users.isGlobalModerator(uid, callback); }; + User.isPrivileged = function (uid, callback) { + async.parallel([ + async.apply(User.isAdministrator, uid), + async.apply(User.isGlobalModerator, uid), + async.apply(User.isModeratorOfAnyCategory, uid) + ], function (err, results) { + callback(err, results ? results.some(Boolean) : false); + }); + }; + User.isAdminOrGlobalMod = function (uid, callback) { async.parallel({ isAdmin: async.apply(User.isAdministrator, uid), From 1e137636c9321524fa2c7a5bc5bb32def9c023f0 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 12 Jan 2017 14:31:28 +0300 Subject: [PATCH 070/122] closes #5359 --- src/topics/delete.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/topics/delete.js b/src/topics/delete.js index 91c1bf53e3..d7148f55c3 100644 --- a/src/topics/delete.js +++ b/src/topics/delete.js @@ -137,15 +137,18 @@ module.exports = function (Topics) { function (next) { reduceCounters(tid, next); } - ], next); + ], function (err) { + next(err); + }); + }, + function (next) { + Topics.getTopicData(tid, next); + }, + function (topicData, next) { + plugins.fireHook('action:topic.purge', {topic: topicData, uid: uid}); + db.delete('topic:' + tid, next); } - ], function (err) { - if (err) { - return callback(err); - } - plugins.fireHook('action:topic.purge', tid); - db.delete('topic:' + tid, callback); - }); + ], callback); }; function deleteFromFollowersIgnorers(tid, callback) { From 274448426d40a3566109c0f07cee7d63e55f68a1 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 12 Jan 2017 14:31:35 +0300 Subject: [PATCH 071/122] helpers.setupAdminPageRoute --- src/routes/helpers.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/routes/helpers.js b/src/routes/helpers.js index 052d99292c..3f3ff06472 100644 --- a/src/routes/helpers.js +++ b/src/routes/helpers.js @@ -9,4 +9,10 @@ helpers.setupPageRoute = function (router, name, middleware, middlewares, contro router.get('/api' + name, middlewares, controller); }; +helpers.setupAdminPageRoute = function (router, name, middleware, middlewares, controller) { + router.get(name, middleware.admin.buildHeader, middlewares, controller); + router.get('/api' + name, middlewares, controller); +}; + + module.exports = helpers; \ No newline at end of file From 938022a0f70fe2ace34d4a1c1b1364e90585cb4b Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 12 Jan 2017 14:32:28 +0300 Subject: [PATCH 072/122] add postData to action:post.delete, closes #5360 --- src/posts/delete.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/posts/delete.js b/src/posts/delete.js index d3f02a95da..a21f2bb81b 100644 --- a/src/posts/delete.js +++ b/src/posts/delete.js @@ -29,6 +29,7 @@ module.exports = function (Posts) { topics.getTopicFields(_post.tid, ['tid', 'cid', 'pinned'], next); }, function (topicData, next) { + postData.cid = topicData.cid; async.parallel([ function (next) { updateTopicTimestamp(topicData, next); @@ -42,7 +43,7 @@ module.exports = function (Posts) { ], next); }, function (results, next) { - plugins.fireHook('action:post.delete', {pid: pid, uid: uid}); + plugins.fireHook('action:post.delete', {post: _.clone(postData), uid: uid}); next(null, postData); } ], callback); From 8f916343f0e849d33069ac2a46b526ef87dfb2b1 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 12 Jan 2017 14:41:35 +0300 Subject: [PATCH 073/122] closes #5361 --- src/posts/delete.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/posts/delete.js b/src/posts/delete.js index a21f2bb81b..d54846c2fd 100644 --- a/src/posts/delete.js +++ b/src/posts/delete.js @@ -147,12 +147,15 @@ module.exports = function (Posts) { db.sortedSetsRemove(['posts:pid', 'posts:flagged'], pid, next); } ], function (err) { - if (err) { - return next(err); - } - plugins.fireHook('action:post.purge', {pid: pid, uid: uid}); - db.delete('post:' + pid, next); + next(err); }); + }, + function (next) { + Posts.getPostData(pid, next); + }, + function (postData, next) { + plugins.fireHook('action:post.purge', {post: postData, uid: uid}); + db.delete('post:' + pid, next); } ], callback); }; From 6c04e393b523607b6f352d5e5ffe72b364f20f10 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 12 Jan 2017 10:03:45 -0500 Subject: [PATCH 074/122] fire hooks for flag update --- src/flags.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/flags.js b/src/flags.js index 168eb5a11e..dd7b038b92 100644 --- a/src/flags.js +++ b/src/flags.js @@ -470,9 +470,13 @@ Flags.update = function (flagId, uid, changeset, callback) { // Save new object to db (upsert) tasks.push(async.apply(db.setObject, 'flag:' + flagId, changeset)); + // Append history tasks.push(async.apply(Flags.appendHistory, flagId, uid, changeset)); + // Fire plugin hook + tasks.push(async.apply(plugins.fireHook, 'action:flag.update', { changeset: changeset, uid: uid })); + async.parallel(tasks, function (err, data) { return next(err); }); From bef3da5b48e89ce769e13c1af71c78415e22e61c Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 12 Jan 2017 10:09:47 -0500 Subject: [PATCH 075/122] pass flagId into flag.update hook --- src/flags.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flags.js b/src/flags.js index dd7b038b92..a50ea54973 100644 --- a/src/flags.js +++ b/src/flags.js @@ -475,7 +475,7 @@ Flags.update = function (flagId, uid, changeset, callback) { tasks.push(async.apply(Flags.appendHistory, flagId, uid, changeset)); // Fire plugin hook - tasks.push(async.apply(plugins.fireHook, 'action:flag.update', { changeset: changeset, uid: uid })); + tasks.push(async.apply(plugins.fireHook, 'action:flag.update', { flagId: flagId, changeset: changeset, uid: uid })); async.parallel(tasks, function (err, data) { return next(err); From 10f270d01666a8a1c05238d574ad2ad5547678de Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 12 Jan 2017 11:31:59 -0500 Subject: [PATCH 076/122] adding byPid zset for flags --- src/flags.js | 5 ++++- test/flags.js | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/flags.js b/src/flags.js index a50ea54973..02e7fdeaad 100644 --- a/src/flags.js +++ b/src/flags.js @@ -336,7 +336,10 @@ Flags.create = function (type, id, uid, reason, timestamp, callback) { tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byTargetUid:' + targetUid, timestamp, flagId)); // by target uid } if (targetCid) { - tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byCid:' + targetCid, timestamp, flagId)); // by target uid + tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byCid:' + targetCid, timestamp, flagId)); // by target cid + } + if (type === 'post') { + tasks.push(async.apply(db.sortedSetAdd.bind(db), 'flags:byPid:' + id, timestamp, flagId)); // by target pid } async.parallel(tasks, function (err, data) { diff --git a/test/flags.js b/test/flags.js index 9df1a11a2b..af53b61271 100644 --- a/test/flags.js +++ b/test/flags.js @@ -80,6 +80,14 @@ describe('Flags', function () { done(); }); }); + + it('should add the flag to the byPid zset for pid 1 if it is of type post', function (done) { + db.isSortedSetMember('flags:byPid:' + 1, 1, function (err, isMember) { + assert.ifError(err); + assert.ok(isMember); + done(); + }); + }); }); describe('.exists()', function () { From 7f9381b0870988d642941855672f893c6475b3d9 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 12 Jan 2017 14:22:30 -0500 Subject: [PATCH 077/122] closes #5346 --- public/src/admin/general/dashboard.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/src/admin/general/dashboard.js b/public/src/admin/general/dashboard.js index f9e2589f65..b58da4126c 100644 --- a/public/src/admin/general/dashboard.js +++ b/public/src/admin/general/dashboard.js @@ -81,7 +81,6 @@ define('admin/general/dashboard', ['semver', 'Chart', 'translator'], function (s setupRealtimeButton(); setupGraphs(); - initiateDashboard(); }; Admin.updateRoomUsage = function (err, data) { @@ -299,6 +298,8 @@ define('admin/general/dashboard', ['semver', 'Chart', 'translator'], function (s } updateTrafficGraph($(this).attr('data-units'), until); }); + + initiateDashboard(); }); } From 65cf2dbe5591753d2d32055a507212e57d0a691c Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 12 Jan 2017 14:26:03 -0500 Subject: [PATCH 078/122] move updateRoomUsage to after graph setup #5346 --- public/src/admin/general/dashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/admin/general/dashboard.js b/public/src/admin/general/dashboard.js index b58da4126c..9a5faede09 100644 --- a/public/src/admin/general/dashboard.js +++ b/public/src/admin/general/dashboard.js @@ -37,7 +37,6 @@ define('admin/general/dashboard', ['semver', 'Chart', 'translator'], function (s Admin.init = function () { app.enterRoom('admin'); - socket.emit('admin.rooms.getAll', Admin.updateRoomUsage); isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); @@ -299,6 +298,7 @@ define('admin/general/dashboard', ['semver', 'Chart', 'translator'], function (s updateTrafficGraph($(this).attr('data-units'), until); }); + socket.emit('admin.rooms.getAll', Admin.updateRoomUsage); initiateDashboard(); }); } From 8f0f959d53efbc0725dff682dd70cbab08e9ad55 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 13 Jan 2017 12:04:12 +0300 Subject: [PATCH 079/122] add `filter:categories.copyPrivilegesFrom` https://github.com/Schamper/nodebb-plugin-poll/issues/77 --- src/categories/create.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/categories/create.js b/src/categories/create.js index 508d8ab348..cebcbcd82b 100644 --- a/src/categories/create.js +++ b/src/categories/create.js @@ -139,9 +139,20 @@ module.exports = function (Categories) { }; Categories.copyPrivilegesFrom = function (fromCid, toCid, callback) { - async.each(privileges.privilegeList, function (privilege, next) { - copyPrivilege(privilege, fromCid, toCid, next); - }, callback); + async.waterfall([ + function (next) { + plugins.fireHook('filter:categories.copyPrivilegesFrom', { + privileges: privileges.privilegeList, + fromCid: fromCid, + toCid: toCid + }, next); + }, + function (data, next) { + async.each(data.privileges, function (privilege, next) { + copyPrivilege(privilege, data.fromCid, data.toCid, next); + }, next); + } + ], callback); }; function copyPrivilege(privilege, fromCid, toCid, callback) { From 05b68391ddacb92719fd19b1013d1d813ce50a40 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 14 Jan 2017 22:36:10 -0700 Subject: [PATCH 080/122] Use `/assets` for client assets - Route `/assets` -> `build/public`, falling back on `public` - Moved destinations for `nodebb.min.js`, `acp.min.js`, `admin.css`, `stylesheet.css`, `templates`, and `sounds` to `build/public` - r.js modules previously routed through express are now symlinked into `public/build/src/modules` - minfiles no longer served from a memory cache - use config `views_dir` setting everywhere template directory is used - fix cache buster `v=v=` --- .eslintignore | 1 + app.js | 2 +- build.js | 1 + public/src/ajaxify.js | 2 +- public/src/app.js | 4 +- public/src/client/account/header.js | 2 +- public/src/modules/translator.js | 4 +- public/src/require-config.js | 2 +- public/src/widgets.js | 2 +- src/admin/search.js | 5 +- src/controllers/admin/settings.js | 3 +- src/controllers/admin/uploads.js | 2 +- src/coverPhoto.js | 2 +- src/meta/css.js | 24 +------- src/meta/js.js | 86 +++++++++------------------- src/meta/sounds.js | 4 +- src/meta/themes.js | 2 +- src/middleware/admin.js | 2 +- src/middleware/header.js | 2 +- src/routes/index.js | 38 ++++++++++-- src/routes/meta.js | 30 ---------- src/views/admin/header.tpl | 26 ++++----- src/views/admin/settings/group.tpl | 2 +- src/views/admin/settings/uploads.tpl | 2 +- src/webserver.js | 4 -- src/widgets/admin.js | 3 +- test/mocks/databasemock.js | 2 +- 27 files changed, 101 insertions(+), 158 deletions(-) diff --git a/.eslintignore b/.eslintignore index 0799652254..250640f954 100644 --- a/.eslintignore +++ b/.eslintignore @@ -18,3 +18,4 @@ logs/ *.ipr *.iws /coverage +/build diff --git a/app.js b/app.js index b6d7d07829..55cc0dbecf 100644 --- a/app.js +++ b/app.js @@ -99,7 +99,7 @@ function loadConfig(callback) { nconf.defaults({ base_dir: __dirname, themes_path: path.join(__dirname, 'node_modules'), - views_dir: path.join(__dirname, 'public/templates'), + views_dir: path.join(__dirname, 'build/public/templates'), version: pkg.version }); diff --git a/build.js b/build.js index a0250dfb37..32359e14f8 100644 --- a/build.js +++ b/build.js @@ -57,6 +57,7 @@ exports.buildTargets = function (targets, callback) { winston.info('[build] Building javascript'); var startTime = Date.now(); async.series([ + meta.js.linkModules, async.apply(meta.js.minify, 'nodebb.min.js'), async.apply(meta.js.minify, 'acp.min.js') ], step.bind(this, startTime, 'js', next)); diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 2e895f380b..7eb46343e5 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -338,7 +338,7 @@ $(document).ready(function () { callback(templates.cache[template]); } else { $.ajax({ - url: RELATIVE_PATH + '/templates/' + template + '.tpl' + (config['cache-buster'] ? '?v=' + config['cache-buster'] : ''), + url: config.relative_path + '/assets/templates/' + template + '.tpl' + '?' + config['cache-buster'], type: 'GET', success: function (data) { callback(data.toString()); diff --git a/public/src/app.js b/public/src/app.js index fe12a7adfc..00d5e7c017 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -558,7 +558,7 @@ app.cacheBuster = null; var scriptEl = document.createElement('script'); scriptEl.type = 'text/javascript'; - scriptEl.src = config.relative_path + '/vendor/jquery/js/jquery-ui.js' + (app.cacheBuster ? '?v=' + app.cacheBuster : ''); + scriptEl.src = config.relative_path + '/vendor/jquery/js/jquery-ui.js' + '?' + config['cache-buster']; scriptEl.onload = callback; document.head.appendChild(scriptEl); }; @@ -625,7 +625,7 @@ app.cacheBuster = null; app.loadProgressiveStylesheet = function () { var linkEl = document.createElement('link'); linkEl.rel = 'stylesheet'; - linkEl.href = config.relative_path + '/js-enabled.css'; + linkEl.href = config.relative_path + '/assets/js-enabled.css'; document.head.appendChild(linkEl); }; diff --git a/public/src/client/account/header.js b/public/src/client/account/header.js index e99b7ee0a8..d0f84ade3a 100644 --- a/public/src/client/account/header.js +++ b/public/src/client/account/header.js @@ -84,7 +84,7 @@ define('forum/account/header', [ params: {uid: ajaxify.data.uid }, accept: '.png,.jpg,.bmp' }, function (imageUrlOnServer) { - components.get('account/cover').css('background-image', 'url(' + imageUrlOnServer + '?v=' + Date.now() + ')'); + components.get('account/cover').css('background-image', 'url(' + imageUrlOnServer + '?' + config['cache-buster'] + ')'); }); }, removeCover diff --git a/public/src/modules/translator.js b/public/src/modules/translator.js index eac467f413..ff2aa53bb0 100644 --- a/public/src/modules/translator.js +++ b/public/src/modules/translator.js @@ -513,12 +513,12 @@ break; } - jQuery.getScript(config.relative_path + '/vendor/jquery/timeago/locales/jquery.timeago.' + languageCode + '.js').done(function () { + jQuery.getScript(config.relative_path + '/assets/vendor/jquery/timeago/locales/jquery.timeago.' + languageCode + '.js').done(function () { jQuery('.timeago').timeago(); adaptor.timeagoShort = assign({}, jQuery.timeago.settings.strings); // Retrieve the shorthand timeago values as well - jQuery.getScript(config.relative_path + '/vendor/jquery/timeago/locales/jquery.timeago.' + languageCode + '-short.js').done(function () { + jQuery.getScript(config.relative_path + '/assets/vendor/jquery/timeago/locales/jquery.timeago.' + languageCode + '-short.js').done(function () { // Switch back to long-form adaptor.toggleTimeagoShorthand(); }); diff --git a/public/src/require-config.js b/public/src/require-config.js index 8618685052..0e021f6be0 100644 --- a/public/src/require-config.js +++ b/public/src/require-config.js @@ -1,5 +1,5 @@ require.config({ - baseUrl: config.relative_path + "/src/modules", + baseUrl: config.relative_path + '/assets/src/modules', waitSeconds: 7, urlArgs: config['cache-buster'], paths: { diff --git a/public/src/widgets.js b/public/src/widgets.js index 46023fad15..377ccb2c53 100644 --- a/public/src/widgets.js +++ b/public/src/widgets.js @@ -29,7 +29,7 @@ } }); - $.get(config.relative_path + '/api/widgets/render' + (config['cache-buster'] ? '?v=' + config['cache-buster'] : ''), { + $.get(config.relative_path + '/api/widgets/render' + '?' + config['cache-buster'], { locations: widgetLocations, template: template + '.tpl', url: url, diff --git a/src/admin/search.js b/src/admin/search.js index 860c527e6b..4c53815e48 100644 --- a/src/admin/search.js +++ b/src/admin/search.js @@ -4,6 +4,7 @@ var fs = require('fs'); var path = require('path'); var async = require('async'); var sanitizeHTML = require('sanitize-html'); +var nconf = require('nconf'); var utils = require('../../public/src/utils'); var Translator = require('../../public/src/modules/translator').Translator; @@ -23,7 +24,7 @@ function filterDirectories(directories) { } function getAdminNamespaces(callback) { - utils.walk(path.resolve(__dirname, '../../public/templates/admin'), function (err, directories) { + utils.walk(path.resolve(nconf.get('views_dir'), 'admin'), function (err, directories) { if (err) { return callback(err); } @@ -60,7 +61,7 @@ var fallbackCacheInProgress = {}; var fallbackCache = {}; function initFallback(namespace, callback) { - fs.readFile(path.resolve(__dirname, '../../public/templates/', namespace + '.tpl'), function (err, file) { + fs.readFile(path.resolve(nconf.get('views_dir'), namespace + '.tpl'), function (err, file) { if (err) { return callback(err); } diff --git a/src/controllers/admin/settings.js b/src/controllers/admin/settings.js index 639267f5f5..0d1f509631 100644 --- a/src/controllers/admin/settings.js +++ b/src/controllers/admin/settings.js @@ -2,6 +2,7 @@ var async = require('async'); +var nconf = require('nconf'); var meta = require('../../meta'); var settingsController = module.exports; @@ -25,7 +26,7 @@ function renderEmail(req, res, next) { var path = require('path'); var utils = require('../../../public/src/utils'); - var emailsPath = path.join(__dirname, '../../../public/templates/emails'); + var emailsPath = path.join(nconf.get('views_dir'), 'emails'); async.waterfall([ function (next) { diff --git a/src/controllers/admin/uploads.js b/src/controllers/admin/uploads.js index d1664cb8f1..2b1a60e281 100644 --- a/src/controllers/admin/uploads.js +++ b/src/controllers/admin/uploads.js @@ -105,7 +105,7 @@ uploadsController.uploadSound = function (req, res, next) { return next(err); } - var soundsPath = path.join(__dirname, '../../../public/sounds'), + var soundsPath = path.join(__dirname, '../../../build/public/sounds'), filePath = path.join(__dirname, '../../../public/uploads/sounds', uploadedFile.name); if (process.platform === 'win32') { diff --git a/src/coverPhoto.js b/src/coverPhoto.js index 699e4ee374..9380b347f4 100644 --- a/src/coverPhoto.js +++ b/src/coverPhoto.js @@ -26,7 +26,7 @@ function getCover(type, id) { return covers[id]; } - return nconf.get('relative_path') + '/images/cover-default.png'; + return nconf.get('relative_path') + '/assets/images/cover-default.png'; } module.exports = coverPhoto; \ No newline at end of file diff --git a/src/meta/css.js b/src/meta/css.js index 0d63e09d6d..f72ef6004d 100644 --- a/src/meta/css.js +++ b/src/meta/css.js @@ -86,15 +86,6 @@ module.exports = function (Meta) { }); }; - Meta.css.getFromFile = function (callback) { - async.series([ - async.apply(Meta.css.loadFile, path.join(__dirname, '../../public/stylesheet.css'), 'cache'), - async.apply(Meta.css.loadFile, path.join(__dirname, '../../public/admin.css'), 'acpCache') - ], function (err) { - callback(err); - }); - }; - function getStyleSource(files, prefix, extension, callback) { var pluginDirectories = [], source = ''; @@ -127,7 +118,7 @@ module.exports = function (Meta) { Meta.css.commitToFile = function (filename, callback) { var file = (filename === 'acpCache' ? 'admin' : 'stylesheet') + '.css'; - fs.writeFile(path.join(__dirname, '../../public/' + file), Meta.css[filename], function (err) { + fs.writeFile(path.join(__dirname, '../../build/public/' + file), Meta.css[filename], function (err) { if (!err) { winston.verbose('[meta/css] ' + file + ' committed to disk.'); } else { @@ -139,19 +130,6 @@ module.exports = function (Meta) { }); }; - Meta.css.loadFile = function (filePath, filename, callback) { - winston.verbose('[meta/css] Reading stylesheet ' + filePath.split('/').pop() + ' from file'); - - fs.readFile(filePath, function (err, file) { - if (err) { - return callback(err); - } - - Meta.css[filename] = file; - callback(); - }); - }; - function minify(source, paths, destination, callback) { callback = callback || function () {}; less.render(source, { diff --git a/src/meta/js.js b/src/meta/js.js index 7f39235993..8c3794043f 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -6,6 +6,7 @@ var path = require('path'); var async = require('async'); var nconf = require('nconf'); var fs = require('fs'); +var mkdirp = require('mkdirp'); var plugins = require('../plugins'); var utils = require('../../public/src/utils'); @@ -85,30 +86,34 @@ module.exports = function (Meta) { } } }; - - Meta.js.bridgeModules = function (app, callback) { - // Add routes for AMD-type modules to serve those files - function addRoute(relPath) { - var relativePath = nconf.get('relative_path'); - - app.get(relativePath + '/src/modules/' + relPath, function (req, res) { - return res.sendFile(path.join(__dirname, '../../', Meta.js.scripts.modules[relPath]), { - maxAge: app.enabled('cache') ? 5184000000 : 0 - }); - }); - } - - var numBridged = 0; - - for(var relPath in Meta.js.scripts.modules) { - if (Meta.js.scripts.modules.hasOwnProperty(relPath)) { - addRoute(relPath); - ++numBridged; + + Meta.js.linkModules = function (callback) { + function link(filePath, destPath, cb) { + if (process.platform === 'win32') { + fs.link(filePath, destPath, cb); + } else { + fs.symlink(filePath, destPath, 'file', cb); } } - winston.verbose('[meta/js] ' + numBridged + ' of ' + Object.keys(Meta.js.scripts.modules).length + ' modules bridged'); - callback(); + plugins.reload(function (err) { + if (err) { + return callback(err); + } + + async.each(Object.keys(Meta.js.scripts.modules), function (relPath, next) { + var filePath = path.join(__dirname, '../../', Meta.js.scripts.modules[relPath]); + var destPath = path.join(__dirname, '../../build/public/src/modules', relPath); + + mkdirp(path.dirname(destPath), function (err) { + if (err) { + return next(err); + } + + link(filePath, destPath, next); + }); + }, callback); + }); }; Meta.js.minify = function (target, callback) { @@ -202,48 +207,11 @@ module.exports = function (Meta) { }; Meta.js.commitToFile = function (target, callback) { - fs.writeFile(path.join(__dirname, '../../public/' + target), Meta.js.target[target].cache, function (err) { + fs.writeFile(path.join(__dirname, '../../build/public/' + target), Meta.js.target[target].cache, function (err) { callback(err); }); }; - Meta.js.getFromFile = function (target, callback) { - function readFile(filePath, next) { - fs.readFile(filePath, function (err, contents) { - if (err) { - if (err.code === 'ENOENT') { - if (!filePath.endsWith('.map')) { - winston.warn('[meta/js] ' + filePath + ' not found on disk, did you run ./nodebb build?'); - } - return next(null, ''); - } - } - next(err, contents); - }); - } - - var scriptPath = path.join(nconf.get('base_dir'), 'public/' + target); - var mapPath = path.join(nconf.get('base_dir'), 'public/' + target + '.map'); - - async.parallel({ - script: function (next) { - readFile(scriptPath, next); - }, - map: function (next) { - readFile(mapPath, next); - } - }, function (err, results) { - if (err) { - return callback(err); - } - Meta.js.target[target] = { - cache: results.script, - map: results.map - }; - callback(); - }); - }; - function setupDebugging() { /** * Check if the parent process is running with the debug option --debug (or --debug-brk) diff --git a/src/meta/sounds.js b/src/meta/sounds.js index 6068f16f5f..6acbd77a1f 100644 --- a/src/meta/sounds.js +++ b/src/meta/sounds.js @@ -28,7 +28,7 @@ module.exports = function (Meta) { Meta.sounds.getFiles = function (callback) { async.waterfall([ function (next) { - fs.readdir(path.join(__dirname, '../../public/sounds'), next); + fs.readdir(path.join(__dirname, '../../build/public/sounds'), next); }, function (sounds, next) { fs.readdir(path.join(__dirname, '../../public/uploads/sounds'), function (err, uploaded) { @@ -88,7 +88,7 @@ module.exports = function (Meta) { }; function setupSounds(callback) { - var soundsPath = path.join(__dirname, '../../public/sounds'); + var soundsPath = path.join(__dirname, '../../build/public/sounds'); async.waterfall([ function (next) { diff --git a/src/meta/themes.js b/src/meta/themes.js index be48d1e70d..e19dcdbf4c 100644 --- a/src/meta/themes.js +++ b/src/meta/themes.js @@ -48,7 +48,7 @@ module.exports = function (Meta) { if (configObj.screenshot) { configObj.screenshot_url = nconf.get('relative_path') + '/css/previews/' + configObj.id; } else { - configObj.screenshot_url = nconf.get('relative_path') + '/images/themes/default.png'; + configObj.screenshot_url = nconf.get('relative_path') + '/assets/images/themes/default.png'; } next(null, configObj); } catch (err) { diff --git a/src/middleware/admin.js b/src/middleware/admin.js index 3240eaf0af..9d4b43bf25 100644 --- a/src/middleware/admin.js +++ b/src/middleware/admin.js @@ -101,7 +101,7 @@ module.exports = function (middleware) { plugins: results.custom_header.plugins, authentication: results.custom_header.authentication, scripts: results.scripts, - 'cache-buster': meta.config['cache-buster'] ? 'v=' + meta.config['cache-buster'] : '', + 'cache-buster': meta.config['cache-buster'] || '', env: process.env.NODE_ENV ? true : false, title: (acpPath || 'Dashboard') + ' | NodeBB Admin Control Panel', bodyClass: data.bodyClass diff --git a/src/middleware/header.js b/src/middleware/header.js index c1b4175b5b..5e78416a0a 100644 --- a/src/middleware/header.js +++ b/src/middleware/header.js @@ -46,7 +46,7 @@ module.exports = function (middleware) { bootswatchCSS: meta.config['theme:src'], title: meta.config.title || '', description: meta.config.description || '', - 'cache-buster': meta.config['cache-buster'] ? 'v=' + meta.config['cache-buster'] : '', + 'cache-buster': meta.config['cache-buster'] || '', 'brand:logo': meta.config['brand:logo'] || '', 'brand:logo:url': meta.config['brand:logo:url'] || '', 'brand:logo:alt': meta.config['brand:logo:alt'] || '', diff --git a/src/routes/index.js b/src/routes/index.js index 158774b624..e1f95891cf 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -145,21 +145,47 @@ module.exports = function (app, middleware, hotswapIds) { } app.use(middleware.privateUploads); - app.use(relativePath + '/assets', express.static(path.join(__dirname, '../../', 'build/public'), { + + app.use(relativePath + '/assets', express.static(path.join(__dirname, '../../build/public'), { + maxAge: app.enabled('cache') ? 5184000000 : 0 + })); + app.use(relativePath + '/assets', express.static(path.join(__dirname, '../../public'), { maxAge: app.enabled('cache') ? 5184000000 : 0 })); + // DEPRECATED + var deprecatedPaths = [ + '/nodebb.min.js', + '/acp.min.js', + '/stylesheet.css', + '/js-enabled.css', + '/admin.css', + '/logo.png', + '/favicon.ico', + '/vendor/', + '/uploads/', + '/templates/', + '/src/', + '/images/', + // '/sounds/', + ]; + app.use(relativePath, function (req, res, next) { + if (deprecatedPaths.some(function (path) { return req.path.startsWith(path); })) { + winston.warn('[deprecated] Accessing `' + req.path.slice(1) + '` from `/` is deprecated. ' + + 'Use `/assets' + req.path + '` to access this file.'); + res.redirect(relativePath + '/assets' + req.path + '?' + meta.config['cache-buster']); + } else { + next(); + } + }); // DEPRECATED app.use(relativePath + '/api/language', function (req, res) { winston.warn('[deprecated] Accessing language files from `/api/language` is deprecated. ' + - 'Use `/assets/language/[langCode]/[namespace].json` for prefetch paths.'); + 'Use `/assets/language' + req.path + '.json` for prefetch paths.'); res.redirect(relativePath + '/assets/language' + req.path + '.json?' + meta.config['cache-buster']); }); - app.use(relativePath, express.static(path.join(__dirname, '../../', 'public'), { - maxAge: app.enabled('cache') ? 5184000000 : 0 - })); - app.use(relativePath + '/vendor/jquery/timeago/locales', middleware.processTimeagoLocales); + app.use(relativePath + '/assets/vendor/jquery/timeago/locales', middleware.processTimeagoLocales); app.use(controllers.handle404); app.use(controllers.handleURIErrors); app.use(controllers.handleErrors); diff --git a/src/routes/meta.js b/src/routes/meta.js index c62465c8d0..af4e89d897 100644 --- a/src/routes/meta.js +++ b/src/routes/meta.js @@ -5,31 +5,6 @@ var nconf = require('nconf'); var meta = require('../meta'); - -function sendMinifiedJS(req, res) { - var target = path.basename(req.path); - var cache = meta.js.target[target] ? meta.js.target[target].cache : ''; - res.type('text/javascript').send(cache); -} - -// The portions of code involving the source map are commented out as they're broken in UglifyJS2 -// Follow along here: https://github.com/mishoo/UglifyJS2/issues/700 -// function sendJSSourceMap(req, res) { -// if (meta.js.hasOwnProperty('map')) { -// res.type('application/json').send(meta.js.map); -// } else { -// res.redirect(404); -// } -// }; - -function sendStylesheet(req, res) { - res.type('text/css').status(200).send(meta.css.cache); -} - -function sendACPStylesheet(req, res) { - res.type('text/css').status(200).send(meta.css.acpCache); -} - function sendSoundFile(req, res, next) { var resolved = meta.sounds._filePathHash[path.basename(req.path)]; @@ -41,11 +16,6 @@ function sendSoundFile(req, res, next) { } module.exports = function (app, middleware, controllers) { - app.get('/stylesheet.css', middleware.addExpiresHeaders, sendStylesheet); - app.get('/admin.css', middleware.addExpiresHeaders, sendACPStylesheet); - app.get('/nodebb.min.js', middleware.addExpiresHeaders, sendMinifiedJS); - app.get('/acp.min.js', middleware.addExpiresHeaders, sendMinifiedJS); - // app.get('/nodebb.min.js.map', middleware.addExpiresHeaders, sendJSSourceMap); app.get('/sitemap.xml', controllers.sitemap.render); app.get('/sitemap/pages.xml', controllers.sitemap.getPages); app.get('/sitemap/categories.xml', controllers.sitemap.getCategories); diff --git a/src/views/admin/header.tpl b/src/views/admin/header.tpl index e6e92490f9..23ce1e2c02 100644 --- a/src/views/admin/header.tpl +++ b/src/views/admin/header.tpl @@ -4,8 +4,8 @@ {title} - - + + - - - - - - - - - - - + + + + + + + + + + + diff --git a/src/views/admin/settings/group.tpl b/src/views/admin/settings/group.tpl index 56a8b2c18e..1c0b660361 100644 --- a/src/views/admin/settings/group.tpl +++ b/src/views/admin/settings/group.tpl @@ -43,7 +43,7 @@

    [[admin/settings/group:default-cover-help]]

    -
    +
    diff --git a/src/views/admin/settings/uploads.tpl b/src/views/admin/settings/uploads.tpl index 2e79da9a2b..6c9b59db80 100644 --- a/src/views/admin/settings/uploads.tpl +++ b/src/views/admin/settings/uploads.tpl @@ -131,7 +131,7 @@

    [[admin/settings/uploads:default-covers-help]]

    - + diff --git a/src/webserver.js b/src/webserver.js index fec42974c6..2e7afdb228 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -88,7 +88,6 @@ function initializeNodeBB(callback) { plugins.init(app, middleware, next); }, async.apply(plugins.fireHook, 'static:assets.prepare', {}), - async.apply(meta.js.bridgeModules, app), function (next) { plugins.fireHook('static:app.preload', { app: app, @@ -104,9 +103,6 @@ function initializeNodeBB(callback) { }, function (next) { async.series([ - async.apply(meta.js.getFromFile, 'nodebb.min.js'), - async.apply(meta.js.getFromFile, 'acp.min.js'), - async.apply(meta.css.getFromFile), async.apply(meta.sounds.init), async.apply(languages.init), async.apply(meta.blacklist.load) diff --git a/src/widgets/admin.js b/src/widgets/admin.js index fc380804c6..ecfd73b750 100644 --- a/src/widgets/admin.js +++ b/src/widgets/admin.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); var async = require('async'); +var nconf = require('nconf'); var plugins = require('../plugins'); var admin = {}; @@ -25,7 +26,7 @@ admin.get = function (callback) { plugins.fireHook('filter:widgets.getWidgets', [], next); }, adminTemplate: function (next) { - fs.readFile(path.resolve(__dirname, '../../public/templates/admin/partials/widget-settings.tpl'), 'utf8', next); + fs.readFile(path.resolve(nconf.get('views_dir'), 'admin/partials/widget-settings.tpl'), 'utf8', next); } }, function (err, widgetData) { if (err) { diff --git a/test/mocks/databasemock.js b/test/mocks/databasemock.js index 44de8c7122..182d9fea12 100644 --- a/test/mocks/databasemock.js +++ b/test/mocks/databasemock.js @@ -20,7 +20,7 @@ base_dir: path.join(__dirname,'../..'), themes_path: path.join(__dirname, '../../node_modules'), upload_url: path.join(path.sep, '../../uploads', path.sep), - views_dir: path.join(__dirname, '../../public/templates'), + views_dir: path.join(__dirname, '../../build/public/templates'), relative_path: '' }); From 8c86b2e32c9ebac4e9bbbfe2b8cb95e9d5e01f9c Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sun, 15 Jan 2017 12:38:16 -0700 Subject: [PATCH 081/122] Build pipeline improvements - Refactor meta/css - `fs.link` usage consolidated to `file.link` - rimraf built modules directory to fix error - Remove `local-assets` flag --- build.js | 10 ++- src/controllers/admin/uploads.js | 6 +- src/file.js | 8 +++ src/meta/css.js | 102 +++++++++++++++---------------- src/meta/js.js | 24 ++------ src/meta/sounds.js | 22 +------ src/plugins/load.js | 3 +- src/routes/index.js | 3 +- src/routes/meta.js | 19 ------ src/webserver.js | 2 +- 10 files changed, 78 insertions(+), 121 deletions(-) diff --git a/build.js b/build.js index 32359e14f8..a8ad5007d1 100644 --- a/build.js +++ b/build.js @@ -46,7 +46,11 @@ exports.buildTargets = function (targets, callback) { var meta = require('./src/meta'); buildStart = buildStart || Date.now(); - var step = function (startTime, target, next) { + var step = function (startTime, target, next, err) { + if (err) { + winston.error('Build failed: ' + err.message); + process.exit(1); + } winston.info('[build] ' + target + ' => Completed in ' + ((Date.now() - startTime) / 1000) + 's'); next(); }; @@ -75,13 +79,13 @@ exports.buildTargets = function (targets, callback) { case 'clientCSS': winston.info('[build] Building client-side CSS'); startTime = Date.now(); - meta.css.minify('stylesheet.css', step.bind(this, startTime, target, next)); + meta.css.minify('client', step.bind(this, startTime, target, next)); break; case 'acpCSS': winston.info('[build] Building admin control panel CSS'); startTime = Date.now(); - meta.css.minify('admin.css', step.bind(this, startTime, target, next)); + meta.css.minify('admin', step.bind(this, startTime, target, next)); break; case 'tpl': diff --git a/src/controllers/admin/uploads.js b/src/controllers/admin/uploads.js index 2b1a60e281..25b2ae34fd 100644 --- a/src/controllers/admin/uploads.js +++ b/src/controllers/admin/uploads.js @@ -108,11 +108,7 @@ uploadsController.uploadSound = function (req, res, next) { var soundsPath = path.join(__dirname, '../../../build/public/sounds'), filePath = path.join(__dirname, '../../../public/uploads/sounds', uploadedFile.name); - if (process.platform === 'win32') { - fs.link(filePath, path.join(soundsPath, path.basename(filePath))); - } else { - fs.symlink(filePath, path.join(soundsPath, path.basename(filePath)), 'file'); - } + file.link(filePath, path.join(soundsPath, path.basename(filePath))); fs.unlink(uploadedFile.path, function (err) { if (err) { diff --git a/src/file.js b/src/file.js index df820cc47f..65f86a0bdd 100644 --- a/src/file.js +++ b/src/file.js @@ -102,4 +102,12 @@ file.existsSync = function (path) { return !!exists; }; +file.link = function link(filePath, destPath, cb) { + if (process.platform === 'win32') { + fs.link(filePath, destPath, cb); + } else { + fs.symlink(filePath, destPath, 'file', cb); + } +}; + module.exports = file; diff --git a/src/meta/css.js b/src/meta/css.js index f72ef6004d..d779ff8018 100644 --- a/src/meta/css.js +++ b/src/meta/css.js @@ -18,8 +18,32 @@ var utils = require('../../public/src/utils'); module.exports = function (Meta) { Meta.css = {}; - Meta.css.cache = undefined; - Meta.css.acpCache = undefined; + + var buildImports = { + client: function (source) { + return '@import "./theme";\n' + source + '\n' + [ + '@import "font-awesome";', + '@import (inline) "../../public/vendor/jquery/css/smoothness/jquery-ui.css";', + '@import (inline) "../../public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";', + '@import (inline) "..' + path.sep + 'public/vendor/colorpicker/colorpicker.css";', + '@import "../../public/less/flags.less";', + '@import "../../public/less/blacklist.less";', + '@import "../../public/less/generics.less";', + '@import "../../public/less/mixins.less";', + '@import "../../public/less/global.less";', + ].map(function (str) { return str.replace(/\//g, path.sep); }).join('\n'); + }, + admin: function (source) { + return source + '\n' + [ + '@import "font-awesome";', + '@import "../public/less/admin/admin";', + '@import "../public/less/generics.less";', + '@import (inline) "../public/vendor/colorpicker/colorpicker.css";', + '@import (inline) "../public/vendor/jquery/css/smoothness/jquery-ui.css";', + '@import (inline) "../public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";', + ].map(function (str) { return str.replace(/\//g, path.sep); }).join('\n'); + }, + }; Meta.css.minify = function (target, callback) { callback = callback || function () {}; @@ -30,25 +54,25 @@ module.exports = function (Meta) { return callback(err); } - var themeId = (themeData['theme:id'] || 'nodebb-theme-persona'), - baseThemePath = path.join(nconf.get('themes_path'), (themeData['theme:type'] && themeData['theme:type'] === 'local' ? themeId : 'nodebb-theme-vanilla')), - paths = [ - baseThemePath, - path.join(__dirname, '../../node_modules'), - path.join(__dirname, '../../public/vendor/fontawesome/less') - ], - source = '@import "font-awesome";'; + var themeId = (themeData['theme:id'] || 'nodebb-theme-persona'); + var baseThemePath = path.join(nconf.get('themes_path'), (themeData['theme:type'] && themeData['theme:type'] === 'local' ? themeId : 'nodebb-theme-vanilla')); + var paths = [ + baseThemePath, + path.join(__dirname, '../../node_modules'), + path.join(__dirname, '../../public/vendor/fontawesome/less') + ]; + var source = ''; - plugins.lessFiles = filterMissingFiles(plugins.lessFiles); - plugins.cssFiles = filterMissingFiles(plugins.cssFiles); + var lessFiles = filterMissingFiles(plugins.lessFiles); + var cssFiles = filterMissingFiles(plugins.cssFiles); async.waterfall([ function (next) { - getStyleSource(plugins.cssFiles, '\n@import (inline) ".', '.css', next); + getStyleSource(cssFiles, '\n@import (inline) ".', '.css', next); }, function (src, next) { source += src; - getStyleSource(plugins.lessFiles, '\n@import ".', '.less', next); + getStyleSource(lessFiles, '\n@import ".', '.less', next); }, function (src, next) { source += src; @@ -59,29 +83,7 @@ module.exports = function (Meta) { return callback(err); } - var acpSource = source; - - if (target !== 'admin.css') { - source += '\n@import (inline) "..' + path.sep + '..' + path.sep + 'public/vendor/jquery/css/smoothness/jquery-ui.css";'; - source += '\n@import (inline) "..' + path.sep + '..' + path.sep + 'public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";'; - source += '\n@import (inline) "..' + path.sep + 'public/vendor/colorpicker/colorpicker.css";'; - source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/flags.less";'; - source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/blacklist.less";'; - source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/generics.less";'; - source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/mixins.less";'; - source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/global.less";'; - source = '@import "./theme";\n' + source; - - minify(source, paths, 'cache', callback); - } else { - acpSource += '\n@import "..' + path.sep + 'public/less/admin/admin";\n'; - acpSource += '\n@import "..' + path.sep + 'public/less/generics.less";\n'; - acpSource += '\n@import (inline) "..' + path.sep + 'public/vendor/colorpicker/colorpicker.css";\n'; - acpSource += '\n@import (inline) "..' + path.sep + 'public/vendor/jquery/css/smoothness/jquery-ui.css";'; - acpSource += '\n@import (inline) "..' + path.sep + 'public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";'; - - minify(acpSource, paths, 'acpCache', callback); - } + minify(buildImports[target](source), paths, target, callback); }); }); }; @@ -115,22 +117,22 @@ module.exports = function (Meta) { }); } - Meta.css.commitToFile = function (filename, callback) { - var file = (filename === 'acpCache' ? 'admin' : 'stylesheet') + '.css'; + Meta.css.commitToFile = function (target, source, callback) { + var filename = (target === 'client' ? 'stylesheet' : 'admin') + '.css'; - fs.writeFile(path.join(__dirname, '../../build/public/' + file), Meta.css[filename], function (err) { + fs.writeFile(path.join(__dirname, '../../build/public/' + filename), source, function (err) { if (!err) { - winston.verbose('[meta/css] ' + file + ' committed to disk.'); + winston.verbose('[meta/css] ' + target + ' CSS committed to disk.'); } else { winston.error('[meta/css] ' + err.message); - process.exit(0); + process.exit(1); } callback(); }); }; - function minify(source, paths, destination, callback) { + function minify(source, paths, target, callback) { callback = callback || function () {}; less.render(source, { paths: paths @@ -140,20 +142,14 @@ module.exports = function (Meta) { return callback(err); } - postcss([ autoprefixer, clean() ]).process(lessOutput.css).then(function (result) { + postcss(global.env === 'development' ? [ autoprefixer ] : [ autoprefixer, clean() ]).process(lessOutput.css).then(function (result) { result.warnings().forEach(function (warn) { winston.verbose(warn.toString()); }); - Meta.css[destination] = result.css; - // Save the compiled CSS in public/ so things like nginx can serve it - if (nconf.get('local-assets') === undefined || nconf.get('local-assets') !== false) { - return Meta.css.commitToFile(destination, function () { - callback(null, result.css); - }); - } - - callback(null, result.css); + return Meta.css.commitToFile(target, result.css, function () { + callback(null, result.css); + }); }); }); } diff --git a/src/meta/js.js b/src/meta/js.js index 8c3794043f..d479e9161c 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -4,9 +4,11 @@ var winston = require('winston'); var fork = require('child_process').fork; var path = require('path'); var async = require('async'); -var nconf = require('nconf'); var fs = require('fs'); var mkdirp = require('mkdirp'); +var rimraf = require('rimraf'); + +var file = require('../file'); var plugins = require('../plugins'); var utils = require('../../public/src/utils'); @@ -88,19 +90,10 @@ module.exports = function (Meta) { }; Meta.js.linkModules = function (callback) { - function link(filePath, destPath, cb) { - if (process.platform === 'win32') { - fs.link(filePath, destPath, cb); - } else { - fs.symlink(filePath, destPath, 'file', cb); - } - } - - plugins.reload(function (err) { + rimraf(path.join(__dirname, '../../build/public/src/modules'), function (err) { if (err) { return callback(err); } - async.each(Object.keys(Meta.js.scripts.modules), function (relPath, next) { var filePath = path.join(__dirname, '../../', Meta.js.scripts.modules[relPath]); var destPath = path.join(__dirname, '../../build/public/src/modules', relPath); @@ -110,7 +103,7 @@ module.exports = function (Meta) { return next(err); } - link(filePath, destPath, next); + file.link(filePath, destPath, next); }); }, callback); }); @@ -143,12 +136,7 @@ module.exports = function (Meta) { winston.verbose('[meta/js] ' + target + ' minification complete'); minifier.kill(); - if (nconf.get('local-assets') === undefined || nconf.get('local-assets') !== false) { - return Meta.js.commitToFile(target, callback); - } else { - return callback(); - } - + Meta.js.commitToFile(target, callback); break; case 'error': winston.error('[meta/js] Could not compile ' + target + ': ' + message.message); diff --git a/src/meta/sounds.js b/src/meta/sounds.js index 6acbd77a1f..e44f43cccc 100644 --- a/src/meta/sounds.js +++ b/src/meta/sounds.js @@ -8,6 +8,7 @@ var rimraf = require('rimraf'); var mkdirp = require('mkdirp'); var async = require('async'); +var file = require('../file'); var plugins = require('../plugins'); var db = require('../database'); @@ -107,21 +108,6 @@ module.exports = function (Meta) { return; } - if (nconf.get('local-assets') === false) { - // Don't regenerate the public/sounds/ directory. Instead, create a mapping for the router to use - Meta.sounds._filePathHash = filePaths.reduce(function (hash, filePath) { - hash[path.basename(filePath)] = filePath; - return hash; - }, {}); - - winston.verbose('[sounds] Sounds OK'); - if (typeof next === 'function') { - return next(); - } else { - return; - } - } - // Clear the sounds directory async.series([ function (next) { @@ -138,11 +124,7 @@ module.exports = function (Meta) { // Link paths async.each(filePaths, function (filePath, next) { - if (process.platform === 'win32') { - fs.link(filePath, path.join(soundsPath, path.basename(filePath)), next); - } else { - fs.symlink(filePath, path.join(soundsPath, path.basename(filePath)), 'file', next); - } + file.link(filePath, path.join(soundsPath, path.basename(filePath)), next); }, function (err) { if (!err) { winston.verbose('[sounds] Sounds OK'); diff --git a/src/plugins/load.js b/src/plugins/load.js index 3121f8457e..cf6e0b4780 100644 --- a/src/plugins/load.js +++ b/src/plugins/load.js @@ -54,7 +54,8 @@ module.exports = function (Plugins) { async.parallel([ async.apply(mapFiles, pluginData, 'css', 'cssFiles'), async.apply(mapFiles, pluginData, 'less', 'lessFiles'), - async.apply(mapClientSideScripts, pluginData) + async.apply(mapClientSideScripts, pluginData), + async.apply(mapClientModules, pluginData), ], next); }, next); } diff --git a/src/routes/index.js b/src/routes/index.js index e1f95891cf..506a0063ec 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -167,7 +167,8 @@ module.exports = function (app, middleware, hotswapIds) { '/templates/', '/src/', '/images/', - // '/sounds/', + '/language/', + '/sounds/', ]; app.use(relativePath, function (req, res, next) { if (deprecatedPaths.some(function (path) { return req.path.startsWith(path); })) { diff --git a/src/routes/meta.js b/src/routes/meta.js index af4e89d897..cb089f1200 100644 --- a/src/routes/meta.js +++ b/src/routes/meta.js @@ -1,20 +1,5 @@ "use strict"; -var path = require('path'); -var nconf = require('nconf'); - -var meta = require('../meta'); - -function sendSoundFile(req, res, next) { - var resolved = meta.sounds._filePathHash[path.basename(req.path)]; - - if (resolved) { - res.status(200).sendFile(resolved); - } else { - next(); - } -} - module.exports = function (app, middleware, controllers) { app.get('/sitemap.xml', controllers.sitemap.render); app.get('/sitemap/pages.xml', controllers.sitemap.getPages); @@ -23,8 +8,4 @@ module.exports = function (app, middleware, controllers) { app.get('/robots.txt', controllers.robots); app.get('/manifest.json', controllers.manifest); app.get('/css/previews/:theme', controllers.admin.themes.get); - - if (nconf.get('local-assets') === false) { - app.get('/sounds/*', middleware.addExpiresHeaders, sendSoundFile); - } }; diff --git a/src/webserver.js b/src/webserver.js index 2e7afdb228..a8324f7376 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -45,7 +45,7 @@ server.on('error', function (err) { winston.error(err); if (err.code === 'EADDRINUSE') { winston.error('NodeBB address in use, exiting...'); - process.exit(0); + process.exit(1); } else { throw err; } From 82e9e1a05dfc0c05663c4ed0c3f918f42919cc6d Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 17 Jan 2017 14:05:19 -0500 Subject: [PATCH 082/122] closes #5189 --- public/src/client/infinitescroll.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/public/src/client/infinitescroll.js b/public/src/client/infinitescroll.js index 6ae9b5cbbc..ed43e4da22 100644 --- a/public/src/client/infinitescroll.js +++ b/public/src/client/infinitescroll.js @@ -23,7 +23,9 @@ define('forum/infinitescroll', function () { }; function onScroll() { - if (loadingMore) { + var bsEnv = utils.findBootstrapEnvironment(); + var mobileComposerOpen = (bsEnv === 'xs' || bsEnv === 'sm') && $('html').hasClass('composing'); + if (loadingMore || mobileComposerOpen) { return; } var currentScrollTop = $(window).scrollTop(); From ef72762ba7c40c7c358b0d94b20d7a30f95b5835 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 18 Jan 2017 20:21:13 +0300 Subject: [PATCH 083/122] use groups.isMemberOfGroups --- src/groups.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/groups.js b/src/groups.js index 51c1d97dc8..15b42b368b 100644 --- a/src/groups.js +++ b/src/groups.js @@ -432,12 +432,8 @@ var utils = require('../public/src/utils'); db.getSortedSetRevRange(set, 0, -1, next); }, function (groupNames, next) { - var groupSets = groupNames.map(function (name) { - return 'group:' + name + ':members'; - }); - async.map(uids, function (uid, next) { - db.isMemberOfSortedSets(groupSets, uid, function (err, isMembers) { + Groups.isMemberOfGroups(uid, groupNames, function (err, isMembers) { if (err) { return next(err); } From 186209a0a3e75914052e400ca2408c9052b05fe9 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 21 Jan 2017 18:57:27 -0700 Subject: [PATCH 084/122] Build plugin `staticDirs` - route `/plugins` -> `build/public/plugins` - symlink `staticDirs` directories into `build/public/plugins` - remove custom `/plugins` route handling --- build.js | 1 + src/file.js | 5 +++++ src/meta/js.js | 22 +++++++++++++++++++++- src/plugins/load.js | 2 ++ src/routes/index.js | 6 ++++-- src/routes/plugins.js | 40 ---------------------------------------- 6 files changed, 33 insertions(+), 43 deletions(-) delete mode 100644 src/routes/plugins.js diff --git a/build.js b/build.js index a8ad5007d1..73013231d5 100644 --- a/build.js +++ b/build.js @@ -62,6 +62,7 @@ exports.buildTargets = function (targets, callback) { var startTime = Date.now(); async.series([ meta.js.linkModules, + meta.js.linkStatics, async.apply(meta.js.minify, 'nodebb.min.js'), async.apply(meta.js.minify, 'acp.min.js') ], step.bind(this, startTime, 'js', next)); diff --git a/src/file.js b/src/file.js index 65f86a0bdd..d8fa128e5e 100644 --- a/src/file.js +++ b/src/file.js @@ -110,4 +110,9 @@ file.link = function link(filePath, destPath, cb) { } }; +file.linkDirs = function linkDirs(sourceDir, destDir, callback) { + var type = (process.platform === 'win32') ? 'junction' : 'dir'; + fs.symlink(sourceDir, destDir, type, callback); +}; + module.exports = file; diff --git a/src/meta/js.js b/src/meta/js.js index d479e9161c..a44d18baba 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -94,7 +94,7 @@ module.exports = function (Meta) { if (err) { return callback(err); } - async.each(Object.keys(Meta.js.scripts.modules), function (relPath, next) { + async.eachLimit(Object.keys(Meta.js.scripts.modules), 1000, function (relPath, next) { var filePath = path.join(__dirname, '../../', Meta.js.scripts.modules[relPath]); var destPath = path.join(__dirname, '../../build/public/src/modules', relPath); @@ -109,6 +109,26 @@ module.exports = function (Meta) { }); }; + Meta.js.linkStatics = function (callback) { + rimraf(path.join(__dirname, '../../build/public/plugins'), function (err) { + if (err) { + return callback(err); + } + async.eachLimit(Object.keys(plugins.staticDirs), 1000, function (mappedPath, next) { + var sourceDir = plugins.staticDirs[mappedPath]; + var destDir = path.join(__dirname, '../../build/public/plugins', mappedPath); + + mkdirp(path.dirname(destDir), function (err) { + if (err) { + return next(err); + } + + file.linkDirs(sourceDir, destDir, next); + }); + }, callback); + }); + }; + Meta.js.minify = function (target, callback) { winston.verbose('[meta/js] Minifying ' + target); diff --git a/src/plugins/load.js b/src/plugins/load.js index cf6e0b4780..01dedc4e45 100644 --- a/src/plugins/load.js +++ b/src/plugins/load.js @@ -56,6 +56,7 @@ module.exports = function (Plugins) { async.apply(mapFiles, pluginData, 'less', 'lessFiles'), async.apply(mapClientSideScripts, pluginData), async.apply(mapClientModules, pluginData), + async.apply(mapStaticDirectories, pluginData, pluginData.path), ], next); }, next); } @@ -299,6 +300,7 @@ module.exports = function (Plugins) { pluginData.version = packageData.version; pluginData.repository = packageData.repository; pluginData.nbbpm = packageData.nbbpm; + pluginData.path = pluginPath; } catch(err) { var pluginDir = pluginPath.split(path.sep); pluginDir = pluginDir[pluginDir.length - 1]; diff --git a/src/routes/index.js b/src/routes/index.js index 506a0063ec..0b9e6fce9a 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -15,7 +15,6 @@ var metaRoutes = require('./meta'); var apiRoutes = require('./api'); var adminRoutes = require('./admin'); var feedRoutes = require('./feeds'); -var pluginRoutes = require('./plugins'); var authRoutes = require('./authentication'); var helpers = require('./helpers'); @@ -123,7 +122,6 @@ module.exports = function (app, middleware, hotswapIds) { metaRoutes(router, middleware, controllers); apiRoutes(router, middleware, controllers); feedRoutes(router, middleware, controllers); - pluginRoutes(router, middleware, controllers); mainRoutes(router, middleware, controllers); topicRoutes(router, middleware, controllers); @@ -152,6 +150,10 @@ module.exports = function (app, middleware, hotswapIds) { app.use(relativePath + '/assets', express.static(path.join(__dirname, '../../public'), { maxAge: app.enabled('cache') ? 5184000000 : 0 })); + // TODO: deprecate? + app.use(relativePath + '/plugins', express.static(path.join(__dirname, '../../build/public/plugins'), { + maxAge: app.enabled('cache') ? 5184000000 : 0 + })); // DEPRECATED var deprecatedPaths = [ diff --git a/src/routes/plugins.js b/src/routes/plugins.js deleted file mode 100644 index 37e23c5ee6..0000000000 --- a/src/routes/plugins.js +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; - -var _ = require('underscore'); -var path = require('path'); - -var plugins = require('../plugins'); - -module.exports = function (app, middleware, controllers) { - // Static Assets - app.get('/plugins/:id/*', middleware.addExpiresHeaders, function (req, res, next) { - - var relPath = req._parsedUrl.pathname.replace('/plugins/', ''); - - var matches = _.map(plugins.staticDirs, function (realPath, mappedPath) { - if (relPath.match(mappedPath)) { - var pathToFile = path.join(plugins.staticDirs[mappedPath], decodeURIComponent(relPath.slice(mappedPath.length))); - if (pathToFile.startsWith(plugins.staticDirs[mappedPath])) { - return pathToFile; - } - } - - return null; - }).filter(Boolean); - - if (!matches || !matches.length) { - return next(); - } - - res.sendFile(matches[0], {}, function (err) { - if (err) { - if (err.code === 'ENOENT') { - // File doesn't exist, this isn't an error, to send to 404 handler - return next(); - } else { - return next(err); - } - } - }); - }); -}; \ No newline at end of file From 001aa3d1a85eb79cc04acae3626b710c9ea482b3 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 21 Jan 2017 19:21:02 -0700 Subject: [PATCH 085/122] Fix tests, npm Windows fixes --- nodebb | 4 ++-- src/plugins/install.js | 2 +- test/mocks/databasemock.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nodebb b/nodebb index e1a4ab7fbf..7f1d2941a3 100755 --- a/nodebb +++ b/nodebb @@ -225,12 +225,12 @@ var getRunningPid = function (callback) { if (['y', 'Y', 'yes', 'YES'].indexOf(result.upgrade) !== -1) { process.stdout.write('\nUpgrading packages...'); - var args = ['npm', 'i']; + var args = ['i']; found.forEach(function (suggestObj) { args.push(suggestObj.name + '@' + suggestObj.suggested); }); - require('child_process').execFile('/usr/bin/env', args, { stdio: 'ignore' }, function (err) { + require('child_process').execFile((process.platform === 'win32') ? 'npm.cmd' : 'npm', args, { stdio: 'ignore' }, function (err) { if (!err) { process.stdout.write(' OK\n'.green); } diff --git a/src/plugins/install.js b/src/plugins/install.js index a914a09ca6..840d46008a 100644 --- a/src/plugins/install.js +++ b/src/plugins/install.js @@ -102,7 +102,7 @@ module.exports = function (Plugins) { } function runNpmCommand(command, pkgName, version, callback) { - require('child_process').execFile('npm', [command, pkgName + (command === 'install' ? '@' + version : '')], function (err, stdout) { + require('child_process').execFile((process.platform === 'win32') ? 'npm.cmd' : 'npm', [command, pkgName + (command === 'install' ? '@' + version : '')], function (err, stdout) { if (err) { return callback(err); } diff --git a/test/mocks/databasemock.js b/test/mocks/databasemock.js index 182d9fea12..b7ed4cfb8c 100644 --- a/test/mocks/databasemock.js +++ b/test/mocks/databasemock.js @@ -140,7 +140,7 @@ nconf.set('theme_config', path.join(nconf.get('themes_path'), 'nodebb-theme-persona', 'theme.json')); nconf.set('bcrypt_rounds', 1); - require('../../build').buildTargets(['js', 'clientCSS', 'acpCSS', 'tpl'], next); + require('../../build').buildAll(next); }, function (next) { var webserver = require('../../src/webserver'); From 0b95eab71e141f72765cc8ae1e8406ea6ea5ec2e Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 23 Jan 2017 13:02:35 +0300 Subject: [PATCH 086/122] use roomName if availabe in taskbar if room is renamed update title on taskbar --- public/src/modules/chat.js | 9 ++++++--- public/src/modules/taskbar.js | 8 ++++++-- src/messaging/notifications.js | 16 ++++++++++++---- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/public/src/modules/chat.js b/public/src/modules/chat.js index f231fd765d..9ef9d21c77 100644 --- a/public/src/modules/chat.js +++ b/public/src/modules/chat.js @@ -70,7 +70,7 @@ define('chat', [ sounds.play('chat-incoming'); taskbar.push('chat', modal.attr('UUID'), { - title: username, + title: data.roomName || username, touid: data.message.fromUser.uid, roomId: data.roomId }); @@ -102,7 +102,10 @@ define('chat', [ }); socket.on('event:chats.roomRename', function (data) { - module.getModal(data.roomId).find('[component="chat/room/name"]').val($('
    ').html(data.newName).text()); + var newTitle = $('
    ').html(data.newName).text(); + var modal = module.getModal(data.roomId); + modal.find('[component="chat/room/name"]').val(newTitle); + taskbar.updateTitle('chat', modal.attr('UUID'), newTitle); }); ChatsMessages.onChatMessageEdit(); @@ -197,7 +200,7 @@ define('chat', [ handle: '.modal-header' }); }); - + scrollStop.apply(chatModal.find('[component="chat/messages"]')); chatModal.find('#chat-close-btn').on('click', function () { diff --git a/public/src/modules/taskbar.js b/public/src/modules/taskbar.js index 7a0b3c39ea..6cd735f15f 100644 --- a/public/src/modules/taskbar.js +++ b/public/src/modules/taskbar.js @@ -39,7 +39,7 @@ define('taskbar', function () { taskbar.discard = function (module, uuid) { var btnEl = taskbar.tasklist.find('[data-module="' + module + '"][data-uuid="' + uuid + '"]'); btnEl.remove(); - + update(); }; @@ -115,7 +115,7 @@ define('taskbar', function () { .html('' + (data.options.icon ? ' ' : '') + (data.options.image ? ' ' : '') + - '' + title + '' + + '' + title + '' + '') .attr({ 'data-module': data.module, @@ -136,5 +136,9 @@ define('taskbar', function () { $(window).trigger('action:taskbar.pushed', data); } + taskbar.updateTitle = function(module, uuid, newTitle) { + taskbar.tasklist.find('[data-module="' + module + '"][data-uuid="' + uuid + '"] [component="taskbar/title"]').text(newTitle); + }; + return taskbar; }); diff --git a/src/messaging/notifications.js b/src/messaging/notifications.js index 6d9500c4ba..2737725462 100644 --- a/src/messaging/notifications.js +++ b/src/messaging/notifications.js @@ -15,7 +15,14 @@ module.exports = function (Messaging) { Messaging.notifyQueue = {}; // Only used to notify a user of a new chat message, see Messaging.notifyUser Messaging.notifyUsersInRoom = function (fromUid, roomId, messageObj) { - Messaging.getUidsInRoom(roomId, 0, -1, function (err, uids) { + async.parallel({ + uids: function (next) { + Messaging.getUidsInRoom(roomId, 0, -1, next); + }, + roomData: function (next) { + Messaging.getRoomData(roomId, next); + } + }, function (err, results) { if (err) { return; } @@ -23,9 +30,10 @@ module.exports = function (Messaging) { var data = { roomId: roomId, fromUid: fromUid, - message: messageObj + message: messageObj, + roomName: results.roomData.roomName }; - uids.forEach(function (uid) { + results.uids.forEach(function (uid) { data.self = parseInt(uid, 10) === parseInt(fromUid) ? 1 : 0; Messaging.pushUnreadCount(uid); sockets.in('uid_' + uid).emit('event:chats.receive', data); @@ -43,7 +51,7 @@ module.exports = function (Messaging) { } queueObj.timeout = setTimeout(function () { - sendNotifications(fromUid, uids, roomId, queueObj.message, function (err) { + sendNotifications(fromUid, results.uids, roomId, queueObj.message, function (err) { if (!err) { delete Messaging.notifyQueue[fromUid + ':' + roomId]; } From 33e452cc8e24af49dba2813d37600fd4598df9fd Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 23 Jan 2017 13:09:51 +0300 Subject: [PATCH 087/122] fix lint --- public/src/modules/taskbar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/modules/taskbar.js b/public/src/modules/taskbar.js index 6cd735f15f..50f8dfd29f 100644 --- a/public/src/modules/taskbar.js +++ b/public/src/modules/taskbar.js @@ -136,7 +136,7 @@ define('taskbar', function () { $(window).trigger('action:taskbar.pushed', data); } - taskbar.updateTitle = function(module, uuid, newTitle) { + taskbar.updateTitle = function (module, uuid, newTitle) { taskbar.tasklist.find('[data-module="' + module + '"][data-uuid="' + uuid + '"] [component="taskbar/title"]').text(newTitle); }; From a7aaf8ea96ce11bb5a8121c007784e26e5a7aef2 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 23 Jan 2017 11:25:05 -0500 Subject: [PATCH 088/122] fixing bug that caused plugin language files to not be parsed --- src/meta/languages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meta/languages.js b/src/meta/languages.js index b7c79db5ba..fd4c9bb0fc 100644 --- a/src/meta/languages.js +++ b/src/meta/languages.js @@ -28,7 +28,7 @@ function getTranslationTree(callback) { }); // Filter out plugins with invalid paths - async.filter(paths, file.exists, function (paths) { + async.filter(paths, file.exists, function (err, paths) { next(null, paths); }); }, From ea7d61e2e4b66d4c4ec06b2512ea443670605baa Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 23 Jan 2017 11:40:51 -0500 Subject: [PATCH 089/122] handling err in src/meta/languages.js --- src/meta/languages.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/meta/languages.js b/src/meta/languages.js index fd4c9bb0fc..bac7a2ba33 100644 --- a/src/meta/languages.js +++ b/src/meta/languages.js @@ -28,9 +28,7 @@ function getTranslationTree(callback) { }); // Filter out plugins with invalid paths - async.filter(paths, file.exists, function (err, paths) { - next(null, paths); - }); + async.filter(paths, file.exists, next); }, function (paths, next) { async.map(paths, Plugins.loadPluginInfo, next); From 8dc5e20f37ef75be03fcefa9359f421589edee3f Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 23 Jan 2017 12:38:05 -0500 Subject: [PATCH 090/122] Up composer version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c57e96b200..e7aefe1f7a 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "morgan": "^1.3.2", "mousetrap": "^1.5.3", "nconf": "~0.8.2", - "nodebb-plugin-composer-default": "4.3.6", + "nodebb-plugin-composer-default": "4.3.7", "nodebb-plugin-dbsearch": "1.0.5", "nodebb-plugin-emoji-extended": "1.1.1", "nodebb-plugin-emoji-one": "1.1.5", From 72092f7109ed3eb78fe4cda09a9ae77f348fba7a Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 23 Jan 2017 14:53:11 -0500 Subject: [PATCH 091/122] bump mentions again --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 56eb8d0702..799e5e687d 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "nodebb-plugin-emoji-extended": "1.1.1", "nodebb-plugin-emoji-one": "1.1.5", "nodebb-plugin-markdown": "7.0.1", - "nodebb-plugin-mentions": "1.1.4", + "nodebb-plugin-mentions": "2.0.0", "nodebb-plugin-soundpack-default": "0.1.6", "nodebb-plugin-spam-be-gone": "0.4.10", "nodebb-rewards-essentials": "0.0.9", From dbb71423a8a830f176fcd37cf44a53ee8c5f7690 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 23 Jan 2017 15:17:53 -0500 Subject: [PATCH 092/122] executing core middlewares first before secondary or plugin middlewares --- src/routes/helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/helpers.js b/src/routes/helpers.js index 3f3ff06472..fd466c78f1 100644 --- a/src/routes/helpers.js +++ b/src/routes/helpers.js @@ -3,7 +3,7 @@ var helpers = {}; helpers.setupPageRoute = function (router, name, middleware, middlewares, controller) { - middlewares = middlewares.concat([middleware.registrationComplete, middleware.pageView, middleware.pluginHooks]); + middlewares = [middleware.registrationComplete, middleware.pageView, middleware.pluginHooks].concat(middlewares); router.get(name, middleware.busyCheck, middleware.buildHeader, middlewares, controller); router.get('/api' + name, middlewares, controller); From f0c941e5aeef86f3b31e6512643bd15d14afd839 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Mon, 23 Jan 2017 17:09:32 -0700 Subject: [PATCH 093/122] No 404 responses for missing language files --- src/routes/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/routes/index.js b/src/routes/index.js index 99ff3a7f27..d33fd316b5 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -157,6 +157,11 @@ module.exports = function (app, middleware, hotswapIds) { res.redirect(relativePath + '/assets/language' + req.path + '.json?' + meta.config['cache-buster']); }); + // stop 404's on `/assets/language` route + app.use(relativePath + '/assets/language', function (req, res) { + res.json({}); + }); + app.use(relativePath, express.static(path.join(__dirname, '../../', 'public'), { maxAge: app.enabled('cache') ? 5184000000 : 0 })); From aeed8f53f3eda192444b809eefd602af8c41db60 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 24 Jan 2017 12:45:36 +0300 Subject: [PATCH 094/122] closes #5393 --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 799e5e687d..2b9e9ccd5f 100644 --- a/package.json +++ b/package.json @@ -81,9 +81,9 @@ "semver": "^5.1.0", "serve-favicon": "^2.1.5", "sitemap": "^1.4.0", - "socket.io": "1.7.1", - "socket.io-client": "1.7.1", - "socket.io-redis": "2.0.0", + "socket.io": "1.7.2", + "socket.io-client": "1.7.2", + "socket.io-redis": "3.1.0", "socketio-wildcard": "~0.3.0", "string": "^3.0.0", "templates.js": "0.3.6", From ae279fe57f65517cac13ade727d03b9bbd39a849 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 24 Jan 2017 12:33:22 -0500 Subject: [PATCH 095/122] casting some values as int, in ensureSelfOrPrivileged middleware --- src/middleware/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middleware/index.js b/src/middleware/index.js index 8f8f8a8002..b32b9147a4 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -79,7 +79,7 @@ middleware.ensureSelfOrPrivileged = function (req, res, next) { middleware.exposeUid prior to invoking this middleware. */ if (req.user) { - if (req.user.uid === res.locals.uid) { + if (parseInt(req.user.uid, 10) === parseInt(res.locals.uid, 10)) { return next(); } From 2a33991f0de40a38f3988664d078b3cf35e7ff2d Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 25 Jan 2017 01:32:24 +0300 Subject: [PATCH 096/122] read usercount from global object --- src/controllers/admin/users.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/controllers/admin/users.js b/src/controllers/admin/users.js index 0e67c7d64c..422de5b02d 100644 --- a/src/controllers/admin/users.js +++ b/src/controllers/admin/users.js @@ -128,7 +128,11 @@ function getUsers(set, section, min, max, req, res, next) { if (byScore) { db.sortedSetCount(set, min, max, next); } else { - db.sortedSetCard(set, next); + if (set === 'users:banned' || set === 'users:notvalidated') { + db.sortedSetCard(set, next); + } else { + db.getObjectField('global', 'userCount', next); + } } }, users: function (next) { From f4147f7922e1f19b1f442546f2225b7bc3193b48 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Mon, 23 Jan 2017 21:06:34 -0700 Subject: [PATCH 097/122] Generate cache buster on build --- build.js | 23 ++++++++++++++------- src/meta/cacheBuster.js | 46 +++++++++++++++++++++++++++++++++++++++++ src/meta/configs.js | 14 +++++++++---- 3 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 src/meta/cacheBuster.js diff --git a/build.js b/build.js index 73013231d5..89c55177ad 100644 --- a/build.js +++ b/build.js @@ -44,6 +44,8 @@ exports.build = function build(targets, callback) { exports.buildTargets = function (targets, callback) { var meta = require('./src/meta'); + var cacheBuster = require('./src/meta/cacheBuster'); + buildStart = buildStart || Date.now(); var step = function (startTime, target, next, err) { @@ -114,14 +116,21 @@ exports.buildTargets = function (targets, callback) { return process.exit(1); } - var time = (Date.now() - buildStart) / 1000; + cacheBuster.write(function (err) { + if (err) { + winston.error('[build] Failed to write `cache-buster.conf`: ' + err.message); + return process.exit(1); + } - winston.info('[build] Asset compilation successful. Completed in ' + time + 's.'); + var time = (Date.now() - buildStart) / 1000; - if (typeof callback === 'function') { - callback(); - } else { - process.exit(0); - } + winston.info('[build] Asset compilation successful. Completed in ' + time + 's.'); + + if (typeof callback === 'function') { + callback(); + } else { + process.exit(0); + } + }); }); }; \ No newline at end of file diff --git a/src/meta/cacheBuster.js b/src/meta/cacheBuster.js new file mode 100644 index 0000000000..ca00fba057 --- /dev/null +++ b/src/meta/cacheBuster.js @@ -0,0 +1,46 @@ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var mkdirp = require('mkdirp'); +var winston = require('winston'); + +var filePath = path.join(__dirname, '../../build/cache-buster'); + +var cached; + +// cache buster is an 11-character, lowercase, alphanumeric string +function generate() { + return (Math.random() * 1e18).toString(32).slice(0, 11); +} + +exports.write = function write(callback) { + mkdirp(path.dirname(filePath), function (err) { + if (err) { + return callback(err); + } + + fs.writeFile(filePath, generate(), callback); + }); +}; + +exports.read = function read(callback) { + if (cached) { + return callback(null, cached); + } + + fs.readFile(filePath, function (err, buffer) { + if (err) { + winston.warn('[cache-buster] could not read cache buster: ' + err.message); + return callback(); + } + + buffer = buffer.toString(); + if (buffer) { + cached = buffer; + return callback(null, cached); + } + + callback(); + }); +}; diff --git a/src/meta/configs.js b/src/meta/configs.js index 75da0595d2..907e0ef477 100644 --- a/src/meta/configs.js +++ b/src/meta/configs.js @@ -6,7 +6,7 @@ var nconf = require('nconf'); var db = require('../database'); var pubsub = require('../pubsub'); -var utils = require('../../public/src/utils'); +var cacheBuster = require('./cacheBuster'); module.exports = function (Meta) { @@ -21,10 +21,16 @@ module.exports = function (Meta) { Meta.configs.list(next); }, function (config, next) { - config['cache-buster'] = 'v=' + utils.generateUUID(); + cacheBuster.read(function (err, buster) { + if (err) { + return next(err); + } + + config['cache-buster'] = 'v=' + (buster || Date.now()); - Meta.config = config; - setImmediate(next); + Meta.config = config; + next(); + }); } ], callback); }; From 4df8832c8db5f2728f3183f2192d913cf45b5382 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 25 Jan 2017 11:02:23 -0500 Subject: [PATCH 098/122] adding conditional to upgrade script to handle cases where an upgrade is performed on a flag that is already in database --- src/upgrade.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/upgrade.js b/src/upgrade.js index 8dce35b901..12939ad99d 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -385,7 +385,14 @@ Upgrade.upgrade = function (callback) { setImmediate(next); } } - ], next); + ], function (err) { + if (err && err.message === '[[error:already-flagged]]') { + // Already flagged, no need to parse, but not an error + next(); + } else { + next(err); + } + }); }); }, next); }); From a143a15f5d2e081e3d4bb18580db5b27885230a7 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 26 Jan 2017 20:44:26 +0300 Subject: [PATCH 099/122] closes #5397 --- src/posts/create.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/posts/create.js b/src/posts/create.js index 3484bc424e..6cb925dc4c 100644 --- a/src/posts/create.js +++ b/src/posts/create.js @@ -108,7 +108,7 @@ module.exports = function (Posts) { }, function (postData, next) { postData.isMain = isMain; - plugins.fireHook('action:post.save', _.clone(postData)); + plugins.fireHook('action:post.save', {post: _.clone(postData)}); next(null, postData); } ], callback); From 3fb7f9fce5f70ce51fc0610999be593722662e68 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 26 Jan 2017 22:18:16 +0300 Subject: [PATCH 100/122] closes #5398 --- src/categories/create.js | 2 +- src/categories/delete.js | 2 +- src/controllers/authentication.js | 2 +- src/groups/create.js | 2 +- src/groups/delete.js | 3 +-- src/plugins/install.js | 4 ++-- src/posts.js | 4 ++-- src/socket.io/admin.js | 3 ++- src/topics/create.js | 7 +++--- src/topics/tools.js | 37 ++++++++++++------------------- src/user/create.js | 2 +- 11 files changed, 30 insertions(+), 38 deletions(-) diff --git a/src/categories/create.js b/src/categories/create.js index cebcbcd82b..ba12fc31b0 100644 --- a/src/categories/create.js +++ b/src/categories/create.js @@ -73,7 +73,7 @@ module.exports = function (Categories) { next(null, category); }, function (category, next) { - plugins.fireHook('action:category.create', category); + plugins.fireHook('action:category.create', {category: category}); next(null, category); } ], callback); diff --git a/src/categories/delete.js b/src/categories/delete.js index 06d4931132..cb0d30a09d 100644 --- a/src/categories/delete.js +++ b/src/categories/delete.js @@ -31,7 +31,7 @@ module.exports = function (Categories) { purgeCategory(cid, next); }, function (next) { - plugins.fireHook('action:category.delete', cid); + plugins.fireHook('action:category.delete', {cid: cid, uid: uid}); next(); } ], callback); diff --git a/src/controllers/authentication.js b/src/controllers/authentication.js index 90a1715cbb..4aa1b028f6 100644 --- a/src/controllers/authentication.js +++ b/src/controllers/authentication.js @@ -332,7 +332,7 @@ authenticationController.onSuccessfulLogin = function (req, uid, callback) { // Force session check for all connected socket.io clients with the same session id sockets.in('sess_' + req.sessionID).emit('checkSession', uid); - plugins.fireHook('action:user.loggedIn', uid); + plugins.fireHook('action:user.loggedIn', {uid: uid, req: req}); callback(); }); }; diff --git a/src/groups/create.js b/src/groups/create.js index a59567afe6..e4533e1ab0 100644 --- a/src/groups/create.js +++ b/src/groups/create.js @@ -70,7 +70,7 @@ module.exports = function (Groups) { async.series(tasks, next); }, function (results, next) { - plugins.fireHook('action:group.create', groupData); + plugins.fireHook('action:group.create', {group: groupData}); next(null, groupData); } ], callback); diff --git a/src/groups/delete.js b/src/groups/delete.js index 0838dd2407..3c2e02ae73 100644 --- a/src/groups/delete.js +++ b/src/groups/delete.js @@ -17,8 +17,6 @@ module.exports = function (Groups) { } var groupObj = groupsData[0]; - plugins.fireHook('action:group.destroy', groupObj); - async.parallel([ async.apply(db.delete, 'group:' + groupName), async.apply(db.sortedSetRemove, 'groups:createtime', groupName), @@ -45,6 +43,7 @@ module.exports = function (Groups) { return callback(err); } Groups.resetCache(); + plugins.fireHook('action:group.destroy', {group: groupObj}); callback(); }); }); diff --git a/src/plugins/install.js b/src/plugins/install.js index a914a09ca6..5c6e4dddac 100644 --- a/src/plugins/install.js +++ b/src/plugins/install.js @@ -50,7 +50,7 @@ module.exports = function (Plugins) { }, function (next) { meta.reloadRequired = true; - Plugins.fireHook(isActive ? 'action:plugin.deactivate' : 'action:plugin.activate', id); + Plugins.fireHook(isActive ? 'action:plugin.deactivate' : 'action:plugin.activate', {id: id}); next(); } ], function (err) { @@ -95,7 +95,7 @@ module.exports = function (Plugins) { Plugins.get(id, next); }, function (pluginData, next) { - Plugins.fireHook('action:plugin.' + type, id); + Plugins.fireHook('action:plugin.' + type, {id: id, version: version}); next(null, pluginData); } ], callback); diff --git a/src/posts.js b/src/posts.js index ed22e51ed1..b8eb93fa1a 100644 --- a/src/posts.js +++ b/src/posts.js @@ -156,7 +156,7 @@ var plugins = require('./plugins'); pid: pid }; data[field] = value; - plugins.fireHook('action:post.setFields', data); + plugins.fireHook('action:post.setFields', {data: data}); callback(); }); }; @@ -167,7 +167,7 @@ var plugins = require('./plugins'); return callback(err); } data.pid = pid; - plugins.fireHook('action:post.setFields', data); + plugins.fireHook('action:post.setFields', {data: data}); callback(); }); }; diff --git a/src/socket.io/admin.js b/src/socket.io/admin.js index b16bafa296..320832e363 100644 --- a/src/socket.io/admin.js +++ b/src/socket.io/admin.js @@ -168,10 +168,11 @@ SocketAdmin.config.setMultiple = function (socket, data, callback) { key: field, value: data[field] }; - plugins.fireHook('action:config.set', setting); + logger.monitorConfig({io: index.server}, setting); } } + plugins.fireHook('action:config.set', {settings: data}); setImmediate(next); } ], callback); diff --git a/src/topics/create.js b/src/topics/create.js index bf62266ecf..2026f006da 100644 --- a/src/topics/create.js +++ b/src/topics/create.js @@ -2,6 +2,7 @@ 'use strict'; var async = require('async'); +var _ = require('underscore'); var validator = require('validator'); var S = require('string'); var db = require('../database'); @@ -82,7 +83,7 @@ module.exports = function (Topics) { ], next); }, function (results, next) { - plugins.fireHook('action:topic.save', topicData); + plugins.fireHook('action:topic.save', {topic: _.clone(topicData)}); next(null, topicData.tid); } ], callback); @@ -174,7 +175,7 @@ module.exports = function (Topics) { data.postData.index = 0; analytics.increment(['topics', 'topics:byCid:' + data.topicData.cid]); - plugins.fireHook('action:topic.post', data.topicData); + plugins.fireHook('action:topic.post', {topic: data.topicData, post: data.postData}); if (parseInt(uid, 10)) { user.notifications.sendTopicNotificationToFollowers(uid, data.topicData, data.postData); @@ -269,7 +270,7 @@ module.exports = function (Topics) { Topics.notifyFollowers(postData, uid); analytics.increment(['posts', 'posts:byCid:' + cid]); - plugins.fireHook('action:topic.reply', postData); + plugins.fireHook('action:topic.reply', {post: _.clone(postData)}); next(null, postData); } diff --git a/src/topics/tools.js b/src/topics/tools.js index a8c00e08c0..295e2a028b 100644 --- a/src/topics/tools.js +++ b/src/topics/tools.js @@ -114,18 +114,18 @@ module.exports = function (Topics) { function toggleLock(tid, uid, lock, callback) { callback = callback || function () {}; - var cid; + var topicData; async.waterfall([ function (next) { - Topics.getTopicField(tid, 'cid', next); + Topics.getTopicFields(tid, ['tid', 'uid', 'cid'], next); }, - function (_cid, next) { - cid = _cid; - if (!cid) { + function (_topicData, next) { + topicData = _topicData; + if (!topicData || !topicData.cid) { return next(new Error('[[error:no-topic]]')); } - privileges.categories.isAdminOrMod(cid, uid, next); + privileges.categories.isAdminOrMod(topicData.cid, uid, next); }, function (isAdminOrMod, next) { if (!isAdminOrMod) { @@ -135,16 +135,11 @@ module.exports = function (Topics) { Topics.setTopicField(tid, 'locked', lock ? 1 : 0, next); }, function (next) { - var data = { - tid: tid, - isLocked: lock, - uid: uid, - cid: cid - }; + topicData.isLocked = lock; - plugins.fireHook('action:topic.lock', data); + plugins.fireHook('action:topic.lock', {topic: _.clone(topicData), uid: uid}); - next(null, data); + next(null, topicData); } ], callback); } @@ -167,7 +162,7 @@ module.exports = function (Topics) { if (!exists) { return callback(new Error('[[error:no-topic]]')); } - Topics.getTopicFields(tid, ['cid', 'lastposttime', 'postcount'], next); + Topics.getTopicFields(tid, ['uid', 'tid', 'cid', 'lastposttime', 'postcount'], next); }, function (_topicData, next) { topicData = _topicData; @@ -198,16 +193,12 @@ module.exports = function (Topics) { ], next); }, function (results, next) { - var data = { - tid: tid, - isPinned: pin, - uid: uid, - cid: topicData.cid - }; - plugins.fireHook('action:topic.pin', data); + topicData.isPinned = pin; - next(null, data); + plugins.fireHook('action:topic.pin', {topic: _.clone(topicData), uid: uid}); + + next(null, topicData); } ], callback); } diff --git a/src/user/create.js b/src/user/create.js index 67d6baf3cd..c6cd92460a 100644 --- a/src/user/create.js +++ b/src/user/create.js @@ -141,7 +141,7 @@ module.exports = function (User) { if (userNameChanged) { User.notifications.sendNameChangeNotification(userData.uid, userData.username); } - plugins.fireHook('action:user.create', userData); + plugins.fireHook('action:user.create', {user: userData}); next(null, userData.uid); } ], callback); From 46cde0444ed17a3fbb45374a9119751ddf31adee Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 27 Jan 2017 12:40:52 +0300 Subject: [PATCH 101/122] up dbsearch --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b9e9ccd5f..5835a9f1f3 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "mousetrap": "^1.5.3", "nconf": "~0.8.2", "nodebb-plugin-composer-default": "4.3.7", - "nodebb-plugin-dbsearch": "1.0.5", + "nodebb-plugin-dbsearch": "2.0.0", "nodebb-plugin-emoji-extended": "1.1.1", "nodebb-plugin-emoji-one": "1.1.5", "nodebb-plugin-markdown": "7.0.1", From a89ed01f4f7d0969625328bd94b419e36be74f72 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 27 Jan 2017 13:14:05 +0300 Subject: [PATCH 102/122] up composer --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5835a9f1f3..ce4e35e96a 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "mousetrap": "^1.5.3", "nconf": "~0.8.2", "nodebb-plugin-composer-default": "4.3.7", - "nodebb-plugin-dbsearch": "2.0.0", + "nodebb-plugin-dbsearch": "2.0.1", "nodebb-plugin-emoji-extended": "1.1.1", "nodebb-plugin-emoji-one": "1.1.5", "nodebb-plugin-markdown": "7.0.1", From f1f00b63fb39d52f1912cef35d4b8a1c317ea9d8 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 27 Jan 2017 20:35:50 +0300 Subject: [PATCH 103/122] closes #5400 --- public/src/modules/translator.js | 6 +++--- test/translator.js | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/public/src/modules/translator.js b/public/src/modules/translator.js index eac467f413..db3953229e 100644 --- a/public/src/modules/translator.js +++ b/public/src/modules/translator.js @@ -155,7 +155,7 @@ while (cursor + 2 <= len) { sliced = str.slice(cursor, cursor + 2); - // found some text after the double bracket, + // found some text after the double bracket, // so this is probably a translation string if (!textBeforeColonFound && validTextRegex.test(sliced[0])) { textBeforeColonFound = true; @@ -174,7 +174,7 @@ cursor += 1; // a space or comma was found before the name // this isn't a translation string, so back out - } else if (!(textBeforeColonFound && colonFound && textAfterColonFound && commaAfterNameFound) && + } else if (!(textBeforeColonFound && colonFound && textAfterColonFound && commaAfterNameFound) && invalidTextRegex.test(sliced[0])) { cursor += 1; lastBreak -= 2; @@ -272,7 +272,7 @@ } var out = translated; translatedArgs.forEach(function (arg, i) { - var escaped = arg.replace(/%/g, '%').replace(/\\,/g, ','); + var escaped = arg.replace(/%(?=\d)/g, '%').replace(/\\,/g, ','); out = out.replace(new RegExp('%' + (i + 1), 'g'), escaped); }); return out; diff --git a/test/translator.js b/test/translator.js index 8198814164..17affe1700 100644 --- a/test/translator.js +++ b/test/translator.js @@ -4,6 +4,7 @@ var assert = require('assert'); var shim = require('../public/src/modules/translator.js'); var Translator = shim.Translator; +var db = require('./mocks/databasemock'); require('../src/languages').init(function () {}); @@ -118,10 +119,20 @@ describe('new Translator(language)', function () { it('should properly escape and ignore % and \\, in arguments', function () { var translator = Translator.create('en-GB'); - var title = 'Test 1\\, 2\\, 3 % salmon'; + var title = 'Test 1\\, 2\\, 3 %2 salmon'; var key = "[[topic:composer.replying_to, " + title + "]]"; return translator.translate(key).then(function (translated) { - assert.strictEqual(translated, 'Replying to Test 1, 2, 3 % salmon'); + assert.strictEqual(translated, 'Replying to Test 1, 2, 3 %2 salmon'); + }); + }); + + it('should not escape regular %', function () { + var translator = Translator.create('en-GB'); + + var title = '3 % salmon'; + var key = "[[topic:composer.replying_to, " + title + "]]"; + return translator.translate(key).then(function (translated) { + assert.strictEqual(translated, 'Replying to 3 % salmon'); }); }); @@ -173,7 +184,7 @@ describe('Translator.create()', function () { describe('Translator modules', function () { it('should work before registered', function () { var translator = Translator.create(); - + Translator.registerModule('test-custom-integer-format', function (lang) { return function (key, args) { var num = parseInt(args[0], 10) || 0; From 366ab103a460fcf53990ee44f20fe05bfe7b5c8a Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 27 Jan 2017 20:37:54 +0300 Subject: [PATCH 104/122] closes #5405 --- src/controllers/unread.js | 10 +++++++- src/socket.io/topics/infinitescroll.js | 2 +- src/socket.io/topics/unread.js | 2 +- src/topics/unread.js | 33 ++++++++++++-------------- test/topics.js | 8 +++---- 5 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/controllers/unread.js b/src/controllers/unread.js index 83de85a67e..8be52f955c 100644 --- a/src/controllers/unread.js +++ b/src/controllers/unread.js @@ -40,7 +40,15 @@ unreadController.get = function (req, res, next) { settings = results.settings; var start = Math.max(0, (page - 1) * settings.topicsPerPage); var stop = start + settings.topicsPerPage - 1; - topics.getUnreadTopics(cid, req.uid, start, stop, filter, next); + var cutoff = req.session.unreadCutoff ? req.session.unreadCutoff : topics.unreadCutoff(); + topics.getUnreadTopics({ + cid: cid, + uid: req.uid, + start: start, + stop: stop, + filter: filter, + cutoff: cutoff + }, next); } ], function (err, data) { if (err) { diff --git a/src/socket.io/topics/infinitescroll.js b/src/socket.io/topics/infinitescroll.js index a68d220609..3efa621656 100644 --- a/src/socket.io/topics/infinitescroll.js +++ b/src/socket.io/topics/infinitescroll.js @@ -98,7 +98,7 @@ module.exports = function (SocketTopics) { var start = parseInt(data.after, 10); var stop = start + 9; - topics.getUnreadTopics(data.cid, socket.uid, start, stop, data.filter, callback); + topics.getUnreadTopics({cid: data.cid, uid: socket.uid, start: start, stop: stop, filter: data.filter}, callback); }; SocketTopics.loadMoreRecentTopics = function (socket, data, callback) { diff --git a/src/socket.io/topics/unread.js b/src/socket.io/topics/unread.js index 39c6485a26..d5a010af14 100644 --- a/src/socket.io/topics/unread.js +++ b/src/socket.io/topics/unread.js @@ -51,7 +51,7 @@ module.exports = function (SocketTopics) { SocketTopics.markCategoryTopicsRead = function (socket, cid, callback) { async.waterfall([ function (next) { - topics.getUnreadTids(cid, socket.uid, '', next); + topics.getUnreadTids({cid: cid, uid: socket.uid, filter: ''}, next); }, function (tids, next) { SocketTopics.markAsRead(socket, tids, next); diff --git a/src/topics/unread.js b/src/topics/unread.js index e61ca46d59..a754fa0f99 100644 --- a/src/topics/unread.js +++ b/src/topics/unread.js @@ -18,14 +18,13 @@ module.exports = function (Topics) { callback = filter; filter = ''; } - Topics.getUnreadTids(0, uid, filter, function (err, tids) { + Topics.getUnreadTids({cid: 0, uid: uid, filter: filter}, function (err, tids) { callback(err, Array.isArray(tids) ? tids.length : 0); }); }; - Topics.getUnreadTopics = function (cid, uid, start, stop, filter, callback) { - + Topics.getUnreadTopics = function (params, callback) { var unreadTopics = { showSelect: true, nextStart : 0, @@ -34,7 +33,7 @@ module.exports = function (Topics) { async.waterfall([ function (next) { - Topics.getUnreadTids(cid, uid, filter, next); + Topics.getUnreadTids(params, next); }, function (tids, next) { unreadTopics.topicCount = tids.length; @@ -43,13 +42,13 @@ module.exports = function (Topics) { return next(null, []); } - if (stop === -1) { - tids = tids.slice(start); + if (params.stop === -1) { + tids = tids.slice(params.start); } else { - tids = tids.slice(start, stop + 1); + tids = tids.slice(params.start, params.stop + 1); } - Topics.getTopicsByTids(tids, uid, next); + Topics.getTopicsByTids(tids, params.uid, next); }, function (topicData, next) { if (!Array.isArray(topicData) || !topicData.length) { @@ -57,7 +56,7 @@ module.exports = function (Topics) { } unreadTopics.topics = topicData; - unreadTopics.nextStart = stop + 1; + unreadTopics.nextStart = params.stop + 1; next(null, unreadTopics); } ], callback); @@ -67,21 +66,19 @@ module.exports = function (Topics) { return Date.now() - (parseInt(meta.config.unreadCutoff, 10) || 2) * 86400000; }; - Topics.getUnreadTids = function (cid, uid, filter, callback) { - uid = parseInt(uid, 10); + Topics.getUnreadTids = function (params, callback) { + var uid = parseInt(params.uid, 10); if (uid === 0) { return callback(null, []); } - - var cutoff = Topics.unreadCutoff(); - + var cutoff = params.cutoff || Topics.unreadCutoff(); var ignoredCids; async.waterfall([ function (next) { async.parallel({ ignoredCids: function (next) { - if (filter === 'watched') { + if (params.filter === 'watched') { return next(null, []); } user.getIgnoredCategories(uid, next); @@ -121,7 +118,7 @@ module.exports = function (Topics) { if (results.ignoredTids.indexOf(recentTopic.value.toString()) !== -1) { return false; } - switch (filter) { + switch (params.filter) { case 'new': return !userRead[recentTopic.value]; default: @@ -133,7 +130,7 @@ module.exports = function (Topics) { return array.indexOf(tid) === index; }); - if (filter === 'watched') { + if (params.filter === 'watched') { Topics.filterWatchedTids(tids, uid, next); } else { next(null, tids); @@ -143,7 +140,7 @@ module.exports = function (Topics) { tids = tids.slice(0, 200); - filterTopics(uid, tids, cid, ignoredCids, filter, next); + filterTopics(uid, tids, params.cid, ignoredCids, params.filter, next); } ], callback); }; diff --git a/test/topics.js b/test/topics.js index 3a192b9e94..38881c4d58 100644 --- a/test/topics.js +++ b/test/topics.js @@ -445,7 +445,7 @@ describe('Topic\'s', function () { assert.equal(pinnedTids[1], tid2); done(); }); - }); + }); }); }); @@ -482,7 +482,7 @@ describe('Topic\'s', function () { topics.ignore( newTid, uid, done ); }, function (done) { - topics.getUnreadTopics(0, uid, 0, -1, '', done ); + topics.getUnreadTopics({cid: 0, uid: uid, start: 0, stop: -1, filter: ''}, done ); }, function (results, done) { var topics = results.topics; @@ -526,7 +526,7 @@ describe('Topic\'s', function () { topics.follow( newTid, uid, done ); }, function (done) { - topics.getUnreadTopics(0, uid, 0, -1, '', done ); + topics.getUnreadTopics({cid: 0, uid: uid, start: 0, stop: -1, filter: ''}, done ); }, function (results, done) { var topics = results.topics; @@ -546,7 +546,7 @@ describe('Topic\'s', function () { topics.follow( newTid, uid, done ); }, function (done) { - topics.getUnreadTopics(0, uid, 0, -1, '', done ); + topics.getUnreadTopics({cid: 0, uid: uid, start: 0, stop: -1, filter: ''}, done ); }, function (results, done) { var topics = results.topics; From 54ac23cc7a708cda27cb7b6e9393b3ba66dbcd89 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Mon, 30 Jan 2017 15:22:20 -0700 Subject: [PATCH 105/122] Revert "No 404 responses for missing language files" This reverts commit f0c941e5aeef86f3b31e6512643bd15d14afd839. --- src/routes/index.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/routes/index.js b/src/routes/index.js index d33fd316b5..99ff3a7f27 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -157,11 +157,6 @@ module.exports = function (app, middleware, hotswapIds) { res.redirect(relativePath + '/assets/language' + req.path + '.json?' + meta.config['cache-buster']); }); - // stop 404's on `/assets/language` route - app.use(relativePath + '/assets/language', function (req, res) { - res.json({}); - }); - app.use(relativePath, express.static(path.join(__dirname, '../../', 'public'), { maxAge: app.enabled('cache') ? 5184000000 : 0 })); From b37d52c089b29204eacb6c1dcf75166666f2dab9 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 31 Jan 2017 18:38:01 +0300 Subject: [PATCH 106/122] closes #5407 --- src/plugins/hooks.js | 4 +++- src/plugins/install.js | 20 ++++++++++++-------- src/plugins/load.js | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/plugins/hooks.js b/src/plugins/hooks.js index b5a32ba1b7..a6a014e776 100644 --- a/src/plugins/hooks.js +++ b/src/plugins/hooks.js @@ -8,7 +8,9 @@ module.exports = function (Plugins) { 'filter:user.custom_fields': null, // remove in v1.1.0 'filter:post.save': 'filter:post.create', 'filter:user.profileLinks': 'filter:user.profileMenu', - 'action:post.flag': 'action:flag.create' + 'action:post.flag': 'action:flag.create', + 'action:plugin.activate': null, + 'action:plugin.install': null }; /* `data` is an object consisting of (* is required): diff --git a/src/plugins/install.js b/src/plugins/install.js index 5c6e4dddac..927316a21c 100644 --- a/src/plugins/install.js +++ b/src/plugins/install.js @@ -50,8 +50,11 @@ module.exports = function (Plugins) { }, function (next) { meta.reloadRequired = true; - Plugins.fireHook(isActive ? 'action:plugin.deactivate' : 'action:plugin.activate', {id: id}); - next(); + if (isActive) { + Plugins.fireHook('action:plugin.deactivate', {id: id}); + } + + setImmediate(next); } ], function (err) { if (err) { @@ -68,7 +71,6 @@ module.exports = function (Plugins) { }; function toggleInstall(id, version, callback) { - var type; var installed; async.waterfall([ function (next) { @@ -76,7 +78,6 @@ module.exports = function (Plugins) { }, function (_installed, next) { installed = _installed; - type = installed ? 'uninstall' : 'install'; Plugins.isActive(id, next); }, function (active, next) { @@ -86,17 +87,20 @@ module.exports = function (Plugins) { }); return; } - next(); + setImmediate(next); }, function (next) { - runNpmCommand(type, id, version || 'latest', next); + runNpmCommand(installed ? 'uninstall' : 'install', id, version || 'latest', next); }, function (next) { Plugins.get(id, next); }, function (pluginData, next) { - Plugins.fireHook('action:plugin.' + type, {id: id, version: version}); - next(null, pluginData); + if (installed) { + Plugins.fireHook('action:plugin.uninstall', {id: id, version: version}); + } + + setImmediate(next, null, pluginData); } ], callback); } diff --git a/src/plugins/load.js b/src/plugins/load.js index 43c3d96f4c..c1d1edf6eb 100644 --- a/src/plugins/load.js +++ b/src/plugins/load.js @@ -88,7 +88,7 @@ module.exports = function (Plugins) { }, function (next) { mapClientModules(pluginData, next); - }, + } ], function (err) { if (err) { winston.verbose('[plugins] Could not load plugin : ' + pluginData.id); From cd652e6730479133afa3dc14ca9acfaeaadfc5bf Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 31 Jan 2017 11:45:20 -0500 Subject: [PATCH 107/122] up mentions --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 14abe3d6da..b2693c9aab 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "nodebb-plugin-emoji-extended": "1.1.1", "nodebb-plugin-emoji-one": "1.1.5", "nodebb-plugin-markdown": "7.0.1", - "nodebb-plugin-mentions": "2.0.0", + "nodebb-plugin-mentions": "2.0.1", "nodebb-plugin-soundpack-default": "0.1.6", "nodebb-plugin-spam-be-gone": "0.4.10", "nodebb-rewards-essentials": "0.0.9", From 9a0bd29d677d27372e2f9ec8463559c44b1a42ad Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 31 Jan 2017 12:12:02 -0500 Subject: [PATCH 108/122] up vanilla --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b2693c9aab..58346fe76c 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.15", "nodebb-theme-persona": "4.1.95", - "nodebb-theme-vanilla": "5.1.58", + "nodebb-theme-vanilla": "5.1.59", "nodebb-widget-essentials": "2.0.13", "nodemailer": "2.6.4", "nodemailer-sendmail-transport": "1.0.0", From 6b9bafc6cd417204dc0453c4f82de8cc7438118e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 2 Feb 2017 11:53:37 -0500 Subject: [PATCH 109/122] adding missing flag strings --- public/language/ar/pages.json | 4 +++- public/language/bg/pages.json | 4 +++- public/language/bn/pages.json | 4 +++- public/language/cs/pages.json | 4 +++- public/language/da/pages.json | 4 +++- public/language/de/pages.json | 4 +++- public/language/el/pages.json | 4 +++- public/language/en-US/pages.json | 4 +++- public/language/en-x-pirate/pages.json | 4 +++- public/language/es/pages.json | 4 +++- public/language/et/pages.json | 4 +++- public/language/fa-IR/pages.json | 4 +++- public/language/fi/pages.json | 4 +++- public/language/fr/pages.json | 4 +++- public/language/gl/pages.json | 4 +++- public/language/he/pages.json | 4 +++- public/language/hu/pages.json | 4 +++- public/language/id/pages.json | 4 +++- public/language/it/pages.json | 4 +++- public/language/ja/pages.json | 4 +++- public/language/ko/pages.json | 4 +++- public/language/lt/pages.json | 4 +++- public/language/ms/pages.json | 4 +++- public/language/nb/pages.json | 4 +++- public/language/nl/pages.json | 4 +++- public/language/pl/pages.json | 4 +++- public/language/pt-BR/pages.json | 4 +++- public/language/pt-PT/pages.json | 4 +++- public/language/ro/pages.json | 4 +++- public/language/ru/pages.json | 4 +++- public/language/rw/pages.json | 4 +++- public/language/sc/pages.json | 4 +++- public/language/sk/pages.json | 4 +++- public/language/sl/pages.json | 4 +++- public/language/sr/pages.json | 4 +++- public/language/sv/pages.json | 4 +++- public/language/th/pages.json | 4 +++- public/language/tr/pages.json | 4 +++- public/language/vi/pages.json | 4 +++- public/language/zh-CN/pages.json | 4 +++- public/language/zh-TW/pages.json | 4 +++- 41 files changed, 123 insertions(+), 41 deletions(-) diff --git a/public/language/ar/pages.json b/public/language/ar/pages.json index 678658b058..c978c623b3 100644 --- a/public/language/ar/pages.json +++ b/public/language/ar/pages.json @@ -6,7 +6,7 @@ "popular-month": "المواضيع الشائعة هذا الشهر", "popular-alltime": "المواضيع الشائعة منذ القدم", "recent": "المواضيع الحديثة", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "اﻷعضاء المتصلون", "users/latest": "أحدث اﻷعضاء", @@ -27,6 +27,8 @@ "group": "%1 مجموعة", "chats": "محادثات", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/bg/pages.json b/public/language/bg/pages.json index 1425f091da..43c87dde63 100644 --- a/public/language/bg/pages.json +++ b/public/language/bg/pages.json @@ -6,7 +6,7 @@ "popular-month": "Популярните теми този месец", "popular-alltime": "Популярните теми за всички времена", "recent": "Скорошни теми", - "flagged-posts": "Докладвани публикации", + "flagged-content": "Flagged Content", "ip-blacklist": "Черен списък за IP адреси", "users/online": "Потребители на линия", "users/latest": "Последни потребители", @@ -27,6 +27,8 @@ "group": "Група %1", "chats": "Разговори", "chat": "Разговаря с %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Редактиране на „%1“", "account/edit/password": "Редактиране на паролата на „%1“", "account/edit/username": "Редактиране на потребителското име на „%1“", diff --git a/public/language/bn/pages.json b/public/language/bn/pages.json index c68042e529..e08fb8f743 100644 --- a/public/language/bn/pages.json +++ b/public/language/bn/pages.json @@ -6,7 +6,7 @@ "popular-month": "Popular topics this month", "popular-alltime": "All time popular topics", "recent": "সাম্প্রতিক টপিক", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online Users", "users/latest": "Latest Users", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/cs/pages.json b/public/language/cs/pages.json index 64902c40c0..97a19aebaa 100644 --- a/public/language/cs/pages.json +++ b/public/language/cs/pages.json @@ -6,7 +6,7 @@ "popular-month": "Oblíbená témata pro tento měsíc", "popular-alltime": "Oblíbená témata za celou dobu", "recent": "Aktuální témata", - "flagged-posts": "Označené příspěvky", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Uživatelé online", "users/latest": "Nejnovější uživatelé", @@ -27,6 +27,8 @@ "group": "%1 skupina", "chats": "Chaty", "chat": "Chatovat s %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/da/pages.json b/public/language/da/pages.json index ea3ccbf48c..40c5478269 100644 --- a/public/language/da/pages.json +++ b/public/language/da/pages.json @@ -6,7 +6,7 @@ "popular-month": "Populære tråde denne måned", "popular-alltime": "Top populære tråde", "recent": "Seneste tråde", - "flagged-posts": "Anmeldte Indlæg", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online brugere", "users/latest": "Seneste brugere", @@ -27,6 +27,8 @@ "group": "%1 gruppe", "chats": "Chats", "chat": "Chatter med %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Redigere \"%1\"", "account/edit/password": "Redigerer adgangskode for \"%1\"", "account/edit/username": "Redigerer brugernavn for \"%1\"", diff --git a/public/language/de/pages.json b/public/language/de/pages.json index 5c47502a3c..0af7092482 100644 --- a/public/language/de/pages.json +++ b/public/language/de/pages.json @@ -6,7 +6,7 @@ "popular-month": "Beliebte Themen dieses Monats", "popular-alltime": "Beliebteste Themen", "recent": "Neueste Themen", - "flagged-posts": "Gemeldete Beiträge", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Benutzer online", "users/latest": "Neuste Benutzer", @@ -27,6 +27,8 @@ "group": "%1 Gruppe", "chats": "Chats", "chat": "Chatte mit %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Bearbeite %1", "account/edit/password": "Bearbeite Passwort von \"%1\"", "account/edit/username": "Bearbeite Benutzernamen von \"%1\"", diff --git a/public/language/el/pages.json b/public/language/el/pages.json index 18a7dd1ef8..243f8511da 100644 --- a/public/language/el/pages.json +++ b/public/language/el/pages.json @@ -6,7 +6,7 @@ "popular-month": "Popular topics this month", "popular-alltime": "All time popular topics", "recent": "Πρόσφατα Θέματα", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online Users", "users/latest": "Latest Users", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/en-US/pages.json b/public/language/en-US/pages.json index af720e865c..dcbb38b5b9 100644 --- a/public/language/en-US/pages.json +++ b/public/language/en-US/pages.json @@ -6,7 +6,7 @@ "popular-month": "Popular topics this month", "popular-alltime": "All time popular topics", "recent": "Recent Topics", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online Users", "users/latest": "Latest Users", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/en-x-pirate/pages.json b/public/language/en-x-pirate/pages.json index af720e865c..dcbb38b5b9 100644 --- a/public/language/en-x-pirate/pages.json +++ b/public/language/en-x-pirate/pages.json @@ -6,7 +6,7 @@ "popular-month": "Popular topics this month", "popular-alltime": "All time popular topics", "recent": "Recent Topics", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online Users", "users/latest": "Latest Users", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/es/pages.json b/public/language/es/pages.json index 0f56b570df..59b1e2624d 100644 --- a/public/language/es/pages.json +++ b/public/language/es/pages.json @@ -6,7 +6,7 @@ "popular-month": "Temas populares del mes", "popular-alltime": "Temas populares de siempre", "recent": "Temas recientes", - "flagged-posts": "Posts reportados", + "flagged-content": "Flagged Content", "ip-blacklist": "Lista negra de IPS", "users/online": "Conectados", "users/latest": "Últimos usuarios", @@ -27,6 +27,8 @@ "group": "Grupo de %1", "chats": "Chats", "chat": "Chatear con %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editar \"%1\"", "account/edit/password": "Editar contraseña de \"%1\"", "account/edit/username": "Editar nombre de usuario de \"%1\"", diff --git a/public/language/et/pages.json b/public/language/et/pages.json index 938fc79e13..e3ca3603dc 100644 --- a/public/language/et/pages.json +++ b/public/language/et/pages.json @@ -6,7 +6,7 @@ "popular-month": "Populaarsed teemad sel kuul", "popular-alltime": "Populaarseimad teemad üldse", "recent": "Hiljutised teemad", - "flagged-posts": "Märgistatud postitused", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Sisseloginud kasutajad", "users/latest": "Hiljutised kasutajad", @@ -27,6 +27,8 @@ "group": "Kasutaja %1 grupp", "chats": "Vestlused", "chat": "Vestlus kasutajaga %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Muudan \"%1\"", "account/edit/password": "Redigeerid \"%1\" parooli", "account/edit/username": "Redigeerid \"%1\" kasutajanime", diff --git a/public/language/fa-IR/pages.json b/public/language/fa-IR/pages.json index 2b0c51f60c..9b55e53351 100644 --- a/public/language/fa-IR/pages.json +++ b/public/language/fa-IR/pages.json @@ -6,7 +6,7 @@ "popular-month": "موضوعات پربازدید این ماه", "popular-alltime": "پربازدیدترین موضوعات", "recent": "موضوع‌های تازه", - "flagged-posts": "پست نشانه گذاری شده", + "flagged-content": "Flagged Content", "ip-blacklist": "لیست سیاه آی‌پی", "users/online": "کاربران آنلاین", "users/latest": "آخرین کاربران", @@ -27,6 +27,8 @@ "group": "%1 گروه", "chats": "چتها", "chat": "چت با %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "ویرایش \"%1\"", "account/edit/password": "ویرایش کلمه ی عبورِ \"%1\"", "account/edit/username": "ویرایش نام کاربریِ \"%1\"", diff --git a/public/language/fi/pages.json b/public/language/fi/pages.json index 4ac31974c4..a5e8b87187 100644 --- a/public/language/fi/pages.json +++ b/public/language/fi/pages.json @@ -6,7 +6,7 @@ "popular-month": "Suositut aiheet tässä kuussa", "popular-alltime": "Suositut aiheet koko ajalta", "recent": "Viimeisimmät aiheet", - "flagged-posts": "Liputetut viestit", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Paikalla olevat käyttäjät", "users/latest": "Viimeisimmat käyttäjät", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Keskustelut", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/fr/pages.json b/public/language/fr/pages.json index 898d6c84ce..a28d0193c4 100644 --- a/public/language/fr/pages.json +++ b/public/language/fr/pages.json @@ -6,7 +6,7 @@ "popular-month": "Sujets populaires ce mois-ci", "popular-alltime": "Sujets populaires depuis toujours", "recent": "Sujets récents", - "flagged-posts": "Messages signalés", + "flagged-content": "Flagged Content", "ip-blacklist": "Liste noire d'adresses IP", "users/online": "Utilisateurs en ligne", "users/latest": "Derniers inscrits", @@ -27,6 +27,8 @@ "group": "%1 groupe", "chats": "Discussions", "chat": "Conversation avec %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Édition de \"%1\"", "account/edit/password": "Édition du mot de passe de \"%1\"", "account/edit/username": "Édition du nom d'utilisateur de \"%1\"", diff --git a/public/language/gl/pages.json b/public/language/gl/pages.json index c0c26c54e4..ce26b384ea 100644 --- a/public/language/gl/pages.json +++ b/public/language/gl/pages.json @@ -6,7 +6,7 @@ "popular-month": "Temas populares do mes", "popular-alltime": "Temas populares de tódolos tempos", "recent": "Temas recentes", - "flagged-posts": "Publicacions Marcadas.", + "flagged-content": "Flagged Content", "ip-blacklist": "Lista negra de IPs", "users/online": "Usuarios conectados", "users/latest": "Últimos usuarios", @@ -27,6 +27,8 @@ "group": "%1 grupo", "chats": "Charlas", "chat": "Falando con %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editando \"%1\"", "account/edit/password": "Editando contrasinal \"%1\"", "account/edit/username": "Editando nome de usuario \"%1\"", diff --git a/public/language/he/pages.json b/public/language/he/pages.json index 2ae5abf720..8832d5915a 100644 --- a/public/language/he/pages.json +++ b/public/language/he/pages.json @@ -6,7 +6,7 @@ "popular-month": "נושאים חמים החודש", "popular-alltime": "הנושאים החמים בכל הזמנים", "recent": "נושאים אחרונים", - "flagged-posts": "פוסטים מסומנים", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "משתמשים מחוברים", "users/latest": "משתמשים אחרונים", @@ -27,6 +27,8 @@ "group": "קבוצת %1", "chats": "הודעות פרטיות", "chat": "שלחו הודעה פרטית ל%1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "לערוך את \"%1\"", "account/edit/password": "עורך את הסיסמה של \"%1\"", "account/edit/username": "עורך את שם המשתמש של \"%1\"", diff --git a/public/language/hu/pages.json b/public/language/hu/pages.json index 8a5faaf35d..e3c175a2b5 100644 --- a/public/language/hu/pages.json +++ b/public/language/hu/pages.json @@ -6,7 +6,7 @@ "popular-month": "Havi népszerű témakörök", "popular-alltime": "Mindenkori legnépszerűbb témakörök", "recent": "Legfrissebb témakörök", - "flagged-posts": "Megjelölt Üzenetek", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Aktiv Felhasználok", "users/latest": "Latest Users", @@ -27,6 +27,8 @@ "group": "%1 csoport", "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/id/pages.json b/public/language/id/pages.json index b8aa021b71..e3b340e0de 100644 --- a/public/language/id/pages.json +++ b/public/language/id/pages.json @@ -6,7 +6,7 @@ "popular-month": "Popular topics this month", "popular-alltime": "All time popular topics", "recent": "Topik Terkini", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online Users", "users/latest": "Latest Users", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/it/pages.json b/public/language/it/pages.json index 465cdd5b05..818fca88e0 100644 --- a/public/language/it/pages.json +++ b/public/language/it/pages.json @@ -6,7 +6,7 @@ "popular-month": "Discussioni popolari questo mese", "popular-alltime": "Discussioni più popolari di sempre", "recent": "Discussioni Recenti", - "flagged-posts": "Post Segnalati", + "flagged-content": "Flagged Content", "ip-blacklist": "Lista nera degli IP", "users/online": "Utenti Online", "users/latest": "Ultimi Utenti", @@ -27,6 +27,8 @@ "group": "Gruppo %1", "chats": "Chat", "chat": "In chat con %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Modificando \"%1\"", "account/edit/password": "Modificando la password di \"%1\"", "account/edit/username": "Modificando il nome utente di \"%1\"", diff --git a/public/language/ja/pages.json b/public/language/ja/pages.json index 79ad63add2..39b7f3619e 100644 --- a/public/language/ja/pages.json +++ b/public/language/ja/pages.json @@ -6,7 +6,7 @@ "popular-month": "今月人気のトピック", "popular-alltime": "人気のトピック", "recent": "最新スレッド", - "flagged-posts": "投稿にフラグを立てました", + "flagged-content": "Flagged Content", "ip-blacklist": "IPブラックリスト", "users/online": "オンラインのユーザー", "users/latest": "最近のユーザー", @@ -27,6 +27,8 @@ "group": "%1 グループ", "chats": "チャット", "chat": "%1とチャットします", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "編集中 \"%1\"", "account/edit/password": "\"%1\"のパスワードを編集中", "account/edit/username": "\"%1\"のユーザー名を編集中", diff --git a/public/language/ko/pages.json b/public/language/ko/pages.json index 553595268e..2d258932ac 100644 --- a/public/language/ko/pages.json +++ b/public/language/ko/pages.json @@ -6,7 +6,7 @@ "popular-month": "인기있는 주제 (월간)", "popular-alltime": "인기있는 주제", "recent": "최근 주제", - "flagged-posts": "플래그된 게시물", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "온라인 사용자", "users/latest": "최근 사용자", @@ -27,6 +27,8 @@ "group": "%1 그룹", "chats": "대화", "chat": "%1 님과 대화", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "\"%1\" 편집", "account/edit/password": "\"%1\" 의 패스워드 변경", "account/edit/username": "\"%1\" 의 사용자명 변경", diff --git a/public/language/lt/pages.json b/public/language/lt/pages.json index 26a2b0167a..62fe318c71 100644 --- a/public/language/lt/pages.json +++ b/public/language/lt/pages.json @@ -6,7 +6,7 @@ "popular-month": "Popular topics this month", "popular-alltime": "All time popular topics", "recent": "Paskutinės temos", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online Users", "users/latest": "Latest Users", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/ms/pages.json b/public/language/ms/pages.json index d10ea46388..bfade44f86 100644 --- a/public/language/ms/pages.json +++ b/public/language/ms/pages.json @@ -6,7 +6,7 @@ "popular-month": "Topik Popular Bulan Ini", "popular-alltime": "Topik Popular Sepanjang Masa", "recent": "Topik Baru", - "flagged-posts": "Kiriman Dipalang", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Pengguna Atas Talian", "users/latest": "Pengguna Terkini", @@ -27,6 +27,8 @@ "group": "%1 Kumpulan", "chats": "Borak", "chat": "Borak Dengan %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Menyunting \"%1\"", "account/edit/password": "Mengemaskini kata laluan \"%1\"", "account/edit/username": "Mengemaskini nama pengguna \"%1\"", diff --git a/public/language/nb/pages.json b/public/language/nb/pages.json index c15ff8a9a3..39f5bd7800 100644 --- a/public/language/nb/pages.json +++ b/public/language/nb/pages.json @@ -6,7 +6,7 @@ "popular-month": "Populære emner denne måneden", "popular-alltime": "Mest populære emner for all tid", "recent": "Nylige emner", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Påloggede Brukere", "users/latest": "Nyeste Brukere", @@ -27,6 +27,8 @@ "group": "%1 gruppe", "chats": "Samtaler", "chat": "Samtale med %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Endrer \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/nl/pages.json b/public/language/nl/pages.json index 700b5de892..816f62be22 100644 --- a/public/language/nl/pages.json +++ b/public/language/nl/pages.json @@ -6,7 +6,7 @@ "popular-month": "De populaire onderwerpen van deze maand", "popular-alltime": "De populaire onderwerpen", "recent": "Recente onderwerpen", - "flagged-posts": "Ongepaste berichten", + "flagged-content": "Flagged Content", "ip-blacklist": "IP zwarte lijst", "users/online": "Online Gebruikers", "users/latest": "Meest recente gebruikers", @@ -27,6 +27,8 @@ "group": "%1's groep", "chats": "Chats", "chat": "Chatten met %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "\"%1\" aanpassen", "account/edit/password": "Wachtwoord van \"%1\" aanpassen", "account/edit/username": "Gebruikersnaam van \"%1\" aanpassen", diff --git a/public/language/pl/pages.json b/public/language/pl/pages.json index dfd76118bf..167e5696f5 100644 --- a/public/language/pl/pages.json +++ b/public/language/pl/pages.json @@ -6,7 +6,7 @@ "popular-month": "Tematy popularne w tym miesiącu", "popular-alltime": "Wszystkie popularne tematy", "recent": "Ostatnie Tematy", - "flagged-posts": "Oflagowane posty", + "flagged-content": "Flagged Content", "ip-blacklist": "Czarna lista adresów IP", "users/online": "Dostępni Użytkownicy", "users/latest": "Nowi Użytkownicy", @@ -27,6 +27,8 @@ "group": "Grupa %1", "chats": "Rozmowy", "chat": "Rozmowa z %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Edytowanie \"%1\"", "account/edit/password": "Edytowanie hasła \"%1\"", "account/edit/username": "Edytowanie nazwy \"%1\"", diff --git a/public/language/pt-BR/pages.json b/public/language/pt-BR/pages.json index 1d8c4f87bb..7a27b39a3c 100644 --- a/public/language/pt-BR/pages.json +++ b/public/language/pt-BR/pages.json @@ -6,7 +6,7 @@ "popular-month": "Tópicos populares deste mês", "popular-alltime": "Tópicos populares de todos os tempos", "recent": "Tópicos Recentes", - "flagged-posts": "Posts Sinalizados", + "flagged-content": "Flagged Content", "ip-blacklist": "Lista negra de IPs", "users/online": "Usuários Online", "users/latest": "Últimos Usuários", @@ -27,6 +27,8 @@ "group": "%1 grupo", "chats": "Chats", "chat": "Conversando com %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editando \"%1\"", "account/edit/password": "Editando senha de \"%1\"", "account/edit/username": "Editando nome de usuário de \"%1\"", diff --git a/public/language/pt-PT/pages.json b/public/language/pt-PT/pages.json index b0c9ea6b93..d22a86e4d1 100644 --- a/public/language/pt-PT/pages.json +++ b/public/language/pt-PT/pages.json @@ -6,7 +6,7 @@ "popular-month": "Tópicos populares este mês", "popular-alltime": "Tópicos populares desde sempre", "recent": "Tópicos recentes", - "flagged-posts": "Publicações sinalizadas", + "flagged-content": "Flagged Content", "ip-blacklist": "Lista negra de IPs", "users/online": "Utilizadores online", "users/latest": "Últimos utilizadores", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Conversas", "chat": "Conversando com %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editando \"%1\"", "account/edit/password": "Editando palavra-passe de \"%1\"", "account/edit/username": "Editando o nome de utilizador de \"%1\"", diff --git a/public/language/ro/pages.json b/public/language/ro/pages.json index 36eafbd6ef..4816853bef 100644 --- a/public/language/ro/pages.json +++ b/public/language/ro/pages.json @@ -6,7 +6,7 @@ "popular-month": "Subiecte populare în luna asta", "popular-alltime": "All time popular topics", "recent": "Subiecte Noi", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Utilizatori online", "users/latest": "Ultimii membrii", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/ru/pages.json b/public/language/ru/pages.json index ec4fccb5f1..86cfc9da3e 100644 --- a/public/language/ru/pages.json +++ b/public/language/ru/pages.json @@ -6,7 +6,7 @@ "popular-month": "Популярные темы этого месяца", "popular-alltime": "Популярные темы за всё время", "recent": "Последние темы", - "flagged-posts": "Отмеченные сообщения", + "flagged-content": "Flagged Content", "ip-blacklist": "Чёрный список IP", "users/online": "В сети", "users/latest": "Новые участники", @@ -27,6 +27,8 @@ "group": "Группа %1", "chats": "Чаты", "chat": "Чат с участником %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Редактирование \"%1\"", "account/edit/password": "Сменить пароль \"%1\"", "account/edit/username": "Изменить имя пользователя \"%1\"", diff --git a/public/language/rw/pages.json b/public/language/rw/pages.json index 1905438799..6b1fcdccca 100644 --- a/public/language/rw/pages.json +++ b/public/language/rw/pages.json @@ -6,7 +6,7 @@ "popular-month": "Ibiganiro bikunzwe uku kwezi", "popular-alltime": "Ibiganiro byakunzwe ibihe byose", "recent": "Ibiganiro Biheruka", - "flagged-posts": "Ibyatambikanywe", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Abariho", "users/latest": "Abashya", @@ -27,6 +27,8 @@ "group": "Itsinda %1 ", "chats": "Mu Gikari", "chat": "Ukuganira na %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Uguhindura \"%1\"", "account/edit/password": "Uguhindura ijambobanga rya \"%1\"", "account/edit/username": "Uguhindura izina rya \"%1\"", diff --git a/public/language/sc/pages.json b/public/language/sc/pages.json index 2602c1834f..25d7ccb5ce 100644 --- a/public/language/sc/pages.json +++ b/public/language/sc/pages.json @@ -6,7 +6,7 @@ "popular-month": "Popular topics this month", "popular-alltime": "All time popular topics", "recent": "Ùrtimas Arresonadas", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online Users", "users/latest": "Latest Users", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/sk/pages.json b/public/language/sk/pages.json index 095ee00be2..7e6d0bc63b 100644 --- a/public/language/sk/pages.json +++ b/public/language/sk/pages.json @@ -6,7 +6,7 @@ "popular-month": "Populárne témy za tento mesiac", "popular-alltime": "Populárne témy za celé obdobie", "recent": "Nedávne témy", - "flagged-posts": "Označené príspevky", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online užívatelia", "users/latest": "Najnovší užívatelia", @@ -27,6 +27,8 @@ "group": "%1 skupina", "chats": "Konverzácie", "chat": "Rozprávate sa s %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Úprava \"%1\"", "account/edit/password": "Úprava hesla \"%1\"", "account/edit/username": "Úprava užívateľského mena \"%1\"", diff --git a/public/language/sl/pages.json b/public/language/sl/pages.json index 9970c374cd..88cd0f8afc 100644 --- a/public/language/sl/pages.json +++ b/public/language/sl/pages.json @@ -6,7 +6,7 @@ "popular-month": "Priljubljene teme v tem mesecu", "popular-alltime": "Vse priljubljene teme", "recent": "Zadnje teme", - "flagged-posts": "Označene teme", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Dosegljivi uporabniki", "users/latest": "Zadnji uporabniki", @@ -27,6 +27,8 @@ "group": "Skupina %1", "chats": "Klepeti", "chat": "Klepet z osebo %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Urejanje \"%1\"", "account/edit/password": "Urejanje gesla za \"%1\"", "account/edit/username": "Urejanje uporabniškega imena za \"%1\"", diff --git a/public/language/sr/pages.json b/public/language/sr/pages.json index 24fafe64ba..5e81f13a6e 100644 --- a/public/language/sr/pages.json +++ b/public/language/sr/pages.json @@ -6,7 +6,7 @@ "popular-month": "Популарне теме овог месеца", "popular-alltime": "Популарне теме свих времена", "recent": "Недавне теме", - "flagged-posts": "Означене поруке", + "flagged-content": "Flagged Content", "ip-blacklist": "Црна листа IP адреса", "users/online": "Корисници на мрежи", "users/latest": "Најновији корисници", @@ -27,6 +27,8 @@ "group": "%1 група", "chats": "Ћаскања", "chat": "Ћаскање са %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Уређивање \"%1\"", "account/edit/password": "Уређивање лозинке од \"%1\"", "account/edit/username": "Уређивање корисничког имена од \"%1\"", diff --git a/public/language/sv/pages.json b/public/language/sv/pages.json index 61f6c23a62..cdc9019082 100644 --- a/public/language/sv/pages.json +++ b/public/language/sv/pages.json @@ -6,7 +6,7 @@ "popular-month": "Populära ämnen denna månad", "popular-alltime": "Populäraste ämnena genom tiderna", "recent": "Senaste ämnena", - "flagged-posts": "Flaggade inlägg", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Svartlista", "users/online": "Användare online", "users/latest": "Senaste Användare", @@ -27,6 +27,8 @@ "group": "%1 grupp", "chats": "Chattar", "chat": "Chattar med %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Redigerar \"%1\"", "account/edit/password": "Redigerar lösenord för \"%1\"", "account/edit/username": "Redigerar användarnamn för \"%1\"", diff --git a/public/language/th/pages.json b/public/language/th/pages.json index e2d1215bcb..7a92d461eb 100644 --- a/public/language/th/pages.json +++ b/public/language/th/pages.json @@ -6,7 +6,7 @@ "popular-month": "Popular topics this month", "popular-alltime": "All time popular topics", "recent": "กระทู้ล่าสุด", - "flagged-posts": "Flagged Posts", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Online Users", "users/latest": "Latest Users", @@ -27,6 +27,8 @@ "group": "%1 group", "chats": "Chats", "chat": "Chatting with %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Editing \"%1\"", "account/edit/password": "Editing password of \"%1\"", "account/edit/username": "Editing username of \"%1\"", diff --git a/public/language/tr/pages.json b/public/language/tr/pages.json index 73900a5eb1..7eec286875 100644 --- a/public/language/tr/pages.json +++ b/public/language/tr/pages.json @@ -6,7 +6,7 @@ "popular-month": "Bu ayki popüler başlıklar", "popular-alltime": "En popüler başlıklar", "recent": "Güncel Konular", - "flagged-posts": "Bayraklanmış İletiler", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Karaliste", "users/online": "Çevrimiçi Kullanıcılar", "users/latest": "En Yeni Kullanıcılar", @@ -27,6 +27,8 @@ "group": "%1 grubu", "chats": "Sohbetler", "chat": "%1 ile sohbet", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "\"%1\" düzenleniyor", "account/edit/password": "\"%1\" parolayı düzenliyor", "account/edit/username": "\"%1\" kullanıcı adını düzenliyor", diff --git a/public/language/vi/pages.json b/public/language/vi/pages.json index 4ac7cf00a9..ba094bf22e 100644 --- a/public/language/vi/pages.json +++ b/public/language/vi/pages.json @@ -6,7 +6,7 @@ "popular-month": "Chủ đề nổi bật tháng này", "popular-alltime": "Chủ đề nổi bật mọi thời đại", "recent": "Chủ đề gần đây", - "flagged-posts": "Bài viết bị gắn cờ", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "Thành viên đang online", "users/latest": "Thành viên mới nhất", @@ -27,6 +27,8 @@ "group": "Nhóm %1", "chats": "Chat", "chat": "Chat với %1", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "Chỉnh sửa \"%1\"", "account/edit/password": "Chỉnh sửa mật khẩu của \"%1\"", "account/edit/username": "Chỉnh sửa tên đăng nhập của \"%1\"", diff --git a/public/language/zh-CN/pages.json b/public/language/zh-CN/pages.json index af1f0bedfa..428ded20bd 100644 --- a/public/language/zh-CN/pages.json +++ b/public/language/zh-CN/pages.json @@ -6,7 +6,7 @@ "popular-month": "当月热门话题", "popular-alltime": "热门主题", "recent": "最新主题", - "flagged-posts": "已举报的帖子", + "flagged-content": "Flagged Content", "ip-blacklist": "IP 黑名单", "users/online": "在线会员", "users/latest": "最新会员", @@ -27,6 +27,8 @@ "group": "%1 的用户组", "chats": "聊天", "chat": "与 %1 聊天", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "正在编辑 \"%1\"", "account/edit/password": "正在编辑 \"%1\" 的密码", "account/edit/username": "正在编辑 \"%1\" 的用户名", diff --git a/public/language/zh-TW/pages.json b/public/language/zh-TW/pages.json index 0f3a3a5e1e..708850a33d 100644 --- a/public/language/zh-TW/pages.json +++ b/public/language/zh-TW/pages.json @@ -6,7 +6,7 @@ "popular-month": "本月受歡迎的主題", "popular-alltime": "所有時間受歡迎的主題", "recent": "近期的主題", - "flagged-posts": "標記的張貼", + "flagged-content": "Flagged Content", "ip-blacklist": "IP Blacklist", "users/online": "線上使用者", "users/latest": "最近使用者", @@ -27,6 +27,8 @@ "group": "%1 群組", "chats": "聊天", "chat": "與 %1 聊天", + "flags": "Flags", + "flag-details": "Flag %1 Details", "account/edit": "編輯 \"%1\"", "account/edit/password": "編輯 \"%1\" 的密碼", "account/edit/username": "編輯\"%1\"的帳號", From 5bb0c3ae073562380abb67263111fa405cbb83a4 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 3 Feb 2017 10:24:19 -0500 Subject: [PATCH 110/122] increased file watch interval to reduce high CPU usage when using grunt --- Gruntfile.js | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index ca5d4dad49..85ea76938f 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -71,10 +71,16 @@ module.exports = function (grunt) { 'node_modules/nodebb-*/*.less', 'node_modules/nodebb-*/**/*.less', '!node_modules/nodebb-*/node_modules/**', '!node_modules/nodebb-*/.git/**' - ] + ], + options: { + interval: 1000 + } }, lessUpdated_Admin: { - files: ['public/**/*.less'] + files: ['public/**/*.less'], + options: { + interval: 1000 + } }, clientUpdated: { files: [ @@ -83,10 +89,16 @@ module.exports = function (grunt) { '!node_modules/nodebb-*/node_modules/**', 'node_modules/templates.js/lib/templates.js', '!node_modules/nodebb-*/.git/**' - ] + ], + options: { + interval: 1000 + } }, serverUpdated: { - files: ['*.js', 'install/*.js', 'src/**/*.js'] + files: ['*.js', 'install/*.js', 'src/**/*.js'], + options: { + interval: 1000 + } }, templatesUpdated: { files: [ @@ -94,7 +106,10 @@ module.exports = function (grunt) { 'node_modules/nodebb-*/*.tpl', 'node_modules/nodebb-*/**/*.tpl', '!node_modules/nodebb-*/node_modules/**', '!node_modules/nodebb-*/.git/**' - ] + ], + options: { + interval: 1000 + } }, langUpdated: { files: [ @@ -107,6 +122,9 @@ module.exports = function (grunt) { '!node_modules/nodebb-*/package.json', '!node_modules/nodebb-*/theme.json', ], + options: { + interval: 1000 + } }, } }); From 44a59ac435e18e62666821fbde21a69e72eaee68 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 3 Feb 2017 16:37:03 -0700 Subject: [PATCH 111/122] Fix tests to use default activated plugin --- test/plugins.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/plugins.js b/test/plugins.js index 09537d8990..06aabaab8d 100644 --- a/test/plugins.js +++ b/test/plugins.js @@ -152,7 +152,7 @@ describe('Plugins', function () { }); describe('static assets', function () { - it('should 404 if resource does not exist', function (done) { + it('should 404 if plugin does not exist', function (done) { request.get(nconf.get('url') + '/plugins/doesnotexist/should404.tpl', function (err, res, body) { assert.ifError(err); assert.equal(res.statusCode, 404); @@ -162,7 +162,7 @@ describe('Plugins', function () { }); it('should 404 if resource does not exist', function (done) { - request.get(nconf.get('url') + '/plugins/nodebb-plugin-dbsearch/dbsearch/templates/admin/plugins/should404.tpl', function (err, res, body) { + request.get(nconf.get('url') + '/plugins/nodebb-plugin-markdown/js/should404.js', function (err, res, body) { assert.ifError(err); assert.equal(res.statusCode, 404); assert(body); @@ -171,7 +171,7 @@ describe('Plugins', function () { }); it('should get resource', function (done) { - request.get(nconf.get('url') + '/plugins/nodebb-plugin-dbsearch/dbsearch/templates/admin/plugins/dbsearch.tpl', function (err, res, body) { + request.get(nconf.get('url') + '/plugins/nodebb-plugin-markdown/js/admin.js', function (err, res, body) { assert.ifError(err); assert.equal(res.statusCode, 200); assert(body); From d31499a860b6e567b41c030132853eb1cb1a01b3 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 3 Feb 2017 18:29:09 -0700 Subject: [PATCH 112/122] Fix tests rewriting `logo.png` --- src/image.js | 3 +++ src/user/picture.js | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/image.js b/src/image.js index 1cfbdccbe3..0ab68e5a23 100644 --- a/src/image.js +++ b/src/image.js @@ -65,6 +65,9 @@ image.resizeImage = function (data, callback) { } }, function (image, next) { + if (data.write === false) { + return next(); + } image.write(data.target || data.path, next); } ], function (err) { diff --git a/src/user/picture.js b/src/user/picture.js index 0fd1d1a3bd..273a5dd413 100644 --- a/src/user/picture.js +++ b/src/user/picture.js @@ -57,7 +57,8 @@ module.exports = function (User) { path: picture.path, extension: extension, width: imageDimension, - height: imageDimension + height: imageDimension, + write: false, }, next); }, function (next) { From fdad66f58e721b4a02b89f5d06d1b6c2889f27ef Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 3 Feb 2017 23:48:43 -0700 Subject: [PATCH 113/122] Revert "Fix tests to use default activated plugin" This reverts commit 44a59ac435e18e62666821fbde21a69e72eaee68. --- test/plugins.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/plugins.js b/test/plugins.js index 06aabaab8d..09537d8990 100644 --- a/test/plugins.js +++ b/test/plugins.js @@ -152,7 +152,7 @@ describe('Plugins', function () { }); describe('static assets', function () { - it('should 404 if plugin does not exist', function (done) { + it('should 404 if resource does not exist', function (done) { request.get(nconf.get('url') + '/plugins/doesnotexist/should404.tpl', function (err, res, body) { assert.ifError(err); assert.equal(res.statusCode, 404); @@ -162,7 +162,7 @@ describe('Plugins', function () { }); it('should 404 if resource does not exist', function (done) { - request.get(nconf.get('url') + '/plugins/nodebb-plugin-markdown/js/should404.js', function (err, res, body) { + request.get(nconf.get('url') + '/plugins/nodebb-plugin-dbsearch/dbsearch/templates/admin/plugins/should404.tpl', function (err, res, body) { assert.ifError(err); assert.equal(res.statusCode, 404); assert(body); @@ -171,7 +171,7 @@ describe('Plugins', function () { }); it('should get resource', function (done) { - request.get(nconf.get('url') + '/plugins/nodebb-plugin-markdown/js/admin.js', function (err, res, body) { + request.get(nconf.get('url') + '/plugins/nodebb-plugin-dbsearch/dbsearch/templates/admin/plugins/dbsearch.tpl', function (err, res, body) { assert.ifError(err); assert.equal(res.statusCode, 200); assert(body); From d43564dbbd31a8d7cd04cdcef0db80901035397b Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 3 Feb 2017 23:55:33 -0700 Subject: [PATCH 114/122] No need to build multiple times --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1395ce329d..c43218397f 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "scripts": { "start": "node loader.js", "lint": "eslint --cache .", - "pretest": "npm run lint && node app --build", + "pretest": "npm run lint", "test": "istanbul cover node_modules/mocha/bin/_mocha -- -R dot", "coveralls": "istanbul cover _mocha --report lcovonly -- -R dot && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage" }, From b530701cffd74c70f37225c598cd226f2a13b525 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Mon, 6 Feb 2017 15:54:21 -0700 Subject: [PATCH 115/122] Fix tabs :rage: --- src/meta/css.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meta/css.js b/src/meta/css.js index 6c4a0f62e3..3627c6c41a 100644 --- a/src/meta/css.js +++ b/src/meta/css.js @@ -26,7 +26,7 @@ module.exports = function (Meta) { '@import (inline) "../public/vendor/jquery/css/smoothness/jquery-ui.css";', '@import (inline) "../public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";', '@import (inline) "../public/vendor/colorpicker/colorpicker.css";', - '@import (inline) "../node_modules/cropperjs/dist/cropper.css";', + '@import (inline) "../node_modules/cropperjs/dist/cropper.css";', '@import "../../public/less/flags.less";', '@import "../../public/less/blacklist.less";', '@import "../../public/less/generics.less";', From a122aad54d7418226f59e353b97a191a45afadeb Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 7 Feb 2017 20:53:34 +0000 Subject: [PATCH 116/122] updating fallbacks --- public/language/ar/admin/general/dashboard.json | 10 +++++++++- public/language/bg/admin/general/dashboard.json | 10 +++++++++- public/language/bn/admin/general/dashboard.json | 10 +++++++++- public/language/cs/admin/general/dashboard.json | 10 +++++++++- public/language/da/admin/general/dashboard.json | 10 +++++++++- public/language/de/admin/general/dashboard.json | 12 ++++++++++-- public/language/el/admin/general/dashboard.json | 10 +++++++++- public/language/en-US/admin/general/dashboard.json | 10 +++++++++- .../en-x-pirate/admin/general/dashboard.json | 10 +++++++++- public/language/es/admin/general/dashboard.json | 10 +++++++++- public/language/et/admin/general/dashboard.json | 10 +++++++++- public/language/fa-IR/admin/general/dashboard.json | 10 +++++++++- public/language/fi/admin/general/dashboard.json | 10 +++++++++- public/language/fr/admin/general/dashboard.json | 10 +++++++++- public/language/gl/admin/general/dashboard.json | 10 +++++++++- public/language/he/admin/general/dashboard.json | 10 +++++++++- public/language/hu/admin/general/dashboard.json | 10 +++++++++- public/language/id/admin/general/dashboard.json | 10 +++++++++- public/language/it/admin/general/dashboard.json | 10 +++++++++- public/language/ja/admin/general/dashboard.json | 10 +++++++++- public/language/ko/admin/general/dashboard.json | 10 +++++++++- public/language/lt/admin/general/dashboard.json | 10 +++++++++- public/language/ms/admin/general/dashboard.json | 10 +++++++++- public/language/nb/admin/general/dashboard.json | 10 +++++++++- public/language/nl/admin/general/dashboard.json | 10 +++++++++- public/language/pl/admin/general/dashboard.json | 10 +++++++++- public/language/pt-BR/admin/general/dashboard.json | 10 +++++++++- public/language/pt-PT/admin/general/dashboard.json | 10 +++++++++- public/language/ro/admin/general/dashboard.json | 10 +++++++++- public/language/ru/admin/general/dashboard.json | 10 +++++++++- public/language/rw/admin/general/dashboard.json | 10 +++++++++- public/language/sc/admin/general/dashboard.json | 10 +++++++++- public/language/sk/admin/general/dashboard.json | 10 +++++++++- public/language/sl/admin/general/dashboard.json | 10 +++++++++- public/language/sr/admin/general/dashboard.json | 10 +++++++++- public/language/sv/admin/general/dashboard.json | 10 +++++++++- public/language/th/admin/general/dashboard.json | 10 +++++++++- public/language/tr/admin/general/dashboard.json | 10 +++++++++- public/language/vi/admin/general/dashboard.json | 10 +++++++++- public/language/zh-CN/admin/general/dashboard.json | 10 +++++++++- public/language/zh-TW/admin/general/dashboard.json | 10 +++++++++- 41 files changed, 370 insertions(+), 42 deletions(-) diff --git a/public/language/ar/admin/general/dashboard.json b/public/language/ar/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/ar/admin/general/dashboard.json +++ b/public/language/ar/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/bg/admin/general/dashboard.json b/public/language/bg/admin/general/dashboard.json index 357fbcba2d..b54fa53d30 100644 --- a/public/language/bg/admin/general/dashboard.json +++ b/public/language/bg/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Трафик на форума", "page-views": "Преглеждания на страниците", "unique-visitors": "Уникални посетители", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Преглеждания на страниците през последния месец", "page-views-this-month": "Преглеждания на страниците този месец", "page-views-last-day": "Преглеждания на страниците през последните 24 часа", @@ -20,6 +23,11 @@ "prerelease-warning": "

    Това е версия за предварителен преглед на NodeBB. Възможно е да има неочаквани неизправности.

    ", "notices": "Забележки", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "Системен контрол", "reload": "Презареждане", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Уникални посетители", "graphs.registered-users": "Регистрирани потребители", "graphs.anonymous-users": "Анонимни потребители" -} \ No newline at end of file +} diff --git a/public/language/bn/admin/general/dashboard.json b/public/language/bn/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/bn/admin/general/dashboard.json +++ b/public/language/bn/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/cs/admin/general/dashboard.json b/public/language/cs/admin/general/dashboard.json index 4a41012de9..7b53dd6562 100644 --- a/public/language/cs/admin/general/dashboard.json +++ b/public/language/cs/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/da/admin/general/dashboard.json b/public/language/da/admin/general/dashboard.json index 1ceda1053c..23153a3f1b 100644 --- a/public/language/da/admin/general/dashboard.json +++ b/public/language/da/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffik", "page-views": "Side Visninger", "unique-visitors": "Unikke Besøgere", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Side Visninger Sidste Måned", "page-views-this-month": "Side Visninger Denne Måned", "page-views-last-day": "Side visninger i de sidste 24 timer", @@ -20,6 +23,11 @@ "prerelease-warning": "

    Dette er en pre-release udgave af NodeBB. Uforventede bugs kan forekomme.

    ", "notices": "Varsler", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Kontrol", "reload": "Genindlæs", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/de/admin/general/dashboard.json b/public/language/de/admin/general/dashboard.json index 6c87767148..b6eda417ab 100644 --- a/public/language/de/admin/general/dashboard.json +++ b/public/language/de/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Seitenaufrufe", "unique-visitors": "Besucher", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Aufrufe im letzten Monat", "page-views-this-month": "Aufrufe in diesem Monat", "page-views-last-day": "Aufrufe in den letzten 24 Stunden", @@ -12,7 +15,7 @@ "stats.all": "Alle", "updates": "Updates", - "running-version": "Es läuft NodeBB v%1.", + "running-version": "Es läuft NodeBB v%1.", "keep-updated": "Stelle immer sicher, dass dein NodeBB auf dem neuesten Stand ist für die neuesten Sicherheits-Patches und Bug-fixes.", "up-to-date": "

    System ist aktuell

    ", "upgrade-available": "

    Version (v%1) wurde veröffentlicht. Beachte um ein NodeBB Upgrade durchzuführen.

    ", @@ -20,6 +23,11 @@ "prerelease-warning": "

    Das ist eine pre-release Version von NodeBB. Es können ungewollte Fehler auftreten.

    ", "notices": "Hinweise", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "Systemsteuerung", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "verschiedene Besucher", "graphs.registered-users": "registrierte Benutzer", "graphs.anonymous-users": "anonyme Benutzer" -} \ No newline at end of file +} diff --git a/public/language/el/admin/general/dashboard.json b/public/language/el/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/el/admin/general/dashboard.json +++ b/public/language/el/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/en-US/admin/general/dashboard.json b/public/language/en-US/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/en-US/admin/general/dashboard.json +++ b/public/language/en-US/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/en-x-pirate/admin/general/dashboard.json b/public/language/en-x-pirate/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/en-x-pirate/admin/general/dashboard.json +++ b/public/language/en-x-pirate/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/es/admin/general/dashboard.json b/public/language/es/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/es/admin/general/dashboard.json +++ b/public/language/es/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/et/admin/general/dashboard.json b/public/language/et/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/et/admin/general/dashboard.json +++ b/public/language/et/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/fa-IR/admin/general/dashboard.json b/public/language/fa-IR/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/fa-IR/admin/general/dashboard.json +++ b/public/language/fa-IR/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/fi/admin/general/dashboard.json b/public/language/fi/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/fi/admin/general/dashboard.json +++ b/public/language/fi/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/fr/admin/general/dashboard.json b/public/language/fr/admin/general/dashboard.json index 3123167d2a..02ea6849a7 100644 --- a/public/language/fr/admin/general/dashboard.json +++ b/public/language/fr/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Trafic du forum", "page-views": "Pages vues", "unique-visitors": "Visiteurs uniques", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Pages vues le mois dernier", "page-views-this-month": "Pages vues ce mois-ci", "page-views-last-day": "Pages vues ces dernières 24 heures", @@ -20,6 +23,11 @@ "prerelease-warning": "

    Ceci est une version préliminaire de NodeBB. Des bugs inattendus peuvent se produire.

    ", "notices": "Informations", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "Contrôle du système", "reload": "Recharger", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Visiteurs uniques", "graphs.registered-users": "Utilisateurs enregistrés", "graphs.anonymous-users": "Utilisateurs anonymes" -} \ No newline at end of file +} diff --git a/public/language/gl/admin/general/dashboard.json b/public/language/gl/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/gl/admin/general/dashboard.json +++ b/public/language/gl/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/he/admin/general/dashboard.json b/public/language/he/admin/general/dashboard.json index 5be33f9db1..74abb83ea1 100644 --- a/public/language/he/admin/general/dashboard.json +++ b/public/language/he/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "רענן", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/hu/admin/general/dashboard.json b/public/language/hu/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/hu/admin/general/dashboard.json +++ b/public/language/hu/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/id/admin/general/dashboard.json b/public/language/id/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/id/admin/general/dashboard.json +++ b/public/language/id/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/it/admin/general/dashboard.json b/public/language/it/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/it/admin/general/dashboard.json +++ b/public/language/it/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/ja/admin/general/dashboard.json b/public/language/ja/admin/general/dashboard.json index c650f6043c..813f3d272a 100644 --- a/public/language/ja/admin/general/dashboard.json +++ b/public/language/ja/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "フォーラムのトラフィック", "page-views": "ページビュー", "unique-visitors": "ユニークな訪問者", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "先月のページビュー数", "page-views-this-month": "今月のページビュー数", "page-views-last-day": "過去24時間のページビュー", @@ -20,6 +23,11 @@ "prerelease-warning": "

    これはNodeBBのプレリリース版です。意図しないバグが発生することがあります。

    ", "notices": "通知", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "システムコントロール", "reload": "再読み込み", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "ユニークな訪問者", "graphs.registered-users": "登録したユーザー", "graphs.anonymous-users": "匿名ユーザー" -} \ No newline at end of file +} diff --git a/public/language/ko/admin/general/dashboard.json b/public/language/ko/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/ko/admin/general/dashboard.json +++ b/public/language/ko/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/lt/admin/general/dashboard.json b/public/language/lt/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/lt/admin/general/dashboard.json +++ b/public/language/lt/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/ms/admin/general/dashboard.json b/public/language/ms/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/ms/admin/general/dashboard.json +++ b/public/language/ms/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/nb/admin/general/dashboard.json b/public/language/nb/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/nb/admin/general/dashboard.json +++ b/public/language/nb/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/nl/admin/general/dashboard.json b/public/language/nl/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/nl/admin/general/dashboard.json +++ b/public/language/nl/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/pl/admin/general/dashboard.json b/public/language/pl/admin/general/dashboard.json index 00dea84351..d20af29013 100644 --- a/public/language/pl/admin/general/dashboard.json +++ b/public/language/pl/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Ruch na forum", "page-views": "Wyświetlenia strony", "unique-visitors": "Unikalni goście", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Wyświetlenia strony w ostatnim miesiącu", "page-views-this-month": "Wyświetlenia strony w tym miesiącu", "page-views-last-day": "Wyświetlenia strony z ostatnich 24 godzin", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Powiadomienia", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "Zarządzanie systemem", "reload": "Odśwież", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unikalni Użytkownicy", "graphs.registered-users": "Zarejestrowani Użytkownicy", "graphs.anonymous-users": "Anonimowi Użytkownicy" -} \ No newline at end of file +} diff --git a/public/language/pt-BR/admin/general/dashboard.json b/public/language/pt-BR/admin/general/dashboard.json index 0642d2b51e..d818f5f754 100644 --- a/public/language/pt-BR/admin/general/dashboard.json +++ b/public/language/pt-BR/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Tráfego do Forum", "page-views": "Visualizações de Página", "unique-visitors": "Visitantes Únicos", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Visualizações de página no Último Mês", "page-views-this-month": "Visualizações de Página Este Mês", "page-views-last-day": "Visualizações de página nas últimas 24 horas", @@ -20,6 +23,11 @@ "prerelease-warning": "

    Esta é uma versão pre-release do NodeBB. Bugs inesperados podem ocorrer.

    ", "notices": "Avisos", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "Controle do Sistema", "reload": "Recarregar", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Visitantes Únicos", "graphs.registered-users": "Usuários Registrados", "graphs.anonymous-users": "Usuários Anônimos" -} \ No newline at end of file +} diff --git a/public/language/pt-PT/admin/general/dashboard.json b/public/language/pt-PT/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/pt-PT/admin/general/dashboard.json +++ b/public/language/pt-PT/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/ro/admin/general/dashboard.json b/public/language/ro/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/ro/admin/general/dashboard.json +++ b/public/language/ro/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/ru/admin/general/dashboard.json b/public/language/ru/admin/general/dashboard.json index c5c6a3e2f3..ea879e2ff8 100644 --- a/public/language/ru/admin/general/dashboard.json +++ b/public/language/ru/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Трафик ", "page-views": "Просмотров", "unique-visitors": "Посетителей", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Просмотров за прошлый месяц", "page-views-this-month": "Просмотров за этот месяц", "page-views-last-day": "Просмотров за 24 часа", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Уведомления", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "Управление", "reload": "Перезапустить", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Уникальных пользователей", "graphs.registered-users": "Зарегистрированных пользователей", "graphs.anonymous-users": "Анонимных пользователей" -} \ No newline at end of file +} diff --git a/public/language/rw/admin/general/dashboard.json b/public/language/rw/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/rw/admin/general/dashboard.json +++ b/public/language/rw/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/sc/admin/general/dashboard.json b/public/language/sc/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/sc/admin/general/dashboard.json +++ b/public/language/sc/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/sk/admin/general/dashboard.json b/public/language/sk/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/sk/admin/general/dashboard.json +++ b/public/language/sk/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/sl/admin/general/dashboard.json b/public/language/sl/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/sl/admin/general/dashboard.json +++ b/public/language/sl/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/sr/admin/general/dashboard.json b/public/language/sr/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/sr/admin/general/dashboard.json +++ b/public/language/sr/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/sv/admin/general/dashboard.json b/public/language/sv/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/sv/admin/general/dashboard.json +++ b/public/language/sv/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/th/admin/general/dashboard.json b/public/language/th/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/th/admin/general/dashboard.json +++ b/public/language/th/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/tr/admin/general/dashboard.json b/public/language/tr/admin/general/dashboard.json index 3379d19afa..2f2493e435 100644 --- a/public/language/tr/admin/general/dashboard.json +++ b/public/language/tr/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Trafiği", "page-views": "Sayfa Gösterimi", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/vi/admin/general/dashboard.json b/public/language/vi/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/vi/admin/general/dashboard.json +++ b/public/language/vi/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} diff --git a/public/language/zh-CN/admin/general/dashboard.json b/public/language/zh-CN/admin/general/dashboard.json index dd4035371e..72c80aa352 100644 --- a/public/language/zh-CN/admin/general/dashboard.json +++ b/public/language/zh-CN/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "论坛流量", "page-views": "PV 数量", "unique-visitors": "单一访客", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "上个月 PV 数量", "page-views-this-month": "本月 PV 数量", "page-views-last-day": "过去24小时 PV 数量", @@ -20,6 +23,11 @@ "prerelease-warning": "

    正在使用测试版 NodeBB。可能会出现意外的 Bug。

    ", "notices": "提醒", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "系统控制", "reload": "重载", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "单一访客", "graphs.registered-users": "已注册用户", "graphs.anonymous-users": "匿名用户" -} \ No newline at end of file +} diff --git a/public/language/zh-TW/admin/general/dashboard.json b/public/language/zh-TW/admin/general/dashboard.json index b82802db1b..a70dda322e 100644 --- a/public/language/zh-TW/admin/general/dashboard.json +++ b/public/language/zh-TW/admin/general/dashboard.json @@ -2,6 +2,9 @@ "forum-traffic": "Forum Traffic", "page-views": "Page Views", "unique-visitors": "Unique Visitors", + "users": "Users", + "posts": "Posts", + "topics": "Topics", "page-views-last-month": "Page views Last Month", "page-views-this-month": "Page views This Month", "page-views-last-day": "Page views in last 24 hours", @@ -20,6 +23,11 @@ "prerelease-warning": "

    This is a pre-release version of NodeBB. Unintended bugs may occur.

    ", "notices": "Notices", + "restart-not-required": "Restart not required", + "restart-required": "Restart required", + "search-plugin-installed": "Search Plugin installed", + "search-plugin-not-installed": "Search Plugin not installed", + "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", "control-panel": "System Control", "reload": "Reload", @@ -52,4 +60,4 @@ "graphs.unique-visitors": "Unique Visitors", "graphs.registered-users": "Registered Users", "graphs.anonymous-users": "Anonymous Users" -} \ No newline at end of file +} From 23d92c214d66d38927fe51dbcafeaf1ef6b05a32 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 7 Feb 2017 16:28:25 -0500 Subject: [PATCH 117/122] up persona, vanilla, and markdown --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 2aebb0e57b..58a9f518a8 100644 --- a/package.json +++ b/package.json @@ -56,14 +56,14 @@ "nodebb-plugin-dbsearch": "1.0.5", "nodebb-plugin-emoji-extended": "1.1.1", "nodebb-plugin-emoji-one": "1.1.5", - "nodebb-plugin-markdown": "7.0.3", + "nodebb-plugin-markdown": "7.1.0", "nodebb-plugin-mentions": "1.1.3", "nodebb-plugin-soundpack-default": "0.1.6", "nodebb-plugin-spam-be-gone": "0.4.10", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.15", - "nodebb-theme-persona": "4.1.95", - "nodebb-theme-vanilla": "5.1.59", + "nodebb-theme-persona": "4.2.1", + "nodebb-theme-vanilla": "5.2.0", "nodebb-widget-essentials": "2.0.13", "nodemailer": "2.6.4", "nodemailer-sendmail-transport": "1.0.0", From d966b52dc7d338aa8e7d2353fc2b286b4311ad97 Mon Sep 17 00:00:00 2001 From: "Misty (Bot)" Date: Wed, 8 Feb 2017 09:21:49 +0000 Subject: [PATCH 118/122] Latest translations and fallbacks --- public/language/ar/admin/menu.json | 1 - .../language/ar/admin/settings/uploads.json | 4 +- public/language/ar/notifications.json | 3 ++ public/language/ar/topic.json | 22 +------- public/language/ar/user.json | 3 ++ .../language/bg/admin/general/dashboard.json | 16 +++--- public/language/bg/admin/menu.json | 1 - .../language/bg/admin/settings/uploads.json | 4 +- public/language/bg/notifications.json | 3 ++ public/language/bg/topic.json | 22 +------- public/language/bg/user.json | 3 ++ public/language/bn/admin/menu.json | 1 - .../language/bn/admin/settings/uploads.json | 4 +- public/language/bn/notifications.json | 3 ++ public/language/bn/topic.json | 22 +------- public/language/bn/user.json | 3 ++ public/language/cs/admin/menu.json | 1 - .../language/cs/admin/settings/uploads.json | 4 +- public/language/cs/notifications.json | 3 ++ public/language/cs/topic.json | 22 +------- public/language/cs/user.json | 3 ++ public/language/da/admin/menu.json | 1 - .../language/da/admin/settings/uploads.json | 4 +- public/language/da/notifications.json | 3 ++ public/language/da/topic.json | 22 +------- public/language/da/user.json | 3 ++ public/language/de/admin/menu.json | 1 - .../language/de/admin/settings/uploads.json | 4 +- public/language/de/notifications.json | 3 ++ public/language/de/topic.json | 22 +------- public/language/de/user.json | 3 ++ public/language/el/admin/menu.json | 1 - .../language/el/admin/settings/uploads.json | 4 +- public/language/el/notifications.json | 3 ++ public/language/el/topic.json | 22 +------- public/language/el/user.json | 3 ++ public/language/en-US/admin/menu.json | 1 - .../en-US/admin/settings/uploads.json | 4 +- public/language/en-US/notifications.json | 3 ++ public/language/en-US/topic.json | 22 +------- public/language/en-US/user.json | 3 ++ public/language/en-x-pirate/admin/menu.json | 1 - .../en-x-pirate/admin/settings/uploads.json | 4 +- .../language/en-x-pirate/notifications.json | 3 ++ public/language/en-x-pirate/topic.json | 22 +------- public/language/en-x-pirate/user.json | 3 ++ public/language/es/admin/menu.json | 1 - .../language/es/admin/settings/uploads.json | 4 +- public/language/es/notifications.json | 3 ++ public/language/es/topic.json | 22 +------- public/language/es/user.json | 3 ++ public/language/et/admin/menu.json | 1 - .../language/et/admin/settings/uploads.json | 4 +- public/language/et/notifications.json | 3 ++ public/language/et/topic.json | 22 +------- public/language/et/user.json | 3 ++ public/language/fa-IR/admin/menu.json | 1 - .../fa-IR/admin/settings/uploads.json | 4 +- public/language/fa-IR/notifications.json | 3 ++ public/language/fa-IR/topic.json | 22 +------- public/language/fa-IR/user.json | 3 ++ public/language/fi/admin/menu.json | 1 - .../language/fi/admin/settings/uploads.json | 4 +- public/language/fi/notifications.json | 3 ++ public/language/fi/topic.json | 22 +------- public/language/fi/user.json | 3 ++ .../language/fr/admin/general/dashboard.json | 16 +++--- public/language/fr/admin/menu.json | 1 - .../language/fr/admin/settings/uploads.json | 4 +- public/language/fr/notifications.json | 3 ++ public/language/fr/topic.json | 22 +------- public/language/fr/user.json | 3 ++ public/language/gl/admin/menu.json | 1 - .../language/gl/admin/settings/uploads.json | 4 +- public/language/gl/notifications.json | 3 ++ public/language/gl/topic.json | 22 +------- public/language/gl/user.json | 3 ++ public/language/he/admin/menu.json | 1 - .../language/he/admin/settings/uploads.json | 4 +- public/language/he/notifications.json | 3 ++ public/language/he/topic.json | 22 +------- public/language/he/user.json | 3 ++ public/language/hu/admin/menu.json | 1 - .../language/hu/admin/settings/uploads.json | 4 +- public/language/hu/notifications.json | 3 ++ public/language/hu/topic.json | 22 +------- public/language/hu/user.json | 3 ++ public/language/id/admin/menu.json | 1 - .../language/id/admin/settings/uploads.json | 4 +- public/language/id/notifications.json | 3 ++ public/language/id/topic.json | 22 +------- public/language/id/user.json | 3 ++ public/language/it/admin/menu.json | 1 - .../language/it/admin/settings/uploads.json | 4 +- public/language/it/notifications.json | 3 ++ public/language/it/topic.json | 22 +------- public/language/it/user.json | 3 ++ public/language/ja/admin/menu.json | 1 - .../language/ja/admin/settings/uploads.json | 4 +- public/language/ja/notifications.json | 3 ++ public/language/ja/topic.json | 22 +------- public/language/ja/user.json | 3 ++ public/language/ko/admin/menu.json | 1 - .../language/ko/admin/settings/uploads.json | 4 +- public/language/ko/notifications.json | 3 ++ public/language/ko/topic.json | 22 +------- public/language/ko/user.json | 3 ++ public/language/lt/admin/menu.json | 1 - .../language/lt/admin/settings/uploads.json | 4 +- public/language/lt/notifications.json | 3 ++ public/language/lt/topic.json | 22 +------- public/language/lt/user.json | 3 ++ public/language/ms/admin/menu.json | 1 - .../language/ms/admin/settings/uploads.json | 4 +- public/language/ms/notifications.json | 3 ++ public/language/ms/topic.json | 22 +------- public/language/ms/user.json | 3 ++ public/language/nb/admin/menu.json | 1 - .../language/nb/admin/settings/uploads.json | 4 +- public/language/nb/notifications.json | 3 ++ public/language/nb/topic.json | 22 +------- public/language/nb/user.json | 3 ++ public/language/nl/admin/menu.json | 1 - .../language/nl/admin/settings/uploads.json | 4 +- public/language/nl/notifications.json | 3 ++ public/language/nl/topic.json | 22 +------- public/language/nl/user.json | 3 ++ public/language/pl/admin/menu.json | 1 - .../language/pl/admin/settings/uploads.json | 4 +- public/language/pl/notifications.json | 3 ++ public/language/pl/topic.json | 22 +------- public/language/pl/user.json | 3 ++ public/language/pt-BR/admin/menu.json | 1 - .../pt-BR/admin/settings/uploads.json | 4 +- public/language/pt-BR/notifications.json | 3 ++ public/language/pt-BR/topic.json | 22 +------- public/language/pt-BR/user.json | 3 ++ public/language/pt-PT/admin/menu.json | 1 - .../pt-PT/admin/settings/uploads.json | 4 +- public/language/pt-PT/notifications.json | 3 ++ public/language/pt-PT/topic.json | 22 +------- public/language/pt-PT/user.json | 3 ++ public/language/ro/admin/menu.json | 1 - .../language/ro/admin/settings/uploads.json | 4 +- public/language/ro/notifications.json | 3 ++ public/language/ro/topic.json | 22 +------- public/language/ro/user.json | 3 ++ public/language/ru/admin/menu.json | 1 - .../language/ru/admin/settings/uploads.json | 4 +- public/language/ru/notifications.json | 3 ++ public/language/ru/topic.json | 22 +------- public/language/ru/user.json | 3 ++ public/language/rw/admin/menu.json | 1 - .../language/rw/admin/settings/uploads.json | 4 +- public/language/rw/notifications.json | 3 ++ public/language/rw/topic.json | 22 +------- public/language/rw/user.json | 3 ++ public/language/sc/admin/menu.json | 1 - .../language/sc/admin/settings/uploads.json | 4 +- public/language/sc/notifications.json | 3 ++ public/language/sc/topic.json | 22 +------- public/language/sc/user.json | 3 ++ public/language/sk/admin/menu.json | 1 - .../language/sk/admin/settings/uploads.json | 4 +- public/language/sk/notifications.json | 3 ++ public/language/sk/topic.json | 22 +------- public/language/sk/user.json | 3 ++ public/language/sl/admin/menu.json | 1 - .../language/sl/admin/settings/uploads.json | 4 +- public/language/sl/notifications.json | 3 ++ public/language/sl/topic.json | 22 +------- public/language/sl/user.json | 3 ++ public/language/sr/admin/menu.json | 1 - .../language/sr/admin/settings/uploads.json | 4 +- public/language/sr/notifications.json | 3 ++ public/language/sr/topic.json | 22 +------- public/language/sr/user.json | 3 ++ public/language/sv/admin/menu.json | 1 - .../language/sv/admin/settings/uploads.json | 4 +- public/language/sv/notifications.json | 3 ++ public/language/sv/topic.json | 22 +------- public/language/sv/user.json | 3 ++ public/language/th/admin/menu.json | 1 - .../language/th/admin/settings/uploads.json | 4 +- public/language/th/notifications.json | 3 ++ public/language/th/topic.json | 22 +------- public/language/th/user.json | 3 ++ public/language/tr/admin/menu.json | 1 - .../language/tr/admin/settings/uploads.json | 4 +- public/language/tr/notifications.json | 3 ++ public/language/tr/topic.json | 22 +------- public/language/tr/user.json | 3 ++ public/language/vi/admin/menu.json | 1 - .../language/vi/admin/settings/uploads.json | 4 +- public/language/vi/notifications.json | 3 ++ public/language/vi/topic.json | 22 +------- public/language/vi/user.json | 3 ++ .../zh-CN/admin/general/dashboard.json | 16 +++--- public/language/zh-CN/admin/menu.json | 1 - .../zh-CN/admin/settings/uploads.json | 4 +- public/language/zh-CN/notifications.json | 3 ++ public/language/zh-CN/topic.json | 22 +------- public/language/zh-CN/user.json | 3 ++ .../language/zh-TW/admin/advanced/cache.json | 18 +++---- .../zh-TW/admin/advanced/database.json | 54 +++++++++---------- .../language/zh-TW/admin/advanced/errors.json | 24 ++++----- public/language/zh-TW/admin/menu.json | 1 - .../language/zh-TW/admin/settings/group.json | 16 +++--- .../zh-TW/admin/settings/notifications.json | 6 +-- .../zh-TW/admin/settings/sockets.json | 8 +-- .../zh-TW/admin/settings/uploads.json | 4 +- public/language/zh-TW/notifications.json | 3 ++ public/language/zh-TW/topic.json | 22 +------- public/language/zh-TW/user.json | 3 ++ 214 files changed, 456 insertions(+), 1071 deletions(-) diff --git a/public/language/ar/admin/menu.json b/public/language/ar/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/ar/admin/menu.json +++ b/public/language/ar/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/ar/admin/settings/uploads.json b/public/language/ar/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/ar/admin/settings/uploads.json +++ b/public/language/ar/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/ar/notifications.json b/public/language/ar/notifications.json index 9df1e7e355..382e346f84 100644 --- a/public/language/ar/notifications.json +++ b/public/language/ar/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 أشعَرَ بمشاركة مخلة في %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 أضاف ردا إلى: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/ar/topic.json b/public/language/ar/topic.json index 0247a147d6..40d2b0f25f 100644 --- a/public/language/ar/topic.json +++ b/public/language/ar/topic.json @@ -25,28 +25,11 @@ "link": "رابط", "share": "نشر", "tools": "أدوات", - "flag": "تبليغ", "locked": "مقفل", "pinned": "مثبت", "moved": "منقول", "bookmark_instructions": "اضغط هنا للعودة لأخر مشاركة مقروءة في الموضوع", "flag_title": "إشعار بمشاركة مخلة.", - "flag_success": "تم الإشعار بهذه المشاركة على أنها مخلة", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "هذه المشاركة محذوفة. فقط من لهم صلاحية الإشراف على ا لمشاركات يمكنهم معاينتها.", "following_topic.message": "ستستلم تنبيها عند كل مشاركة جديدة في هذا الموضوع.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "موضوع جديد", "stale.reply_anyway": "الرد على هذا الموضوع ", - "link_back": "رد: [%1](%2)", - "spam": "سبام", - "offensive": "مسيئ", - "custom-flag-reason": "أدخل سبب التبليغ" + "link_back": "رد: [%1](%2)" } \ No newline at end of file diff --git a/public/language/ar/user.json b/public/language/ar/user.json index f765a7458a..08b44d2ef8 100644 --- a/public/language/ar/user.json +++ b/public/language/ar/user.json @@ -33,6 +33,7 @@ "chat": "محادثة", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "تابع", "unfollow": "إلغاء المتابعة", "more": "المزيد", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remove Uploaded Picture", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "خيارات", "show_email": "أظهر بريدي الإلكتروني", "show_fullname": "أظهر اسمي الكامل", diff --git a/public/language/bg/admin/general/dashboard.json b/public/language/bg/admin/general/dashboard.json index b54fa53d30..e0f09b639a 100644 --- a/public/language/bg/admin/general/dashboard.json +++ b/public/language/bg/admin/general/dashboard.json @@ -2,9 +2,9 @@ "forum-traffic": "Трафик на форума", "page-views": "Преглеждания на страниците", "unique-visitors": "Уникални посетители", - "users": "Users", - "posts": "Posts", - "topics": "Topics", + "users": "Потребители", + "posts": "Публикации", + "topics": "Теми", "page-views-last-month": "Преглеждания на страниците през последния месец", "page-views-this-month": "Преглеждания на страниците този месец", "page-views-last-day": "Преглеждания на страниците през последните 24 часа", @@ -23,11 +23,11 @@ "prerelease-warning": "

    Това е версия за предварителен преглед на NodeBB. Възможно е да има неочаквани неизправности.

    ", "notices": "Забележки", - "restart-not-required": "Restart not required", - "restart-required": "Restart required", - "search-plugin-installed": "Search Plugin installed", - "search-plugin-not-installed": "Search Plugin not installed", - "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", + "restart-not-required": "Не се изисква рестартиране", + "restart-required": "Изисква се рестартиране", + "search-plugin-installed": "Добавката за търсене е инсталирана", + "search-plugin-not-installed": "Добавката за търсене не е инсталирана", + "search-plugin-tooltip": "Инсталирайте добавка за търсене от страницата с добавките, за да включите функционалността за търсене", "control-panel": "Системен контрол", "reload": "Презареждане", diff --git a/public/language/bg/admin/menu.json b/public/language/bg/admin/menu.json index 78ddd79b7c..4870901b68 100644 --- a/public/language/bg/admin/menu.json +++ b/public/language/bg/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Потребители", "manage/registration": "Регистрационна опашка", "manage/groups": "Групи", - "manage/flags": "Доклади", "manage/ip-blacklist": "Черен списък за IP адреси", "section-settings": "Настройки", diff --git a/public/language/bg/admin/settings/uploads.json b/public/language/bg/admin/settings/uploads.json index 834b707706..3c1d0d7c59 100644 --- a/public/language/bg/admin/settings/uploads.json +++ b/public/language/bg/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Позволяване на потребителите да качват миниатюрни изображения за темите", "topic-thumb-size": "Размер на миниатюрите за темите", "allowed-file-extensions": "Разрешени файлови разширения", - "allowed-file-extensions-help": "Въведете файловите разширения тук, разделени със запетаи (напр. pdf,xls,doc).\n\\t\\t\\t\\t\\tАко списъкът е празен, всички файлови разширения ще бъдат разрешени.", + "allowed-file-extensions-help": "Въведете файловите разширения, разделени със запетаи (пример: pdf,xls,doc). Ако списъкът е празен, всички файлови разширения ще бъдат разрешени.", "profile-avatars": "Профилни изображения", "allow-profile-image-uploads": "Позволяване на потребителите да качват профилни изображения", "convert-profile-image-png": "Превръщане на качените профилни изображения във формата „PNG“", @@ -25,4 +25,4 @@ "profile-covers": "Корици на профила", "default-covers": "Стандартни изображения за корицата", "default-covers-help": "Добавете стандартни изображения на корицата (разделени със запетаи) за акаунтите, които нямат качено такова." -} \ No newline at end of file +} diff --git a/public/language/bg/notifications.json b/public/language/bg/notifications.json index 1b0c4b9a93..2367060bc8 100644 --- a/public/language/bg/notifications.json +++ b/public/language/bg/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 докладва Ваша публикация в %2", "user_flagged_post_in_dual": "%1 и %2 докладваха Ваша публикация в %3", "user_flagged_post_in_multiple": "%1 и %2 други докладваха Ваша публикация в %3", + "user_flagged_user": "%1 докладва потребителски профил (%2)", + "user_flagged_user_dual": "%1 и %2 докладваха потребителски профил (%3)", + "user_flagged_user_multiple": "%1 и още %2 потребители докладваха потребителски профил (%3)", "user_posted_to": "%1 публикува отговор на: %2", "user_posted_to_dual": "%1 и %2 публикуваха отговори на: %3", "user_posted_to_multiple": "%1 и %2 други публикуваха отговори на: %3", diff --git a/public/language/bg/topic.json b/public/language/bg/topic.json index 09088b1b95..e51e69765a 100644 --- a/public/language/bg/topic.json +++ b/public/language/bg/topic.json @@ -25,28 +25,11 @@ "link": "Връзка", "share": "Споделяне", "tools": "Инструменти", - "flag": "Докладване", "locked": "Заключена", "pinned": "Закачена", "moved": "Преместена", "bookmark_instructions": "Щракнете тук, за да се върнете към последно прочетената публикация в тази тема.", "flag_title": "Докладване на тази публикация до модератор", - "flag_success": "Тази публикация е била докладвана до модератор.", - "flag_manage_title": "Докладвана публикация в %1", - "flag_manage_history": "История на дейността", - "flag_manage_no_history": "Няма история на събитията", - "flag_manage_assignee": "Назначен", - "flag_manage_state": "Състояние", - "flag_manage_state_open": "Нов/отворен", - "flag_manage_state_wip": "В процес на работа", - "flag_manage_state_resolved": "Разрешен", - "flag_manage_state_rejected": "Отхвърлен", - "flag_manage_notes": "Споделени бележки", - "flag_manage_update": "Обновяване на състоянието на доклада", - "flag_manage_history_assignee": "Разпределен на %1", - "flag_manage_history_state": "Състоянието е променено на „%1“", - "flag_manage_history_notes": "Бележките към доклада са обновени", - "flag_manage_saved": "Подробностите за доклада са обновени", "deleted_message": "Темата е изтрита. Само потребители с права за управление на темите могат да я видят.", "following_topic.message": "Вече ще получавате известия когато някой публикува коментар в тази тема.", "not_following_topic.message": "Ще виждате тази тема в списъка с непрочетени теми, но няма да получавате известия, когато хората публикуват нещо в нея.", @@ -131,8 +114,5 @@ "stale.warning": "Темата, в която отговаряте, е доста стара. Искате ли вместо това да създадете нова и да направите препратка към тази в отговора си?", "stale.create": "Създаване на нова тема", "stale.reply_anyway": "Отговаряне в тази тема въпреки това", - "link_back": "Отговор: [%1](%2)", - "spam": "Спам", - "offensive": "Обидно", - "custom-flag-reason": "Изберете причина за докладване" + "link_back": "Отговор: [%1](%2)" } \ No newline at end of file diff --git a/public/language/bg/user.json b/public/language/bg/user.json index 3836c26357..926ecc3735 100644 --- a/public/language/bg/user.json +++ b/public/language/bg/user.json @@ -33,6 +33,7 @@ "chat": "Разговор", "chat_with": "Продължаване на разговора с %1", "new_chat_with": "Започване на нов разговор с %1", + "flag-profile": "Докладване на профила", "follow": "Следване", "unfollow": "Спиране на следването", "more": "Още", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Премахване на качената снимка", "upload_cover_picture": "Качване на снимка на корицата", "remove_cover_picture_confirm": "Наистина ли искате да премахнете снимката на корицата?", + "crop_picture": "Орязване на снимката", + "upload_cropped_picture": "Орязване и качване", "settings": "Настройки", "show_email": "Да се показва е-пощата ми", "show_fullname": "Да се показва цялото ми име", diff --git a/public/language/bn/admin/menu.json b/public/language/bn/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/bn/admin/menu.json +++ b/public/language/bn/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/bn/admin/settings/uploads.json b/public/language/bn/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/bn/admin/settings/uploads.json +++ b/public/language/bn/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/bn/notifications.json b/public/language/bn/notifications.json index f139fe03fc..4c1a057d10 100644 --- a/public/language/bn/notifications.json +++ b/public/language/bn/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 flagged a post in %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 একটি উত্তর দিয়েছেন: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/bn/topic.json b/public/language/bn/topic.json index afdc93df1d..de7801a0c6 100644 --- a/public/language/bn/topic.json +++ b/public/language/bn/topic.json @@ -25,28 +25,11 @@ "link": "লিঙ্ক", "share": "শেয়ার", "tools": "টুলস", - "flag": "ফ্ল্যাগ", "locked": "বন্ধ", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "মডারেশনের জন্য এই পোস্টটি ফ্ল্যাগ করুন", - "flag_success": "এই পোস্টটি মডারেশনের জন্য ফ্ল্যাগ করা হয়েছে।", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "এই টপিকটি মুছে ফেলা হয়েছে। শুধুমাত্র টপিক ব্যবস্থাপনার ক্ষমতাপ্রাপ্ত সদস্যগণ এটি দেখতে পারবেন।", "following_topic.message": "এখন থেকে এই টপিকে অন্যকেউ পোস্ট করলে আপনি নোটিফিকেশন পাবেন।", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/bn/user.json b/public/language/bn/user.json index f28036d574..1c5685a7bb 100644 --- a/public/language/bn/user.json +++ b/public/language/bn/user.json @@ -33,6 +33,7 @@ "chat": "বার্তালাপ", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "অনুসরন করুন", "unfollow": "অনুসরন করা থেকে বিরত থাকুন", "more": "আরো...", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "আপলোড করা ছবিটি সরিয়ে নাও", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "সেটিংস", "show_email": "আমার ইমেইল দেখাও", "show_fullname": "আমার সম্পূর্ণ নাম দেখাও", diff --git a/public/language/cs/admin/menu.json b/public/language/cs/admin/menu.json index 68ad626681..4ac4eb1a01 100644 --- a/public/language/cs/admin/menu.json +++ b/public/language/cs/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/cs/admin/settings/uploads.json b/public/language/cs/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/cs/admin/settings/uploads.json +++ b/public/language/cs/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/cs/notifications.json b/public/language/cs/notifications.json index 277cdff4fa..f25c7ac701 100644 --- a/public/language/cs/notifications.json +++ b/public/language/cs/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 flagged a post in %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 has posted a reply to: %2", "user_posted_to_dual": "%1%2 odpověděli v tématu %3", "user_posted_to_multiple": "%1 a %2 další odpověděli v tématu %3", diff --git a/public/language/cs/topic.json b/public/language/cs/topic.json index 5c8804dfd6..0a05708df2 100644 --- a/public/language/cs/topic.json +++ b/public/language/cs/topic.json @@ -25,28 +25,11 @@ "link": "Odkaz", "share": "Sdílet", "tools": "Nástroje", - "flag": "Flag", "locked": "Uzamčeno", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Flag this post for moderation", - "flag_success": "This post has been flagged for moderation.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "This topic has been deleted. Only users with topic management privileges can see it.", "following_topic.message": "You will now be receiving notifications when somebody posts to this topic.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "Reagujete na starší téma. Nechcete raději vytvořit téma nové a na původní v něm odkázat?", "stale.create": "Vytvořit nové téma", "stale.reply_anyway": "Přesto reagovat na toto téma", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Urážlivé", - "custom-flag-reason": "Vložte důvod oznámení" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/cs/user.json b/public/language/cs/user.json index 91a35a34cf..01cf965cc8 100644 --- a/public/language/cs/user.json +++ b/public/language/cs/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Sledovat", "unfollow": "Nesledovat", "more": "Více", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Odstranit nahraný obrázek", "upload_cover_picture": "Náhrát titulní obrázek", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Nastavení", "show_email": "Zobrazovat můj e-mail v profilu", "show_fullname": "Zobrazovat celé jméno", diff --git a/public/language/da/admin/menu.json b/public/language/da/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/da/admin/menu.json +++ b/public/language/da/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/da/admin/settings/uploads.json b/public/language/da/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/da/admin/settings/uploads.json +++ b/public/language/da/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/da/notifications.json b/public/language/da/notifications.json index d05a19fa4b..659a87cafe 100644 --- a/public/language/da/notifications.json +++ b/public/language/da/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 har anmeldt et indlæg i %2", "user_flagged_post_in_dual": "%1 og %2 har anmeldt et indlæg i %3", "user_flagged_post_in_multiple": "%1 og %2 andre har anmeldt et indlæg i %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 har skrevet et svar til: %2", "user_posted_to_dual": "%1 og %2 har skrevet svar til: %3", "user_posted_to_multiple": "%1 og %2 andre har skrevet svar til: %3", diff --git a/public/language/da/topic.json b/public/language/da/topic.json index 5bd68c4a12..0d27bf2fd6 100644 --- a/public/language/da/topic.json +++ b/public/language/da/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Del", "tools": "Værktøjer", - "flag": "Marker", "locked": "Låst", "pinned": "Pinned", "moved": "Flyttet", "bookmark_instructions": "Klik her for at vende tilbage til den sidst læste indlæg i denne tråd.", "flag_title": "Meld dette indlæg til moderation", - "flag_success": "Dette indlæg er blevet meldt til moderation.", - "flag_manage_title": "Markeret indlæg %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "Ny/Åben", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Løst", - "flag_manage_state_rejected": "Afvist", - "flag_manage_notes": "Delte Noter", - "flag_manage_update": "Opdater Markerings Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Denne tråd er blevet slettet. Kun brugere med emne behandlings privilegier kan se den.", "following_topic.message": "Du vil nu modtage notifikationer når nogle skriver et indlæg i dette emne.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "Emnet du svarer på er ret gammelt. Vil du oprette et nyt emne istedet og referere dette indlæg i dit svar?", "stale.create": "Opret nyt emne", "stale.reply_anyway": "Svar dette emne alligevel", - "link_back": "Svar: [%1](%2)", - "spam": "Spam", - "offensive": "Stødende", - "custom-flag-reason": "Indsæt en markeringsgrund" + "link_back": "Svar: [%1](%2)" } \ No newline at end of file diff --git a/public/language/da/user.json b/public/language/da/user.json index 077dc27577..7e1b09b453 100644 --- a/public/language/da/user.json +++ b/public/language/da/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Fortsæt chatte med %1", "new_chat_with": "Start en ny chat med %1", + "flag-profile": "Flag Profile", "follow": "Følg", "unfollow": "Følg ikke", "more": "Mere", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Fjern uploaded billede", "upload_cover_picture": "Upload coverbillede", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Indstillinger", "show_email": "Vis min emailaddresse", "show_fullname": "Vis mit fulde navn", diff --git a/public/language/de/admin/menu.json b/public/language/de/admin/menu.json index fa0afa7405..1dcb331bb5 100644 --- a/public/language/de/admin/menu.json +++ b/public/language/de/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Benutzer", "manage/registration": "Warteliste", "manage/groups": "Gruppen", - "manage/flags": "Markierungen", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Einstellungen", diff --git a/public/language/de/admin/settings/uploads.json b/public/language/de/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/de/admin/settings/uploads.json +++ b/public/language/de/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/de/notifications.json b/public/language/de/notifications.json index 18cc3b5e77..20796b7eb9 100644 --- a/public/language/de/notifications.json +++ b/public/language/de/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 hat einen Beitrag in
    %2 gemeldet", "user_flagged_post_in_dual": "%1 und %2 haben einen Beitrag in %3 gemeldet", "user_flagged_post_in_multiple": "%1 und %2 andere Nutzer haben einen Beitrag in %3 gemeldet", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 hat auf %2 geantwortet.", "user_posted_to_dual": "%1 und %2 haben auf %3 geantwortet.", "user_posted_to_multiple": "%1 und %2 andere Nutzer haben auf %3 geantwortet.", diff --git a/public/language/de/topic.json b/public/language/de/topic.json index 736ae69582..d9eed1419f 100644 --- a/public/language/de/topic.json +++ b/public/language/de/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Teilen", "tools": "Werkzeuge", - "flag": "Markieren", "locked": "Gesperrt", "pinned": "Angepinnt", "moved": "Verschoben", "bookmark_instructions": "Klicke hier, um zum letzten gelesenen Beitrag des Themas zurückzukehren.", "flag_title": "Diesen Beitrag zur Moderation markieren", - "flag_success": "Dieser Beitrag wurde erfolgreich für die Moderation markiert.", - "flag_manage_title": "Gemeldeter Beitrag in %1", - "flag_manage_history": "Aktions-Verlauf", - "flag_manage_no_history": "Kein Ereignisverlauf zum Bericht", - "flag_manage_assignee": "Zugeordnete Person", - "flag_manage_state": "Zustand", - "flag_manage_state_open": "Neu/Offen", - "flag_manage_state_wip": "In Arbeit", - "flag_manage_state_resolved": "Gelöst", - "flag_manage_state_rejected": "Abgelehnt", - "flag_manage_notes": "Geteilte Notizen", - "flag_manage_update": "Meldungsstatus aktualisieren", - "flag_manage_history_assignee": "%1 zugewiesen", - "flag_manage_history_state": "Status zu %1 aktualisiert", - "flag_manage_history_notes": "Meldungsnotizen aktualisiert", - "flag_manage_saved": "Meldungsdetails aktualisiert", "deleted_message": "Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.", "following_topic.message": "Du erhälst nun eine Benachrichtigung, wenn jemand einen Beitrag zu diesem Thema verfasst.", "not_following_topic.message": "Ungelesene Beiträge in diesem Thema werden angezeigt, aber du erhältst keine Benachrichtigung wenn jemand einen Beitrag zu diesem Thema verfasst.", @@ -131,8 +114,5 @@ "stale.warning": "Das Thema auf das du antworten möchtest ist ziemlich alt. Möchtest du stattdessen ein neues Thema erstellen und auf dieses in deiner Antwort hinweisen?", "stale.create": "Ein neues Thema erstellen", "stale.reply_anyway": "Auf dieses Thema trotzdem antworten", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Beleidigend", - "custom-flag-reason": "Gib einen Grund für die Markierung ein" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/de/user.json b/public/language/de/user.json index 2d3361df73..a98b90f75a 100644 --- a/public/language/de/user.json +++ b/public/language/de/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Führe deinen Chat mit %1 fort", "new_chat_with": "Beginne einen neuen Chat mit %1", + "flag-profile": "Flag Profile", "follow": "Folgen", "unfollow": "Nicht mehr folgen", "more": "Mehr", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Hochgeladenes Bild entfernen", "upload_cover_picture": "Titelbild hochladen", "remove_cover_picture_confirm": "Bist du sicher, dass du dein Titelbild entfernen möchtest?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Einstellungen", "show_email": "Zeige meine E-Mail Adresse an.", "show_fullname": "Zeige meinen kompletten Namen an", diff --git a/public/language/el/admin/menu.json b/public/language/el/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/el/admin/menu.json +++ b/public/language/el/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/el/admin/settings/uploads.json b/public/language/el/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/el/admin/settings/uploads.json +++ b/public/language/el/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/el/notifications.json b/public/language/el/notifications.json index 00903465f5..1a4328a085 100644 --- a/public/language/el/notifications.json +++ b/public/language/el/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "Ο/Η %1 επεσήμανε μια δημοσίευσή σου στο %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "Ο/Η %1 έγραψε μια απάντηση στο: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/el/topic.json b/public/language/el/topic.json index d175de6bfa..1a0d2d751a 100644 --- a/public/language/el/topic.json +++ b/public/language/el/topic.json @@ -25,28 +25,11 @@ "link": "Σύνδεσμος", "share": "Μοιράσου το", "tools": "Εργαλεία", - "flag": "Σημαία", "locked": "Κλειδωμένο", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Επισήμανση αυτής της δημοσίευσης για συντονισμό", - "flag_success": "Αυτή η δημοσίευση έχει επισημανθεί για συντονισμό.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Το θέμα αυτό έχει διαγραφεί. Μόνο οι χρήστες με δικαιώματα διαχειριστή θεμάτων μπορούν να το δουν.", "following_topic.message": "Θα λαμβάνεις ειδοποιήσεις όποτε κάποιος δημοσιεύει κάτι σε αυτό το θέμα.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/el/user.json b/public/language/el/user.json index 3fd3a376a4..622b41ab30 100644 --- a/public/language/el/user.json +++ b/public/language/el/user.json @@ -33,6 +33,7 @@ "chat": "Συνομιλία", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Ακολούθησε", "unfollow": "Μην Ακολουθείς", "more": "More", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remove Uploaded Picture", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Επιλογές", "show_email": "Εμφάνιση του email μου", "show_fullname": "Show My Full Name", diff --git a/public/language/en-US/admin/menu.json b/public/language/en-US/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/en-US/admin/menu.json +++ b/public/language/en-US/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/en-US/admin/settings/uploads.json b/public/language/en-US/admin/settings/uploads.json index f7f9d2daa6..35eaa5a58f 100644 --- a/public/language/en-US/admin/settings/uploads.json +++ b/public/language/en-US/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\\t\\t\\t\\t\\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/en-US/notifications.json b/public/language/en-US/notifications.json index 580e697548..e2ab96c850 100644 --- a/public/language/en-US/notifications.json +++ b/public/language/en-US/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 flagged a post in %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 has posted a reply to: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/en-US/topic.json b/public/language/en-US/topic.json index c4a9109252..2ce61da6a7 100644 --- a/public/language/en-US/topic.json +++ b/public/language/en-US/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Share", "tools": "Tools", - "flag": "Flag", "locked": "Locked", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Flag this post for moderation", - "flag_success": "This post has been flagged for moderation.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "This topic has been deleted. Only users with topic management privileges can see it.", "following_topic.message": "You will now be receiving notifications when somebody posts to this topic.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/en-US/user.json b/public/language/en-US/user.json index 4718cd00a0..61f103e7d5 100644 --- a/public/language/en-US/user.json +++ b/public/language/en-US/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Follow", "unfollow": "Unfollow", "more": "More", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remove Uploaded Picture", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Settings", "show_email": "Show My Email", "show_fullname": "Show My Full Name", diff --git a/public/language/en-x-pirate/admin/menu.json b/public/language/en-x-pirate/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/en-x-pirate/admin/menu.json +++ b/public/language/en-x-pirate/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/en-x-pirate/admin/settings/uploads.json b/public/language/en-x-pirate/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/en-x-pirate/admin/settings/uploads.json +++ b/public/language/en-x-pirate/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/en-x-pirate/notifications.json b/public/language/en-x-pirate/notifications.json index c6dedd3eb0..8f54b7b7df 100644 --- a/public/language/en-x-pirate/notifications.json +++ b/public/language/en-x-pirate/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 flagged a post in %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 has posted a reply to: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/en-x-pirate/topic.json b/public/language/en-x-pirate/topic.json index c4a9109252..2ce61da6a7 100644 --- a/public/language/en-x-pirate/topic.json +++ b/public/language/en-x-pirate/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Share", "tools": "Tools", - "flag": "Flag", "locked": "Locked", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Flag this post for moderation", - "flag_success": "This post has been flagged for moderation.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "This topic has been deleted. Only users with topic management privileges can see it.", "following_topic.message": "You will now be receiving notifications when somebody posts to this topic.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/en-x-pirate/user.json b/public/language/en-x-pirate/user.json index fcf518c200..350326450d 100644 --- a/public/language/en-x-pirate/user.json +++ b/public/language/en-x-pirate/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Follow", "unfollow": "Unfollow", "more": "More", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remove Uploaded Picture", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Settings", "show_email": "Show My Email", "show_fullname": "Show My Full Name", diff --git a/public/language/es/admin/menu.json b/public/language/es/admin/menu.json index 41bbd5ee3b..7cb50e1dc5 100644 --- a/public/language/es/admin/menu.json +++ b/public/language/es/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Usuarios", "manage/registration": "Cola de Registro", "manage/groups": "Grupos", - "manage/flags": "Reportes", "manage/ip-blacklist": "Lista negra de IP", "section-settings": "Opciones", diff --git a/public/language/es/admin/settings/uploads.json b/public/language/es/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/es/admin/settings/uploads.json +++ b/public/language/es/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/es/notifications.json b/public/language/es/notifications.json index b0391106db..6c634a81d6 100644 --- a/public/language/es/notifications.json +++ b/public/language/es/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 ha reportado una respuesta en %2", "user_flagged_post_in_dual": "%1 y %2 han reportado un post en %3", "user_flagged_post_in_multiple": "%1 y otras %2 personas han reportado un post en %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 ha respondido a: %2", "user_posted_to_dual": "%1 y %2 han respondido a %3", "user_posted_to_multiple": "%1 y otras %2 personas han respondido a: %3", diff --git a/public/language/es/topic.json b/public/language/es/topic.json index 0e21d90b24..8310b554c3 100644 --- a/public/language/es/topic.json +++ b/public/language/es/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Compartir", "tools": "Herramientas", - "flag": "Reportar", "locked": "Cerrado", "pinned": "Fijo", "moved": "Movido", "bookmark_instructions": "Haz click aquí para volver a tu último mensaje leído en este tema", "flag_title": "Reportar este mensaje", - "flag_success": "Este mensaje ha sido reportado para moderación.", - "flag_manage_title": "Mensaje reportado en %1", - "flag_manage_history": "Historial de acciones", - "flag_manage_no_history": "Sin histórico de eventos", - "flag_manage_assignee": "Asignado", - "flag_manage_state": "Estado", - "flag_manage_state_open": "Nuevo/Abrir", - "flag_manage_state_wip": "En revisión", - "flag_manage_state_resolved": "Resuelto", - "flag_manage_state_rejected": "Rechazado", - "flag_manage_notes": "Notas compartidas", - "flag_manage_update": "Actualizar estado de reporte", - "flag_manage_history_assignee": "Asignado a %1", - "flag_manage_history_state": "Actualizado estado a %1", - "flag_manage_history_notes": "Actualizar notas de reporte", - "flag_manage_saved": "Detalles de reporte actualizados", "deleted_message": "Este tema ha sido borrado. Solo los usuarios que tengan privilegios de administración de temas pueden verlo.", "following_topic.message": "Ahora recibiras notificaciones cuando alguien publique en este tema.", "not_following_topic.message": "Podras ver este tema en la lista de no leidos, pero no recibirás notificaciones cuando alguien escriba en él.", @@ -131,8 +114,5 @@ "stale.warning": "El hilo al que estás respondiendo es muy antiguo. ¿Quieres crear un nuevo hilo en su lugar y añadir una referencia a este en tu mensaje?", "stale.create": "Crear un nuevo hilo", "stale.reply_anyway": "Publicar este hilo de todos modos.", - "link_back": "Re: [%1](%2)", - "spam": "SPAM", - "offensive": "Ofensivo", - "custom-flag-reason": "Introduzca una razón indicatoria." + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/es/user.json b/public/language/es/user.json index 2fabed751a..3e16137749 100644 --- a/public/language/es/user.json +++ b/public/language/es/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Continuar chat con %1", "new_chat_with": "Empezar chat con %1", + "flag-profile": "Flag Profile", "follow": "Seguir", "unfollow": "Dejar de seguir", "more": "Más", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Borrar Imagen subida", "upload_cover_picture": "Subir imagen de portada", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Opciones", "show_email": "Mostrar mi correo electrónico", "show_fullname": "Mostrar mi nombre completo", diff --git a/public/language/et/admin/menu.json b/public/language/et/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/et/admin/menu.json +++ b/public/language/et/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/et/admin/settings/uploads.json b/public/language/et/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/et/admin/settings/uploads.json +++ b/public/language/et/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/et/notifications.json b/public/language/et/notifications.json index c804914ee1..ba85a69ba5 100644 --- a/public/language/et/notifications.json +++ b/public/language/et/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 raporteeris postitust %2", "user_flagged_post_in_dual": "%1 ja %2 märgistasid postituse: %3", "user_flagged_post_in_multiple": "%1 ja %2 teist märgistasid postituse: %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "Kasutaja %1 postitas vastuse teemasse %2", "user_posted_to_dual": "%1 ja %2 on postitanud vastused: %3", "user_posted_to_multiple": "%1 ja %2 teist on postitanud vastused: %3", diff --git a/public/language/et/topic.json b/public/language/et/topic.json index 91c9e354c0..65dc5525c7 100644 --- a/public/language/et/topic.json +++ b/public/language/et/topic.json @@ -25,28 +25,11 @@ "link": "Ühenda", "share": "Jaga", "tools": "Tööriistad", - "flag": "Märgista", "locked": "Lukustatud", "pinned": "Märgistatud", "moved": "Liigutatud", "bookmark_instructions": "Vajuta siia, et tagasi minna viimati loetud postituse juurde siin teemas.", "flag_title": "Märgista see postitus modereerimiseks", - "flag_success": "See postitus on nüüd märgistatud modereerimiseks.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "See teema on kustutatud. Ainult kasutajad kellel on piisavalt õigusi saavad seda näha.", "following_topic.message": "Sulle ei edastata enam teateid uutest postitustest kui keegi postitab siia teemasse.", "not_following_topic.message": "Sa näed seda postitust lugemata postituste nimekirjas, kuid sa ei näe selle kohta teateid, kui keegi sinna postitab.", @@ -131,8 +114,5 @@ "stale.warning": "Teema, millele vastad on küllaltki vana. Kas sooviksid hoopiski uue teema luua ning viidata sellele sinu vastuses?", "stale.create": "Loo uus teema/alapealkiri", "stale.reply_anyway": "Vasta sellele teemale siiski", - "link_back": "Re: [%1](%2)", - "spam": "Rämpspost", - "offensive": "Solvav", - "custom-flag-reason": "Sisesta teavitamise põhjus" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/et/user.json b/public/language/et/user.json index 5da27588e1..ba2738c38e 100644 --- a/public/language/et/user.json +++ b/public/language/et/user.json @@ -33,6 +33,7 @@ "chat": "Vestlus", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Jälgi", "unfollow": "Ära jälgi enam", "more": "Rohkem", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Eemalda üleslaetud pilt", "upload_cover_picture": "Lae üles katte pilt", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Seaded", "show_email": "Näita minu emaili", "show_fullname": "Näita minu täisnime", diff --git a/public/language/fa-IR/admin/menu.json b/public/language/fa-IR/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/fa-IR/admin/menu.json +++ b/public/language/fa-IR/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/fa-IR/admin/settings/uploads.json b/public/language/fa-IR/admin/settings/uploads.json index ff98119762..fdf0ff5c1c 100644 --- a/public/language/fa-IR/admin/settings/uploads.json +++ b/public/language/fa-IR/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/fa-IR/notifications.json b/public/language/fa-IR/notifications.json index 6d49770f07..c60fde1b95 100644 --- a/public/language/fa-IR/notifications.json +++ b/public/language/fa-IR/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 پست شما را در %2 علامتدار کرده", "user_flagged_post_in_dual": "%1 و %2 نشانه‌گذاری کرده اند پست را در %3", "user_flagged_post_in_multiple": "%1 و %2 نفر دیگر این پست را نشانه‌گذاری کرده در %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "پاسخ دادن به %2 از سوی %1", "user_posted_to_dual": "%1 و %2 پاسخ به پست دادند در: %3", "user_posted_to_multiple": "%1 و %2 نفر دیگر به پست شما پاسخ ارسال کرده‌اند در: %3", diff --git a/public/language/fa-IR/topic.json b/public/language/fa-IR/topic.json index 0e0ca2714a..f1961f4c47 100644 --- a/public/language/fa-IR/topic.json +++ b/public/language/fa-IR/topic.json @@ -25,28 +25,11 @@ "link": "پیوند", "share": "اشتراک‌گذاری", "tools": "ابزارها", - "flag": "پرچم", "locked": "قفل شده است", "pinned": "سنجاق شده", "moved": "منتقل شده", "bookmark_instructions": "برای بازگشت به آخرین پست در این موضوع اینجا را کلیک کنید.", "flag_title": "پرچم‌گذاری این موضوع برای بررسی ناظران", - "flag_success": "این موضوع برای بررسی ناظران پرچم گذاشته شد.", - "flag_manage_title": "پست نشانه‌گذاری شده در %1", - "flag_manage_history": "تاریخچه عملیات", - "flag_manage_no_history": "هیچ تاریخ رویدادی برای گزارش نیست", - "flag_manage_assignee": "نماینده", - "flag_manage_state": "حالت", - "flag_manage_state_open": "جدید/باز‌‌کردن", - "flag_manage_state_wip": "کار در حال انجام", - "flag_manage_state_resolved": "دوباره حل‌ شده", - "flag_manage_state_rejected": "رد شده", - "flag_manage_notes": "یادداشت‌ها به اشتراک گذاشته شده", - "flag_manage_update": "به‌روزرسانی وضعیت نشانه", - "flag_manage_history_assignee": "اختصاص داده شده به %1", - "flag_manage_history_state": "وضعیت به‌روزرسانی شد به %1", - "flag_manage_history_notes": "یادداشت‌های نشانه به‌روزرسانی شد", - "flag_manage_saved": "جزئیات نشانه به‌روزرسانی شد", "deleted_message": "این موضوع پاک شده است. تنها کاربرانِ با حق مدیریت موضوع می‌توانند آن را ببینند.", "following_topic.message": "از این پس اگر کسی در این موضوع پست بگذارد، شما آگاه خواهید شد.", "not_following_topic.message": "شما این موضوع را تو فهرست موضوعات خوانده نشده می‌بینید، اما وقتی پست جدیدی ارسال می‌شود آگاه‌سازی دریافت نمی‌کنید.", @@ -131,8 +114,5 @@ "stale.warning": "موضوعی که شما در حال پاسخگویی به آن هستید قدیمی می باشد. آیا میلید به جای آن یک موضوع جدید ایجاد کنید و در آن به این موضوع ارجاع دهید؟", "stale.create": "ایجاد یک موضوع جدید", "stale.reply_anyway": "در هر صورت می خواهم به این موضوع پاسخ دهم", - "link_back": "پاسخ: [%1](%2)", - "spam": "اسپم", - "offensive": "توهین آمیز", - "custom-flag-reason": "وارد کردن دلیل پرچمگذاری" + "link_back": "پاسخ: [%1](%2)" } \ No newline at end of file diff --git a/public/language/fa-IR/user.json b/public/language/fa-IR/user.json index 98ffef7085..0c57c4f7a8 100644 --- a/public/language/fa-IR/user.json +++ b/public/language/fa-IR/user.json @@ -33,6 +33,7 @@ "chat": "چت", "chat_with": "ادامه چت با %1", "new_chat_with": "شروع چت جدید با %1", + "flag-profile": "Flag Profile", "follow": "دنبال کن", "unfollow": "دنبال نکن", "more": "بیشتر", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "پاک کردن عکس بارگذاری شده", "upload_cover_picture": "بارگذاری عکس کاور", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "تنظیمات", "show_email": "نمایش ایمیل‌های من", "show_fullname": "نام کامل من را نشان بده", diff --git a/public/language/fi/admin/menu.json b/public/language/fi/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/fi/admin/menu.json +++ b/public/language/fi/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/fi/admin/settings/uploads.json b/public/language/fi/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/fi/admin/settings/uploads.json +++ b/public/language/fi/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/fi/notifications.json b/public/language/fi/notifications.json index b10e43729c..2869a9e5e5 100644 --- a/public/language/fi/notifications.json +++ b/public/language/fi/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 flagged a post in %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 on vastannut viestiin: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/fi/topic.json b/public/language/fi/topic.json index 933c042445..73a74f1696 100644 --- a/public/language/fi/topic.json +++ b/public/language/fi/topic.json @@ -25,28 +25,11 @@ "link": "Linkitä", "share": "Jaa", "tools": "Työkalut", - "flag": "Ilmianna", "locked": "Lukittu", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Ilmianna tämä viesti moderaattoreille", - "flag_success": "Tämä viesti ilmiannettiin moderaattoreille.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Tämä aihe on poistettu. Vain käyttäjät, joilla on aiheen hallintaoikeudet, voivat nähdä sen.", "following_topic.message": "Saat nyt ilmoituksen, kun joku kirjoittaa tähän aiheeseen.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/fi/user.json b/public/language/fi/user.json index c657c38b38..1495e20b8f 100644 --- a/public/language/fi/user.json +++ b/public/language/fi/user.json @@ -33,6 +33,7 @@ "chat": "Keskustele", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Seuraa", "unfollow": "Älä seuraa", "more": "More", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remove Uploaded Picture", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Asetukset", "show_email": "Näytä sähköpostiosoitteeni", "show_fullname": "Näytä koko nimeni", diff --git a/public/language/fr/admin/general/dashboard.json b/public/language/fr/admin/general/dashboard.json index 02ea6849a7..a4d59944f8 100644 --- a/public/language/fr/admin/general/dashboard.json +++ b/public/language/fr/admin/general/dashboard.json @@ -2,9 +2,9 @@ "forum-traffic": "Trafic du forum", "page-views": "Pages vues", "unique-visitors": "Visiteurs uniques", - "users": "Users", - "posts": "Posts", - "topics": "Topics", + "users": "Utilisateurs", + "posts": "Messages", + "topics": "Sujets", "page-views-last-month": "Pages vues le mois dernier", "page-views-this-month": "Pages vues ce mois-ci", "page-views-last-day": "Pages vues ces dernières 24 heures", @@ -23,11 +23,11 @@ "prerelease-warning": "

    Ceci est une version préliminaire de NodeBB. Des bugs inattendus peuvent se produire.

    ", "notices": "Informations", - "restart-not-required": "Restart not required", - "restart-required": "Restart required", - "search-plugin-installed": "Search Plugin installed", - "search-plugin-not-installed": "Search Plugin not installed", - "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", + "restart-not-required": "Pas de redémarrage nécessaire", + "restart-required": "Redémarrage requis", + "search-plugin-installed": "Recherche un plugin installé", + "search-plugin-not-installed": "Rechercher un plugin non installé", + "search-plugin-tooltip": "Installer un plugin de recherche depuis la page des plugins pour activer la fonctionnalité de recherche", "control-panel": "Contrôle du système", "reload": "Recharger", diff --git a/public/language/fr/admin/menu.json b/public/language/fr/admin/menu.json index c4fa00ba0c..4552354510 100644 --- a/public/language/fr/admin/menu.json +++ b/public/language/fr/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Utilisateurs", "manage/registration": "File d'inscription", "manage/groups": "Groupes", - "manage/flags": "Signalements", "manage/ip-blacklist": "Liste noire d'IPs", "section-settings": "Réglages", diff --git a/public/language/fr/admin/settings/uploads.json b/public/language/fr/admin/settings/uploads.json index d4b789766f..a03fbe3a4b 100644 --- a/public/language/fr/admin/settings/uploads.json +++ b/public/language/fr/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Autoriser les utilisateurs à télécharger des miniatures de sujet", "topic-thumb-size": "Miniature du sujet", "allowed-file-extensions": "Extensions de fichier autorisés", - "allowed-file-extensions-help": "Entrer une liste d'extensions autorisées, séparées par des virgules (par exemple : pdf, xls, doc).\n\\t\\t\\t\\t\\tUne liste vide signifie que toutes les extensions sont autorisés.", + "allowed-file-extensions-help": "Entrer une liste d’extensions de fichier séparés par une virgule (ex : pdf,xls,doc). Une liste vide signifie que toutes les extensions sont autorisées.", "profile-avatars": "Avatar", "allow-profile-image-uploads": "Autoriser les utilisateurs à télécharger des avatars", "convert-profile-image-png": "Convertir les avatars téléchargés au format PNG", @@ -25,4 +25,4 @@ "profile-covers": "Image de couverture", "default-covers": "Image de couverture par défaut", "default-covers-help": "Ajouter des images de couvertures par défaut séparées par des virgules pour les comptes n'ayant pas téléchargé d'image de couverture" -} \ No newline at end of file +} diff --git a/public/language/fr/notifications.json b/public/language/fr/notifications.json index e13aba7ee4..531b3d9273 100644 --- a/public/language/fr/notifications.json +++ b/public/language/fr/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 a signalé un message dans %2.", "user_flagged_post_in_dual": "%1 et %2 ont signalé un message dans %3", "user_flagged_post_in_multiple": "%1 et %2 autres on signalé un message dans %3", + "user_flagged_user": "%1 a signalé un profil utilisateur (%2)", + "user_flagged_user_dual": "%1 et %2 ont signalé un profil utilisateur (%3)", + "user_flagged_user_multiple": "%1 et %2 autres utilisateurs ont signalé un profil utilisateur (%3)", "user_posted_to": "%1 a répondu à : %2", "user_posted_to_dual": "%1 et %2 ont posté une réponse à : %3", "user_posted_to_multiple": "%1 et %2 autres ont posté une réponse à : %3", diff --git a/public/language/fr/topic.json b/public/language/fr/topic.json index 51dee037a4..80d6006ccb 100644 --- a/public/language/fr/topic.json +++ b/public/language/fr/topic.json @@ -25,28 +25,11 @@ "link": "Lien", "share": "Partager", "tools": "Outils", - "flag": "Signaler", "locked": "Verrouillé", "pinned": "Épinglé", "moved": "Déplacé", "bookmark_instructions": "Cliquez ici pour retourner au dernier message lu de ce fil.", "flag_title": "Signaler ce message à la modération", - "flag_success": "Ce message a bien été signalé aux modérateurs.", - "flag_manage_title": "Post signalé dans %1", - "flag_manage_history": "Historique des actions", - "flag_manage_no_history": "Aucun historique d'évènement à reporter", - "flag_manage_assignee": "Assigné à", - "flag_manage_state": "État", - "flag_manage_state_open": "Nouveau/Ouvert", - "flag_manage_state_wip": "En cours", - "flag_manage_state_resolved": "Résolu", - "flag_manage_state_rejected": "Rejeté", - "flag_manage_notes": "Notes partagées", - "flag_manage_update": "Mettre à jour l'état du signalement", - "flag_manage_history_assignee": "Assigné à %1", - "flag_manage_history_state": "État mis à jour à %1", - "flag_manage_history_notes": "Notes du signalement à jour", - "flag_manage_saved": "Détails du signalement à jour", "deleted_message": "Ce sujet a été supprimé. Seuls les utilisateurs avec les droits d'administration peuvent le voir.", "following_topic.message": "Vous recevrez désormais des notifications lorsque quelqu'un postera dans ce sujet.", "not_following_topic.message": "Vous verrez ce sujet dans la liste des sujets non-lus, mais vous ne recevrez pas de notification lorsque quelqu'un postera dans ce sujet.", @@ -131,8 +114,5 @@ "stale.warning": "Le sujet auquel vous répondez est assez ancien. Ne voudriez-vous pas créer un nouveau sujet à la place et placer une référence vers celui-ci dans votre réponse ?", "stale.create": "Créer un nouveau sujet", "stale.reply_anyway": "Répondre à ce sujet quand même", - "link_back": "Re : [%1](%2)", - "spam": "Spam", - "offensive": "Offensif", - "custom-flag-reason": "Entrez une raison pour laquelle vous signalez ce message" + "link_back": "Re : [%1](%2)" } \ No newline at end of file diff --git a/public/language/fr/user.json b/public/language/fr/user.json index 9b8dc1c50a..521789084c 100644 --- a/public/language/fr/user.json +++ b/public/language/fr/user.json @@ -33,6 +33,7 @@ "chat": "Discussion", "chat_with": "Continuer la discussion avec %1", "new_chat_with": "Commencer une nouvelle discussion avec %1", + "flag-profile": "Signaler le profil", "follow": "S'abonner", "unfollow": "Se désabonner", "more": "Plus", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Supprimer l'image envoyée", "upload_cover_picture": "Envoyer une image de couverture", "remove_cover_picture_confirm": "Êtes-vous sûr de vouloir supprimer l'image de couverture ?", + "crop_picture": "Découper l’image", + "upload_cropped_picture": "Découper et envoyer", "settings": "Paramètres", "show_email": "Afficher mon email", "show_fullname": "Afficher mon nom complet", diff --git a/public/language/gl/admin/menu.json b/public/language/gl/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/gl/admin/menu.json +++ b/public/language/gl/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/gl/admin/settings/uploads.json b/public/language/gl/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/gl/admin/settings/uploads.json +++ b/public/language/gl/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/gl/notifications.json b/public/language/gl/notifications.json index 326680a2fd..251f80feea 100644 --- a/public/language/gl/notifications.json +++ b/public/language/gl/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 reportou unha mensaxe en %2", "user_flagged_post_in_dual": "%1 e %2 reportaron a túa mensaxe en %3", "user_flagged_post_in_multiple": "%1 e outras %2 persoas reportaron unha mensaxe en %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 publicou unha resposta en: %2", "user_posted_to_dual": "%1 e %2 responderon a %3", "user_posted_to_multiple": "%1 e outras %2 persoas responderon a: %3", diff --git a/public/language/gl/topic.json b/public/language/gl/topic.json index 9b29bb6b69..88264a9730 100644 --- a/public/language/gl/topic.json +++ b/public/language/gl/topic.json @@ -25,28 +25,11 @@ "link": "Ligazón", "share": "Compartir", "tools": "Ferramentas", - "flag": "Reportar", "locked": "Pechado", "pinned": "Fixo", "moved": "Movido", "bookmark_instructions": "Pica aquí para volver á última mensaxe lida neste tema ", "flag_title": "Reportar esta mensaxe", - "flag_success": "Esta mensaxe foi reportada para moderación.", - "flag_manage_title": "Mensaxe reportada en %1", - "flag_manage_history": "Historial de accións", - "flag_manage_no_history": "Sen histórico de eventos", - "flag_manage_assignee": "Encargado", - "flag_manage_state": "Estado", - "flag_manage_state_open": "Novo/Abrir", - "flag_manage_state_wip": "En revisión", - "flag_manage_state_resolved": "Solucionado", - "flag_manage_state_rejected": "Rexeitado", - "flag_manage_notes": "Notas compartidas", - "flag_manage_update": "Actualizar estado do reporte", - "flag_manage_history_assignee": "Asignado a %1", - "flag_manage_history_state": "Estado actualizado a %1", - "flag_manage_history_notes": "Actualizar notas do reporte", - "flag_manage_saved": "Detalles do reporte actualizados", "deleted_message": "Este tema foi borrado. Só os usuarios con privilexios administrativos poden velo.", "following_topic.message": "Agora recibirás notificacións cando alguén publique neste tema.", "not_following_topic.message": "Poderás ver este tema na lista de No Lidos, pero non recibirás notificacións cando alguén escriba nel.", @@ -131,8 +114,5 @@ "stale.warning": "O tema no que queres publicar é bastante vello. Queres crear un novo tema no seu lugar e incluir unha referencia a este na túa mensaxe?", "stale.create": "Crear un novo tema", "stale.reply_anyway": "Publicar neste tema de tódolos xeitos", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Ofensivo", - "custom-flag-reason": "Describe o motivo do reporte" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/gl/user.json b/public/language/gl/user.json index 6510e010b4..b40df23bca 100644 --- a/public/language/gl/user.json +++ b/public/language/gl/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Continuar a falar con %1", "new_chat_with": "Comezar a falar con %1", + "flag-profile": "Flag Profile", "follow": "Seguir", "unfollow": "Deixar de seguir", "more": "máis", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Borrar unha foto subida", "upload_cover_picture": "Subir imaxen de portada", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Opcións", "show_email": "Amosa-lo meu Email", "show_fullname": "Amosa-lo meu Nome Completo", diff --git a/public/language/he/admin/menu.json b/public/language/he/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/he/admin/menu.json +++ b/public/language/he/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/he/admin/settings/uploads.json b/public/language/he/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/he/admin/settings/uploads.json +++ b/public/language/he/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/he/notifications.json b/public/language/he/notifications.json index 134b173de0..447280cfdc 100644 --- a/public/language/he/notifications.json +++ b/public/language/he/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 דיווח על פוסט ב %2", "user_flagged_post_in_dual": "%1 ו%2 סימנו פוסט ב%3", "user_flagged_post_in_multiple": "%1 ו%2 נוספים סימנו פוסט ב%3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 פרסם תגובה ל: %2", "user_posted_to_dual": "%1 ו%2 הגיבו ל: %3", "user_posted_to_multiple": "%1 ו%2 אחרים הגיבו ל: %3", diff --git a/public/language/he/topic.json b/public/language/he/topic.json index 3e07544391..92b8df9090 100644 --- a/public/language/he/topic.json +++ b/public/language/he/topic.json @@ -25,28 +25,11 @@ "link": "לינק", "share": "שתף", "tools": "כלים", - "flag": "דווח", "locked": "נעול", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "דווח על פוסט זה למנהל", - "flag_success": "התקבל דיווח על פוסט זה.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "נושא זה נמחק. רק משתמשים עם ההרשאות המתאימות יכולים לצפות בו.", "following_topic.message": "מעתה, תקבל הודעות כאשר מישהו יעלה פוסט לנושא זה.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "הנושא בו אתה מגיב הוא דיי ישן. האם ברצונך לפתוח נושא חדש, ולהזכיר את הנושא הזה בתגובתך?", "stale.create": "צור נושא חדש", "stale.reply_anyway": "הגב לנושא זה בכל מקרה", - "link_back": "תגובה: [%1](%2)", - "spam": "ספאם", - "offensive": "פוגעני", - "custom-flag-reason": "הכנס סיבה מסמנת" + "link_back": "תגובה: [%1](%2)" } \ No newline at end of file diff --git a/public/language/he/user.json b/public/language/he/user.json index 7528b0465f..9d6e5e8c55 100644 --- a/public/language/he/user.json +++ b/public/language/he/user.json @@ -33,6 +33,7 @@ "chat": "צ'אט", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "עקוב", "unfollow": "הפסק לעקוב", "more": "עוד", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "מחק את התמונה שהועלתה", "upload_cover_picture": "העלה תמונת נושא", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "הגדרות", "show_email": "פרסם את כתובת האימייל שלי", "show_fullname": "הצג את שמי המלא", diff --git a/public/language/hu/admin/menu.json b/public/language/hu/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/hu/admin/menu.json +++ b/public/language/hu/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/hu/admin/settings/uploads.json b/public/language/hu/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/hu/admin/settings/uploads.json +++ b/public/language/hu/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/hu/notifications.json b/public/language/hu/notifications.json index 5694137dd4..defc23b945 100644 --- a/public/language/hu/notifications.json +++ b/public/language/hu/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 flagged a post in %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 has posted a reply to: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/hu/topic.json b/public/language/hu/topic.json index ce2aa8b817..9c912a38b1 100644 --- a/public/language/hu/topic.json +++ b/public/language/hu/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Megosztás", "tools": "Eszközök", - "flag": "Jelentés", "locked": "Locked", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "A hozzászólás jelentése a moderátoroknál", - "flag_success": "This post has been flagged for moderation.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "This topic has been deleted. Only users with topic management privileges can see it.", "following_topic.message": "You will now be receiving notifications when somebody posts to this topic.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/hu/user.json b/public/language/hu/user.json index 808dbc70e1..d0e3db3a43 100644 --- a/public/language/hu/user.json +++ b/public/language/hu/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Chat folytatása %1 felhasználóval", "new_chat_with": "Új chat indítása %1 felhasználóval", + "flag-profile": "Flag Profile", "follow": "Követés", "unfollow": "Nem követem", "more": "Több", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Feltöltött kép eltávolítása", "upload_cover_picture": "Címlap kép feltöltése", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Beállítások", "show_email": "E-mail címem mutatása", "show_fullname": "A teljes nevem mutatása", diff --git a/public/language/id/admin/menu.json b/public/language/id/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/id/admin/menu.json +++ b/public/language/id/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/id/admin/settings/uploads.json b/public/language/id/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/id/admin/settings/uploads.json +++ b/public/language/id/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/id/notifications.json b/public/language/id/notifications.json index f0d1954715..d68159db2d 100644 --- a/public/language/id/notifications.json +++ b/public/language/id/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 menandai sebuah posting di %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 telah mengirim sebuah balasan kepada: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/id/topic.json b/public/language/id/topic.json index d12a3c81d5..45d4476707 100644 --- a/public/language/id/topic.json +++ b/public/language/id/topic.json @@ -25,28 +25,11 @@ "link": "Tautan", "share": "Bagikan", "tools": "Perangkat", - "flag": "Tandai", "locked": "Terkunci", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Tandai posting ini untuk moderasi", - "flag_success": "Posting ini telah ditandai untuk moderasi", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Topik ini telah dihapus. Hanya pengguna dengan hak manajemen topik yang dapat melihatnya.", "following_topic.message": "Saat ini kamu akan menerima pemberitahuan saat seseorang membuat posting di dalam topik ini.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/id/user.json b/public/language/id/user.json index 1334b53d8f..bc5bcfd0f8 100644 --- a/public/language/id/user.json +++ b/public/language/id/user.json @@ -33,6 +33,7 @@ "chat": "Percakapan", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Ikuti", "unfollow": "Tinggalkan", "more": "More", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remove Uploaded Picture", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Pengaturan", "show_email": "Tampilkan Email Saya", "show_fullname": "Tampilkan Nama Lengkap Saya", diff --git a/public/language/it/admin/menu.json b/public/language/it/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/it/admin/menu.json +++ b/public/language/it/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/it/admin/settings/uploads.json b/public/language/it/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/it/admin/settings/uploads.json +++ b/public/language/it/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/it/notifications.json b/public/language/it/notifications.json index 82fa25deec..a3f72fae22 100644 --- a/public/language/it/notifications.json +++ b/public/language/it/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 ha segnalato un post in %2", "user_flagged_post_in_dual": "%1 e %2 hanno segnalato un post in %3", "user_flagged_post_in_multiple": "%1 ed altri %2 hanno segnalato un post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 ha postato una risposta a: %2", "user_posted_to_dual": "%1 e %2 hanno postato una risposta su: %3", "user_posted_to_multiple": "%1 ed altri %2 hanno postato una risposta su: %3", diff --git a/public/language/it/topic.json b/public/language/it/topic.json index a33a961a84..e4024d1884 100644 --- a/public/language/it/topic.json +++ b/public/language/it/topic.json @@ -25,28 +25,11 @@ "link": "Collegamento", "share": "Condividi", "tools": "Strumenti", - "flag": "Segnala", "locked": "Bloccato", "pinned": "Appeso", "moved": "Spostato", "bookmark_instructions": "Clicca qui per tornare all'ultimo post letto in questa discussione.", "flag_title": "Segnala questo post per la moderazione", - "flag_success": "Questo post è stato contrassegnato per la moderazione.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Questa discussione è stata cancellata. Solo gli utenti con diritti di gestione possono vederla.", "following_topic.message": "Da ora riceverai notifiche quando qualcuno posterà in questa discussione.", "not_following_topic.message": "Vedrai questa discussione nella lista delle discussioni non lette, ma non riceverai notifiche quando qualcuno risponde a questa discussione.", @@ -131,8 +114,5 @@ "stale.warning": "Il topic al quale stai rispondendo è abbastanza vecchio. Vorresti piuttosto creare un nuovo topic in riferimento a questo nella tua risposta?", "stale.create": "Crea una nuova discussione", "stale.reply_anyway": "Rispondi comunque a questa discussione", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensivo", - "custom-flag-reason": "Inserisci il motivo per flaggare" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/it/user.json b/public/language/it/user.json index 10a35fa433..1ff23922ac 100644 --- a/public/language/it/user.json +++ b/public/language/it/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Continua la chat con %1", "new_chat_with": "Inizia una nuova chat con %1", + "flag-profile": "Flag Profile", "follow": "Segui", "unfollow": "Smetti di seguire", "more": "Altro", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Elimina foto caricata", "upload_cover_picture": "Carica immagine di copertina", "remove_cover_picture_confirm": "Sei sicuro di voler eliminare l'immagine di copertina?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Impostazioni", "show_email": "Mostra la mia Email", "show_fullname": "Mostra il mio nome completo", diff --git a/public/language/ja/admin/menu.json b/public/language/ja/admin/menu.json index 904ea0bcc8..fab17aa4dd 100644 --- a/public/language/ja/admin/menu.json +++ b/public/language/ja/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "ユーザー", "manage/registration": "登録キュー", "manage/groups": "グループ", - "manage/flags": "フラグ", "manage/ip-blacklist": "IPブラックリスト", "section-settings": "設定", diff --git a/public/language/ja/admin/settings/uploads.json b/public/language/ja/admin/settings/uploads.json index d5520e2603..f980ea8bac 100644 --- a/public/language/ja/admin/settings/uploads.json +++ b/public/language/ja/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "ユーザーがスレッドのサムネイルをアップロードできるようにする", "topic-thumb-size": "スレッドのサムネイルの大きさ", "allowed-file-extensions": "ファイル拡張子が有効になりました。", - "allowed-file-extensions-help": "ここにファイル拡張子のカンマ区切りリストを入力します(例: pdf、xls、doc )。\n\\t\\t\\t\\t\\t空リストは、すべての拡張が許可されていることを意味します。", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "プロフィールの顔写真", "allow-profile-image-uploads": "ユーザーがプロフィール画像をアップロードできるようにする。", "convert-profile-image-png": "プロフィール画像のアップロードをPNGに変換する", @@ -25,4 +25,4 @@ "profile-covers": "プロフィールのカバー", "default-covers": "デフォルトのカバー画像", "default-covers-help": "アップロードされたカバー画像を持たないアカウントのカンマ区切りのデフォルト表紙画像を追加する" -} \ No newline at end of file +} diff --git a/public/language/ja/notifications.json b/public/language/ja/notifications.json index e525f8a638..a90c665158 100644 --- a/public/language/ja/notifications.json +++ b/public/language/ja/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1%2 の投稿にフラグを付けました。", "user_flagged_post_in_dual": "%1%2%3 の投稿にフラグを立てました。", "user_flagged_post_in_multiple": "%1 と %2 または他のユーザーが投稿 %3にフラグをつけました。", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1さんは %2に返信しました。", "user_posted_to_dual": "%1%2 は、返信しました: %3", "user_posted_to_multiple": "%1 と %2 または他のユーザーが返信しました: %3", diff --git a/public/language/ja/topic.json b/public/language/ja/topic.json index 8856d6ed93..52b5984d33 100644 --- a/public/language/ja/topic.json +++ b/public/language/ja/topic.json @@ -25,28 +25,11 @@ "link": "リンク", "share": "シェア", "tools": "ツール", - "flag": "フラグ", "locked": "ロック", "pinned": "ピンされた", "moved": "移動しました", "bookmark_instructions": "ここをクリックすると、このスレッドの最後に読んでいた投稿へ移動します。", "flag_title": "問題を報告する", - "flag_success": "この投稿をリポートしました。", - "flag_manage_title": "%1 の投稿にフラグをつけました", - "flag_manage_history": "活動履歴", - "flag_manage_no_history": "報告できるイベント履歴はありません", - "flag_manage_assignee": "譲受人", - "flag_manage_state": "状態", - "flag_manage_state_open": "新規/開く", - "flag_manage_state_wip": "進行中の作業", - "flag_manage_state_resolved": "解決済み", - "flag_manage_state_rejected": "拒否済", - "flag_manage_notes": "共有されたノート", - "flag_manage_update": "フラグの状態を更新", - "flag_manage_history_assignee": "%1が割り当てられました", - "flag_manage_history_state": "%1に更新された状態", - "flag_manage_history_notes": "フラグのメモが更新されました", - "flag_manage_saved": "フラグの詳細が更新されました", "deleted_message": "このスレッドが削除されました。スレッド管理権を持っているユーザーにしか読めません。", "following_topic.message": "このスレッドが更新された際に通知を受け取ります。", "not_following_topic.message": "あなたはスレッド一覧を未読にすると、このスレッドを参照できます。ただし誰かがこのスレッドに投稿したときは通知を受信できません。", @@ -131,8 +114,5 @@ "stale.warning": "あなたが返信しようとしてるスレッドが古いスレッドです。新しいスレッドを作って、そしてこのスレッドが参考として入れた方を勧めます。そうしますか?", "stale.create": "新しいスレッドを作ります。", "stale.reply_anyway": "とにかく、このスレッドに返信します", - "link_back": "返信: [%1](%2)", - "spam": "スパム", - "offensive": "攻撃", - "custom-flag-reason": "フラグを入れた理由" + "link_back": "返信: [%1](%2)" } \ No newline at end of file diff --git a/public/language/ja/user.json b/public/language/ja/user.json index e573a94005..78cf9324c2 100644 --- a/public/language/ja/user.json +++ b/public/language/ja/user.json @@ -33,6 +33,7 @@ "chat": "チャット", "chat_with": "%1とチャットを続ける", "new_chat_with": "%1とチャットを始める", + "flag-profile": "Flag Profile", "follow": "フォロー", "unfollow": "フォロー解除", "more": "つづき", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "アップした写真を取り消します", "upload_cover_picture": "カバー写真をアップロード", "remove_cover_picture_confirm": "カバー写真を削除してもよろしいですか?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "設定", "show_email": "メールアドレスを表示", "show_fullname": "フルネームで表示", diff --git a/public/language/ko/admin/menu.json b/public/language/ko/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/ko/admin/menu.json +++ b/public/language/ko/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/ko/admin/settings/uploads.json b/public/language/ko/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/ko/admin/settings/uploads.json +++ b/public/language/ko/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/ko/notifications.json b/public/language/ko/notifications.json index a6c9dd68e6..7086f01fa4 100644 --- a/public/language/ko/notifications.json +++ b/public/language/ko/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1님이 %2의 게시물을 신고했습니다.", "user_flagged_post_in_dual": "%1 님과 %2 님이 %3 안의 게시물에 플래그를 세웠습니다.", "user_flagged_post_in_multiple": "%1 님과 %2 명의 다른 유저들이 %3 안의 게시물에 플래그를 세웠습니다.", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1님이 %2에 답글을 작성했습니다.", "user_posted_to_dual": "%1 님과 %2 님이 %3 에 답글을 달았습니다.", "user_posted_to_multiple": "%1 님과 %2 명의 다른 유저들이 %3 에 답글을 달았습니다.", diff --git a/public/language/ko/topic.json b/public/language/ko/topic.json index ab12f8bb11..66e1709af7 100644 --- a/public/language/ko/topic.json +++ b/public/language/ko/topic.json @@ -25,28 +25,11 @@ "link": "링크", "share": "공유", "tools": "도구", - "flag": "신고", "locked": "잠김", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "이 스레드에서 읽은 마지막 게시글로 이동하시려면 여기를 클릭하세요.", "flag_title": "이 게시물을 신고", - "flag_success": "이 게시물은 신고되었습니다.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "이 주제는 삭제되었습니다. 주제 관리 권한이 있는 사용자만 볼 수 있습니다.", "following_topic.message": "이제 이 주제에 새 답글이 달리면 알림을 받습니다.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "현재 답글을 작성중인 주제가 꽤 오래되었습니다. 새로 주제를 생성하시고 이글을 인용하시겠습니까?", "stale.create": "새로운 주제를 작성", "stale.reply_anyway": "아무튼 이 주제에 답변해주세요.", - "link_back": "답글: [%1](%2)", - "spam": "스팸", - "offensive": "공격적인", - "custom-flag-reason": "신고 사유를 입력하세요." + "link_back": "답글: [%1](%2)" } \ No newline at end of file diff --git a/public/language/ko/user.json b/public/language/ko/user.json index 68bd356579..f33875aaaa 100644 --- a/public/language/ko/user.json +++ b/public/language/ko/user.json @@ -33,6 +33,7 @@ "chat": "채팅", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "팔로우", "unfollow": "팔로우 취소", "more": "더 보기", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "등록된 사진을 삭제", "upload_cover_picture": "커버 사진 업로드", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "설정", "show_email": "이메일 공개", "show_fullname": "실명 공개", diff --git a/public/language/lt/admin/menu.json b/public/language/lt/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/lt/admin/menu.json +++ b/public/language/lt/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/lt/admin/settings/uploads.json b/public/language/lt/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/lt/admin/settings/uploads.json +++ b/public/language/lt/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/lt/notifications.json b/public/language/lt/notifications.json index 1e8f1b20bf..e67ffb0c19 100644 --- a/public/language/lt/notifications.json +++ b/public/language/lt/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1pagrįso nuomone čia %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 parašė atsaką %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/lt/topic.json b/public/language/lt/topic.json index 6cb1219347..521404a4b4 100644 --- a/public/language/lt/topic.json +++ b/public/language/lt/topic.json @@ -25,28 +25,11 @@ "link": "Nuoroda", "share": "Dalintis", "tools": "Įrankiai", - "flag": "Pažymėti", "locked": "Užrakinta", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Pažymėti ši pranešimą moderatoriams", - "flag_success": "Šis pranešimas buvo pažymėtas moderatorių patikrinimui.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Ši tema buvo ištrinta. Tik Vartotojai su temos redagavimo privilegijomis gali matyti ja", "following_topic.message": "Dabar jūs gausite pranešimus kai kas nors atrašys šioje temoje.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/lt/user.json b/public/language/lt/user.json index eebcf85b8f..2255264355 100644 --- a/public/language/lt/user.json +++ b/public/language/lt/user.json @@ -33,6 +33,7 @@ "chat": "Susirašinėti", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Sekti", "unfollow": "Nesekti", "more": "Daugiau", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Ištrinti paveikslėlį", "upload_cover_picture": "Įkelti viršelio nuotrauką", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Nustatymai", "show_email": "Rodyti mano el. paštą viešai", "show_fullname": "Rodyti mano vardą ir pavardę", diff --git a/public/language/ms/admin/menu.json b/public/language/ms/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/ms/admin/menu.json +++ b/public/language/ms/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/ms/admin/settings/uploads.json b/public/language/ms/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/ms/admin/settings/uploads.json +++ b/public/language/ms/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/ms/notifications.json b/public/language/ms/notifications.json index 722b7f3482..29243fda49 100644 --- a/public/language/ms/notifications.json +++ b/public/language/ms/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 menanda kiriman anda di %2", "user_flagged_post_in_dual": "%1 dan %2 telah menanda kiriman anda pada %3", "user_flagged_post_in_multiple": "%1 dan %2 lagi telah menanda kiriman anda pada %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 telah membalas kiriman kepada: %2", "user_posted_to_dual": "%1 dan %2 membalas kiriman : %3", "user_posted_to_multiple": "%1 dan %2 lagu membalas kiriman: %3", diff --git a/public/language/ms/topic.json b/public/language/ms/topic.json index 2e932a66bd..e6e377c2a5 100644 --- a/public/language/ms/topic.json +++ b/public/language/ms/topic.json @@ -25,28 +25,11 @@ "link": "Pautan", "share": "Kongsi", "tools": "Perkakas", - "flag": "Tanda", "locked": "Kunci", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Tanda kiriman ini untuk diselia", - "flag_success": "Kiriman ini telah ditandakan untuk diselia", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Topik ini telah dipadam. Hanya pengguna dengan kuasa pengurusan boleh melihatnya.", "following_topic.message": "Anda akan menerima makluman apabila ada kiriman ke dalam topik ini", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "Topik yang anda nak balas agak lapuk. Adakah anda ingin buka topik baru dan rujukkan topik ini dalam balasan anda?", "stale.create": "Buka topik baru", "stale.reply_anyway": "Tetap balas topik ini", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Menyinggung", - "custom-flag-reason": "Nyatakan alasan anda" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/ms/user.json b/public/language/ms/user.json index be4f7de2b2..b6ebe15400 100644 --- a/public/language/ms/user.json +++ b/public/language/ms/user.json @@ -33,6 +33,7 @@ "chat": "Bersembang", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Ikuti", "unfollow": "Henti mengikuti", "more": "Lagi", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Buang Gambar Yang Dimuatnaik", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Tetapan", "show_email": "Tunjukkan emel saya", "show_fullname": "Tunjukkan Nama Penuh", diff --git a/public/language/nb/admin/menu.json b/public/language/nb/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/nb/admin/menu.json +++ b/public/language/nb/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/nb/admin/settings/uploads.json b/public/language/nb/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/nb/admin/settings/uploads.json +++ b/public/language/nb/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/nb/notifications.json b/public/language/nb/notifications.json index f9580f623c..724940606b 100644 --- a/public/language/nb/notifications.json +++ b/public/language/nb/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 har flagget et innlegg i %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 har skrevet et svar til: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/nb/topic.json b/public/language/nb/topic.json index 6ec1db0f41..e21ff2b0a8 100644 --- a/public/language/nb/topic.json +++ b/public/language/nb/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Del", "tools": "Verktøy", - "flag": "Rapporter", "locked": "Låst", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Rapporter dette innlegget for granskning", - "flag_success": "Dette innlegget har blitt rapportert.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Dette emnet har blitt slettet. Bare brukere med emnehåndterings-privilegier kan se den.", "following_topic.message": "Du vil nå motta varsler når noen skriver i denne tråden.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/nb/user.json b/public/language/nb/user.json index 8f81e82466..0400d23623 100644 --- a/public/language/nb/user.json +++ b/public/language/nb/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Følg", "unfollow": "Avfølg", "more": "Mer", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Fjern Opplastet Bilde", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Innstillinger", "show_email": "Vis min e-post", "show_fullname": "Vis mitt fulle navn", diff --git a/public/language/nl/admin/menu.json b/public/language/nl/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/nl/admin/menu.json +++ b/public/language/nl/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/nl/admin/settings/uploads.json b/public/language/nl/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/nl/admin/settings/uploads.json +++ b/public/language/nl/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/nl/notifications.json b/public/language/nl/notifications.json index c1efb52f43..1cde811989 100644 --- a/public/language/nl/notifications.json +++ b/public/language/nl/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 rapporteerde een bericht in %2", "user_flagged_post_in_dual": "%1 en %2 rapporteerde een bericht in %3", "user_flagged_post_in_multiple": "%1 en %2 andere rapporteede een bericht in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 heeft een reactie geplaatst in %2", "user_posted_to_dual": "%1 en %2 hebben een reactie geplaatst in: %3", "user_posted_to_multiple": "%1 en %2 hebben een reactie geplaatst in: %3", diff --git a/public/language/nl/topic.json b/public/language/nl/topic.json index 94a652d728..832f8fe5dd 100644 --- a/public/language/nl/topic.json +++ b/public/language/nl/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Delen", "tools": "Extra", - "flag": "Markeren", "locked": "Gesloten", "pinned": "Pinned", "moved": "Verplaatst", "bookmark_instructions": "Klik hier om terug te keren naar de laatst gelezen post in deze thread.", "flag_title": "Bericht aan beheerders melden", - "flag_success": "Dit bericht is gerapporteerd aan de beheerder.", - "flag_manage_title": "Gemarkeerd bericht in %1", - "flag_manage_history": "Activiteiten geschiedenis", - "flag_manage_no_history": "Geen geschiedenis te tonen", - "flag_manage_assignee": "Toekenning", - "flag_manage_state": "Staat", - "flag_manage_state_open": "Nieuw/Open", - "flag_manage_state_wip": "Wordt aan gewerkt", - "flag_manage_state_resolved": "Opgelost", - "flag_manage_state_rejected": "Afgewezen", - "flag_manage_notes": "Gedeelde notities", - "flag_manage_update": "Markering updaten", - "flag_manage_history_assignee": "Toegewezen aan %1", - "flag_manage_history_state": "Update status naar 1%", - "flag_manage_history_notes": "Update gemarkeerde notities", - "flag_manage_saved": "Markeering details geupdatet", "deleted_message": "Dit onderwerp is verwijderd. Alleen gebruikers met beheerrechten op onderwerpniveau kunnen dit inzien.", "following_topic.message": "Vanaf nu worden meldingen ontvangen zodra iemand een reactie op dit onderwerp geeft.", "not_following_topic.message": "Dit onderwerp zal verschijnen in de lijst van ongelezen onderwerpen, maar er zullen geen meldingen ontvangen zodra iemand een reactie op dit onderwerp geeft.", @@ -131,8 +114,5 @@ "stale.warning": "Het onderwerp waar je op antwoord is vrij oud. Zou je graag een nieuw onderwerp maken met een referentie naar dit onderwerp in je antwoord?", "stale.create": "Maak een nieuw onderwerp", "stale.reply_anyway": "Reageer toch op dit onderwerp", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Aanstootgevend", - "custom-flag-reason": "Geef een reden voor de melding." + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/nl/user.json b/public/language/nl/user.json index 22e0d6a947..1e6b49c38d 100644 --- a/public/language/nl/user.json +++ b/public/language/nl/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Chat verder met %1", "new_chat_with": "Begin een chat met %1", + "flag-profile": "Flag Profile", "follow": "Volgen", "unfollow": "Ontvolgen", "more": "Meer", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Verwijder gëuploade foto", "upload_cover_picture": "Upload je coverafbeelding", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Instellingen", "show_email": "E-mailadres weergeven", "show_fullname": "Laat mijn volledige naam zien", diff --git a/public/language/pl/admin/menu.json b/public/language/pl/admin/menu.json index 4c2f6b4b53..6b86f47e50 100644 --- a/public/language/pl/admin/menu.json +++ b/public/language/pl/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Użytkownicy", "manage/registration": "Kolejka Rejestracji", "manage/groups": "Grupy", - "manage/flags": "Flagi", "manage/ip-blacklist": "Czarna Lista IP", "section-settings": "Ustawienia", diff --git a/public/language/pl/admin/settings/uploads.json b/public/language/pl/admin/settings/uploads.json index cf0414fdab..9a610fb576 100644 --- a/public/language/pl/admin/settings/uploads.json +++ b/public/language/pl/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/pl/notifications.json b/public/language/pl/notifications.json index e9a6ecaf7e..7f8abea58a 100644 --- a/public/language/pl/notifications.json +++ b/public/language/pl/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 oflagował Twój post w %2", "user_flagged_post_in_dual": "%1 oraz %2 oflagowali post w %3", "user_flagged_post_in_multiple": "%1 oraz %2 innych oflagowali post w %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 dodał odpowiedź do %2", "user_posted_to_dual": "%1 oraz %2 dodali odpowiedzi do %3", "user_posted_to_multiple": "%1 oraz %2 innych dodali odpowiedzi do %3", diff --git a/public/language/pl/topic.json b/public/language/pl/topic.json index e821a3f114..2e380a2dee 100644 --- a/public/language/pl/topic.json +++ b/public/language/pl/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Udostępnij", "tools": "Narzędzia", - "flag": "Zgłoś", "locked": "Zablokowany", "pinned": "Przypięte", "moved": "Przeniesione", "bookmark_instructions": "Kliknij tutaj, by powrócić do ostatniego przeczytanego postu w tym wątku.", "flag_title": "Zgłoś post do moderacji", - "flag_success": "Ten post został oznaczony do moderacji.", - "flag_manage_title": "Oflagowanych postów do %1", - "flag_manage_history": "Historia wykonanych akcji", - "flag_manage_no_history": "Brak historii eventów ", - "flag_manage_assignee": "Beneficjant", - "flag_manage_state": "Stan", - "flag_manage_state_open": "Nowy/Otwarty", - "flag_manage_state_wip": "W trakcie prac", - "flag_manage_state_resolved": "Zdecydowany", - "flag_manage_state_rejected": "Odrzucono", - "flag_manage_notes": "Udostępniono notki", - "flag_manage_update": "Zaktualizowano status oflagowanych postów", - "flag_manage_history_assignee": "Przypisane do %1", - "flag_manage_history_state": "Zaktualizowano stan do %1", - "flag_manage_history_notes": "Zaktualizowano notki oflagowanych postów", - "flag_manage_saved": "Zaktualizowano oflagowane posty", "deleted_message": "Ten temat został skasowany. Tylko użytkownicy z uprawnieniami do zarządzania mogą go zobaczyć.", "following_topic.message": "Będziesz od teraz otrzymywał powiadomienia, gdy ktoś odpowie w tym temacie.", "not_following_topic.message": "Zobaczysz ten temat na liście nieprzeczytanych, ale nie otrzymasz żadnego powiadomienia dotyczącego tego tematu.", @@ -131,8 +114,5 @@ "stale.warning": "Wątek, na który chcesz udzielić odpowiedzi, jest przestarzały. Czy nie chciałbyś utworzyć nowego tematu, zamiast udzielać się w tym?", "stale.create": "Stwórz nowy temat", "stale.reply_anyway": "Odpowiedź na ten temat mimo tego", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Obraźliwy", - "custom-flag-reason": "Wprowadź powód oznaczenia" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/pl/user.json b/public/language/pl/user.json index ffdaf8b073..c4ba5ed631 100644 --- a/public/language/pl/user.json +++ b/public/language/pl/user.json @@ -33,6 +33,7 @@ "chat": "Rozmawiaj", "chat_with": "Kontynuuj rozmowę z %1", "new_chat_with": "Rozpocznij rozmowę z %1", + "flag-profile": "Flag Profile", "follow": "Śledź", "unfollow": "Przestań śledzić", "more": "Więcej", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Usuń Przesłane Zdjęcie", "upload_cover_picture": "Prześlij zdjęcie tła", "remove_cover_picture_confirm": "Czy jesteś pewny, że chcesz usunąć zdjęcie okładki?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Ustawienia", "show_email": "Wyświetlaj mój adres e-mail", "show_fullname": "Wyświetlaj moją pełną nazwę", diff --git a/public/language/pt-BR/admin/menu.json b/public/language/pt-BR/admin/menu.json index 24891a317b..e47f627ac5 100644 --- a/public/language/pt-BR/admin/menu.json +++ b/public/language/pt-BR/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Usuários", "manage/registration": "Fila de Registro", "manage/groups": "Grupos", - "manage/flags": "Sinalizações", "manage/ip-blacklist": "Lista Negra de IPs", "section-settings": "Configurações", diff --git a/public/language/pt-BR/admin/settings/uploads.json b/public/language/pt-BR/admin/settings/uploads.json index 26699bfe62..8016a20720 100644 --- a/public/language/pt-BR/admin/settings/uploads.json +++ b/public/language/pt-BR/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Permitir usuários de enviar miniaturas de tópico", "topic-thumb-size": "Tamanho da Miniatura de Tópico", "allowed-file-extensions": "Extensões de Arquivo Permitidas", - "allowed-file-extensions-help": "Digite aqui uma lista de extensões de arquivo separada por vírgulas (e.g. pdf,xls,doc).\n\\t\\t\\t\\t\\tUma lista vazia significa que todas as extensões são permitidas.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Avatares de Perfil", "allow-profile-image-uploads": "Permitir usuários de enviar imagens de perfil", "convert-profile-image-png": "Converter imagens de perfil enviadas para PNG", @@ -25,4 +25,4 @@ "profile-covers": "Capas de Perfil", "default-covers": "Imagens de Capa Padrão", "default-covers-help": "Adicione uma lista separada por vírgulas de imagens de capa padrão para contas que não tenham enviado uma imagem de capa" -} \ No newline at end of file +} diff --git a/public/language/pt-BR/notifications.json b/public/language/pt-BR/notifications.json index 2ef1d95178..f189833c1d 100644 --- a/public/language/pt-BR/notifications.json +++ b/public/language/pt-BR/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 sinalizou um post em %2", "user_flagged_post_in_dual": "%1 e %2 sinalizaram um post em %3", "user_flagged_post_in_multiple": "%1 e %2 outros sinalizaram um post em %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 postou uma resposta para: %2", "user_posted_to_dual": "%1 e %2 postaram respostas para: %3", "user_posted_to_multiple": "%1 e %2 outros postaram respostas para: %3", diff --git a/public/language/pt-BR/topic.json b/public/language/pt-BR/topic.json index 14fa9c7826..b807b4fd09 100644 --- a/public/language/pt-BR/topic.json +++ b/public/language/pt-BR/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Compartilhar", "tools": "Ferramentas", - "flag": "Sinalizar", "locked": "Trancado", "pinned": "Afixado", "moved": "Movido", "bookmark_instructions": "Clique aqui para retornar ao último post lido neste tópico.", "flag_title": "Sinalizar este post para moderação", - "flag_success": "Este post foi sinalizado para ser moderado.", - "flag_manage_title": "Post sinalizado em %1", - "flag_manage_history": "Histórico de Atividades", - "flag_manage_no_history": "Nenhum histórico de eventos para mostrar", - "flag_manage_assignee": "Procurador", - "flag_manage_state": "Situação", - "flag_manage_state_open": "Novo/Aberto", - "flag_manage_state_wip": "Trabalho em Andamento", - "flag_manage_state_resolved": "Resolvido", - "flag_manage_state_rejected": "Rejeitado", - "flag_manage_notes": "Notas Compartilhadas", - "flag_manage_update": "Atualizar Status da Sinalização", - "flag_manage_history_assignee": "Procuração concedida para %1", - "flag_manage_history_state": "Situação atualizada para %1", - "flag_manage_history_notes": "Notas de sinalização atualizadas", - "flag_manage_saved": "Detalhes da Sinalização Atualizados", "deleted_message": "Este tópico foi deletado. Apenas usuários com privilégios de moderação de tópico podem vê-lo.", "following_topic.message": "Agora você receberá notificações quando alguém responder este tópico.", "not_following_topic.message": "Você verá este tópico na lista de tópicos não-lidos, mas você não receberá notificações quendo alguém posta no tópico.", @@ -131,8 +114,5 @@ "stale.warning": "O tópico que você está respondendo é bem antigo. Você gostaria de criar um novo tópico ao invés disso, e referenciá-lo em sua resposta?", "stale.create": "Criar um novo tópico", "stale.reply_anyway": "Responder à este tópico assim mesmo", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Ofensivo", - "custom-flag-reason": "Informe um motivo para a sinalização" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/pt-BR/user.json b/public/language/pt-BR/user.json index 0df550d5c7..d3e5415207 100644 --- a/public/language/pt-BR/user.json +++ b/public/language/pt-BR/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Continuar a conversa com %1", "new_chat_with": "Iniciar uma nova conversa com %1", + "flag-profile": "Flag Profile", "follow": "Seguir", "unfollow": "Deixar de Seguir", "more": "Mais", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remover Foto Enviada", "upload_cover_picture": "Fazer upload de imagem de capa ", "remove_cover_picture_confirm": "Tem certeza que deseja remover a imagem de capa?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Configurações", "show_email": "Mostrar Meu Email", "show_fullname": "Mostrar Meu Nome Completo", diff --git a/public/language/pt-PT/admin/menu.json b/public/language/pt-PT/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/pt-PT/admin/menu.json +++ b/public/language/pt-PT/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/pt-PT/admin/settings/uploads.json b/public/language/pt-PT/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/pt-PT/admin/settings/uploads.json +++ b/public/language/pt-PT/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/pt-PT/notifications.json b/public/language/pt-PT/notifications.json index c9b9fdd32a..434094d108 100644 --- a/public/language/pt-PT/notifications.json +++ b/public/language/pt-PT/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 sinalizou uma publicação em %2", "user_flagged_post_in_dual": "%1 e %2 sinalizaram uma publicação em %3", "user_flagged_post_in_multiple": "%1 e %2 outros utilizadores sinalizaram uma publicação em %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 publicou uma resposta a: %2", "user_posted_to_dual": "%1 e %2 publicaram respostas a: %3", "user_posted_to_multiple": "%1 e %2 outros utilizadores publicaram respostas a: %3", diff --git a/public/language/pt-PT/topic.json b/public/language/pt-PT/topic.json index e6e023174b..43bc1a5290 100644 --- a/public/language/pt-PT/topic.json +++ b/public/language/pt-PT/topic.json @@ -25,28 +25,11 @@ "link": "Ligação", "share": "Partilhar", "tools": "Ferramentas", - "flag": "Sinalizar", "locked": "Bloqueado", "pinned": "Afixado", "moved": "Movido", "bookmark_instructions": "Carrega aqui para voltares à última publicação lide assunto.", "flag_title": "Sinaliza esta publicação para moderação", - "flag_success": "Esta publicação foi sinalizada para moderação.", - "flag_manage_title": "Publicação sinalizada em %1", - "flag_manage_history": "Histórico de ação", - "flag_manage_no_history": "Não existe histórico de eventos para reportar", - "flag_manage_assignee": "Assinante", - "flag_manage_state": "Estado", - "flag_manage_state_open": "Novo/Abrir", - "flag_manage_state_wip": "Trabalho em progresso", - "flag_manage_state_resolved": "Resolvido", - "flag_manage_state_rejected": "Rejeitado", - "flag_manage_notes": "Notas partilhadas", - "flag_manage_update": "Atualiza o estado da sinalização", - "flag_manage_history_assignee": "Designado para %1", - "flag_manage_history_state": "Estado atualizado para %1", - "flag_manage_history_notes": "Notas da sinalização atualizadas", - "flag_manage_saved": "Detalhes de sinalização atualizados", "deleted_message": "Este tópico foi eliminado. Somente utilizadores com privilégios de manutenção do tópico podem vê-lo.", "following_topic.message": "A partir de agora receberás uma notificação sempre que alguém publicar neste tópico.", "not_following_topic.message": "Verás este tópico na lista de tópicos por ler mas não irás receber notificações quando alguém publicar neste tópico.", @@ -131,8 +114,5 @@ "stale.warning": "O tópico ao qual estás a responder é bastante antigo. Gostarias antes de criar um novo tópico e referir este na tua resposta?", "stale.create": "Criar um novo tópico", "stale.reply_anyway": "Responder a este tópico à mesma", - "link_back": "Referindo: [%1](%2)", - "spam": "Spam", - "offensive": "Ofensivo", - "custom-flag-reason": "Introduzir uma razão para a sinalização" + "link_back": "Referindo: [%1](%2)" } \ No newline at end of file diff --git a/public/language/pt-PT/user.json b/public/language/pt-PT/user.json index acff84f2de..10d919de39 100644 --- a/public/language/pt-PT/user.json +++ b/public/language/pt-PT/user.json @@ -33,6 +33,7 @@ "chat": "Conversa", "chat_with": "Continuar a conversa com %1", "new_chat_with": "Começa nova conversa com %1", + "flag-profile": "Flag Profile", "follow": "Segue", "unfollow": "Deixar de seguir", "more": "Mais", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remover imagem carregada", "upload_cover_picture": "Carregar fotografia de capa", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Definições", "show_email": "Mostrar o meu e-mail", "show_fullname": "Mostrar o meu nome completo", diff --git a/public/language/ro/admin/menu.json b/public/language/ro/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/ro/admin/menu.json +++ b/public/language/ro/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/ro/admin/settings/uploads.json b/public/language/ro/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/ro/admin/settings/uploads.json +++ b/public/language/ro/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/ro/notifications.json b/public/language/ro/notifications.json index ea8a0d2b06..341ac1f2d1 100644 --- a/public/language/ro/notifications.json +++ b/public/language/ro/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 a semnalizat un mesaj în %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 a postat un răspuns la: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/ro/topic.json b/public/language/ro/topic.json index fbeb287222..a09f54141c 100644 --- a/public/language/ro/topic.json +++ b/public/language/ro/topic.json @@ -25,28 +25,11 @@ "link": "Link", "share": "Distribuie", "tools": "Unelte", - "flag": "Semnalizează", "locked": "Închis", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Semnalizează acest mesaj pentru moderare", - "flag_success": "Acest mesaj a fost semnalizat pentru moderare.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Acest subiect a fost șters. Doar utilizatorii cu privilegii pentru moderarea subiectelor îl poate vedea.", "following_topic.message": "Vei primi notificări când cineva va posta un nou mesaj in acest subiect.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/ro/user.json b/public/language/ro/user.json index 467d27a931..47ad0ca252 100644 --- a/public/language/ro/user.json +++ b/public/language/ro/user.json @@ -33,6 +33,7 @@ "chat": "Conversație", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Urmărește", "unfollow": "Oprește urmărirea", "more": "Mai multe", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remove Uploaded Picture", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Setări", "show_email": "Arată adresa mea de email", "show_fullname": "Show My Full Name", diff --git a/public/language/ru/admin/menu.json b/public/language/ru/admin/menu.json index c465ecacce..07b7030f22 100644 --- a/public/language/ru/admin/menu.json +++ b/public/language/ru/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Пользователи", "manage/registration": "Очередь на регистрацию", "manage/groups": "Группы", - "manage/flags": "Жалобы", "manage/ip-blacklist": "Блокировка IP", "section-settings": "Настройки", diff --git a/public/language/ru/admin/settings/uploads.json b/public/language/ru/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/ru/admin/settings/uploads.json +++ b/public/language/ru/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/ru/notifications.json b/public/language/ru/notifications.json index dc128d5acc..40727a85f3 100644 --- a/public/language/ru/notifications.json +++ b/public/language/ru/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "Участник %1 пометил сообщение в %2", "user_flagged_post_in_dual": "Участники %1 и %2 пометили ваше сообщение в %3", "user_flagged_post_in_multiple": "Участник %1 и %2 других пометили ваше сообщение %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "Участник %1 ответил на запись: %2", "user_posted_to_dual": "Участники %1 и %2 ответили на вашу запись: %3", "user_posted_to_multiple": "Участник %1 и %2 других ответили на вашу запись: %3", diff --git a/public/language/ru/topic.json b/public/language/ru/topic.json index fd6f1a146a..fff5ccbfb3 100644 --- a/public/language/ru/topic.json +++ b/public/language/ru/topic.json @@ -25,28 +25,11 @@ "link": "Ссылка", "share": "Поделиться", "tools": "Настройки записи", - "flag": "Отметить", "locked": "Закрыт", "pinned": "Прикреплена", "moved": "Перемещена", "bookmark_instructions": "Нажмите здесь, чтобы вернуться к последнему прочитанному сообщению в этой теме.", "flag_title": "Отметить сообщение для модерирования", - "flag_success": "Это сообщение было помечено для модерации", - "flag_manage_title": "Отмеченные сообщения в %1", - "flag_manage_history": "История действий", - "flag_manage_no_history": "В отчёте нет событий", - "flag_manage_assignee": "Правоприемник", - "flag_manage_state": "Состояние", - "flag_manage_state_open": "Новое/Открытое", - "flag_manage_state_wip": "Рассматривается", - "flag_manage_state_resolved": "Подтверждено", - "flag_manage_state_rejected": "Отклонено", - "flag_manage_notes": "Коллективные заметки", - "flag_manage_update": "Обновить статус жалобы", - "flag_manage_history_assignee": "Назначено %1", - "flag_manage_history_state": "Статус обновлён на %1", - "flag_manage_history_notes": "Статус жалобы обновлен", - "flag_manage_saved": "Подробности жалобы обновлены", "deleted_message": "Эта тема была удалена. Только пользователи с правами управления темами могут ее видеть.", "following_topic.message": "Теперь вы будете получать уведомления при обновлении этой темы.", "not_following_topic.message": "Вы увидите эту тему в списке непрочитанных тем, но Вы не будете получать уведомления, когда кто-то напишет сообщение в эту тему.", @@ -131,8 +114,5 @@ "stale.warning": "Тема, в которую вы пишите, очень старая. Вы хотите создать новую тему?", "stale.create": "Создать новую тему", "stale.reply_anyway": "Всё равно ответить в этой теме", - "link_back": "Ответ: [%1](%2)", - "spam": "Спам", - "offensive": "Оскорбление", - "custom-flag-reason": "Введите другую причину" + "link_back": "Ответ: [%1](%2)" } \ No newline at end of file diff --git a/public/language/ru/user.json b/public/language/ru/user.json index a5906fc774..b04c04f9a4 100644 --- a/public/language/ru/user.json +++ b/public/language/ru/user.json @@ -33,6 +33,7 @@ "chat": "Чат", "chat_with": "Продолжить чат с %1", "new_chat_with": "Начать новый чат с %1", + "flag-profile": "Flag Profile", "follow": "Подписаться", "unfollow": "Отписаться", "more": "Больше", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Удалить фото", "upload_cover_picture": "Загрузить обложку профиля", "remove_cover_picture_confirm": "Вы уверены, что хотите удалить изображение обложки?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Настройки", "show_email": "Показывать мою элетронную почту", "show_fullname": "Показывать полное имя", diff --git a/public/language/rw/admin/menu.json b/public/language/rw/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/rw/admin/menu.json +++ b/public/language/rw/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/rw/admin/settings/uploads.json b/public/language/rw/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/rw/admin/settings/uploads.json +++ b/public/language/rw/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/rw/notifications.json b/public/language/rw/notifications.json index 26e3343ad1..9bc91ae6e3 100644 --- a/public/language/rw/notifications.json +++ b/public/language/rw/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 yatambikanye ikintu muri %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 yanditse kuri: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/rw/topic.json b/public/language/rw/topic.json index fec915e355..15a3b23e29 100644 --- a/public/language/rw/topic.json +++ b/public/language/rw/topic.json @@ -25,28 +25,11 @@ "link": "Shyiraho Umurongo", "share": "Sangiza", "tools": "Ibikoresho", - "flag": "Tambikana", "locked": "Birafungiranye", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Bimenyeshe ubuyobozi", - "flag_success": "Bimaze kumenyeshwa ubuyobozi ngo bikurikiranwe. ", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Iki kiganiro cyamaze gukurwaho. Abantu babifitiye uburenganzira ni bo bonyine bashobora kukibona. ", "following_topic.message": "Ntabwo uzongera kubimenyeshwa nihagira umuntu ugira icyo yandika kuri iki kiganiro. ", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "Ikiganiro ushaka kuvugaho cyarashaje. Wahitamo gutangiza ikiganiro gishya ariko wenda ukagaragaza kino mu gisubizo uza gushyiraho?", "stale.create": "Tangiza ikiganiro gishya", "stale.reply_anyway": "Vuga kuri iki kiganiro nubundi", - "link_back": "Igisubizo: [%1](%2)", - "spam": "Spam", - "offensive": "Ugukomeretsanya", - "custom-flag-reason": "Shyiramo impamvu yo gutambikana" + "link_back": "Igisubizo: [%1](%2)" } \ No newline at end of file diff --git a/public/language/rw/user.json b/public/language/rw/user.json index 868ab052c2..4c48fa09da 100644 --- a/public/language/rw/user.json +++ b/public/language/rw/user.json @@ -33,6 +33,7 @@ "chat": "Mu Gikari", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Kurikira", "unfollow": "Ntukurikire", "more": "Ibindi", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Kuraho Ifoto", "upload_cover_picture": "Pakira ifoto yo hejuru", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Itunganya", "show_email": "Hagaragazwe Email Yanjye", "show_fullname": "Hagaragazwe Izina Ryuzuye Ryanjye", diff --git a/public/language/sc/admin/menu.json b/public/language/sc/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/sc/admin/menu.json +++ b/public/language/sc/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/sc/admin/settings/uploads.json b/public/language/sc/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/sc/admin/settings/uploads.json +++ b/public/language/sc/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/sc/notifications.json b/public/language/sc/notifications.json index d92a4638cc..2629bb867b 100644 --- a/public/language/sc/notifications.json +++ b/public/language/sc/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 flagged a post in %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 has posted a reply to: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/sc/topic.json b/public/language/sc/topic.json index 07050c2c1c..41f6eb7fce 100644 --- a/public/language/sc/topic.json +++ b/public/language/sc/topic.json @@ -25,28 +25,11 @@ "link": "Acàpiu", "share": "Cumpartzi", "tools": "Ainas", - "flag": "Signala", "locked": "Locked", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "Signala custu arresonu pro sa moderatzione", - "flag_success": "This post has been flagged for moderation.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "This topic has been deleted. Only users with topic management privileges can see it.", "following_topic.message": "As a retzire notìficas si calincunu pùblica in custa arresonada.", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/sc/user.json b/public/language/sc/user.json index b30a2a031f..1a26d84fc2 100644 --- a/public/language/sc/user.json +++ b/public/language/sc/user.json @@ -33,6 +33,7 @@ "chat": "Tzarra", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Sighi", "unfollow": "Non sighes prus", "more": "More", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remove Uploaded Picture", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Sèberos", "show_email": "Ammustra s'Email Mia", "show_fullname": "Show My Full Name", diff --git a/public/language/sk/admin/menu.json b/public/language/sk/admin/menu.json index 35f5088443..0a1c30b63c 100644 --- a/public/language/sk/admin/menu.json +++ b/public/language/sk/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/sk/admin/settings/uploads.json b/public/language/sk/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/sk/admin/settings/uploads.json +++ b/public/language/sk/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/sk/notifications.json b/public/language/sk/notifications.json index 0b5ad76572..423c7cc1ea 100644 --- a/public/language/sk/notifications.json +++ b/public/language/sk/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 pridal značku na príspevok %2", "user_flagged_post_in_dual": "%1 a %2 pridali značky na príspevok %3", "user_flagged_post_in_multiple": "%1 a %2 ďalší pridali značku na príspevok:%3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 odpovedal: %2", "user_posted_to_dual": "%1 a %2 uverejnili odpoveď na:%3", "user_posted_to_multiple": "%1 a %2 ďalší uverejnili odpovede na:%3", diff --git a/public/language/sk/topic.json b/public/language/sk/topic.json index 28cbb130c1..7043b401ec 100644 --- a/public/language/sk/topic.json +++ b/public/language/sk/topic.json @@ -25,28 +25,11 @@ "link": "Odkaz", "share": "Zdieľaj", "tools": "Nástroje", - "flag": "Označiť", "locked": "Uzamknuté", "pinned": "Pripnuté", "moved": "Presunuté", "bookmark_instructions": "Kliknite sem pre návrat k poslednému prečítanému príspevku vo vlákne.", "flag_title": "Označiť príspevok pre zmiernenie", - "flag_success": "Tento príspevok bol označený na zmiernenie.", - "flag_manage_title": "Označený príspevok v %1", - "flag_manage_history": "História činností", - "flag_manage_no_history": "Žiadne história udalosti k nahláseniu", - "flag_manage_assignee": "Nástupca", - "flag_manage_state": "Vyhlásiť", - "flag_manage_state_open": "Nový/Otvoriť", - "flag_manage_state_wip": "Prebiehajú práce", - "flag_manage_state_resolved": "Vyriešené", - "flag_manage_state_rejected": "Odmietnuté", - "flag_manage_notes": "Zdieľané poznámky", - "flag_manage_update": "Aktualizovať stav značky", - "flag_manage_history_assignee": "Priradené k %1", - "flag_manage_history_state": "Aktualizovaná stáť pre %1", - "flag_manage_history_notes": "Značka poznámok aktualizovaná", - "flag_manage_saved": "Podrobnosti značky aktualizované", "deleted_message": "Táto téma bola odstránená. Iba užívatelia s výsadami správcu ju môžu vidieť.", "following_topic.message": "Odteraz budete prijímať oznámenia, keď niekto prispeje do tejto témy.", "not_following_topic.message": "Uvidíte túto tému v zozname neprečítaných tém, ale nebudete dostávať oznámenia, keď niekto pridá príspevok do tejto témy.", @@ -131,8 +114,5 @@ "stale.warning": "Téma na ktorú odpovedáte je pomerne stará. Chceli by ste vytvoriť novú tému namiesto tejto, a odkazovať na ňu vo Vašej odpovedi?", "stale.create": "Vytvoriť novú tému", "stale.reply_anyway": "Napriek tomu odpovedať na túto tému", - "link_back": "Re: [%1](%2)", - "spam": "Nevyžiadaná pošta", - "offensive": "Hnutie", - "custom-flag-reason": "Zadajte dôvod pre označenie" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/sk/user.json b/public/language/sk/user.json index c54901b60a..a0ea093b73 100644 --- a/public/language/sk/user.json +++ b/public/language/sk/user.json @@ -33,6 +33,7 @@ "chat": "Konverzácia", "chat_with": "Konverzácia s %1", "new_chat_with": "Začať novú konverzáciu s %1", + "flag-profile": "Flag Profile", "follow": "Nasledovať", "unfollow": "Prestať sledovať", "more": "Viac", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Vymazať nahraný obrázok", "upload_cover_picture": "Nahrať titulný obrázok", "remove_cover_picture_confirm": "Ste si naozaj istý, že chcete odstrániť titulný obrázok?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Nastavenia", "show_email": "Zobrazovať môj e-mail", "show_fullname": "Zobrazovať moje skutočné meno", diff --git a/public/language/sl/admin/menu.json b/public/language/sl/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/sl/admin/menu.json +++ b/public/language/sl/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/sl/admin/settings/uploads.json b/public/language/sl/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/sl/admin/settings/uploads.json +++ b/public/language/sl/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/sl/notifications.json b/public/language/sl/notifications.json index 5986a2115a..cf3bc5601c 100644 --- a/public/language/sl/notifications.json +++ b/public/language/sl/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1je označil/-a vašo objavo v %2.", "user_flagged_post_in_dual": "%1 in %2 sta označila/-a vašo objavo v %3.", "user_flagged_post_in_multiple": "%1 and %2 drugih je označilo vašo objavo v %3.", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 je objavil/-a odgovor na: %2.", "user_posted_to_dual": "%1 in %2 sta objavila/-i odgovor na: %3.", "user_posted_to_multiple": "%1 in %2 drugih je objavilo odgovor na: %3.", diff --git a/public/language/sl/topic.json b/public/language/sl/topic.json index 2714c29b67..faf5ff5ef2 100644 --- a/public/language/sl/topic.json +++ b/public/language/sl/topic.json @@ -25,28 +25,11 @@ "link": "Povezava", "share": "Deli", "tools": "Orodja", - "flag": "Označi", "locked": "Zaklenjeno", "pinned": "Pripeto", "moved": "Premaknjeno", "bookmark_instructions": "Klikni tukaj za vrnitev na zadnje prebrano objavo v tej niti", "flag_title": "Označi to objavo za vodenje", - "flag_success": "Ta objava je bila označena za vodenje.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Ta tema je bila izbrisana. Le uporabniki s pravicami upravljanja tem jo lahko vidijo.", "following_topic.message": "Če nekdo objavi v to temo, boste od sedaj dobivali obvestila. ", "not_following_topic.message": "To temo boste videli v seznamu neprebranih tem. Ne boste pa dobili obvestila, če bo nekdo objavil v tej temi. ", @@ -131,8 +114,5 @@ "stale.warning": "Tema na katero odgovarjaš je precej stara. A ne bi raje ustvaril novo temo namesto te, z sklicem na to v tvojem odgovoru?", "stale.create": "Ustvari novo temo", "stale.reply_anyway": "Vseeno odgovori na to temo", - "link_back": "Odg: [%1](%2)", - "spam": "Neželeno", - "offensive": "Žaljivo", - "custom-flag-reason": "Vstavi vzrok označevanja" + "link_back": "Odg: [%1](%2)" } \ No newline at end of file diff --git a/public/language/sl/user.json b/public/language/sl/user.json index 5d6ae2a9d7..5905feb481 100644 --- a/public/language/sl/user.json +++ b/public/language/sl/user.json @@ -33,6 +33,7 @@ "chat": "Klepet", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Spremljaj", "unfollow": "Ne spremljaj", "more": "Več", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Odstrani preneseno sliko ", "upload_cover_picture": "Prenesi fotografijo naslovnice", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Nastavitve", "show_email": "Pokaži moj e-poštni naslov.", "show_fullname": "Pokaži moj ime in priimek.", diff --git a/public/language/sr/admin/menu.json b/public/language/sr/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/sr/admin/menu.json +++ b/public/language/sr/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/sr/admin/settings/uploads.json b/public/language/sr/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/sr/admin/settings/uploads.json +++ b/public/language/sr/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/sr/notifications.json b/public/language/sr/notifications.json index 3b41edb510..b1e9761adb 100644 --- a/public/language/sr/notifications.json +++ b/public/language/sr/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 је означио поруку у %2", "user_flagged_post_in_dual": "%1 и %2 су означили поруку у %3", "user_flagged_post_in_multiple": "%1 и осталих %2 су означили поруку у %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 је послао нови одговор на: %2", "user_posted_to_dual": "%1 и %2 су одговорили на: %3", "user_posted_to_multiple": "%1 и %2 других су одговорили на: %3", diff --git a/public/language/sr/topic.json b/public/language/sr/topic.json index 44fb671866..d449f9d57c 100644 --- a/public/language/sr/topic.json +++ b/public/language/sr/topic.json @@ -25,28 +25,11 @@ "link": "Веза", "share": "Дели", "tools": "Алатке", - "flag": "Означи", "locked": "Закључано", "pinned": "Закачено", "moved": "Премештено", "bookmark_instructions": "Кликните овде за повратак на последњу прочитану поруку у овој теми.", "flag_title": "Означи ову поруку за модерацију", - "flag_success": "Ова порука је означена за модерацију.", - "flag_manage_title": "Означена порука у %1", - "flag_manage_history": "Историја радњи", - "flag_manage_no_history": "Нема историје догађаја за пријаву", - "flag_manage_assignee": "Заступник", - "flag_manage_state": "Стање", - "flag_manage_state_open": "Ново/Отвори", - "flag_manage_state_wip": "Рад у току", - "flag_manage_state_resolved": "Решено", - "flag_manage_state_rejected": "Одбијено", - "flag_manage_notes": "Дељене белешке", - "flag_manage_update": "Ажурирај статус ознаке", - "flag_manage_history_assignee": "Додељено %1", - "flag_manage_history_state": "Ажуриран статус %1", - "flag_manage_history_notes": "Белешке статуса су ажуриране", - "flag_manage_saved": "Детаљи статуса су ажурирани", "deleted_message": "Ова тема је избрисана. Само корисници са привилегијама управљања темама је могу видети.", "following_topic.message": "Од сада ће те примати обавештења када неко одговори у овој теми.", "not_following_topic.message": "Видећете ову тему у списку непрочитаних тема али нећете примати обавештења када неко одговори у њој.", @@ -131,8 +114,5 @@ "stale.warning": "Тема у којој желите да одговорите је сувише стара. Да ли желите да уместо тога креирате нову тему и упутите на ову у вашем одговору?", "stale.create": "Креирај нову тему", "stale.reply_anyway": "Одговори на ову тему у сваком случају", - "link_back": "Re: [%1](%2)", - "spam": "Непожељно", - "offensive": "Увредљиво", - "custom-flag-reason": "Унесите разлог означавања" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/sr/user.json b/public/language/sr/user.json index c25b641603..4eb21c474e 100644 --- a/public/language/sr/user.json +++ b/public/language/sr/user.json @@ -33,6 +33,7 @@ "chat": "Ђаскање", "chat_with": "Настави ћаскање са %1", "new_chat_with": "Започни ново ћаскање са %1", + "flag-profile": "Flag Profile", "follow": "Прати", "unfollow": "Не прати", "more": "Више", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Уклоните отпремљену слику", "upload_cover_picture": "Отпреми насловну слику", "remove_cover_picture_confirm": "Да ли сте сигурни да желите да уклоните насловну слику?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Подешавања", "show_email": "Прикажи моју лозинку", "show_fullname": "Прикажи моје пуно име", diff --git a/public/language/sv/admin/menu.json b/public/language/sv/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/sv/admin/menu.json +++ b/public/language/sv/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/sv/admin/settings/uploads.json b/public/language/sv/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/sv/admin/settings/uploads.json +++ b/public/language/sv/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/sv/notifications.json b/public/language/sv/notifications.json index 53f94b6b3a..5236999f3f 100644 --- a/public/language/sv/notifications.json +++ b/public/language/sv/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 flaggade ett inlägg i %2", "user_flagged_post_in_dual": "%1 och %2 rapporterade ett inlägg i %3", "user_flagged_post_in_multiple": "%1 och %2 andra rapporterade ett inlägg i %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 har skrivit ett svar på: %2", "user_posted_to_dual": "%1 och %2 har svarat på: %3", "user_posted_to_multiple": "%1 och %2 andra har svarat på: %3", diff --git a/public/language/sv/topic.json b/public/language/sv/topic.json index b1e56a95f9..a451adf9d9 100644 --- a/public/language/sv/topic.json +++ b/public/language/sv/topic.json @@ -25,28 +25,11 @@ "link": "Länk", "share": "Dela", "tools": "Verktyg", - "flag": "Rapportera", "locked": "Låst", "pinned": "Fäst", "moved": "Flyttad", "bookmark_instructions": "Klicka här för att återgå till senast lästa inlägg i detta ämne.", "flag_title": "Rapportera detta inlägg för granskning", - "flag_success": "Det här inlägget har flaggats för moderering.", - "flag_manage_title": "Inlägg flaggad i %1", - "flag_manage_history": "Händelse historia", - "flag_manage_no_history": "Inga händelser att rapportera", - "flag_manage_assignee": "Tilldelad", - "flag_manage_state": "Status", - "flag_manage_state_open": "Ny/Öppen", - "flag_manage_state_wip": "Pågående arbete", - "flag_manage_state_resolved": "Löst", - "flag_manage_state_rejected": "Avvisad", - "flag_manage_notes": "Delade anteckningar", - "flag_manage_update": "Uppdatera flag Status", - "flag_manage_history_assignee": "Tilldelad till %1", - "flag_manage_history_state": "Uppdaterade status till %1", - "flag_manage_history_notes": "Uppdaterade flag anteckningar", - "flag_manage_saved": "Flag detaljer uppdaterad", "deleted_message": "Det här ämnet har raderats. Endast användare med ämneshanterings-privilegier kan se det.", "following_topic.message": "Du kommer nu få notiser när någon gör inlägg i detta ämne.", "not_following_topic.message": "Du kommer att se det här ämnet i listan olästa ämnen, men du kommer inte att få meddelande när någon gör inlägg till detta ämne.", @@ -131,8 +114,5 @@ "stale.warning": "Ämnet du svarar på är ganska gammalt. Vill du skapa ett nytt ämne istället och inkludera en referens till det här ämnet i ditt inlägg?", "stale.create": "Skapa nytt ämne", "stale.reply_anyway": "Svara på ämnet ändå", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Kränkande", - "custom-flag-reason": "Ange skälet för rapporteringen" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/sv/user.json b/public/language/sv/user.json index 9f3f6c3342..7025caca67 100644 --- a/public/language/sv/user.json +++ b/public/language/sv/user.json @@ -33,6 +33,7 @@ "chat": "Chatta", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Följ", "unfollow": "Sluta följ", "more": "Mer", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Ta bort uppladdad bild", "upload_cover_picture": "Ladda upp omslagsbild", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Inställningar", "show_email": "Visa min e-postadress", "show_fullname": "Visa fullständigt namn", diff --git a/public/language/th/admin/menu.json b/public/language/th/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/th/admin/menu.json +++ b/public/language/th/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/th/admin/settings/uploads.json b/public/language/th/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/th/admin/settings/uploads.json +++ b/public/language/th/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/th/notifications.json b/public/language/th/notifications.json index 3d1e6d9866..f75223f772 100644 --- a/public/language/th/notifications.json +++ b/public/language/th/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 flagged a post in %2", "user_flagged_post_in_dual": "%1 and %2 flagged a post in %3", "user_flagged_post_in_multiple": "%1 and %2 others flagged a post in %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 has posted a reply to: %2", "user_posted_to_dual": "%1 and %2 have posted replies to: %3", "user_posted_to_multiple": "%1 and %2 others have posted replies to: %3", diff --git a/public/language/th/topic.json b/public/language/th/topic.json index a1abfb9e2a..aea99944ff 100644 --- a/public/language/th/topic.json +++ b/public/language/th/topic.json @@ -25,28 +25,11 @@ "link": "ลิงค์", "share": "แชร์", "tools": "เครื่องมือ", - "flag": "ปักธง", "locked": "Locked", "pinned": "Pinned", "moved": "Moved", "bookmark_instructions": "Click here to return to the last read post in this thread.", "flag_title": "ปักธงโพสต์นี้เพื่อดำเนินการ", - "flag_success": "This post has been flagged for moderation.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "Topic นี้ถูกลบไปแล้ว เฉพาะผู้ใช้งานที่มีสิทธิ์ในการจัดการ Topic เท่านั้นที่จะมีสิทธิ์ในการเข้าชม", "following_topic.message": "คุณจะได้รับการแจ้งเตือนเมื่อมีคนโพสต์ในกระทู้นี้", "not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.", @@ -131,8 +114,5 @@ "stale.warning": "The topic you are replying to is quite old. Would you like to create a new topic instead, and reference this one in your reply?", "stale.create": "Create a new topic", "stale.reply_anyway": "Reply to this topic anyway", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Offensive", - "custom-flag-reason": "Enter a flagging reason" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/th/user.json b/public/language/th/user.json index 968a909371..f42bf44168 100644 --- a/public/language/th/user.json +++ b/public/language/th/user.json @@ -33,6 +33,7 @@ "chat": "แชท", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "ติดตาม", "unfollow": "เลิกติดตาม", "more": "More", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Remove Uploaded Picture", "upload_cover_picture": "Upload cover picture", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "ตั้งค่า", "show_email": "แสดงอีเมล์", "show_fullname": "แสดงชื่อจริง", diff --git a/public/language/tr/admin/menu.json b/public/language/tr/admin/menu.json index d61ad44718..869d01e0d7 100644 --- a/public/language/tr/admin/menu.json +++ b/public/language/tr/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Kullanıcılar", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/tr/admin/settings/uploads.json b/public/language/tr/admin/settings/uploads.json index 5385404ac6..b83ea976ce 100644 --- a/public/language/tr/admin/settings/uploads.json +++ b/public/language/tr/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/tr/notifications.json b/public/language/tr/notifications.json index 5474cc8872..8ae2cbda19 100644 --- a/public/language/tr/notifications.json +++ b/public/language/tr/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 bir iletiyi bayrakladı. %2", "user_flagged_post_in_dual": " %1 ve %2 %3 gönderini bayrakladı", "user_flagged_post_in_multiple": "%1 ve %2 kişi daha %3 gönderini bayrakladı", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 %2 başlığına bir ileti gönderdi.", "user_posted_to_dual": "%1 ve %2 gönderine cevap verdi: %3", "user_posted_to_multiple": "%1 ve %2 kişi daha gönderine cevap verdi: %3", diff --git a/public/language/tr/topic.json b/public/language/tr/topic.json index 0fc68c3382..956579773c 100644 --- a/public/language/tr/topic.json +++ b/public/language/tr/topic.json @@ -25,28 +25,11 @@ "link": "Bağlantı", "share": "Paylaş", "tools": "Araçlar", - "flag": "Bayrak", "locked": "Kilitli", "pinned": "İğnelendi", "moved": "Taşındı", "bookmark_instructions": "Bu başlıkta en son kaldığın yere dönmek için tıklayın.", "flag_title": "Bu iletiyi moderatöre haber et", - "flag_success": "Bu ileti yöneticilere bildirildi.", - "flag_manage_title": "%1 ileti bayraklandı", - "flag_manage_history": "Hareket Tarihi", - "flag_manage_no_history": "Hiçbir olay geçmişi yok", - "flag_manage_assignee": "Vekil", - "flag_manage_state": "Bildir", - "flag_manage_state_open": "Yeni/Açık", - "flag_manage_state_wip": "Yapım Aşamasında", - "flag_manage_state_resolved": "Çözüldü", - "flag_manage_state_rejected": "Reddedildi", - "flag_manage_notes": "Paylaşılan Not", - "flag_manage_update": "Bayram Durumunu Güncelle", - "flag_manage_history_assignee": "%1 atandı", - "flag_manage_history_state": "%1 bildiri güncellendi", - "flag_manage_history_notes": "Bayrak notu güncellendi", - "flag_manage_saved": "Bayrak Detayları Güncellendi", "deleted_message": "Bu başlık silindi. Sadece başlık düzenleme yetkisi olan kullanıcılar görebilir.", "following_topic.message": "Artık bir kullanıcı bu başlığa ileti gönderdiğinde bildirim alacaksınız.", "not_following_topic.message": "Bu başlığı okunmamışlarda göreceksiniz ama biri bir şey yazdığında bildirim gelmeyecek.", @@ -131,8 +114,5 @@ "stale.warning": "Yanıtlamak istediğin konu oldukca eskidir. Bu konuya referans oluşturacak yeni bir konu oluşturmak ister misin?", "stale.create": "Yeni bir başlık yarat", "stale.reply_anyway": "Bu konuyu cevapla", - "link_back": "Re: [%1](%2)", - "spam": "Gereksiz", - "offensive": "Saldırgan", - "custom-flag-reason": "Şikayetinizin nedenini girin" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/tr/user.json b/public/language/tr/user.json index 2b808ba266..00d4ddad09 100644 --- a/public/language/tr/user.json +++ b/public/language/tr/user.json @@ -33,6 +33,7 @@ "chat": "Sohbet", "chat_with": "%1 ile sohbete devam et", "new_chat_with": "%1 ile yeni sohbete başla", + "flag-profile": "Flag Profile", "follow": "Takip Et", "unfollow": "Takip etme", "more": "Daha Fazla", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Yüklenmiş fotoğrafı kaldır", "upload_cover_picture": "Kapak fotoğrafı yükle", "remove_cover_picture_confirm": "Kapak görselini silmek istediğinden emin misin?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Ayarlar", "show_email": "E-postamı göster", "show_fullname": "Tam ismimi göster", diff --git a/public/language/vi/admin/menu.json b/public/language/vi/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/vi/admin/menu.json +++ b/public/language/vi/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/vi/admin/settings/uploads.json b/public/language/vi/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/vi/admin/settings/uploads.json +++ b/public/language/vi/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/vi/notifications.json b/public/language/vi/notifications.json index 8433a1353d..747e7562e8 100644 --- a/public/language/vi/notifications.json +++ b/public/language/vi/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 gắn cờ 1 bài trong %2", "user_flagged_post_in_dual": "%1%2 đã gắn cờ một bài viết trong %3", "user_flagged_post_in_multiple": "%1 và %2 người khác đã gắn cờ bài viết của bạn trong %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 đã trả lời %2", "user_posted_to_dual": "%1%2 đã trả lời: %3", "user_posted_to_multiple": "%1 và %2 người khác đã trả lời: %3", diff --git a/public/language/vi/topic.json b/public/language/vi/topic.json index 6ef833d39e..855701e667 100644 --- a/public/language/vi/topic.json +++ b/public/language/vi/topic.json @@ -25,28 +25,11 @@ "link": "Đường dẫn", "share": "Chia sẻ", "tools": "Công cụ", - "flag": "Gắn cờ", "locked": "Khóa", "pinned": "Đã ghim", "moved": "Chuyển đi", "bookmark_instructions": "Bấm vào đây để quay về đọc bài viết mới nhất trong chủ đề này.", "flag_title": "Flag bài viết này để chỉnh sửa", - "flag_success": "Chủ đề này đã được flag để chỉnh sửa", - "flag_manage_title": "Bài viết bị gắn cờ trong %1", - "flag_manage_history": "Lịch sử hoạt động", - "flag_manage_no_history": "Không có lịch sử sự kiện nào", - "flag_manage_assignee": "Người giao việc", - "flag_manage_state": "Trạng thái", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Công việc đang thực thi", - "flag_manage_state_resolved": "Đã hoàn thành", - "flag_manage_state_rejected": "Đã từ chối", - "flag_manage_notes": "Những ghi chú được chia sẻ", - "flag_manage_update": "Cập nhật trạng thái gắn c", - "flag_manage_history_assignee": "Đã giao cho %1", - "flag_manage_history_state": "Cập nhật trạng thái thành %1", - "flag_manage_history_notes": "Đã cập nhật ghi chú gắn c", - "flag_manage_saved": "Đã cập nhật nội dung gắn c", "deleted_message": "Chủ đề này đã bị xóa. Chỉ ban quản trị mới xem được.", "following_topic.message": "Từ giờ bạn sẽ nhận được thông báo khi có ai đó gửi bài viết trong chủ đề này", "not_following_topic.message": "Bạn có thể xem chủ đề này trong danh sách chủ đề chưa xem, nhưng bạn sẽ không nhận thông báo khi có ai đó đăng bài viết trong chủ đề này", @@ -131,8 +114,5 @@ "stale.warning": "Chủ đề bạn đang trả lời đã khá cũ. Bạn có muốn tạo chủ đề mới, và liên kết với chủ đề hiện tại trong bài viết trả lời của bạn?", "stale.create": "Tạo chủ đề mới", "stale.reply_anyway": "Trả lời chủ đề này", - "link_back": "Re: [%1](%2)", - "spam": "Spam", - "offensive": "Phản cảm", - "custom-flag-reason": "Nhập lý do bị gắn cờ" + "link_back": "Re: [%1](%2)" } \ No newline at end of file diff --git a/public/language/vi/user.json b/public/language/vi/user.json index d46f4f139f..cfbf45eea9 100644 --- a/public/language/vi/user.json +++ b/public/language/vi/user.json @@ -33,6 +33,7 @@ "chat": "Chat", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "Theo dõi", "unfollow": "Hủy theo dõi", "more": "Xem thêm", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "Xoá ảnh đã tải lên", "upload_cover_picture": "Tải ảnh bìa lên", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "Thiết lập", "show_email": "Hiện Email của tôi", "show_fullname": "Hiện tên đầy đủ", diff --git a/public/language/zh-CN/admin/general/dashboard.json b/public/language/zh-CN/admin/general/dashboard.json index 72c80aa352..923a573b3f 100644 --- a/public/language/zh-CN/admin/general/dashboard.json +++ b/public/language/zh-CN/admin/general/dashboard.json @@ -2,9 +2,9 @@ "forum-traffic": "论坛流量", "page-views": "PV 数量", "unique-visitors": "单一访客", - "users": "Users", - "posts": "Posts", - "topics": "Topics", + "users": "用户", + "posts": "发帖", + "topics": "主题", "page-views-last-month": "上个月 PV 数量", "page-views-this-month": "本月 PV 数量", "page-views-last-day": "过去24小时 PV 数量", @@ -23,11 +23,11 @@ "prerelease-warning": "

    正在使用测试版 NodeBB。可能会出现意外的 Bug。

    ", "notices": "提醒", - "restart-not-required": "Restart not required", - "restart-required": "Restart required", - "search-plugin-installed": "Search Plugin installed", - "search-plugin-not-installed": "Search Plugin not installed", - "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", + "restart-not-required": "不需要重启", + "restart-required": "需要重启", + "search-plugin-installed": "已安装搜索插件", + "search-plugin-not-installed": "未安装搜索插件", + "search-plugin-tooltip": "在插件页面安装搜索插件来激活搜索功能", "control-panel": "系统控制", "reload": "重载", diff --git a/public/language/zh-CN/admin/menu.json b/public/language/zh-CN/admin/menu.json index 989ea89170..1a6771b20e 100644 --- a/public/language/zh-CN/admin/menu.json +++ b/public/language/zh-CN/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "用户", "manage/registration": "注册队列", "manage/groups": "用户组", - "manage/flags": "举报", "manage/ip-blacklist": "IP 黑名单", "section-settings": "设置", diff --git a/public/language/zh-CN/admin/settings/uploads.json b/public/language/zh-CN/admin/settings/uploads.json index ca9f92012e..6c52e63b11 100644 --- a/public/language/zh-CN/admin/settings/uploads.json +++ b/public/language/zh-CN/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "允许用户上传主题缩略图", "topic-thumb-size": "主题缩略图大小", "allowed-file-extensions": "允许的文件扩展名", - "allowed-file-extensions-help": "在这里输入以逗号分隔的文件扩展名(例如:pdf,xls,doc)。\n填写空意味着所有扩展名是允许的。", + "allowed-file-extensions-help": "在此处输入以逗号分隔的文件扩展名列表 (例如 pdf,xls,doc )。 为空则表示允许所有扩展名。", "profile-avatars": "个人头像", "allow-profile-image-uploads": "允许用户上传个人资料照片", "convert-profile-image-png": "转换个人资料图片为 PNG", @@ -25,4 +25,4 @@ "profile-covers": "资料封面", "default-covers": "默认封面图片", "default-covers-help": "为没有上传封面图片的帐户添加以逗号分隔的默认封面图片" -} \ No newline at end of file +} diff --git a/public/language/zh-CN/notifications.json b/public/language/zh-CN/notifications.json index 30dc07854d..39f6acb3a1 100644 --- a/public/language/zh-CN/notifications.json +++ b/public/language/zh-CN/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1%2 标记了一个帖子", "user_flagged_post_in_dual": "%1%2%3 标记了一个帖子", "user_flagged_post_in_multiple": "%1 和 %2 个其他人在 %3 标记了一个帖子", + "user_flagged_user": "%1 举报了 (%2) 的用户资料", + "user_flagged_user_dual": "%1%2 举报了 (%3) 的用户资料", + "user_flagged_user_multiple": "%1 和其他 %2 人举报了 (%3) 的用户资料", "user_posted_to": "%1 回复了:%2", "user_posted_to_dual": "%1%2 回复了: %3", "user_posted_to_multiple": "%1 和 %2 个其他人回复了: %3", diff --git a/public/language/zh-CN/topic.json b/public/language/zh-CN/topic.json index ec9d3a7242..c44ef9292f 100644 --- a/public/language/zh-CN/topic.json +++ b/public/language/zh-CN/topic.json @@ -25,28 +25,11 @@ "link": "链接", "share": "分享", "tools": "工具", - "flag": "举报", "locked": "已锁定", "pinned": "已固定", "moved": "已移动", "bookmark_instructions": "点击阅读本主题帖中的最新回复", "flag_title": "举报此帖", - "flag_success": "已举报此回帖。", - "flag_manage_title": "在 1% 中已举报的帖子", - "flag_manage_history": "操作历史", - "flag_manage_no_history": "没有事件历史可汇报", - "flag_manage_assignee": "代理人", - "flag_manage_state": "状态", - "flag_manage_state_open": "新建/打开", - "flag_manage_state_wip": "正在处理", - "flag_manage_state_resolved": "已解决", - "flag_manage_state_rejected": "已拒绝", - "flag_manage_notes": "共享的笔记", - "flag_manage_update": "更新标记状态", - "flag_manage_history_assignee": "已指派给 %1", - "flag_manage_history_state": "更新状态到 1%", - "flag_manage_history_notes": "更新标记笔记", - "flag_manage_saved": "举报详情已更新", "deleted_message": "此主题已被删除。只有拥有主题管理权限的用户可以查看。", "following_topic.message": "当有人回复此主题时,您会收到通知。", "not_following_topic.message": "您将在未读主题列表中看到这个主题,但您不会在帖子被回复时收到通知。", @@ -131,8 +114,5 @@ "stale.warning": "您回复的主题已经非常老了。开个新帖,然后在新帖中引用这个老帖的内容,可以吗?", "stale.create": "创建新主题", "stale.reply_anyway": "仍然回复此帖", - "link_back": "回复: [%1](%2)", - "spam": "垃圾帖", - "offensive": "人身攻击", - "custom-flag-reason": "输入举报原因" + "link_back": "回复: [%1](%2)" } \ No newline at end of file diff --git a/public/language/zh-CN/user.json b/public/language/zh-CN/user.json index ec8ce2a270..30a707014c 100644 --- a/public/language/zh-CN/user.json +++ b/public/language/zh-CN/user.json @@ -33,6 +33,7 @@ "chat": "聊天", "chat_with": "继续与 %1 聊天", "new_chat_with": "开始与 %1 的新会话", + "flag-profile": "举报资料", "follow": "关注", "unfollow": "取消关注", "more": "更多", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "删除已上传的头像", "upload_cover_picture": "上传封面图片", "remove_cover_picture_confirm": "您确定要移除封面图片吗?", + "crop_picture": "剪裁图片", + "upload_cropped_picture": "剪裁并上传", "settings": "设置", "show_email": "显示我的电子邮箱", "show_fullname": "显示我的全名", diff --git a/public/language/zh-TW/admin/advanced/cache.json b/public/language/zh-TW/admin/advanced/cache.json index 5a954f1232..52db0c3668 100644 --- a/public/language/zh-TW/admin/advanced/cache.json +++ b/public/language/zh-TW/admin/advanced/cache.json @@ -1,11 +1,11 @@ { - "post-cache": "Post Cache", - "posts-in-cache": "Posts in Cache", - "average-post-size": "Average Post Size", - "length-to-max": "Length / Max", - "percent-full": "%1% Full", - "post-cache-size": "Post Cache Size", - "items-in-cache": "Items in Cache", - "control-panel": "Control Panel", - "update-settings": "Update Cache Settings" + "post-cache": "文章快取", + "posts-in-cache": "暫存中的文章", + "average-post-size": "平均文章大小", + "length-to-max": "長度 / 最大", + "percent-full": "%1% 已滿", + "post-cache-size": "文章快取大小", + "items-in-cache": "暫存中的項目", + "control-panel": "控制面板", + "update-settings": "更新快取設定" } \ No newline at end of file diff --git a/public/language/zh-TW/admin/advanced/database.json b/public/language/zh-TW/admin/advanced/database.json index f7db6220ee..860a040b3d 100644 --- a/public/language/zh-TW/admin/advanced/database.json +++ b/public/language/zh-TW/admin/advanced/database.json @@ -1,35 +1,35 @@ { "x-b": "%1 b", "x-mb": "%1 mb", - "uptime-seconds": "Uptime in Seconds", - "uptime-days": "Uptime in Days", + "uptime-seconds": "正常運作秒數", + "uptime-days": "正常運作天數", "mongo": "Mongo", - "mongo.version": "MongoDB Version", - "mongo.storage-engine": "Storage Engine", - "mongo.collections": "Collections", - "mongo.objects": "Objects", - "mongo.avg-object-size": "Avg. Object Size", - "mongo.data-size": "Data Size", - "mongo.storage-size": "Storage Size", - "mongo.index-size": "Index Size", - "mongo.file-size": "File Size", - "mongo.resident-memory": "Resident Memory", - "mongo.virtual-memory": "Virtual Memory", - "mongo.mapped-memory": "Mapped Memory", - "mongo.raw-info": "MongoDB Raw Info", + "mongo.version": "MongoDB 版本", + "mongo.storage-engine": "儲存引擎", + "mongo.collections": "收集", + "mongo.objects": "物件", + "mongo.avg-object-size": "平均物件大小", + "mongo.data-size": "資料大小", + "mongo.storage-size": "儲存大小", + "mongo.index-size": "索引大小", + "mongo.file-size": "檔案大小", + "mongo.resident-memory": "常駐記憶體", + "mongo.virtual-memory": "虛擬記憶體", + "mongo.mapped-memory": "映射記憶體", + "mongo.raw-info": "MongoDB 原始資訊", "redis": "Redis", - "redis.version": "Redis Version", - "redis.connected-clients": "Connected Clients", - "redis.connected-slaves": "Connected Slaves", - "redis.blocked-clients": "Blocked Clients", - "redis.used-memory": "Used Memory", - "redis.memory-frag-ratio": "Memory Fragmentation Ratio", - "redis.total-connections-recieved": "Total Connections Received", - "redis.total-commands-processed": "Total Commands Processed", - "redis.iops": "Instantaneous Ops. Per Second", - "redis.keyspace-hits": "Keyspace Hits", - "redis.keyspace-misses": "Keyspace Misses", - "redis.raw-info": "Redis Raw Info" + "redis.version": "Redis 版本", + "redis.connected-clients": "已連接的用戶端", + "redis.connected-slaves": "已連接的從屬端", + "redis.blocked-clients": "已阻擋的用戶端", + "redis.used-memory": "已使用的記憶體", + "redis.memory-frag-ratio": "記憶體碎片比例", + "redis.total-connections-recieved": "已接收的連線數量", + "redis.total-commands-processed": "已處裡的命令數量", + "redis.iops": "每秒操作數量", + "redis.keyspace-hits": "鍵空間命中次數", + "redis.keyspace-misses": "鍵空間未命中次數", + "redis.raw-info": "Redis 原始資料" } \ No newline at end of file diff --git a/public/language/zh-TW/admin/advanced/errors.json b/public/language/zh-TW/admin/advanced/errors.json index 963e68b116..21fec31ea2 100644 --- a/public/language/zh-TW/admin/advanced/errors.json +++ b/public/language/zh-TW/admin/advanced/errors.json @@ -1,14 +1,14 @@ { - "figure-x": "Figure %1", - "error-events-per-day": "%1 events per day", - "error.404": "404 Not Found", - "error.503": "503 Service Unavailable", - "manage-error-log": "Manage Error Log", - "export-error-log": "Export Error Log (CSV)", - "clear-error-log": "Clear Error Log", - "route": "Route", - "count": "Count", - "no-routes-not-found": "Hooray! There are no routes that were not found.", - "clear404-confirm": "Are you sure you wish to clear the 404 error logs?", - "clear404-success": "\"404 Not Found\" errors cleared" + "figure-x": "表 %1", + "error-events-per-day": "%1 事件/天", + "error.404": "404 伺服器無法回應", + "error.503": "503 伺服器忙碌中", + "manage-error-log": "管理錯誤日誌", + "export-error-log": "匯出錯誤日誌 (CSV)", + "clear-error-log": "清除錯誤日誌", + "route": "路由", + "count": "計數", + "no-routes-not-found": "太好了!這裡沒有未找到的路由", + "clear404-confirm": "您確定要清除404錯誤日誌嗎?", + "clear404-success": "\"404 Not Found\" 錯誤已清除" } \ No newline at end of file diff --git a/public/language/zh-TW/admin/menu.json b/public/language/zh-TW/admin/menu.json index 6a4995ea6e..985c540e8a 100644 --- a/public/language/zh-TW/admin/menu.json +++ b/public/language/zh-TW/admin/menu.json @@ -13,7 +13,6 @@ "manage/users": "Users", "manage/registration": "Registration Queue", "manage/groups": "Groups", - "manage/flags": "Flags", "manage/ip-blacklist": "IP Blacklist", "section-settings": "Settings", diff --git a/public/language/zh-TW/admin/settings/group.json b/public/language/zh-TW/admin/settings/group.json index 1ae88c9cf5..acec8abd7c 100644 --- a/public/language/zh-TW/admin/settings/group.json +++ b/public/language/zh-TW/admin/settings/group.json @@ -1,12 +1,12 @@ { - "general": "General", - "private-groups": "Private Groups", - "private-groups.help": "If enabled, joining of groups requires the approval of the group owner (Default: enabled)", + "general": "一般", + "private-groups": "私人群組", + "private-groups.help": "如果開啟,加入群組需要經過群組擁有者批準 (預設: enabled)", "private-groups.warning": "Beware! If this option is disabled and you have private groups, they automatically become public.", - "allow-creation": "Allow Group Creation", - "allow-creation-help": "If enabled, users can create groups (Default: disabled)", - "max-name-length": "Maximum Group Name Length", - "cover-image": "Group Cover Image", - "default-cover": "Default Cover Images", + "allow-creation": "允許建立群組", + "allow-creation-help": "如果開啟,使用者可自行建立群組 (預設: disabled)", + "max-name-length": "群組最大名稱長度", + "cover-image": "群組封面圖像", + "default-cover": "預設封面圖像", "default-cover-help": "Add comma-separated default cover images for groups that don't have an uploaded cover image" } \ No newline at end of file diff --git a/public/language/zh-TW/admin/settings/notifications.json b/public/language/zh-TW/admin/settings/notifications.json index 4eff7f341a..6d4a1e4771 100644 --- a/public/language/zh-TW/admin/settings/notifications.json +++ b/public/language/zh-TW/admin/settings/notifications.json @@ -1,5 +1,5 @@ { - "notifications": "Notifications", - "welcome-notification": "Welcome Notification", - "welcome-notification-link": "Welcome Notification Link" + "notifications": "告示", + "welcome-notification": "歡迎告示", + "welcome-notification-link": "歡迎告示連結" } \ No newline at end of file diff --git a/public/language/zh-TW/admin/settings/sockets.json b/public/language/zh-TW/admin/settings/sockets.json index d04ee42fcf..37e7ce858f 100644 --- a/public/language/zh-TW/admin/settings/sockets.json +++ b/public/language/zh-TW/admin/settings/sockets.json @@ -1,6 +1,6 @@ { - "reconnection": "Reconnection Settings", - "max-attempts": "Max Reconnection Attempts", - "default-placeholder": "Default: %1", - "delay": "Reconnection Delay" + "reconnection": "重新連接設定", + "max-attempts": "最大重試次數", + "default-placeholder": "預設: %1", + "delay": "重新連接延遲時間" } \ No newline at end of file diff --git a/public/language/zh-TW/admin/settings/uploads.json b/public/language/zh-TW/admin/settings/uploads.json index 8a56c85663..35eaa5a58f 100644 --- a/public/language/zh-TW/admin/settings/uploads.json +++ b/public/language/zh-TW/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Allow users to upload topic thumbnails", "topic-thumb-size": "Topic Thumb Size", "allowed-file-extensions": "Allowed File Extensions", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc).\n\t\t\t\t\tAn empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", "profile-avatars": "Profile Avatars", "allow-profile-image-uploads": "Allow users to upload profile images", "convert-profile-image-png": "Convert profile image uploads to PNG", @@ -25,4 +25,4 @@ "profile-covers": "Profile Covers", "default-covers": "Default Cover Images", "default-covers-help": "Add comma-separated default cover images for accounts that don't have an uploaded cover image" -} \ No newline at end of file +} diff --git a/public/language/zh-TW/notifications.json b/public/language/zh-TW/notifications.json index 6028595b2f..3e96be1089 100644 --- a/public/language/zh-TW/notifications.json +++ b/public/language/zh-TW/notifications.json @@ -19,6 +19,9 @@ "user_flagged_post_in": "%1 標記了 %2裡的一個張貼。", "user_flagged_post_in_dual": "%1%2 標記一個張貼在 %3", "user_flagged_post_in_multiple": "%1 與 %2 其他人標記一個張貼在 %3", + "user_flagged_user": "%1 flagged a user profile (%2)", + "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", + "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", "user_posted_to": "%1 發布一個回覆給: %2", "user_posted_to_dual": "%1%2 已經張貼回覆到: %3", "user_posted_to_multiple": "%1 與 %2 其他人已經張貼回覆到: %3", diff --git a/public/language/zh-TW/topic.json b/public/language/zh-TW/topic.json index a9b4eb1c28..f3c4877f8f 100644 --- a/public/language/zh-TW/topic.json +++ b/public/language/zh-TW/topic.json @@ -25,28 +25,11 @@ "link": "鏈接", "share": "分享", "tools": "工具", - "flag": "檢舉", "locked": "已鎖定", "pinned": "釘住", "moved": "移動", "bookmark_instructions": "點擊這裡返回到這個討論串的最後一篇張貼文", "flag_title": "檢舉這篇文章, 交給仲裁者來審閱.", - "flag_success": "這文章已經被檢舉要求仲裁.", - "flag_manage_title": "Flagged post in %1", - "flag_manage_history": "Action History", - "flag_manage_no_history": "No event history to report", - "flag_manage_assignee": "Assignee", - "flag_manage_state": "State", - "flag_manage_state_open": "New/Open", - "flag_manage_state_wip": "Work in Progress", - "flag_manage_state_resolved": "Resolved", - "flag_manage_state_rejected": "Rejected", - "flag_manage_notes": "Shared Notes", - "flag_manage_update": "Update Flag Status", - "flag_manage_history_assignee": "Assigned to %1", - "flag_manage_history_state": "Updated state to %1", - "flag_manage_history_notes": "Updated flag notes", - "flag_manage_saved": "Flag Details Updated", "deleted_message": "此主題已被刪除。只有具有主題管理權限的使用者才能看到它。", "following_topic.message": "有人貼文回覆主題時, 你將會收到新通知.", "not_following_topic.message": "你將會看到這個主題在未讀主題列表中出現,但你將不會在其他人張貼到這個主題時接收到通知。", @@ -131,8 +114,5 @@ "stale.warning": "你正回覆的主題是非常舊的一篇。你想要改為建立一個新主題,然後參考到這篇你回覆的?", "stale.create": "建立新主題", "stale.reply_anyway": "無論如何都回覆這個主題", - "link_back": "回覆: [%1](%2)", - "spam": "灌水", - "offensive": "攻擊", - "custom-flag-reason": "輸入標記的理由" + "link_back": "回覆: [%1](%2)" } \ No newline at end of file diff --git a/public/language/zh-TW/user.json b/public/language/zh-TW/user.json index a67efa65b6..631a63d81c 100644 --- a/public/language/zh-TW/user.json +++ b/public/language/zh-TW/user.json @@ -33,6 +33,7 @@ "chat": "聊天", "chat_with": "Continue chat with %1", "new_chat_with": "Start new chat with %1", + "flag-profile": "Flag Profile", "follow": "跟隨", "unfollow": "取消跟隨", "more": "更多", @@ -64,6 +65,8 @@ "remove_uploaded_picture": "移除上傳的圖片", "upload_cover_picture": "上傳封面圖片", "remove_cover_picture_confirm": "Are you sure you want to remove the cover picture?", + "crop_picture": "Crop picture", + "upload_cropped_picture": "Crop and upload", "settings": "設定", "show_email": "顯示我的電子郵件地址", "show_fullname": "顯示我的全名", From 387110fecc89f535055249411d8f4421554836e0 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 8 Feb 2017 18:23:34 +0300 Subject: [PATCH 119/122] closes #5315 --- .../language/en-GB/admin/settings/general.json | 3 ++- public/language/en-GB/search.json | 1 + public/src/client/search.js | 4 ++-- src/controllers/search.js | 3 ++- src/search.js | 4 ++-- src/views/admin/settings/general.tpl | 17 +++++++++++++++++ 6 files changed, 26 insertions(+), 6 deletions(-) diff --git a/public/language/en-GB/admin/settings/general.json b/public/language/en-GB/admin/settings/general.json index c26740ee4f..72ecfe641f 100644 --- a/public/language/en-GB/admin/settings/general.json +++ b/public/language/en-GB/admin/settings/general.json @@ -26,5 +26,6 @@ "touch-icon.upload": "Upload", "touch-icon.help": "Recommended size and format: 192x192, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "outgoing-links": "Outgoing Links", - "outgoing-links.warning-page": "Use Outgoing Links Warning Page" + "outgoing-links.warning-page": "Use Outgoing Links Warning Page", + "search-default-sort-by": "Search default sort by" } \ No newline at end of file diff --git a/public/language/en-GB/search.json b/public/language/en-GB/search.json index 98c1afcea2..51a0a76ebb 100644 --- a/public/language/en-GB/search.json +++ b/public/language/en-GB/search.json @@ -12,6 +12,7 @@ "reply-count": "Reply Count", "at-least": "At least", "at-most": "At most", + "relevance": "Relevance", "post-time": "Post time", "newer-than": "Newer than", "older-than": "Older than", diff --git a/public/src/client/search.js b/public/src/client/search.js index 48cf358c0c..28a9ac94cd 100644 --- a/public/src/client/search.js +++ b/public/src/client/search.js @@ -105,8 +105,8 @@ define('forum/search', ['search', 'autocomplete'], function (searchModule, autoc $('#post-time-filter').val(formData.timeFilter); } - if (formData.sortBy) { - $('#post-sort-by').val(formData.sortBy); + if (formData.sortBy || ajaxify.data.searchDefaultSortBy) { + $('#post-sort-by').val(formData.sortBy || ajaxify.data.searchDefaultSortBy); $('#post-sort-direction').val(formData.sortDirection); } diff --git a/src/controllers/search.js b/src/controllers/search.js index 2261e4f3b7..db3adf0682 100644 --- a/src/controllers/search.js +++ b/src/controllers/search.js @@ -38,7 +38,7 @@ searchController.search = function (req, res, next) { repliesFilter: req.query.repliesFilter, timeRange: req.query.timeRange, timeFilter: req.query.timeFilter, - sortBy: req.query.sortBy, + sortBy: req.query.sortBy || meta.config.searchDefaultSortBy || '', sortDirection: req.query.sortDirection, page: page, uid: req.uid, @@ -67,6 +67,7 @@ searchController.search = function (req, res, next) { searchData.title = '[[global:header.search]]'; searchData.breadcrumbs = helpers.buildBreadcrumbs([{text: '[[global:search]]'}]); searchData.expandSearch = !req.query.term; + searchData.searchDefaultSortBy = meta.config.searchDefaultSortBy || ''; res.render('search', searchData); }); diff --git a/src/search.js b/src/search.js index d77b1f58f0..bd1fde947d 100644 --- a/src/search.js +++ b/src/search.js @@ -147,7 +147,7 @@ function getMatchedPosts(pids, data, callback) { topicFields.push('postcount'); } - if (data.sortBy) { + if (data.sortBy && data.sortBy !== 'relevance') { if (data.sortBy.startsWith('category')) { topicFields.push('cid'); } else if (data.sortBy.startsWith('topic.')) { @@ -328,7 +328,7 @@ function filterByTags(posts, hasTags) { } function sortPosts(posts, data) { - if (!posts.length || !data.sortBy) { + if (!posts.length || !data.sortBy || data.sortBy === 'relevance') { return; } diff --git a/src/views/admin/settings/general.tpl b/src/views/admin/settings/general.tpl index 990509e41f..68705951da 100644 --- a/src/views/admin/settings/general.tpl +++ b/src/views/admin/settings/general.tpl @@ -113,6 +113,23 @@
    +
    +
    [[admin/settings/general:search-default-sort-by]]
    +
    + +
    +
    +
    [[admin/settings/general:outgoing-links]]
    From d5a45832c327d6b2f68eb09d12d7058da3fef720 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 8 Feb 2017 10:26:00 -0500 Subject: [PATCH 120/122] up composer --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 58a9f518a8..8672421476 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "morgan": "^1.3.2", "mousetrap": "^1.5.3", "nconf": "~0.8.2", - "nodebb-plugin-composer-default": "4.3.8", + "nodebb-plugin-composer-default": "4.4.0", "nodebb-plugin-dbsearch": "1.0.5", "nodebb-plugin-emoji-extended": "1.1.1", "nodebb-plugin-emoji-one": "1.1.5", From ce2bda06487ee482e3402e49af2b8194e19d5476 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 8 Feb 2017 10:42:55 -0500 Subject: [PATCH 121/122] utilising async series if OS reports that system only contains one CPU processor --- src/meta/build.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/meta/build.js b/src/meta/build.js index 2d89abaf5a..3f2feb8a2a 100644 --- a/src/meta/build.js +++ b/src/meta/build.js @@ -45,6 +45,9 @@ exports.build = function build(targets, callback) { exports.buildTargets = function (targets, callback) { var cacheBuster = require('./cacheBuster'); var meta = require('../meta'); + var numCpus = require('os').cpus().length; + var strategy = (targets.length > 1 && numCpus > 1); + buildStart = buildStart || Date.now(); var step = function (startTime, target, next, err) { @@ -56,7 +59,13 @@ exports.buildTargets = function (targets, callback) { next(); }; - async.parallel([ + if (strategy) { + winston.verbose('[build] Utilising multiple cores/processes'); + } else { + winston.verbose('[build] Utilising single-core'); + } + + async[strategy ? 'parallel' : 'series']([ function (next) { if (targets.indexOf('js') !== -1) { winston.info('[build] Building javascript'); From a48c914a165db28fba1f25634c0654597e3a5e7e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 8 Feb 2017 11:23:27 -0500 Subject: [PATCH 122/122] explicitly cast jobsDisabled as Boolean --- app.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app.js b/app.js index 77da25936d..de5642e515 100644 --- a/app.js +++ b/app.js @@ -117,6 +117,17 @@ function loadConfig(callback) { nconf.set('url_parsed', url.parse(nconf.get('url'))); } + // Explicitly cast 'jobsDisabled' as Bool + var castAsBool = ['jobsDisabled']; + nconf.stores.env.readOnly = false; + castAsBool.forEach(function (prop) { + var value = nconf.get(prop); + if (value) { + nconf.set(prop, typeof value === 'boolean' ? value : String(value).toLowerCase() === 'true'); + } + }); + nconf.stores.env.readOnly = true; + if (typeof callback === 'function') { callback(); }