Merge branch 'master' into aperez-admin-question-videos

This commit is contained in:
Raimond Garcia
2017-10-06 01:12:22 +02:00
committed by GitHub
42 changed files with 460 additions and 277 deletions

View File

@@ -149,6 +149,7 @@ $sidebar-active: #f4fcd0;
}
table {
.break {
word-break: break-word;
}

View File

@@ -1591,6 +1591,10 @@
.orbit-container {
height: 100% !important;
max-height: none !important;
li {
margin-bottom: 0 !important;
}
}
.orbit-slide {

View File

@@ -0,0 +1,32 @@
class Admin::Poll::Questions::Answers::ImagesController < Admin::Poll::BaseController
before_action :load_answer
def index
end
def new
@answer = ::Poll::Question::Answer.find(params[:answer_id])
end
def create
@answer = ::Poll::Question::Answer.find(params[:answer_id])
@answer.attributes = images_params
if @answer.save
redirect_to admin_answer_images_path(@answer),
notice: "Image uploaded successfully"
else
render :new
end
end
private
def images_params
params.permit(images_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy])
end
def load_answer
@answer = ::Poll::Question::Answer.find(params[:answer_id])
end
end

View File

@@ -1,7 +1,6 @@
class Admin::Poll::ShiftsController < Admin::Poll::BaseController
before_action :load_booth
before_action :load_polls
before_action :load_officer
def new
@@ -39,10 +38,6 @@ class Admin::Poll::ShiftsController < Admin::Poll::BaseController
@booth = ::Poll::Booth.find(params[:booth_id])
end
def load_polls
@polls = ::Poll.current_or_incoming
end
def load_shifts
@shifts = @booth.shifts
end

View File

@@ -3,7 +3,8 @@ class Officing::VotersController < Officing::BaseController
def new
@user = User.find(params[:id])
@polls = Poll.answerable_by(@user)
booths = current_user.poll_officer.shifts.current.vote_collection.pluck(:booth_id).uniq
@polls = Poll.answerable_by(@user).where(id: Poll::BoothAssignment.where(booth: booths).pluck(:poll_id).uniq)
end
def create

View File

@@ -25,7 +25,7 @@ module AdminHelper
end
def menu_polls?
%w[polls questions officers booths officer_assignments booth_assignments recounts results shifts].include? controller_name
%w[polls questions officers booths officer_assignments booth_assignments recounts results shifts questions answers].include? controller_name
end
def menu_profiles?

View File

@@ -0,0 +1,12 @@
module Galleryable
extend ActiveSupport::Concern
included do
has_many :images, as: :imageable, dependent: :destroy
accepts_nested_attributes_for :images, allow_destroy: true, update_only: true
def image_url(style)
image.attachment.url(style) if image && image.attachment.exists?
end
end
end

View File

@@ -19,7 +19,9 @@ class DirectUpload
if @resource_type.present? && @resource_relation.present? && (@attachment.present? || @cached_attachment.present?)
@resource = @resource_type.constantize.find_or_initialize_by(id: @resource_id)
if @resource.class.reflections[@resource_relation].macro == :has_one
if @resource.respond_to?(:images)
@relation = @resource.images.send("build", relation_attributtes)
elsif @resource.class.reflections[@resource_relation].macro == :has_one
@relation = @resource.send("build_#{resource_relation}", relation_attributtes)
else
@relation = @resource.send(@resource_relation).build(relation_attributtes)

View File

@@ -2,6 +2,7 @@ class Poll
class Officer < ActiveRecord::Base
belongs_to :user
has_many :officer_assignments, class_name: "Poll::OfficerAssignment"
has_many :shifts, class_name: "Poll::Shift"
has_many :failed_census_calls, foreign_key: :poll_officer_id
validates :user_id, presence: true, uniqueness: true

View File

@@ -1,4 +1,6 @@
class Poll::Question::Answer < ActiveRecord::Base
include Galleryable
belongs_to :question, class_name: 'Poll::Question', foreign_key: 'question_id'
has_many :videos, class_name: 'Poll::Question::Answer::Video'

View File

@@ -10,6 +10,10 @@ class Poll
enum task: { vote_collection: 0, recount_scrutiny: 1 }
scope :vote_collection, -> { where(task: 'vote_collection') }
scope :recount_scrutiny, -> { where(task: 'recount_scrutiny') }
scope :current, -> { where(date: Date.current) }
before_create :persist_data
after_create :create_officer_assignments
before_destroy :destroy_officer_assignments

View File

@@ -60,12 +60,14 @@
<span class="icon-checkmark-circle"></span>
<strong><%= t("admin.menu.title_polls") %></strong>
</a>
<ul id="polls_menu" <%= "class=is-active" if menu_polls? && controller.class.parent == Admin::Poll %>>
<ul id="polls_menu" <%= "class=is-active" if menu_polls? || controller.class.parent == Admin::Poll::Questions::Answers %>>
<li <%= "class=active" if ["polls", "officer_assignments", "booth_assignments", "recounts", "results"].include? controller_name %>>
<%= link_to t('admin.menu.polls'), admin_polls_path %>
</li>
<li <%= "class=active" if current_page?(admin_questions_path) %>>
<li <%= "class=active" if controller_name == "questions" ||
controller_name == "answers" ||
controller.class.parent == Admin::Poll::Questions::Answers %>>
<%= link_to t("admin.menu.poll_questions"), admin_questions_path %>
</li>
@@ -158,12 +160,14 @@
<span class="icon-settings"></span>
<strong><%= t("admin.menu.title_site_customization") %></strong>
</a>
<ul <%= "class=is-active" if menu_customization? %>>
<ul <%= "class=is-active" if menu_customization? &&
controller.class.parent != Admin::Poll::Questions::Answers %>>
<li <%= "class=active" if controller_name == "pages" %>>
<%= link_to t("admin.menu.site_customization.pages"), admin_site_customization_pages_path %>
</li>
<li <%= "class=active" if controller_name == "images" %>>
<li <%= "class=active" if controller_name == "images" &&
controller.class.parent != Admin::Poll::Questions::Answers %>>
<%= link_to t("admin.menu.site_customization.images"), admin_site_customization_images_path %>
</li>

View File

@@ -4,34 +4,30 @@
<%= f.hidden_field :proposal_id %>
<div class="row">
<div class="small-12 column">
<div class="small-12 medium-6 large-4">
<%= f.select :poll_id,
options_for_select(Poll.pluck(:name, :id)),
prompt: t("admin.questions.index.select_poll"),
label: t("admin.questions.new.poll_label") %>
</div>
<div class="small-12">
<div class="small-12 medium-6 large-4">
<%= f.select :poll_id,
options_for_select(Poll.pluck(:name, :id)),
prompt: t("admin.questions.index.select_poll"),
label: t("admin.questions.new.poll_label") %>
</div>
<%= f.text_field :title, maxlength: Poll::Question.title_max_length %>
<%= f.text_field :title, maxlength: Poll::Question.title_max_length %>
<div class="documents small-12">
<%= render 'documents/nested_documents', documentable: @question, f: f %>
</div>
<div class="documents small-12">
<%= render 'documents/nested_documents', documentable: @question, f: f %>
</div>
<div class="small-12">
<%= f.label :video_url, t("proposals.form.proposal_video_url") %>
<p class="help-text" id="video-url-help-text"><%= t("proposals.form.proposal_video_url_note") %></p>
<%= f.text_field :video_url, placeholder: t("proposals.form.proposal_video_url"), label: false,
aria: {describedby: "video-url-help-text"} %>
</div>
<div class="small-12">
<%= f.label :video_url, t("proposals.form.proposal_video_url") %>
<p class="help-text" id="video-url-help-text"><%= t("proposals.form.proposal_video_url_note") %></p>
<%= f.text_field :video_url, placeholder: t("proposals.form.proposal_video_url"), label: false,
aria: {describedby: "video-url-help-text"} %>
</div>
<div class="row">
<div class="actions small-12 medium-4 column margin-top">
<%= f.submit(class: "button expanded", value: t("shared.save")) %>
</div>
</div>
<div class="small-12 medium-6 large-4 margin-top">
<%= f.submit(class: "button expanded", value: t("shared.save")) %>
</div>
</div>

View File

@@ -4,21 +4,19 @@
<%= f.hidden_field :question_id, value: @question.id %>
<div class="row">
<div class="small-12 column">
<%= f.text_field :title %>
<%= f.label :title, t('admin.questions.new.form.title') %>
<%= f.text_field :title, label: false %>
<div class="ckeditor">
<%= f.cktext_area :description,
maxlength: Poll::Question.description_max_length,
ckeditor: { language: I18n.locale } %>
</div>
<div class="row">
<div class="actions small-12 medium-4 column margin-top">
<%= f.submit(class: "button expanded", value: t("shared.save")) %>
</div>
</div>
</div>
<div class="ckeditor">
<%= f.label :description, t('admin.questions.new.form.description') %>
<%= f.cktext_area :description,
maxlength: Poll::Question.description_max_length,
ckeditor: { language: I18n.locale },
label: false %>
</div>
<div class="small-12 medium-6 large-4">
<%= f.submit(class: "button expanded", value: t("shared.save")) %>
</div>
<% end %>

View File

@@ -0,0 +1,16 @@
<%= back_link_to admin_question_path(@answer.question) %>
<%= link_to t("admin.questions.answers.images.add_image"),
new_admin_answer_image_path(@answer),
class: "button hollow float-right" %>
<ul class="breadcrumbs margin-top">
<li><%= @answer.question.title %></li>
<li><%= @answer.title %></li>
</ul>
<% @answer.images.each do |image| %>
<div class="small-12 medium-4 column end">
<%= render_image(image, :large, true) if image.present? %>
</div>
<% end %>

View File

@@ -0,0 +1,13 @@
<div class="poll-question-form">
<%= form_for(Poll::Question::Answer.new,
url: admin_answer_images_path(@answer),
method: :post) do |f| %>
<%= render 'shared/errors', resource: @answer %>
<div class="images">
<%= render 'images/nested_image', imageable: @answer, f: f, image_fields: :images %>
</div>
<%= f.submit t("admin.questions.answers.images.save_image"), class: "button success" %>
<% end %>
</div>

View File

@@ -1,5 +1,10 @@
<%= back_link_to %>
<ul class="breadcrumbs margin-top">
<li><%= @question.title %></li>
<li><%= t('admin.answers.new.title') %></li>
</ul>
<h2><%= t('admin.answers.new.title') %></h2>
<div class="poll-question-answer-form">

View File

@@ -1,6 +1,6 @@
<%= back_link_to %>
<h2><%= t("admin.questions.edit.title") %></h2>
<h2 class="margin-top"><%= t("admin.questions.edit.title") %></h2>
<div class="poll-question-form">
<%= render "form", form_url: admin_question_path(@question) %>

View File

@@ -3,10 +3,8 @@
<%= link_to t('admin.questions.index.create'), new_admin_question_path,
class: "button success float-right" %>
<div class="row">
<div class="small-12 medium-6 column">
<%= render 'search' %>
</div>
<div class="small-12 medium-6">
<%= render 'search' %>
</div>
<div class="tabs-content" data-tabs-content="questions-tabs">

View File

@@ -1,6 +1,6 @@
<%= back_link_to %>
<h2><%= t("admin.questions.new.title") %></h2>
<h2 class="margin-top"><%= t("admin.questions.new.title") %></h2>
<div class="poll-question-form">
<%= render "form", form_url: admin_questions_path %>

View File

@@ -5,10 +5,19 @@
<div class="clear"></div>
<div class="row">
<div class="small-12 medium-9 column">
<strong><%= t("admin.questions.show.title") %></strong>
<h1><%= @question.title %></h1>
<div class="small-12 medium-6">
<div class="callout highlight">
<p>
<strong><%= t("admin.questions.show.title") %></strong>
<br>
<%= @question.title %>
</p>
<p>
<strong><%= t("admin.questions.show.author") %></strong>
<br>
<%= link_to @question.author.name, user_path(@question.author) %>
</p>
<% if @question.proposal.present? %>
<p>
@@ -17,60 +26,53 @@
<%= link_to @question.proposal.title, proposal_path(@question.proposal) %>
</p>
<% end %>
<p>
<strong><%= t("admin.questions.show.author") %></strong>
<br>
<%= link_to @question.author.name, user_path(@question.author) %>
</p>
<table>
<thead>
<tr>
<th>
<%= t('admin.questions.show.valid_answers') %>
</th>
<th colspan="2">
<%= link_to t("admin.questions.show.add_answer"),
new_admin_question_answer_path(@question),
class: "button hollow float-right" %>
</th>
</tr>
<tr>
<th><%= t("admin.questions.show.answers.title") %></th>
<th><%= t("admin.questions.show.answers.description") %></th>
<th><%= t("admin.questions.show.answers.videos") %></th>
</tr>
</thead>
<tbody>
<% @question.question_answers.each do |answer| %>
<tr id="<%= dom_id(answer) %>" class="poll_question_answer">
<td><%= answer.title %></td>
<td><%= answer.description %></td>
<td><%= link_to t("admin.questions.show.answers.video_list",
count: answer.videos.count),
admin_answer_videos_path(answer) %></td>
</tr>
<% end %>
</tbody>
</table>
<% if @question.video_url.present? %>
<p>
<strong><%= t("admin.questions.show.video_url") %></strong>
<br>
<a href="<%= @question.video_url %>"><%= @question.video_url %></a>
</p>
<% end %>
<% if @question.documents.any? %>
<p>
<strong><%= t("admin.questions.show.documents") %></strong>
<br>
<a href="<%= @question.documents.first.attachment.url %>"><%= @question.documents.first.title %></a>
</p>
<% end %>
</div>
</div>
<table class="margin-top">
<tr>
<th colspan="3" scope="col" class="with-button">
<%= t('admin.questions.show.valid_answers') %>
<%= link_to t("admin.questions.show.add_answer"),
new_admin_question_answer_path(@question),
class: "button hollow float-right" %>
</th>
</tr>
<tr>
<th><%= t("admin.questions.show.answers.title") %></th>
<th class="medium-7"><%= t("admin.questions.show.answers.description") %></th>
<th class="text-center"><%= t("admin.questions.show.answers.images") %></th>
<th><%= t("admin.questions.show.answers.videos") %></th>
</tr>
<% @question.question_answers.each do |answer| %>
<tr id="<%= dom_id(answer) %>" class="poll_question_answer">
<td><%= answer.title %></td>
<td><%= answer.description %></td>
<td class="text-center">
(<%= answer.images.count %>)<br>
<%= link_to t("admin.questions.show.answers.images_list"),
admin_answer_images_path(answer) %></td>
<td><%= link_to t("admin.questions.show.answers.video_list",
count: answer.videos.count),
admin_answer_videos_path(answer) %></td>
</tr>
<% end %>
</table>
<% if @question.video_url.present? %>
<p>
<strong><%= t("admin.questions.show.video_url") %></strong>
<br>
<a href="<%= @question.video_url %>"><%= @question.video_url %></a>
</p>
<% end %>
<% if @question.documents.any? %>
<p>
<strong><%= t("admin.questions.show.documents") %></strong>
<br>
<a href="<%= @question.documents.first.attachment.url %>"><%= @question.documents.first.title %></a>
</p>
<% end %>

View File

@@ -24,12 +24,12 @@
<div class="small-12 medium-3 column">
<label><%= t("admin.poll_shifts.new.date") %></label>
<%= select 'shift[date]', 'vote_collection_date',
options_for_select(shift_vote_collection_dates(@polls)),
options_for_select(shift_vote_collection_dates(@booth.polls)),
{ prompt: t("admin.poll_shifts.new.select_date"),
label: false },
class: 'js-shift-vote-collection-dates' %>
<%= select 'shift[date]', 'recount_scrutiny_date',
options_for_select(shift_recount_scrutiny_dates(@polls)),
options_for_select(shift_recount_scrutiny_dates(@booth.polls)),
{ prompt: t("admin.poll_shifts.new.select_date"),
label: false },
class: 'js-shift-recount-scrutiny-dates',

View File

@@ -2,7 +2,6 @@
<div>
<%= f.label :image, t("images.form.admin_title") %>
<%= link_to_add_association t('images.form.add_new_image'), f, :image,
force_non_association_create: true,
partial: "images/image_fields",
@@ -16,6 +15,8 @@
association_insertion_method: "append"
} %>
<%= render_image(f.object.image, :thumb, false) if f.object.image %>
<div id="nested-image">
<%= f.fields_for :image do |image_builder| %>
@@ -26,17 +27,11 @@
<%= image_builder.text_field :title, placeholder: t("images.form.title_placeholder"), label: "#{t("images.form.admin_alt_text")}" %>
<div class="attachment-actions">
<div class="small-12 column action-add attachment-errors image-attachment">
<%= render_image_attachment(image_builder, imageable, image_builder.object) %>
</div>
</div>
<div class="small-12 column">
<div class="progress-bar-placeholder"><div class="loading-bar"></div></div>
</div>
</div>
<% end %>

View File

@@ -1,17 +1,20 @@
<%= f.label :image, t("images.form.title") %>
<% image_fields ||= :image %>
<%= f.label image_fields, t("images.form.title") %>
<p class="help-text"><%= imageables_note(imageable) %></p>
<div id="nested-image">
<%= f.fields_for :image do |image_builder| %>
<%= f.fields_for image_fields do |image_builder| %>
<%= render 'images/image_fields', f: image_builder, imageable: imageable %>
<% end %>
</div>
<%= link_to_add_association t('images.form.add_new_image'), f, :image,
<%= link_to_add_association t('images.form.add_new_image'), f, image_fields,
force_non_association_create: true,
partial: "images/image_fields",
id: "new_image_link",
class: "button hollow #{"hide" if imageable.image.present?}",
class: "button hollow
#{"hide" if image_fields == :image && imageable.image.present?}",
render_options: {
locals: { imageable: imageable }
},

View File

@@ -1,5 +1,5 @@
<div class="orbit margin-bottom" role="region" aria-label="Answer 1" data-orbit data-auto-play="false">
<a data-toggle="answer_1" class="zoom-link show-for-medium-up">
<div class="orbit margin-bottom" role="region" aria-label="<%= answer.title %>" data-orbit data-auto-play="false">
<a data-toggle="answer_<%= answer.id %>" class="zoom-link show-for-medium-up">
<span class="icon-search-plus"></span>
<span class="show-for-sr"><%= t("polls.show.zoom_plus") %></span>
</a>
@@ -15,32 +15,25 @@
<span class="show-for-sr"><%= t("shared.orbit.next_slide") %></span>&#9654;&#xFE0E;
</button>
</li>
<!-- each image do -->
<li class="is-active orbit-slide">
<%= link_to "/assets/example_vertical.jpg", target: "_blank" do %>
<%= image_tag "example_horizontal.jpg", class: "orbit-image" %>
<% end %>
<!-- replace this with image title -->
<span class="orbit-caption">Image title 1</span>
<!-- /. replace this with image title -->
</li>
<!-- end -->
<li class="orbit-slide">
<%= link_to "/assets/example_vertical.jpg", target: "_blank" do %>
<%= image_tag "example_vertical.jpg", class: "orbit-image" %>
<% end %>
<span class="orbit-caption">Image title 2</span>
</li>
<% answer.images.each_with_index do |image, index| %>
<li class="orbit-slide <%= active_class(index) %>">
<%= link_to image.attachment.url(:original), target: "_blank" do %>
<%= image_tag image.attachment.url(:medium),
class: "orbit-image",
alt: image.title %>
<% end %>
<span class="orbit-caption"><%= image.title %></span>
</li>
<% end %>
</ul>
<nav class="orbit-bullets">
<button class="is-active" data-slide="0">
<!-- replace this with image title -->
<span class="show-for-sr">Image title 1</span>
<!-- /. replace this with image title -->
</button>
<button data-slide="1">
<span class="show-for-sr">Image title 2</span>
</button>
<% answer.images.each_with_index do |image, index| %>
<button class="<%= active_class(index) %>" data-slide="<%= index %>">
<span class="show-for-sr"><%= image.title %></span>
</button>
<% end %>
</nav>
</div>

View File

@@ -1,37 +1,9 @@
<% poll_group.each do |poll| %>
<div class="poll with-image">
<% if poll.answerable_by?(current_user) && poll.votable_by?(current_user) %>
<%= link_to poll,
class: "icon-poll-answer can-answer",
title: t("polls.index.can_answer") do %>
<span class="show-for-sr">
<%= t("polls.index.can_answer") %>
</span>
<% end %>
<% elsif current_user.nil? %>
<%= link_to new_user_session_path,
class: "icon-poll-answer not-logged-in",
title: t("polls.index.cant_answer_not_logged_in") do %>
<span class="show-for-sr">
<%= t("polls.index.cant_answer_not_logged_in") %>
</span>
<% end %>
<% elsif current_user.unverified? %>
<%= link_to verification_path,
class: "icon-poll-answer unverified",
title: t("polls.index.cant_answer_verify") do %>
<span class="show-for-sr">
<%= t("polls.index.cant_answer_verify") %>
</span>
<% end %>
<% elsif !poll.votable_by?(current_user) %>
<% if user_signed_in? && !poll.votable_by?(current_user) %>
<div class="icon-poll-answer already-answer" title="<%= t("polls.index.already_answer") %>">
<span class="show-for-sr"><%= t("polls.index.already_answer") %></span>
</div>
<% else %>
<div class="icon-poll-answer cant-answer" title="<%= t("polls.index.cant_answer") %>">
<span class="show-for-sr"><%= t("polls.index.cant_answer") %></span>
</div>
<% end %>
<div class="row" data-equalizer>
<div class="small-12 medium-3 column">

View File

@@ -62,27 +62,23 @@
<div class="expanded poll-more-info-answers">
<div class="row padding">
<!-- EACH ANSWER DO -->
<div class="small-12 medium-6 column end" id="answer_1" data-toggler=".medium-6">
<% @poll.questions.map(&:question_answers).flatten.each do |answer| %>
<div class="small-12 medium-6 column end" id="answer_<%= answer.id %>"
data-toggler=".medium-6">
<!-- REPLACE THIS WITH answer title -->
<h3>Answer 1</h3>
<!-- /. REPLACE THIS WITH answer title -->
<h3><%= answer.title %></h3>
<!-- If Answer have images render this:
Maybe something like <%# render "gallery", gallery: answer.gallery %> -->
<%= render "gallery" %>
<!-- If Answer have images render this -->
<% if answer.images.any? %>
<%= render "gallery", answer: answer %>
<% end %>
<div class="margin-top">
<%= safe_html_with_links simple_format(answer.description) %>
</div>
<!-- REPLACE THIS WITH answer description -->
<div class="margin-top">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<!-- /. REPLACE THIS WITH answer description -->
</div>
<% end %>
</div>
<!-- /. EACH ANSWER DO -->
</div>
</div>

View File

@@ -1,25 +1,28 @@
staging:
deploy_to: "/var/www/consul"
ssh_port: 21
server: staging.consul.es
user: xxxxx
full_app_name: consul
server_name: staging.consul.es
db_server: postgre.consul.es
server: "staging.consul.es"
db_server: "postgre.consul.es"
user: "xxxxx"
server_name: "staging.consul.es"
full_app_name: "consul"
preproduction:
deploy_to: "/var/www/consul"
ssh_port: 2222
server1: xxx.xxx.xxx.xxx
server2: xxx.xxx.xxx.xxx
user: xxxxx
full_app_name: consul
db_server: xxx.xxx.xxx.xxx
user: xxxxx
server_name: pre.consul.es
full_app_name: "consul"
production:
deploy_to: "/var/www/consul"
ssh_port: 2222
server: xxx.xxx.xxx.xxx
user: xxxxx
full_app_name: consul
ssh_port: 22
server1: xxx.xxx.xxx.xxx
server2: xxx.xxx.xxx.xxx
db_server: xxx.xxx.xxx.xxx
user: "deploy"
server_name: "consul.es"
full_app_name: "consul"

View File

@@ -587,6 +587,13 @@ en:
new:
title: "Create Question"
poll_label: "Poll"
form:
title: Title
description: Description
answers:
images:
add_image: "Add image"
save_image: "Save image"
show:
proposal: Original proposal
author: Author
@@ -600,6 +607,8 @@ en:
description: Description
videos: Videos
video_list: Video list (%{count})
images: Images
images_list: Images list
answers:
new:
title: New answer

View File

@@ -180,6 +180,7 @@ en:
spending_proposal: Spending proposal
budget/investment: Investment
poll/shift: Shift
poll/question/answer: Answer
user: Account
verification/sms: phone
signature_sheet: Signature sheet
@@ -466,10 +467,6 @@ en:
no_geozone_restricted: "All city"
geozone_restricted: "Districts"
geozone_info: "Can participate people in the Census of: "
can_answer: "You can participate in this poll!"
cant_answer: "This poll is not available on your geozone"
cant_answer_not_logged_in: "You must sign in or sign up to participate"
cant_answer_verify: "You must verify your account in order to answer"
already_answer: "You already have participated in this poll"
section_header:
icon_alt: Voting icon

View File

@@ -587,6 +587,13 @@ es:
new:
title: "Crear pregunta ciudadana"
poll_label: "Votación"
form:
title: Título
description: Descripción
answers:
images:
add_image: "Añadir imagen"
save_image: "Guardar imagen"
show:
proposal: Propuesta ciudadana original
author: Autor
@@ -601,6 +608,8 @@ es:
description: Descripción
videos: Vídeos
video_list: Lista de vídeos (%{count})
images: Imágenes
images_list: Lista de imágenes
answers:
new:
title: "Nueva respuesta"

View File

@@ -180,6 +180,7 @@ es:
spending_proposal: la propuesta de gasto
budget/investment: la propuesta de inversión
poll/shift: el turno
poll/question/answer: la respuesta
user: la cuenta
verification/sms: el teléfono
signature_sheet: la hoja de firmas
@@ -466,10 +467,6 @@ es:
no_geozone_restricted: "Toda la ciudad"
geozone_restricted: "Distritos"
geozone_info: "Pueden participar las personas empadronadas en: "
can_answer: "¡Puedes participar en esta votación!"
cant_answer: "Esta votación no está disponible en tu zona"
cant_answer_not_logged_in: "Necesitas iniciar sesión o registrarte para participar"
cant_answer_verify: "Por favor verifica tu cuenta para poder responder"
already_answer: "Ya has participado en esta votación"
section_header:
icon_alt: Icono de Votaciones

View File

@@ -301,7 +301,8 @@ Rails.application.routes.draw do
end
resources :questions, shallow: true do
resources :answers, only: [:new, :create], controller: 'questions/answers' do
resources :answers, only: [:new, :create], controller: 'questions/answers', shallow: true do
resources :images, controller: 'questions/answers/images'
resources :videos, controller: 'questions/answers/videos'
end
end

View File

@@ -1,46 +1,74 @@
default: &default
secret_key_base: "56792feef405a59b18ea7db57b4777e855103882b926413d4afdfb8c0ea8aa86ea6649da4e729c5f5ae324c0ab9338f789174cf48c544173bc18fdc3b14262e4"
secret_key_base: 56792feef405a59b18ea7db57b4777e855103882b926413d4afdfb8c0ea8aa86ea6649da4e729c5f5ae324c0ab9338f789174cf48c544173bc18fdc3b14262e4
maps: &maps
map_tiles_provider: "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
map_tiles_provider_attribution: "&copy; <a href=\"http://osm.org/copyright\">OpenStreetMap</a> contributors"
development:
<<: *default
test:
<<: *default
staging:
server_name: ""
<<: *default
production: &production
secret_key_base: "817232feef405a59b18ea7db57b4777e855103882b926413d4afdfb8c0ea8aa86ea6649da4e729c5f5ae324c0ab9338f789174cf48c544173bc18fdc3b14262e4"
apis: &apis
census_api_end_point: ""
census_api_institution_code: ""
census_api_portal_name: ""
census_api_user_code: ""
sms_end_point: ""
sms_username: ""
sms_password: ""
http_basic_auth: &http_basic_auth
http_basic_auth: true
development:
http_basic_username: "dev"
http_basic_password: "pass"
<<: *default
test:
<<: *default
<<: *maps
staging:
secret_key_base: ""
server_name: ""
rollbar_server_token: ""
http_basic_username: ""
http_basic_password: ""
managers_url: ""
managers_application_key: ""
<<: *default
<<: *maps
<<: *apis
preproduction:
secret_key_base: ""
server_name: ""
rollbar_server_token: ""
http_basic_username: ""
http_basic_password: ""
managers_url: ""
managers_application_key: ""
twitter_key: ""
twitter_secret: ""
facebook_key: ""
facebook_secret: ""
google_oauth2_key: ""
google_oauth2_secret: ""
<<: *maps
<<: *apis
production:
secret_key_base: ""
server_name: ""
rollbar_server_token: ""
server_name: ""
map_tiles_provider: "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
map_tiles_provider_attribution: "&copy; <a href=\"http://osm.org/copyright\">OpenStreetMap</a> contributors"
preproduction:
server_name: ""
<<: *production
http_basic_username: ""
http_basic_password: ""
managers_url: ""
managers_application_key: ""
twitter_key: ""
twitter_secret: ""
facebook_key: ""
facebook_secret: ""
google_oauth2_key: ""
google_oauth2_secret: ""
<<: *maps
<<: *apis

View File

@@ -70,14 +70,18 @@ feature 'Admin polls' do
scenario "Edit" do
poll = create(:poll)
create(:image, imageable: poll)
visit admin_poll_path(poll)
click_link "Edit"
end_date = 1.year.from_now
expect(page).to have_css("img[alt='#{poll.image.title}']")
fill_in "poll_name", with: "Next Poll"
fill_in 'poll_ends_at', with: end_date.strftime("%d/%m/%Y")
click_button "Update poll"
expect(page).to have_content "Poll updated successfully"

View File

@@ -0,0 +1,14 @@
require 'rails_helper'
feature 'Images' do
background do
admin = create(:administrator)
login_as(admin.user)
end
pending "Index"
pending "Create"
pending "Destroy"
end

View File

@@ -31,6 +31,8 @@ feature 'Admin shifts' do
end
scenario "Create Vote Collection Shift and Recount & Scrutiny Shift on same date", :js do
create(:poll)
create(:poll, :incoming)
poll = create(:poll, :current)
booth = create(:poll_booth)
assignment = create(:poll_booth_assignment, poll: poll, booth: booth)

View File

@@ -2,16 +2,19 @@ require 'rails_helper'
feature 'Voters' do
let(:poll) { create(:poll, :current) }
let(:booth) { create(:poll_booth) }
let(:officer) { create(:poll_officer) }
background do
login_as(officer.user)
create(:geozone, :in_census)
create(:poll_shift, officer: officer, booth: booth, date: Date.current, task: :vote_collection)
booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth)
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment)
end
scenario "Can vote", :js do
poll = create(:poll_officer_assignment, officer: officer).booth_assignment.poll
visit new_officing_residence_path
officing_verify_residence
@@ -31,15 +34,16 @@ feature 'Voters' do
end
scenario "Already voted", :js do
poll1 = create(:poll)
poll2 = create(:poll)
poll2 = create(:poll, :current)
booth_assignment = create(:poll_booth_assignment, poll: poll2, booth: booth)
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment)
user = create(:user, :level_two)
voter = create(:poll_voter, poll: poll1, user: user)
voter = create(:poll_voter, poll: poll, user: user)
visit new_officing_voter_path(id: voter.user.id)
within("#poll_#{poll1.id}") do
within("#poll_#{poll.id}") do
expect(page).to have_content "Has already participated in this poll"
expect(page).to_not have_button "Confirm vote"
end
@@ -52,7 +56,6 @@ feature 'Voters' do
scenario "Had already verified his residence, but is not level 2 yet", :js do
user = create(:user, residence_verified_at: Time.current, document_type: "1", document_number: "12345678Z")
expect(user).to_not be_level_two_verified
poll = create(:poll_officer_assignment, officer: officer).booth_assignment.poll
visit new_officing_residence_path
officing_verify_residence
@@ -61,6 +64,37 @@ feature 'Voters' do
expect(page).to have_content poll.name
end
#Fix and use answerable_by(user)
xscenario "Display only answerable polls"
scenario "Display only current polls on which officer has a voting shift today, and user can answer", :js do
poll_current = create(:poll, :current)
second_booth = create(:poll_booth)
booth_assignment = create(:poll_booth_assignment, poll: poll_current, booth: second_booth)
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment)
create(:poll_shift, officer: officer, booth: second_booth, date: Date.current, task: :recount_scrutiny)
create(:poll_shift, officer: officer, booth: second_booth, date: Date.tomorrow, task: :vote_collection)
poll_expired = create(:poll, :expired)
create(:poll_officer_assignment, officer: officer, booth_assignment: create(:poll_booth_assignment, poll: poll_expired, booth: booth))
poll_incoming = create(:poll, :incoming)
create(:poll_officer_assignment, officer: officer, booth_assignment: create(:poll_booth_assignment, poll: poll_incoming, booth: booth))
poll_geozone_restricted_in = create(:poll, :current, geozone_restricted: true, geozones: [Geozone.first])
booth_assignment = create(:poll_booth_assignment, poll: poll_geozone_restricted_in, booth: booth)
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment)
poll_geozone_restricted_out = create(:poll, :current, geozone_restricted: true, geozones: [create(:geozone, census_code: "02")])
booth_assignment = create(:poll_booth_assignment, poll: poll_geozone_restricted_out, booth: booth)
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment)
visit new_officing_residence_path
officing_verify_residence
expect(page).to have_content "Polls"
expect(page).to have_content poll.name
expect(page).not_to have_content poll_current.name
expect(page).not_to have_content poll_expired.name
expect(page).not_to have_content poll_incoming.name
expect(page).to have_content poll_geozone_restricted_in.name
expect(page).not_to have_content poll_geozone_restricted_out.name
end
end

View File

@@ -33,9 +33,25 @@ feature 'Answers' do
click_button "Save"
expect(page).to have_content "Answer created successfully"
expect(page).to have_css(".poll_question_answer", count: 1)
expect(page).to have_content "¿Would you like to reform Central Park?"
expect(page).to have_content "Adding more trees, creating a play area..."
end
pending "Update"
pending "Destroy"
context "Gallery" do
it_behaves_like "nested imageable",
"poll_question_answer",
"new_admin_answer_image_path",
{ "answer_id": "id" },
nil,
"Save image",
"Image uploaded successfully",
true
end
end

View File

@@ -6,11 +6,15 @@ feature 'Polls' do
scenario 'Polls can be listed' do
polls = create_list(:poll, 3)
create(:image, imageable: polls[0])
create(:image, imageable: polls[1])
create(:image, imageable: polls[2])
visit polls_path
polls.each do |poll|
expect(page).to have_content(poll.name)
expect(page).to have_css("img[alt='#{poll.image.title}']")
expect(page).to have_link("Participate in this poll")
end
end
@@ -59,7 +63,7 @@ feature 'Polls' do
context 'Show' do
let(:geozone) { create(:geozone) }
let(:poll) { create(:poll) }
let(:poll) { create(:poll, summary: "Summary", description: "Description") }
scenario 'Lists questions from proposals as well as regular ones' do
normal_question = create(:poll_question, poll: poll)
@@ -67,6 +71,8 @@ feature 'Polls' do
visit poll_path(poll)
expect(page).to have_content(poll.name)
expect(page).to have_content(poll.summary)
expect(page).to have_content(poll.description)
expect(page).to have_content(normal_question.title)
expect(page).to have_content(proposal_question.title)

View File

@@ -4,11 +4,24 @@ feature "Voter" do
context "Origin" do
scenario "Voting via web", :js do
let(:poll) { create(:poll, :current) }
let(:booth) { create(:poll_booth) }
let(:officer) { create(:poll_officer) }
background do
create(:geozone, :in_census)
create(:poll_shift, officer: officer, booth: booth, date: Date.current, task: :vote_collection)
booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth)
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment)
end
scenario "Voting via web - Standard", :js do
poll = create(:poll)
question = create(:poll_question, poll: poll)
answer1 = create(:poll_question_answer, question: question, title: 'Yes')
answer2 = create(:poll_question_answer, question: question, title: 'No')
user = create(:user, :level_two)
login_as user
@@ -24,14 +37,7 @@ feature "Voter" do
end
scenario "Voting in booth", :js do
user = create(:user, :in_census)
create(:geozone, :in_census)
poll = create(:poll)
officer = create(:poll_officer)
ba = create(:poll_booth_assignment, poll: poll)
create(:poll_officer_assignment, officer: officer, booth_assignment: ba)
user = create(:user, :in_census)
login_through_form_as_officer(officer.user)
@@ -50,14 +56,12 @@ feature "Voter" do
context "Trying to vote the same poll in booth and web" do
let(:poll) { create(:poll) }
let(:question) { create(:poll_question, poll: poll) }
let!(:answer1) { create(:poll_question_answer, question: question, title: 'Yes') }
let!(:answer2) { create(:poll_question_answer, question: question, title: 'No') }
let!(:user) { create(:user, :in_census) }
let(:officer) { create(:poll_officer) }
let(:ba) { create(:poll_booth_assignment, poll: poll) }
let!(:oa) { create(:poll_officer_assignment, officer: officer, booth_assignment: ba) }
let!(:user) { create(:user, :in_census) }
scenario "Trying to vote in web and then in booth", :js do
login_as user

View File

@@ -1,21 +1,23 @@
shared_examples "nested imageable" do |imageable_factory_name, path, imageable_path_arguments, fill_resource_method_name, submit_button, imageable_success_notice|
shared_examples "nested imageable" do |imageable_factory_name, path, imageable_path_arguments, fill_resource_method_name, submit_button, imageable_success_notice, has_many_images=false|
include ActionView::Helpers
include ImagesHelper
include ImageablesHelper
let!(:administrator) { create(:user) }
let!(:user) { create(:user, :level_two) }
let!(:administrator) { create(:administrator, user: user) }
let!(:arguments) { {} }
let!(:imageable) { create(imageable_factory_name, author: user) }
let!(:imageable) { create(imageable_factory_name) }
before do
create(:administrator, user: administrator)
if imageable_path_arguments
imageable_path_arguments.each do |argument_name, path_to_value|
arguments.merge!("#{argument_name}": imageable.send(path_to_value))
end
end
if imageable.respond_to?(:author)
imageable.update(author: user)
end
end
describe "at #{path}" do
@@ -66,7 +68,11 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
image_input = find(".image").find("input[type=file]", visible: false)
attach_file(image_input[:id], "spec/fixtures/files/clippy.jpg", make_visible: true)
expect(find("##{imageable_factory_name}_image_attributes_title").value).to eq "Title"
if has_many_images
expect(find("input[id$='_title']").value).to eq "Title"
else
expect(find("##{imageable_factory_name}_image_attributes_title").value).to eq "Title"
end
end
scenario "Should update loading bar style after valid file upload", :js do
@@ -78,7 +84,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
expect(page).to have_selector ".loading-bar.complete"
end
scenario "Should update loading bar style after unvalid file upload", :js do
scenario "Should update loading bar style after invalid file upload", :js do
login_as user
visit send(path, arguments)
@@ -112,8 +118,12 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
click_link "Add image"
click_on submit_button
within "#nested-image .image" do
expect(page).to have_content("can't be blank", count: 2)
if has_many_images
#Pending. Review soon and test
else
within "#nested-image .image" do
expect(page).to have_content("can't be blank", count: 2)
end
end
end
@@ -159,8 +169,12 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
click_on submit_button
imageable_redirected_to_resource_show_or_navigate_to
expect(page).to have_selector "figure img"
expect(page).to have_selector "figure figcaption"
if has_many_images
#Pending. Review soon and test
else
expect(page).to have_selector "figure img"
expect(page).to have_selector "figure figcaption"
end
end
if path.include? "edit"