From 5de7d889fda157f942c6a275bc95bf98d88ad892 Mon Sep 17 00:00:00 2001 From: Vikhyat Korrapati Date: Sat, 12 Apr 2014 22:53:21 +0530 Subject: [PATCH] Add close/open poll buttons to poll UI. --- .../discourse/templates/poll.js.handlebars | 12 ++ plugins/poll/assets/javascripts/poll_ui.js | 13 +- plugins/poll/config/locales/client.en.yml | 3 + plugins/poll/plugin.rb | 34 ++++++ .../spec/poll_plugin/poll_controller_spec.rb | 115 ++++++++++++------ 5 files changed, 137 insertions(+), 40 deletions(-) diff --git a/plugins/poll/assets/javascripts/discourse/templates/poll.js.handlebars b/plugins/poll/assets/javascripts/discourse/templates/poll.js.handlebars index 82b3ecd4f..c71974513 100644 --- a/plugins/poll/assets/javascripts/discourse/templates/poll.js.handlebars +++ b/plugins/poll/assets/javascripts/discourse/templates/poll.js.handlebars @@ -24,6 +24,18 @@ {{/if}} +{{#if poll.post.topic.details.can_edit}} + +{{/if}} + {{#if loading}} {{/if}} diff --git a/plugins/poll/assets/javascripts/poll_ui.js b/plugins/poll/assets/javascripts/poll_ui.js index 4e4bc8a56..90407615f 100644 --- a/plugins/poll/assets/javascripts/poll_ui.js +++ b/plugins/poll/assets/javascripts/poll_ui.js @@ -44,7 +44,6 @@ var Poll = Discourse.Model.extend({ var PollController = Discourse.Controller.extend({ poll: null, showResults: Em.computed.oneWay('poll.closed'), - disableRadio: Em.computed.any('poll.closed', 'loading'), actions: { @@ -67,6 +66,18 @@ var PollController = Discourse.Controller.extend({ toggleShowResults: function() { this.set('showResults', !this.get('showResults')); + }, + + toggleClosePoll: function() { + this.set('loading', true); + return Discourse.ajax("/poll/toggle_close", { + type: "PUT", + data: {post_id: this.get('poll.post.id')} + }).then(function(topicJson) { + this.set('poll.post.topic.title', topicJson.basic_topic.title); + this.set('poll.post.topic.fancy_title', topicJson.basic_topic.title); + this.set('loading', false); + }.bind(this)); } } }); diff --git a/plugins/poll/config/locales/client.en.yml b/plugins/poll/config/locales/client.en.yml index 0d9ed7c52..23169bcfc 100644 --- a/plugins/poll/config/locales/client.en.yml +++ b/plugins/poll/config/locales/client.en.yml @@ -15,3 +15,6 @@ en: results: show: Show Results hide: Hide Results + + close_poll: "Close Poll" + open_poll: "Open Poll" diff --git a/plugins/poll/plugin.rb b/plugins/poll/plugin.rb index 64d1a598b..fddf82516 100644 --- a/plugins/poll/plugin.rb +++ b/plugins/poll/plugin.rb @@ -58,11 +58,45 @@ after_initialize do render json: poll.serialize(current_user) end + + def toggle_close + post = Post.find(params[:post_id]) + topic = post.topic + poll = PollPlugin::Poll.new(post) + + # Make sure the user is allowed to close the poll. + Guardian.new(current_user).ensure_can_edit!(topic) + + # Make sure this is actually a poll. + unless poll.has_poll_details? + render status: 400, json: false + return + end + + # Make sure the topic is not closed. + if topic.closed? + render status: 400, json: false + return + end + + # Modify topic title. + if topic.title =~ /^(#{I18n.t('poll.prefix').strip})\s?:/i + topic.title = topic.title.gsub(/^(#{I18n.t('poll.prefix').strip})\s?:/i, I18n.t('poll.closed_prefix') + ':') + elsif topic.title =~ /^(#{I18n.t('poll.closed_prefix').strip})\s?:/i + topic.title = topic.title.gsub(/^(#{I18n.t('poll.closed_prefix').strip})\s?:/i, I18n.t('poll.prefix') + ':') + end + + topic.acting_user = current_user + topic.save! + + render json: topic, serializer: BasicTopicSerializer + end end end PollPlugin::Engine.routes.draw do put '/' => 'poll#vote' + put '/toggle_close' => 'poll#toggle_close' end Discourse::Application.routes.append do diff --git a/plugins/poll/spec/poll_plugin/poll_controller_spec.rb b/plugins/poll/spec/poll_plugin/poll_controller_spec.rb index 7ccdc471f..a621db576 100644 --- a/plugins/poll/spec/poll_plugin/poll_controller_spec.rb +++ b/plugins/poll/spec/poll_plugin/poll_controller_spec.rb @@ -2,52 +2,89 @@ require 'spec_helper' describe PollPlugin::PollController, type: :controller do let(:topic) { create_topic(title: "Poll: Chitoge vs Onodera") } - let(:post) { create_post(topic: topic, raw: "Pick one.\n\n[poll]\n* Chitoge\n* Onodera\n[/poll]") } + let!(:post) { create_post(topic: topic, raw: "Pick one.\n\n[poll]\n* Chitoge\n* Onodera\n[/poll]") } let(:user1) { Fabricate(:user) } let(:user2) { Fabricate(:user) } + let(:admin) { Fabricate(:admin) } - it "should return 403 if no user is logged in" do - xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll - response.should be_forbidden + describe 'vote' do + it "returns 403 if no user is logged in" do + xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll + response.should be_forbidden + end + + it "returns 400 if post_id or invalid option is not specified" do + log_in_user user1 + xhr :put, :vote, use_route: :poll + response.status.should eq(400) + xhr :put, :vote, post_id: post.id, use_route: :poll + response.status.should eq(400) + xhr :put, :vote, option: "Chitoge", use_route: :poll + response.status.should eq(400) + xhr :put, :vote, post_id: post.id, option: "Tsugumi", use_route: :poll + response.status.should eq(400) + end + + it "returns 400 if post_id doesn't correspond to a poll post" do + log_in_user user1 + post2 = create_post(topic: topic, raw: "Generic reply") + xhr :put, :vote, post_id: post2.id, option: "Chitoge", use_route: :poll + end + + it "saves votes correctly" do + MessageBus.expects(:publish).times(3) + + log_in_user user1 + xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll + PollPlugin::Poll.new(post).get_vote(user1).should eq("Chitoge") + + log_in_user user2 + xhr :put, :vote, post_id: post.id, option: "Onodera", use_route: :poll + PollPlugin::Poll.new(post).get_vote(user2).should eq("Onodera") + + PollPlugin::Poll.new(post).details["Chitoge"].should eq(1) + PollPlugin::Poll.new(post).details["Onodera"].should eq(1) + + xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll + PollPlugin::Poll.new(post).get_vote(user2).should eq("Chitoge") + + PollPlugin::Poll.new(post).details["Chitoge"].should eq(2) + PollPlugin::Poll.new(post).details["Onodera"].should eq(0) + end end - it "should return 400 if post_id or invalid option is not specified" do - log_in_user user1 - xhr :put, :vote, use_route: :poll - response.status.should eq(400) - xhr :put, :vote, post_id: post.id, use_route: :poll - response.status.should eq(400) - xhr :put, :vote, option: "Chitoge", use_route: :poll - response.status.should eq(400) - xhr :put, :vote, post_id: post.id, option: "Tsugumi", use_route: :poll - response.status.should eq(400) - end + describe 'toggle_close' do + it "returns 400 if post_id doesn't correspond to a poll post" do + log_in_user admin + post2 = create_post(topic: topic, raw: "Generic reply") + xhr :put, :toggle_close, post_id: post2.id, use_route: :poll + response.status.should eq(400) + end - it "should return 400 if post_id doesn't correspond to a poll post" do - log_in_user user1 - post2 = create_post(topic: topic, raw: "Generic reply") - xhr :put, :vote, post_id: post2.id, option: "Chitoge", use_route: :poll - response.status.should eq(400) - end + it "returns 400 if the topic is locked" do + log_in_user admin + topic.update_attributes closed: true + xhr :put, :toggle_close, post_id: post.id, use_route: :poll + response.status.should eq(400) + end - it "should save votes correctly" do - MessageBus.expects(:publish).times(4) + it "raises Discourse::InvalidAccess is the user is not authorized" do + log_in_user user1 + expect do + xhr :put, :toggle_close, post_id: post.id, use_route: :poll + end.to raise_error(Discourse::InvalidAccess) + end - log_in_user user1 - xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll - PollPlugin::Poll.new(post).get_vote(user1).should eq("Chitoge") - - log_in_user user2 - xhr :put, :vote, post_id: post.id, option: "Onodera", use_route: :poll - PollPlugin::Poll.new(post).get_vote(user2).should eq("Onodera") - - PollPlugin::Poll.new(post).details["Chitoge"].should eq(1) - PollPlugin::Poll.new(post).details["Onodera"].should eq(1) - - xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll - PollPlugin::Poll.new(post).get_vote(user2).should eq("Chitoge") - - PollPlugin::Poll.new(post).details["Chitoge"].should eq(2) - PollPlugin::Poll.new(post).details["Onodera"].should eq(0) + it "renames the topic" do + I18n.stubs(:t).with('poll.prefix').returns("Poll ") + I18n.stubs(:t).with('poll.closed_prefix').returns("Closed Poll ") + log_in_user admin + xhr :put, :toggle_close, post_id: post.id, use_route: :poll + response.status.should eq(200) + topic.reload.title.should == "Closed Poll : Chitoge vs Onodera" + xhr :put, :toggle_close, post_id: post.id, use_route: :poll + response.status.should eq(200) + topic.reload.title.should == "Poll : Chitoge vs Onodera" + end end end