Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add poll questions that accept multiple answers per user #5012

Merged
merged 17 commits into from
Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
javierm marked this conversation as resolved.
Show resolved Hide resolved
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