diff --git a/nodebb-theme-slackers/templates/partials/topic/post-menu-list.tpl b/nodebb-theme-slackers/templates/partials/topic/post-menu-list.tpl
new file mode 100644
index 0000000000..ceb32ca8a1
--- /dev/null
+++ b/nodebb-theme-slackers/templates/partials/topic/post-menu-list.tpl
@@ -0,0 +1,146 @@
+{{{ if posts.display_moderator_tools }}}
+
+
+ [[topic:edit]]
+
+
+
+
+ [[topic:delete]]
+
+
+
+
+ [[topic:restore]]
+
+
+{{{ if posts.display_purge_tools }}}
+
+
+ [[topic:purge]]
+
+
+{{{ end }}}
+
+{{{ if posts.display_move_tools }}}
+
+
+ [[topic:move]]
+
+
+{{{ end }}}
+
+{{{ if !posts.verify }}}
+
+
+ Verify Message
+
+
+{{{ else }}}
+
+
+ Un-Verify Message
+
+
+{{{ end }}}
+
+{{{ if posts.display_change_owner_tools }}}
+
+
+ [[topic:change-owner]]
+
+
+{{{ end }}}
+
+{{{ if posts.ip }}}
+
+
+ [[topic:copy-ip]] {posts.ip}
+
+
+{{{ if posts.display_ip_ban }}}
+
+
+ [[topic:ban-ip]] {posts.ip}
+
+
+{{{ end }}}
+{{{ end }}}
+{{{ end }}}
+
+{{{ each posts.tools }}}
+
+
+ {{./html}}
+
+
+{{{ end }}}
+
+{{{ if !posts.deleted }}}
+ {{{ if posts.display_history}}}
+
+
+ [[topic:view-history]]
+
+
+ {{{ end }}}
+
+ {{{ if config.loggedIn }}}
+
+
+
+ [[topic:bookmark]]
+ {posts.bookmarks}
+
+
+ {{{ end }}}
+
+
+
+ [[topic:copy-permalink]]
+
+
+
+ {{{ if postSharing.length }}}
+ {{{ if config.loggedIn }}}{{{ end }}}
+
+ {{{ end }}}
+
+ {{{ each postSharing }}}
+
+ {{{ end }}}
+
+{{{ end }}}
+
+{{{ if posts.display_flag_tools }}}
+
+
+
+ [[topic:flag-post]]
+
+
+ [[topic:already-flagged]]
+
+
+{{{ if (!posts.selfPost && posts.uid) }}}
+
+ [[topic:flag-user]]
+
+{{{ end }}}
+{{{ end }}}
+
+{{{ if posts.display_moderator_tools }}}
+{{{ if posts.flags.exists }}}
+
+ [[topic:view-flag-report]]
+
+{{{ if (posts.flags.state == "open") }}}
+
+ [[topic:resolve-flag]]
+
+{{{ end }}}
+{{{ end }}}
+{{{ end }}}
diff --git a/nodebb-theme-slackers/templates/partials/topic/post.tpl b/nodebb-theme-slackers/templates/partials/topic/post.tpl
new file mode 100644
index 0000000000..c8c3309831
--- /dev/null
+++ b/nodebb-theme-slackers/templates/partials/topic/post.tpl
@@ -0,0 +1,130 @@
+{{{ if (!./index && widgets.mainpost-header.length) }}}
+
+ {{{ each widgets.mainpost-header }}}
+ {widgets.mainpost-header.html}
+ {{{ end }}}
+
+{{{ end }}}
+
+
+
+
+
+
+ {posts.content}
+
+
+
+
+
+{{{ if (!./index && widgets.mainpost-footer.length) }}}
+
+ {{{ each widgets.mainpost-footer }}}
+ {widgets.mainpost-footer.html}
+ {{{ end }}}
+
+{{{ end }}}
\ No newline at end of file
diff --git a/public/openapi/components/schemas/PostObject.yaml b/public/openapi/components/schemas/PostObject.yaml
index f49297e938..88b56b1c04 100644
--- a/public/openapi/components/schemas/PostObject.yaml
+++ b/public/openapi/components/schemas/PostObject.yaml
@@ -16,6 +16,8 @@ PostObject:
type: number
deleted:
type: boolean
+ verify:
+ type: number
answered:
type: number
upvotes:
@@ -141,4 +143,4 @@ PostObject:
isMainPost:
type: boolean
replies:
- type: number
\ No newline at end of file
+ type: number
diff --git a/public/openapi/read/topic/topic_id.yaml b/public/openapi/read/topic/topic_id.yaml
index 977eef98ab..fd4412dc2a 100644
--- a/public/openapi/read/topic/topic_id.yaml
+++ b/public/openapi/read/topic/topic_id.yaml
@@ -67,6 +67,10 @@ get:
type: number
deleted:
type: number
+ verify:
+ type: number
+ verifyUid:
+ type: number
answered:
type: number
upvotes:
@@ -447,4 +451,4 @@ get:
- tid
- $ref: ../../components/schemas/Pagination.yaml#/Pagination
- $ref: ../../components/schemas/Breadcrumbs.yaml#/Breadcrumbs
- - $ref: ../../components/schemas/CommonProps.yaml#/CommonProps
\ No newline at end of file
+ - $ref: ../../components/schemas/CommonProps.yaml#/CommonProps
diff --git a/public/openapi/write.yaml b/public/openapi/write.yaml
index c59b9bce29..aea404e425 100644
--- a/public/openapi/write.yaml
+++ b/public/openapi/write.yaml
@@ -186,6 +186,8 @@ paths:
$ref: 'write/posts/pid/upvoters.yaml'
/posts/{pid}/bookmark:
$ref: 'write/posts/pid/bookmark.yaml'
+ /posts/{pid}/verify:
+ $ref: 'write/posts/pid/verify.yaml'
/posts/{pid}/diffs:
$ref: 'write/posts/pid/diffs.yaml'
/posts/{pid}/diffs/{since}:
@@ -261,4 +263,4 @@ paths:
/files/:
$ref: 'write/files.yaml'
/files/folder:
- $ref: 'write/files/folder.yaml'
\ No newline at end of file
+ $ref: 'write/files/folder.yaml'
diff --git a/public/openapi/write/posts/pid.yaml b/public/openapi/write/posts/pid.yaml
index 8ba44a033a..89df2d6b0d 100644
--- a/public/openapi/write/posts/pid.yaml
+++ b/public/openapi/write/posts/pid.yaml
@@ -40,6 +40,10 @@ get:
type: number
deleted:
type: number
+ verify:
+ type: number
+ verifyUid:
+ type: number
answered:
type: number
upvotes:
@@ -142,4 +146,4 @@ delete:
$ref: ../../components/schemas/Status.yaml#/Status
response:
type: object
- properties: {}
\ No newline at end of file
+ properties: {}
diff --git a/public/openapi/write/posts/pid/replies.yaml b/public/openapi/write/posts/pid/replies.yaml
index 78042a6afd..99f48aa325 100644
--- a/public/openapi/write/posts/pid/replies.yaml
+++ b/public/openapi/write/posts/pid/replies.yaml
@@ -45,6 +45,8 @@ get:
type: number
deleted:
type: number
+ verify:
+ type: number
answered:
type: number
upvotes:
diff --git a/public/openapi/write/posts/pid/verify.yaml b/public/openapi/write/posts/pid/verify.yaml
new file mode 100644
index 0000000000..d5f6c8517f
--- /dev/null
+++ b/public/openapi/write/posts/pid/verify.yaml
@@ -0,0 +1,26 @@
+put:
+ tags:
+ - posts
+ summary: verifies a post
+ description: This operation verifies a post.
+ parameters:
+ - in: path
+ name: pid
+ schema:
+ type: string
+ required: true
+ description: a valid post id
+ example: 2
+ responses:
+ '200':
+ description: Post successfully verified
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ status:
+ $ref: ../../../components/schemas/Status.yaml#/Status
+ response:
+ type: object
+ properties: {}
diff --git a/public/src/client/topic/events.js b/public/src/client/topic/events.js
index 2f52e25446..8894d62358 100644
--- a/public/src/client/topic/events.js
+++ b/public/src/client/topic/events.js
@@ -40,6 +40,9 @@ define('forum/topic/events', [
'posts.bookmark': togglePostBookmark,
'posts.unbookmark': togglePostBookmark,
+ 'posts.verify': toggleVerifyMessage,
+ 'posts.unverify': toggleVerifyMessage,
+
'posts.answer': toggleAnswered,
'posts.unanswer': toggleAnswered,
@@ -68,6 +71,10 @@ define('forum/topic/events', [
}
};
+ function toggleVerifyMessage(data) {
+ console.log(data);
+ }
+
function onUserStatusChange(data) {
app.updateUserStatus($('[data-uid="' + data.uid + '"] [component="user/status"]'), data.status);
}
diff --git a/public/src/client/topic/postTools.js b/public/src/client/topic/postTools.js
index f8d2ca8933..d32ab12fac 100644
--- a/public/src/client/topic/postTools.js
+++ b/public/src/client/topic/postTools.js
@@ -129,6 +129,10 @@ define('forum/topic/postTools', [
return bookmarkPost($(this), getData($(this), 'data-pid'));
});
+ postContainer.on('click', '[component="post/verify"]', function () {
+ return verifyMessage($(this));
+ });
+
postContainer.on('click', '[component="post/upvote"]', function () {
return votes.toggleVote($(this), '.upvoted', 1);
});
@@ -404,6 +408,14 @@ define('forum/topic/postTools', [
postAction(action, pid);
}
+ async function verifyMessage(button) {
+ const pid = getData(button, 'data-pid');
+ const method = 'put';
+ const action = 'verify';
+ console.log('trying to call api');
+ api[method](`/posts/${pid}/${action}`).catch(alerts.error);
+ }
+
function purgePost(button) {
postAction('purge', getData(button, 'data-pid'));
}
diff --git a/src/api/posts.js b/src/api/posts.js
index 80ff4360a8..44c4ca7a03 100644
--- a/src/api/posts.js
+++ b/src/api/posts.js
@@ -421,6 +421,14 @@ postsAPI.unbookmark = async function (caller, data) {
return await apiHelpers.postCommand(caller, 'unbookmark', 'bookmarked', '', data);
};
+postsAPI.verify = async function (caller, data) {
+ return await apiHelpers.postCommand(caller, 'verify', 'verify', '', data);
+};
+
+postsAPI.unverify = async function (caller, data) {
+ return await apiHelpers.postCommand(caller, 'unverify', 'unverify', '', data);
+};
+
async function diffsPrivilegeCheck(pid, uid) {
const [deleted, privilegesData] = await Promise.all([
posts.getPostField(pid, 'deleted'),
diff --git a/src/controllers/write/posts.js b/src/controllers/write/posts.js
index 5e592fdeb8..fc58594ffc 100644
--- a/src/controllers/write/posts.js
+++ b/src/controllers/write/posts.js
@@ -153,6 +153,18 @@ Posts.unbookmark = async (req, res) => {
helpers.formatApiResponse(200, res);
};
+Posts.verify = async (req, res) => {
+ const data = await mock(req);
+ await api.posts.verify(req, data);
+ helpers.formatApiResponse(200, res);
+};
+
+Posts.unverify = async (req, res) => {
+ const data = await mock(req);
+ await api.posts.unverify(req, data);
+ helpers.formatApiResponse(200, res);
+};
+
Posts.answer = async (req, res) => {
const data = await mock(req);
await api.posts.answer(req, data);
@@ -162,6 +174,7 @@ Posts.answer = async (req, res) => {
Posts.unanswer = async (req, res) => {
const data = await mock(req);
await api.posts.unanswer(req, data);
+
helpers.formatApiResponse(200, res);
};
diff --git a/src/posts/data.js b/src/posts/data.js
index b2bcb8555c..1889c5d2d5 100644
--- a/src/posts/data.js
+++ b/src/posts/data.js
@@ -7,7 +7,8 @@ const utils = require('../utils');
const intFields = [
'uid', 'pid', 'tid', 'deleted', 'timestamp',
'upvotes', 'downvotes', 'deleterUid', 'edited',
- 'replies', 'bookmarks', 'answered', 'answererUid',
+ 'replies', 'bookmarks', 'verify', 'verifyUid',
+ 'answered', 'answererUid',
];
module.exports = function (Posts) {
diff --git a/src/posts/index.js b/src/posts/index.js
index 9a055ead2c..3dc9e4ddd2 100644
--- a/src/posts/index.js
+++ b/src/posts/index.js
@@ -25,6 +25,7 @@ require('./votes')(Posts);
require('./bookmarks')(Posts);
require('./answer')(Posts);
require('./queue')(Posts);
+require('./verify')(Posts);
require('./diffs')(Posts);
require('./uploads')(Posts);
diff --git a/src/posts/summary.js b/src/posts/summary.js
index f27c8c56b1..927f071ee8 100644
--- a/src/posts/summary.js
+++ b/src/posts/summary.js
@@ -20,7 +20,8 @@ module.exports = function (Posts) {
options.parse = options.hasOwnProperty('parse') ? options.parse : true;
options.extraFields = options.hasOwnProperty('extraFields') ? options.extraFields : [];
- const fields = ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted', 'upvotes', 'downvotes', 'replies', 'handle', 'answered'].concat(options.extraFields);
+
+ const fields = ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted', 'upvotes', 'downvotes', 'replies', 'handle', 'answered', 'verify'].concat(options.extraFields);
let posts = await Posts.getPostsFields(pids, fields);
posts = posts.filter(Boolean);
diff --git a/src/posts/verify.js b/src/posts/verify.js
new file mode 100644
index 0000000000..08f1ab621f
--- /dev/null
+++ b/src/posts/verify.js
@@ -0,0 +1,27 @@
+'use strict';
+
+const plugins = require('../plugins');
+
+module.exports = function (Posts) {
+ Posts.verify = async function (pid, uid) {
+ return await toggleVerify('verify', pid, uid);
+ };
+
+ Posts.unverify = async function (pid, uid) {
+ return await toggleVerify('unverify', pid, uid);
+ };
+
+ async function toggleVerify(type, pid, uid) {
+ const isVerifying = type === 'verify';
+ await plugins.hooks.fire(`filter:post.${type}`, { pid: pid, uid: uid });
+
+ await Posts.setPostFields(pid, {
+ verify: isVerifying ? 1 : 0,
+ verifyUid: isVerifying ? uid : 0,
+ });
+
+ const postData = await Posts.getPostFields(pid, ['pid', 'tid', 'uid', 'content', 'timestamp']);
+
+ return postData;
+ }
+};
diff --git a/src/routes/write/posts.js b/src/routes/write/posts.js
index e573bbb9b0..29d1520ef7 100644
--- a/src/routes/write/posts.js
+++ b/src/routes/write/posts.js
@@ -32,6 +32,9 @@ module.exports = function () {
setupApiRoute(router, 'put', '/:pid/bookmark', middlewares, controllers.write.posts.bookmark);
setupApiRoute(router, 'delete', '/:pid/bookmark', middlewares, controllers.write.posts.unbookmark);
+ setupApiRoute(router, 'put', '/:pid/verify', middlewares, controllers.write.posts.verify);
+ setupApiRoute(router, 'put', '/:pid/verify', middlewares, controllers.write.posts.unverify);
+
setupApiRoute(router, 'get', '/:pid/diffs', [middleware.assert.post], controllers.write.posts.getDiffs);
setupApiRoute(router, 'get', '/:pid/diffs/:since', [middleware.assert.post], controllers.write.posts.loadDiff);
setupApiRoute(router, 'put', '/:pid/diffs/:since', middlewares, controllers.write.posts.restoreDiff);
diff --git a/test/posts.js b/test/posts.js
index 4b78fa378f..063c341b96 100644
--- a/test/posts.js
+++ b/test/posts.js
@@ -281,10 +281,19 @@ describe('Post\'s', () => {
});
});
+ describe('verifying', async () => {
+ it('should mark post verified', async () => {
+ await apiPosts.verify({ uid: voterUid }, { pid: postData.pid, room_id: `topic_${postData.tid}` });
+ const isVerified = await posts.getPostField(postData.pid, 'verify');
+ assert.strictEqual(isVerified, 1);
+ });
+ });
+
describe('answering', async () => {
it('should mark post answered', async () => {
const data = await apiPosts.answer({ uid: voterUid }, { pid: postData.pid, room_id: `topic_${postData.tid}` });
const isAnswered = await posts.getPostField(postData.pid, 'answered');
+
assert.strictEqual(isAnswered, 1);
});
});