nodebb-plugin-poll 1.1.7 → 2.0.2
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/.eslintrc +116 -0
- package/languages/ru/poll.json +15 -15
- package/lib/config.js +16 -17
- package/lib/hooks.js +35 -24
- package/lib/nodebb.js +2 -1
- package/lib/poll.js +104 -104
- package/lib/scheduler.js +25 -24
- package/lib/serializer.js +2 -2
- package/lib/sockets.js +71 -60
- package/lib/vote.js +55 -53
- package/library.js +25 -27
- package/package-lock.json +1646 -16
- package/package.json +10 -5
- package/plugin.json +11 -5
- package/public/js/.eslintrc +82 -0
- package/public/js/admin.js +11 -9
- package/public/js/poll/creator.js +112 -100
- package/public/js/poll/main.js +6 -8
- package/public/js/poll/serializer.js +29 -32
- package/public/js/poll/sockets.js +17 -19
- package/public/js/poll/view.js +192 -194
- package/public/less/style.less +1 -648
- package/templates/poll/creator.tpl +8 -10
- package/upgrades/convert_poll_id_voters_and_options_votes_to_sorted_sets.js +22 -21
- package/upgrades/give_categories_poll_create_privs_to_reg_users.js +13 -10
- package/vendor/dayjs.min.js +1 -0
- package/vendor/flatpickr.l10n.js +1 -0
- package/vendor/flatpickr.min.css +13 -0
- package/vendor/flatpickr.min.js +2 -0
- package/public/js/vendor/bootstrap-datetimepicker.min.js +0 -9
- package/public/js/vendor/flatpickr.min.js +0 -1592
- package/public/js/vendor/jquery.serialize-object.min.js +0 -8
- package/public/js/vendor/moment.min.js +0 -7
package/.eslintrc
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "airbnb-base",
|
|
3
|
+
"ignorePatterns": ["**/vendor/*.js"],
|
|
4
|
+
"parserOptions": {
|
|
5
|
+
"sourceType": "script"
|
|
6
|
+
},
|
|
7
|
+
|
|
8
|
+
"rules": {
|
|
9
|
+
// === Configure rules for our style ===
|
|
10
|
+
// imports must be resolvable
|
|
11
|
+
"import/no-unresolved": "error",
|
|
12
|
+
// use single quotes,
|
|
13
|
+
// unless a different style allows avoiding escapes
|
|
14
|
+
"quotes": ["error", "single", {
|
|
15
|
+
"avoidEscape": true,
|
|
16
|
+
"allowTemplateLiterals": true
|
|
17
|
+
}],
|
|
18
|
+
// allow else-if return
|
|
19
|
+
"no-else-return": [ "error", { "allowElseIf": true } ],
|
|
20
|
+
// expressions split over multiple lines
|
|
21
|
+
// should break after the operator
|
|
22
|
+
"operator-linebreak": [ "error", "after" ],
|
|
23
|
+
// require arrow parens only when needed
|
|
24
|
+
// and whenever the body is a block
|
|
25
|
+
"arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }],
|
|
26
|
+
// what variables are errors in callbacks
|
|
27
|
+
"handle-callback-err": [ "error","^(e$|(e|(.*(_e|E)))rr)" ],
|
|
28
|
+
// allow dangling commas in functions
|
|
29
|
+
// require them everywhere else
|
|
30
|
+
"comma-dangle": ["error", {
|
|
31
|
+
"arrays": "always-multiline",
|
|
32
|
+
"objects": "always-multiline",
|
|
33
|
+
"imports": "always-multiline",
|
|
34
|
+
"exports": "always-multiline",
|
|
35
|
+
"functions": "only-multiline"
|
|
36
|
+
}],
|
|
37
|
+
// we actually encourage `return await`
|
|
38
|
+
"no-return-await": "off",
|
|
39
|
+
// allow `while (true)`
|
|
40
|
+
"no-constant-condition": ["error", { "checkLoops": false }],
|
|
41
|
+
// allow ignoring an error with `catch`
|
|
42
|
+
"no-empty": ["error", { "allowEmptyCatch": true }],
|
|
43
|
+
// allow `3 + 5 - 1`, but not `3 * 5 - 1`
|
|
44
|
+
"no-mixed-operators": ["error", { "allowSamePrecedence": true }],
|
|
45
|
+
// require `'use strict';`
|
|
46
|
+
"strict": ["error", "global"],
|
|
47
|
+
// we actually use tabs for indentation
|
|
48
|
+
"indent": ["error", "tab", { "SwitchCase": 1 }],
|
|
49
|
+
"no-tabs": "off",
|
|
50
|
+
// we want `== null` to also handle undefined
|
|
51
|
+
"no-eq-null": "off",
|
|
52
|
+
// allow `for (..; i++)`
|
|
53
|
+
"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }],
|
|
54
|
+
// allow using functions defined later
|
|
55
|
+
"no-use-before-define": ["error", "nofunc"],
|
|
56
|
+
// require consistent newlines before and after braces
|
|
57
|
+
// if contents are multiline
|
|
58
|
+
"object-curly-newline": ["error", { "consistent": true, "multiline": true }],
|
|
59
|
+
// require consistent linebreaks inline function parenthesis (arguments or params)
|
|
60
|
+
"function-paren-newline": ["error", "consistent"],
|
|
61
|
+
// only require const if all parts of destructuring can be const
|
|
62
|
+
"prefer-const": ["error", { "destructuring": "all" }],
|
|
63
|
+
// don't require destructuring for arrays or assignment
|
|
64
|
+
"prefer-destructuring": ["error", {
|
|
65
|
+
"VariableDeclarator": { "array": false, "object": true },
|
|
66
|
+
"AssignmentExpression": { "array": false, "object": false }
|
|
67
|
+
}],
|
|
68
|
+
// identical to airbnb rule, except for allowing for..of, because we want to use it
|
|
69
|
+
"no-restricted-syntax": [
|
|
70
|
+
"error",
|
|
71
|
+
{
|
|
72
|
+
"selector": "ForInStatement",
|
|
73
|
+
"message": "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array."
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"selector": "LabeledStatement",
|
|
77
|
+
"message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand."
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"selector": "WithStatement",
|
|
81
|
+
"message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize."
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
// allow lines of up to 120 characters
|
|
85
|
+
"max-len": ["error", { "code": 120, "tabWidth": 2, "ignoreUrls": true, "ignoreStrings": true, "ignoreTemplateLiterals": true, "ignoreRegExpLiterals": true }],
|
|
86
|
+
|
|
87
|
+
// === Disable rules ===
|
|
88
|
+
// more liberal naming
|
|
89
|
+
"camelcase": "off",
|
|
90
|
+
"no-underscore-dangle": "off",
|
|
91
|
+
// don't require anonymous function names
|
|
92
|
+
"func-names": "off",
|
|
93
|
+
// allow console
|
|
94
|
+
"no-console": "off",
|
|
95
|
+
// allow new for side effects
|
|
96
|
+
// allow new with non-capitalized
|
|
97
|
+
"no-new": "off",
|
|
98
|
+
"new-cap": "off",
|
|
99
|
+
// allow shadowing variables (usually callbacks)
|
|
100
|
+
"no-shadow": "off",
|
|
101
|
+
// allow multiple empty lines in a row
|
|
102
|
+
"no-multiple-empty-lines": "off",
|
|
103
|
+
// allow not using object shorthand
|
|
104
|
+
"object-shorthand": "off",
|
|
105
|
+
|
|
106
|
+
// TODO
|
|
107
|
+
"consistent-return": "off",
|
|
108
|
+
"no-restricted-globals": "off",
|
|
109
|
+
"no-prototype-builtins": "off",
|
|
110
|
+
"import/no-extraneous-dependencies": "off",
|
|
111
|
+
"import/no-dynamic-require": "off",
|
|
112
|
+
"global-require": "off",
|
|
113
|
+
"no-param-reassign": "off",
|
|
114
|
+
"default-case": "off"
|
|
115
|
+
}
|
|
116
|
+
}
|
package/languages/ru/poll.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"poll": "Опрос",
|
|
3
|
-
"toggles": "
|
|
4
|
-
"allow_guests": "Разрешить гостям
|
|
3
|
+
"toggles": "Переключатели",
|
|
4
|
+
"allow_guests": "Разрешить гостям видеть результаты опроса",
|
|
5
5
|
"limits": "Ограничения",
|
|
6
6
|
"max_options": "Максимальное количество вариантов в опросе",
|
|
7
|
-
"defaults": "
|
|
8
|
-
"default_title": "
|
|
7
|
+
"defaults": "Значение по умолчанию",
|
|
8
|
+
"default_title": "Название опроса по умолчанию",
|
|
9
9
|
"max_votes": "Максимальное количество голосов в опросе",
|
|
10
10
|
"disallow_vote_update": "Запретить переголосование",
|
|
11
|
-
"info_choices": "
|
|
11
|
+
"info_choices": "Число большее 1 позволит проводить опросы с несколькими вариантами ответа.",
|
|
12
12
|
"settings": "Настройки",
|
|
13
13
|
"save": "Сохранить",
|
|
14
14
|
"reset": "Сброс",
|
|
@@ -16,29 +16,29 @@
|
|
|
16
16
|
"creator_title": "Создать опрос",
|
|
17
17
|
"poll_title": "Название опроса",
|
|
18
18
|
"poll_title_placeholder": "Введите название опроса",
|
|
19
|
-
"options_title": "
|
|
20
|
-
"options_add": "Добавить вариант",
|
|
19
|
+
"options_title": "Варианты ответов",
|
|
20
|
+
"options_add": "Добавить вариант ответа",
|
|
21
21
|
"max_votes_placeholder": "Введите максимальное кол-во голосов",
|
|
22
22
|
"auto_end_title": "Автоматически закончить опрос",
|
|
23
23
|
"auto_end_placeholder": "Нажмите, чтобы ввести дату и время",
|
|
24
|
-
"auto_end_help": "
|
|
24
|
+
"auto_end_help": "Если оставить данное поле пустым, то опрос будет всегда открыт.",
|
|
25
25
|
|
|
26
26
|
"error.max_options": "Вы можете создать только %d опций.",
|
|
27
|
-
"error.no_options": "Создайте хотя бы один
|
|
28
|
-
"error.valid_date": "Введите
|
|
27
|
+
"error.no_options": "Создайте хотя бы один вариант ответа.",
|
|
28
|
+
"error.valid_date": "Введите корректную дату.",
|
|
29
29
|
|
|
30
|
-
"error.not_main": "Опрос доступен при создании темы",
|
|
30
|
+
"error.not_main": "Опрос доступен только при создании темы",
|
|
31
31
|
"error.privilege.create": "У вас недостаточно прав для создания опроса",
|
|
32
32
|
|
|
33
|
-
"vote": "
|
|
33
|
+
"vote": "Проголосовать",
|
|
34
34
|
"update_vote": "Переголосовать",
|
|
35
35
|
"remove_vote": "Удалить голос",
|
|
36
|
-
"to_voting": "
|
|
36
|
+
"to_voting": "Проголосовать",
|
|
37
37
|
"to_results": "Результаты",
|
|
38
38
|
"voting_unavailable_title": "Голосование недоступно",
|
|
39
39
|
"voting_unavailable_message": "Этот опрос завершен или был помечен как удаленный. Вы все еще можете просмотреть результаты.",
|
|
40
|
-
"voting_update_disallowed_message": "
|
|
41
|
-
"vote_is_final": "
|
|
40
|
+
"voting_update_disallowed_message": "Вы уже проголосовали, и изменение вашего голоса не допускается для этого голосования.",
|
|
41
|
+
"vote_is_final": "В данном опросе нельзя переголосовать.",
|
|
42
42
|
"vote_count": "пользователей проголосовали за этот вариант",
|
|
43
43
|
"votes": "голосов"
|
|
44
44
|
}
|
package/lib/config.js
CHANGED
|
@@ -1,49 +1,48 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const NodeBB = require('./nodebb');
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
pluginId = pluginInfo.id.replace('nodebb-plugin-', '');
|
|
5
|
+
const packageInfo = require('../package.json');
|
|
6
|
+
const pluginInfo = require('../plugin.json');
|
|
8
7
|
|
|
9
|
-
(
|
|
8
|
+
const pluginId = pluginInfo.id.replace('nodebb-plugin-', '');
|
|
10
9
|
|
|
10
|
+
(function (Config) {
|
|
11
11
|
Config.plugin = {
|
|
12
12
|
name: pluginInfo.name,
|
|
13
13
|
id: pluginId,
|
|
14
14
|
version: packageInfo.version,
|
|
15
15
|
description: packageInfo.description,
|
|
16
|
-
icon: 'fa-bar-chart-o'
|
|
16
|
+
icon: 'fa-bar-chart-o',
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
Config.defaults = {
|
|
20
20
|
toggles: {
|
|
21
|
-
allowAnon: false
|
|
21
|
+
allowAnon: false,
|
|
22
22
|
},
|
|
23
23
|
limits: {
|
|
24
|
-
maxOptions: 10
|
|
24
|
+
maxOptions: 10,
|
|
25
25
|
},
|
|
26
26
|
defaults: {
|
|
27
27
|
title: 'Poll',
|
|
28
28
|
maxvotes: 1,
|
|
29
29
|
disallowVoteUpdate: 0,
|
|
30
|
-
end: 0
|
|
31
|
-
}
|
|
30
|
+
end: 0,
|
|
31
|
+
},
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
Config.settings = {};
|
|
35
35
|
|
|
36
|
-
Config.init = function(callback) {
|
|
36
|
+
Config.init = function (callback) {
|
|
37
37
|
Config.settings = new NodeBB.Settings(Config.plugin.id, Config.plugin.version, Config.defaults, callback);
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
Config.adminSockets = {
|
|
41
|
-
sync: function() {
|
|
41
|
+
sync: function () {
|
|
42
42
|
Config.settings.sync();
|
|
43
43
|
},
|
|
44
|
-
getDefaults: function(socket, data, callback) {
|
|
44
|
+
getDefaults: function (socket, data, callback) {
|
|
45
45
|
callback(null, Config.settings.createDefaultWrapper());
|
|
46
|
-
}
|
|
46
|
+
},
|
|
47
47
|
};
|
|
48
|
-
|
|
49
|
-
})(exports);
|
|
48
|
+
}(exports));
|
package/lib/hooks.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Config = require('./config'),
|
|
4
|
-
Poll = require('./poll'),
|
|
5
|
-
Serializer = require('./serializer');
|
|
1
|
+
'use strict';
|
|
6
2
|
|
|
7
3
|
const util = require('util');
|
|
4
|
+
const NodeBB = require('./nodebb');
|
|
5
|
+
|
|
6
|
+
const Config = require('./config');
|
|
7
|
+
const Poll = require('./poll');
|
|
8
|
+
const Serializer = require('./serializer');
|
|
8
9
|
|
|
9
|
-
(function(Hooks) {
|
|
10
10
|
|
|
11
|
+
(function (Hooks) {
|
|
11
12
|
Hooks.filter = {};
|
|
12
13
|
Hooks.action = {};
|
|
13
14
|
|
|
14
|
-
Hooks.filter.parseRaw = function(raw, callback) {
|
|
15
|
+
Hooks.filter.parseRaw = function (raw, callback) {
|
|
15
16
|
callback(null, Serializer.removeMarkup(raw, '[Poll]'));
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
Hooks.filter.postCreate = async function (obj) {
|
|
19
20
|
if (Serializer.hasMarkup(obj.post.content) && obj.data.isMain) {
|
|
20
21
|
return await savePoll(obj);
|
|
21
|
-
} else {
|
|
22
|
-
return obj;
|
|
23
22
|
}
|
|
23
|
+
return obj;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
Hooks.filter.postEdit = async function(obj) {
|
|
26
|
+
Hooks.filter.postEdit = async function (obj) {
|
|
27
27
|
const { tid, pollId } = await NodeBB.Posts.getPostFields(obj.data.pid, ['tid', 'pollId']);
|
|
28
28
|
if (pollId || !Serializer.hasMarkup(obj.post.content)) {
|
|
29
29
|
return obj;
|
|
@@ -56,41 +56,52 @@ const util = require('util');
|
|
|
56
56
|
return obj;
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
-
Hooks.filter.topicPost = async function (data
|
|
59
|
+
Hooks.filter.topicPost = async function (data) {
|
|
60
60
|
if (Serializer.hasMarkup(data.content)) {
|
|
61
61
|
await canCreate(data.cid, data.uid);
|
|
62
62
|
return data;
|
|
63
|
-
} else {
|
|
64
|
-
return data;
|
|
65
63
|
}
|
|
64
|
+
return data;
|
|
66
65
|
};
|
|
67
66
|
|
|
68
|
-
Hooks.action.postDelete = function(data) {
|
|
69
|
-
Poll.getPollIdByPid(data.post.pid,
|
|
67
|
+
Hooks.action.postDelete = function (data) {
|
|
68
|
+
Poll.getPollIdByPid(data.post.pid, (err, pollId) => {
|
|
69
|
+
if (err) {
|
|
70
|
+
console.error(err);
|
|
71
|
+
}
|
|
70
72
|
if (pollId) {
|
|
71
73
|
Poll.delete(pollId);
|
|
72
74
|
}
|
|
73
75
|
});
|
|
74
76
|
};
|
|
75
77
|
|
|
76
|
-
Hooks.action.postRestore = function(data) {
|
|
77
|
-
Poll.getPollIdByPid(data.post.pid,
|
|
78
|
+
Hooks.action.postRestore = function (data) {
|
|
79
|
+
Poll.getPollIdByPid(data.post.pid, (err, pollId) => {
|
|
80
|
+
if (err) {
|
|
81
|
+
console.error(err);
|
|
82
|
+
}
|
|
78
83
|
if (pollId) {
|
|
79
84
|
Poll.restore(pollId);
|
|
80
85
|
}
|
|
81
86
|
});
|
|
82
87
|
};
|
|
83
88
|
|
|
84
|
-
Hooks.action.topicDelete = function(data) {
|
|
85
|
-
Poll.getPollIdByTid(data.topic.tid,
|
|
89
|
+
Hooks.action.topicDelete = function (data) {
|
|
90
|
+
Poll.getPollIdByTid(data.topic.tid, (err, pollId) => {
|
|
91
|
+
if (err) {
|
|
92
|
+
console.error(err);
|
|
93
|
+
}
|
|
86
94
|
if (pollId) {
|
|
87
95
|
Poll.delete(pollId);
|
|
88
96
|
}
|
|
89
97
|
});
|
|
90
98
|
};
|
|
91
99
|
|
|
92
|
-
Hooks.action.topicRestore = function(data) {
|
|
93
|
-
Poll.getPollIdByTid(data.topic.tid,
|
|
100
|
+
Hooks.action.topicRestore = function (data) {
|
|
101
|
+
Poll.getPollIdByTid(data.topic.tid, (err, pollId) => {
|
|
102
|
+
if (err) {
|
|
103
|
+
console.error(err);
|
|
104
|
+
}
|
|
94
105
|
if (pollId) {
|
|
95
106
|
Poll.restore(pollId);
|
|
96
107
|
}
|
|
@@ -105,8 +116,8 @@ const util = require('util');
|
|
|
105
116
|
}
|
|
106
117
|
|
|
107
118
|
async function savePoll(obj) {
|
|
108
|
-
|
|
109
|
-
|
|
119
|
+
const postobj = obj.post ? obj.post : obj;
|
|
120
|
+
const pollData = Serializer.serialize(postobj.content, Config.settings.get());
|
|
110
121
|
|
|
111
122
|
if (!pollData || !pollData.options.length) {
|
|
112
123
|
return obj;
|
|
@@ -120,4 +131,4 @@ const util = require('util');
|
|
|
120
131
|
|
|
121
132
|
return obj;
|
|
122
133
|
}
|
|
123
|
-
}
|
|
134
|
+
}(exports));
|
package/lib/nodebb.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use strict';
|
|
1
2
|
|
|
2
3
|
module.exports = {
|
|
3
4
|
db: require.main.require('./src/database'),
|
|
@@ -12,5 +13,5 @@ module.exports = {
|
|
|
12
13
|
SocketIndex: require.main.require('./src/socket.io/index'),
|
|
13
14
|
Translator: require.main.require('./public/src/modules/translator'),
|
|
14
15
|
winston: require.main.require('winston'),
|
|
15
|
-
app: null
|
|
16
|
+
app: null,
|
|
16
17
|
};
|