FIX: editing a poll/post with a poll wasn't working properly

This commit is contained in:
Régis Hanol 2015-04-26 00:12:19 +02:00
parent 84c65aeb60
commit 151dea4088
4 changed files with 70 additions and 46 deletions

View file

@ -94,8 +94,8 @@ module HasCustomFields
!@custom_fields || @custom_fields_orig == @custom_fields
end
def save_custom_fields
if !custom_fields_clean?
def save_custom_fields(force=false)
if force || !custom_fields_clean?
dup = @custom_fields.dup
array_fields = {}
@ -108,6 +108,12 @@ module HasCustomFields
else
array_fields[f.name] << f
end
elsif dup[f.name].is_a? Hash
if dup[f.name].to_json != f.value
f.destroy
else
dup.delete(f.name)
end
else
if dup[f.name] != f.value
f.destroy

View file

@ -78,12 +78,12 @@ class Plugin::Instance
end
# Add validation method but check that the plugin is enabled
def validate(klass, attr, &block)
def validate(klass, name, &block)
klass = klass.to_s.classify.constantize
klass.send(:define_method, attr, &block)
klass.send(:define_method, name, &block)
plugin = self
klass.validate(attr, if: -> { plugin.enabled? })
klass.validate(name, if: -> { plugin.enabled? })
end
# will make sure all the assets this plugin needs are registered

View file

@ -32,6 +32,9 @@ export default {
// don't even bother when there's no poll
if (!polls) { return; }
// clean-up if needed
this._cleanUpPollViews();
const pollViews = {};
// iterate over all polls
@ -47,14 +50,20 @@ export default {
});
this.messageBus.subscribe("/polls/" + this.get("post.id"), results => {
pollViews[results.poll.name].get("controller").set("model", Em.Object.create(results.poll));
if (results && results.polls) {
_.forEach(results.polls, poll => {
if (pollViews[poll.name]) {
pollViews[poll.name].get("controller").set("model", Em.Object.create(poll));
}
});
}
});
this.set("pollViews", pollViews);
}.on("postViewInserted"),
}.on("postViewInserted", "postViewUpdated"),
_cleanUpPollViews: function() {
this.messageBus.unsubscribe("/polls/*");
this.messageBus.unsubscribe("/polls/" + this.get("post.id"));
if (this.get("pollViews")) {
_.forEach(this.get("pollViews"), v => v.destroy());

View file

@ -64,9 +64,9 @@ after_initialize do
post.custom_fields[POLLS_CUSTOM_FIELD] = polls
post.custom_fields["#{VOTES_CUSTOM_FIELD}-#{user_id}"] = votes
post.save_custom_fields
post.save_custom_fields(true)
DiscourseBus.publish("/polls/#{post_id}", { poll: poll })
DiscourseBus.publish("/polls/#{post_id}", { polls: polls })
render json: { poll: poll, vote: options }
end
@ -97,10 +97,9 @@ after_initialize do
polls[poll_name]["status"] = status
post.custom_fields[POLLS_CUSTOM_FIELD] = polls
post.save_custom_fields
post.save_custom_fields(true)
DiscourseBus.publish("/polls/#{post_id}", { poll: polls[poll_name] })
DiscourseBus.publish("/polls/#{post_id}", { polls: polls })
render json: { poll: polls[poll_name] }
end
@ -120,7 +119,6 @@ after_initialize do
Post.class_eval do
attr_accessor :polls
# save the polls when the post is created
after_save do
next if self.polls.blank? || !self.polls.is_a?(Hash)
@ -129,7 +127,7 @@ after_initialize do
DistributedMutex.synchronize("#{PLUGIN_NAME}-#{post.id}") do
post.custom_fields[POLLS_CUSTOM_FIELD] = polls
post.save_custom_fields
post.save_custom_fields(true)
end
end
end
@ -137,7 +135,7 @@ after_initialize do
DATA_PREFIX ||= "data-poll-".freeze
DEFAULT_POLL_NAME ||= "poll".freeze
validate(:post, :polls) do
validate(:post, :validate_polls) do
# only care when raw has changed!
return unless self.raw_changed?
@ -200,8 +198,8 @@ after_initialize do
polls[poll["name"]] = poll
end
# are we updating a post outside the 5-minute edit window?
if self.id.present? && self.created_at < 5.minutes.ago
# are we updating a post?
if self.id.present?
post = self
DistributedMutex.synchronize("#{PLUGIN_NAME}-#{post.id}") do
# load previous polls
@ -211,43 +209,54 @@ after_initialize do
if polls.keys != previous_polls.keys ||
polls.values.map { |p| p["options"] } != previous_polls.values.map { |p| p["options"] }
# cannot add/remove/change/re-order polls
if polls.keys != previous_polls.keys
post.errors.add(:base, I18n.t("poll.cannot_change_polls_after_5_minutes"))
return
# outside the 5-minute edit window?
if post.created_at < 5.minutes.ago
# cannot add/remove/change/re-order polls
if polls.keys != previous_polls.keys
post.errors.add(:base, I18n.t("poll.cannot_change_polls_after_5_minutes"))
return
end
# deal with option changes
if User.staff.pluck(:id).include?(post.last_editor_id)
# staff can only edit options
polls.each_key do |poll_name|
if polls[poll_name]["options"].size != previous_polls[poll_name]["options"].size
post.errors.add(:base, I18n.t("poll.staff_cannot_add_or_remove_options_after_5_minutes"))
return
end
end
else
# OP cannot change polls
post.errors.add(:base, I18n.t("poll.cannot_change_polls_after_5_minutes"))
return
end
end
# deal with option changes
if User.staff.pluck(:id).include?(post.last_editor_id)
# staff can only edit options
polls.each_key do |poll_name|
if polls[poll_name]["options"].size != previous_polls[poll_name]["options"].size
post.errors.add(:base, I18n.t("poll.staff_cannot_add_or_remove_options_after_5_minutes"))
return
end
# merge votes when same number of options
polls.each_key do |poll_name|
next unless previous_polls.has_key?(poll_name)
next unless polls[poll_name]["options"].size == previous_polls[poll_name]["options"].size
polls[poll_name]["total_votes"] = previous_polls[poll_name]["total_votes"]
for o in 0...polls[poll_name]["options"].size
polls[poll_name]["options"][o]["votes"] = previous_polls[poll_name]["options"][o]["votes"]
end
# merge votes
polls.each_key do |poll_name|
polls[poll_name]["total_votes"] = previous_polls[poll_name]["total_votes"]
for o in 0...polls[poll_name]["options"].size
polls[poll_name]["options"][o]["votes"] = previous_polls[poll_name]["options"][o]["votes"]
end
end
else
# OP cannot change polls after 5 minutes
post.errors.add(:base, I18n.t("poll.cannot_change_polls_after_5_minutes"))
return
end
# immediately store the polls
post.custom_fields[POLLS_CUSTOM_FIELD] = polls
post.save_custom_fields(true)
# push the changes
DiscourseBus.publish("/polls/#{post_id}", { polls: polls })
end
# immediately store the polls
post.custom_fields[POLLS_CUSTOM_FIELD] = polls
post.save_custom_fields
end
else
# polls will be saved once we have a post id
self.polls = polls
end
true
end
Post.register_custom_field_type(POLLS_CUSTOM_FIELD, :json)