Merge branch 'master' into iagirre-remove-documents-questions

This commit is contained in:
Raimond Garcia
2017-10-06 01:02:56 +02:00
committed by GitHub
29 changed files with 294 additions and 186 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

@@ -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

@@ -1,4 +1,6 @@
class Poll::Question::Answer < ActiveRecord::Base
include Galleryable
belongs_to :question, class_name: 'Poll::Question', foreign_key: 'question_id'
validates :title, presence: true

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,9 +4,7 @@
<%= f.hidden_field :proposal_id %>
<div class="row">
<div class="small-12 column">
<div class="small-12">
<div class="small-12 medium-6 large-4">
<%= f.select :poll_id,
options_for_select(Poll.pluck(:name, :id)),
@@ -23,12 +21,9 @@
aria: {describedby: "video-url-help-text"} %>
</div>
<div class="row">
<div class="actions small-12 medium-4 column margin-top">
<div class="small-12 medium-6 large-4 margin-top">
<%= f.submit(class: "button expanded", value: t("shared.save")) %>
</div>
</div>
</div>
</div>
<% end %>

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.label :description, t('admin.questions.new.form.description') %>
<%= f.cktext_area :description,
maxlength: Poll::Question.description_max_length,
ckeditor: { language: I18n.locale } %>
ckeditor: { language: I18n.locale },
label: false %>
</div>
<div class="row">
<div class="actions small-12 medium-4 column margin-top">
<div class="small-12 medium-6 large-4">
<%= f.submit(class: "button expanded", value: t("shared.save")) %>
</div>
</div>
</div>
</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">
<div class="small-12 medium-6">
<%= render 'search' %>
</div>
</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">
<div class="small-12 medium-6">
<div class="callout highlight">
<p>
<strong><%= t("admin.questions.show.title") %></strong>
<h1><%= @question.title %></h1>
<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,19 +26,13 @@
<%= link_to @question.proposal.title, proposal_path(@question.proposal) %>
</p>
<% end %>
</div>
</div>
<p>
<strong><%= t("admin.questions.show.author") %></strong>
<br>
<%= link_to @question.author.name, user_path(@question.author) %>
</p>
<table>
<table class="margin-top">
<tr>
<th colspan="1" scope="colgroup">
<th colspan="3" scope="col" class="with-button">
<%= t('admin.questions.show.valid_answers') %>
</th>
<th colspan="1" scope="colgroup">
<%= link_to t("admin.questions.show.add_answer"),
new_admin_question_answer_path(@question),
class: "button hollow float-right" %>
@@ -37,24 +40,28 @@
</tr>
<tr>
<th scope="col"><%= t("admin.questions.show.answers.title") %></th>
<th scope="col"><%= t("admin.questions.show.answers.description") %></th>
<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>
</tr>
<% @question.question_answers.each do |answer| %>
<tr id="<%= dom_id(answer) %>" class="poll_question_answer">
<th scope="col"><%= answer.title %></th>
<th scope="col"><%= answer.description %></th>
<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>
</tr>
<% end %>
</table>
</table>
<% if @question.video_url.present? %>
<% 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 %>
</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" %>
<% 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 %>
<!-- replace this with image title -->
<span class="orbit-caption">Image title 1</span>
<!-- /. replace this with image title -->
<span class="orbit-caption"><%= image.title %></span>
</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>
</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>
<% 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 %>
<!-- 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>
<%= safe_html_with_links simple_format(answer.description) %>
</div>
<!-- /. REPLACE THIS WITH answer description -->
</div>
<% end %>
</div>
<!-- /. EACH ANSWER DO -->
</div>
</div>

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
@@ -597,6 +604,8 @@ en:
answers:
title: Answer
description: Description
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
@@ -599,6 +606,8 @@ es:
answers:
title: Respuesta
description: Descripción
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,10 @@ Rails.application.routes.draw do
end
resources :questions do
resources :answers, only: [:new, :create], controller: 'questions/answers'
resources :answers, only: [:new, :create], controller: 'questions/answers', shallow: true do
resources :images, controller: 'questions/answers/images'
end
end
end

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

@@ -42,4 +42,16 @@ feature 'Answers' do
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

@@ -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,8 +68,12 @@ 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)
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
login_as user
@@ -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,10 +118,14 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
click_link "Add image"
click_on submit_button
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
scenario "Should remove nested image after valid file upload and click on remove button", :js do
login_as user
@@ -159,9 +169,13 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
click_on submit_button
imageable_redirected_to_resource_show_or_navigate_to
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"