mirror of
https://github.com/discourse/discourse.git
synced 2025-06-06 11:54:41 +08:00
- FEATURE: revamped poll plugin
- add User.staff scope - inject MessageBus into Ember views (so it can be used by the poll plugin) - REFACTOR: use more accurate is_first_post? method instead of post_number == 1 - FEATURE: add support for JSON-typed custom fields - FEATURE: allow plugins to add validation - FEATURE: add post_custom_fields to PostSerializer - FEATURE: allow plugins to whitelist post_custom_fields - FIX: don't bump when post did not save successfully - FEATURE: polls are supported in any post - FEATURE: allow for multiple polls in the same post - FEATURE: multiple choice polls - FEATURE: rating polls - FEATURE: new dialect allowing users to preview polls in the composer
This commit is contained in:
@ -1,48 +1,188 @@
|
||||
import DiscourseController from 'discourse/controllers/controller';
|
||||
export default Em.Controller.extend({
|
||||
isMultiple: Em.computed.equal("poll.type", "multiple"),
|
||||
isNumber: Em.computed.equal("poll.type", "number"),
|
||||
isRandom : Em.computed.equal("poll.order", "random"),
|
||||
isClosed: Em.computed.equal("poll.status", "closed"),
|
||||
|
||||
export default DiscourseController.extend({
|
||||
poll: null,
|
||||
showResults: Em.computed.oneWay('poll.closed'),
|
||||
disableRadio: Em.computed.any('poll.closed', 'loading'),
|
||||
showToggleClosePoll: Em.computed.alias('poll.post.topic.details.can_edit'),
|
||||
// immediately shows the results when the user has already voted
|
||||
showResults: Em.computed.gt("vote.length", 0),
|
||||
|
||||
// shows the results when
|
||||
// - poll is closed
|
||||
// - topic is archived/closed
|
||||
// - user wants to see the results
|
||||
showingResults: Em.computed.or("isClosed", "post.topic.closed", "post.topic.archived", "showResults"),
|
||||
|
||||
showResultsDisabled: Em.computed.equal("poll.total_votes", 0),
|
||||
hideResultsDisabled: Em.computed.alias("isClosed"),
|
||||
|
||||
poll: function() {
|
||||
const poll = this.get("model"),
|
||||
vote = this.get("vote");
|
||||
|
||||
if (poll) {
|
||||
const options = _.map(poll.get("options"), o => Em.Object.create(o));
|
||||
|
||||
if (vote) {
|
||||
options.forEach(o => o.set("selected", vote.indexOf(o.get("id")) >= 0));
|
||||
}
|
||||
|
||||
poll.set("options", options);
|
||||
}
|
||||
|
||||
return poll;
|
||||
}.property("model"),
|
||||
|
||||
selectedOptions: function() {
|
||||
return _.map(this.get("poll.options").filterBy("selected"), o => o.get("id"));
|
||||
}.property("poll.options.@each.selected"),
|
||||
|
||||
totalVotesText: function() {
|
||||
return I18n.t("poll.total_votes", { count: this.get("poll.total_votes") });
|
||||
}.property("poll.total_votes"),
|
||||
|
||||
min: function() {
|
||||
let min = parseInt(this.get("poll.min"), 10);
|
||||
if (isNaN(min) || min < 1) { min = 1; }
|
||||
return min;
|
||||
}.property("poll.min"),
|
||||
|
||||
max: function() {
|
||||
let options = this.get("poll.options.length"),
|
||||
max = parseInt(this.get("poll.max"), 10);
|
||||
if (isNaN(max) || max > options) { max = options; }
|
||||
return max;
|
||||
}.property("poll.max", "poll.options.length"),
|
||||
|
||||
multipleHelpText: function() {
|
||||
const options = this.get("poll.options.length"),
|
||||
min = this.get("min"),
|
||||
max = this.get("max");
|
||||
|
||||
if (max > 0) {
|
||||
if (min === max) {
|
||||
if (min > 1) {
|
||||
return I18n.t("poll.multiple.help.x_options", { count: min });
|
||||
}
|
||||
} else if (min > 1) {
|
||||
if (max < options) {
|
||||
return I18n.t("poll.multiple.help.between_min_and_max_options", { min: min, max: max });
|
||||
} else {
|
||||
return I18n.t("poll.multiple.help.at_least_min_options", { count: min });
|
||||
}
|
||||
} else if (max <= options) {
|
||||
return I18n.t("poll.multiple.help.up_to_max_options", { count: max });
|
||||
}
|
||||
}
|
||||
}.property("min", "max", "poll.options.length"),
|
||||
|
||||
canCastVotes: function() {
|
||||
if (this.get("isClosed") ||
|
||||
this.get("showingResults") ||
|
||||
this.get("loading")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const selectedOptionCount = this.get("selectedOptions.length");
|
||||
|
||||
if (this.get("isMultiple")) {
|
||||
return selectedOptionCount >= this.get("min") && selectedOptionCount <= this.get("max");
|
||||
} else {
|
||||
return selectedOptionCount > 0;
|
||||
}
|
||||
}.property("isClosed", "showingResults", "loading",
|
||||
"selectedOptions.length",
|
||||
"isMultiple", "min", "max"),
|
||||
|
||||
castVotesDisabled: Em.computed.not("canCastVotes"),
|
||||
|
||||
canToggleStatus: function() {
|
||||
return this.currentUser &&
|
||||
(this.currentUser.get("id") === this.get("post.user_id") || this.currentUser.get("staff")) &&
|
||||
!this.get("loading") &&
|
||||
!this.get("post.topic.closed") &&
|
||||
!this.get("post.topic.archived");
|
||||
}.property("loading", "post.user_id", "post.topic.{closed,archived}"),
|
||||
|
||||
actions: {
|
||||
selectOption(option) {
|
||||
if (this.get('disableRadio')) {
|
||||
return;
|
||||
|
||||
toggleOption(option) {
|
||||
if (this.get("isClosed")) { return; }
|
||||
if (!this.currentUser) { return this.send("showLogin"); }
|
||||
|
||||
const wasSelected = option.get("selected");
|
||||
|
||||
if (!this.get("isMultiple")) {
|
||||
this.get("poll.options").forEach(o => o.set("selected", false));
|
||||
}
|
||||
|
||||
if (!this.get('postController.currentUser.id')) {
|
||||
this.get('postController').send('showLogin');
|
||||
return;
|
||||
}
|
||||
option.toggleProperty("selected");
|
||||
|
||||
this.set('loading', true);
|
||||
if (!this.get("isMultiple") && !wasSelected) { this.send("castVotes"); }
|
||||
},
|
||||
|
||||
castVotes() {
|
||||
if (!this.get("canCastVotes")) { return; }
|
||||
if (!this.currentUser) { return this.send("showLogin"); }
|
||||
|
||||
const self = this;
|
||||
this.get('poll').saveVote(option).then(function() {
|
||||
self.setProperties({ loading: false, showResults: true});
|
||||
|
||||
this.set("loading", true);
|
||||
|
||||
Discourse.ajax("/polls/vote", {
|
||||
type: "PUT",
|
||||
data: {
|
||||
post_id: this.get("post.id"),
|
||||
poll_name: this.get("poll.name"),
|
||||
options: this.get("selectedOptions"),
|
||||
}
|
||||
}).then(function(results) {
|
||||
self.setProperties({ vote: results.vote, showingResults: true });
|
||||
self.set("model", Em.Object.create(results.poll));
|
||||
}).catch(function() {
|
||||
bootbox.alert(I18n.t("poll.error_while_casting_votes"));
|
||||
}).finally(function() {
|
||||
self.set("loading", false);
|
||||
});
|
||||
},
|
||||
|
||||
toggleShowResults() {
|
||||
this.toggleProperty('showResults');
|
||||
toggleResults() {
|
||||
this.toggleProperty("showResults");
|
||||
},
|
||||
|
||||
toggleClosePoll() {
|
||||
const self = this;
|
||||
toggleStatus() {
|
||||
if (!this.get("canToggleStatus")) { return; }
|
||||
|
||||
this.set('loading', true);
|
||||
const self = this,
|
||||
confirm = this.get("isClosed") ? "poll.open.confirm" : "poll.close.confirm";
|
||||
|
||||
return Discourse.ajax('/poll/toggle_close', {
|
||||
type: 'PUT',
|
||||
data: { post_id: this.get('poll.post.id') }
|
||||
}).then(function(result) {
|
||||
self.set('poll.post.topic.title', result.basic_topic.title);
|
||||
self.set('poll.post.topic.fancy_title', result.basic_topic.title);
|
||||
self.set('loading', false);
|
||||
});
|
||||
}
|
||||
bootbox.confirm(
|
||||
I18n.t(confirm),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
function(confirmed) {
|
||||
if (confirmed) {
|
||||
self.set("loading", true);
|
||||
|
||||
Discourse.ajax("/polls/toggle_status", {
|
||||
type: "PUT",
|
||||
data: {
|
||||
post_id: self.get("post.id"),
|
||||
poll_name: self.get("poll.name"),
|
||||
status: self.get("isClosed") ? "open" : "closed",
|
||||
}
|
||||
}).then(function(results) {
|
||||
self.set("model", Em.Object.create(results.poll));
|
||||
}).catch(function() {
|
||||
bootbox.alert(I18n.t("poll.error_while_toggling_status"));
|
||||
}).finally(function() {
|
||||
self.set("loading", false);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
Reference in New Issue
Block a user