From abf02808bffdf9559ecc385566d735c603c40b7e Mon Sep 17 00:00:00 2001 From: werdenktwas-gmbh <80844842+werdenktwas-gmbh@users.noreply.github.com> Date: Tue, 8 Jul 2025 13:06:39 +0200 Subject: [PATCH] Disable other answers when reaching maximum votes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is similar to the way we were disabling buttons in the old design. Co-authored-by: Javi Martín --- app/assets/javascripts/application.js | 2 ++ app/assets/javascripts/polls/form.js | 27 ++++++++++++++++ .../polls/questions/question_component.rb | 9 ++++++ .../questions/question_component_spec.rb | 15 --------- spec/system/polls/votation_types_spec.rb | 32 ++++++++++++++++++- 5 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 app/assets/javascripts/polls/form.js diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index d1070d56a..c4b419a95 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -120,6 +120,7 @@ //= require datepicker //= require authenticity_token_refresh //= require_tree ./admin +//= require_tree ./polls //= require_tree ./sdg //= require_tree ./sdg_management //= require_tree ./custom @@ -178,6 +179,7 @@ var initialize_modules = function() { App.BudgetEditAssociations.initialize(); App.BudgetHideMoney.initialize(); App.Datepicker.initialize(); + App.PollsForm.initialize(); App.SDGRelatedListSelector.initialize(); App.SDGManagementRelationSearch.initialize(); App.AuthenticityTokenRefresh.initialize(); diff --git a/app/assets/javascripts/polls/form.js b/app/assets/javascripts/polls/form.js new file mode 100644 index 000000000..f44e66742 --- /dev/null +++ b/app/assets/javascripts/polls/form.js @@ -0,0 +1,27 @@ +(function() { + "use strict"; + App.PollsForm = { + updateMultipleChoiceStatus: function(fieldset) { + var max_votes = $(fieldset).attr("data-max-votes"); + var checked_boxes = $(fieldset).find(":checkbox:checked"); + var unchecked_boxes = $(fieldset).find(":checkbox:not(:checked)"); + + if (checked_boxes.length >= max_votes) { + $(unchecked_boxes).prop("disabled", true); + } else { + $(fieldset).find(":checkbox").prop("disabled", false); + } + }, + initialize: function() { + $(".poll-form .multiple-choice").each(function() { + App.PollsForm.updateMultipleChoiceStatus(this); + }); + + $(".poll-form .multiple-choice :checkbox").on("change", function() { + var fieldset = $(this).closest("fieldset"); + + App.PollsForm.updateMultipleChoiceStatus(fieldset); + }); + } + }; +}).call(this); diff --git a/app/components/polls/questions/question_component.rb b/app/components/polls/questions/question_component.rb index 6961ca412..2669a8688 100644 --- a/app/components/polls/questions/question_component.rb +++ b/app/components/polls/questions/question_component.rb @@ -14,10 +14,19 @@ class Polls::Questions::QuestionComponent < ApplicationComponent tag.attributes( id: dom_id(question), disabled: ("disabled" if disabled?), + class: fieldset_class, data: { max_votes: question.max_votes } ) end + def fieldset_class + if multiple_choice? + "multiple-choice" + else + "single-choice" + end + end + def options_read_more_links safe_join(question.options_with_read_more.map do |option| link_to option.title, "#option_#{option.id}" diff --git a/spec/components/polls/questions/question_component_spec.rb b/spec/components/polls/questions/question_component_spec.rb index e03851222..dd76fd0fc 100644 --- a/spec/components/polls/questions/question_component_spec.rb +++ b/spec/components/polls/questions/question_component_spec.rb @@ -34,21 +34,6 @@ describe Polls::Questions::QuestionComponent do end end - skip "disables fields when maximum votes has been reached" do # TODO: requires JavaScript - user = create(:user, :verified) - question = create(:poll_question_multiple, :abc, max_votes: 2, author: user) - - create(:poll_answer, author: user, question: question, answer: "Answer A") - create(:poll_answer, author: user, question: question, answer: "Answer C") - sign_in(user) - - render_inline Polls::Questions::QuestionComponent.new(question) - - expect(page).to have_field "Answer A", type: :checkbox, checked: true - expect(page).to have_field "Answer B", type: :checkbox, checked: false - expect(page).to have_field "Answer C", type: :checkbox, checked: true - end - context "Verified user" do let(:user) { create(:user, :level_two) } before { sign_in(user) } diff --git a/spec/system/polls/votation_types_spec.rb b/spec/system/polls/votation_types_spec.rb index e77ad2d7b..a4de3edf9 100644 --- a/spec/system/polls/votation_types_spec.rb +++ b/spec/system/polls/votation_types_spec.rb @@ -2,13 +2,13 @@ require "rails_helper" describe "Poll Votation Type" do let(:author) { create(:user, :level_two) } + let(:poll) { create(:poll) } before do login_as(author) end scenario "Unique and multiple answers" do - poll = create(:poll) create(:poll_question_unique, :yes_no, poll: poll, title: "Is it that bad?") create(:poll_question_multiple, :abcde, poll: poll, max_votes: 3, title: "Which ones do you prefer?") @@ -41,4 +41,34 @@ describe "Poll Votation Type" do expect(page).to have_button "Vote" end + + scenario "Maximum votes has been reached" do + question = create(:poll_question_multiple, :abc, poll: poll, max_votes: 2) + create(:poll_answer, author: author, question: question, answer: "Answer A") + + visit poll_path(poll) + + expect(page).to have_field "Answer A", type: :checkbox, checked: true + expect(page).to have_field "Answer B", type: :checkbox, checked: false + expect(page).to have_field "Answer C", type: :checkbox, checked: false + + check "Answer C" + + expect(page).to have_field "Answer A", type: :checkbox, checked: true + expect(page).to have_field "Answer B", type: :checkbox, checked: false, disabled: true + expect(page).to have_field "Answer C", type: :checkbox, checked: true + + click_button "Vote" + + expect(page).to have_content "Thank you for voting!" + expect(page).to have_field "Answer A", type: :checkbox, checked: true + expect(page).to have_field "Answer B", type: :checkbox, checked: false, disabled: true + expect(page).to have_field "Answer C", type: :checkbox, checked: true + + uncheck "Answer A" + + expect(page).to have_field "Answer A", type: :checkbox, checked: false + expect(page).to have_field "Answer B", type: :checkbox, checked: false + expect(page).to have_field "Answer C", type: :checkbox, checked: true + end end