Merge pull request #3586 from LextrendIT/feature/3475_add_votation_types
Add custom votation types
This commit is contained in:
@@ -87,6 +87,7 @@
|
|||||||
//= require cookies
|
//= require cookies
|
||||||
//= require columns_selector
|
//= require columns_selector
|
||||||
//= require budget_edit_associations.js.coffee
|
//= require budget_edit_associations.js.coffee
|
||||||
|
//= require votations
|
||||||
|
|
||||||
var initialize_modules = function() {
|
var initialize_modules = function() {
|
||||||
App.Answers.initialize();
|
App.Answers.initialize();
|
||||||
@@ -140,6 +141,8 @@ var initialize_modules = function() {
|
|||||||
if ( $('#js-columns-selector').length )
|
if ( $('#js-columns-selector').length )
|
||||||
App.ColumnsSelector.initialize();
|
App.ColumnsSelector.initialize();
|
||||||
App.BudgetEditAssociations.initialize();
|
App.BudgetEditAssociations.initialize();
|
||||||
|
if ( $("#votation_type_enum_type").length )
|
||||||
|
App.Votations.initialize();
|
||||||
};
|
};
|
||||||
|
|
||||||
$(function(){
|
$(function(){
|
||||||
|
|||||||
@@ -7,3 +7,11 @@ App.Sortable =
|
|||||||
url: $(".sortable").data("js-url"),
|
url: $(".sortable").data("js-url"),
|
||||||
data: { ordered_list: new_order },
|
data: { ordered_list: new_order },
|
||||||
type: "POST"
|
type: "POST"
|
||||||
|
|
||||||
|
$(".sortable-priotirized-votation").sortable
|
||||||
|
update: (event, ui) ->
|
||||||
|
new_order = $(this).sortable("toArray", { attribute: "data-answer-id" })
|
||||||
|
$.ajax
|
||||||
|
url: $(this).data("js-url"),
|
||||||
|
data: { ordered_list: new_order },
|
||||||
|
type: "POST"
|
||||||
|
|||||||
45
app/assets/javascripts/votations.js.coffee
Normal file
45
app/assets/javascripts/votations.js.coffee
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
App.Votations =
|
||||||
|
|
||||||
|
checkMaxVotes: ->
|
||||||
|
if $("#votation_type_enum_type").val() == "0"
|
||||||
|
$(".js-max_votes").hide()
|
||||||
|
$("#max_votes").attr(disabled: true)
|
||||||
|
else
|
||||||
|
$(".js-max_votes").show()
|
||||||
|
$("#max_votes").attr(disabled: false)
|
||||||
|
|
||||||
|
checkPrioritization: ->
|
||||||
|
if $("#votation_type_enum_type").val() == "2"
|
||||||
|
$(".js-prioritization_type").show()
|
||||||
|
$("#prioritization_type").attr(disabled: false)
|
||||||
|
else
|
||||||
|
$(".js-prioritization_type").hide()
|
||||||
|
$("#prioritization_type").attr(disabled: true)
|
||||||
|
|
||||||
|
checkMaxGroups: ->
|
||||||
|
if $("#votation_type_enum_type").val() == "7" || $("#votation_type_enum_type").val() == "8"
|
||||||
|
$(".js-max_group_votes").show()
|
||||||
|
$("#max_groups_answers").attr(disabled: false)
|
||||||
|
else
|
||||||
|
$(".js-max_group_votes").hide()
|
||||||
|
$("#max_groups_answers").attr(disabled: true)
|
||||||
|
|
||||||
|
setTraduction: (response) ->
|
||||||
|
console.log response
|
||||||
|
$(".js-description_text").text(response["traduction"])
|
||||||
|
|
||||||
|
updateChecks: () ->
|
||||||
|
App.Votations.checkMaxVotes()
|
||||||
|
App.Votations.checkPrioritization()
|
||||||
|
App.Votations.checkMaxGroups()
|
||||||
|
|
||||||
|
initialize: ->
|
||||||
|
App.Votations.updateChecks()
|
||||||
|
$("#votation_type_enum_type").on
|
||||||
|
change: ->
|
||||||
|
App.Votations.updateChecks()
|
||||||
|
url = "/admin/get_options_traductions.json"
|
||||||
|
params = { enum_type: $("#votation_type_enum_type").val() }
|
||||||
|
$.get(url, params, (response) -> App.Votations.setTraduction response, "json")
|
||||||
|
|
||||||
|
false
|
||||||
@@ -786,6 +786,10 @@ code {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
|
|
||||||
.callout {
|
.callout {
|
||||||
@@ -796,6 +800,15 @@ table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.info-type {
|
||||||
|
background-color: #ccf5ff;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-description {
|
||||||
|
margin-top: rem-calc(20);
|
||||||
|
}
|
||||||
|
|
||||||
// 07. Legislation
|
// 07. Legislation
|
||||||
// --------------
|
// --------------
|
||||||
|
|
||||||
|
|||||||
@@ -1745,8 +1745,12 @@
|
|||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
|
|
||||||
.column:nth-child(odd) {
|
.margin-bottom {
|
||||||
border-right: 2px solid $text;
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orbit-bullets {
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-divider {
|
.answer-divider {
|
||||||
@@ -1756,14 +1760,35 @@
|
|||||||
padding-bottom: $line-height;
|
padding-bottom: $line-height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.answer-left-divider {
|
||||||
|
border-left: solid 1px $text;
|
||||||
|
padding-left: rem-calc(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-top {
|
||||||
|
margin-top: rem-calc(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-bottom {
|
||||||
|
margin-bottom: rem-calc(20);
|
||||||
|
}
|
||||||
|
|
||||||
.answer-description {
|
.answer-description {
|
||||||
height: 100%;
|
max-height: rem-calc(1000);
|
||||||
|
|
||||||
&.short {
|
&.short {
|
||||||
height: rem-calc(300);
|
max-height: rem-calc(70);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
max-width: rem-calc(700);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.question-divider {
|
||||||
|
border-bottom: rgba(219, 219, 219, 0.62) solid 1px;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
padding: rem-calc(24);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.orbit-bullets button {
|
.orbit-bullets button {
|
||||||
@@ -1991,6 +2016,69 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-like,
|
||||||
|
.icon-unlike {
|
||||||
|
background: #fff;
|
||||||
|
border: 2px solid $text-light;
|
||||||
|
border-radius: rem-calc(3);
|
||||||
|
color: $text-light;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: rem-calc(30);
|
||||||
|
line-height: rem-calc(30);
|
||||||
|
padding: rem-calc(3) rem-calc(6);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.active-like {
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 1 !important;
|
||||||
|
background: $like;
|
||||||
|
border: 2px solid $like;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active-unlike {
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 1 !important;
|
||||||
|
background: $unlike;
|
||||||
|
border: 2px solid $unlike;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-like {
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active,
|
||||||
|
.picked {
|
||||||
|
background: $like;
|
||||||
|
border: 2px solid $like;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-unlike {
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
background: $unlike;
|
||||||
|
border: 2px solid $unlike;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-align {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-divider {
|
||||||
|
border-bottom: 1px solid $text-light;
|
||||||
|
}
|
||||||
|
|
||||||
// 09. Polls results and stats
|
// 09. Polls results and stats
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
|
|||||||
before_action :load_change_log, only: [:show]
|
before_action :load_change_log, only: [:show]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
load_tags
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
format.js
|
format.js
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class Admin::Poll::QuestionsController < Admin::Poll::BaseController
|
|||||||
|
|
||||||
def create
|
def create
|
||||||
@question.author = @question.proposal.try(:author) || current_user
|
@question.author = @question.proposal.try(:author) || current_user
|
||||||
|
@question.votation_type = VotationType.build_by_type(@question, params[:votation_type])
|
||||||
|
|
||||||
if @question.save
|
if @question.save
|
||||||
redirect_to admin_question_path(@question)
|
redirect_to admin_question_path(@question)
|
||||||
@@ -53,11 +54,18 @@ class Admin::Poll::QuestionsController < Admin::Poll::BaseController
|
|||||||
redirect_to admin_questions_path, notice: notice
|
redirect_to admin_questions_path, notice: notice
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_options_traductions
|
||||||
|
render json: {
|
||||||
|
traduction: t("polls.index.descriptions.#{VotationType.enum_types.key params[:enum_type].to_i}")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def question_params
|
def question_params
|
||||||
attributes = [:poll_id, :question, :proposal_id]
|
attributes = [:poll_id, :question, :proposal_id]
|
||||||
params.require(:poll_question).permit(*attributes, translation_params(Poll::Question))
|
params.require(:poll_question).permit(*attributes, translation_params(Poll::Question),
|
||||||
|
:votation_type, :max_votes, :prioritization_type, :max_groups_answers)
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_params
|
def search_params
|
||||||
|
|||||||
70
app/controllers/polls/answers_controller.rb
Normal file
70
app/controllers/polls/answers_controller.rb
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
class Polls::AnswersController < ApplicationController
|
||||||
|
|
||||||
|
load_and_authorize_resource :poll
|
||||||
|
load_and_authorize_resource :question, class: "Poll::Question"
|
||||||
|
authorize_resource :answer, class: "Poll::Answer"
|
||||||
|
|
||||||
|
def create
|
||||||
|
@question = Poll::Question.find_by(id: params[:id])
|
||||||
|
if @question.votation_type.open? && !check_question_answer_exist
|
||||||
|
@question.question_answers.create(
|
||||||
|
title: params[:answer],
|
||||||
|
given_order: @question.question_answers.count + 1,
|
||||||
|
hidden: false
|
||||||
|
)
|
||||||
|
flash.now[:notice] = t("dashboard.polls.index.succesfull")
|
||||||
|
else
|
||||||
|
flash.now[:alert] = "Unfortunately failed to sent"
|
||||||
|
end
|
||||||
|
load_for_answers
|
||||||
|
if @question.enum_type&.include?("answer_couples")
|
||||||
|
last_pair ||= generate_and_store_new_pair(@question)
|
||||||
|
@last_pair_question_answers = {@question.id => last_pair}
|
||||||
|
end
|
||||||
|
render "polls/questions/answer", format: :js
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete
|
||||||
|
@question = Poll::Question.find_by(id: params[:id])
|
||||||
|
!@question.answers.find_by(author: current_user, answer: params[:answer]).destroy
|
||||||
|
@question.question_answers.each do |question_answer|
|
||||||
|
question_answer.set_most_voted
|
||||||
|
end
|
||||||
|
question_answers
|
||||||
|
load_for_answers
|
||||||
|
if @question.enum_type&.include?("answer_couples")
|
||||||
|
last_pair ||= generate_and_store_new_pair(@question)
|
||||||
|
@last_pair_question_answers = {@question.id => last_pair}
|
||||||
|
end
|
||||||
|
render "polls/questions/answer", format: :js
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def check_question_answer_exist
|
||||||
|
exist = false
|
||||||
|
@question.question_answers.each do |question_answer|
|
||||||
|
break if exist
|
||||||
|
exist = true if question_answer.title == params[:answer]
|
||||||
|
end
|
||||||
|
exist
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_for_answers
|
||||||
|
@page = params[:page].present? ? params[:page] : 1
|
||||||
|
question_answers
|
||||||
|
@answers_by_question_id = {@question.id => @question.answers
|
||||||
|
.by_author(current_user)
|
||||||
|
.order(:order)
|
||||||
|
.pluck(:answer)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def question_answers
|
||||||
|
if @question.is_positive_negative?
|
||||||
|
@answers = @question.question_answers.visibles.page(params[:page])
|
||||||
|
else
|
||||||
|
@answers = @question.question_answers.visibles
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -3,18 +3,79 @@ class Polls::QuestionsController < ApplicationController
|
|||||||
load_and_authorize_resource :poll
|
load_and_authorize_resource :poll
|
||||||
load_and_authorize_resource :question, class: "Poll::Question"
|
load_and_authorize_resource :question, class: "Poll::Question"
|
||||||
|
|
||||||
has_orders %w{most_voted newest oldest}, only: :show
|
has_orders %w[most_voted newest oldest], only: :show
|
||||||
|
|
||||||
def answer
|
def answer
|
||||||
answer = @question.answers.find_or_initialize_by(author: current_user)
|
answer = store_answer
|
||||||
token = params[:token]
|
vote_stored(answer, params[:answer], params[:token]) if answer.present?
|
||||||
|
load_for_answers
|
||||||
|
if @question.enum_type&.include?("answer_couples")
|
||||||
|
last_pair ||= generate_and_store_new_pair(@question)
|
||||||
|
@last_pair_question_answers = {@question.id => last_pair}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
answer.answer = params[:answer]
|
def load_answers
|
||||||
|
load_for_answers
|
||||||
|
render action: "answer.js.erb"
|
||||||
|
end
|
||||||
|
|
||||||
|
def prioritized_answers
|
||||||
|
unless params[:ordered_list].empty?
|
||||||
|
params[:ordered_list].each_with_index do |answer, i|
|
||||||
|
answer_obj = @question.votation_type.answer(current_user,
|
||||||
|
answer,
|
||||||
|
order: i + 1)
|
||||||
|
vote_stored(answer_obj, answer, params[:tooken]) if answer_obj.present?
|
||||||
|
end
|
||||||
|
@question.votation_type.update_priorized_values(current_user.id)
|
||||||
|
end
|
||||||
|
load_for_answers
|
||||||
|
render action: "answer.js.erb"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def load_for_answers
|
||||||
|
@page = params[:page].present? ? params[:page] : 1
|
||||||
|
question_answers
|
||||||
|
@answers_by_question_id = {@question.id => @question.answers
|
||||||
|
.by_author(current_user)
|
||||||
|
.order(:order)
|
||||||
|
.pluck(:answer)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def vote_stored(answer, new_answer, token)
|
||||||
|
answer.answer = new_answer
|
||||||
answer.touch if answer.persisted?
|
answer.touch if answer.persisted?
|
||||||
answer.save!
|
answer.save!
|
||||||
answer.record_voter_participation(token)
|
answer.record_voter_participation(token)
|
||||||
|
@question.question_answers.visibles.where(question_id: @question).each do |question_answer|
|
||||||
|
question_answer.set_most_voted
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@answers_by_question_id = { @question.id => params[:answer] }
|
def store_answer
|
||||||
|
if @question.votation_type.nil?
|
||||||
|
answer = @question.answers.find_or_initialize_by(author: current_user)
|
||||||
|
else
|
||||||
|
answer = @question.votation_type.answer(current_user,
|
||||||
|
params[:answer],
|
||||||
|
positive: params[:positive])
|
||||||
|
end
|
||||||
|
answer
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_and_store_new_pair(question)
|
||||||
|
Poll::PairAnswer.generate_pair(question, current_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def question_answers
|
||||||
|
if @question.is_positive_negative?
|
||||||
|
@answers = @question.question_answers.visibles.page(@page)
|
||||||
|
else
|
||||||
|
@answers = @question.question_answers.visibles
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -20,13 +20,27 @@ class PollsController < ApplicationController
|
|||||||
def show
|
def show
|
||||||
@questions = @poll.questions.for_render.sort_for_list
|
@questions = @poll.questions.for_render.sort_for_list
|
||||||
@token = poll_voter_token(@poll, current_user)
|
@token = poll_voter_token(@poll, current_user)
|
||||||
@poll_questions_answers = Poll::Question::Answer.where(question: @poll.questions)
|
@poll_questions_answers = Poll::Question::Answer.visibles
|
||||||
|
.where(question: @poll.questions)
|
||||||
.where.not(description: "").order(:given_order)
|
.where.not(description: "").order(:given_order)
|
||||||
|
|
||||||
@answers_by_question_id = {}
|
@answers_by_question_id = {}
|
||||||
poll_answers = ::Poll::Answer.by_question(@poll.question_ids).by_author(current_user.try(:id))
|
poll_answers = ::Poll::Answer.by_question(@poll.question_ids).by_author(current_user.try(:id))
|
||||||
poll_answers.each do |answer|
|
|
||||||
@answers_by_question_id[answer.question_id] = answer.answer
|
@last_pair_question_answers = {}
|
||||||
|
@questions.each do |question|
|
||||||
|
@answers_by_question_id[question.id] = question.answers.by_author(current_user).pluck(:answer)
|
||||||
|
|
||||||
|
if question.enum_type&.include?("answer_couples")
|
||||||
|
last_pair = question.pair_answers.by_author(current_user).first
|
||||||
|
last_pair ||= generate_and_store_new_pair(question)
|
||||||
|
@last_pair_question_answers[question.id] = last_pair
|
||||||
|
end
|
||||||
|
|
||||||
|
if question.enum_type&.include?("answer_set_closed") ||
|
||||||
|
question.enum_type&.include?("answer_set_open")
|
||||||
|
votation_answer_sets(question)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@commentable = @poll
|
@commentable = @poll
|
||||||
@@ -42,6 +56,18 @@ class PollsController < ApplicationController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def votation_answer_sets(question)
|
||||||
|
if question.votation_type.votation_set_answers.by_author(current_user).empty?
|
||||||
|
question.question_answers&.sample(question.max_groups_answers).each do |question_answer|
|
||||||
|
answer = VotationSetAnswer.new(answer: question_answer.title,
|
||||||
|
votation_type: question.votation_type,
|
||||||
|
author: current_user)
|
||||||
|
question.votation_type.votation_set_answers << answer
|
||||||
|
end
|
||||||
|
!question.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def load_poll
|
def load_poll
|
||||||
@poll = Poll.where(slug: params[:id]).first || Poll.where(id: params[:id]).first
|
@poll = Poll.where(slug: params[:id]).first || Poll.where(id: params[:id]).first
|
||||||
end
|
end
|
||||||
@@ -50,4 +76,8 @@ class PollsController < ApplicationController
|
|||||||
@active_poll = ActivePoll.first
|
@active_poll = ActivePoll.first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def generate_and_store_new_pair(question)
|
||||||
|
Poll::PairAnswer.generate_pair(question, current_user)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -78,4 +78,8 @@ module PollsHelper
|
|||||||
def show_polls_description?
|
def show_polls_description?
|
||||||
@active_poll.present? && @current_filter == "current"
|
@active_poll.present? && @current_filter == "current"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def stored_positive_negative_value(question, answer)
|
||||||
|
question.answers.find_by(author_id: current_user.id, answer: answer.title).positive
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ module Abilities
|
|||||||
can [:search, :create, :index, :destroy], ::Poll::Officer
|
can [:search, :create, :index, :destroy], ::Poll::Officer
|
||||||
can [:create, :destroy, :manage], ::Poll::BoothAssignment
|
can [:create, :destroy, :manage], ::Poll::BoothAssignment
|
||||||
can [:create, :destroy], ::Poll::OfficerAssignment
|
can [:create, :destroy], ::Poll::OfficerAssignment
|
||||||
can [:read, :create, :update], Poll::Question
|
can [:read, :create, :update, :get_options_traductions], Poll::Question
|
||||||
can :destroy, Poll::Question # , comments_count: 0, votes_up: 0
|
can :destroy, Poll::Question
|
||||||
|
|
||||||
can :manage, SiteCustomization::Page
|
can :manage, SiteCustomization::Page
|
||||||
can :manage, SiteCustomization::Image
|
can :manage, SiteCustomization::Image
|
||||||
|
|||||||
@@ -104,12 +104,18 @@ module Abilities
|
|||||||
|
|
||||||
can :create, DirectMessage
|
can :create, DirectMessage
|
||||||
can :show, DirectMessage, sender_id: user.id
|
can :show, DirectMessage, sender_id: user.id
|
||||||
can :answer, Poll do |poll|
|
|
||||||
|
can [:load_answers], Poll::Question
|
||||||
|
can [:answer], Poll do |poll|
|
||||||
poll.answerable_by?(user)
|
poll.answerable_by?(user)
|
||||||
end
|
end
|
||||||
can :answer, Poll::Question do |question|
|
can [:answer, :prioritized_answers], Poll::Question do |question|
|
||||||
question.answerable_by?(user)
|
question.answerable_by?(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
can [:create, :delete], Poll::Answer do |answer|
|
||||||
|
answer.question.answerable_by?(user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
can [:create, :show], ProposalNotification, proposal: { author_id: user.id }
|
can [:create, :show], ProposalNotification, proposal: { author_id: user.id }
|
||||||
|
|||||||
34
app/models/poll/pair_answer.rb
Normal file
34
app/models/poll/pair_answer.rb
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
class Poll::PairAnswer < ApplicationRecord
|
||||||
|
|
||||||
|
belongs_to :question, -> { with_hidden }
|
||||||
|
belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
|
||||||
|
belongs_to :answer_right, class_name: "Poll::Question::Answer", foreign_key: "answer_rigth_id"
|
||||||
|
belongs_to :answer_left, class_name: "Poll::Question::Answer", foreign_key: "answer_left_id"
|
||||||
|
|
||||||
|
delegate :poll, :poll_id, to: :question
|
||||||
|
|
||||||
|
validates :question, presence: true
|
||||||
|
validates :author, presence: true
|
||||||
|
validates :answer_left, presence: true
|
||||||
|
validates :answer_right, presence: true
|
||||||
|
|
||||||
|
validates :answer_left, inclusion: { in: ->(a) { a.question.question_answers.visibles }},
|
||||||
|
unless: ->(a) { a.question.blank? }
|
||||||
|
|
||||||
|
validates :answer_right, inclusion: { in: ->(a) { a.question.question_answers.visibles }},
|
||||||
|
unless: ->(a) { a.question.blank? }
|
||||||
|
|
||||||
|
|
||||||
|
scope :by_author, ->(author_id) { where(author_id: author_id) }
|
||||||
|
scope :by_question, ->(question_id) { where(question_id: question_id) }
|
||||||
|
|
||||||
|
def self.generate_pair(question, user)
|
||||||
|
answers = question.question_answers.visibles.sample(2)
|
||||||
|
question.pair_answers.by_author(user).map(&:destroy)
|
||||||
|
question.pair_answers.create(author: user, answer_left: answers[0], answer_right: answers[1])
|
||||||
|
end
|
||||||
|
|
||||||
|
def answers
|
||||||
|
[answer_left, answer_right].compact
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -11,6 +11,7 @@ class Poll::PartialResult < ApplicationRecord
|
|||||||
validates :author, presence: true
|
validates :author, presence: true
|
||||||
validates :answer, presence: true
|
validates :answer, presence: true
|
||||||
validates :answer, inclusion: { in: ->(a) { a.question.question_answers
|
validates :answer, inclusion: { in: ->(a) { a.question.question_answers
|
||||||
|
.visibles
|
||||||
.joins(:translations)
|
.joins(:translations)
|
||||||
.pluck("poll_question_answer_translations.title") }},
|
.pluck("poll_question_answer_translations.title") }},
|
||||||
unless: ->(a) { a.question.blank? }
|
unless: ->(a) { a.question.blank? }
|
||||||
|
|||||||
@@ -15,14 +15,22 @@ class Poll::Question < ApplicationRecord
|
|||||||
has_many :answers, class_name: "Poll::Answer"
|
has_many :answers, class_name: "Poll::Answer"
|
||||||
has_many :question_answers, -> { order "given_order asc" }, class_name: "Poll::Question::Answer", dependent: :destroy
|
has_many :question_answers, -> { order "given_order asc" }, class_name: "Poll::Question::Answer", dependent: :destroy
|
||||||
has_many :partial_results
|
has_many :partial_results
|
||||||
|
has_many :pair_answers, class_name: "Poll::PairAnswer"
|
||||||
|
has_one :votation_type, as: :questionable
|
||||||
belongs_to :proposal
|
belongs_to :proposal
|
||||||
|
|
||||||
|
attr_accessor :enum_type, :max_votes, :prioritization_type
|
||||||
|
|
||||||
validates_translation :title, presence: true, length: { minimum: 4 }
|
validates_translation :title, presence: true, length: { minimum: 4 }
|
||||||
validates :author, presence: true
|
validates :author, presence: true
|
||||||
validates :poll_id, presence: true, if: Proc.new { |question| question.poll.nil? }
|
validates :poll_id, presence: true, if: Proc.new { |question| question.poll.nil? }
|
||||||
|
|
||||||
|
validates_associated :votation_type
|
||||||
accepts_nested_attributes_for :question_answers, reject_if: :all_blank, allow_destroy: true
|
accepts_nested_attributes_for :question_answers, reject_if: :all_blank, allow_destroy: true
|
||||||
|
|
||||||
|
delegate :enum_type, :max_votes, :prioritization_type, :max_groups_answers,
|
||||||
|
to: :votation_type, allow_nil: true
|
||||||
|
|
||||||
scope :by_poll_id, ->(poll_id) { where(poll_id: poll_id) }
|
scope :by_poll_id, ->(poll_id) { where(poll_id: poll_id) }
|
||||||
|
|
||||||
scope :sort_for_list, -> { order("poll_questions.proposal_id IS NULL", :created_at)}
|
scope :sort_for_list, -> { order("poll_questions.proposal_id IS NULL", :created_at)}
|
||||||
@@ -59,10 +67,24 @@ class Poll::Question < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def answers_total_votes
|
def answers_total_votes
|
||||||
question_answers.inject(0) { |total, question_answer| total + question_answer.total_votes }
|
question_answers.visibles.inject(0) { |total, question_answer| total + question_answer.total_votes }
|
||||||
end
|
end
|
||||||
|
|
||||||
def most_voted_answer_id
|
def most_voted_answer_id
|
||||||
question_answers.max_by { |answer| answer.total_votes }.id
|
question_answers.max_by { |answer| answer.total_votes }.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def answers_with_read_more?
|
||||||
|
question_answers.visibles.any? do |answer| answer.description.present? || answer.images.any? ||
|
||||||
|
answer.documents.present? || answer.videos.present?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_can_vote(user)
|
||||||
|
max_votes.nil? || max_votes > answers.where(author: user).count
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_positive_negative?
|
||||||
|
votation_type.present? && enum_type == "positive_negative_open"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
class Poll::Question::Answer < ApplicationRecord
|
class Poll::Question::Answer < ApplicationRecord
|
||||||
include Galleryable
|
include Galleryable
|
||||||
include Documentable
|
include Documentable
|
||||||
|
paginates_per 10
|
||||||
|
|
||||||
translates :title, touch: true
|
translates :title, touch: true
|
||||||
translates :description, touch: true
|
translates :description, touch: true
|
||||||
@@ -14,6 +15,10 @@ class Poll::Question::Answer < ApplicationRecord
|
|||||||
validates_translation :title, presence: true
|
validates_translation :title, presence: true
|
||||||
validates :given_order, presence: true, uniqueness: { scope: :question_id }
|
validates :given_order, presence: true, uniqueness: { scope: :question_id }
|
||||||
|
|
||||||
|
scope :by_author, -> (author) { where(author: author) }
|
||||||
|
|
||||||
|
scope :visibles, -> { where(hidden: false) }
|
||||||
|
|
||||||
def description
|
def description
|
||||||
self[:description].try :html_safe
|
self[:description].try :html_safe
|
||||||
end
|
end
|
||||||
@@ -29,11 +34,72 @@ class Poll::Question::Answer < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def total_votes
|
def total_votes
|
||||||
|
if !question.votation_type.present?
|
||||||
Poll::Answer.where(question_id: question, answer: title).count +
|
Poll::Answer.where(question_id: question, answer: title).count +
|
||||||
::Poll::PartialResult.where(question: question).where(answer: title).sum(:amount)
|
::Poll::PartialResult.where(question: question).where(answer: title).sum(:amount)
|
||||||
|
else
|
||||||
|
case question.votation_type.enum_type
|
||||||
|
when "positive_negative_open"
|
||||||
|
total_votes_positive_negative
|
||||||
|
when "prioritized"
|
||||||
|
total_votes_prioritized
|
||||||
|
when "unique"
|
||||||
|
Poll::Answer.where(question_id: question, answer: title).count +
|
||||||
|
::Poll::PartialResult.where(question: question).where(answer: title).sum(:amount)
|
||||||
|
else
|
||||||
|
Poll::Answer.where(question_id: question, answer: title).count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def total_votes_positive_negative
|
||||||
|
count_positive_negative(self, true) - count_positive_negative(self, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def total_votes_prioritized
|
||||||
|
Poll::Answer.where(question_id: question, answer: title).sum(:value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def most_voted?
|
||||||
|
most_voted
|
||||||
end
|
end
|
||||||
|
|
||||||
def total_votes_percentage
|
def total_votes_percentage
|
||||||
question.answers_total_votes.zero? ? 0 : (total_votes * 100.0) / question.answers_total_votes
|
question.answers_total_votes.zero? ? 0 : (total_votes * 100.0) / question.answers_total_votes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_most_voted
|
||||||
|
if question.enum_type.nil?
|
||||||
|
for_only_votes
|
||||||
|
else
|
||||||
|
case question.enum_type
|
||||||
|
when "positive_negative_open"
|
||||||
|
answers = question.question_answers.visibles
|
||||||
|
.map { |a| count_positive_negative(a, true) - count_positive_negative(a, false) }
|
||||||
|
is_most_voted = answers.none? {|a| a > total_votes_positive_negative}
|
||||||
|
update(most_voted: is_most_voted)
|
||||||
|
when "prioritized"
|
||||||
|
answers = question.question_answers.visibles
|
||||||
|
.map { |a| Poll::Answer.where(question_id: a.question, answer: a.title).sum(:value) }
|
||||||
|
is_most_voted = answers.none? {|a| a > total_votes_prioritized}
|
||||||
|
update(most_voted: is_most_voted)
|
||||||
|
else
|
||||||
|
for_only_votes
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def count_positive_negative(answer, value)
|
||||||
|
Poll::Answer.where(question_id: answer.question, answer: answer.title, positive: value).count
|
||||||
|
end
|
||||||
|
|
||||||
|
def for_only_votes
|
||||||
|
answers = question.question_answers.visibles
|
||||||
|
.map {|a| Poll::Answer.where(question_id: a.question, answer: a.title).count}
|
||||||
|
is_most_voted = answers.none? {|a| a > total_votes}
|
||||||
|
update(most_voted: is_most_voted)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class User < ApplicationRecord
|
|||||||
has_many :follows
|
has_many :follows
|
||||||
has_many :budget_rol_assignments
|
has_many :budget_rol_assignments
|
||||||
has_many :budgets, through: :budget_rol_assignments
|
has_many :budgets, through: :budget_rol_assignments
|
||||||
|
has_many :votation_set_answers
|
||||||
belongs_to :geozone
|
belongs_to :geozone
|
||||||
|
|
||||||
validates :username, presence: true, if: :username_required?
|
validates :username, presence: true, if: :username_required?
|
||||||
|
|||||||
6
app/models/votation_set_answer.rb
Normal file
6
app/models/votation_set_answer.rb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
class VotationSetAnswer < ApplicationRecord
|
||||||
|
belongs_to :votation_type
|
||||||
|
belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
|
||||||
|
|
||||||
|
scope :by_author, -> (author) { where(author: author) }
|
||||||
|
end
|
||||||
202
app/models/votation_type.rb
Normal file
202
app/models/votation_type.rb
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
class VotationType < ApplicationRecord
|
||||||
|
belongs_to :questionable, polymorphic: true
|
||||||
|
has_many :votation_set_answers
|
||||||
|
|
||||||
|
QUESTIONABLE_TYPES = %w[Poll::Question].freeze
|
||||||
|
|
||||||
|
ENUM_TYPES_PROPS = {
|
||||||
|
unique: { enum_type: 0, open_answer: false, prioritized: false },
|
||||||
|
multiple: { enum_type: 1, open_answer: false, prioritized: false,
|
||||||
|
variables: [:max_votes] },
|
||||||
|
prioritized: { enum_type: 2, open_answer: false, prioritized: true,
|
||||||
|
variables: [:max_votes, :prioritization_type] },
|
||||||
|
positive_open: { enum_type: 3, open_answer: true, prioritized: false,
|
||||||
|
variables: [:max_votes] },
|
||||||
|
positive_negative_open: { enum_type: 4, open_answer: true, prioritized: false,
|
||||||
|
variables: [:max_votes] },
|
||||||
|
answer_couples_open: { enum_type: 5, open_answer: true, prioritized: false,
|
||||||
|
variables: [:max_votes, :display_skip_question] },
|
||||||
|
answer_couples_closed: { enum_type: 6, open_answer: false, prioritized: false,
|
||||||
|
variables: [:max_votes, :display_skip_question] },
|
||||||
|
answer_set_open: { enum_type: 7, open_answer: true, prioritized: false,
|
||||||
|
variables: [:max_votes, :max_groups_answers] },
|
||||||
|
answer_set_closed: { enum_type: 8, open_answer: false, prioritized: false,
|
||||||
|
variables: [:max_votes, :max_groups_answers] },
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
enum enum_type: ENUM_TYPES_PROPS.map{ |k,v| [k, v[:enum_type]] }.to_h.freeze
|
||||||
|
|
||||||
|
enum prioritization_type: {borda: 1, dowdall: 2}.freeze
|
||||||
|
|
||||||
|
validates :questionable, presence: true
|
||||||
|
validates :questionable_type, inclusion: {in: QUESTIONABLE_TYPES}
|
||||||
|
validates_presence_of :max_votes, allow_blank: false,
|
||||||
|
if: :max_votes_required?
|
||||||
|
validates_presence_of :max_groups_answers, allow_blank: false,
|
||||||
|
if: :max_groups_answers_required?
|
||||||
|
validates_presence_of :prioritization_type, allow_blank: false,
|
||||||
|
if: :prioritization_type_required?
|
||||||
|
|
||||||
|
after_create :add_skip_question_answer, if: :display_skip_question?
|
||||||
|
|
||||||
|
attr_accessor :display_skip_question
|
||||||
|
|
||||||
|
def open?
|
||||||
|
open_answer
|
||||||
|
end
|
||||||
|
|
||||||
|
def prioritized?
|
||||||
|
prioritized
|
||||||
|
end
|
||||||
|
|
||||||
|
def answer (user, answer, options = {})
|
||||||
|
result = nil
|
||||||
|
votes = questionable.answers
|
||||||
|
|
||||||
|
if votable_question?(answer)
|
||||||
|
case enum_type
|
||||||
|
when "unique"
|
||||||
|
result = votes.find_or_initialize_by(author: user)
|
||||||
|
|
||||||
|
when "multiple", "positive_open"
|
||||||
|
if check_max_votes(user, votes)
|
||||||
|
result = votes.find_or_initialize_by(author: user, answer: answer)
|
||||||
|
end
|
||||||
|
|
||||||
|
when "prioritized"
|
||||||
|
result = votes.find_by(author: user, answer: answer)
|
||||||
|
if result.nil?
|
||||||
|
if check_max_votes(user, votes)
|
||||||
|
if votes.by_author(user.id).empty?
|
||||||
|
order = 1
|
||||||
|
else
|
||||||
|
order = votes.by_author(user.id).order(:order).last.order + 1
|
||||||
|
end
|
||||||
|
result = votes.find_or_initialize_by(author: user,
|
||||||
|
answer: answer,
|
||||||
|
order: order)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
!result.update(order: options[:order])
|
||||||
|
end
|
||||||
|
|
||||||
|
when "positive_negative_open"
|
||||||
|
result = votes.by_author(user.id).find_by(answer: answer)
|
||||||
|
if result.nil?
|
||||||
|
if check_max_votes(user, votes)
|
||||||
|
result = votes.create(author: user,
|
||||||
|
answer: answer,
|
||||||
|
positive: options[:positive])
|
||||||
|
end
|
||||||
|
else
|
||||||
|
!result.update(positive: options[:positive])
|
||||||
|
end
|
||||||
|
|
||||||
|
when "answer_couples_closed", "answer_couples_open"
|
||||||
|
if check_max_votes(user, votes)
|
||||||
|
result = votes.create(
|
||||||
|
answer: answer,
|
||||||
|
author: user,
|
||||||
|
positive: true,
|
||||||
|
order: votes&.by_author(user.id).count + 1
|
||||||
|
)
|
||||||
|
end
|
||||||
|
Poll::PairAnswer.generate_pair(questionable, user)
|
||||||
|
|
||||||
|
when "answer_set_open", "answer_set_closed"
|
||||||
|
if check_max_votes(user, votes) && answer_in_set?(answer, user)
|
||||||
|
result = votes&.find_or_initialize_by(author: user, answer: answer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_question_answer(answer, hidden=false)
|
||||||
|
return if questionable.question_answers.where(title: answer).any?
|
||||||
|
|
||||||
|
questionable.question_answers
|
||||||
|
.create(
|
||||||
|
title: answer,
|
||||||
|
given_order: questionable.question_answers.maximum(:given_order).to_i + 1,
|
||||||
|
hidden: hidden
|
||||||
|
)
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def votable_question?(answer)
|
||||||
|
questionable.question_answers.where(title: answer).present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.build_by_type(questionable, params)
|
||||||
|
attributes = {questionable: questionable}
|
||||||
|
enum_type = self.enum_types.key(params[:enum_type].to_i)
|
||||||
|
enum_type_props = enum_properties(enum_type)
|
||||||
|
attributes.merge!(enum_type_props.except(:variables))
|
||||||
|
enum_type_props[:variables]&.each do |property|
|
||||||
|
attributes[property] = params[property]
|
||||||
|
end
|
||||||
|
attributes[:prioritization_type] = attributes[:prioritization_type]&.to_i
|
||||||
|
new(attributes)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create_by_type(questionable, params)
|
||||||
|
votation_type = build_by_type(questionable, params)
|
||||||
|
votation_type.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_priorized_values(user)
|
||||||
|
case prioritization_type
|
||||||
|
when "borda"
|
||||||
|
questionable.answers.by_author(user).order(:order).each_with_index do |answer, i|
|
||||||
|
value = max_votes - i
|
||||||
|
!answer.update(value: value)
|
||||||
|
end
|
||||||
|
when "dowdall"
|
||||||
|
questionable.answers.by_author(user).order(:order).each_with_index do |answer, i|
|
||||||
|
value = 60/(i + 1)
|
||||||
|
!answer.update(value: value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def answer_in_set?(answer, user)
|
||||||
|
votation_set_answers&.by_author(user)&.pluck(:answer).include?(answer)
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_max_votes(user, votes)
|
||||||
|
max_votes > votes&.by_author(user.id).count
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.enum_properties(enum_type)
|
||||||
|
ENUM_TYPES_PROPS[enum_type&.to_sym] || ENUM_TYPES_PROPS[:unique]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.enum_properties_variables(enum_type)
|
||||||
|
enum_properties(enum_type)&.dig(:variables)
|
||||||
|
end
|
||||||
|
|
||||||
|
def max_votes_required?
|
||||||
|
VotationType.enum_properties_variables(self.enum_type)&.include?(:max_votes)
|
||||||
|
end
|
||||||
|
|
||||||
|
def max_groups_answers_required?
|
||||||
|
VotationType.enum_properties_variables(self.enum_type)&.include?(:max_groups_answers)
|
||||||
|
end
|
||||||
|
|
||||||
|
def prioritization_type_required?
|
||||||
|
VotationType.enum_properties_variables(self.enum_type)&.include?(:prioritization_type)
|
||||||
|
end
|
||||||
|
|
||||||
|
def display_skip_question?
|
||||||
|
VotationType.enum_properties_variables(self.enum_type)&.include?(:display_skip_question)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_skip_question_answer
|
||||||
|
create_question_answer("I can't decided", true)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -25,6 +25,38 @@
|
|||||||
<%= translations_form.text_field :title %>
|
<%= translations_form.text_field :title %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% if !@question.persisted? %>
|
||||||
|
<%= fields_for :votation_type do |votation_f| %>
|
||||||
|
<div class="small-12 medium-6">
|
||||||
|
<%= votation_f.select :enum_type,
|
||||||
|
options_for_select(VotationType.enum_types.map {|k, v| [t(k, scope: :enum_type), v]},
|
||||||
|
params.dig(:votation_type, :enum_type)), default: 0,
|
||||||
|
disabled: @question.persisted?, label: t("enum_type.title") %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-type">
|
||||||
|
<span class="js-description_text">
|
||||||
|
<%= t("polls.index.descriptions.unique") %>
|
||||||
|
</span>
|
||||||
|
<div class="small-12 medium-6 margin-description js-max_votes hidden ">
|
||||||
|
<%= votation_f.number_field :max_votes, min: 1, max: 999,
|
||||||
|
value: params.dig(:votation_type, :max_votes),
|
||||||
|
label: t("question.max_votes") %>
|
||||||
|
</div>
|
||||||
|
<div class="small-12 medium-6 js-prioritization_type hidden">
|
||||||
|
<%= votation_f.select :prioritization_type,
|
||||||
|
options_for_select(VotationType.prioritization_types.map {|k, v| [t(k, scope: :prioritization_type), v]},
|
||||||
|
params.dig(:votation_type, :prioritization_type) ), default: 0,
|
||||||
|
disabled: @question.persisted?, label: t("prioritization_type.title") %>
|
||||||
|
</div>
|
||||||
|
<div class="small-12 medium-6 js-max_group_votes hidden">
|
||||||
|
<%= votation_f.number_field :max_groups_answers, min: 1, max: 999,
|
||||||
|
value: params.dig(:votation_type, :max_groups_answers), label: t("question.max_group_answers") %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<div class="small-12 medium-4 large-2 margin-top">
|
<div class="small-12 medium-4 large-2 margin-top">
|
||||||
<%= f.submit(class: "button success expanded", value: t("shared.save")) %>
|
<%= f.submit(class: "button success expanded", value: t("shared.save")) %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -26,6 +26,35 @@
|
|||||||
<%= link_to @question.proposal.title, proposal_path(@question.proposal) %>
|
<%= link_to @question.proposal.title, proposal_path(@question.proposal) %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% unless @question.votation_type.nil? %>
|
||||||
|
<p>
|
||||||
|
<strong><%= t("question.votation_type") %></strong>
|
||||||
|
<br>
|
||||||
|
<%= t("enum_type.#{@question.votation_type.enum_type}") %>
|
||||||
|
</p>
|
||||||
|
<% if !@question.votation_type.max_votes.nil? %>
|
||||||
|
<p>
|
||||||
|
<strong><%= t("question.max_votes") %></strong>
|
||||||
|
<br>
|
||||||
|
<%= @question.votation_type.max_votes %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
<% if !@question.votation_type.prioritization_type.nil? %>
|
||||||
|
<p>
|
||||||
|
<strong><%= t("prioritization_type.title") %></strong>
|
||||||
|
<br>
|
||||||
|
<%= t("prioritization_type.#{@question.votation_type.prioritization_type}") %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
<% if !@question.votation_type.max_groups_answers.nil? %>
|
||||||
|
<p>
|
||||||
|
<strong><%= t("question.max_group_answers") %></strong>
|
||||||
|
<br>
|
||||||
|
<%= @question.votation_type.max_groups_answers %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<div class="polls-results-stats">
|
||||||
|
|
||||||
|
<div class="row margin">
|
||||||
|
<div class="small-12 medium-3 column">
|
||||||
|
<p><strong><%= t("polls.show.results.title") %></strong></p>
|
||||||
|
<ul class="menu vertical">
|
||||||
|
<%- @poll.questions.each do |question| %>
|
||||||
|
<li><%= link_to question.title, "##{question.title.parameterize}" %></li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="small-12 medium-9 column">
|
||||||
|
<%- @poll.questions.each do |question| %>
|
||||||
|
<h3 id="<%= question.title.parameterize %>"><%= question.title %></h3>
|
||||||
|
<table id="question_<%= question.id %>_results_table">
|
||||||
|
<tbody>
|
||||||
|
<%- question.question_answers.visibles.each do |answer| %>
|
||||||
|
<tr scope="col" <%= answer.most_voted? ? "class=win" : "" %>>
|
||||||
|
<td>
|
||||||
|
<% if answer.most_voted %>
|
||||||
|
<span class="show-for-sr"><%= t("polls.show.results.most_voted_answer") %></span>
|
||||||
|
<% end %>
|
||||||
|
<%= answer.title %>
|
||||||
|
</td>
|
||||||
|
<td id="answer_<%= answer.id %>_result" <%= answer.most_voted? ? "class=win" : "" %>>
|
||||||
|
<%= answer.total_votes %>
|
||||||
|
<% unless question.enum_type == "positive_negative_open" %>
|
||||||
|
(<%= answer.total_votes_percentage.round(2) %>%)
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -11,11 +11,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% if @poll.questions.any? { |question| question.votation_type.present? } %>
|
||||||
|
<%= render "votation_types_results" %>
|
||||||
|
<% else %>
|
||||||
<% if @partial_results.present? %>
|
<% if @partial_results.present? %>
|
||||||
<%= render "recount", resource: @poll %>
|
<%= render "recount", resource: @poll %>
|
||||||
<%= render "result" %>
|
<%= render "result" %>
|
||||||
<%= render "results_by_booth" %>
|
<%= render "results_by_booth" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<% if @poll.voters.any? %>
|
<% if @poll.voters.any? %>
|
||||||
<%= render "show_results", resource: @poll %>
|
<%= render "show_results", resource: @poll %>
|
||||||
|
|||||||
@@ -1,33 +1,22 @@
|
|||||||
<div class="poll-question-answers">
|
<% if question.votation_type.nil? %>
|
||||||
<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
|
<%= render "polls/questions/answers_unique", question: question, answers: answers, token: token %>
|
||||||
<% question.question_answers.each do |answer| %>
|
<% else %>
|
||||||
<% if @answers_by_question_id[question.id] == answer.title &&
|
<% case question.votation_type.enum_type %>
|
||||||
(!voted_before_sign_in(question) ||
|
<% when "unique" %>
|
||||||
question.poll.voted_in_booth?(current_user)) %>
|
<%= render "polls/questions/answers_unique", question: question, answers: answers, token: token %>
|
||||||
<span class="button answered"
|
<% when "multiple", "positive_open" %>
|
||||||
title="<%= t("poll_questions.show.voted", answer: answer.title)%>">
|
<%= render "polls/questions/answers_multiple", question: question, answers: answers, token: token %>
|
||||||
<%= answer.title %>
|
<% when "positive_negative_open" %>
|
||||||
</span>
|
<%= render "polls/questions/answers_positive_negative", question: question, answers: answers, token: token, page: page %>
|
||||||
|
<% when "answer_couples_closed" %>
|
||||||
|
<%= render "polls/questions/answers_couples", answers_open: false, question: question, token: token %>
|
||||||
|
<% when "answer_couples_open" %>
|
||||||
|
<%= render "polls/questions/answers_couples", answers_open: true, question: question, token: token %>
|
||||||
|
<% when "answer_set_closed", "answer_set_open" %>
|
||||||
|
<%= render "polls/questions/answers_set", question: question, token: token, answers: question.votation_type.votation_set_answers.by_author(current_user) %>
|
||||||
|
<% when "prioritized" %>
|
||||||
|
<%= render "polls/questions/answers_prioritized", answers_open: false, question: question, answers: answers, token: token %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= link_to answer.title,
|
<%= render "polls/questions/answers_unique", question: question, answers: answers, token: token %>
|
||||||
answer_question_path(question, answer: answer.title, token: token),
|
|
||||||
method: :post,
|
|
||||||
remote: true,
|
|
||||||
title: t("poll_questions.show.vote_answer", answer: answer.title),
|
|
||||||
class: "button secondary hollow js-question-answer" %>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% elsif !user_signed_in? %>
|
|
||||||
<% question.question_answers.order(id: :desc).each do |answer| %>
|
|
||||||
<%= link_to answer.title, new_user_session_path, class: "button secondary hollow" %>
|
|
||||||
<% end %>
|
|
||||||
<% elsif !current_user.level_two_or_three_verified? %>
|
|
||||||
<% question.question_answers.order(id: :desc).each do |answer| %>
|
|
||||||
<%= link_to answer.title, verification_path, class: "button secondary hollow" %>
|
|
||||||
<% end %>
|
|
||||||
<% else %>
|
|
||||||
<% question.question_answers.order(id: :desc).each do |answer| %>
|
|
||||||
<span class="button secondary hollow disabled"><%= answer.title %></span>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
|
|||||||
39
app/views/polls/questions/_answers_couples.html.erb
Normal file
39
app/views/polls/questions/_answers_couples.html.erb
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<div class="poll-question-answers">
|
||||||
|
<% if can?(:answer, question) && question.user_can_vote(current_user) %>
|
||||||
|
<div class="small-12 medium-12 text-center">
|
||||||
|
<% @last_pair_question_answers.dig(question.id)&.answers&.each do |answer| %>
|
||||||
|
<div class="small-12 medium-5 inline-block">
|
||||||
|
<%= link_to answer.title,
|
||||||
|
answer_question_path(question, answer: answer.title, token: token),
|
||||||
|
method: :post,
|
||||||
|
remote: true,
|
||||||
|
title: t("poll_questions.show.vote_answer", answer: answer.title),
|
||||||
|
class: "button secondary hollow js-question-answer" %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div class="small-12 medium-12 text-center">
|
||||||
|
<%= link_to "I can't decide",
|
||||||
|
answer_question_path(question, answer: "I can't decided", token: token),
|
||||||
|
method: :post,
|
||||||
|
remote: true,
|
||||||
|
title: "I can't decide",
|
||||||
|
class: "button secondary hollow js-question-answer" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% if answers_open %>
|
||||||
|
<%= render "/polls/questions/new_answer", question: question, token: token %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% elsif !user_signed_in? %>
|
||||||
|
<% question.question_answers.visibles.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.title, new_user_session_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% elsif !current_user.level_two_or_three_verified? %>
|
||||||
|
<% question.question_answers.visibles.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.title, verification_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= t('polls.index.max_votes_reached') %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
36
app/views/polls/questions/_answers_multiple.html.erb
Normal file
36
app/views/polls/questions/_answers_multiple.html.erb
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<div class="poll-question-answers">
|
||||||
|
<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
|
||||||
|
<% answers&.each do |answer| %>
|
||||||
|
<% if @answers_by_question_id[question.id].include?(answer.title) %>
|
||||||
|
<%= link_to answer.title,
|
||||||
|
answer_question_path(question, answer: answer.title, token: token),
|
||||||
|
method: :delete,
|
||||||
|
remote: true,
|
||||||
|
title: t("poll_questions.show.voted", answer: answer.title),
|
||||||
|
class: "button answered expand" %>
|
||||||
|
<% else %>
|
||||||
|
<%= link_to answer.title,
|
||||||
|
answer_question_path(question, answer: answer.title, token: token),
|
||||||
|
method: :post,
|
||||||
|
remote: true,
|
||||||
|
title: t("poll_questions.show.vote_answer", answer: answer.title),
|
||||||
|
class: "button secondary hollow js-question-answer" %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% if question.enum_type == "positive_open" %>
|
||||||
|
<%= render "/polls/questions/new_answer", question: question, token: token %>
|
||||||
|
<% end %>
|
||||||
|
<% elsif !user_signed_in? %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.title, new_user_session_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% elsif !current_user.level_two_or_three_verified? %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.title, verification_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<span class="button secondary hollow disabled"><%= answer.title %></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<div class="poll-question-answers">
|
||||||
|
<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
|
||||||
|
<table class="voting-list">
|
||||||
|
<% answers&.each do |answer| %>
|
||||||
|
<tr class="answer medium-12 inline-block" style="border-bottom: 1px solid lightslategrey;">
|
||||||
|
<td class="title-answer medium-9 inline-block">
|
||||||
|
<span class="inline-block"><%= answer.title %></span>
|
||||||
|
</td>
|
||||||
|
<td class="votes inline-block vote-align">
|
||||||
|
<div class="in-favor inline-block">
|
||||||
|
<% if @answers_by_question_id[question.id].include?(answer.title) &&
|
||||||
|
stored_positive_negative_value(question, answer) %>
|
||||||
|
<%= render "polls/questions/like_dislike", question: question,
|
||||||
|
answer: answer, method: "delete", positive: true,
|
||||||
|
token: token, active: true, page: page %>
|
||||||
|
<% else %>
|
||||||
|
<%= render "polls/questions/like_dislike", question: question,
|
||||||
|
answer: answer, method: "post", positive: true,
|
||||||
|
token: token, active: false, page: page %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div class="against inline-block">
|
||||||
|
<% if @answers_by_question_id[question.id].include?(answer.title) &&
|
||||||
|
!stored_positive_negative_value(question, answer) %>
|
||||||
|
<%= render "polls/questions/like_dislike", question: question,
|
||||||
|
answer: answer, method: "delete", positive: false,
|
||||||
|
token: token, active: true, page: page %>
|
||||||
|
<% else %>
|
||||||
|
<%= render "polls/questions/like_dislike", question: question,
|
||||||
|
answer: answer, method: "post", positive: false,
|
||||||
|
token: token, active: false, page: page %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
<%= paginate answers, params: {controller: "polls/questions", action: :load_answers, id: question}, remote: true %>
|
||||||
|
|
||||||
|
<%= render "/polls/questions/new_answer", question: question, token: token %>
|
||||||
|
|
||||||
|
<% elsif !user_signed_in? %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.title, new_user_session_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% elsif !current_user.level_two_or_three_verified? %>
|
||||||
|
<% answers.visibles.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.title, verification_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<span class="button secondary hollow disabled"><%= answer.title %></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
44
app/views/polls/questions/_answers_prioritized.html.erb
Normal file
44
app/views/polls/questions/_answers_prioritized.html.erb
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<div class="poll-question-answers">
|
||||||
|
<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
|
||||||
|
<ol type="1" class="sortable-priotirized-votation" data-js-url="<%= prioritized_answers_question_path(question, token: token) %>">
|
||||||
|
<% @answers_by_question_id[question.id].each do |answer| %>
|
||||||
|
<li data-answer-id="<%= answer %>">
|
||||||
|
<span class="button answered expanded"
|
||||||
|
title="<%= t("poll_questions.show.voted", answer: answer) %>">
|
||||||
|
<%= answer %>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<% answers&.each do |answer| %>
|
||||||
|
<% if @answers_by_question_id[question.id].include?(answer.title) %>
|
||||||
|
<%= link_to answer.title,
|
||||||
|
answer_question_path(question, answer: answer.title, token: token),
|
||||||
|
method: :delete,
|
||||||
|
remote: true,
|
||||||
|
title: t("poll_questions.show.voted", answer: answer.title),
|
||||||
|
class: "button answered expand" %>
|
||||||
|
<% else %>
|
||||||
|
<%= link_to answer.title,
|
||||||
|
answer_question_path(question, answer: answer.title, token: token),
|
||||||
|
method: :post,
|
||||||
|
remote: true,
|
||||||
|
title: t("poll_questions.show.vote_answer", answer: answer.title),
|
||||||
|
class: "button secondary hollow js-question-answer" %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% elsif !user_signed_in? %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.title, new_user_session_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% elsif !current_user.level_two_or_three_verified? %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.title, verification_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<span class="button secondary hollow disabled"><%= answer.title %></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
37
app/views/polls/questions/_answers_set.html.erb
Normal file
37
app/views/polls/questions/_answers_set.html.erb
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<div class="poll-question-answers">
|
||||||
|
<% if can?(:answer, question) %>
|
||||||
|
<% answers.each do |answer| %>
|
||||||
|
<% if @answers_by_question_id[question.id].include?(answer.answer) %>
|
||||||
|
<%= link_to answer.answer,
|
||||||
|
answer_question_path(question, answer: answer.answer, token: token),
|
||||||
|
method: :delete,
|
||||||
|
remote: true,
|
||||||
|
title: t("poll_questions.show.voted", answer: answer.answer),
|
||||||
|
class: "button answered" %>
|
||||||
|
<% else %>
|
||||||
|
<%= link_to answer.answer,
|
||||||
|
answer_question_path(question, answer: answer.answer, token: token),
|
||||||
|
method: :post,
|
||||||
|
remote: true,
|
||||||
|
title: t("poll_questions.show.vote_answer", answer: answer.answer),
|
||||||
|
class: "button secondary hollow js-question-answer" %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% if question.enum_type == "answer_set_open" %>
|
||||||
|
<%= render "/polls/questions/new_answer", question: question, token: token %>
|
||||||
|
<%= flash[:notice] %>
|
||||||
|
<% end %>
|
||||||
|
<% elsif !user_signed_in? %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.answer, new_user_session_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% elsif !current_user.level_two_or_three_verified? %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.answer, verification_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<span class="button secondary hollow disabled"><%= answer.answer %></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
33
app/views/polls/questions/_answers_unique.html.erb
Normal file
33
app/views/polls/questions/_answers_unique.html.erb
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<div class="poll-question-answers">
|
||||||
|
<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
|
||||||
|
<% answers&.each do |answer| %>
|
||||||
|
<% if @answers_by_question_id[question.id].include?(answer.title) &&
|
||||||
|
(!voted_before_sign_in(question) ||
|
||||||
|
question.poll.voted_in_booth?(current_user)) %>
|
||||||
|
<span class="button answered"
|
||||||
|
title="<%= t("poll_questions.show.voted", answer: answer.title) %>">
|
||||||
|
<%= answer.title %>
|
||||||
|
</span>
|
||||||
|
<% else %>
|
||||||
|
<%= link_to answer.title,
|
||||||
|
answer_question_path(question, answer: answer.title, token: token),
|
||||||
|
method: :post,
|
||||||
|
remote: true,
|
||||||
|
title: t("poll_questions.show.vote_answer", answer: answer.title),
|
||||||
|
class: "button secondary hollow js-question-answer" %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% elsif !user_signed_in? %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.title, new_user_session_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% elsif !current_user.level_two_or_three_verified? %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<%= link_to answer.title, verification_path, class: "button secondary hollow" %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<% answers.order(id: :desc).each do |answer| %>
|
||||||
|
<span class="button secondary hollow disabled"><%= answer.title %></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
19
app/views/polls/questions/_like_dislike.html.erb
Normal file
19
app/views/polls/questions/_like_dislike.html.erb
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<%= link_to answer_question_path(question, answer: answer.title, positive: positive, token: token, page: page),
|
||||||
|
method: method.to_sym,
|
||||||
|
remote: true,
|
||||||
|
title: t("poll_questions.show.vote_answer", answer: answer.title),
|
||||||
|
class: "expand js-question-answer" do %>
|
||||||
|
<% if positive %>
|
||||||
|
<% if active %>
|
||||||
|
<span class="icon-like active-like"></span>
|
||||||
|
<% else %>
|
||||||
|
<span class="icon-like"></span>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<% if active %>
|
||||||
|
<span class="icon-unlike active-unlike"></span>
|
||||||
|
<% else %>
|
||||||
|
<span class="icon-unlike"></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
5
app/views/polls/questions/_new_answer.html.erb
Normal file
5
app/views/polls/questions/_new_answer.html.erb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<%= form_tag(create_answer_question_path(question, token: token), method: :post, remote: true) do %>
|
||||||
|
<label> You can add your own answer</label>
|
||||||
|
<input type="text" class="medium-10" name="answer">
|
||||||
|
<input class="button success" type="submit" value="<%= t("poll_questions.show.add_answer") %>">
|
||||||
|
<% end %>
|
||||||
@@ -3,7 +3,35 @@
|
|||||||
<%= question.title %>
|
<%= question.title %>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
<% unless question.votation_type.nil? %>
|
||||||
|
<strong>
|
||||||
|
<%= t("poll_questions.description.#{question.enum_type}",
|
||||||
|
maximum: question.votation_type.max_votes,
|
||||||
|
system: question.votation_type.prioritization_type) %>
|
||||||
|
</strong>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<div id="<%= dom_id(question) %>_answers" class="padding">
|
<div id="<%= dom_id(question) %>_answers" class="padding">
|
||||||
<%= render "polls/questions/answers", question: question, token: token %>
|
<% answers = question.is_positive_negative? ? question.question_answers.visibles.page(1) : question.question_answers.visibles %>
|
||||||
|
<%= render "polls/questions/answers", question: question, token: token, answers: answers, page: 1 %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<% if question.answers_with_read_more? %>
|
||||||
|
<div class="poll_question_read_more">
|
||||||
|
<p><%= t("poll_questions.read_more_about") %></p>
|
||||||
|
<p>
|
||||||
|
<% first = true %>
|
||||||
|
<% question.question_answers&.visibles&.each do |answer| %>
|
||||||
|
<% if answer.description.present? || answer.images.any? ||
|
||||||
|
answer.documents.present? || answer.videos.present? %>
|
||||||
|
<% unless first %>
|
||||||
|
<span>, </span>
|
||||||
|
<% end %>
|
||||||
|
<% first = false if first %>
|
||||||
|
<%= link_to answer.title, "#answer_description_#{answer.id}" %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
<% token = poll_voter_token(@question.poll, current_user) %>
|
<% token = poll_voter_token(@question.poll, current_user) %>
|
||||||
$("#<%= dom_id(@question) %>_answers").html("<%= j render("polls/questions/answers", question: @question, token: token) %>");
|
$("#<%= dom_id(@question) %>_answers").html("<%= j render("polls/questions/answers", question: @question, answers: @answers, token: token, page: @page) %>");
|
||||||
|
App.Sortable.initialize();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<% provide :title do %><%= @poll.name %><% end %>
|
<% provide :title do %><%= @poll.name %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<div class="polls-results-stats">
|
<div class="polls-results-stats">
|
||||||
<%= render "poll_header" %>
|
<%= render "poll_header" %>
|
||||||
@@ -10,37 +11,32 @@
|
|||||||
<p><strong><%= t("polls.show.results.title") %></strong></p>
|
<p><strong><%= t("polls.show.results.title") %></strong></p>
|
||||||
<ul class="menu vertical">
|
<ul class="menu vertical">
|
||||||
<%- @poll.questions.each do |question| %>
|
<%- @poll.questions.each do |question| %>
|
||||||
<li><%=link_to question.title, "##{question.title.parameterize}" %></li>
|
<li><%= link_to question.title, "##{question.title.parameterize}" %></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="small-12 medium-9 column" data-equalizer-watch>
|
<div class="small-12 medium-9 column" data-equalizer-watch>
|
||||||
<%- @poll.questions.each do |question| %>
|
<%- @poll.questions.each do |question| %>
|
||||||
<% most_voted_answer_id = question.most_voted_answer_id %>
|
|
||||||
<h3 id="<%= question.title.parameterize %>"><%= question.title %></h3>
|
<h3 id="<%= question.title.parameterize %>"><%= question.title %></h3>
|
||||||
<table id="question_<%= question.id %>_results_table">
|
<table id="question_<%= question.id %>_results_table">
|
||||||
<thead>
|
<tbody>
|
||||||
<tr>
|
<%- question.question_answers.visibles.each do |answer| %>
|
||||||
<%- question.question_answers.each do |answer| %>
|
<tr scope="col" <%= answer.most_voted? ? "class=win" : "" %>>
|
||||||
<th scope="col" <%= answer.id == most_voted_answer_id ? "class=win" : "" %>>
|
<td>
|
||||||
<% if answer.id == most_voted_answer_id %>
|
<% if answer.most_voted %>
|
||||||
<span class="show-for-sr"><%= t("polls.show.results.most_voted_answer") %></span>
|
<span class="show-for-sr"><%= t("polls.show.results.most_voted_answer") %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= answer.title %>
|
<%= answer.title %>
|
||||||
</th>
|
|
||||||
<% end %>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<%- question.question_answers.each do |answer| %>
|
|
||||||
<td id="answer_<%= answer.id %>_result" <%= answer.id == most_voted_answer_id ? "class=win" : "" %>>
|
|
||||||
<%= answer.total_votes %>
|
|
||||||
(<%= answer.total_votes_percentage.round(2) %>%)
|
|
||||||
</td>
|
</td>
|
||||||
|
<td id="answer_<%= answer.id %>_result" <%= answer.most_voted? ? "class=win" : "" %>>
|
||||||
|
<%= answer.total_votes %>
|
||||||
|
<% unless question.enum_type == "positive_negative_open" || question.enum_type == "prioritized" %>
|
||||||
|
(<%= answer.total_votes_percentage.round(2) %>%)
|
||||||
<% end %>
|
<% end %>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<% end %>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -55,36 +55,24 @@
|
|||||||
|
|
||||||
<div id="poll_more_info_answers" class="expanded poll-more-info-answers">
|
<div id="poll_more_info_answers" class="expanded poll-more-info-answers">
|
||||||
<div class="row padding">
|
<div class="row padding">
|
||||||
|
<% @questions.each do |question| %>
|
||||||
<% @poll_questions_answers.each do |answer| %>
|
<% if question.answers_with_read_more? %>
|
||||||
<div class="small-12 medium-6 column end answer <%= cycle("first", "") %>" id="answer_<%= answer.id %>">
|
<div class="row question-divider">
|
||||||
|
<h2><%= question.title %></h2>
|
||||||
<% if answer.description.present? %>
|
<% question.question_answers.visibles.each do |answer| %>
|
||||||
|
<% if answer.description.present? || answer.images.any? || answer.documents.present? || answer.videos.present? %>
|
||||||
|
<div class="small-12 medium-6 column margin-top margin-bottom" id="answer_<%= answer.id %>">
|
||||||
<h3><%= answer.title %></h3>
|
<h3><%= answer.title %></h3>
|
||||||
|
<div class="margin-top">
|
||||||
|
<div id="answer_description_<%= answer.id %>"
|
||||||
|
class="answer-description short answer-left-divider" data-toggler="short">
|
||||||
|
<% if answer.description.present? %>
|
||||||
|
<%= answer.description %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if answer.images.any? %>
|
<% if answer.images.any? %>
|
||||||
<%= render "gallery", answer: answer %>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<% if answer.description.present? %>
|
|
||||||
<div class="margin-top">
|
<div class="margin-top">
|
||||||
<div id="answer_description_<%= answer.id %>" class="answer-description short" data-toggler="short">
|
<%= render "gallery", answer: answer %>
|
||||||
<%= safe_html_with_links simple_format(answer.description) %>
|
|
||||||
</div>
|
|
||||||
<div class="margin">
|
|
||||||
<a 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) %>
|
|
||||||
</a>
|
|
||||||
<a 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) %>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
@@ -94,12 +82,12 @@
|
|||||||
<span class="icon-document"></span>
|
<span class="icon-document"></span>
|
||||||
<strong><%= t("polls.show.documents") %></strong>
|
<strong><%= t("polls.show.documents") %></strong>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<% answer.documents.each do |document| %>
|
<% answer.documents.each do |document| %>
|
||||||
<%= link_to document.title,
|
<%= link_to document.title,
|
||||||
document.attachment.url,
|
document.attachment.url,
|
||||||
target: "_blank",
|
target: "_blank",
|
||||||
rel: "nofollow" %><br>
|
rel: "nofollow" %>
|
||||||
|
<br>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -115,11 +103,32 @@
|
|||||||
<%= link_to video.title,
|
<%= link_to video.title,
|
||||||
video.url,
|
video.url,
|
||||||
target: "_blank",
|
target: "_blank",
|
||||||
rel: "nofollow" %><br>
|
rel: "nofollow" %>
|
||||||
|
<br>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="margin-top margin-bottom">
|
||||||
|
<a 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) %>
|
||||||
|
</a>
|
||||||
|
<a 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) %>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -556,6 +556,7 @@ en:
|
|||||||
index:
|
index:
|
||||||
title: Polls
|
title: Polls
|
||||||
create: Create poll
|
create: Create poll
|
||||||
|
succesfull: Answer added succesfully
|
||||||
count:
|
count:
|
||||||
one: You have created %{count} poll.
|
one: You have created %{count} poll.
|
||||||
other: You have created %{count} polls.
|
other: You have created %{count} polls.
|
||||||
@@ -648,6 +649,17 @@ en:
|
|||||||
title: Help about voting
|
title: Help about voting
|
||||||
description: Citizens' polls are a participatory mechanism by which citizens with voting rights can make direct decisions
|
description: Citizens' polls are a participatory mechanism by which citizens with voting rights can make direct decisions
|
||||||
no_polls: "There are no open votings."
|
no_polls: "There are no open votings."
|
||||||
|
max_votes_reached: "You have already made the maximum number of votes. Thank you very much for participating"
|
||||||
|
descriptions:
|
||||||
|
unique: It's only possible to answer one time to the question.
|
||||||
|
multiple: Allows to choose multiple answers. It's possible to set the maximum number of answers.
|
||||||
|
prioritized: Allows to choose more than one answer and they will be prioritized. It's possible to set the maximum number of answers chosen and the answer count type.
|
||||||
|
positive_open: Allows to vote positively a maximum number of times to questions. It's possible to set the maximum number of answers and add other answers.
|
||||||
|
positive_negative_open: Allows to vote positively and negatively a maximum number of times to questions. It's possible to set the maximum number of answers and add other answers.
|
||||||
|
answer_couples_open: Allows to vote a maximum number of times to couples of possible answers. It's possible to set the maximum number of couples and add other answers.
|
||||||
|
answer_couples_closed: Allows to vote a maximum number of times to couples of possible answers. It's possible to set the maximum number of couples and it's not possible to add other answers.
|
||||||
|
answer_set_open: Allows to vote a maximum number of answers to a group of them. It's possible to set the maximum number of answers, the size of the group and add other answers.
|
||||||
|
answer_set_closed: Allows to vote a maximum number of answers to a group of them. It's possible to set the maximum number of answers and the size of the group.
|
||||||
show:
|
show:
|
||||||
already_voted_in_booth: "You have already participated in a physical booth. You can not participate again."
|
already_voted_in_booth: "You have already participated in a physical booth. You can not participate again."
|
||||||
already_voted_in_web: "You have already participated in this poll. If you vote again it will be overwritten."
|
already_voted_in_web: "You have already participated in this poll. If you vote again it will be overwritten."
|
||||||
@@ -689,6 +701,18 @@ en:
|
|||||||
show:
|
show:
|
||||||
vote_answer: "Vote %{answer}"
|
vote_answer: "Vote %{answer}"
|
||||||
voted: "You have voted %{answer}"
|
voted: "You have voted %{answer}"
|
||||||
|
add_answer: "Add answer"
|
||||||
|
description:
|
||||||
|
multiple: "You can select a maximum of %{maximum} answers."
|
||||||
|
positive_negative_open: "You can vote positive or negative a maximum of %{maximum} answers. And you can add your own answers."
|
||||||
|
answer_couples_open: "Choose an option from the following pair. You can choose a maximum of %{maximum} answers."
|
||||||
|
answer_couples_closed: "Choose an option from the following pair. You can choose a maximum of %{maximum} answers."
|
||||||
|
answer_set_open: "You can choose a maximum of %{maximum} answers."
|
||||||
|
answer_set_closed: "You can choose a maximum of %{maximum} answers."
|
||||||
|
prioritized: "You can select a maximum of %{maximum} answers. This question will use the %{system} system for count."
|
||||||
|
positive_open: "You can select a maximum of %{maximum} answers and add your own answers."
|
||||||
|
unique: ""
|
||||||
|
read_more_about: "Read more about:"
|
||||||
proposal_notifications:
|
proposal_notifications:
|
||||||
new:
|
new:
|
||||||
title: "Send message"
|
title: "Send message"
|
||||||
@@ -992,3 +1016,22 @@ en:
|
|||||||
surveys: Surveys
|
surveys: Surveys
|
||||||
poll:
|
poll:
|
||||||
take_part: Take part from %{from} to %{to}
|
take_part: Take part from %{from} to %{to}
|
||||||
|
question:
|
||||||
|
max_votes: Maximum number of votes
|
||||||
|
max_group_answers: Maximum number of answers in the set
|
||||||
|
votation_type: Votation type
|
||||||
|
enum_type:
|
||||||
|
title: Votation type
|
||||||
|
unique: Unique answer, closed
|
||||||
|
multiple: Multiple answers, closed
|
||||||
|
prioritized: Multiple prioritized answer, closed
|
||||||
|
positive_open: Votable positive, open
|
||||||
|
positive_negative_open: Votable positive and negative, open
|
||||||
|
answer_couples_open: Couples of answers, open
|
||||||
|
answer_couples_closed: Couples of answers, closed
|
||||||
|
answer_set_open: Set of answers, open
|
||||||
|
answer_set_closed: Set of answers, closed
|
||||||
|
prioritization_type:
|
||||||
|
title: Prioritization type
|
||||||
|
borda: Borda votation
|
||||||
|
dowdall: Dowdall votation
|
||||||
|
|||||||
@@ -556,6 +556,7 @@ es:
|
|||||||
index:
|
index:
|
||||||
title: Encuestas
|
title: Encuestas
|
||||||
create: Crear encuesta
|
create: Crear encuesta
|
||||||
|
succesfull: Respuesta añadida correctamente.
|
||||||
count:
|
count:
|
||||||
one: Has creado %{count} encuesta.
|
one: Has creado %{count} encuesta.
|
||||||
other: Has creado %{count} encuestas.
|
other: Has creado %{count} encuestas.
|
||||||
@@ -646,6 +647,17 @@ es:
|
|||||||
title: Ayuda sobre las votaciones
|
title: Ayuda sobre las votaciones
|
||||||
description: Las votaciones ciudadanas son un mecanismo de participación por el que la ciudadanía con derecho a voto puede tomar decisiones de forma directa.
|
description: Las votaciones ciudadanas son un mecanismo de participación por el que la ciudadanía con derecho a voto puede tomar decisiones de forma directa.
|
||||||
no_polls: "No hay votaciones abiertas."
|
no_polls: "No hay votaciones abiertas."
|
||||||
|
max_votes_reached: "Ya has realizado el número máximo de votos. Muchas gracias por participar"
|
||||||
|
descriptions:
|
||||||
|
unique: Solo se puede responder a la pregunta con una única respuesta.
|
||||||
|
multiple: Permite elegir más de una respuesta. Se puede elegir el número máximo de respuestas.
|
||||||
|
prioritized: Permite elegir mas de una respuesta, que a su vez se podran ordenar por prioridad. Se puede elegir el número máximo de respuestas y que tipo de recuento se utilizará en la priorización.
|
||||||
|
positive_open: Permite votar positivamente a un número máximo de respuestas. Se puede elegir el número máximo y los usuarios podran añadir resuestas.
|
||||||
|
positive_negative_open: Permite votar positiva y negativamente a un máximo de respuestas. Se puede elegir el número máximo y los usuarios podran añadir resuestas.
|
||||||
|
answer_couples_open: Permite votar a un número maximo de pares de respuestas. Se puede elegir el número maximo de pares y los usuarios podran añadir respuestas.
|
||||||
|
answer_couples_closed: Permite votar a un número maximo de pares de respuestas. Se puede elegir el número maximo de pares y los usuarios NO podran añadir respuestas.
|
||||||
|
answer_set_open: Permite votar un número máximo de respuestas en un conjunto de ellas. Se puede elegir el numero máximo de respuestas y el número de respuestas que hay en el conjunto. Los usuarios podran añadir respuestas.
|
||||||
|
answer_set_closed: Permite votar un número máximo de respuestas en un conjunto de ellas. Se puede elegir el numero máximo de respuestas y el número de respuestas que hay en el conjunto.
|
||||||
show:
|
show:
|
||||||
already_voted_in_booth: "Ya has participado en esta votación en urnas presenciales, no puedes volver a participar."
|
already_voted_in_booth: "Ya has participado en esta votación en urnas presenciales, no puedes volver a participar."
|
||||||
already_voted_in_web: "Ya has participado en esta votación. Si vuelves a votar se sobreescribirá tu resultado anterior."
|
already_voted_in_web: "Ya has participado en esta votación. Si vuelves a votar se sobreescribirá tu resultado anterior."
|
||||||
@@ -687,6 +699,17 @@ es:
|
|||||||
show:
|
show:
|
||||||
vote_answer: "Votar %{answer}"
|
vote_answer: "Votar %{answer}"
|
||||||
voted: "Has votado %{answer}"
|
voted: "Has votado %{answer}"
|
||||||
|
add_answer: "Añadir respuesta"
|
||||||
|
description:
|
||||||
|
multiple: "Puedes seleccionar un máximo de %{maximum} respuestas."
|
||||||
|
positive_negative_open: "Puedes votar, positiva o negativamente, un máximo de %{maximum} respuestas. Puedes añadir tus propias respuestas."
|
||||||
|
multiple: "Puedes seleccionar un máximo de %{maximum} respuestas"
|
||||||
|
answer_couples_open: "Elige una opción entre el siguiente par. Puedes elegir un máximo de %{maximum} respuestas"
|
||||||
|
answer_couples_closed: "Elige una opción entre el siguiente par. Puedes elegir un máximo de %{maximum} respuestas"
|
||||||
|
prioritized: "Puedes seleccionar un máximo de %{maximum} respuestas. Esta pregunta utilizara el método %{system} para el recuento."
|
||||||
|
positive_open: "Puedes seleccionar un máximo de %{maximum} respuestas y añadir tus propias respuestas."
|
||||||
|
unique: ""
|
||||||
|
read_more_about: "Leer más:"
|
||||||
proposal_notifications:
|
proposal_notifications:
|
||||||
new:
|
new:
|
||||||
title: "Enviar mensaje"
|
title: "Enviar mensaje"
|
||||||
@@ -990,3 +1013,22 @@ es:
|
|||||||
surveys: Encuestas
|
surveys: Encuestas
|
||||||
poll:
|
poll:
|
||||||
take_part: Participa del %{from} al %{to}
|
take_part: Participa del %{from} al %{to}
|
||||||
|
question:
|
||||||
|
max_votes: Número máximo de votos
|
||||||
|
max_group_answers: Número máximo de respuestas en el conjunto
|
||||||
|
votation_type: Tipo de votación
|
||||||
|
enum_type:
|
||||||
|
title: Tipo de votación
|
||||||
|
unique: Respuesta única, cerrada
|
||||||
|
multiple: Respuesta múltiple, cerrada
|
||||||
|
prioritized: Respuesta múltiple priorizada, cerrada
|
||||||
|
positive_open: Respuestas votables positivamente, abiertas
|
||||||
|
positive_negative_open: Respuestas votables positiva y negativamente, abiertas
|
||||||
|
answer_couples_open: Respuestas a pares, abiertas
|
||||||
|
answer_couples_closed: Respuestas a pares, cerradas
|
||||||
|
answer_set_open: Conjunto de respuestas, abiertas
|
||||||
|
answer_set_closed: Conjunto de respuestas, cerradas
|
||||||
|
prioritization_type:
|
||||||
|
title: Tipo de priorizacion
|
||||||
|
borda: Votación con recuento Borda
|
||||||
|
dowdall: Votación con recuento Dowdall
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ namespace :admin do
|
|||||||
end
|
end
|
||||||
|
|
||||||
resource :active_polls, only: [:create, :edit, :update]
|
resource :active_polls, only: [:create, :edit, :update]
|
||||||
|
get :get_options_traductions, controller: "questions"
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :verifications, controller: :verifications, only: :index do
|
resources :verifications, controller: :verifications, only: :index do
|
||||||
|
|||||||
@@ -5,6 +5,12 @@ resources :polls, only: [:show, :index] do
|
|||||||
end
|
end
|
||||||
|
|
||||||
resources :questions, controller: "polls/questions", shallow: true do
|
resources :questions, controller: "polls/questions", shallow: true do
|
||||||
post :answer, on: :member
|
member do
|
||||||
|
post :answer
|
||||||
|
post :prioritized_answers
|
||||||
|
delete :answer, to: "polls/answers#delete"
|
||||||
|
post :create_answer, to: "polls/answers#create"
|
||||||
|
get :load_answers
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
17
db/migrate/20190513112613_create_votation_types.rb
Normal file
17
db/migrate/20190513112613_create_votation_types.rb
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
class CreateVotationTypes < ActiveRecord::Migration[5.0]
|
||||||
|
def change
|
||||||
|
create_table :votation_types do |t|
|
||||||
|
t.integer :questionable_id
|
||||||
|
t.string :questionable_type
|
||||||
|
t.integer :enum_type
|
||||||
|
t.boolean :open_answer
|
||||||
|
t.boolean :prioritized
|
||||||
|
t.integer :prioritization_type
|
||||||
|
t.integer :max_votes
|
||||||
|
t.integer :max_groups_answers
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class AddOrderAndPositiveInPollAnswers < ActiveRecord::Migration[5.0]
|
||||||
|
def change
|
||||||
|
add_column :poll_answers, :positive, :boolean
|
||||||
|
add_column :poll_answers, :order, :integer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
13
db/migrate/20190522075912_create_poll_pair_answers.rb
Normal file
13
db/migrate/20190522075912_create_poll_pair_answers.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
class CreatePollPairAnswers < ActiveRecord::Migration[5.0]
|
||||||
|
def change
|
||||||
|
create_table :poll_pair_answers do |t|
|
||||||
|
t.references :question, index: true
|
||||||
|
t.references :author, index: true
|
||||||
|
t.references :answer_rigth
|
||||||
|
t.references :answer_left
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class AddHiddenFieldToPollQuestionAnswers < ActiveRecord::Migration[5.0]
|
||||||
|
def change
|
||||||
|
add_column :poll_question_answers, :hidden, :boolean, default: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
6
db/migrate/20190524121957_add_value_to_poll_answers.rb
Normal file
6
db/migrate/20190524121957_add_value_to_poll_answers.rb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
class AddValueToPollAnswers < ActiveRecord::Migration[5.0]
|
||||||
|
def change
|
||||||
|
add_column :poll_answers, :value, :integer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
12
db/migrate/20190528134530_create_votation_set_answers.rb
Normal file
12
db/migrate/20190528134530_create_votation_set_answers.rb
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
class CreateVotationSetAnswers < ActiveRecord::Migration[5.0]
|
||||||
|
def change
|
||||||
|
create_table :votation_set_answers do |t|
|
||||||
|
t.integer :author_id, index: true
|
||||||
|
t.references :votation_type, foreign_key: true, index: true
|
||||||
|
t.string :answer
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
41
db/schema.rb
41
db/schema.rb
@@ -1029,6 +1029,9 @@ ActiveRecord::Schema.define(version: 20190607160900) do
|
|||||||
t.string "answer"
|
t.string "answer"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
|
t.boolean "positive"
|
||||||
|
t.integer "order"
|
||||||
|
t.integer "value"
|
||||||
t.index ["author_id"], name: "index_poll_answers_on_author_id", using: :btree
|
t.index ["author_id"], name: "index_poll_answers_on_author_id", using: :btree
|
||||||
t.index ["question_id", "answer"], name: "index_poll_answers_on_question_id_and_answer", using: :btree
|
t.index ["question_id", "answer"], name: "index_poll_answers_on_question_id_and_answer", using: :btree
|
||||||
t.index ["question_id"], name: "index_poll_answers_on_question_id", using: :btree
|
t.index ["question_id"], name: "index_poll_answers_on_question_id", using: :btree
|
||||||
@@ -1084,6 +1087,19 @@ ActiveRecord::Schema.define(version: 20190607160900) do
|
|||||||
t.index ["user_id"], name: "index_poll_officers_on_user_id", using: :btree
|
t.index ["user_id"], name: "index_poll_officers_on_user_id", using: :btree
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "poll_pair_answers", force: :cascade do |t|
|
||||||
|
t.integer "question_id"
|
||||||
|
t.integer "author_id"
|
||||||
|
t.integer "answer_rigth_id"
|
||||||
|
t.integer "answer_left_id"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["answer_left_id"], name: "index_poll_pair_answers_on_answer_left_id", using: :btree
|
||||||
|
t.index ["answer_rigth_id"], name: "index_poll_pair_answers_on_answer_rigth_id", using: :btree
|
||||||
|
t.index ["author_id"], name: "index_poll_pair_answers_on_author_id", using: :btree
|
||||||
|
t.index ["question_id"], name: "index_poll_pair_answers_on_question_id", using: :btree
|
||||||
|
end
|
||||||
|
|
||||||
create_table "poll_partial_results", force: :cascade do |t|
|
create_table "poll_partial_results", force: :cascade do |t|
|
||||||
t.integer "question_id"
|
t.integer "question_id"
|
||||||
t.integer "author_id"
|
t.integer "author_id"
|
||||||
@@ -1127,6 +1143,7 @@ ActiveRecord::Schema.define(version: 20190607160900) do
|
|||||||
t.integer "question_id"
|
t.integer "question_id"
|
||||||
t.integer "given_order", default: 1
|
t.integer "given_order", default: 1
|
||||||
t.boolean "most_voted", default: false
|
t.boolean "most_voted", default: false
|
||||||
|
t.boolean "hidden", default: false
|
||||||
t.index ["question_id"], name: "index_poll_question_answers_on_question_id", using: :btree
|
t.index ["question_id"], name: "index_poll_question_answers_on_question_id", using: :btree
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1613,6 +1630,29 @@ ActiveRecord::Schema.define(version: 20190607160900) do
|
|||||||
t.index ["user_id"], name: "index_visits_on_user_id", using: :btree
|
t.index ["user_id"], name: "index_visits_on_user_id", using: :btree
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "votation_set_answers", force: :cascade do |t|
|
||||||
|
t.integer "author_id"
|
||||||
|
t.integer "votation_type_id"
|
||||||
|
t.string "answer"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["author_id"], name: "index_votation_set_answers_on_author_id", using: :btree
|
||||||
|
t.index ["votation_type_id"], name: "index_votation_set_answers_on_votation_type_id", using: :btree
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "votation_types", force: :cascade do |t|
|
||||||
|
t.integer "questionable_id"
|
||||||
|
t.string "questionable_type"
|
||||||
|
t.integer "enum_type"
|
||||||
|
t.boolean "open_answer"
|
||||||
|
t.boolean "prioritized"
|
||||||
|
t.integer "prioritization_type"
|
||||||
|
t.integer "max_votes"
|
||||||
|
t.integer "max_groups_answers"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
end
|
||||||
|
|
||||||
create_table "votes", force: :cascade do |t|
|
create_table "votes", force: :cascade do |t|
|
||||||
t.string "votable_type"
|
t.string "votable_type"
|
||||||
t.integer "votable_id"
|
t.integer "votable_id"
|
||||||
@@ -1721,4 +1761,5 @@ ActiveRecord::Schema.define(version: 20190607160900) do
|
|||||||
add_foreign_key "trackers", "users"
|
add_foreign_key "trackers", "users"
|
||||||
add_foreign_key "users", "geozones"
|
add_foreign_key "users", "geozones"
|
||||||
add_foreign_key "valuators", "users"
|
add_foreign_key "valuators", "users"
|
||||||
|
add_foreign_key "votation_set_answers", "votation_types"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -38,6 +38,69 @@ FactoryBot.define do
|
|||||||
create(:poll_question_answer, question: question, title: "No")
|
create(:poll_question_answer, question: question, title: "No")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :poll_question_unique do
|
||||||
|
after(:create) do |question|
|
||||||
|
create(:votation_type_unique, questionable: question)
|
||||||
|
question.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :poll_question_multiple do
|
||||||
|
after(:create) do |question|
|
||||||
|
create(:votation_type_multiple, questionable: question)
|
||||||
|
question.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :poll_question_prioritized do
|
||||||
|
after(:create) do |question|
|
||||||
|
create(:votation_type_prioritized, questionable: question)
|
||||||
|
question.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :poll_question_positive_open do
|
||||||
|
after(:create) do |question|
|
||||||
|
create(:votation_type_positive_open, questionable: question)
|
||||||
|
question.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :poll_question_positive_negative_open do
|
||||||
|
after(:create) do |question|
|
||||||
|
create(:votation_type_positive_negative_open, questionable: question)
|
||||||
|
question.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :poll_question_answer_couples_open do
|
||||||
|
after(:create) do |question|
|
||||||
|
create(:votation_type_answer_couples_open, questionable: question)
|
||||||
|
question.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :poll_question_answer_couples_closed do
|
||||||
|
after(:create) do |question|
|
||||||
|
create(:votation_type_answer_couples_closed, questionable: question)
|
||||||
|
question.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :poll_question_answer_set_open do
|
||||||
|
after(:create) do |question|
|
||||||
|
create(:votation_type_answer_set_open, questionable: question)
|
||||||
|
question.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :poll_question_answer_set_closed do
|
||||||
|
after(:create) do |question|
|
||||||
|
create(:votation_type_answer_set_closed, questionable: question)
|
||||||
|
question.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :poll_question_answer, class: "Poll::Question::Answer" do
|
factory :poll_question_answer, class: "Poll::Question::Answer" do
|
||||||
@@ -177,4 +240,11 @@ FactoryBot.define do
|
|||||||
|
|
||||||
factory :active_poll do
|
factory :active_poll do
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :poll_pair_answer, class: "Poll::PairAnswer" do
|
||||||
|
question { create :poll_question }
|
||||||
|
author { create :user }
|
||||||
|
answer_left { create(:poll_question_answer, question: question) }
|
||||||
|
answer_right { create(:poll_question_answer, question: question) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
77
spec/factories/votation_type.rb
Normal file
77
spec/factories/votation_type.rb
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
FactoryBot.define do
|
||||||
|
factory :votation_type do
|
||||||
|
factory :votation_type_unique do
|
||||||
|
enum_type "unique"
|
||||||
|
open_answer false
|
||||||
|
prioritized false
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :votation_type_multiple do
|
||||||
|
enum_type "multiple"
|
||||||
|
open_answer false
|
||||||
|
prioritized false
|
||||||
|
max_votes 5
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :votation_type_prioritized do
|
||||||
|
enum_type "prioritized"
|
||||||
|
open_answer false
|
||||||
|
prioritized true
|
||||||
|
max_votes 5
|
||||||
|
prioritization_type "borda"
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :votation_type_positive_open do
|
||||||
|
enum_type "positive_open"
|
||||||
|
open_answer true
|
||||||
|
prioritized false
|
||||||
|
max_votes 5
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :votation_type_positive_negative_open do
|
||||||
|
enum_type "positive_negative_open"
|
||||||
|
open_answer true
|
||||||
|
prioritized false
|
||||||
|
max_votes 5
|
||||||
|
prioritization_type "borda"
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :votation_type_answer_couples_open do
|
||||||
|
enum_type "answer_couples_open"
|
||||||
|
open_answer true
|
||||||
|
prioritized false
|
||||||
|
max_votes 5
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :votation_type_answer_couples_closed do
|
||||||
|
enum_type "answer_couples_open"
|
||||||
|
open_answer false
|
||||||
|
prioritized false
|
||||||
|
max_votes 5
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :votation_type_answer_set_open do
|
||||||
|
enum_type "answer_set_open"
|
||||||
|
open_answer true
|
||||||
|
prioritized false
|
||||||
|
max_votes 3
|
||||||
|
max_groups_answers 5
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :votation_type_answer_set_closed do
|
||||||
|
enum_type "answer_set_open"
|
||||||
|
open_answer false
|
||||||
|
prioritized false
|
||||||
|
max_votes 3
|
||||||
|
max_groups_answers 5
|
||||||
|
end
|
||||||
|
|
||||||
|
trait :open do
|
||||||
|
open_answer true
|
||||||
|
end
|
||||||
|
trait :prioritized do
|
||||||
|
prioritized true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -248,14 +248,17 @@ describe "Admin polls" do
|
|||||||
scenario "Question list", :js do
|
scenario "Question list", :js do
|
||||||
poll = create(:poll)
|
poll = create(:poll)
|
||||||
question = create(:poll_question, poll: poll)
|
question = create(:poll_question, poll: poll)
|
||||||
|
votation_type_question = create(:poll_question_unique, poll: poll)
|
||||||
other_question = create(:poll_question)
|
other_question = create(:poll_question)
|
||||||
|
|
||||||
visit admin_poll_path(poll)
|
visit admin_poll_path(poll)
|
||||||
|
|
||||||
expect(page).to have_content "Questions (1)"
|
expect(page).to have_content "Questions (2)"
|
||||||
expect(page).to have_content question.title
|
expect(page).to have_content question.title
|
||||||
|
expect(page).to have_content votation_type_question.title
|
||||||
expect(page).not_to have_content other_question.title
|
expect(page).not_to have_content other_question.title
|
||||||
expect(page).not_to have_content "There are no questions assigned to this poll"
|
expect(page).not_to have_content "There are no questions assigned to this poll"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ describe "Admin poll questions" do
|
|||||||
question1 = create(:poll_question, poll: poll1)
|
question1 = create(:poll_question, poll: poll1)
|
||||||
question2 = create(:poll_question, poll: poll2)
|
question2 = create(:poll_question, poll: poll2)
|
||||||
question3 = create(:poll_question, poll: poll3, proposal: proposal)
|
question3 = create(:poll_question, poll: poll3, proposal: proposal)
|
||||||
|
question4 = create(:poll_question_unique, poll: poll1)
|
||||||
|
|
||||||
visit admin_poll_path(poll1)
|
visit admin_poll_path(poll1)
|
||||||
expect(page).to have_content(poll1.name)
|
expect(page).to have_content(poll1.name)
|
||||||
@@ -30,6 +31,13 @@ describe "Admin poll questions" do
|
|||||||
expect(page).to have_content("Delete")
|
expect(page).to have_content("Delete")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
within("#poll_question_#{question4.id}") do
|
||||||
|
expect(page).to have_content(question4.title)
|
||||||
|
expect(page).to have_content("Edit answers")
|
||||||
|
expect(page).to have_content("Edit")
|
||||||
|
expect(page).to have_content("Delete")
|
||||||
|
end
|
||||||
|
|
||||||
visit admin_poll_path(poll2)
|
visit admin_poll_path(poll2)
|
||||||
expect(page).to have_content(poll2.name)
|
expect(page).to have_content(poll2.name)
|
||||||
|
|
||||||
@@ -52,16 +60,35 @@ describe "Admin poll questions" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Show" do
|
context "Show" do
|
||||||
|
scenario "Without Votation type" do
|
||||||
geozone = create(:geozone)
|
geozone = create(:geozone)
|
||||||
poll = create(:poll, geozone_restricted: true, geozone_ids: [geozone.id])
|
poll = create(:poll, geozone_restricted: true, geozone_ids: [geozone.id])
|
||||||
question = create(:poll_question, poll: poll)
|
question = create(:poll_question, poll: poll)
|
||||||
|
|
||||||
|
visit admin_poll_path(poll)
|
||||||
|
click_link question.title
|
||||||
|
|
||||||
|
expect(page).to have_content(question.title)
|
||||||
|
expect(page).to have_content(question.author.name)
|
||||||
|
expect(page).not_to have_content("Votation type")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "With Votation type" do
|
||||||
|
geozone = create(:geozone)
|
||||||
|
poll = create(:poll, geozone_restricted: true, geozone_ids: [geozone.id])
|
||||||
|
question = create(:poll_question_multiple, poll: poll)
|
||||||
|
|
||||||
visit admin_poll_path(poll)
|
visit admin_poll_path(poll)
|
||||||
click_link "#{question.title}"
|
click_link "#{question.title}"
|
||||||
|
|
||||||
expect(page).to have_content(question.title)
|
expect(page).to have_content(question.title)
|
||||||
expect(page).to have_content(question.author.name)
|
expect(page).to have_content(question.author.name)
|
||||||
|
expect(page).to have_content("Votation type")
|
||||||
|
expect(page).to have_content("Multiple")
|
||||||
|
expect(page).to have_content("Maximum number of votes")
|
||||||
|
expect(page).to have_content("5")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Create" do
|
scenario "Create" do
|
||||||
@@ -123,6 +150,179 @@ describe "Admin poll questions" do
|
|||||||
expect(page).to have_content(proposal.title)
|
expect(page).to have_content(proposal.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "create with votation type" do
|
||||||
|
before do
|
||||||
|
poll = create(:poll, name: "Movies")
|
||||||
|
visit admin_poll_path(poll)
|
||||||
|
click_link "Create question"
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "unique" do
|
||||||
|
title = "unique question"
|
||||||
|
fill_in "Question", with: title
|
||||||
|
select "Unique answer, closed", from: "votation_type_enum_type"
|
||||||
|
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content(title)
|
||||||
|
expect(page).to have_content("Unique answer, closed")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "multiple" do
|
||||||
|
title = "multiple question"
|
||||||
|
fill_in "Question", with: title
|
||||||
|
select "Multiple answers, closed", from: "votation_type_enum_type"
|
||||||
|
|
||||||
|
expect(page).to have_content("Maximum number of votes")
|
||||||
|
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content("1 error prevented this Poll/Question from being saved.")
|
||||||
|
|
||||||
|
fill_in "Maximum number of votes", with: 6
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content(title)
|
||||||
|
expect(page).to have_content("Multiple answers, closed")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "prioritized" do
|
||||||
|
title = "prioritized question"
|
||||||
|
fill_in "Question", with: title
|
||||||
|
select "Multiple prioritized answer, closed", from: "votation_type_enum_type"
|
||||||
|
|
||||||
|
expect(page).to have_content("Maximum number of votes")
|
||||||
|
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content("1 error prevented this Poll/Question from being saved.")
|
||||||
|
|
||||||
|
fill_in "Maximum number of votes", with: 6
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content(title)
|
||||||
|
expect(page).to have_content("Multiple prioritized answer, closed")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "positive_open" do
|
||||||
|
title = "positive open question"
|
||||||
|
fill_in "Question", with: title
|
||||||
|
select "Votable positive, open", from: "votation_type_enum_type"
|
||||||
|
|
||||||
|
expect(page).to have_content("Maximum number of votes")
|
||||||
|
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content("1 error prevented this Poll/Question from being saved.")
|
||||||
|
|
||||||
|
fill_in "Maximum number of votes", with: 6
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content(title)
|
||||||
|
expect(page).to have_content("Votable positive, open")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "positive_negative_open" do
|
||||||
|
title = "positive negative open question"
|
||||||
|
fill_in "Question", with: title
|
||||||
|
select "Votable positive and negative, open", from: "votation_type_enum_type"
|
||||||
|
|
||||||
|
expect(page).to have_content("Maximum number of votes")
|
||||||
|
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content("1 error prevented this Poll/Question from being saved.")
|
||||||
|
|
||||||
|
fill_in "Maximum number of votes", with: 6
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content(title)
|
||||||
|
expect(page).to have_content("Votable positive and negative, open")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "answer_couples_open" do
|
||||||
|
title = "answer couples open question"
|
||||||
|
fill_in "Question", with: title
|
||||||
|
select "Couples of answers, open", from: "votation_type_enum_type"
|
||||||
|
|
||||||
|
expect(page).to have_content("Maximum number of votes")
|
||||||
|
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content("1 error prevented this Poll/Question from being saved.")
|
||||||
|
|
||||||
|
fill_in "Maximum number of votes", with: 6
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content(title)
|
||||||
|
expect(page).to have_content("Couples of answers, open")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "answer_couples_closed" do
|
||||||
|
title = "answer couples closed question"
|
||||||
|
fill_in "Question", with: title
|
||||||
|
select "Couples of answers, closed", from: "votation_type_enum_type"
|
||||||
|
|
||||||
|
expect(page).to have_content("Maximum number of votes")
|
||||||
|
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content("1 error prevented this Poll/Question from being saved.")
|
||||||
|
|
||||||
|
fill_in "Maximum number of votes", with: 6
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content(title)
|
||||||
|
expect(page).to have_content("Couples of answers, closed")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "answer_set_open" do
|
||||||
|
title = "answer set open question"
|
||||||
|
fill_in "Question", with: title
|
||||||
|
select "Set of answers, open", from: "votation_type_enum_type"
|
||||||
|
|
||||||
|
expect(page).to have_content("Maximum number of votes")
|
||||||
|
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content("1 error prevented this Poll/Question from being saved.")
|
||||||
|
|
||||||
|
fill_in "Maximum number of votes", with: 6
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content("1 error prevented this Poll/Question from being saved.")
|
||||||
|
|
||||||
|
fill_in "Maximum number of answers in the set", with: 3
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content(title)
|
||||||
|
expect(page).to have_content("Set of answers, open")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "answer_set_closed" do
|
||||||
|
title = "answer set closed question"
|
||||||
|
fill_in "Question", with: title
|
||||||
|
select "Set of answers, closed", from: "votation_type_enum_type"
|
||||||
|
|
||||||
|
expect(page).to have_content("Maximum number of votes")
|
||||||
|
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content("1 error prevented this Poll/Question from being saved.")
|
||||||
|
|
||||||
|
fill_in "Maximum number of votes", with: 6
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content("1 error prevented this Poll/Question from being saved.")
|
||||||
|
|
||||||
|
fill_in "Maximum number of answers in the set", with: 3
|
||||||
|
click_button "Save"
|
||||||
|
|
||||||
|
expect(page).to have_content(title)
|
||||||
|
expect(page).to have_content("Set of answers, closed")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scenario "Update" do
|
scenario "Update" do
|
||||||
poll = create(:poll)
|
poll = create(:poll)
|
||||||
question1 = create(:poll_question, poll: poll)
|
question1 = create(:poll_question, poll: poll)
|
||||||
|
|||||||
@@ -231,11 +231,12 @@ describe "Polls" do
|
|||||||
|
|
||||||
visit poll_path(expired_poll)
|
visit poll_path(expired_poll)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
expect(page).to have_content("Luke")
|
expect(page).to have_content("Luke")
|
||||||
expect(page).to have_content("Leia")
|
expect(page).to have_content("Leia")
|
||||||
expect(page).not_to have_link("Luke")
|
expect(page).not_to have_link("Luke")
|
||||||
expect(page).not_to have_link("Leia")
|
expect(page).not_to have_link("Leia")
|
||||||
|
end
|
||||||
expect(page).to have_content("This poll has finished")
|
expect(page).to have_content("This poll has finished")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -251,11 +252,13 @@ describe "Polls" do
|
|||||||
|
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
expect(page).to have_content("Vader")
|
expect(page).to have_content("Vader")
|
||||||
expect(page).to have_content("Palpatine")
|
expect(page).to have_content("Palpatine")
|
||||||
expect(page).not_to have_link("Vader")
|
expect(page).not_to have_link("Vader")
|
||||||
expect(page).not_to have_link("Palpatine")
|
expect(page).not_to have_link("Palpatine")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scenario "Level 2 users reading a same-geozone poll" do
|
scenario "Level 2 users reading a same-geozone poll" do
|
||||||
poll.update(geozone_restricted: true)
|
poll.update(geozone_restricted: true)
|
||||||
@@ -268,9 +271,11 @@ describe "Polls" do
|
|||||||
login_as(create(:user, :level_two, geozone: geozone))
|
login_as(create(:user, :level_two, geozone: geozone))
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
expect(page).to have_link("Han Solo")
|
expect(page).to have_link("Han Solo")
|
||||||
expect(page).to have_link("Chewbacca")
|
expect(page).to have_link("Chewbacca")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scenario "Level 2 users reading a all-geozones poll" do
|
scenario "Level 2 users reading a all-geozones poll" do
|
||||||
question = create(:poll_question, poll: poll)
|
question = create(:poll_question, poll: poll)
|
||||||
@@ -280,9 +285,11 @@ describe "Polls" do
|
|||||||
login_as(create(:user, :level_two))
|
login_as(create(:user, :level_two))
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
expect(page).to have_link("Han Solo")
|
expect(page).to have_link("Han Solo")
|
||||||
expect(page).to have_link("Chewbacca")
|
expect(page).to have_link("Chewbacca")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scenario "Level 2 users who have already answered" do
|
scenario "Level 2 users who have already answered" do
|
||||||
question = create(:poll_question, poll: poll)
|
question = create(:poll_question, poll: poll)
|
||||||
@@ -294,9 +301,11 @@ describe "Polls" do
|
|||||||
login_as user
|
login_as user
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
expect(page).to have_link("Han Solo")
|
expect(page).to have_link("Han Solo")
|
||||||
expect(page).to have_link("Chewbacca")
|
expect(page).to have_link("Chewbacca")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scenario "Level 2 users answering", :js do
|
scenario "Level 2 users answering", :js do
|
||||||
poll.update(geozone_restricted: true)
|
poll.update(geozone_restricted: true)
|
||||||
@@ -311,11 +320,13 @@ describe "Polls" do
|
|||||||
login_as user
|
login_as user
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
click_link "Han Solo"
|
click_link "Han Solo"
|
||||||
|
|
||||||
expect(page).not_to have_link("Han Solo")
|
expect(page).not_to have_link("Han Solo")
|
||||||
expect(page).to have_link("Chewbacca")
|
expect(page).to have_link("Chewbacca")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scenario "Level 2 users changing answer", :js do
|
scenario "Level 2 users changing answer", :js do
|
||||||
poll.update(geozone_restricted: true)
|
poll.update(geozone_restricted: true)
|
||||||
@@ -330,6 +341,7 @@ describe "Polls" do
|
|||||||
login_as user
|
login_as user
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
click_link "Han Solo"
|
click_link "Han Solo"
|
||||||
|
|
||||||
expect(page).not_to have_link("Han Solo")
|
expect(page).not_to have_link("Han Solo")
|
||||||
@@ -340,6 +352,7 @@ describe "Polls" do
|
|||||||
expect(page).not_to have_link("Chewbacca")
|
expect(page).not_to have_link("Chewbacca")
|
||||||
expect(page).to have_link("Han Solo")
|
expect(page).to have_link("Han Solo")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scenario "Level 2 votes, signs out, signs in, votes again", :js do
|
scenario "Level 2 votes, signs out, signs in, votes again", :js do
|
||||||
poll.update(geozone_restricted: true)
|
poll.update(geozone_restricted: true)
|
||||||
@@ -353,28 +366,35 @@ describe "Polls" do
|
|||||||
|
|
||||||
login_as user
|
login_as user
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
click_link "Han Solo"
|
click_link "Han Solo"
|
||||||
|
|
||||||
expect(page).not_to have_link("Han Solo")
|
expect(page).not_to have_link("Han Solo")
|
||||||
expect(page).to have_link("Chewbacca")
|
expect(page).to have_link("Chewbacca")
|
||||||
|
end
|
||||||
|
|
||||||
click_link "Sign out"
|
click_link "Sign out"
|
||||||
login_as user
|
login_as user
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
click_link "Han Solo"
|
click_link "Han Solo"
|
||||||
|
|
||||||
expect(page).not_to have_link("Han Solo")
|
expect(page).not_to have_link("Han Solo")
|
||||||
expect(page).to have_link("Chewbacca")
|
expect(page).to have_link("Chewbacca")
|
||||||
|
end
|
||||||
|
|
||||||
click_link "Sign out"
|
click_link "Sign out"
|
||||||
login_as user
|
login_as user
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
click_link "Chewbacca"
|
click_link "Chewbacca"
|
||||||
|
|
||||||
expect(page).not_to have_link("Chewbacca")
|
expect(page).not_to have_link("Chewbacca")
|
||||||
expect(page).to have_link("Han Solo")
|
expect(page).to have_link("Han Solo")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "Booth & Website", :with_frozen_time do
|
context "Booth & Website", :with_frozen_time do
|
||||||
|
|
||||||
|
|||||||
442
spec/features/polls/votation_type_spec.rb
Normal file
442
spec/features/polls/votation_type_spec.rb
Normal file
@@ -0,0 +1,442 @@
|
|||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
feature "Poll Votation Type" do
|
||||||
|
|
||||||
|
context "Unique" do
|
||||||
|
|
||||||
|
let(:user) { create(:user, :verified) }
|
||||||
|
let(:poll_current) { create(:poll, :current) }
|
||||||
|
let(:unique) { create(:poll_question_unique, poll: poll_current) }
|
||||||
|
let!(:answer1) { create(:poll_question_answer, question: unique, title: "answer_1") }
|
||||||
|
let!(:answer2) { create(:poll_question_answer, question: unique, title: "answer_2") }
|
||||||
|
|
||||||
|
background do
|
||||||
|
login_as(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question without votation type" do
|
||||||
|
question = create(:poll_question, :with_answers, poll: poll_current)
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
expect(page).to have_content(question.title)
|
||||||
|
expect(page).to have_content(answer1.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question with votation type" do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
expect(page).to have_content(unique.title)
|
||||||
|
expect(page).to have_content(answer1.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question vote", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{unique.id}_answers") do
|
||||||
|
click_link answer1.title
|
||||||
|
expect(page).to have_css("a", text: answer2.title)
|
||||||
|
expect(page).not_to have_css("a", text: answer1.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question change vote", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{unique.id}_answers") do
|
||||||
|
click_link answer1.title
|
||||||
|
expect(page).to have_css("a", text: answer2.title)
|
||||||
|
expect(page).not_to have_css("a", text: answer1.title)
|
||||||
|
click_link answer2.title
|
||||||
|
expect(page).to have_css("a", text: answer1.title)
|
||||||
|
expect(page).not_to have_css("a", text: answer2.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "Multiple" do
|
||||||
|
|
||||||
|
let(:user) { create(:user, :verified) }
|
||||||
|
let(:poll_current) { create(:poll, :current) }
|
||||||
|
let(:question) { create(:poll_question_multiple, poll: poll_current) }
|
||||||
|
let!(:answer1) { create(:poll_question_answer, question: question, title: "answer_1") }
|
||||||
|
let!(:answer2) { create(:poll_question_answer, question: question, title: "answer_2") }
|
||||||
|
let!(:answer3) { create(:poll_question_answer, question: question, title: "answer_3") }
|
||||||
|
let!(:answer4) { create(:poll_question_answer, question: question, title: "answer_4") }
|
||||||
|
let!(:answer5) { create(:poll_question_answer, question: question, title: "answer_5") }
|
||||||
|
|
||||||
|
background do
|
||||||
|
login_as(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question" do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
expect(page).to have_content(answer.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question vote", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.title
|
||||||
|
expect(page).to have_css(".answered", text: answer.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question no more vote than allowed", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.title
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
answer6 = create(:poll_question_answer, question: question, title: "answer_6")
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer6.title
|
||||||
|
expect(page).not_to have_css(".answered", text: answer6.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question remove vote and vote again", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.title
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer1.title
|
||||||
|
end
|
||||||
|
|
||||||
|
answer6 = create(:poll_question_answer, question: question, title: "answer_6")
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
expect(page).to have_css("a", text: answer6.title)
|
||||||
|
|
||||||
|
click_link answer6.title
|
||||||
|
|
||||||
|
expect(page).to have_css(".answered", text: answer6.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "Prioritized" do
|
||||||
|
|
||||||
|
let(:user) { create(:user, :verified) }
|
||||||
|
let(:poll_current) { create(:poll, :current) }
|
||||||
|
let(:question) { create(:poll_question_prioritized, poll: poll_current) }
|
||||||
|
let!(:answer1) { create(:poll_question_answer, question: question, title: "answer_1") }
|
||||||
|
let!(:answer2) { create(:poll_question_answer, question: question, title: "answer_2") }
|
||||||
|
let!(:answer3) { create(:poll_question_answer, question: question, title: "answer_3") }
|
||||||
|
let!(:answer4) { create(:poll_question_answer, question: question, title: "answer_4") }
|
||||||
|
let!(:answer5) { create(:poll_question_answer, question: question, title: "answer_5") }
|
||||||
|
|
||||||
|
background do
|
||||||
|
login_as(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question" do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
expect(page).to have_content(answer.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question vote", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.title
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
expect(page).to have_css("a", text: answer.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question no more vote than allowed", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.title
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
answer6 = create(:poll_question_answer, question: question, title: "answer_6")
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer6.title
|
||||||
|
expect(page).not_to have_css(".answered", text: answer6.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "Positive open" do
|
||||||
|
|
||||||
|
let(:user) { create(:user, :verified) }
|
||||||
|
let(:poll_current) { create(:poll, :current) }
|
||||||
|
let(:question) { create(:poll_question_positive_open, poll: poll_current) }
|
||||||
|
let!(:answer1) { create(:poll_question_answer, question: question, title: "answer_1") }
|
||||||
|
let!(:answer2) { create(:poll_question_answer, question: question, title: "answer_2") }
|
||||||
|
let!(:answer3) { create(:poll_question_answer, question: question, title: "answer_3") }
|
||||||
|
let!(:answer4) { create(:poll_question_answer, question: question, title: "answer_4") }
|
||||||
|
let!(:answer5) { create(:poll_question_answer, question: question, title: "answer_5") }
|
||||||
|
|
||||||
|
background do
|
||||||
|
login_as(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question" do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
expect(page).to have_content(answer.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question vote", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.title
|
||||||
|
expect(page).to have_css(".answered", text: answer.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question no more vote than allowed", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.title
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
answer6 = create(:poll_question_answer, question: question, title: "answer_6")
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer6.title
|
||||||
|
expect(page).not_to have_css(".answered", text: answer6.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question remove vote and vote again", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.title
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer1.title
|
||||||
|
end
|
||||||
|
|
||||||
|
answer6 = create(:poll_question_answer, question: question, title: "answer_6")
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer6.title
|
||||||
|
expect(page).to have_css(".answered", text: answer6.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "add answer", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
fill_in "answer", with: "added_answer"
|
||||||
|
click_button "Add answer"
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
expect(page).to have_css("a", text: "added_answer")
|
||||||
|
click_link "added_answer"
|
||||||
|
expect(page).to have_css(".answered", text: "added_answer")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
xcontext "Positive and negative open" do
|
||||||
|
|
||||||
|
let(:user) { create(:user, :verified) }
|
||||||
|
let(:poll_current) { create(:poll, :current) }
|
||||||
|
let(:question) { create(:poll_question_positive_negative_open, poll: poll_current) }
|
||||||
|
let!(:answer1) { create(:poll_question_answer, question: question, title: "answer_1") }
|
||||||
|
let!(:answer2) { create(:poll_question_answer, question: question, title: "answer_2") }
|
||||||
|
let!(:answer3) { create(:poll_question_answer, question: question, title: "answer_3") }
|
||||||
|
let!(:answer4) { create(:poll_question_answer, question: question, title: "answer_4") }
|
||||||
|
let!(:answer5) { create(:poll_question_answer, question: question, title: "answer_5") }
|
||||||
|
|
||||||
|
background do
|
||||||
|
login_as(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question" do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
expect(page).to have_content(answer.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question vote", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
title = "vote #{answer.title}"
|
||||||
|
page.find("poll_question_#{question.id}_answers .in-favor a[title=#{title}]").click
|
||||||
|
page.find("poll_question_#{question.id}_answers .in-favor a[title=#{title}]").has_css?(".answered")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question no more vote than allowed", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.title
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
answer6 = create(:poll_question_answer, question: question, title: "answer_6")
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer6.title
|
||||||
|
expect(page.find_link(answer6.title)).not_to have_css(".answered")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question remove vote and vote again", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.question_answers.each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.title
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer1.title
|
||||||
|
end
|
||||||
|
|
||||||
|
answer6 = create(:poll_question_answer, question: question, title: "answer_6")
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer6.title
|
||||||
|
page.find_link(answer6.title).has_css?(".answered")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "add answer", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
fill_in "answer", with: "added_answer"
|
||||||
|
click_button "Add answer"
|
||||||
|
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
expect(page).to have_css("a", text: "added_answer")
|
||||||
|
click_link "added_answer"
|
||||||
|
expect(page).to have_css(".answered", text: "added_answer")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "Answers set" do
|
||||||
|
|
||||||
|
let(:user) { create(:user, :verified) }
|
||||||
|
let(:poll_current) { create(:poll, :current) }
|
||||||
|
let(:question) { create(:poll_question_answer_set_open, poll: poll_current) }
|
||||||
|
let!(:answer1) { create(:poll_question_answer, question: question, title: "answer_1") }
|
||||||
|
let!(:answer2) { create(:poll_question_answer, question: question, title: "answer_2") }
|
||||||
|
let!(:answer3) { create(:poll_question_answer, question: question, title: "answer_3") }
|
||||||
|
let!(:answer4) { create(:poll_question_answer, question: question, title: "answer_4") }
|
||||||
|
let!(:answer5) { create(:poll_question_answer, question: question, title: "answer_5") }
|
||||||
|
|
||||||
|
before do
|
||||||
|
login_as(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question" do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
expect(page.find("#poll_question_#{question.id}_answers")).to have_css("a", count: question.max_groups_answers)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "response question vote", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
question.votation_type.votation_set_answers.by_author(user).each do |answer|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
click_link answer.answer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
expect(page).to have_css(".answered", count: question.max_votes)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "add answer", :js do
|
||||||
|
visit poll_path(poll_current)
|
||||||
|
|
||||||
|
fill_in "answer", with: "added_answer"
|
||||||
|
click_button "Add answer"
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
|
expect(page).to have_content("Answer added succesfully")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
@@ -150,7 +150,9 @@ describe "Voter" do
|
|||||||
login_as user
|
login_as user
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
expect(page).not_to have_link(answer_yes.title)
|
expect(page).not_to have_link(answer_yes.title)
|
||||||
|
end
|
||||||
expect(page).to have_content "You have already participated in a physical booth. You can not participate again."
|
expect(page).to have_content "You have already participated in a physical booth. You can not participate again."
|
||||||
expect(Poll::Voter.count).to eq(1)
|
expect(Poll::Voter.count).to eq(1)
|
||||||
|
|
||||||
@@ -214,7 +216,10 @@ describe "Voter" do
|
|||||||
|
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
|
||||||
|
within("#poll_question_#{question.id}_answers") do
|
||||||
expect(page).not_to have_link(answer_yes.title)
|
expect(page).not_to have_link(answer_yes.title)
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_content "You have already participated in a physical booth. You can not participate again."
|
expect(page).to have_content "You have already participated in a physical booth. You can not participate again."
|
||||||
expect(Poll::Voter.count).to eq(1)
|
expect(Poll::Voter.count).to eq(1)
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,11 @@ describe Abilities::Administrator do
|
|||||||
it { should be_able_to(:stats, poll) }
|
it { should be_able_to(:stats, poll) }
|
||||||
it { should be_able_to(:results, poll) }
|
it { should be_able_to(:results, poll) }
|
||||||
|
|
||||||
|
it { should be_able_to(:read, Poll::Question)}
|
||||||
|
it { should be_able_to(:create, Poll::Question)}
|
||||||
|
it { should be_able_to(:update, Poll::Question)}
|
||||||
|
it { should be_able_to(:get_options_traductions, Poll::Question)}
|
||||||
|
|
||||||
it { is_expected.to be_able_to :manage, Dashboard::AdministratorTask }
|
it { is_expected.to be_able_to :manage, Dashboard::AdministratorTask }
|
||||||
it { is_expected.to be_able_to :manage, dashboard_administrator_task }
|
it { is_expected.to be_able_to :manage, dashboard_administrator_task }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -213,6 +213,18 @@ describe Abilities::Common do
|
|||||||
it { should_not be_able_to(:answer, expired_poll_question_from_all_geozones) }
|
it { should_not be_able_to(:answer, expired_poll_question_from_all_geozones) }
|
||||||
it { should_not be_able_to(:answer, expired_poll_question_from_other_geozone) }
|
it { should_not be_able_to(:answer, expired_poll_question_from_other_geozone) }
|
||||||
|
|
||||||
|
it { should be_able_to(:prioritized_answers, poll_question_from_own_geozone) }
|
||||||
|
it { should be_able_to(:prioritized_answers, poll_question_from_all_geozones) }
|
||||||
|
it { should_not be_able_to(:prioritized_answers, poll_question_from_other_geozone) }
|
||||||
|
|
||||||
|
it { should_not be_able_to(:prioritized_answers, expired_poll_question_from_own_geozone) }
|
||||||
|
it { should_not be_able_to(:prioritized_answers, expired_poll_question_from_all_geozones) }
|
||||||
|
it { should_not be_able_to(:prioritized_answers, expired_poll_question_from_other_geozone) }
|
||||||
|
|
||||||
|
context "Poll::Question" do
|
||||||
|
it { should be_able_to(:load_answers, Poll::Question) }
|
||||||
|
end
|
||||||
|
|
||||||
context "without geozone" do
|
context "without geozone" do
|
||||||
before { user.geozone = nil }
|
before { user.geozone = nil }
|
||||||
|
|
||||||
|
|||||||
131
spec/models/poll/pair_answer_spec.rb
Normal file
131
spec/models/poll/pair_answer_spec.rb
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
describe Poll::PairAnswer do
|
||||||
|
|
||||||
|
describe "validations" do
|
||||||
|
|
||||||
|
let(:pair_answer) { build(:poll_pair_answer) }
|
||||||
|
|
||||||
|
it "is valid" do
|
||||||
|
expect(pair_answer).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid wihout a question" do
|
||||||
|
pair_answer.question = nil
|
||||||
|
|
||||||
|
expect(pair_answer).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid without an author" do
|
||||||
|
pair_answer.author = nil
|
||||||
|
|
||||||
|
expect(pair_answer).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is valid if answer_left is included in the Poll::Question's question_answers list" do
|
||||||
|
question = create(:poll_question)
|
||||||
|
answer1 = create(:poll_question_answer, title: "One", question: question)
|
||||||
|
answer2 = create(:poll_question_answer, title: "Two", question: question)
|
||||||
|
answer3 = create(:poll_question_answer, title: "Three")
|
||||||
|
|
||||||
|
expect(build(:poll_pair_answer, question: question, answer_left: answer1)).to be_valid
|
||||||
|
expect(build(:poll_pair_answer, question: question, answer_left: answer2)).to be_valid
|
||||||
|
expect(build(:poll_pair_answer, question: question, answer_left: answer3)).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is valid if answer_right is included in the Poll::Question's question_answers list" do
|
||||||
|
question = create(:poll_question)
|
||||||
|
answer1 = create(:poll_question_answer, title: "One", question: question)
|
||||||
|
answer2 = create(:poll_question_answer, title: "Two", question: question)
|
||||||
|
answer3 = create(:poll_question_answer, title: "Three")
|
||||||
|
|
||||||
|
expect(build(:poll_pair_answer, question: question, answer_right: answer1)).to be_valid
|
||||||
|
expect(build(:poll_pair_answer, question: question, answer_right: answer2)).to be_valid
|
||||||
|
expect(build(:poll_pair_answer, question: question, answer_right: answer3)).not_to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "scopes" do
|
||||||
|
let(:pair_answer_1) { create(:poll_pair_answer) }
|
||||||
|
let(:pair_answer_2) { create(:poll_pair_answer) }
|
||||||
|
|
||||||
|
describe "#by_author" do
|
||||||
|
|
||||||
|
it "returns pair_answers associated to an user" do
|
||||||
|
author = pair_answer_1.author
|
||||||
|
|
||||||
|
expect(described_class.by_author(author)).to include(pair_answer_1)
|
||||||
|
expect(described_class.by_author(author)).not_to include(pair_answer_2)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#by_question" do
|
||||||
|
|
||||||
|
it "returns pair_answers associated to a question" do
|
||||||
|
question = pair_answer_1.question
|
||||||
|
|
||||||
|
expect(described_class.by_question(question)).to include(pair_answer_1)
|
||||||
|
expect(described_class.by_question(question)).not_to include(pair_answer_2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe "#generate_pair" do
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:question) { create(:poll_question) }
|
||||||
|
|
||||||
|
context "without question_answers" do
|
||||||
|
|
||||||
|
it "assigns nil value to pair_answers" do
|
||||||
|
pair_answer = described_class.generate_pair(question, user)
|
||||||
|
|
||||||
|
expect(pair_answer).to be_a Poll::PairAnswer
|
||||||
|
expect(pair_answer.question).to eq(question)
|
||||||
|
expect(pair_answer.author).to eq(user)
|
||||||
|
expect(pair_answer.answer_left).to be_nil
|
||||||
|
expect(pair_answer.answer_right).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "With question answers" do
|
||||||
|
let!(:answer1) { create(:poll_question_answer, question: question) }
|
||||||
|
|
||||||
|
it "assigns only right question if only has one question_answer" do
|
||||||
|
pair_answer = described_class.generate_pair(question, user)
|
||||||
|
|
||||||
|
expect(pair_answer).to be_a Poll::PairAnswer
|
||||||
|
expect(pair_answer.question).to eq(question)
|
||||||
|
expect(pair_answer.author).to eq(user)
|
||||||
|
expect(pair_answer.answer_left).to eq(answer1)
|
||||||
|
expect(pair_answer.answer_right).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "assigns random values if question has some question_answer" do
|
||||||
|
create(:poll_question_answer, question: question)
|
||||||
|
|
||||||
|
pair_answer = described_class.generate_pair(question, user)
|
||||||
|
|
||||||
|
expect(pair_answer).to be_a Poll::PairAnswer
|
||||||
|
expect(pair_answer.question).to eq(question)
|
||||||
|
expect(pair_answer.author).to eq(user)
|
||||||
|
expect(pair_answer.answer_left).to be_a Poll::Question::Answer
|
||||||
|
expect(pair_answer.answer_right).to be_a Poll::Question::Answer
|
||||||
|
expect(pair_answer.answer_left).not_to eq(pair_answer.answer_right)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#answers" do
|
||||||
|
let(:pair_answer) { create(:poll_pair_answer) }
|
||||||
|
|
||||||
|
it "returns and array of answers" do
|
||||||
|
expect(pair_answer.answers).to be_a Array
|
||||||
|
expect(pair_answer.answers[0]).to eq(pair_answer.answer_left)
|
||||||
|
expect(pair_answer.answers[1]).to eq(pair_answer.answer_right)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -44,4 +44,35 @@ RSpec.describe Poll::Question, type: :model do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#enum_type" do
|
||||||
|
|
||||||
|
it "returns nil if not has votation_type association" do
|
||||||
|
expect(poll_question.votation_type).to be_nil
|
||||||
|
expect(poll_question.enum_type).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns enum_type from votation_type association" do
|
||||||
|
question = create(:poll_question_answer_couples_open)
|
||||||
|
|
||||||
|
expect(question.votation_type).not_to be_nil
|
||||||
|
expect(question.enum_type).to eq("answer_couples_open")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#max_votes" do
|
||||||
|
|
||||||
|
it "returns nil if not has votation_type association" do
|
||||||
|
expect(poll_question.votation_type).to be_nil
|
||||||
|
expect(poll_question.max_votes).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns max_votes from votation_type association" do
|
||||||
|
question = create(:poll_question_answer_couples_open)
|
||||||
|
|
||||||
|
expect(question.votation_type).not_to be_nil
|
||||||
|
expect(question.max_votes).to eq(5)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user