Merge pull request #3398 from Platoniq/platoniq-dashboard/polls-form-bugs
Platoniq dashboard/polls form bugs
This commit is contained in:
20
app/assets/javascripts/answers.js.coffee
Normal file
20
app/assets/javascripts/answers.js.coffee
Normal file
@@ -0,0 +1,20 @@
|
||||
App.Answers =
|
||||
|
||||
initializeAnswers: (answers) ->
|
||||
$(answers).on 'cocoon:after-insert', (e, new_answer) ->
|
||||
given_order = App.Answers.maxGivenOrder(answers) + 1
|
||||
$(new_answer).find("[name$='[given_order]']").val(given_order)
|
||||
|
||||
maxGivenOrder: (answers) ->
|
||||
max_order = 0
|
||||
$(answers).find("[name$='[given_order]']").each (index, answer) ->
|
||||
value = parseFloat($(answer).val())
|
||||
max_order = if value > max_given_order then value else max_given_order
|
||||
return max_given_order
|
||||
|
||||
nestedAnswers: ->
|
||||
$('.js-answers').each (index, answers) ->
|
||||
App.Answers.initializeAnswers(answers)
|
||||
|
||||
initialize: ->
|
||||
App.Answers.nestedAnswers()
|
||||
@@ -59,6 +59,8 @@
|
||||
//= require markdown-it
|
||||
//= require markdown_editor
|
||||
//= require cocoon
|
||||
//= require answers
|
||||
//= require questions
|
||||
//= require legislation_admin
|
||||
//= require legislation
|
||||
//= require legislation_allegations
|
||||
@@ -87,6 +89,8 @@
|
||||
//= require send_admin_notification_alert
|
||||
|
||||
var initialize_modules = function() {
|
||||
App.Answers.initialize();
|
||||
App.Questions.initialize();
|
||||
App.Comments.initialize();
|
||||
App.Users.initialize();
|
||||
App.Votes.initialize();
|
||||
|
||||
8
app/assets/javascripts/questions.js.coffee
Normal file
8
app/assets/javascripts/questions.js.coffee
Normal file
@@ -0,0 +1,8 @@
|
||||
App.Questions =
|
||||
|
||||
nestedQuestions: ->
|
||||
$('.js-questions').on 'cocoon:after-insert', (e, new_question) ->
|
||||
App.Answers.initializeAnswers($(new_question).find('.js-answers'))
|
||||
|
||||
initialize: ->
|
||||
App.Questions.nestedQuestions()
|
||||
@@ -50,7 +50,8 @@ class Admin::Poll::Questions::AnswersController < Admin::Poll::BaseController
|
||||
|
||||
def answer_params
|
||||
documents_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
|
||||
attributes = [:title, :description, :question_id, documents_attributes: documents_attributes]
|
||||
attributes = [:title, :description, :given_order, :question_id,
|
||||
documents_attributes: documents_attributes]
|
||||
params.require(:poll_question_answer).permit(*attributes, *translation_params(Poll::Question::Answer))
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class Dashboard::PollsController < Dashboard::BaseController
|
||||
class Dashboard::PollsController < Dashboard::BaseController
|
||||
helper_method :poll
|
||||
|
||||
def index
|
||||
@@ -62,7 +62,8 @@ class Dashboard::PollsController < Dashboard::BaseController
|
||||
end
|
||||
|
||||
def question_answers_attributes
|
||||
[:id, :_destroy, :title, :description, :question_id, documents_attributes: documents_attributes]
|
||||
[:id, :_destroy, :title, :description, :given_order, :question_id,
|
||||
documents_attributes: documents_attributes]
|
||||
end
|
||||
|
||||
def documents_attributes
|
||||
|
||||
@@ -17,8 +17,6 @@ class Poll::Question::Answer < ActiveRecord::Base
|
||||
validates :title, presence: true
|
||||
validates :given_order, presence: true, uniqueness: { scope: :question_id }
|
||||
|
||||
before_validation :set_order, on: :create
|
||||
|
||||
def description
|
||||
self[:description].try :html_safe
|
||||
end
|
||||
@@ -29,10 +27,6 @@ class Poll::Question::Answer < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def set_order
|
||||
self.given_order = self.class.last_position(question_id) + 1
|
||||
end
|
||||
|
||||
def self.last_position(question_id)
|
||||
where(question_id: question_id).maximum('given_order') || 0
|
||||
end
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
<%= render 'shared/errors', resource: @answer %>
|
||||
|
||||
<%= f.hidden_field :given_order,
|
||||
value: @answer.persisted? ? @answer.given_order : @answer.class.last_position(@answer.question_id || @question.id) + 1 %>
|
||||
|
||||
<%= f.hidden_field :question_id, value: @answer.question_id || @question.id %>
|
||||
|
||||
<%= f.translatable_text_field :title %>
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="questions">
|
||||
<div class="js-questions">
|
||||
<%= f.fields_for :questions do |question| %>
|
||||
<%= render 'question_fields', f: question %>
|
||||
<% end %>
|
||||
|
||||
<div id="links" class="row expanded">
|
||||
<div class="links row expanded">
|
||||
<div class="small-12 column">
|
||||
<%= link_to_add_association t("dashboard.polls.form.add_question"),
|
||||
f, :questions, class: "button" %>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<div class="small-12 medium-6 column">
|
||||
<div class="nested-fields nested-answers small-12 medium-6 column">
|
||||
<div class="answer-fields">
|
||||
<%= f.hidden_field :given_order %>
|
||||
<div class="row expanded">
|
||||
<div class="small-12 medium-9 column">
|
||||
<%= f.text_field :title %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="question-fields">
|
||||
<div class="question-fields nested-fields">
|
||||
<%= f.hidden_field :author_id, value: f.object.author_id || current_user.id %>
|
||||
<%= f.hidden_field :proposal_id, value: f.object.proposal_id || proposal.id %>
|
||||
<div class="row expanded">
|
||||
@@ -12,12 +12,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="answers">
|
||||
<div class="js-answers">
|
||||
<%= f.fields_for :question_answers do |answer| %>
|
||||
<%= render 'question_answer_fields', f: answer %>
|
||||
<% end %>
|
||||
|
||||
<div id="links" class="row expanded">
|
||||
<div class="answer-links links row expanded">
|
||||
<div class="small-12 column">
|
||||
<%= link_to_add_association t("dashboard.polls.question_fields.add_answer"),
|
||||
f, :question_answers, class: "button hollow" %>
|
||||
|
||||
@@ -56,11 +56,12 @@ section "Creating Poll Questions & Answers" do
|
||||
end
|
||||
end
|
||||
question.save!
|
||||
Faker::Lorem.words((2..4).to_a.sample).each do |title|
|
||||
Faker::Lorem.words((2..4).to_a.sample).each_with_index do |title, index|
|
||||
description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>"
|
||||
answer = Poll::Question::Answer.new(question: question,
|
||||
title: title.capitalize,
|
||||
description: description)
|
||||
description: description,
|
||||
given_order: index + 1)
|
||||
I18n.available_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
answer.title = "#{title} (#{locale})"
|
||||
@@ -200,20 +201,7 @@ section "Creating Poll Questions from Proposals" do
|
||||
3.times do
|
||||
proposal = Proposal.all.sample
|
||||
poll = Poll.current.first
|
||||
question = Poll::Question.create(poll: poll)
|
||||
Faker::Lorem.words((2..4).to_a.sample).each do |title|
|
||||
description = "<p>#{Faker::ChuckNorris.fact}</p>"
|
||||
answer = Poll::Question::Answer.new(question: question,
|
||||
title: title.capitalize,
|
||||
description: description)
|
||||
I18n.available_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
answer.title = "#{title} (#{locale})"
|
||||
answer.description = "#{description} (#{locale})"
|
||||
end
|
||||
end
|
||||
answer.save!
|
||||
end
|
||||
question = Poll::Question.new(poll: poll)
|
||||
question.copy_attributes_from_proposal(proposal)
|
||||
title = question.title
|
||||
I18n.available_locales.map do |locale|
|
||||
@@ -222,6 +210,20 @@ section "Creating Poll Questions from Proposals" do
|
||||
end
|
||||
end
|
||||
question.save!
|
||||
Faker::Lorem.words((2..4).to_a.sample).each_with_index do |title, index|
|
||||
description = "<p>#{Faker::ChuckNorris.fact}</p>"
|
||||
answer = Poll::Question::Answer.new(question: question,
|
||||
title: title.capitalize,
|
||||
description: description,
|
||||
given_order: index + 1)
|
||||
I18n.available_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
answer.title = "#{title} (#{locale})"
|
||||
answer.description = "#{description} (#{locale})"
|
||||
end
|
||||
end
|
||||
answer.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -229,20 +231,7 @@ section "Creating Successful Proposals" do
|
||||
10.times do
|
||||
proposal = Proposal.all.sample
|
||||
poll = Poll.current.first
|
||||
question = Poll::Question.create(poll: poll)
|
||||
Faker::Lorem.words((2..4).to_a.sample).each do |title|
|
||||
description = "<p>#{Faker::ChuckNorris.fact}</p>"
|
||||
answer = Poll::Question::Answer.new(question: question,
|
||||
title: title.capitalize,
|
||||
description: description)
|
||||
I18n.available_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
answer.title = "#{title} (#{locale})"
|
||||
answer.description = "#{description} (#{locale})"
|
||||
end
|
||||
end
|
||||
answer.save!
|
||||
end
|
||||
question = Poll::Question.new(poll: poll)
|
||||
question.copy_attributes_from_proposal(proposal)
|
||||
title = question.title
|
||||
I18n.available_locales.map do |locale|
|
||||
@@ -251,5 +240,19 @@ section "Creating Successful Proposals" do
|
||||
end
|
||||
end
|
||||
question.save!
|
||||
Faker::Lorem.words((2..4).to_a.sample).each_with_index do |title, index|
|
||||
description = "<p>#{Faker::ChuckNorris.fact}</p>"
|
||||
answer = Poll::Question::Answer.new(question: question,
|
||||
title: title.capitalize,
|
||||
description: description,
|
||||
given_order: index + 1)
|
||||
I18n.available_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
answer.title = "#{title} (#{locale})"
|
||||
answer.description = "#{description} (#{locale})"
|
||||
end
|
||||
end
|
||||
answer.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,6 +47,7 @@ FactoryBot.define do
|
||||
association :question, factory: :poll_question
|
||||
sequence(:title) { |n| "Answer title #{n}" }
|
||||
sequence(:description) { |n| "Answer description #{n}" }
|
||||
sequence(:given_order) { |n| n }
|
||||
end
|
||||
|
||||
factory :poll_answer_video, class: 'Poll::Question::Answer::Video' do
|
||||
|
||||
@@ -65,7 +65,7 @@ feature 'Answers' do
|
||||
expect(page).to have_content(new_title)
|
||||
expect(page).not_to have_content(old_title)
|
||||
|
||||
expect(page.body.index(new_title)).to be < page.body.index(answer2.title)
|
||||
expect(answer2.title).to appear_before(new_title)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -52,7 +52,7 @@ feature 'Polls' do
|
||||
|
||||
scenario 'Edit poll is allowed for upcoming polls' do
|
||||
poll = create(:poll, :incoming, related: proposal)
|
||||
|
||||
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
|
||||
within "div#poll_#{poll.id}" do
|
||||
@@ -68,7 +68,7 @@ feature 'Polls' do
|
||||
|
||||
scenario 'Edit poll redirects back when invalid data', js: true do
|
||||
poll = create(:poll, :incoming, related: proposal)
|
||||
|
||||
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
|
||||
within "div#poll_#{poll.id}" do
|
||||
@@ -86,7 +86,7 @@ feature 'Polls' do
|
||||
|
||||
scenario 'Edit poll is not allowed for current polls' do
|
||||
poll = create(:poll, :current, related: proposal)
|
||||
|
||||
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
|
||||
within "div#poll_#{poll.id}" do
|
||||
@@ -96,7 +96,7 @@ feature 'Polls' do
|
||||
|
||||
scenario 'Edit poll is not allowed for expired polls' do
|
||||
poll = create(:poll, :expired, related: proposal)
|
||||
|
||||
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
|
||||
within "div#poll_#{poll.id}" do
|
||||
@@ -104,9 +104,58 @@ feature 'Polls' do
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Edit poll should allow to remove questions", :js do
|
||||
poll = create(:poll, :incoming, related: proposal)
|
||||
create(:poll_question, poll: poll)
|
||||
create(:poll_question, poll: poll)
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
within "div#poll_#{poll.id}" do
|
||||
click_link "Edit survey"
|
||||
end
|
||||
|
||||
within ".js-questions" do
|
||||
expect(page).to have_css ".nested-fields", count: 2
|
||||
within first(".nested-fields") do
|
||||
find("a.delete").click
|
||||
end
|
||||
expect(page).to have_css ".nested-fields", count: 1
|
||||
end
|
||||
|
||||
click_button "Update poll"
|
||||
visit edit_proposal_dashboard_poll_path(proposal, poll)
|
||||
|
||||
expect(page).to have_css ".nested-fields", count: 1
|
||||
end
|
||||
|
||||
scenario "Edit poll should allow to remove answers", :js do
|
||||
poll = create(:poll, :incoming, related: proposal)
|
||||
question = create(:poll_question, poll: poll)
|
||||
create(:poll_question_answer, question: question)
|
||||
create(:poll_question_answer, question: question)
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
within "div#poll_#{poll.id}" do
|
||||
click_link "Edit survey"
|
||||
end
|
||||
|
||||
within ".js-questions .js-answers" do
|
||||
expect(page).to have_css ".nested-fields", count: 2
|
||||
within first(".nested-fields") do
|
||||
find("a.delete").click
|
||||
end
|
||||
expect(page).to have_css ".nested-fields", count: 1
|
||||
end
|
||||
|
||||
click_button "Update poll"
|
||||
visit edit_proposal_dashboard_poll_path(proposal, poll)
|
||||
|
||||
within ".js-questions .js-answers" do
|
||||
expect(page).to have_css ".nested-fields", count: 1
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'View results not available for upcoming polls' do
|
||||
poll = create(:poll, :incoming, related: proposal)
|
||||
|
||||
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
|
||||
within "div#poll_#{poll.id}" do
|
||||
@@ -116,7 +165,7 @@ feature 'Polls' do
|
||||
|
||||
scenario 'View results available for current polls' do
|
||||
poll = create(:poll, :current, related: proposal)
|
||||
|
||||
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
|
||||
within "div#poll_#{poll.id}" do
|
||||
@@ -126,7 +175,7 @@ feature 'Polls' do
|
||||
|
||||
scenario 'View results available for expired polls' do
|
||||
poll = create(:poll, :expired, related: proposal)
|
||||
|
||||
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
|
||||
within "div#poll_#{poll.id}" do
|
||||
@@ -136,7 +185,7 @@ feature 'Polls' do
|
||||
|
||||
scenario 'View results redirects to results in public zone', js: true do
|
||||
poll = create(:poll, :expired, related: proposal)
|
||||
|
||||
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
|
||||
within "div#poll_#{poll.id}" do
|
||||
@@ -150,7 +199,7 @@ feature 'Polls' do
|
||||
|
||||
scenario 'Poll card' do
|
||||
poll = create(:poll, :expired, related: proposal)
|
||||
|
||||
|
||||
visit proposal_dashboard_polls_path(proposal)
|
||||
|
||||
within "div#poll_#{poll.id}" do
|
||||
|
||||
@@ -8,11 +8,11 @@ feature 'Officing Results', :with_frozen_time do
|
||||
@poll = @officer_assignment.booth_assignment.poll
|
||||
@poll.update(ends_at: 1.day.ago)
|
||||
@question_1 = create(:poll_question, poll: @poll)
|
||||
create(:poll_question_answer, title: 'Yes', question: @question_1)
|
||||
create(:poll_question_answer, title: 'No', question: @question_1)
|
||||
create(:poll_question_answer, title: "Yes", question: @question_1, given_order: 1)
|
||||
create(:poll_question_answer, title: "No", question: @question_1, given_order: 2)
|
||||
@question_2 = create(:poll_question, poll: @poll)
|
||||
create(:poll_question_answer, title: 'Today', question: @question_2)
|
||||
create(:poll_question_answer, title: 'Tomorrow', question: @question_2)
|
||||
create(:poll_question_answer, title: "Today", question: @question_2, given_order: 1)
|
||||
create(:poll_question_answer, title: "Tomorrow", question: @question_2, given_order: 2)
|
||||
|
||||
login_as(@poll_officer.user)
|
||||
end
|
||||
|
||||
@@ -16,7 +16,7 @@ feature 'Answers' do
|
||||
visit admin_question_path(question)
|
||||
|
||||
expect(page).to have_css(".poll_question_answer", count: 2)
|
||||
expect(page.body.index(answer1.title)).to be < page.body.index(answer2.title)
|
||||
expect(answer2.title).to appear_before(answer1.title)
|
||||
|
||||
within("#poll_question_answer_#{answer1.id}") do
|
||||
expect(page).to have_content answer1.title
|
||||
|
||||
@@ -28,7 +28,7 @@ feature 'Polls' do
|
||||
|
||||
scenario "Proposal polls won't be listed" do
|
||||
proposal = create(:proposal)
|
||||
_poll = create(:poll, related: proposal)
|
||||
_poll = create(:poll, related: proposal)
|
||||
|
||||
visit polls_path
|
||||
expect(page).to have_content('There are no open votings')
|
||||
@@ -164,7 +164,7 @@ feature 'Polls' do
|
||||
visit poll_path(poll)
|
||||
|
||||
within("div#poll_question_#{question.id}") do
|
||||
expect(page.body.index(answer1.title)).to be < page.body.index(answer2.title)
|
||||
expect(answer2.title).to appear_before(answer1.title)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -176,7 +176,7 @@ feature 'Polls' do
|
||||
visit poll_path(poll)
|
||||
|
||||
within('div.poll-more-info-answers') do
|
||||
expect(page.body.index(answer1.title)).to be < page.body.index(answer2.title)
|
||||
expect(answer2.title).to appear_before(answer1.title)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user