Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add private voting #139

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Currently supported settings:
maxvotes="1" //Max number of votes per user. If larger than 1, a multiple choice poll will be created
disallowVoteUpdate="0" //if set, users won't be able to update/remove their vote
title="Poll title" //Poll title
privateVotes="true" //if set, only the poll creator and admins can see per user voting details
hiddenVotes="true" //if set, only admins can see per user voting details (overrides privateVotes)

There's also a helpful modal available that will allow you to easily create a poll:
![](https://i.imgur.com/2fPnWLb.png)
Expand Down
6 changes: 5 additions & 1 deletion languages/en_GB/poll.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"default_title": "Default poll title",
"max_votes": "Maximum number of votes per user",
"disallow_vote_update": "Don't allow users to update their vote",
"private_votes": "Private votes",
"hidden_votes": "Hidden votes",
"info_choices": "A number greater than 1 will enable multiple choice polls.",
"settings": "Settings",
"save": "Save",
Expand Down Expand Up @@ -41,8 +43,10 @@
"voting_unavailable_message": "This poll has ended or has been marked as deleted. You can still view the results.",
"voting_update_disallowed_message": "You have already voted and changing your vote is not allowed for this poll",
"vote_is_final": "Changing your vote is not allowed for this poll so your vote is final",
"votes_are_private": "The votes in this poll are hidden from other users excluding the creator of the poll.",
"votes_are_hidden": "The votes in this poll are hidden from other users.",

"vote_count": "users voted for this option",
"votes": "votes",
"admin.create-poll": "Create Poll"
}
}
6 changes: 5 additions & 1 deletion languages/en_US/poll.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"default_title": "Default poll title",
"max_votes": "Maximum number of votes per user",
"disallow_vote_update": "Don't allow users to update their vote",
"private_votes": "Private votes",
"hidden_votes": "Hidden votes",
"info_choices": "A number greater than 1 will enable multiple choice polls.",
"settings": "Settings",
"save": "Save",
Expand Down Expand Up @@ -41,7 +43,9 @@
"voting_unavailable_message": "This poll has ended or has been marked as deleted. You can still view the results.",
"voting_update_disallowed_message": "You have already voted and changing your vote is not allowed for this poll",
"vote_is_final": "Changing your vote is not allowed for this poll so your vote is final",
"votes_are_private": "The votes in this poll are hidden from other users excluding the creator of the poll.",
"votes_are_hidden": "The votes in this poll are hidden from other users.",

"vote_count": "users voted for this option",
"votes": "votes"
}
}
4 changes: 3 additions & 1 deletion lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const pluginId = pluginInfo.id.replace('nodebb-plugin-', '');
maxvotes: 1,
disallowVoteUpdate: 0,
end: 0,
privateVotes: 0,
hiddenVotes: 0,
},
};

Expand All @@ -45,4 +47,4 @@ const pluginId = pluginInfo.id.replace('nodebb-plugin-', '');
callback(null, Config.settings.createDefaultWrapper());
},
};
}(exports));
}(exports));
16 changes: 15 additions & 1 deletion lib/poll.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ const Scheduler = require('./scheduler');
option.percentage = isNaN(percentage) ? 0 : percentage;
});
pollData.settings.disallowVoteUpdate = parseInt(pollData.settings.disallowVoteUpdate, 10);
pollData.settings.privateVotes = parseInt(pollData.settings.privateVotes, 10);
pollData.settings.hiddenVotes = parseInt(pollData.settings.hiddenVotes, 10);
callback(null, pollData);
});
};
Expand Down Expand Up @@ -253,6 +255,18 @@ const Scheduler = require('./scheduler');
Poll.setField(pollId, 'ended', 1);
};

Poll.isPrivateVotes = function (pollId, callback) {
Poll.getSettingsField(pollId, 'privateVotes', (err, result) => {
callback(err, parseInt(result, 10) === 1);
});
};

Poll.isHiddenVotes = function (pollId, callback) {
Poll.getSettingsField(pollId, 'hiddenVotes', (err, result) => {
callback(err, parseInt(result, 10) === 1);
});
};

Poll.changePid = function (pollId, pid, callback) {
async.parallel([
function (next) {
Expand Down Expand Up @@ -298,4 +312,4 @@ const Scheduler = require('./scheduler');
Poll.setSettingsField = function (pollId, field, value, callback) {
NodeBB.db.setObjectField(`poll:${pollId}:settings`, field, callback);
};
}(exports));
}(exports));
31 changes: 25 additions & 6 deletions lib/sockets.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,31 @@ const Vote = require('./vote');
return callback(null, result);
}

NodeBB.User.getUsersFields(result.votes, ['uid', 'username', 'userslug', 'picture'], (err, userData) => {
if (err) {
console.error(err);
async.parallel({
isAdmin: function(next){
NodeBB.User.isAdministrator(socket.uid, next);
},
pollData: function(next){
Poll.getInfo(data.pollId, next);
},
privateVotes : function(next){
Poll.isPrivateVotes(data.pollId, next);
},
hiddenVotes : function(next){
Poll.isHiddenVotes(data.pollId, next);
},
}, (err, data) => {
if (!data.isAdmin && ((data.pollData.uid!==socket.uid && !!data.privateVotes) || !!data.hiddenVotes)) {
result.votes=[];
return callback(null, result);
}
result.votes = userData;
callback(null, result);
NodeBB.User.getUsersFields(result.votes, ['uid', 'username', 'userslug', 'picture'], (err, userData) => {
if (err) {
console.error(err);
}
result.votes = userData;
callback(null, result);
});
});
});
};
Expand Down Expand Up @@ -244,4 +263,4 @@ const Vote = require('./vote');
return callback(null, can);
});
}
}(exports));
}(exports));
4 changes: 3 additions & 1 deletion public/js/poll/creator.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@
title: obj['settings.title'],
maxvotes: obj['settings.maxvotes'],
disallowVoteUpdate: obj['settings.disallowVoteUpdate'] === 'on' ? 'true' : 'false',
privateVotes: obj['settings.privateVotes'] === 'on' ? 'true' : 'false',
hiddenVotes: obj['settings.hiddenVotes'] === 'on' ? 'true' : 'false',
end: obj['settings.end'],
},
};
Expand All @@ -251,4 +253,4 @@
Poll.creator = Creator;

init();
}(window.Poll));
}(window.Poll));
18 changes: 17 additions & 1 deletion public/js/poll/serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ module.exports = function (utils) {
return parseInt(value, 10);
},
},
privateVotes: {
test: function (value) {
return /true|false/.test(value);
},
parse: function (value) {
return value === 'true' || value === true ? 1 : 0;
},
},
hiddenVotes: {
test: function (value) {
return /true|false/.test(value);
},
parse: function (value) {
return value === 'true' || value === true ? 1 : 0;
},
},
disallowVoteUpdate: {
test: function (value) {
return /true|false/.test(value);
Expand Down Expand Up @@ -162,4 +178,4 @@ module.exports = function (utils) {
window.Poll.serializer = Serializer;
}
return Serializer;
};
};
12 changes: 10 additions & 2 deletions public/js/poll/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
return Poll.alertError(err.message);
}

view.showOptionDetails(details);
view.showOptionDetails({...details, privateVotes: view.isPrivateVotes(), hiddenVotes: view.isHiddenVotes()});
});
},
},
Expand Down Expand Up @@ -204,6 +204,14 @@
return parseInt(this.pollData.settings.disallowVoteUpdate, 10) !== 1;
};

View.prototype.isPrivateVotes = function () {
return parseInt(this.pollData.settings.privateVotes, 10) === 1;
};

View.prototype.isHiddenVotes = function () {
return parseInt(this.pollData.settings.hiddenVotes, 10) === 1;
};

View.prototype.pollEndedOrDeleted = function () {
if (this.hasPollEndedOrDeleted()) {
this.showResultsPanel();
Expand Down Expand Up @@ -369,4 +377,4 @@
}
},
};
}(window.Poll));
}(window.Poll));
14 changes: 14 additions & 0 deletions templates/poll/creator.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@
</div>
</div>

<div class="mb-3">
<div class="form-check">
<label class="form-check-label" for="pollPrivateVotes">[[poll:hidden_votes]]</label>
<input class="form-check-input" type="checkbox" name="settings.hiddenVotes" id="pollPrivateVotes" {{{if poll.settings.hiddenVotes}}}checked{{{end}}}>
</div>
</div>

<div class="mb-3">
<div class="form-check">
<label class="form-check-label" for="pollPrivateVotes">[[poll:private_votes]]</label>
<input class="form-check-input" type="checkbox" name="settings.privateVotes" id="pollPrivateVotes" {{{if poll.settings.privateVotes}}}checked{{{end}}}>
</div>
</div>

<div class="mb-3">
<label class="form-label" for="pollInputEnd">[[poll:auto_end_title]]</label>
<div class="input-group date flatpickr">
Expand Down
7 changes: 7 additions & 0 deletions templates/poll/view/details.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@
{buildAvatar(votes, "24px", true)}
</a>
<!-- END votes -->
<!-- IF hiddenVotes -->
<p>[[poll:votes_are_hidden]]</p>
<!-- ELSE -->
<!-- IF privateVotes -->
<p>[[poll:votes_are_private]]</p>
<!-- ENDIF privateVotes -->
<!-- ENDIF hiddenVotes -->