Skip to content

Commit

Permalink
UI for open answers
Browse files Browse the repository at this point in the history
  • Loading branch information
dzenreda authored and taitus committed May 10, 2024
1 parent 55668b5 commit 5b4a537
Show file tree
Hide file tree
Showing 11 changed files with 281 additions and 3 deletions.
13 changes: 12 additions & 1 deletion app/assets/javascripts/custom/polls.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
(function() {
"use strict";
App.Polls = {
text_input_listener: function() {
$(document).on("input", ".text-input-form textarea", function(event) {
let submitButton = $(event.target).next();
if (submitButton.hasClass("answered")) {
submitButton.removeClass("answered");
submitButton.addClass("secondary hollow");
submitButton.val("Enviar");
}
});
},
initialize: function() {
$(".zoom-link").on("click", function(event) {
var answer;
Expand All @@ -20,6 +30,7 @@
}
}
});
}
App.Polls.text_input_listener();
},
};
}).call(this);
7 changes: 7 additions & 0 deletions app/assets/stylesheets/custom.scss
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,13 @@
z-index: 1;
}

// POLLS OPEN QUESTION

.poll-question-answers {
.text-input-form {
width: 100%;
}
}
// /* This controls how many elements will be on each row of the block grid. */
// /* Set this to whatever number you need, up to the max allowed in the variable */
// $per-row: false;
Expand Down
19 changes: 19 additions & 0 deletions app/components/custom/polls/questions/answers_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
<div class="poll-question-answers">
<% if question.vote_type == "open" %>
<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
<%= form_tag answer_question_path(question), remote: true, id: "question-#{question.id}", class: "text-input-form" do %>
<%= text_area_tag :answer, open_answer, rows: 4, required: true %>
<% if open_answer.empty? %>
<%= submit_tag(t("poll_questions.show.open.answer"), class: "button secondary hollow") %>
<% else %>
<%= submit_tag(t("poll_questions.show.open.answered"), class: "button answered") %>
<% end %>
<% end %>
<% elsif !user_signed_in? %>
<%= link_to t("poll_questions.show.open.answer"), new_user_session_path, class: "button secondary hollow" %>
<% elsif !current_user.level_two_or_three_verified? %>
<%= link_to t("poll_questions.show.open.answer"), verification_path, class: "button secondary hollow" %>
<% else %>
<%= text_area_tag :answer, open_answer, rows: 4, required: true, disabled: true %>
<% end %>
<% end %>

<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
<% question_answers.each do |question_answer| %>
<% if already_answered?(question_answer) %>
Expand Down
13 changes: 13 additions & 0 deletions app/components/custom/polls/questions/answers_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Polls::Questions::AnswersComponent < ApplicationComponent; end

require_dependency Rails.root.join("app", "components", "polls", "questions", "answers_component").to_s


class Polls::Questions::AnswersComponent < ApplicationComponent
def open_answer
if question.answers.nil? || question.answers.empty?
return ""
end
question.answers.by_author(current_user).first.answer
end
end
15 changes: 15 additions & 0 deletions app/models/custom/concerns/questionable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require_dependency Rails.root.join("app", "models", "concerns", "questionable").to_s

module Questionable
alias_method :consul_find_by_attributes, :find_by_attributes

private

def find_by_attributes(user, title)
if vote_type == "open"
{ author: user }
else
consul_find_by_attributes(user, title)
end
end
end
5 changes: 3 additions & 2 deletions app/models/custom/poll/answer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ class Poll::Answer < ApplicationRecord
validate :max_votes

validates :answer, inclusion: { in: ->(a) { a.question.possible_answers }},
unless: ->(a) { a.question.blank? }
unless: ->(a) { a.question.blank? },
if: ->(a) { a.question&.vote_type != 'open' }

scope :by_author, ->(author_id) { where(author_id: author_id) }
scope :by_question, ->(question_id) { where(question_id: question_id) }
Expand All @@ -36,7 +37,7 @@ def destroy_and_remove_voter_participation
private

def max_votes
return if !question || question&.unique? || persisted?
return if !question || question&.unique? || question.vote_type == 'open' || persisted?

author.lock!

Expand Down
7 changes: 7 additions & 0 deletions config/locales/custom/es/general.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ es:
services: Servicios Digitales
collaborative_legislation: Propuestas del Cabildo
tenerife_logo: "Cabildo Tenerife"
poll_questions:
description:
open: "Escribe aquí tu respuesta."
show:
open:
answer: Enviar
answered: Enviado
shared:
main_links:
cabildo: Cabildo Abierto
Expand Down
65 changes: 65 additions & 0 deletions spec/components/custom/polls/questions/answers_component_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
require "rails_helper"

describe Polls::Questions::AnswersComponent do
include Rails.application.routes.url_helpers
let(:poll) { create(:poll) }
let(:question) { create(:poll_question_open, poll: poll) }
let(:component) { Polls::Questions::AnswersComponent.new(question) }

describe "open questions" do

it "renders form to vote open question answers" do
sign_in(create(:user, :verified))

I18n.with_locale(:es) { render_inline component }

expect(page).to have_button "Enviar"
expect(page).not_to have_button "Enviado"
expect(page).to have_css "textarea[id='answer']"
end

it "renders custom button text when current user answers" do
user = create(:user, :verified)
create(:poll_answer, author: user, question: question, answer: "Yes")
sign_in(user)

I18n.with_locale(:es) { render_inline component }

expect(page).not_to have_button "Enviar"
expect(page).to have_button "Enviado"
end

it "when user is not signed in, renders submit button pointing to user sign in path" do
I18n.with_locale(:es) { render_inline component }

expect(page).to have_link "Enviar", href: new_user_session_path
end

it "when user is not verified, renders submit button pointing to user verification in path" do
sign_in(create(:user))

I18n.with_locale(:es) { render_inline component }

expect(page).to have_link "Enviar", href: verification_path
end

it "when user already voted in booth it renders disabled answers" do
user = create(:user, :level_two)
create(:poll_voter, :from_booth, poll: poll, user: user)
sign_in(user)

I18n.with_locale(:es) { render_inline component }

expect(page).to have_css "textarea[disabled='disabled']"
end

it "user cannot vote when poll expired it renders disabled form" do
question = create(:poll_question_open, poll: create(:poll, :expired))
sign_in(create(:user, :level_two))

I18n.with_locale(:es) { render_inline Polls::Questions::AnswersComponent.new(question) }

expect(page).to have_css "textarea[disabled='disabled']"
end
end
end
6 changes: 6 additions & 0 deletions spec/factories/polls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@
answer { question.question_answers.sample.title }
end

factory :poll_open_answer, class: "Poll::Answer" do
question factory: :poll_question_open
author factory: [:user, :level_two]
answer { "open text" }
end

factory :poll_partial_result, class: "Poll::PartialResult" do
question factory: [:poll_question, :yes_no]
author factory: :user
Expand Down
101 changes: 101 additions & 0 deletions spec/models/custom/poll/answer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
require "rails_helper"

describe Poll::Answer do
describe "validations" do
let(:answer) { build(:poll_open_answer) }

it "is valid" do
expect(answer).to be_valid
end

it "is not valid wihout a question" do
answer.question = nil
expect(answer).not_to be_valid
end

it "is not valid without an author" do
answer.author = nil
expect(answer).not_to be_valid
end

it "is not valid without an answer" do
answer.answer = nil
expect(answer).not_to be_valid
end
end

describe "#save_and_record_voter_participation" do
let(:author) { create(:user, :level_two) }
let(:poll) { create(:poll) }
let(:question) { create(:poll_question_open, poll: poll) }

it "creates a poll_voter with user and poll data" do
answer = create(:poll_open_answer, question: question, author: author, answer: "Yes")
expect(answer.poll.voters).to be_blank

answer.save_and_record_voter_participation
expect(poll.reload.voters.size).to eq(1)
voter = poll.voters.first

expect(voter.document_number).to eq(answer.author.document_number)
expect(voter.poll_id).to eq(answer.poll.id)
expect(voter.officer_id).to be nil
end

it "updates a poll_voter with user and poll data" do
answer = create(:poll_open_answer, question: question, author: author, answer: "Yes")
answer.save_and_record_voter_participation

expect(poll.reload.voters.size).to eq(1)

# answer = create(:poll_open_answer, question: question, author: author, answer: "No")
answer.answer = "no"
answer.save_and_record_voter_participation

expect(poll.reload.voters.size).to eq(1)

voter = poll.voters.first
expect(voter.document_number).to eq(answer.author.document_number)
expect(voter.poll_id).to eq(answer.poll.id)
end

it "does not save the answer if the voter is invalid" do
allow_any_instance_of(Poll::Voter).to receive(:valid?).and_return(false)
answer = build(:poll_open_answer)

expect do
answer.save_and_record_voter_participation
end.to raise_error(ActiveRecord::RecordInvalid)

expect(answer).not_to be_persisted
end
end

describe "#destroy_and_remove_voter_participation" do
let(:poll) { create(:poll) }
let(:question) { create(:poll_question_open, poll: poll) }

it "destroys voter record and answer when it was the only user's answer" do
answer = build(:poll_open_answer, question: question)
answer.save_and_record_voter_participation

expect { answer.destroy_and_remove_voter_participation }
.to change { Poll::Answer.count }.by(-1)
.and change { Poll::Voter.count }.by(-1)
end

it "destroys the answer but does not destroy the voter record when the user
has answered other poll questions" do
answer = build(:poll_open_answer, question: question)
answer.save_and_record_voter_participation
other_question = create(:poll_question_open, poll: poll)
other_answer = build(:poll_open_answer, question: other_question, author: answer.author)
other_answer.save_and_record_voter_participation

expect(other_answer).to be_persisted
expect { answer.destroy_and_remove_voter_participation }
.to change { Poll::Answer.count }.by(-1)
.and change { Poll::Voter.count }.by(0)
end
end
end
33 changes: 33 additions & 0 deletions spec/system/custom/polls/votation_types_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require "rails_helper"

describe "Poll Votation Type" do
let(:author) { create(:user, :level_two) }

before do
login_as(author)
end

scenario "Open answer" do
question = create(:poll_question_open)

visit poll_path(question.poll, locale: :es)

expect(page).to have_content "Escribe aquí tu respuesta."
expect(page).to have_content(question.title)
expect(page).to have_button("Enviar")
expect(page).not_to have_button("Enviado")

within "#poll_question_#{question.id}_answers" do
fill_in "answer", with: "Some text"
click_button "Enviar"

expect(page).to have_button("Enviado")
expect(page).not_to have_button("Enviar")

fill_in "answer", with: "Some another text"

expect(page).to have_button("Enviar")
expect(page).not_to have_button("Enviado")
end
end
end

0 comments on commit 5b4a537

Please sign in to comment.