nodebb-plugin-poll 3.2.8 → 4.0.0
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/README.md +14 -32
- package/languages/en_GB/poll.json +12 -4
- package/languages/fr/poll.json +46 -38
- package/lib/config.js +13 -29
- package/lib/hooks.js +82 -67
- package/lib/nodebb.js +0 -1
- package/lib/poll.js +242 -121
- package/lib/sockets.js +60 -44
- package/lib/vote.js +29 -16
- package/library.js +27 -25
- package/package.json +4 -4
- package/plugin.json +8 -5
- package/public/js/admin.js +3 -32
- package/public/js/poll/creator.js +230 -177
- package/public/js/poll/main.js +64 -28
- package/public/js/poll/view.js +67 -81
- package/public/scss/style.scss +1 -4
- package/schema.md +24 -0
- package/templates/admin/partials/widgets/poll.tpl +2 -2
- package/templates/admin/plugins/poll.tpl +63 -48
- package/templates/poll/creator.tpl +18 -22
- package/templates/poll/manage.tpl +18 -0
- package/templates/poll/option-input.tpl +6 -0
- package/templates/poll/view/details.tpl +7 -6
- package/templates/poll/view/voting.tpl +4 -4
- package/templates/poll/view.tpl +14 -9
- package/upgrades/poll-4.0-upgrade.js +128 -0
- package/lib/scheduler.js +0 -52
- package/lib/serializer.js +0 -4
- package/public/js/poll/serializer.js +0 -173
|
@@ -1,210 +1,240 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
(function (Poll) {
|
|
4
|
-
|
|
4
|
+
const Creator = {};
|
|
5
5
|
|
|
6
6
|
function init() {
|
|
7
7
|
$(window).on('action:composer.enhanced', initComposer);
|
|
8
|
+
}
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
function initComposer(ev, { postContainer, postData }) {
|
|
11
|
+
require(['composer', 'composer/formatting'], function (composer, formatting) {
|
|
12
|
+
if (formatting) {
|
|
13
|
+
formatting.addButtonDispatch('poll', function (/* textarea */) {
|
|
14
|
+
onPollButtonClicked(composer);
|
|
15
|
+
});
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
if ($.Redactor) {
|
|
13
|
-
if (data.composerData.isMain && $.Redactor.opts.plugins.indexOf('poll') === -1) {
|
|
14
|
-
$.Redactor.opts.plugins.push('poll');
|
|
15
|
-
} else if (!data.composerData.isMain && $.Redactor.opts.plugins.indexOf('poll') !== -1) {
|
|
16
|
-
$.Redactor.opts.plugins.splice($.Redactor.opts.plugins.indexOf('poll'), 1);
|
|
17
|
-
}
|
|
17
|
+
updateComposerBadgeCount(postContainer, postData.polls ? postData.polls.length : 0);
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
async function onPollButtonClicked(composer) {
|
|
23
|
+
const postData = composer.posts[composer.active];
|
|
24
|
+
if (!postData) {
|
|
25
|
+
return showAlert('error', '[[poll:error.invalid-post]]');
|
|
26
|
+
}
|
|
27
|
+
if (parseInt(postData.cid, 10) === 0) {
|
|
28
|
+
return showAlert('error', '[[error:category-not-selected]]');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const canCreate = await socket.emit('plugins.poll.canCreate', {
|
|
32
|
+
cid: postData.cid,
|
|
33
|
+
pid: postData.pid,
|
|
34
|
+
tid: postData.tid,
|
|
29
35
|
});
|
|
36
|
+
if (!canCreate) {
|
|
37
|
+
return showAlert('error', '[[error:no-privileges]]');
|
|
38
|
+
}
|
|
39
|
+
postData.polls = postData.polls || [];
|
|
40
|
+
await openManageModal({ postData, uuid: composer.active });
|
|
30
41
|
}
|
|
31
42
|
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
43
|
+
async function openManageModal(payload) {
|
|
44
|
+
const bootbox = await app.require('bootbox');
|
|
45
|
+
const { postData, modal, uuid } = payload;
|
|
46
|
+
const html = await app.parseAndTranslate('poll/manage', { post: postData });
|
|
47
|
+
|
|
48
|
+
if (modal) {
|
|
49
|
+
modal.find('.bootbox-body').html(html[0].outerHTML);
|
|
50
|
+
handleSort({ modal, polls: postData.polls });
|
|
51
|
+
} else {
|
|
52
|
+
const modal = bootbox.dialog({
|
|
53
|
+
title: '[[poll:manage-polls]]',
|
|
54
|
+
message: html,
|
|
55
|
+
className: 'poll-manage',
|
|
56
|
+
buttons: {
|
|
57
|
+
add: {
|
|
58
|
+
label: '<i class="fa fa-plus"></i> [[poll:add-poll]]',
|
|
59
|
+
className: 'btn-success',
|
|
60
|
+
callback: () => {
|
|
61
|
+
Creator.show('[[poll:creator_title]]', {
|
|
62
|
+
// temp id, will be replaced in the backend before saving
|
|
63
|
+
// used to identify the poll in the manage modal after creation
|
|
64
|
+
// so we can edit/delete
|
|
65
|
+
pollId: Date.now(),
|
|
66
|
+
maximumVotesPerUser: config.poll.maximumVotesPerUser,
|
|
67
|
+
}, config.poll).then((newPoll) => {
|
|
68
|
+
if (newPoll) {
|
|
69
|
+
postData.polls.push(newPoll);
|
|
70
|
+
}
|
|
71
|
+
openManageModal({ ...payload, modal });
|
|
72
|
+
const postContainer = $(`[component="composer"][data-uuid="${uuid}"]`);
|
|
73
|
+
updateComposerBadgeCount(postContainer, postData.polls.length);
|
|
74
|
+
});
|
|
75
|
+
return false;
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
close: {
|
|
79
|
+
label: '[[global:close]]',
|
|
80
|
+
className: 'btn-primary',
|
|
81
|
+
},
|
|
58
82
|
},
|
|
59
|
-
};
|
|
60
|
-
|
|
83
|
+
});
|
|
84
|
+
handleDelete({ ...payload, modal });
|
|
85
|
+
handleEdit({ ...payload, modal });
|
|
86
|
+
handleSort({ modal, polls: postData.polls });
|
|
87
|
+
}
|
|
61
88
|
}
|
|
62
89
|
|
|
63
|
-
function
|
|
64
|
-
require(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
socket.emit('plugins.poll.canCreate', {
|
|
74
|
-
cid: post.cid,
|
|
75
|
-
pid: post.pid,
|
|
76
|
-
}, function (err, canCreate) {
|
|
77
|
-
if (err) {
|
|
78
|
-
return alerts.error(err);
|
|
90
|
+
async function handleDelete(payload) {
|
|
91
|
+
const bootbox = await app.require('bootbox');
|
|
92
|
+
const { uuid, modal, postData } = payload;
|
|
93
|
+
modal.on('click', 'button[data-action="remove"]', function () {
|
|
94
|
+
const clickedPollId = $(this).attr('data-poll-id');
|
|
95
|
+
bootbox.confirm('[[poll:confirm-remove]]', (ok) => {
|
|
96
|
+
if (!ok) {
|
|
97
|
+
return;
|
|
79
98
|
}
|
|
80
|
-
|
|
81
|
-
|
|
99
|
+
const poll = postData?.polls.find(poll => String(poll.pollId) === clickedPollId);
|
|
100
|
+
if (poll) {
|
|
101
|
+
postData.polls = postData.polls.filter(poll => String(poll.pollId) !== clickedPollId);
|
|
102
|
+
openManageModal(payload);
|
|
103
|
+
const postContainer = $(`[component="composer"][data-uuid="${uuid}"]`);
|
|
104
|
+
updateComposerBadgeCount(postContainer, postData.polls.length);
|
|
82
105
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
var poll = {};
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
};
|
|
89
109
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
110
|
+
function handleEdit(payload) {
|
|
111
|
+
const { modal, postData } = payload;
|
|
112
|
+
modal.on('click', 'button[data-action="edit"]', async function () {
|
|
113
|
+
const clickedPollId = $(this).attr('data-poll-id');
|
|
114
|
+
const poll = postData?.polls.find(poll => String(poll.pollId) === clickedPollId);
|
|
115
|
+
if (poll) {
|
|
116
|
+
const editedPoll = await Creator.show(
|
|
117
|
+
'[[poll:edit-a-poll-title]]',
|
|
118
|
+
poll,
|
|
119
|
+
config.poll,
|
|
120
|
+
);
|
|
121
|
+
if (editedPoll) {
|
|
122
|
+
postData.polls = postData.polls.map(
|
|
123
|
+
p => String(p.pollId) === String(editedPoll.pollId) ? editedPoll : p
|
|
124
|
+
);
|
|
125
|
+
openManageModal(payload);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
93
130
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
131
|
+
function handleSort({ modal, polls }) {
|
|
132
|
+
if (Array.isArray(polls) && polls.length > 1) {
|
|
133
|
+
const selectorEl = modal.find('.topic-poll-modal');
|
|
134
|
+
selectorEl.sortable({
|
|
135
|
+
handle: '[component="sort/handle"]',
|
|
136
|
+
axis: 'y',
|
|
137
|
+
zIndex: 9999,
|
|
138
|
+
items: '[component="post/poll/item"]',
|
|
139
|
+
});
|
|
140
|
+
selectorEl.on('sortupdate', function () {
|
|
141
|
+
if (!polls) return;
|
|
142
|
+
const newOrder = [];
|
|
143
|
+
selectorEl.find('[component="post/poll/item"]').each(function () {
|
|
144
|
+
const pollId = $(this).attr('data-poll-id');
|
|
145
|
+
const poll = polls.find(p => String(p.pollId) === pollId);
|
|
146
|
+
if (poll) {
|
|
147
|
+
newOrder.push(poll);
|
|
99
148
|
}
|
|
100
|
-
|
|
101
|
-
Creator.show(poll, config, function (data) {
|
|
102
|
-
// Anything invalid will be discarded by the serializer
|
|
103
|
-
var markup = Poll.serializer.deserialize(data, config);
|
|
104
|
-
|
|
105
|
-
// Remove any existing poll markup
|
|
106
|
-
textarea.value = Poll.serializer.removeMarkup(textarea.value);
|
|
107
|
-
|
|
108
|
-
// Insert the poll markup at the bottom
|
|
109
|
-
if (textarea.value.charAt(textarea.value.length - 1) !== '\n') {
|
|
110
|
-
markup = '\n' + markup;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if ($.Redactor) {
|
|
114
|
-
textarea.redactor(textarea.value + '<p>' + markup + '</p>');
|
|
115
|
-
} else {
|
|
116
|
-
controls.insertIntoTextarea(textarea, markup);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
149
|
});
|
|
150
|
+
// Mutate polls array in place
|
|
151
|
+
polls.length = 0;
|
|
152
|
+
Array.prototype.push.apply(polls, newOrder);
|
|
120
153
|
});
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
Creator.show = function (poll, config, callback) {
|
|
125
|
-
if (poll.hasOwnProperty('info')) {
|
|
126
|
-
return Poll.alertError('Editing not implemented');
|
|
127
154
|
}
|
|
155
|
+
};
|
|
128
156
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
157
|
+
Creator.show = function (modalTitle, poll, config) {
|
|
158
|
+
return new Promise((resolve) => {
|
|
159
|
+
require(['bootbox'], function (bootbox) {
|
|
160
|
+
app.parseAndTranslate('poll/creator', { poll, config }, function (html) {
|
|
161
|
+
const modal = bootbox.dialog({
|
|
162
|
+
title: modalTitle,
|
|
163
|
+
message: html,
|
|
164
|
+
className: 'poll-creator',
|
|
165
|
+
buttons: {
|
|
166
|
+
cancel: {
|
|
167
|
+
label: '[[global:close]]',
|
|
168
|
+
callback: function () {
|
|
169
|
+
resolve(null);
|
|
170
|
+
},
|
|
142
171
|
},
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (obj.settings.end) {
|
|
162
|
-
obj.settings.end = new Date(obj.settings.end).getTime();
|
|
163
|
-
}
|
|
164
|
-
callback(obj);
|
|
165
|
-
return true;
|
|
172
|
+
save: {
|
|
173
|
+
label: '[[modules:bootbox.confirm]]',
|
|
174
|
+
callback: function () {
|
|
175
|
+
clearErrors();
|
|
176
|
+
const form = modal.find('#pollCreator');
|
|
177
|
+
const newPoll = serializeObjectFromForm(form);
|
|
178
|
+
|
|
179
|
+
// Let's be nice and at least show an error if there are no options
|
|
180
|
+
if (newPoll.options.length === 0) {
|
|
181
|
+
error('[[poll:error.no_options]]');
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
resolve(newPoll);
|
|
186
|
+
return true;
|
|
187
|
+
},
|
|
166
188
|
},
|
|
167
189
|
},
|
|
168
|
-
}
|
|
169
|
-
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
handleOptionSort({ modal });
|
|
170
193
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
194
|
+
// Add option adder
|
|
195
|
+
modal.find('#pollAddOption')
|
|
196
|
+
.off('click')
|
|
197
|
+
.on('click', async function (e) {
|
|
198
|
+
const el = $(e.currentTarget);
|
|
199
|
+
if (config.maxOptions <= el.prevAll('input').length) {
|
|
200
|
+
clearErrors();
|
|
201
|
+
error(`[[poll:error.max_options, ${config.maxOptions}]]`);
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
const id = Date.now();
|
|
205
|
+
const newOptionInput = await app.parseAndTranslate('poll/option-input', {
|
|
206
|
+
id: id,
|
|
207
|
+
title: '',
|
|
184
208
|
});
|
|
185
|
-
|
|
186
|
-
|
|
209
|
+
const container = modal.find('#poll-options-container');
|
|
210
|
+
container.append(newOptionInput);
|
|
211
|
+
modal.find(`[data-option-id="${id}"] input`).focus();
|
|
212
|
+
});
|
|
187
213
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
214
|
+
modal.find('#poll-options-container').on('click', '[data-action="remove-option"]', function () {
|
|
215
|
+
$(this).parents('[component="post/poll/option/item"]').remove();
|
|
191
216
|
});
|
|
192
|
-
|
|
193
|
-
if (poll.settings && poll.settings.end) {
|
|
194
|
-
|
|
195
|
-
// flatpickrInstance.setDate(poll.settings.end);
|
|
196
|
-
}
|
|
217
|
+
});
|
|
197
218
|
});
|
|
198
219
|
});
|
|
199
220
|
};
|
|
200
221
|
|
|
201
|
-
function
|
|
202
|
-
|
|
222
|
+
function handleOptionSort({ modal }) {
|
|
223
|
+
const selectorEl = modal.find('#poll-options-container');
|
|
224
|
+
selectorEl.sortable({
|
|
225
|
+
handle: '[component="sort/handle"]',
|
|
226
|
+
axis: 'y',
|
|
227
|
+
zIndex: 9999,
|
|
228
|
+
items: '[component="post/poll/option/item"]',
|
|
229
|
+
});
|
|
230
|
+
}
|
|
203
231
|
|
|
232
|
+
async function error(message) {
|
|
233
|
+
const errorBox = $('#pollErrorBox');
|
|
234
|
+
const translator = await app.require('translator');
|
|
235
|
+
const msgTranslated = await translator.translate(message);
|
|
204
236
|
errorBox.removeClass('hidden');
|
|
205
|
-
errorBox.append(
|
|
206
|
-
|
|
207
|
-
return false;
|
|
237
|
+
errorBox.append(msgTranslated + '<br>');
|
|
208
238
|
}
|
|
209
239
|
|
|
210
240
|
function clearErrors() {
|
|
@@ -212,21 +242,44 @@
|
|
|
212
242
|
}
|
|
213
243
|
|
|
214
244
|
function serializeObjectFromForm(form) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
245
|
+
const obj = form.serializeObject();
|
|
246
|
+
obj.options = obj.options || [];
|
|
247
|
+
obj.id = obj.id || [];
|
|
248
|
+
|
|
249
|
+
const options = obj.options.map((opt, index) => ({
|
|
250
|
+
id: obj.id[index],
|
|
251
|
+
title: opt,
|
|
252
|
+
})).filter(option => option.title?.length);
|
|
253
|
+
|
|
254
|
+
const result = {
|
|
255
|
+
pollId: obj.pollId,
|
|
256
|
+
options: options,
|
|
257
|
+
title: obj.title,
|
|
258
|
+
maximumVotesPerUser: obj.maximumVotesPerUser,
|
|
259
|
+
disallowVoteUpdate: obj.disallowVoteUpdate === 'on' ? 1 : 0,
|
|
260
|
+
allowAnonVoting: obj.allowAnonVoting === 'on' ? 1 : 0,
|
|
261
|
+
end: obj.end ? new Date(obj.end).getTime() : 0,
|
|
225
262
|
};
|
|
226
263
|
|
|
227
264
|
return result;
|
|
228
265
|
}
|
|
229
266
|
|
|
267
|
+
function showAlert(type, message) {
|
|
268
|
+
require(['alerts'], function (alerts) {
|
|
269
|
+
alerts[type](message);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function updateComposerBadgeCount(postContainer, count) {
|
|
274
|
+
require(['composer'], (composer) => {
|
|
275
|
+
composer.updateFormattingBtnBadgeCount(
|
|
276
|
+
postContainer,
|
|
277
|
+
'poll',
|
|
278
|
+
count
|
|
279
|
+
);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
230
283
|
Poll.creator = Creator;
|
|
231
284
|
|
|
232
285
|
init();
|
package/public/js/poll/main.js
CHANGED
|
@@ -4,38 +4,65 @@
|
|
|
4
4
|
|
|
5
5
|
window.Poll = {};
|
|
6
6
|
|
|
7
|
-
(function () {
|
|
7
|
+
$(document).ready(function () {
|
|
8
8
|
window.Poll.alertError = function (message) {
|
|
9
9
|
require(['alerts'], function (alerts) {
|
|
10
10
|
alerts.error(message);
|
|
11
11
|
});
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
require('
|
|
14
|
+
require(['hooks'], function (hooks) {
|
|
15
|
+
// add polls to data that is sent to server on composer submit
|
|
16
|
+
hooks.on('filter:composer.submit', function (hookData) {
|
|
17
|
+
hookData.composerData.polls = hookData.postData.polls || [];
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
hooks.on('filter:composer.drafts.save', function (hookData) {
|
|
21
|
+
const { draft, postData } = hookData;
|
|
22
|
+
if (Object.hasOwn(postData, 'polls')) {
|
|
23
|
+
draft.polls = postData.polls || [];
|
|
24
|
+
}
|
|
25
|
+
return hookData;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
hooks.on('filter:composer.drafts.open', function (hookData) {
|
|
29
|
+
const { draft } = hookData;
|
|
30
|
+
if (Object.hasOwn(draft, 'polls')) {
|
|
31
|
+
hookData.composerData.polls = draft.polls || [];
|
|
32
|
+
}
|
|
33
|
+
return hookData;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
hooks.on('filter:composer.topic.push', function (hookData) {
|
|
37
|
+
hookData.pushData.polls = hookData.data.polls || [];
|
|
38
|
+
return hookData;
|
|
39
|
+
});
|
|
40
|
+
hooks.on('filter:composer.reply.push', function (hookData) {
|
|
41
|
+
hookData.pushData.polls = hookData.data.polls || [];
|
|
42
|
+
return hookData;
|
|
43
|
+
});
|
|
44
|
+
});
|
|
15
45
|
|
|
16
46
|
$(window).on('action:topic.loading', function () {
|
|
17
|
-
|
|
18
|
-
getPollByPost(
|
|
19
|
-
}
|
|
47
|
+
ajaxify.data.posts.forEach((post) => {
|
|
48
|
+
getPollByPost(post);
|
|
49
|
+
});
|
|
20
50
|
});
|
|
21
51
|
|
|
22
52
|
$(window).on('action:posts.loaded', function (ev, data) {
|
|
23
53
|
data.posts.forEach((post) => {
|
|
24
|
-
|
|
25
|
-
getPollByPost(post);
|
|
26
|
-
}
|
|
54
|
+
getPollByPost(post);
|
|
27
55
|
});
|
|
28
56
|
});
|
|
29
57
|
|
|
30
58
|
$(window).on('action:posts.edited', function (ev, data) {
|
|
31
|
-
|
|
32
|
-
getPollByPost(data.post);
|
|
33
|
-
}
|
|
59
|
+
getPollByPost(data.post);
|
|
34
60
|
});
|
|
35
61
|
|
|
36
62
|
$(window).on('action:ajaxify.end', function () {
|
|
37
63
|
$('[data-widget-poll-id]').each(function () {
|
|
38
|
-
|
|
64
|
+
const $this = $(this);
|
|
65
|
+
getPolls([$this.attr('data-widget-poll-id')], $this);
|
|
39
66
|
});
|
|
40
67
|
});
|
|
41
68
|
|
|
@@ -44,25 +71,34 @@ window.Poll = {};
|
|
|
44
71
|
});
|
|
45
72
|
|
|
46
73
|
function getPollByPost(post) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
74
|
+
if (!post || !post.hasOwnProperty('pollIds') || !post.pollIds) return;
|
|
75
|
+
let pollIds;
|
|
76
|
+
try {
|
|
77
|
+
pollIds = JSON.parse(post.pollIds || '[]');
|
|
78
|
+
} catch (err) {
|
|
79
|
+
pollIds = [];
|
|
80
|
+
}
|
|
81
|
+
if (pollIds.length) {
|
|
82
|
+
const postEl = $(`[component="post"][data-pid="${post.pid}"]`);
|
|
83
|
+
getPolls(pollIds, postEl.find('[component="post/content"]'));
|
|
50
84
|
}
|
|
51
85
|
}
|
|
52
86
|
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
|
|
87
|
+
function getPolls(pollIds, container) {
|
|
88
|
+
const validPollIds = pollIds.map(id => parseInt(id, 10)).filter(id => !isNaN(id));
|
|
89
|
+
socket.emit('plugins.poll.get', { pollIds: validPollIds }, async function (err, pollDataArr) {
|
|
90
|
+
if (err) {
|
|
91
|
+
return Poll.alertError(err.message);
|
|
58
92
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return Poll.alertError(err.message);
|
|
62
|
-
}
|
|
93
|
+
pollDataArr.reverse();
|
|
94
|
+
for (const pollData of pollDataArr) {
|
|
63
95
|
pollData.container = container;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
96
|
+
if (container.attr('data-widget-poll-id')) {
|
|
97
|
+
pollData.isWidget = true;
|
|
98
|
+
}
|
|
99
|
+
// eslint-disable-next-line no-await-in-loop
|
|
100
|
+
await Poll.view.load(pollData);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
67
103
|
}
|
|
68
|
-
}
|
|
104
|
+
});
|