diff --git a/.tx/config b/.tx/config index aa341d290a..293681c974 100644 --- a/.tx/config +++ b/.tx/config @@ -1266,60 +1266,60 @@ trans.vi = public/language/vi/admin/manage/uploads.json trans.zh_CN = public/language/zh-CN/admin/manage/uploads.json trans.zh_TW = public/language/zh-TW/admin/manage/uploads.json -[o:nodebb:p:nodebb:r:admin-manage-user-ban-reasons] -file_filter = public/language//admin/manage/ban-reasons.json -source_file = public/language/en-GB/admin/manage/ban-reasons.json +[o:nodebb:p:nodebb:r:admin-manage-user-custom-reasons] +file_filter = public/language//admin/manage/custom-reasons.json +source_file = public/language/en-GB/admin/manage/custom-reasons.json source_lang = en_GB type = KEYVALUEJSON -trans.ar = public/language/ar/admin/manage/ban-reasons.json -trans.az = public/language/az/admin/manage/ban-reasons.json -trans.bg = public/language/bg/admin/manage/ban-reasons.json -trans.bn = public/language/bn/admin/manage/ban-reasons.json -trans.cs = public/language/cs/admin/manage/ban-reasons.json -trans.da = public/language/da/admin/manage/ban-reasons.json -trans.de = public/language/de/admin/manage/ban-reasons.json -trans.el = public/language/el/admin/manage/ban-reasons.json -trans.en_US = public/language/en-US/admin/manage/ban-reasons.json -trans.en@pirate = public/language/en-x-pirate/admin/manage/ban-reasons.json -trans.es = public/language/es/admin/manage/ban-reasons.json -trans.et = public/language/et/admin/manage/ban-reasons.json -trans.fa_IR = public/language/fa-IR/admin/manage/ban-reasons.json -trans.fi = public/language/fi/admin/manage/ban-reasons.json -trans.fr = public/language/fr/admin/manage/ban-reasons.json -trans.gl = public/language/gl/admin/manage/ban-reasons.json -trans.he = public/language/he/admin/manage/ban-reasons.json -trans.hr = public/language/hr/admin/manage/ban-reasons.json -trans.hu = public/language/hu/admin/manage/ban-reasons.json -trans.hy = public/language/hy/admin/manage/ban-reasons.json -trans.id = public/language/id/admin/manage/ban-reasons.json -trans.it = public/language/it/admin/manage/ban-reasons.json -trans.ja = public/language/ja/admin/manage/ban-reasons.json -trans.ko = public/language/ko/admin/manage/ban-reasons.json -trans.lt = public/language/lt/admin/manage/ban-reasons.json -trans.lv = public/language/lv/admin/manage/ban-reasons.json -trans.ms = public/language/ms/admin/manage/ban-reasons.json -trans.nb = public/language/nb/admin/manage/ban-reasons.json -trans.nl = public/language/nl/admin/manage/ban-reasons.json -trans.nn_NO = public/language/nn-NO/admin/manage/ban-reasons.json -trans.pl = public/language/pl/admin/manage/ban-reasons.json -trans.pt_BR = public/language/pt-BR/admin/manage/ban-reasons.json -trans.pt_PT = public/language/pt-PT/admin/manage/ban-reasons.json -trans.ro = public/language/ro/admin/manage/ban-reasons.json -trans.ru = public/language/ru/admin/manage/ban-reasons.json -trans.rw = public/language/rw/admin/manage/ban-reasons.json -trans.sc = public/language/sc/admin/manage/ban-reasons.json -trans.sk = public/language/sk/admin/manage/ban-reasons.json -trans.sl = public/language/sl/admin/manage/ban-reasons.json -trans.sq_AL = public/language/sq-AL/admin/manage/ban-reasons.json -trans.sr = public/language/sr/admin/manage/ban-reasons.json -trans.sv = public/language/sv/admin/manage/ban-reasons.json -trans.th = public/language/th/admin/manage/ban-reasons.json -trans.tr = public/language/tr/admin/manage/ban-reasons.json -trans.uk = public/language/uk/admin/manage/ban-reasons.json -trans.ur = public/language/ur/admin/manage/ban-reasons.json -trans.vi = public/language/vi/admin/manage/ban-reasons.json -trans.zh_CN = public/language/zh-CN/admin/manage/ban-reasons.json -trans.zh_TW = public/language/zh-TW/admin/manage/ban-reasons.json +trans.ar = public/language/ar/admin/manage/custom-reasons.json +trans.az = public/language/az/admin/manage/custom-reasons.json +trans.bg = public/language/bg/admin/manage/custom-reasons.json +trans.bn = public/language/bn/admin/manage/custom-reasons.json +trans.cs = public/language/cs/admin/manage/custom-reasons.json +trans.da = public/language/da/admin/manage/custom-reasons.json +trans.de = public/language/de/admin/manage/custom-reasons.json +trans.el = public/language/el/admin/manage/custom-reasons.json +trans.en_US = public/language/en-US/admin/manage/custom-reasons.json +trans.en@pirate = public/language/en-x-pirate/admin/manage/custom-reasons.json +trans.es = public/language/es/admin/manage/custom-reasons.json +trans.et = public/language/et/admin/manage/custom-reasons.json +trans.fa_IR = public/language/fa-IR/admin/manage/custom-reasons.json +trans.fi = public/language/fi/admin/manage/custom-reasons.json +trans.fr = public/language/fr/admin/manage/custom-reasons.json +trans.gl = public/language/gl/admin/manage/custom-reasons.json +trans.he = public/language/he/admin/manage/custom-reasons.json +trans.hr = public/language/hr/admin/manage/custom-reasons.json +trans.hu = public/language/hu/admin/manage/custom-reasons.json +trans.hy = public/language/hy/admin/manage/custom-reasons.json +trans.id = public/language/id/admin/manage/custom-reasons.json +trans.it = public/language/it/admin/manage/custom-reasons.json +trans.ja = public/language/ja/admin/manage/custom-reasons.json +trans.ko = public/language/ko/admin/manage/custom-reasons.json +trans.lt = public/language/lt/admin/manage/custom-reasons.json +trans.lv = public/language/lv/admin/manage/custom-reasons.json +trans.ms = public/language/ms/admin/manage/custom-reasons.json +trans.nb = public/language/nb/admin/manage/custom-reasons.json +trans.nl = public/language/nl/admin/manage/custom-reasons.json +trans.nn_NO = public/language/nn-NO/admin/manage/custom-reasons.json +trans.pl = public/language/pl/admin/manage/custom-reasons.json +trans.pt_BR = public/language/pt-BR/admin/manage/custom-reasons.json +trans.pt_PT = public/language/pt-PT/admin/manage/custom-reasons.json +trans.ro = public/language/ro/admin/manage/custom-reasons.json +trans.ru = public/language/ru/admin/manage/custom-reasons.json +trans.rw = public/language/rw/admin/manage/custom-reasons.json +trans.sc = public/language/sc/admin/manage/custom-reasons.json +trans.sk = public/language/sk/admin/manage/custom-reasons.json +trans.sl = public/language/sl/admin/manage/custom-reasons.json +trans.sq_AL = public/language/sq-AL/admin/manage/custom-reasons.json +trans.sr = public/language/sr/admin/manage/custom-reasons.json +trans.sv = public/language/sv/admin/manage/custom-reasons.json +trans.th = public/language/th/admin/manage/custom-reasons.json +trans.tr = public/language/tr/admin/manage/custom-reasons.json +trans.uk = public/language/uk/admin/manage/custom-reasons.json +trans.ur = public/language/ur/admin/manage/custom-reasons.json +trans.vi = public/language/vi/admin/manage/custom-reasons.json +trans.zh_CN = public/language/zh-CN/admin/manage/custom-reasons.json +trans.zh_TW = public/language/zh-TW/admin/manage/custom-reasons.json [o:nodebb:p:nodebb:r:admin-manage-user-custom-fields] file_filter = public/language//admin/manage/user-custom-fields.json diff --git a/public/language/en-GB/admin/manage/ban-reasons.json b/public/language/en-GB/admin/manage/ban-reasons.json deleted file mode 100644 index 03b9f6462f..0000000000 --- a/public/language/en-GB/admin/manage/ban-reasons.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "title": "Manage Ban Reasons", - "create-reason": "Create Reason", - "edit-reason": "Edit Reason", - "reason-title": "Title", - "reason-body": "Body", - "ban-reasons-saved": "Ban reasons saved successfully", - "delete-reason-confirm-x": "Are you sure you want to delete the ban reason with the title %1?" -} \ No newline at end of file diff --git a/public/language/en-GB/admin/manage/custom-reasons.json b/public/language/en-GB/admin/manage/custom-reasons.json new file mode 100644 index 0000000000..90a2e620af --- /dev/null +++ b/public/language/en-GB/admin/manage/custom-reasons.json @@ -0,0 +1,16 @@ +{ + "title": "Manage Custom Reasons", + "create-reason": "Create Reason", + "edit-reason": "Edit Reason", + "reasons-help": "Reasons are predefined explanations used when banning or muting users, or when rejecting posts in the post queue.", + "reason-title": "Title", + "reason-type": "Type", + "reason-body": "Body", + "reason-all": "All", + "reason-ban": "Ban", + "reason-mute": "Mute", + "reason-post-queue": "Post Queue", + "reason-type-help": "The type of action this reason applies to. If 'All' is selected, this reason will be available for all action types.", + "custom-reasons-saved": "Custom reasons saved successfully", + "delete-reason-confirm-x": "Are you sure you want to delete the custom reason with the title %1?" +} \ No newline at end of file diff --git a/public/language/en-GB/admin/manage/users.json b/public/language/en-GB/admin/manage/users.json index 818cc2b87d..fc36120840 100644 --- a/public/language/en-GB/admin/manage/users.json +++ b/public/language/en-GB/admin/manage/users.json @@ -23,7 +23,7 @@ "purge": "Delete User(s) and Content", "download-csv": "Download CSV", "custom-user-fields": "Custom User Fields", - "ban-reasons": "Ban Reasons", + "custom-reasons": "Custom Reasons", "manage-groups": "Manage Groups", "set-reputation": "Set Reputation", "add-group": "Add Group", diff --git a/public/language/en-GB/notifications.json b/public/language/en-GB/notifications.json index 6eee3dd6ba..43eaa603b3 100644 --- a/public/language/en-GB/notifications.json +++ b/public/language/en-GB/notifications.json @@ -78,6 +78,7 @@ "users-csv-exported": "Users csv exported, click to download", "post-queue-accepted": "Your queued post has been accepted. Click here to see your post.", "post-queue-rejected": "Your queued post has been rejected.", + "post-queue-rejected-for-reason": "Your queued post has been rejected for the following reason: \"%1\"", "post-queue-notify": "Queued post received a notification: \"%1\"", "email-confirmed": "Email Confirmed", diff --git a/public/src/admin/manage/users.js b/public/src/admin/manage/users.js index 3a24b1aa4e..bbf5ed1a00 100644 --- a/public/src/admin/manage/users.js +++ b/public/src/admin/manage/users.js @@ -260,7 +260,7 @@ define('admin/manage/users', [ alerts.error('[[error:no-users-selected]]'); return false; // specifically to keep the menu open } - const reasons = await socket.emit('user.getBanReasons'); + const reasons = await socket.emit('user.getCustomReasons', { type: 'ban' }); const html = await app.parseAndTranslate('modals/temporary-ban', { reasons }); const modal = bootbox.dialog({ title: '[[user:ban-account]]', diff --git a/public/src/admin/manage/users/ban-reasons.js b/public/src/admin/manage/users/custom-reasons.js similarity index 73% rename from public/src/admin/manage/users/ban-reasons.js rename to public/src/admin/manage/users/custom-reasons.js index 927d427945..923f601cae 100644 --- a/public/src/admin/manage/users/ban-reasons.js +++ b/public/src/admin/manage/users/custom-reasons.js @@ -1,9 +1,9 @@ -define('admin/manage/user/ban-reasons', [ +define('admin/manage/user/custom-reasons', [ 'benchpress', 'bootbox', 'alerts', 'translator', 'jquery-ui/widgets/sortable', ], function (benchpress, bootbox, alerts, translator) { - const manageBanReasons = {}; + const manageCustomReasons = {}; - manageBanReasons.init = function () { + manageCustomReasons.init = function () { const table = $('table'); $('#new').on('click', () => showModal()); @@ -16,7 +16,7 @@ define('admin/manage/user/ban-reasons', [ table.on('click', '[data-action="delete"]', function () { const row = $(this).parents('[data-key]'); const title = row.attr('data-title'); - bootbox.confirm(`[[admin/manage/ban-reasons:delete-reason-confirm-x, "${title}"]]`, function (ok) { + bootbox.confirm(`[[admin/manage/custom-reasons:delete-reason-confirm-x, "${title}"]]`, function (ok) { if (!ok) { return; } @@ -35,11 +35,11 @@ define('admin/manage/user/ban-reasons', [ $('tbody tr[data-key]').each((index, el) => { reasons.push(getDataFromEl($(el))); }); - socket.emit('admin.user.saveBanReasons', reasons, function (err) { + socket.emit('admin.user.saveCustomReasons', reasons, function (err) { if (err) { return alerts.error(err); } - alerts.success('[[admin/manage/ban-reasons:ban-reasons-saved]]'); + alerts.success('[[admin/manage/custom-reasons:custom-reasons-saved]]'); }); }); }; @@ -48,18 +48,19 @@ define('admin/manage/user/ban-reasons', [ return { key: el.attr('data-key'), title: el.attr('data-title'), + type: el.attr('data-type'), body: el.attr('data-body'), }; } async function showModal(reason = null) { - const html = await benchpress.render('admin/partials/manage-ban-reasons-modal', reason); + const html = await benchpress.render('admin/partials/manage-custom-reasons-modal', reason); const modal = bootbox.dialog({ message: html, onEscape: true, title: reason ? - '[[admin/manage/ban-reasons:edit-reason]]' : - '[[admin/manage/ban-reasons:create-reason]]', + '[[admin/manage/custom-reasons:edit-reason]]' : + '[[admin/manage/custom-reasons:create-reason]]', buttons: { submit: { label: '[[global:save]]', @@ -69,7 +70,7 @@ define('admin/manage/user/ban-reasons', [ formData.body = translator.escape(formData.body); formData.parsedBody = translator.escape(await socket.emit('admin.parseRaw', formData.body)); - app.parseAndTranslate('admin/manage/users/ban-reasons', 'reasons', { + app.parseAndTranslate('admin/manage/users/custom-reasons', 'reasons', { reasons: [formData], }, (html) => { if (reason) { @@ -90,7 +91,7 @@ define('admin/manage/user/ban-reasons', [ } - return manageBanReasons; + return manageCustomReasons; }); diff --git a/public/src/client/post-queue.js b/public/src/client/post-queue.js index 5cdf120517..debd6d3066 100644 --- a/public/src/client/post-queue.js +++ b/public/src/client/post-queue.js @@ -2,11 +2,11 @@ define('forum/post-queue', [ - 'categoryFilter', 'categorySelector', 'api', 'alerts', 'bootbox', - 'accounts/moderate', 'accounts/delete', + 'categoryFilter', 'categorySelector', 'api', 'alerts', 'translator', + 'bootbox', 'accounts/moderate', 'accounts/delete', ], function ( - categoryFilter, categorySelector, api, alerts, bootbox, - AccountModerate, AccountsDelete + categoryFilter, categorySelector, api, alerts, translator, + bootbox, AccountModerate, AccountsDelete ) { const PostQueue = {}; @@ -158,70 +158,122 @@ define('forum/post-queue', [ AccountsDelete.purge(uid, ajaxify.go.bind(null, 'post-queue')); break; - default: - handleQueueActions.call(e.target); + case 'accept': + handleAccept(subselector); break; + + case 'reject': + handleReject(subselector); + break; + + case 'notify': + handleNotify(subselector); + break; + + default: + throw new Error(`Unknown action: ${action}`); } } }); } } - async function handleQueueActions() { - // accept, reject, notify - - const parent = $(this).parents('[data-id]'); - const action = $(this).attr('data-action'); + function handleAccept(btn) { + const parent = $(btn).parents('[data-id]'); const id = parent.attr('data-id'); - const listContainer = parent.get(0).parentNode; + doAction('accept', id).then(() => removePostQueueElement(parent)).catch(alerts.error); + } - if ((!['accept', 'reject', 'notify'].includes(action)) || - (action === 'reject' && !await confirmReject(ajaxify.data.canAccept ? '[[post-queue:confirm-reject]]' : '[[post-queue:confirm-remove]]'))) { + async function handleReject(btn) { + const parent = $(btn).parents('[data-id]'); + const id = parent.attr('data-id'); + const translationString = ajaxify.data.canAccept ? + '[[post-queue:confirm-reject]]' : + '[[post-queue:confirm-remove]]'; + + const message = await getMessage(translationString); + if (message === false) { + return; + } + doAction('reject', id, message).then(() => removePostQueueElement(parent)).catch(alerts.error); + } + + function removePostQueueElement(parent) { + const listContainer = parent.get(0).parentNode; + parent.remove(); + if (listContainer.childElementCount === 0) { + if (ajaxify.data.singlePost) { + ajaxify.go('/post-queue' + window.location.search); + } else { + ajaxify.refresh(); + } + } + } + + async function handleNotify(btn) { + const parent = $(btn).parents('[data-id]'); + const id = parent.attr('data-id'); + const message = await getMessage('[[post-queue:notify-user]]'); + if (message === false) { return; } - doAction(action, id).then(function () { - if (action === 'accept' || action === 'reject') { - parent.remove(); - } - - if (listContainer.childElementCount === 0) { - if (ajaxify.data.singlePost) { - ajaxify.go('/post-queue' + window.location.search); - } else { - ajaxify.refresh(); - } - } - }).catch(alerts.error); - - return false; + doAction('notify', id, message).catch(alerts.error); } - async function doAction(action, id) { - function getMessage() { - return new Promise((resolve) => { - const modal = bootbox.dialog({ - title: '[[post-queue:notify-user]]', - message: '', - buttons: { - OK: { - label: '[[modules:bootbox.send]]', - callback: function () { - const val = modal.find('textarea').val(); - if (val) { - resolve(val); - } - }, + async function getMessage(title) { + const reasons = await socket.emit('user.getCustomReasons', { type: 'post-queue' }); + const html = await app.parseAndTranslate('partials/custom-reason', { reasons }); + + return new Promise((resolve) => { + let resolved = false; + const done = (value) => { + if (resolved) { + return; + } + resolved = true; + resolve(value); + }; + + const modal = bootbox.dialog({ + title: title, + message: `
${html.html()}
`, + show: true, + onEscape: true, + buttons: { + close: { + label: '[[global:close]]', + className: 'btn-link', + callback: function () { + done(false); }, }, - }); + submit: { + label: '[[modules:bootbox.confirm]]', + callback: function () { + done(modal.find('[name="reason"]').val()); + }, + }, + }, }); - } + modal.on('hidden.bs.modal', () => { + done(false); + }); + modal.find('[data-key]').on('click', function () { + const reason = reasons.find(r => String(r.key) === $(this).attr('data-key')); + if (reason && reason.body) { + modal.find('[name="reason"]').val(translator.unescape(reason.body)); + } + }); + }); + } + + async function doAction(action, id, message = '') { const actionsMap = { accept: () => api.post(`/posts/queue/${id}`, {}), - reject: () => api.del(`/posts/queue/${id}`, {}), - notify: async () => api.post(`/posts/queue/${id}/notify`, { message: await getMessage() }), + reject: () => api.del(`/posts/queue/${id}`, { message }), + notify: () => api.post(`/posts/queue/${id}/notify`, { message }), }; if (actionsMap[action]) { const result = actionsMap[action](); diff --git a/public/src/modules/accounts/moderate.js b/public/src/modules/accounts/moderate.js index 9ebbc7e45e..084376140e 100644 --- a/public/src/modules/accounts/moderate.js +++ b/public/src/modules/accounts/moderate.js @@ -14,6 +14,7 @@ define('forum/account/moderate', [ throwModal({ tpl: 'modals/temporary-ban', title: '[[user:ban-account]]', + type: 'ban', onSubmit: function (formData) { const until = formData.length > 0 ? ( Date.now() + (formData.length * 1000 * 60 * 60 * (parseInt(formData.unit, 10) ? 24 : 1)) @@ -36,6 +37,7 @@ define('forum/account/moderate', [ throwModal({ tpl: 'modals/unban', title: '[[user:unban-account]]', + type: 'ban', onSubmit: function (formData) { api.del('/users/' + encodeURIComponent(theirid) + '/ban', { reason: formData.reason || '', @@ -51,6 +53,7 @@ define('forum/account/moderate', [ throwModal({ tpl: 'modals/temporary-mute', title: '[[user:mute-account]]', + type: 'mute', onSubmit: function (formData) { const until = formData.length > 0 ? ( Date.now() + (formData.length * 1000 * 60 * 60 * (parseInt(formData.unit, 10) ? 24 : 1)) @@ -84,7 +87,7 @@ define('forum/account/moderate', [ }; async function throwModal(options) { - const reasons = await socket.emit('user.getBanReasons'); + const reasons = await socket.emit('user.getCustomReasons', { type: options.type || '' }); const html = await app.parseAndTranslate(options.tpl, { reasons }); const modal = bootbox.dialog({ title: options.title, diff --git a/src/api/posts.js b/src/api/posts.js index 1af86535e4..767ea8eb1c 100644 --- a/src/api/posts.js +++ b/src/api/posts.js @@ -592,7 +592,10 @@ postsAPI.removeQueuedPost = async (caller, data) => { await canEditQueue(caller.uid, data, 'reject'); const result = await posts.removeFromQueue(data.id); if (result && caller.uid !== parseInt(result.uid, 10)) { - await sendQueueNotification('post-queue-rejected', result.uid, '/'); + const msg = validator.escape(String(data.message ? data.message : '')); + await sendQueueNotification( + msg ? 'post-queue-rejected-for-reason' : 'post-queue-rejected', result.uid, '/', msg + ); } await logQueueEvent(caller, result, 'reject'); }; @@ -612,7 +615,7 @@ postsAPI.notifyQueuedPostOwner = async (caller, data) => { await canEditQueue(caller.uid, data, 'notify'); const result = await posts.getFromQueue(data.id); if (result) { - await sendQueueNotification('post-queue-notify', result.uid, `/post-queue/${data.id}`, validator.escape(String(data.message))); + await sendQueueNotification('post-queue-notify', result.uid, `/post-queue/${data.id}`, validator.escape(String(data.message || ''))); } }; diff --git a/src/controllers/admin/users.js b/src/controllers/admin/users.js index f8738ff641..6a07823cd8 100644 --- a/src/controllers/admin/users.js +++ b/src/controllers/admin/users.js @@ -316,6 +316,6 @@ usersController.customFields = async function (req, res) { }; usersController.banReasons = async function (req, res) { - const reasons = await user.bans.getBanReasons(); - res.render('admin/manage/users/ban-reasons', { reasons }); + const reasons = await user.bans.getCustomReasons(); + res.render('admin/manage/users/custom-reasons', { reasons }); }; \ No newline at end of file diff --git a/src/controllers/write/posts.js b/src/controllers/write/posts.js index 9e8053d17d..0c0a480dfb 100644 --- a/src/controllers/write/posts.js +++ b/src/controllers/write/posts.js @@ -196,7 +196,7 @@ Posts.acceptQueuedPost = async (req, res) => { }; Posts.removeQueuedPost = async (req, res) => { - await api.posts.removeQueuedPost(req, { id: req.params.id }); + await api.posts.removeQueuedPost(req, { id: req.params.id, message: req.body.message }); helpers.formatApiResponse(200, res); }; diff --git a/src/routes/admin.js b/src/routes/admin.js index 4b6216d84a..96cc92c62d 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -23,7 +23,7 @@ module.exports = function (app, name, middleware, controllers) { helpers.setupAdminPageRoute(app, `/${name}/manage/users`, middlewares, controllers.admin.users.index); helpers.setupAdminPageRoute(app, `/${name}/manage/users/custom-fields`, middlewares, controllers.admin.users.customFields); - helpers.setupAdminPageRoute(app, `/${name}/manage/users/ban-reasons`, middlewares, controllers.admin.users.banReasons); + helpers.setupAdminPageRoute(app, `/${name}/manage/users/custom-reasons`, middlewares, controllers.admin.users.banReasons); helpers.setupAdminPageRoute(app, `/${name}/manage/registration`, middlewares, controllers.admin.users.registrationQueue); helpers.setupAdminPageRoute(app, `/${name}/manage/admins-mods`, middlewares, controllers.admin.adminsMods.get); diff --git a/src/socket.io/admin/user.js b/src/socket.io/admin/user.js index beeeaae39b..0a981eacbb 100644 --- a/src/socket.io/admin/user.js +++ b/src/socket.io/admin/user.js @@ -219,11 +219,11 @@ User.saveCustomFields = async function (socket, fields) { await user.reloadCustomFieldWhitelist(); }; -User.saveBanReasons = async function (socket, reasons) { - const keys = await db.getSortedSetRange('ban-reasons', 0, -1); - await db.delete('ban-reasons'); - await db.deleteAll(keys.map(k => `ban-reason:${k}`)); +User.saveCustomReasons = async function (socket, reasons) { + const keys = await db.getSortedSetRange('custom-reasons', 0, -1); + await db.delete('custom-reasons'); + await db.deleteAll(keys.map(k => `custom-reason:${k}`)); const ids = reasons.map((f, i) => i); - await db.sortedSetAdd(`ban-reasons`, ids, ids); - await db.setObjectBulk(reasons.map((reason, i) => [`ban-reason:${i}`, reason])); + await db.sortedSetAdd(`custom-reasons`, ids, ids); + await db.setObjectBulk(reasons.map((reason, i) => [`custom-reason:${i}`, reason])); }; diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 75ba2f5005..7903d44014 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -174,12 +174,12 @@ SocketUser.editModerationNote = async function (socket, data) { return await user.getModerationNotesByIds(data.uid, [data.id]); }; -SocketUser.getBanReasons = async function (socket) { +SocketUser.getCustomReasons = async function (socket, { type }) { const canBan = await privileges.users.hasBanPrivilege(socket.uid); if (!canBan) { throw new Error('[[error:no-privileges]]'); } - return await user.bans.getBanReasons(); + return await user.bans.getCustomReasons({ type }); }; SocketUser.deleteUpload = async function (socket, data) { diff --git a/src/user/bans.js b/src/user/bans.js index f1c13d1120..417f0c3e7d 100644 --- a/src/user/bans.js +++ b/src/user/bans.js @@ -165,14 +165,18 @@ module.exports = function (User) { return banObj && banObj.reason ? banObj.reason : ''; }; - User.bans.getBanReasons = async function () { - const keys = await db.getSortedSetRange('ban-reasons', 0, -1); - const reasons = (await db.getObjects(keys.map(k => `ban-reason:${k}`))).filter(Boolean); + User.bans.getCustomReasons = async function ({ type = '' } = {}) { + const keys = await db.getSortedSetRange('custom-reasons', 0, -1); + type = type || ''; + const reasons = (await db.getObjects(keys.map(k => `custom-reason:${k}`))).filter(Boolean); await Promise.all(reasons.map(async (reason, i) => { reason.key = i; reason.parsedBody = translator.escape(await plugins.hooks.fire('filter:parse.raw', reason.body || '')); reason.body = translator.escape(reason.body); })); + if (type !== '') { + return reasons.filter(reason => reason.type === type || reason.type === ''); + } return reasons; }; }; diff --git a/src/views/admin/manage/users.tpl b/src/views/admin/manage/users.tpl index f9ca3f841f..3223b2a485 100644 --- a/src/views/admin/manage/users.tpl +++ b/src/views/admin/manage/users.tpl @@ -83,7 +83,7 @@
  • [[admin/manage/users:download-csv]]
  • [[admin/manage/users:custom-user-fields]]
  • -
  • [[admin/manage/users:ban-reasons]] +
  • [[admin/manage/users:custom-reasons]]
  • diff --git a/src/views/admin/manage/users/ban-reasons.tpl b/src/views/admin/manage/users/custom-reasons.tpl similarity index 65% rename from src/views/admin/manage/users/ban-reasons.tpl rename to src/views/admin/manage/users/custom-reasons.tpl index 8cc2502fc3..29ba650e75 100644 --- a/src/views/admin/manage/users/ban-reasons.tpl +++ b/src/views/admin/manage/users/custom-reasons.tpl @@ -1,16 +1,18 @@
    -

    [[admin/manage/ban-reasons:title]]

    +

    [[admin/manage/custom-reasons:title]]

    +

    [[admin/manage/custom-reasons:reasons-help]]

    +
    @@ -18,18 +20,20 @@ - [[admin/manage/ban-reasons:reason-title]] - [[admin/manage/ban-reasons:reason-body]] + [[admin/manage/custom-reasons:reason-title]] + [[admin/manage/custom-reasons:reason-type]] + [[admin/manage/custom-reasons:reason-body]] {{{ each reasons }}} - + - {./title} + {./title} + {{{ if ./type }}}[[admin/manage/custom-reasons:reason-{{./type}}]]{{{ else }}}[[admin/manage/custom-reasons:reason-all]]{{{ end }}} {./parsedBody}
    diff --git a/src/views/admin/partials/manage-ban-reasons-modal.tpl b/src/views/admin/partials/manage-ban-reasons-modal.tpl deleted file mode 100644 index 019c52fa1e..0000000000 --- a/src/views/admin/partials/manage-ban-reasons-modal.tpl +++ /dev/null @@ -1,11 +0,0 @@ -
    -
    - - -
    - -
    - - -
    -
    diff --git a/src/views/admin/partials/manage-custom-reasons-modal.tpl b/src/views/admin/partials/manage-custom-reasons-modal.tpl new file mode 100644 index 0000000000..9e44e5856f --- /dev/null +++ b/src/views/admin/partials/manage-custom-reasons-modal.tpl @@ -0,0 +1,22 @@ +
    +
    + + +
    + +
    + + +

    [[admin/manage/custom-reasons:reason-type-help]]

    +
    + +
    + + +
    +
    diff --git a/src/views/modals/temporary-ban.tpl b/src/views/modals/temporary-ban.tpl index 850289d59a..68d4ab2250 100644 --- a/src/views/modals/temporary-ban.tpl +++ b/src/views/modals/temporary-ban.tpl @@ -23,24 +23,7 @@
    -
    - - {{{ if reasons.length }}} - - {{{ end }}} -
    - - +
    diff --git a/src/views/modals/temporary-mute.tpl b/src/views/modals/temporary-mute.tpl index 9dce754716..08b9127329 100644 --- a/src/views/modals/temporary-mute.tpl +++ b/src/views/modals/temporary-mute.tpl @@ -24,24 +24,7 @@
    -
    - - {{{ if reasons.length }}} - - {{{ end }}} -
    - - +
    diff --git a/src/views/partials/custom-reason.tpl b/src/views/partials/custom-reason.tpl new file mode 100644 index 0000000000..50af17294b --- /dev/null +++ b/src/views/partials/custom-reason.tpl @@ -0,0 +1,20 @@ +
    +
    + + {{{ if reasons.length }}} + + {{{ end }}} +
    + + +
    \ No newline at end of file