diff --git a/Changelog.md b/Changelog.md index dac53baf4f69d3b3a084ae93d02c2378dae3ea92..b3dd6ac19ea6ccdc0b1cf21d938256be6dd79379 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,6 +15,7 @@ ## Features * Ask for confirmation when leaving a submittable comment field [#7530](https://github.com/diaspora/diaspora/pull/7530) +* Show users vote in polls [#7550](https://github.com/diaspora/diaspora/pull/7550) # 0.7.0.0 diff --git a/app/assets/javascripts/app/views/poll_view.js b/app/assets/javascripts/app/views/poll_view.js index 751e47538876884608130477b36f0c181c5d1114..275fb02d64b4512482f98c91230f0e65a7f123a5 100644 --- a/app/assets/javascripts/app/views/poll_view.js +++ b/app/assets/javascripts/app/views/poll_view.js @@ -17,15 +17,22 @@ app.views.Poll = app.views.Base.extend({ var isReshare = (this.model.get('post_type') === 'Reshare'); var showForm = defaultPresenter.loggedIn && !isReshare && - !this.model.get('already_participated_in_poll'); + !this.model.get("poll_participation_answer_id"); var originalPostLink = isReshare && this.model.get('root') ? '<a href="/posts/' + this.model.get('root').id + '" class="root_post_link">' + Diaspora.I18n.t('poll.original_post') + '</a>' : ''; + var answerGiven = this.model.get("poll_participation_answer_id"); + + if (defaultPresenter.poll && defaultPresenter.poll.poll_answers) { + defaultPresenter.poll.poll_answers.forEach(function(answer) { + _.extend(answer, {isCurrentUserVote: answerGiven ? answer.id === answerGiven : false}); + }); + } return _.extend(defaultPresenter, { show_form: showForm, is_reshare: isReshare, - original_post_link: originalPostLink + originalPostLink: originalPostLink }); }, diff --git a/app/assets/stylesheets/color_themes/_color_theme_override.scss b/app/assets/stylesheets/color_themes/_color_theme_override.scss index 7655d08f993a150b2a73ee0bba3c9d18ef90b1b1..37ec7066b33ab8e268ca90d10a0e21588ae818ee 100644 --- a/app/assets/stylesheets/color_themes/_color_theme_override.scss +++ b/app/assets/stylesheets/color_themes/_color_theme_override.scss @@ -6,7 +6,5 @@ body { .left-navbar .hoverable:hover { background-color: $main-color-essence; } - .poll_form .progress .bar { background-color: $main-color-dark; } - .badge { background-color: $brand-primary; } } diff --git a/app/assets/stylesheets/color_themes/_color_theme_override_dark.scss b/app/assets/stylesheets/color_themes/_color_theme_override_dark.scss index ec5e4ef46ceb2e13c6c31005f3c81d28ff14b44f..a09028a3ef92ecdc61458fd4ac82817b55992e47 100644 --- a/app/assets/stylesheets/color_themes/_color_theme_override_dark.scss +++ b/app/assets/stylesheets/color_themes/_color_theme_override_dark.scss @@ -22,6 +22,7 @@ body { .poll_form .progress { background-color: $gray-dark; .bar { background-color: $gray-light; } + .users-vote { background-color: $brand-primary; } } .stream-element .collapsible { diff --git a/app/assets/stylesheets/poll.scss b/app/assets/stylesheets/poll.scss index 21a5e84021137f34e22e4d779cf7fa9f80a1e779..5bd220a982c052991b52770f445527eaa51315be 100644 --- a/app/assets/stylesheets/poll.scss +++ b/app/assets/stylesheets/poll.scss @@ -26,6 +26,10 @@ height: 100%; text-align: left; } + + .users-vote { + background-color: $brand-primary; + } } .submit[disabled] { diff --git a/app/assets/templates/poll_tpl.jst.hbs b/app/assets/templates/poll_tpl.jst.hbs index a1a9be576fb0115dd2b47663de203f6679645109..2a8b221c26a6b770f5875fb953459d7ffd528c2f 100644 --- a/app/assets/templates/poll_tpl.jst.hbs +++ b/app/assets/templates/poll_tpl.jst.hbs @@ -13,13 +13,24 @@ {{#poll.poll_answers}} <div class="result-row"> <input type="radio" name="vote" value="{{id}}"/> - <label>{{answer}}</label> + {{#if isCurrentUserVote}} + <label> + {{answer}} + <span class="label label-primary">{{t "poll.your_vote"}}</span> + </label> + {{else}} + <label>{{answer}}</label> + {{/if}} <div class="poll-result pull-right"> <span class="percentage"></span> ({{t "poll.answer_count" count=vote_count}}) </div> <div class="poll_progress_bar_wrapper progress"> - <div class="poll_progress_bar bar" data-answerid="{{id}}" style="height: 100%"></div> + {{#if isCurrentUserVote}} + <div class="poll_progress_bar bar users-vote" data-answerid="{{id}}" style="height: 100%"></div> + {{else}} + <div class="poll_progress_bar bar" data-answerid="{{id}}" style="height: 100%"></div> + {{/if}} </div> </div> {{/poll.poll_answers}} @@ -38,7 +49,7 @@ {{#if is_reshare }} <div class="poll_footer"> - {{{t "poll.go_to_original_post" original_post_link=original_post_link}}} + {{{t "poll.go_to_original_post" original_post_link=originalPostLink}}} </div> {{/if}} </div> diff --git a/app/models/poll.rb b/app/models/poll.rb index 15589d601b37b0338ce20c54ce177877846c1522..05f8635d187315d5d3543f5d597616647c1b3d46 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -21,19 +21,19 @@ class Poll < ApplicationRecord def as_json(options={}) { - :poll_id => self.id, - :post_id => self.status_message.id, - :question => self.question, - :poll_answers => self.poll_answers, - :participation_count => self.participation_count, + poll_id: id, + post_id: status_message.id, + question: question, + poll_answers: poll_answers, + participation_count: participation_count } end - def participation_count - poll_answers.sum("vote_count") + def participation_answer(user) + poll_participations.find_by(author_id: user.person.id) end - def already_participated?(user) - poll_participations.where(:author_id => user.person.id).present? + def participation_count + poll_answers.sum("vote_count") end end diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb index a1187fba9446b6537356cea1941e99b71c73711f..7ed18afd3bf77105ab9b0ad15d1615c29843ba97 100644 --- a/app/presenters/post_presenter.rb +++ b/app/presenters/post_presenter.rb @@ -67,7 +67,7 @@ class PostPresenter < BasePresenter title: title, location: @post.post_location, poll: @post.poll, - already_participated_in_poll: already_participated_in_poll, + poll_participation_answer_id: poll_participation_answer_id, participation: participate?, interactions: build_interactions_json } @@ -121,10 +121,8 @@ class PostPresenter < BasePresenter @post.reshare_for(current_user).try(:as_api_response, :backbone) end - def already_participated_in_poll - if @post.poll && user_signed_in? - @post.poll.already_participated?(current_user) - end + def poll_participation_answer_id + @post.poll&.participation_answer(current_user)&.poll_answer_id if user_signed_in? end def participate? diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml index 8f4ed6953fdde063dcb8ba3a1216af117dcdd467..e89cf610918468fb8e95342c3d5782454c8ecf6f 100644 --- a/config/locales/javascript/javascript.en.yml +++ b/config/locales/javascript/javascript.en.yml @@ -344,3 +344,4 @@ en: other: "<%=count%> votes" show_result: "Show result" close_result: "Hide result" + your_vote: "Your vote" diff --git a/spec/javascripts/app/views/poll_view_spec.js b/spec/javascripts/app/views/poll_view_spec.js index 93d68533299cfdfa091c308c0e16d2ff17390ed4..034b0a5eb8af949b5f74c12ee9a0b9ce5365192d 100644 --- a/spec/javascripts/app/views/poll_view_spec.js +++ b/spec/javascripts/app/views/poll_view_spec.js @@ -65,7 +65,7 @@ describe("app.views.Poll", function(){ expect(this.view.$('form').length).toBe(1); }); it("hides vote form when user voted before", function(){ - this.view.model.attributes.already_participated_in_poll = true; + this.view.model.set("poll_participation_answer_id", this.view.poll.poll_answers[0].id); this.view.render(); expect(this.view.$('form').length).toBe(0); }); @@ -75,4 +75,25 @@ describe("app.views.Poll", function(){ expect(this.view.$('form').length).toBe(0); }); }); + + describe("answer given", function() { + it("adds 'users-vote' class to progress bar for the option the user voted for", function() { + var answer = this.view.poll.poll_answers[0]; + this.view.model.set("poll_participation_answer_id", answer.id); + expect(this.view.$(".poll_progress_bar.users-vote").length).toBe(1); + }); + + it("doesn't add 'users-vote' class to progress bar of the options the user didn't vote for", function() { + var answer1 = this.view.poll.poll_answers[0]; + var answer2 = this.view.poll.poll_answers[1]; + this.view.model.set("poll_participation_answer_id", answer1.id); + expect(this.view.$(".poll_progress_bar[data-answerid='" + answer2.id + "']").hasClass("users-vote")).toBe(false); + }); + + it("adds label next to the answer the user voted for", function() { + var answer = this.view.poll.poll_answers[0]; + this.view.model.set("poll_participation_answer_id", answer.id); + expect(this.view.$(".label.label-primary").length).toBe(1); + }); + }); }); diff --git a/spec/javascripts/jasmine_helpers/factory.js b/spec/javascripts/jasmine_helpers/factory.js index ba97e5b7151139ca3a1034f4b9c81cac32e2debb..217c68952c3673e9496bf9e2a2fed45aa542b66e 100644 --- a/spec/javascripts/jasmine_helpers/factory.js +++ b/spec/javascripts/jasmine_helpers/factory.js @@ -211,9 +211,9 @@ var factory = { }, postWithPoll : function(overrides) { - var defaultAttrs = _.extend(factory.postAttrs(), {"author" : this.author()}); - defaultAttrs = _.extend(defaultAttrs, {"already_participated_in_poll" : false}); - defaultAttrs = _.extend(defaultAttrs, {"poll" : factory.poll()}); + var defaultAttrs = _.extend(factory.postAttrs(), {"author": this.author()}); + defaultAttrs = _.extend(defaultAttrs, {"poll_participation_answer_id": null}); + defaultAttrs = _.extend(defaultAttrs, {"poll": factory.poll()}); return new app.models.Post(_.extend(defaultAttrs, overrides)); }, diff --git a/spec/models/poll_spec.rb b/spec/models/poll_spec.rb index f18eb4faba3cc23e95d0b834deec45c24f5b33f8..8a8add824b21211a879130a377b1071f055682b2 100644 --- a/spec/models/poll_spec.rb +++ b/spec/models/poll_spec.rb @@ -20,4 +20,23 @@ describe Poll, type: :model do expect(poll.errors).to have_key(:question) end end + + describe "poll_participation" do + it "should return the answer object after a user voted in a poll" do + answer = poll.poll_answers.build(answer: "1") + answer.poll = poll + poll.poll_answers.build(answer: "2").poll = poll + poll.save + participation = poll.poll_participations.create(poll_answer: answer, author: alice.person) + expect(poll.participation_answer(alice)).to eql(participation) + end + + it "should return nil if a user did not participate in a poll" do + answer = poll.poll_answers.build(answer: "1") + answer.poll = poll + poll.poll_answers.build(answer: "2").poll = poll + poll.save + expect(poll.participation_answer(alice)).to eql(nil) + end + end end diff --git a/spec/presenters/post_presenter_spec.rb b/spec/presenters/post_presenter_spec.rb index 4110cedeb319f4d9d558e8bbc60a06391ee503c2..d3bbd6cd04e9df40c02a598ec00450c448a52113 100644 --- a/spec/presenters/post_presenter_spec.rb +++ b/spec/presenters/post_presenter_spec.rb @@ -135,6 +135,19 @@ describe PostPresenter do presenter = PostPresenter.new(status_message_with_poll) expect(presenter.as_json).to be_a(Hash) end + + it "returns the answer id of the current user's poll participation" do + presenter = PostPresenter.new(status_message_with_poll, alice) + poll_answer = status_message_with_poll.poll.poll_answers.first + poll_participation = status_message_with_poll.poll.poll_participations + poll_participation = poll_participation.create(poll_answer: poll_answer, author: alice.person) + expect(presenter.as_json[:poll_participation_answer_id]).to eql(poll_participation.poll_answer_id) + end + + it "returns nil if the user did not participate in a poll" do + presenter = PostPresenter.new(status_message_with_poll, alice) + expect(presenter.as_json[:poll_participation_answer_id]).to eql(nil) + end end describe "#tags" do