feat: #8524, allow editing category of queued topic

v1.18.x
Barış Soner Uşaklı 5 years ago
parent 7260646d6c
commit 844f2b4ed0

@ -1,7 +1,7 @@
'use strict';
define('admin/manage/post-queue', function () {
define('admin/manage/post-queue', ['categorySelector'], function (categorySelector) {
var PostQueue = {};
PostQueue.init = function () {
@ -24,6 +24,32 @@ define('admin/manage/post-queue', function () {
handleContentEdit('.post-content', '.post-content-editable', 'textarea');
handleContentEdit('.topic-title', '.topic-title-editable', 'input');
$('.posts-list').on('click', '.topic-category[data-editable]', function () {
var $this = $(this);
var id = $this.parents('[data-id]').attr('data-id');
categorySelector.modal(ajaxify.data.allCategories, function (cid) {
var category = ajaxify.data.allCategories.find(function (c) {
return parseInt(c.cid, 10) === parseInt(cid, 10);
});
socket.emit('posts.editQueuedContent', {
id: id,
cid: cid,
}, function (err) {
if (err) {
return app.alertError(err.message);
}
app.parseAndTranslate('admin/manage/post-queue', 'posts', {
posts: [{
category: category,
}],
}, function (html) {
$this.replaceWith(html.find('.topic-category'));
});
});
});
return false;
});
};
function handleContentEdit(displayClass, editableClass, inputSelector) {

@ -181,12 +181,17 @@ modsController.postQueue = async function (req, res, next) {
const page = parseInt(req.query.page, 10) || 1;
const postsPerPage = 20;
const [ids, isAdminOrGlobalMod, moderatedCids] = await Promise.all([
const [ids, isAdminOrGlobalMod, moderatedCids, allCategories] = await Promise.all([
db.getSortedSetRange('post:queue', 0, -1),
user.isAdminOrGlobalMod(req.uid),
user.getModeratedCids(req.uid),
categories.buildForSelect(req.uid, 'find', ['disabled', 'link', 'slug']),
]);
allCategories.forEach((c) => {
c.disabledClass = !isAdminOrGlobalMod && !moderatedCids.includes(String(c.cid));
});
let postData = await getQueuedPosts(ids);
postData = postData.filter(p => p && (isAdminOrGlobalMod || moderatedCids.includes(String(p.category.cid))));
@ -198,6 +203,7 @@ modsController.postQueue = async function (req, res, next) {
res.render('admin/manage/post-queue', {
title: '[[pages:post-queue]]',
posts: postData,
allCategories: allCategories,
pagination: pagination.create(page, pageCount),
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:post-queue]]' }]),
});

@ -147,28 +147,31 @@ module.exports = function (Posts) {
socketHelpers.notifyNew(data.uid, 'newPost', result);
}
Posts.editQueuedContent = async function (uid, id, content, title) {
const canEditQueue = await Posts.canEditQueue(uid, id);
Posts.editQueuedContent = async function (uid, editData) {
const canEditQueue = await Posts.canEditQueue(uid, editData);
if (!canEditQueue) {
throw new Error('[[error:no-privileges]]');
}
const data = await getParsedObject(id);
const data = await getParsedObject(editData.id);
if (!data) {
return;
}
if (content !== undefined) {
data.data.content = content;
if (editData.content !== undefined) {
data.data.content = editData.content;
}
if (editData.title !== undefined) {
data.data.title = editData.title;
}
if (title !== undefined) {
data.data.title = title;
if (editData.cid !== undefined) {
data.data.cid = editData.cid;
}
await db.setObjectField('post:queue:' + id, 'data', JSON.stringify(data.data));
await db.setObjectField('post:queue:' + editData.id, 'data', JSON.stringify(data.data));
};
Posts.canEditQueue = async function (uid, id) {
Posts.canEditQueue = async function (uid, editData) {
const [isAdminOrGlobalMod, data] = await Promise.all([
user.isAdminOrGlobalMod(uid),
getParsedObject(id),
getParsedObject(editData.id),
]);
if (!data) {
return false;
@ -184,6 +187,11 @@ module.exports = function (Posts) {
} else if (data.type === 'reply') {
cid = await topics.getTopicField(data.data.tid, 'cid');
}
return await user.isModerator(uid, cid);
const isModerator = await user.isModerator(uid, cid);
let isModeratorOfTargetCid = true;
if (editData.cid) {
isModeratorOfTargetCid = await user.isModerator(uid, editData.cid);
}
return isModerator && isModeratorOfTargetCid;
};
};

@ -166,7 +166,7 @@ SocketPosts.reject = async function (socket, data) {
};
async function acceptOrReject(method, socket, data) {
const canEditQueue = await posts.canEditQueue(socket.uid, data.id);
const canEditQueue = await posts.canEditQueue(socket.uid, data);
if (!canEditQueue) {
throw new Error('[[error:no-privileges]]');
}
@ -174,10 +174,10 @@ async function acceptOrReject(method, socket, data) {
}
SocketPosts.editQueuedContent = async function (socket, data) {
if (!data || !data.id || (!data.content && !data.title)) {
if (!data || !data.id || (!data.content && !data.title && !data.cid)) {
throw new Error('[[error:invalid-data]]');
}
await posts.editQueuedContent(socket.uid, data.id, data.content, data.title);
await posts.editQueuedContent(socket.uid, data);
if (data.content) {
return await plugins.fireHook('filter:parse.post', { postData: data });
}

@ -18,7 +18,7 @@
<thead>
<tr>
<th>[[admin/manage/post-queue:user]]</th>
<th>[[admin/manage/post-queue:category]]</th>
<th>[[admin/manage/post-queue:category]] <i class="fa fa-info-circle" data-toggle="tooltip" title="[[admin/manage/post-queue:content-editable]]"></i></th>
<th>[[admin/manage/post-queue:title]] <i class="fa fa-info-circle" data-toggle="tooltip" title="[[admin/manage/post-queue:content-editable]]"></i></th>
<th>[[admin/manage/post-queue:content]] <i class="fa fa-info-circle" data-toggle="tooltip" title="[[admin/manage/post-queue:content-editable]]"></i></th>
<th>[[admin/manage/post-queue:posted]]</th>
@ -35,8 +35,8 @@
{posts.user.username}
<!-- ENDIF posts.user.userslug -->
</td>
<td class="col-md-2">
<a href="{config.relative_path}/category/{posts.category.slug}"><!-- IF posts.categiry.icon --><span class="fa-stack"><i style="color: {posts.category.bgColor};" class="fa fa-circle fa-stack-2x"></i><i style="color: {posts.category.color};" class="fa fa-stack-1x fa-fw {posts.category.icon}"></i></span><!-- ENDIF posts.category.icon --> {posts.category.name}</a>
<td class="col-md-2 topic-category" {{{if posts.data.cid}}}data-editable="editable"{{{end}}}">
<a href="{config.relative_path}/category/{posts.category.slug}"><!-- IF posts.category.icon --><span class="fa-stack"><i style="color: {posts.category.bgColor};" class="fa fa-circle fa-stack-2x"></i><i style="color: {posts.category.color};" class="fa fa-stack-1x fa-fw {posts.category.icon}"></i></span><!-- ENDIF posts.category.icon --> {posts.category.name}</a>
</td>
<td class="col-md-2 topic-title">
<!-- IF posts.data.tid -->

@ -12,7 +12,7 @@
<a role="menu-item">[[search:no-matches]]</a>
</li>
<!-- BEGIN categories -->
<li role="presentation" class="category" data-cid="{categories.cid}" data-name="{categories.name}">
<li role="presentation" class="category {{{if categories.disabledClass}}}disabled{{{end}}}" data-cid="{categories.cid}" data-name="{categories.name}">
<a role="menu-item">{categories.level}<span component="category-markup"><!-- IF categories.icon --><span class="fa-stack" style="{function.generateCategoryBackground}"><i style="color: {categories.color};" class="fa fa-stack-1x fa-fw {categories.icon}"></i></span><!-- ENDIF categories.icon --> {categories.name}</span></a>
</li>
<!-- END categories -->

@ -1096,6 +1096,21 @@ describe('Post\'s', function () {
});
});
it('should edit topic category in queue', function (done) {
socketPosts.editQueuedContent({ uid: globalModUid }, { id: topicQueueId, cid: 2 }, function (err) {
assert.ifError(err);
request(nconf.get('url') + '/api/post-queue', { jar: jar, json: true }, function (err, res, body) {
assert.ifError(err);
assert.equal(body.posts[0].type, 'topic');
assert.equal(body.posts[0].data.cid, 2);
socketPosts.editQueuedContent({ uid: globalModUid }, { id: topicQueueId, cid: cid }, function (err) {
assert.ifError(err);
done();
});
});
});
});
it('should prevent regular users from approving posts', function (done) {
socketPosts.accept({ uid: uid }, { id: queueId }, function (err) {
assert.equal(err.message, '[[error:no-privileges]]');

Loading…
Cancel
Save