Merge pull request #2262 from vikhyat/poll-plugin
Add open/close buttons to poll UI
This commit is contained in:
commit
fc1f225091
|
@ -9,7 +9,7 @@ Allows you to add a poll to the first post of a topic.
|
||||||
|
|
||||||
## Closing the poll
|
## Closing the poll
|
||||||
|
|
||||||
Change the start of the topic title from "Poll: " to "Closed Poll: "
|
Change the start of the topic title from "Poll: " to "Closed Poll: ". This feature is disabled if the `allow_user_locale` site setting is enabled.
|
||||||
|
|
||||||
_Note: closing a topic will also close the poll._
|
_Note: closing a topic will also close the poll._
|
||||||
|
|
||||||
|
@ -21,12 +21,12 @@ list to be used like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
Intro Text
|
Intro Text
|
||||||
|
|
||||||
- Item one
|
- Item one
|
||||||
- Item two
|
- Item two
|
||||||
|
|
||||||
Here are your choices:
|
Here are your choices:
|
||||||
|
|
||||||
[poll]
|
[poll]
|
||||||
- Option 1
|
- Option 1
|
||||||
- Option 2
|
- Option 2
|
||||||
|
|
|
@ -14,14 +14,28 @@
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<button {{action toggleShowResults}}>
|
<button {{action toggleShowResults}} class="btn btn-small">
|
||||||
{{#if showResults}}
|
{{#if showResults}}
|
||||||
|
<i class="fa fa-eye-slash"></i>
|
||||||
{{i18n poll.results.hide}}
|
{{i18n poll.results.hide}}
|
||||||
{{else}}
|
{{else}}
|
||||||
|
<i class="fa fa-eye"></i>
|
||||||
{{i18n poll.results.show}}
|
{{i18n poll.results.show}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{{#if controller.showToggleClosePoll}}
|
||||||
|
<button {{action toggleClosePoll}} class="btn btn-small">
|
||||||
|
{{#if poll.closed}}
|
||||||
|
<i class="fa fa-unlock-alt"></i>
|
||||||
|
{{i18n poll.open_poll}}
|
||||||
|
{{else}}
|
||||||
|
<i class="fa fa-lock"></i>
|
||||||
|
{{i18n poll.close_poll}}
|
||||||
|
{{/if}}
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if loading}}
|
{{#if loading}}
|
||||||
<i class="fa fa-spin fa-spinner"></i>
|
<i class="fa fa-spin fa-spinner"></i>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -44,8 +44,10 @@ var Poll = Discourse.Model.extend({
|
||||||
var PollController = Discourse.Controller.extend({
|
var PollController = Discourse.Controller.extend({
|
||||||
poll: null,
|
poll: null,
|
||||||
showResults: Em.computed.oneWay('poll.closed'),
|
showResults: Em.computed.oneWay('poll.closed'),
|
||||||
|
|
||||||
disableRadio: Em.computed.any('poll.closed', 'loading'),
|
disableRadio: Em.computed.any('poll.closed', 'loading'),
|
||||||
|
showToggleClosePoll: function() {
|
||||||
|
return this.get('poll.post.topic.details.can_edit') && !Discourse.SiteSettings.allow_user_locale;
|
||||||
|
}.property('poll.post.topic.details.can_edit'),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
selectOption: function(option) {
|
selectOption: function(option) {
|
||||||
|
@ -67,6 +69,18 @@ var PollController = Discourse.Controller.extend({
|
||||||
|
|
||||||
toggleShowResults: function() {
|
toggleShowResults: function() {
|
||||||
this.set('showResults', !this.get('showResults'));
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,3 +15,6 @@ en:
|
||||||
results:
|
results:
|
||||||
show: Show Results
|
show: Show Results
|
||||||
hide: Hide Results
|
hide: Hide Results
|
||||||
|
|
||||||
|
close_poll: "Close Poll"
|
||||||
|
open_poll: "Open Poll"
|
||||||
|
|
|
@ -58,11 +58,45 @@ after_initialize do
|
||||||
|
|
||||||
render json: poll.serialize(current_user)
|
render json: poll.serialize(current_user)
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
PollPlugin::Engine.routes.draw do
|
PollPlugin::Engine.routes.draw do
|
||||||
put '/' => 'poll#vote'
|
put '/' => 'poll#vote'
|
||||||
|
put '/toggle_close' => 'poll#toggle_close'
|
||||||
end
|
end
|
||||||
|
|
||||||
Discourse::Application.routes.append do
|
Discourse::Application.routes.append do
|
||||||
|
@ -147,4 +181,8 @@ register_css <<CSS
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.poll-ui button i.fa {
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
CSS
|
CSS
|
||||||
|
|
|
@ -60,7 +60,7 @@ module ::PollPlugin
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_closed?
|
def is_closed?
|
||||||
@post.topic.closed? || (@post.topic.title =~ /^#{I18n.t('poll.closed_prefix')}/i) === 0
|
@post.topic.closed? || @post.topic.archived? || (!SiteSetting.allow_user_locale? && (@post.topic.title =~ /^#{I18n.t('poll.closed_prefix')}/i) === 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
def options
|
def options
|
||||||
|
|
|
@ -2,52 +2,89 @@ require 'spec_helper'
|
||||||
|
|
||||||
describe PollPlugin::PollController, type: :controller do
|
describe PollPlugin::PollController, type: :controller do
|
||||||
let(:topic) { create_topic(title: "Poll: Chitoge vs Onodera") }
|
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(:user1) { Fabricate(:user) }
|
||||||
let(:user2) { Fabricate(:user) }
|
let(:user2) { Fabricate(:user) }
|
||||||
|
let(:admin) { Fabricate(:admin) }
|
||||||
|
|
||||||
it "should return 403 if no user is logged in" do
|
describe 'vote' do
|
||||||
xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll
|
it "returns 403 if no user is logged in" do
|
||||||
response.should be_forbidden
|
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
|
end
|
||||||
|
|
||||||
it "should return 400 if post_id or invalid option is not specified" do
|
describe 'toggle_close' do
|
||||||
log_in_user user1
|
it "returns 400 if post_id doesn't correspond to a poll post" do
|
||||||
xhr :put, :vote, use_route: :poll
|
log_in_user admin
|
||||||
response.status.should eq(400)
|
post2 = create_post(topic: topic, raw: "Generic reply")
|
||||||
xhr :put, :vote, post_id: post.id, use_route: :poll
|
xhr :put, :toggle_close, post_id: post2.id, use_route: :poll
|
||||||
response.status.should eq(400)
|
response.status.should eq(400)
|
||||||
xhr :put, :vote, option: "Chitoge", use_route: :poll
|
end
|
||||||
response.status.should eq(400)
|
|
||||||
xhr :put, :vote, post_id: post.id, option: "Tsugumi", use_route: :poll
|
|
||||||
response.status.should eq(400)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should return 400 if post_id doesn't correspond to a poll post" do
|
it "returns 400 if the topic is locked" do
|
||||||
log_in_user user1
|
log_in_user admin
|
||||||
post2 = create_post(topic: topic, raw: "Generic reply")
|
topic.update_attributes closed: true
|
||||||
xhr :put, :vote, post_id: post2.id, option: "Chitoge", use_route: :poll
|
xhr :put, :toggle_close, post_id: post.id, use_route: :poll
|
||||||
response.status.should eq(400)
|
response.status.should eq(400)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should save votes correctly" do
|
it "raises Discourse::InvalidAccess is the user is not authorized" do
|
||||||
MessageBus.expects(:publish).times(4)
|
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
|
it "renames the topic" do
|
||||||
xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll
|
I18n.stubs(:t).with('poll.prefix').returns("Poll ")
|
||||||
PollPlugin::Poll.new(post).get_vote(user1).should eq("Chitoge")
|
I18n.stubs(:t).with('poll.closed_prefix').returns("Closed Poll ")
|
||||||
|
log_in_user admin
|
||||||
log_in_user user2
|
xhr :put, :toggle_close, post_id: post.id, use_route: :poll
|
||||||
xhr :put, :vote, post_id: post.id, option: "Onodera", use_route: :poll
|
response.status.should eq(200)
|
||||||
PollPlugin::Poll.new(post).get_vote(user2).should eq("Onodera")
|
topic.reload.title.should == "Closed Poll : Chitoge vs Onodera"
|
||||||
|
xhr :put, :toggle_close, post_id: post.id, use_route: :poll
|
||||||
PollPlugin::Poll.new(post).details["Chitoge"].should eq(1)
|
response.status.should eq(200)
|
||||||
PollPlugin::Poll.new(post).details["Onodera"].should eq(1)
|
topic.reload.title.should == "Poll : Chitoge vs Onodera"
|
||||||
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue