Skip to content

Commit

Permalink
Merge pull request #5012 from consul/multiple_answers
Browse files Browse the repository at this point in the history
Add poll questions that accept multiple answers per user
  • Loading branch information
Senen committed Oct 18, 2022
2 parents 760abff + 1eb52fb commit 0b8cd15
Show file tree
Hide file tree
Showing 52 changed files with 761 additions and 236 deletions.
21 changes: 21 additions & 0 deletions app/assets/javascripts/admin/votation_types/fields.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(function() {
"use strict";
App.AdminVotationTypesFields = {
adjustForm: function() {
if ($(this).val() === "unique") {
$(".max-votes").hide();
$(".description-unique").show();
$(".description-multiple").hide();
$(".votation-type-max-votes").prop("disabled", true);
} else {
$(".max-votes").show();
$(".description-unique").hide();
$(".description-multiple").show();
$(".votation-type-max-votes").prop("disabled", false);
}
},
initialize: function() {
$(".votation-type-vote-type").on("change", App.AdminVotationTypesFields.adjustForm).trigger("change");
}
};
}).call(this);
1 change: 1 addition & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ var initialize_modules = function() {
}
App.AdminBudgetsWizardCreationStep.initialize();
App.AdminMachineLearningScripts.initialize();
App.AdminVotationTypesFields.initialize();
App.BudgetEditAssociations.initialize();
App.BudgetHideMoney.initialize();
App.Datepicker.initialize();
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/sortable.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
attribute: "data-answer-id"
});
$.ajax({
url: $(".sortable").data("js-url"),
url: $(this).data("js-url"),
data: {
ordered_list: new_order
},
Expand Down
8 changes: 8 additions & 0 deletions app/components/admin/poll/questions/form_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@
<% end %>
</div>

<div class="row">
<div class="small-12">
<%= f.fields_for :votation_type do |votation_f| %>
<%= render Admin::VotationTypes::FieldsComponent.new(form: votation_f) %>
<% end %>
</div>
</div>

<div class="row">
<div class="small-12 medium-4 large-2 margin-top column">
<%= f.submit(class: "button success expanded", value: t("shared.save")) %>
Expand Down
20 changes: 20 additions & 0 deletions app/components/admin/votation_types/fields_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div class="small-12 medium-6 column">
<%= form.enum_select :vote_type, {}, class: "votation-type-vote-type" %>
</div>

<div class="small-12 column">
<div class="callout primary">
<span class="description-unique">
<%= t("admin.polls.votation_type.unique_description") %>
</span>
<span class="description-multiple hidden">
<%= t("admin.polls.votation_type.multiple_description") %>
</span>
</div>
</div>

<div class="small-12 medium-6 column end">
<div class="max-votes">
<%= form.number_field :max_votes, min: 2, max: 999, class: "votation-type-max-votes" %>
</div>
</div>
7 changes: 7 additions & 0 deletions app/components/admin/votation_types/fields_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Admin::VotationTypes::FieldsComponent < ApplicationComponent
attr_reader :form

def initialize(form:)
@form = form
end
end
16 changes: 11 additions & 5 deletions app/components/polls/questions/answers_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
<div class="poll-question-answers">
<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
<% question_answers.each do |question_answer| %>
<% if already_answered?(question_answer) && !voted_before_sign_in? %>
<span class="button answered"
title="<%= t("poll_questions.show.voted", answer: question_answer.title) %>">
<% if already_answered?(question_answer) %>
<%= button_to question_answer_path(question, user_answer(question_answer)),
method: :delete,
remote: true,
title: t("poll_questions.show.voted", answer: question_answer.title),
class: "button answered",
"aria-pressed": true do %>
<%= question_answer.title %>
</span>
<% end %>
<% else %>
<%= button_to answer_question_path(question, answer: question_answer.title),
remote: true,
title: t("poll_questions.show.vote_answer", answer: question_answer.title),
class: "button secondary hollow" do %>
class: "button secondary hollow",
"aria-pressed": false,
disabled: disable_answer?(question_answer) do %>
<%= question_answer.title %>
<% end %>
<% end %>
Expand Down
16 changes: 9 additions & 7 deletions app/components/polls/questions/answers_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@ def initialize(question)
end

def already_answered?(question_answer)
user_answers.find_by(answer: question_answer.title).present?
end

def voted_before_sign_in?
user_answers.any? do |vote|
vote.updated_at < current_user.current_sign_in_at
end
user_answer(question_answer).present?
end

def question_answers
question.question_answers
end

def user_answer(question_answer)
user_answers.find_by(answer: question_answer.title)
end

def disable_answer?(question_answer)
question.multiple? && user_answers.count == question.max_votes
end

private

def user_answers
Expand Down
13 changes: 13 additions & 0 deletions app/components/polls/questions/question_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,20 @@
<%= question.title %>
</h3>

<% if question.votation_type.present? %>
<strong>
<%= t("poll_questions.description.#{question.vote_type}", maximum: question.max_votes) %>
</strong>
<% end %>

<div id="<%= dom_id(question) %>_answers" class="padding">
<%= render Polls::Questions::AnswersComponent.new(question) %>
</div>

<% if question.answers_with_read_more? %>
<div>
<p><%= t("poll_questions.read_more_about") %></p>
<p><%= answers_read_more_links %></p>
</div>
<% end %>
</div>
6 changes: 6 additions & 0 deletions app/components/polls/questions/question_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@ class Polls::Questions::QuestionComponent < ApplicationComponent
def initialize(question:)
@question = question
end

def answers_read_more_links
safe_join(question.answers_with_read_more.map do |answer|
link_to answer.title, "#answer_#{answer.id}"
end, ", ")
end
end
60 changes: 0 additions & 60 deletions app/components/polls/questions/read_more_answer_component.html.erb

This file was deleted.

9 changes: 0 additions & 9 deletions app/components/polls/questions/read_more_answer_component.rb

This file was deleted.

63 changes: 63 additions & 0 deletions app/components/polls/questions/read_more_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<h2><%= question.title %></h2>
<% question.answers_with_read_more.each do |answer| %>
<div class="small-12 medium-6 column end answer <%= cycle("first", "") %>" id="answer_<%= answer.id %>">
<h3><%= answer.title %></h3>

<div class="margin-top">
<% if answer.description.present? %>
<div id="answer_description_<%= answer.id %>" class="answer-description short" data-toggler="short">
<%= wysiwyg(answer.description) %>
</div>
<div class="read-more">
<button type="button" id="read_more_<%= answer.id %>"
data-toggle="answer_description_<%= answer.id %> read_more_<%= answer.id %> read_less_<%= answer.id %>"
data-toggler="hide">
<%= t("polls.show.read_more", answer: answer.title) %>
</button>
<button type="button" id="read_less_<%= answer.id %>"
data-toggle="answer_description_<%= answer.id %> read_more_<%= answer.id %> read_less_<%= answer.id %>"
data-toggler="hide"
class="hide">
<%= t("polls.show.read_less", answer: answer.title) %>
</button>
</div>
<% end %>
<% if answer.images.any? %>
<%= render "polls/gallery", answer: answer %>
<% end %>
<% if answer.documents.present? %>
<div class="document-link">
<p>
<span class="icon-document"></span>&nbsp;
<strong><%= t("polls.show.documents") %></strong>
</p>

<% answer.documents.each do |document| %>
<%= link_to document.title,
document.attachment,
target: "_blank",
rel: "nofollow" %><br>
<% end %>
</div>
<% end %>
<% if answer.videos.present? %>
<div class="video-link">
<p>
<span class="icon-video"></span>&nbsp;
<strong><%= t("polls.show.videos") %></strong>
</p>

<% answer.videos.each do |video| %>
<%= link_to video.title,
video.url,
target: "_blank",
rel: "nofollow" %><br>
<% end %>
</div>
<% end %>
</div>
</div>
<% end %>
13 changes: 13 additions & 0 deletions app/components/polls/questions/read_more_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Polls::Questions::ReadMoreComponent < ApplicationComponent
with_collection_parameter :question
attr_reader :question
delegate :wysiwyg, to: :helpers

def initialize(question:)
@question = question
end

def render?
question.answers_with_read_more?
end
end
5 changes: 2 additions & 3 deletions app/controllers/admin/poll/questions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ def index
end

def new
@polls = Poll.all
proposal = Proposal.find(params[:proposal_id]) if params[:proposal_id].present?
@question.copy_attributes_from_proposal(proposal)
@question.poll = @poll
@question.votation_type = VotationType.new

authorize! :create, @question
end
Expand Down Expand Up @@ -58,8 +58,7 @@ def question_params
end

def allowed_params
attributes = [:poll_id, :question, :proposal_id]

attributes = [:poll_id, :question, :proposal_id, votation_type_attributes: [:vote_type, :max_votes]]
[*attributes, translation_params(Poll::Question)]
end

Expand Down
19 changes: 19 additions & 0 deletions app/controllers/polls/answers_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Polls::AnswersController < ApplicationController
load_and_authorize_resource :question, class: "::Poll::Question"
load_and_authorize_resource :answer, class: "::Poll::Answer",
through: :question,
through_association: :answers

def destroy
@answer.destroy_and_remove_voter_participation

respond_to do |format|
format.html do
redirect_to request.referer
end
format.js do
render "polls/questions/answers"
end
end
end
end
6 changes: 2 additions & 4 deletions app/controllers/polls/questions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ class Polls::QuestionsController < ApplicationController
has_orders %w[most_voted newest oldest], only: :show

def answer
answer = @question.answers.find_or_initialize_by(author: current_user)

answer.answer = params[:answer]
answer = @question.find_or_initialize_user_answer(current_user, params[:answer])
answer.save_and_record_voter_participation

respond_to do |format|
format.html do
redirect_to request.referer
end
format.js do
render :answer
render :answers
end
end
end
Expand Down
5 changes: 1 addition & 4 deletions app/controllers/polls_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ def index

def show
@questions = @poll.questions.for_render.sort_for_list
@poll_questions_answers = Poll::Question::Answer.where(question: @poll.questions)
.with_content.order(:given_order)
@commentable = @poll
@comment_tree = CommentTree.new(@commentable, params[:page], @current_order)
@comment_tree = CommentTree.new(@poll, params[:page], @current_order)
end

def stats
Expand Down
Loading

0 comments on commit 0b8cd15

Please sign in to comment.