FEATURE: Add public type to polls.

This commit is contained in:
Guo Xiang Tan
2016-06-07 18:55:01 +08:00
parent 7aac5baeed
commit 8ecde35df3
17 changed files with 322 additions and 30 deletions
@@ -0,0 +1,31 @@
import computed from 'ember-addons/ember-computed-decorators';
import User from 'discourse/models/user';
import PollVoters from 'discourse/plugins/poll/components/poll-voters';
export default PollVoters.extend({
@computed("pollsVoters", "poll.options", "showMore", "isExpanded", "numOfVotersToShow")
users(pollsVoters, options, showMore, isExpanded, numOfVotersToShow) {
var users = [];
var voterIds = [];
const shouldLimit = showMore && !isExpanded;
options.forEach(option => {
option.voter_ids.forEach(voterId => {
if (shouldLimit) {
if (!(users.length > numOfVotersToShow - 1)) {
users.push(pollsVoters[voterId]);
}
} else {
users.push(pollsVoters[voterId]);
}
})
});
return users;
},
@computed("pollsVoters", "numOfVotersToShow")
showMore(pollsVoters, numOfVotersToShow) {
return !(Object.keys(pollsVoters).length < numOfVotersToShow);
}
});
@@ -1,23 +1,27 @@
import round from "discourse/lib/round";
import computed from 'ember-addons/ember-computed-decorators';
export default Em.Component.extend({
tagName: "span",
totalScore: function() {
@computed("poll.options.@each.{html,votes}")
totalScore() {
return _.reduce(this.get("poll.options"), function(total, o) {
const value = parseInt(o.get("html"), 10),
votes = parseInt(o.get("votes"), 10);
return total + value * votes;
}, 0);
}.property("poll.options.@each.{html,votes}"),
},
average: function() {
@computed("totalScore", "poll.voters")
average() {
const voters = this.get("poll.voters");
return voters === 0 ? 0 : round(this.get("totalScore") / voters, -2);
}.property("totalScore", "poll.voters"),
},
averageRating: function() {
@computed("average")
averageRating() {
return I18n.t("poll.average_rating", { average: this.get("average") });
}.property("average"),
},
});
@@ -0,0 +1,25 @@
import computed from 'ember-addons/ember-computed-decorators';
import User from 'discourse/models/user';
import PollVoters from 'discourse/plugins/poll/components/poll-voters';
export default PollVoters.extend({
@computed("pollsVoters", "option.voter_ids", "showMore", "isExpanded", "numOfVotersToShow")
users(pollsVoters, voterIds, showMore, isExpanded, numOfVotersToShow) {
var users = [];
if (showMore && !isExpanded) {
voterIds = voterIds.slice(0, numOfVotersToShow);
}
voterIds.forEach(voterId => {
users.push(pollsVoters[voterId]);
});
return users;
},
@computed("option.votes", "numOfVotersToShow")
showMore(numOfVotes, numOfVotersToShow) {
return !(numOfVotes < numOfVotersToShow);
}
});
@@ -0,0 +1,13 @@
export default Ember.Component.extend({
layoutName: "components/poll-voters",
tagName: 'ul',
classNames: ["poll-voters-list"],
isExpanded: false,
numOfVotersToShow: 20,
actions: {
toggleExpand() {
this.toggleProperty("isExpanded");
}
}
});
@@ -6,6 +6,7 @@ export default Ember.Controller.extend({
isNumber: Ember.computed.equal("poll.type", "number"),
isRandom : Ember.computed.equal("poll.order", "random"),
isClosed: Ember.computed.equal("poll.status", "closed"),
pollsVoters: Ember.computed.alias("post.polls_voters"),
// shows the results when
// - poll is closed
@@ -145,8 +146,16 @@ export default Ember.Controller.extend({
options: this.get("selectedOptions"),
}
}).then(results => {
this.setProperties({ vote: results.vote, showResults: true });
this.set("model", Em.Object.create(results.poll));
const poll = results.poll;
const votes = results.vote;
const currentUser = this.currentUser;
this.setProperties({ vote: votes, showResults: true });
this.set("model", Em.Object.create(poll));
if (poll.public) {
this.get("pollsVoters")[currentUser.get("id")] = currentUser;
}
}).catch(() => {
bootbox.alert(I18n.t("poll.error_while_casting_votes"));
}).finally(() => {
@@ -1 +1,5 @@
{{{averageRating}}}
{{#if poll.public}}
{{poll-results-number-voters poll=poll pollsVoters=pollsVoters}}
{{/if}}
@@ -9,5 +9,9 @@
<div class="bar-back">
<div class="bar" style={{option.style}}></div>
</div>
{{#if poll.public}}
{{poll-results-standard-voters option=option pollsVoters=pollsVoters}}
{{/if}}
</li>
{{/each}}
@@ -0,0 +1,19 @@
<div class="poll-voters">
{{#each users as |user|}}
<li>
<a data-user-card={{unbound user.username}}>
{{avatar user imageSize="tiny"}}
</a>
</li>
{{/each}}
<div class="poll-voters-toggle-expand">
{{#if showMore}}
{{#if isExpanded}}
<a {{action "toggleExpand"}}>{{fa-icon "chevron-up"}}</a>
{{else}}
<a {{action "toggleExpand"}}>{{fa-icon "chevron-down"}}</a>
{{/if}}
{{/if}}
</div>
</div>
@@ -2,9 +2,9 @@
<div class="poll-container">
{{#if showingResults}}
{{#if isNumber}}
{{poll-results-number poll=poll}}
{{poll-results-number poll=poll pollsVoters=pollsVoters}}
{{else}}
{{poll-results-standard poll=poll}}
{{poll-results-standard poll=poll pollsVoters=pollsVoters}}
{{/if}}
{{else}}
<ul>
@@ -1,11 +1,17 @@
import { withPluginApi } from 'discourse/lib/plugin-api';
import { observes } from "ember-addons/ember-computed-decorators";
function createPollView(container, post, poll, vote) {
function createPollView(container, post, poll, vote, publicPoll) {
const controller = container.lookup("controller:poll", { singleton: false });
const view = container.lookup("view:poll");
controller.set("vote", vote);
controller.setProperties({ model: poll, post });
controller.setProperties({
model: poll,
vote: vote,
public: publicPoll,
post
});
view.set("controller", controller);
return view;
@@ -23,6 +29,10 @@ function initializePolls(api) {
const post = this.get('model.postStream').findLoadedPost(msg.post_id);
if (post) {
post.set('polls', msg.polls);
if (msg.user) {
post.set(`polls_voters.${msg.user.id}`, msg.user);
}
}
});
},
@@ -38,7 +48,8 @@ function initializePolls(api) {
pollsObject: null,
// we need a proper ember object so it is bindable
pollsChanged: function(){
@observes("polls")
pollsChanged() {
const polls = this.get("polls");
if (polls) {
this._polls = this._polls || {};
@@ -52,7 +63,7 @@ function initializePolls(api) {
});
this.set("pollsObject", this._polls);
}
}.observes("polls")
}
});
function cleanUpPollViews() {
@@ -69,6 +80,7 @@ function initializePolls(api) {
const post = helper.getModel();
api.preventCloak(post.id);
const votes = post.get('polls_votes') || {};
post.set("polls_voters", (post.get("polls_voters") || {}));
post.pollsChanged();
@@ -82,8 +94,16 @@ function initializePolls(api) {
const $poll = $(pollElem);
const pollName = $poll.data("poll-name");
const publicPoll = $poll.data("poll-public");
const pollId = `${pollName}-${post.id}`;
const pollView = createPollView(helper.container, post, polls[pollName], votes[pollName]);
const pollView = createPollView(
helper.container,
post,
polls[pollName],
votes[pollName],
publicPoll
);
$poll.replaceWith($div);
Em.run.next(() => pollView.renderer.replaceIn(pollView, $div[0]));
@@ -5,7 +5,7 @@
var DATA_PREFIX = "data-poll-";
var DEFAULT_POLL_NAME = "poll";
var WHITELISTED_ATTRIBUTES = ["type", "name", "min", "max", "step", "order", "status"];
var WHITELISTED_ATTRIBUTES = ["type", "name", "min", "max", "step", "order", "status", "public"];
var ATTRIBUTES_REGEX = new RegExp("(" + WHITELISTED_ATTRIBUTES.join("|") + ")=['\"]?[^\\s\\]]+['\"]?", "g");
@@ -3,17 +3,12 @@ import { on } from "ember-addons/ember-computed-decorators";
export default Em.View.extend({
templateName: "poll",
classNames: ["poll"],
attributeBindings: ["data-poll-type", "data-poll-name", "data-poll-status"],
attributeBindings: ["data-poll-type", "data-poll-name", "data-poll-status", "data-poll-public"],
poll: Em.computed.alias("controller.poll"),
"data-poll-type": Em.computed.alias("poll.type"),
"data-poll-name": Em.computed.alias("poll.name"),
"data-poll-status": Em.computed.alias("poll.status"),
@on("didInsertElement")
_fixPollContainerHeight() {
const pollContainer = this.$(".poll-container");
pollContainer.height(pollContainer.height());
}
"data-poll-public": Em.computed.alias("poll.public")
});