@nodebb/nodebb-plugin-reactions 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/library.js +34 -6
- package/package.json +2 -2
- package/public/admin.js +36 -3
- package/templates/admin/plugins/reactions/partials/sorted-list/emoji-form.tpl +10 -0
- package/templates/admin/plugins/reactions/partials/sorted-list/emoji-item.tpl +12 -0
- package/templates/admin/plugins/reactions.tpl +22 -6
package/library.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const _ = require.main.require('lodash');
|
|
4
4
|
const meta = require.main.require('./src/meta');
|
|
5
5
|
const user = require.main.require('./src/user');
|
|
6
|
+
const posts = require.main.require('./src/posts');
|
|
6
7
|
const db = require.main.require('./src/database');
|
|
7
8
|
const routesHelpers = require.main.require('./src/routes/helpers');
|
|
8
9
|
const websockets = require.main.require('./src/socket.io/index');
|
|
@@ -139,9 +140,9 @@ ReactionsPlugin.deleteReactions = async function (hookData) {
|
|
|
139
140
|
const keys = [];
|
|
140
141
|
pidsReactions.forEach((reactions, index) => {
|
|
141
142
|
keys.push(
|
|
142
|
-
...reactions.map(reaction => `pid:${
|
|
143
|
+
...reactions.map(reaction => `pid:${pids[index]}:reaction:${reaction}`),
|
|
143
144
|
`pid:${pids[index]}:reactions`,
|
|
144
|
-
)
|
|
145
|
+
);
|
|
145
146
|
});
|
|
146
147
|
|
|
147
148
|
await db.deleteAll(keys);
|
|
@@ -176,6 +177,20 @@ async function sendEvent(data, eventName) {
|
|
|
176
177
|
}
|
|
177
178
|
}
|
|
178
179
|
|
|
180
|
+
async function getReactionReputation(reaction) {
|
|
181
|
+
const settings = await meta.settings.get('reactions');
|
|
182
|
+
const reactionsReps = settings['reaction-reputations'] || [];
|
|
183
|
+
const foundReaction = reactionsReps.find(r => r.reaction === reaction);
|
|
184
|
+
return foundReaction ? parseInt(foundReaction.reputation, 10) || 0 : 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function giveOwnerReactionReputation(reactionReputation, pid) {
|
|
188
|
+
const ownerUid = await posts.getPostField(pid, 'uid');
|
|
189
|
+
if (parseInt(ownerUid, 10) > 0) {
|
|
190
|
+
await user.incrementUserReputationBy(ownerUid, reactionReputation);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
179
194
|
SocketPlugins.reactions = {
|
|
180
195
|
addPostReaction: async function (socket, data) {
|
|
181
196
|
if (!socket.uid) {
|
|
@@ -191,10 +206,11 @@ SocketPlugins.reactions = {
|
|
|
191
206
|
try {
|
|
192
207
|
const settings = await meta.settings.get('reactions');
|
|
193
208
|
const maximumReactions = settings.maximumReactions || DEFAULT_MAX_EMOTES;
|
|
194
|
-
|
|
195
|
-
const [totalReactions, isMember] = await Promise.all([
|
|
209
|
+
const [totalReactions, isMember, alreadyReacted, reactionReputation] = await Promise.all([
|
|
196
210
|
db.setCount(`pid:${data.pid}:reactions`),
|
|
197
211
|
db.isSetMember(`pid:${data.pid}:reactions`, data.reaction),
|
|
212
|
+
db.isSetMember(`pid:${data.pid}:reaction:${data.reaction}`, socket.uid),
|
|
213
|
+
getReactionReputation(data.reaction),
|
|
198
214
|
]);
|
|
199
215
|
|
|
200
216
|
if (!isMember && totalReactions >= maximumReactions) {
|
|
@@ -206,6 +222,10 @@ SocketPlugins.reactions = {
|
|
|
206
222
|
db.setAdd(`pid:${data.pid}:reaction:${data.reaction}`, socket.uid),
|
|
207
223
|
]);
|
|
208
224
|
|
|
225
|
+
if (!alreadyReacted && reactionReputation > 0) {
|
|
226
|
+
await giveOwnerReactionReputation(reactionReputation, data.pid);
|
|
227
|
+
}
|
|
228
|
+
|
|
209
229
|
await sendEvent(data, 'event:reactions.addPostReaction');
|
|
210
230
|
} catch (e) {
|
|
211
231
|
console.error(e);
|
|
@@ -223,13 +243,21 @@ SocketPlugins.reactions = {
|
|
|
223
243
|
data.uid = socket.uid;
|
|
224
244
|
|
|
225
245
|
try {
|
|
226
|
-
await
|
|
246
|
+
const [hasReacted, reactionReputation] = await Promise.all([
|
|
247
|
+
db.isSetMember(`pid:${data.pid}:reaction:${data.reaction}`, socket.uid),
|
|
248
|
+
getReactionReputation(data.reaction),
|
|
249
|
+
]);
|
|
250
|
+
if (hasReacted) {
|
|
251
|
+
await db.setRemove(`pid:${data.pid}:reaction:${data.reaction}`, socket.uid);
|
|
252
|
+
}
|
|
227
253
|
|
|
228
254
|
const reactionCount = await db.setCount(`pid:${data.pid}:reaction:${data.reaction}`);
|
|
229
255
|
if (reactionCount === 0) {
|
|
230
256
|
await db.setRemove(`pid:${data.pid}:reactions`, data.reaction);
|
|
231
257
|
}
|
|
232
|
-
|
|
258
|
+
if (hasReacted && reactionReputation > 0) {
|
|
259
|
+
await giveOwnerReactionReputation(-reactionReputation, data.pid);
|
|
260
|
+
}
|
|
233
261
|
await sendEvent(data, 'event:reactions.removePostReaction');
|
|
234
262
|
} catch (e) {
|
|
235
263
|
console.error(e);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodebb/nodebb-plugin-reactions",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"nbbpm": {
|
|
5
5
|
"compatibility": "^1.19.7"
|
|
6
6
|
},
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"name": "Barış Soner Uşaklı",
|
|
32
32
|
"email": "baris@nodebb.org",
|
|
33
33
|
"url": "https://github.com/barisusakli"
|
|
34
|
-
|
|
34
|
+
}
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {},
|
|
37
37
|
"peerDependencies": {
|
package/public/admin.js
CHANGED
|
@@ -1,9 +1,42 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
define('admin/plugins/reactions', [
|
|
3
|
+
define('admin/plugins/reactions', [
|
|
4
|
+
'settings', 'alerts', 'hooks', 'emoji-dialog', 'emoji',
|
|
5
|
+
], function (Settings, alerts, hooks, emojiDialog, emoji) {
|
|
4
6
|
var ACP = {};
|
|
5
7
|
ACP.init = function () {
|
|
6
|
-
|
|
8
|
+
emoji.init(function () {
|
|
9
|
+
Settings.load('reactions', $('.reactions-settings'), onSettingsLoaded);
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function onSettingsLoaded() {
|
|
14
|
+
hooks.on('action:settings.sorted-list.parse', function (data) {
|
|
15
|
+
const reactionEl = data.itemHtml.find('[data-reaction]');
|
|
16
|
+
if (reactionEl.length) {
|
|
17
|
+
const reaction = reactionEl.attr('data-reaction');
|
|
18
|
+
if (reaction) {
|
|
19
|
+
const foundEmoji = emoji.table[reaction]
|
|
20
|
+
if (foundEmoji) {
|
|
21
|
+
reactionEl.html(emoji.buildEmoji(foundEmoji));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
hooks.on('action:settings.sorted-list.modal', function (data) {
|
|
28
|
+
const { modal } = data;
|
|
29
|
+
modal.removeAttr('tabindex');
|
|
30
|
+
modal.find('#reaction').off('click').on('click', function () {
|
|
31
|
+
emojiDialog.toggle(modal.find('#reaction')[0], function (_, name, dialog) {
|
|
32
|
+
emojiDialog.dialogActions.close(dialog);
|
|
33
|
+
modal.find('#reaction').val(name);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
modal.off('hide.bs.modal').on('hide.bs.modal', function () {
|
|
37
|
+
emojiDialog.dialogActions.close($('#emoji-dialog'));
|
|
38
|
+
});
|
|
39
|
+
});
|
|
7
40
|
|
|
8
41
|
$('#save').on('click', function () {
|
|
9
42
|
Settings.save('reactions', $('.reactions-settings'), function () {
|
|
@@ -15,7 +48,7 @@ define('admin/plugins/reactions', ['settings', 'alerts'], function (Settings, a
|
|
|
15
48
|
});
|
|
16
49
|
});
|
|
17
50
|
});
|
|
18
|
-
}
|
|
51
|
+
}
|
|
19
52
|
|
|
20
53
|
return ACP;
|
|
21
54
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<form>
|
|
2
|
+
<div class="form-group">
|
|
3
|
+
<label for="reaction">Reaction</label>
|
|
4
|
+
<input type="text" id="reaction" name="reaction" class="form-control" placeholder="Reaction" />
|
|
5
|
+
</div>
|
|
6
|
+
<div class="form-group">
|
|
7
|
+
<label for="reputation">Reputation</label>
|
|
8
|
+
<input type="number" id="reputation" name="reputation" class="form-control" placeholder="reputation" />
|
|
9
|
+
</div>
|
|
10
|
+
</form>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<li data-type="item" class="list-group-item">
|
|
2
|
+
<div class="row">
|
|
3
|
+
<div class="col-xs-9">
|
|
4
|
+
<span data-reaction="{reaction}"></span><strong> {reaction}</strong><br />
|
|
5
|
+
<small>Reputation: {reputation}</small>
|
|
6
|
+
</div>
|
|
7
|
+
<div class="col-xs-3 text-right">
|
|
8
|
+
<button type="button" data-type="edit" class="btn btn-info">Edit</button>
|
|
9
|
+
<button type="button" data-type="remove" class="btn btn-danger">Delete</button>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</li>
|
|
@@ -1,14 +1,30 @@
|
|
|
1
|
-
<
|
|
2
|
-
<div class="
|
|
3
|
-
|
|
4
|
-
<
|
|
1
|
+
<form role="form" class="reactions-settings">
|
|
2
|
+
<div class="row">
|
|
3
|
+
<div class="col-sm-2 col-xs-12 settings-header">Reactions plugin settings</div>
|
|
4
|
+
<div class="col-sm-10 col-xs-12">
|
|
5
5
|
<div class="form-group">
|
|
6
6
|
<label>Maximum unique reactions per post</label>
|
|
7
7
|
<input type="text" class="form-control" id="maximumReactions" name="maximumReactions">
|
|
8
8
|
</div>
|
|
9
|
-
</
|
|
9
|
+
</div>
|
|
10
10
|
</div>
|
|
11
|
-
|
|
11
|
+
<div class="row">
|
|
12
|
+
<div class="col-sm-2 col-xs-12 settings-header">Reaction Reputations (Optional)</div>
|
|
13
|
+
<div class="col-sm-10 col-xs-12">
|
|
14
|
+
<p class="help-text">
|
|
15
|
+
You can assign a reputation to individual reactions. When a reaction is applied to a post, the owner of that post will get this reputation.
|
|
16
|
+
</p>
|
|
17
|
+
<div class="form-group" data-type="sorted-list" data-sorted-list="reaction-reputations" data-item-template="admin/plugins/reactions/partials/sorted-list/emoji-item" data-form-template="admin/plugins/reactions/partials/sorted-list/emoji-form">
|
|
18
|
+
<ul data-type="list" class="list-group"></ul>
|
|
19
|
+
<button type="button" data-type="add" class="btn btn-info">Add Item</button>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</form>
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
12
28
|
|
|
13
29
|
<button id="save" class="floating-button mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored">
|
|
14
30
|
<i class="material-icons">save</i>
|