Merge branch 'master' into mlucena-poll-comments
This commit is contained in:
@@ -70,6 +70,7 @@
|
||||
//= require polls_admin
|
||||
//= require leaflet
|
||||
//= require map
|
||||
//= require polls
|
||||
|
||||
var initialize_modules = function() {
|
||||
App.Comments.initialize();
|
||||
@@ -108,6 +109,7 @@ var initialize_modules = function() {
|
||||
App.TagAutocomplete.initialize();
|
||||
App.PollsAdmin.initialize();
|
||||
App.Map.initialize();
|
||||
App.Polls.initialize();
|
||||
};
|
||||
|
||||
$(function(){
|
||||
|
||||
28
app/assets/javascripts/polls.js.coffee
Normal file
28
app/assets/javascripts/polls.js.coffee
Normal file
@@ -0,0 +1,28 @@
|
||||
App.Polls =
|
||||
generateToken: ->
|
||||
token = ''
|
||||
rand = ''
|
||||
for n in [0..5]
|
||||
rand = Math.random().toString(36).substr(2) # remove `0.`
|
||||
token = token + rand;
|
||||
|
||||
token = token.substring(0, 64)
|
||||
return token
|
||||
|
||||
replaceToken: ->
|
||||
for link in $('.js-question-answer')
|
||||
token_param = link.search.slice(-6)
|
||||
if token_param == "token="
|
||||
link.href = link.href + @token
|
||||
|
||||
initialize: ->
|
||||
@token = App.Polls.generateToken()
|
||||
App.Polls.replaceToken()
|
||||
|
||||
$(".js-question-answer").on
|
||||
click: =>
|
||||
token_message = $(".js-token-message")
|
||||
if !token_message.is(':visible')
|
||||
token_message.html(token_message.html() + "<br><strong>" + @token + "</strong>");
|
||||
token_message.show()
|
||||
false
|
||||
@@ -335,8 +335,16 @@
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.callout.proposal-retired {
|
||||
font-size: $base-font-size;
|
||||
.callout {
|
||||
&.token-message {
|
||||
background-color: #fff;
|
||||
border-color: $info-border;
|
||||
color: $color-info;
|
||||
}
|
||||
|
||||
&.proposal-retired {
|
||||
font-size: $base-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
.social-share-full .social-share-button {
|
||||
@@ -1574,7 +1582,23 @@
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
.column:nth-child(odd) {
|
||||
border-right: 1px solid #eee;
|
||||
border-right: 2px solid $text;
|
||||
}
|
||||
|
||||
.answer-divider {
|
||||
border-bottom: 2px solid $text;
|
||||
border-right: 0 !important;
|
||||
margin-bottom: $line-height;
|
||||
padding-bottom: $line-height;
|
||||
}
|
||||
|
||||
.answer-description {
|
||||
height: 100%;
|
||||
|
||||
&.short {
|
||||
height: $line-height * 12;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1599,6 +1623,10 @@
|
||||
|
||||
.orbit-slide {
|
||||
max-height: none !important;
|
||||
|
||||
img {
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
}
|
||||
|
||||
.orbit-caption {
|
||||
@@ -1606,6 +1634,11 @@
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.orbit-next,
|
||||
.orbit-previous {
|
||||
background: rgba(34, 34, 34, 0.25);
|
||||
}
|
||||
|
||||
.zoom-link {
|
||||
background: #fff;
|
||||
border-radius: rem-calc(48);
|
||||
@@ -1638,7 +1671,10 @@
|
||||
.poll {
|
||||
|
||||
&.with-image {
|
||||
padding: 0 $line-height / 2 0 0;
|
||||
|
||||
@include breakpoint(medium) {
|
||||
padding: 0 $line-height / 2 0 0;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
@@ -1769,6 +1805,10 @@
|
||||
margin-right: $line-height / 4;
|
||||
min-width: rem-calc(168);
|
||||
|
||||
@include breakpoint(medium down) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.answered {
|
||||
background: #f4f8ec;
|
||||
border: 2px solid #92ba48;
|
||||
|
||||
@@ -23,7 +23,8 @@ class Admin::Poll::Questions::Answers::ImagesController < Admin::Poll::BaseContr
|
||||
private
|
||||
|
||||
def images_params
|
||||
params.permit(images_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy])
|
||||
params.require(:poll_question_answer).permit(:answer_id,
|
||||
images_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy])
|
||||
end
|
||||
|
||||
def load_answer
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
class Admin::Poll::Questions::Answers::VideosController < Admin::Poll::BaseController
|
||||
before_action :load_answer, only: [:index, :new, :create]
|
||||
before_action :load_video, only: [:edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
end
|
||||
|
||||
def new
|
||||
@video = ::Poll::Question::Answer::Video.new
|
||||
end
|
||||
|
||||
def create
|
||||
@video = ::Poll::Question::Answer::Video.new(video_params)
|
||||
|
||||
if @video.save
|
||||
redirect_to admin_answer_videos_path(@answer),
|
||||
notice: t("flash.actions.create.poll_question_answer_video")
|
||||
else
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
if @video.update(video_params)
|
||||
redirect_to admin_answer_videos_path(@video.answer_id),
|
||||
notice: t("flash.actions.save_changes.notice")
|
||||
else
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @video.destroy
|
||||
notice = t("flash.actions.destroy.poll_question_answer_video")
|
||||
else
|
||||
notice = t("flash.actions.destroy.error")
|
||||
end
|
||||
redirect_to :back, notice: notice
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def video_params
|
||||
params.require(:poll_question_answer_video).permit(:title, :url, :answer_id)
|
||||
end
|
||||
|
||||
def load_answer
|
||||
@answer = ::Poll::Question::Answer.find(params[:answer_id])
|
||||
end
|
||||
|
||||
def load_video
|
||||
@video = ::Poll::Question::Answer::Video.find(params[:id])
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,5 @@
|
||||
class Admin::Poll::Questions::AnswersController < Admin::Poll::BaseController
|
||||
before_action :load_question
|
||||
before_action :load_answer, only: [:show, :edit, :update, :documents]
|
||||
|
||||
load_and_authorize_resource :question, class: "::Poll::Question"
|
||||
|
||||
@@ -11,20 +11,42 @@ class Admin::Poll::Questions::AnswersController < Admin::Poll::BaseController
|
||||
@answer = ::Poll::Question::Answer.new(answer_params)
|
||||
|
||||
if @answer.save
|
||||
redirect_to admin_question_path(@question),
|
||||
redirect_to admin_question_path(@answer.question),
|
||||
notice: t("flash.actions.create.poll_question_answer")
|
||||
else
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
if @answer.update(answer_params)
|
||||
redirect_to admin_question_path(@answer.question),
|
||||
notice: t("flash.actions.save_changes.notice")
|
||||
else
|
||||
redirect_to :back
|
||||
end
|
||||
end
|
||||
|
||||
def documents
|
||||
@documents = @answer.documents
|
||||
|
||||
render 'admin/poll/questions/answers/documents'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def answer_params
|
||||
params.require(:poll_question_answer).permit(:title, :description, :question_id)
|
||||
params.require(:poll_question_answer).permit(:title, :description, :question_id, documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy])
|
||||
end
|
||||
|
||||
def load_question
|
||||
@question = ::Poll::Question.find(params[:question_id])
|
||||
def load_answer
|
||||
@answer = ::Poll::Question::Answer.find(params[:id] || params[:answer_id])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -56,8 +56,7 @@ class Admin::Poll::QuestionsController < Admin::Poll::BaseController
|
||||
private
|
||||
|
||||
def question_params
|
||||
params.require(:poll_question).permit(:poll_id, :title, :question, :proposal_id, :valid_answers, :video_url,
|
||||
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy])
|
||||
params.require(:poll_question).permit(:poll_id, :title, :question, :proposal_id, :valid_answers, :video_url)
|
||||
end
|
||||
|
||||
def search_params
|
||||
|
||||
@@ -7,10 +7,12 @@ class Polls::QuestionsController < ApplicationController
|
||||
|
||||
def answer
|
||||
answer = @question.answers.find_or_initialize_by(author: current_user)
|
||||
token = params[:token]
|
||||
|
||||
answer.answer = params[:answer]
|
||||
answer.touch if answer.persisted?
|
||||
answer.save!
|
||||
answer.record_voter_participation
|
||||
answer.record_voter_participation(token)
|
||||
|
||||
@answers_by_question_id = { @question.id => params[:answer] }
|
||||
end
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
class PollsController < ApplicationController
|
||||
include CommentableActions
|
||||
|
||||
include PollsHelper
|
||||
|
||||
load_and_authorize_resource
|
||||
|
||||
has_filters %w{current expired incoming}
|
||||
@@ -14,15 +16,16 @@ class PollsController < ApplicationController
|
||||
|
||||
def show
|
||||
@questions = @poll.questions.for_render.sort_for_list
|
||||
|
||||
@commentable = @poll
|
||||
@comment_tree = CommentTree.new(@commentable, params[:page], @current_order)
|
||||
|
||||
@token = poll_voter_token(@poll, current_user)
|
||||
|
||||
@answers_by_question_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
|
||||
end
|
||||
|
||||
@commentable = @poll
|
||||
@comment_tree = CommentTree.new(@commentable, params[:page], @current_order)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -41,4 +41,12 @@ module PollsHelper
|
||||
booth.name + location
|
||||
end
|
||||
|
||||
def poll_voter_token(poll, user)
|
||||
Poll::Voter.where(poll: poll, user: user, origin: "web").first&.token || ''
|
||||
end
|
||||
|
||||
def voted_before_sign_in(question)
|
||||
question.answers.where(author: current_user).any? { |vote| current_user.current_sign_in_at >= vote.updated_at }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -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.respond_to?(:images)
|
||||
#Refactor
|
||||
if @resource.respond_to?(:images) &&
|
||||
((@attachment.present? && !@attachment.content_type.match(/pdf/)) || @cached_attachment.present?)
|
||||
@relation = @resource.images.send("build", relation_attributtes)
|
||||
elsif @resource.class.reflections[@resource_relation].macro == :has_one
|
||||
@relation = @resource.send("build_#{resource_relation}", relation_attributtes)
|
||||
|
||||
@@ -16,7 +16,7 @@ class Poll::Answer < ActiveRecord::Base
|
||||
scope :by_author, ->(author_id) { where(author_id: author_id) }
|
||||
scope :by_question, ->(question_id) { where(question_id: question_id) }
|
||||
|
||||
def record_voter_participation
|
||||
Poll::Voter.find_or_create_by!(user: author, poll: poll, origin: "web")
|
||||
def record_voter_participation(token)
|
||||
Poll::Voter.find_or_create_by(user: author, poll: poll, origin: "web", token: token)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
class Poll::Question < ActiveRecord::Base
|
||||
include Measurable
|
||||
include Searchable
|
||||
include Documentable
|
||||
documentable max_documents_allowed: 1,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
accepts_nested_attributes_for :documents, allow_destroy: true
|
||||
|
||||
acts_as_paranoid column: :hidden_at
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
class Poll::Question::Answer < ActiveRecord::Base
|
||||
include Galleryable
|
||||
include Documentable
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
accepts_nested_attributes_for :documents, allow_destroy: true
|
||||
|
||||
belongs_to :question, class_name: 'Poll::Question', foreign_key: 'question_id'
|
||||
has_many :videos, class_name: 'Poll::Question::Answer::Video'
|
||||
|
||||
validates :title, presence: true
|
||||
|
||||
|
||||
16
app/models/poll/question/answer/video.rb
Normal file
16
app/models/poll/question/answer/video.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
class Poll::Question::Answer::Video < ActiveRecord::Base
|
||||
belongs_to :answer, class_name: 'Poll::Question::Answer', foreign_key: 'answer_id'
|
||||
|
||||
VIMEO_REGEX = /vimeo.*(staffpicks\/|channels\/|videos\/|video\/|\/)([^#\&\?]*).*/
|
||||
YOUTUBE_REGEX = /youtu.*(be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
|
||||
|
||||
validates :title, presence: true
|
||||
validate :valid_url?
|
||||
|
||||
def valid_url?
|
||||
return if url.blank?
|
||||
return if url.match(VIMEO_REGEX)
|
||||
return if url.match(YOUTUBE_REGEX)
|
||||
errors.add(:url, :invalid)
|
||||
end
|
||||
end
|
||||
@@ -53,7 +53,6 @@
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
|
||||
<% if feature?(:polls) %>
|
||||
<li class="section-title">
|
||||
<a href="#">
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<tbody>
|
||||
<% @officer_assignments.each do |officer_assignment| %>
|
||||
<tr id="<%= dom_id officer_assignment %>">
|
||||
<td><%= officer_assignment.final? ? t('polls.final_date') : l(officer_assignment.date.to_date) %></td>
|
||||
<td><%= l(officer_assignment.date.to_date)%> <%= content_tag :strong, t('polls.final_date') if officer_assignment.final %></td>
|
||||
<td><%= booth_name_with_location(officer_assignment.booth_assignment.booth) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
<%= f.hidden_field :proposal_id %>
|
||||
|
||||
|
||||
<div class="small-12">
|
||||
<div class="small-12 medium-6 large-4">
|
||||
<%= f.select :poll_id,
|
||||
@@ -13,17 +12,19 @@
|
||||
label: t("admin.questions.new.poll_label") %>
|
||||
</div>
|
||||
|
||||
<%= f.text_field :title, maxlength: Poll::Question.title_max_length %>
|
||||
|
||||
<div class="documents small-12">
|
||||
<%= render 'documents/nested_documents', documentable: @question, f: f %>
|
||||
</div>
|
||||
<%= f.text_field :title %>
|
||||
|
||||
<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"} %>
|
||||
|
||||
<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 medium-6 large-4 margin-top">
|
||||
|
||||
@@ -2,20 +2,17 @@
|
||||
|
||||
<%= render 'shared/errors', resource: @answer %>
|
||||
|
||||
<%= f.hidden_field :question_id, value: @question.id %>
|
||||
<%= f.hidden_field :question_id, value: @answer.question_id || @question.id %>
|
||||
|
||||
<%= f.label :title, t('admin.questions.new.form.title') %>
|
||||
<%= f.text_field :title, label: false %>
|
||||
<%= f.text_field :title %>
|
||||
|
||||
<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 %>
|
||||
ckeditor: { language: I18n.locale } %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-6 large-4">
|
||||
<div class="small-12 medium-6 large-4 margin-top">
|
||||
<%= f.submit(class: "button expanded", value: t("shared.save")) %>
|
||||
</div>
|
||||
|
||||
|
||||
55
app/views/admin/poll/questions/answers/documents.html.erb
Normal file
55
app/views/admin/poll/questions/answers/documents.html.erb
Normal file
@@ -0,0 +1,55 @@
|
||||
<%= back_link_to %>
|
||||
|
||||
<h2><%= t("admin.questions.show.answers.documents_list") %></h2>
|
||||
|
||||
<ul class="breadcrumbs">
|
||||
<li><%= @answer.question.title %></li>
|
||||
<li><%= @answer.title %></li>
|
||||
</ul>
|
||||
|
||||
<div class="poll-question-form">
|
||||
<%= form_for(Poll::Question::Answer.new,
|
||||
url: admin_answer_path(@answer),
|
||||
method: :put) do |f| %>
|
||||
|
||||
<%= render 'shared/errors', resource: @answer %>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<div class="documents small-12">
|
||||
<%= render 'documents/nested_documents', documentable: @answer, f: f %>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="actions small-12 medium-4 margin-top">
|
||||
<%= f.submit(class: "button expanded", value: t("shared.save")) %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @answer.documents.present? %>
|
||||
<table>
|
||||
<tr>
|
||||
<th scope="col"><%= t("admin.questions.show.answers.document_title") %></th>
|
||||
<th scope="col" class="text-right"><%= t("admin.questions.show.answers.document_actions") %></th>
|
||||
</tr>
|
||||
|
||||
<% @answer.documents.each do |document| %>
|
||||
<tr>
|
||||
<td>
|
||||
<%= link_to document.title, document.attachment.url %>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<%= link_to t('documents.buttons.download_document'),
|
||||
document.attachment.url,
|
||||
target: "_blank",
|
||||
rel: "nofollow",
|
||||
class: 'button hollow' %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
<% end %>
|
||||
</div>
|
||||
14
app/views/admin/poll/questions/answers/edit.html.erb
Normal file
14
app/views/admin/poll/questions/answers/edit.html.erb
Normal file
@@ -0,0 +1,14 @@
|
||||
<%= back_link_to %>
|
||||
|
||||
<ul class="breadcrumbs margin-top">
|
||||
<li><%= @answer.title %></li>
|
||||
<li><%= t('admin.answers.edit.title') %></li>
|
||||
</ul>
|
||||
|
||||
<h2 class="margin-top">
|
||||
<%= t("admin.answers.edit.title") %>
|
||||
</h2>
|
||||
|
||||
<div class="poll-question-answer-form">
|
||||
<%= render "form", form_url: admin_answer_path(@answer) %>
|
||||
</div>
|
||||
32
app/views/admin/poll/questions/answers/show.html.erb
Normal file
32
app/views/admin/poll/questions/answers/show.html.erb
Normal file
@@ -0,0 +1,32 @@
|
||||
<%= back_link_to %>
|
||||
|
||||
<%= link_to t('shared.edit'), edit_admin_answer_path(@answer),
|
||||
class: "button hollow float-right" %>
|
||||
|
||||
<ul class="breadcrumbs margin-top">
|
||||
<li><%= @answer.question.title %></li>
|
||||
<li><%= @answer.title %></li>
|
||||
</ul>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
<div class="small-12 medium-6">
|
||||
<div class="callout highlight">
|
||||
<p>
|
||||
<strong><%= t("admin.answers.show.title") %></strong>
|
||||
<br>
|
||||
<%= @answer.title %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<strong><%= t("admin.answers.show.description") %></strong>
|
||||
<%= @answer.description %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<strong><%= t("admin.answers.show.images") %></strong>
|
||||
<br>
|
||||
<%= link_to t("admin.answers.show.images_list"), admin_answer_images_path(@answer) %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
21
app/views/admin/poll/questions/answers/videos/_form.html.erb
Normal file
21
app/views/admin/poll/questions/answers/videos/_form.html.erb
Normal file
@@ -0,0 +1,21 @@
|
||||
<%= form_for(@video, url: form_url) do |f| %>
|
||||
|
||||
<%= render 'shared/errors', resource: @video %>
|
||||
|
||||
<%= f.hidden_field :answer_id, value: @video.answer_id || @answer.id %>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
|
||||
<%= f.text_field :title %>
|
||||
<%= f.text_field :url %>
|
||||
|
||||
<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>
|
||||
<% end %>
|
||||
@@ -0,0 +1,9 @@
|
||||
<%= back_link_to %>
|
||||
|
||||
<h2>
|
||||
<%= t("admin.answers.videos.edit.title") %>
|
||||
</h2>
|
||||
|
||||
<div class="poll-question-answer-video-form">
|
||||
<%= render "form", form_url: admin_video_path(@video) %>
|
||||
</div>
|
||||
47
app/views/admin/poll/questions/answers/videos/index.html.erb
Normal file
47
app/views/admin/poll/questions/answers/videos/index.html.erb
Normal file
@@ -0,0 +1,47 @@
|
||||
<%= back_link_to admin_question_path(@answer.question_id) %>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
<h2 class="inline-block">
|
||||
<%= t("admin.answers.videos.index.title") %>
|
||||
</h2>
|
||||
|
||||
<%= link_to t("admin.answers.videos.index.add_video"),
|
||||
new_admin_answer_video_path,
|
||||
class: "button success float-right" %>
|
||||
|
||||
<div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><%= t("admin.answers.videos.index.video_title") %></th>
|
||||
<th><%= t("admin.answers.videos.index.video_url") %></th>
|
||||
<th class="text-right">
|
||||
<%= t("admin.actions.actions") %>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<% @answer.videos.each do |video| %>
|
||||
<tr id="<%= dom_id(video) %>" class="poll_question_answer_video">
|
||||
<td><%= video.title %></td>
|
||||
<td><%= link_to "#{video.url}", video.url %></td>
|
||||
<td class="text-right">
|
||||
|
||||
<%= link_to t("shared.edit"),
|
||||
edit_admin_video_path(video),
|
||||
class: "button hollow" %>
|
||||
|
||||
<%= link_to t("shared.delete"),
|
||||
admin_video_path(video),
|
||||
class: "button hollow alert",
|
||||
method: :delete %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
<%= back_link_to admin_answer_videos_path(@answer) %>
|
||||
|
||||
<h2>
|
||||
<%= t('admin.answers.videos.new.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="poll-question-answer-video-form">
|
||||
<%= render "form", form_url: admin_answer_videos_path %>
|
||||
</div>
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<table class="margin-top">
|
||||
<tr>
|
||||
<th colspan="3" scope="col" class="with-button">
|
||||
<th colspan="5" 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),
|
||||
@@ -41,19 +41,34 @@
|
||||
|
||||
<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 scope="col" class="medium-7"><%= t("admin.questions.show.answers.description") %></th>
|
||||
<th scope="col" class="text-center"><%= t("admin.questions.show.answers.images") %></th>
|
||||
<th scope="col" class="text-center"><%= t("admin.questions.show.answers.documents") %></th>
|
||||
<th scope="col" class="text-center"><%= 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><%= link_to answer.title, admin_answer_path(answer) %></td>
|
||||
<td><%= answer.description %></td>
|
||||
<td class="text-center">
|
||||
(<%= answer.images.count %>)<br>
|
||||
(<%= answer.images.count %>)
|
||||
<br>
|
||||
<%= link_to t("admin.questions.show.answers.images_list"),
|
||||
admin_answer_images_path(answer) %>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
(<%= answer.documents.count rescue 0 %>)
|
||||
<br>
|
||||
<%= link_to t("admin.questions.show.answers.documents_list"),
|
||||
admin_answer_documents_path(answer) %>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
(<%= answer.videos.count %>)
|
||||
<br>
|
||||
<%= link_to t("admin.questions.show.answers.video_list"),
|
||||
admin_answer_videos_path(answer) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
@@ -65,11 +80,3 @@
|
||||
<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 %>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<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>
|
||||
<a data-toggle="answer_<%= answer.id %> zoom_<%= answer.id %>" class="zoom-link hide-for-small-only">
|
||||
<span id="zoom_<%= answer.id %>" class="icon-search-plus" data-toggler="icon-search-plus icon-search-minus"></span>
|
||||
<span class="show-for-sr"><%= t("polls.show.zoom_plus") %></span>
|
||||
</a>
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
</button>
|
||||
</li>
|
||||
|
||||
<% answer.images.each_with_index do |image, index| %>
|
||||
<% answer.images.reverse.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),
|
||||
<%= image_tag image.attachment.url(:original),
|
||||
class: "orbit-image",
|
||||
alt: image.title %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<% poll_group.each do |poll| %>
|
||||
<div class="poll with-image">
|
||||
<% if user_signed_in? && !poll.votable_by?(current_user) %>
|
||||
<% if user_signed_in? && !current_user.unverified? && !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>
|
||||
<% end %>
|
||||
<div class="row" data-equalizer>
|
||||
<div class="row" data-equalizer data-equalize-on="medium">
|
||||
<div class="small-12 medium-3 column">
|
||||
<div class="image-container" data-equalizer-watch>
|
||||
<% if poll.image.present? %>
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
<div class="poll-question-answers">
|
||||
<% if can? :answer, question %>
|
||||
<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
|
||||
<% question.question_answers.each do |answer| %>
|
||||
<% if @answers_by_question_id[question.id] == answer.title %>
|
||||
<span class="button answered"
|
||||
title="<%= t("poll_questions.show.voted", answer: answer)%>">
|
||||
<% if @answers_by_question_id[question.id] == 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),
|
||||
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" %>
|
||||
class: "button secondary hollow js-question-answer" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
</h3>
|
||||
|
||||
<div id="<%= dom_id(question) %>_answers" class="padding">
|
||||
<%= render 'polls/questions/answers', question: question %>
|
||||
<%= render 'polls/questions/answers', question: question, token: token %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
$("#<%= dom_id(@question) %>_answers").html('<%= j render("polls/questions/answers", question: @question) %>');
|
||||
<% token = poll_voter_token(@question.poll, current_user) %>
|
||||
$("#<%= dom_id(@question) %>_answers").html('<%= j render("polls/questions/answers", question: @question, token: token) %>');
|
||||
|
||||
@@ -38,10 +38,25 @@
|
||||
<%= t("polls.show.already_voted_in_booth") %>
|
||||
</div>
|
||||
<% else %>
|
||||
<% @questions.each do |question| %>
|
||||
<%= render 'polls/questions/question', question: question %>
|
||||
|
||||
<% if current_user && !@poll.votable_by?(current_user) %>
|
||||
<div class="callout warning">
|
||||
<%= t("polls.show.already_voted_in_web") %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% @questions.each do |question| %>
|
||||
<%= render 'polls/questions/question', question: question, token: @token %>
|
||||
<% end %>
|
||||
|
||||
<% if poll_voter_token(@poll, current_user).empty? %>
|
||||
<div class="callout token-message js-token-message" style="display: none">
|
||||
<%= t('poll_questions.show.voted_token') %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= link_to t("polls.show.participate_in_other_polls"), polls_path, class: "button hollow" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -52,10 +67,12 @@
|
||||
<%= safe_html_with_links simple_format(@poll.description) %>
|
||||
</div>
|
||||
|
||||
<aside class="small-12 medium-3 column">
|
||||
<% if false %>
|
||||
<aside class="small-12 medium-3 column">
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("polls.show.documents") %></h2>
|
||||
</aside>
|
||||
</aside>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -64,23 +81,57 @@
|
||||
|
||||
<% @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">
|
||||
data-toggler="medium-6 answer-divider">
|
||||
|
||||
<h3><%= answer.title %></h3>
|
||||
<% if answer.description.present? %>
|
||||
<h3><%= answer.title %></h3>
|
||||
<% end %>
|
||||
|
||||
<% if answer.images.any? %>
|
||||
<%= render "gallery", answer: answer %>
|
||||
<% end %>
|
||||
|
||||
<div class="margin-top">
|
||||
<%= safe_html_with_links simple_format(answer.description) %>
|
||||
</div>
|
||||
<% if answer.description.present? %>
|
||||
<div class="margin-top">
|
||||
<div id="answer_description_<%= answer.id %>" class="answer-description short" data-toggler="short">
|
||||
<%= safe_html_with_links simple_format(answer.description) %>
|
||||
</div>
|
||||
<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>
|
||||
<% end %>
|
||||
|
||||
<% if answer.documents.present? %>
|
||||
<div class="document-link">
|
||||
<p>
|
||||
<span class="icon-document"></span>
|
||||
<strong><%= t("polls.show.documents") %></strong>
|
||||
</p>
|
||||
|
||||
<% answer.documents.each do |document| %>
|
||||
<%= link_to document.title,
|
||||
document.attachment.url,
|
||||
target: "_blank",
|
||||
rel: "nofollow" %><br>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="tabs-panel is-active" id="tab-comments">
|
||||
<%= render "shared/comments" %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -213,9 +213,12 @@ en:
|
||||
image:
|
||||
title: Title
|
||||
attachment: Attachment
|
||||
poll/question_answer:
|
||||
title: "Answer"
|
||||
description: "Description"
|
||||
poll/question/answer:
|
||||
title: Answer
|
||||
description: Description
|
||||
poll/question/answer/video:
|
||||
title: Title
|
||||
url: External video
|
||||
errors:
|
||||
models:
|
||||
user:
|
||||
|
||||
@@ -587,9 +587,6 @@ en:
|
||||
new:
|
||||
title: "Create Question"
|
||||
poll_label: "Poll"
|
||||
form:
|
||||
title: Title
|
||||
description: Description
|
||||
answers:
|
||||
images:
|
||||
add_image: "Add image"
|
||||
@@ -599,17 +596,39 @@ en:
|
||||
author: Author
|
||||
title: Title
|
||||
valid_answers: Valid answers
|
||||
add_answer: "Add answer"
|
||||
add_answer: Add answer
|
||||
video_url: External video
|
||||
documents: Documents (1)
|
||||
answers:
|
||||
title: Answer
|
||||
description: Description
|
||||
videos: Videos
|
||||
video_list: Video list
|
||||
images: Images
|
||||
images_list: Images list
|
||||
documents: Documents
|
||||
documents_list: Documents list
|
||||
document_title: Title
|
||||
document_actions: Actions
|
||||
answers:
|
||||
new:
|
||||
title: "New answer"
|
||||
title: New answer
|
||||
show:
|
||||
title: Title
|
||||
description: Description
|
||||
images: Images
|
||||
images_list: Images list
|
||||
edit:
|
||||
title: Edit answer
|
||||
videos:
|
||||
index:
|
||||
title: Videos
|
||||
add_video: Add video
|
||||
video_title: Title
|
||||
video_url: External video
|
||||
new:
|
||||
title: New video
|
||||
edit:
|
||||
title: Edit video
|
||||
recounts:
|
||||
index:
|
||||
title: "Recounts"
|
||||
|
||||
@@ -478,7 +478,8 @@ en:
|
||||
help_text_1: "Voting takes place when a citizen proposal supports reaches 1% of the census with voting rights. Voting can also include questions that the City Council ask to the citizens decision."
|
||||
help_text_2: "To participate in the next vote you have to sign up on %{org} and verify your account. All registered voters in the city over 16 years old can vote. The results of all votes are binding on the government."
|
||||
show:
|
||||
already_voted_in_booth: "You have already participated in a booth for this poll."
|
||||
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."
|
||||
back: Back to voting
|
||||
cant_answer_not_logged_in: "You must %{signin} or %{signup} to participate."
|
||||
signin: Sign in
|
||||
@@ -491,12 +492,16 @@ en:
|
||||
more_info_title: "More information"
|
||||
documents: Documents
|
||||
zoom_plus: Expand image
|
||||
read_more: "Read more about %{answer}"
|
||||
read_less: "Read less about %{answer}"
|
||||
participate_in_other_polls: Participate in other polls
|
||||
poll_questions:
|
||||
create_question: "Create question"
|
||||
default_valid_answers: "Yes, No"
|
||||
show:
|
||||
vote_answer: "Vote %{answer}"
|
||||
voted: "You have voted %{answer}"
|
||||
voted_token: "You can write down this vote identifier, to check your vote on the final results:"
|
||||
proposal_notifications:
|
||||
new:
|
||||
title: "Send message"
|
||||
|
||||
@@ -9,6 +9,7 @@ en:
|
||||
poll: "Poll created successfully."
|
||||
poll_booth: "Booth created successfully."
|
||||
poll_question_answer: "Answer created successfully"
|
||||
poll_question_answer_video: "Video created successfully"
|
||||
proposal: "Proposal created successfully."
|
||||
proposal_notification: "Your message has been sent correctly."
|
||||
spending_proposal: "Spending proposal created successfully. You can access it from %{activity}"
|
||||
@@ -31,3 +32,4 @@ en:
|
||||
budget_investment: "Investment project deleted succesfully."
|
||||
error: "Could not delete"
|
||||
topic: "Topic deleted successfully."
|
||||
poll_question_answer_video: "Answer video deleted successfully."
|
||||
|
||||
@@ -207,9 +207,12 @@ es:
|
||||
image:
|
||||
title: Título
|
||||
attachment: Archivo adjunto
|
||||
poll/question_answer:
|
||||
title: "Respuesta"
|
||||
description: "Descripción"
|
||||
poll/question/answer:
|
||||
title: Respuesta
|
||||
description: Descripción
|
||||
poll/question/answer/video:
|
||||
title: Título
|
||||
url: Vídeo externo
|
||||
errors:
|
||||
models:
|
||||
user:
|
||||
|
||||
@@ -587,9 +587,6 @@ es:
|
||||
new:
|
||||
title: "Crear pregunta ciudadana"
|
||||
poll_label: "Votación"
|
||||
form:
|
||||
title: Título
|
||||
description: Descripción
|
||||
answers:
|
||||
images:
|
||||
add_image: "Añadir imagen"
|
||||
@@ -599,21 +596,41 @@ es:
|
||||
author: Autor
|
||||
title: Título
|
||||
valid_answers: Respuestas válidas
|
||||
add_answer: "Añadir respuesta"
|
||||
description: Descripción
|
||||
add_answer: Añadir respuesta
|
||||
video_url: Video externo
|
||||
documents: Documentos (1)
|
||||
preview: Ver en la web
|
||||
answers:
|
||||
title: Respuesta
|
||||
description: Descripción
|
||||
videos: Vídeos
|
||||
video_list: Lista de vídeos
|
||||
images: Imágenes
|
||||
images_list: Lista de imágenes
|
||||
documents: Documentos
|
||||
documents_list: Lista de documentos
|
||||
document_title: Título
|
||||
document_actions: Acciones
|
||||
answers:
|
||||
new:
|
||||
title: "Nueva respuesta"
|
||||
title: Nueva respuesta
|
||||
video_url: Video externo
|
||||
documents: Documentos (1)
|
||||
show:
|
||||
title: Título
|
||||
description: Descripción
|
||||
images: Imágenes
|
||||
images_list: Lista de imágenes
|
||||
edit:
|
||||
title: Editar respuesta
|
||||
videos:
|
||||
index:
|
||||
title: Vídeos
|
||||
add_video: Añadir vídeo
|
||||
video_title: Título
|
||||
video_url: External video
|
||||
new:
|
||||
title: Nuevo video
|
||||
edit:
|
||||
title: Editar vídeo
|
||||
recounts:
|
||||
index:
|
||||
title: "Recuentos"
|
||||
|
||||
@@ -478,7 +478,8 @@ es:
|
||||
help_text_1: "Las votaciones se convocan cuando una propuesta ciudadana alcanza el 1% de apoyos del censo con derecho a voto. En las votaciones también se pueden incluir cuestiones que el Ayuntamiento somete a decisión directa de la ciudadanía."
|
||||
help_text_2: "Para participar en la próxima votación tienes que registrarte en %{org} y verificar tu cuenta. Pueden votar todas las personas empadronadas en la ciudad mayores de 16 años. Los resultados de todas las votaciones serán vinculantes para el gobierno."
|
||||
show:
|
||||
already_voted_in_booth: "Ya has participado en esta votación en una urna."
|
||||
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."
|
||||
back: Volver a votaciones
|
||||
cant_answer_not_logged_in: "Necesitas %{signin} o %{signup} para participar."
|
||||
signin: iniciar sesión
|
||||
@@ -491,12 +492,16 @@ es:
|
||||
more_info_title: "Más información"
|
||||
documents: Documentación
|
||||
zoom_plus: Ampliar imagen
|
||||
read_more: "Leer más sobre %{answer}"
|
||||
read_less: "Leer menos sobre %{answer}"
|
||||
participate_in_other_polls: Participar en otras votaciones
|
||||
poll_questions:
|
||||
create_question: "Crear pregunta para votación"
|
||||
default_valid_answers: "Sí, No"
|
||||
show:
|
||||
vote_answer: "Votar %{answer}"
|
||||
voted: "Has votado %{answer}"
|
||||
voted_token: "Puedes apuntar este identificador de voto, para comprobar tu votación en el resultado final:"
|
||||
proposal_notifications:
|
||||
new:
|
||||
title: "Enviar mensaje"
|
||||
|
||||
@@ -9,6 +9,7 @@ es:
|
||||
poll: "Votación creada correctamente."
|
||||
poll_booth: "Urna creada correctamente."
|
||||
poll_question_answer: "Respuesta creada correctamente"
|
||||
poll_question_answer_video: "Vídeo creado correctamente"
|
||||
proposal: "Propuesta creada correctamente."
|
||||
proposal_notification: "Tu message ha sido enviado correctamente."
|
||||
spending_proposal: "Propuesta de inversión creada correctamente. Puedes acceder a ella desde %{activity}"
|
||||
@@ -31,3 +32,4 @@ es:
|
||||
budget_investment: "Propuesta de inversión eliminada."
|
||||
error: "No se pudo borrar"
|
||||
topic: "Tema eliminado."
|
||||
poll_question_answer_video: "Vídeo de respuesta eliminado."
|
||||
|
||||
@@ -147,9 +147,12 @@ fr:
|
||||
name: Nom
|
||||
locale: Langue
|
||||
body: Contenu
|
||||
poll/question_answer:
|
||||
title: "Réponse"
|
||||
description: "Description"
|
||||
poll/question/answer:
|
||||
title: Réponse
|
||||
description: Description
|
||||
poll/question/answer/video:
|
||||
title: Titre
|
||||
url: Vidéo externe
|
||||
errors:
|
||||
models:
|
||||
user:
|
||||
|
||||
@@ -382,13 +382,34 @@ fr:
|
||||
author: Auteur
|
||||
title: Titre
|
||||
valid_answers: Réponses valides
|
||||
add_answer: "Ajouter une réponse"
|
||||
answer: "Réponse"
|
||||
description: Description
|
||||
add_answer: Ajouter une réponse
|
||||
documents: Documents (1)
|
||||
preview: Voir l'aperçu
|
||||
answers:
|
||||
title: Réponse
|
||||
description: Description
|
||||
videos: Vidéos
|
||||
video_list: Liste des vidéos
|
||||
answers:
|
||||
show:
|
||||
title: Titre
|
||||
description: Description
|
||||
images: Images
|
||||
images_list: Liste des images
|
||||
new:
|
||||
title: "Nouvelle réponse"
|
||||
title: Nouvelle réponse
|
||||
edit:
|
||||
title: Modifier réponse
|
||||
videos:
|
||||
index:
|
||||
title: Vidéos
|
||||
add_video: Ajouter une vidéo
|
||||
video_title: Titre
|
||||
video_url: Vidéo externe
|
||||
new:
|
||||
title: Nouveau vidéo
|
||||
edit:
|
||||
title: Modifier la vidéo
|
||||
recounts:
|
||||
index:
|
||||
title: "Dépouillements"
|
||||
|
||||
@@ -8,6 +8,8 @@ fr:
|
||||
direct_message: "Votre message a été envoyé avec succès."
|
||||
poll: "Vote créé avec succès."
|
||||
poll_booth: "Urne créée avec succès."
|
||||
poll_question_answer: "Réponse créée avec succès"
|
||||
poll_question_answer_video: "Vidéo créée avec succès"
|
||||
proposal: "Proposition créée avec succès."
|
||||
proposal_notification: "Votre message a correctement été envoyé."
|
||||
spending_proposal: "Proposition de dépense créée avec succès. Vous pouvez y accéder depuis %{activity}"
|
||||
@@ -27,3 +29,4 @@ fr:
|
||||
spending_proposal: "Proposition de dépense supprimée avec succès."
|
||||
budget_investment: "Budget d'investissement supprimé avec succès."
|
||||
error: "Suppression impossible"
|
||||
poll_question_answer_video: "Réponse vidéo supprimée avec succès."
|
||||
|
||||
@@ -300,11 +300,12 @@ Rails.application.routes.draw do
|
||||
end
|
||||
end
|
||||
|
||||
resources :questions do
|
||||
resources :answers, only: [:new, :create], controller: 'questions/answers', shallow: true do
|
||||
resources :questions, shallow: true do
|
||||
resources :answers, except: [:index, :destroy], controller: 'questions/answers', shallow: true do
|
||||
resources :images, controller: 'questions/answers/images'
|
||||
resources :videos, controller: 'questions/answers/videos'
|
||||
get :documents, to: 'questions/answers#documents'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -557,11 +557,14 @@ print "Creating Poll Questions"
|
||||
author = User.reorder("RANDOM()").first
|
||||
description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>"
|
||||
open_at = rand(2.months.ago..2.months.from_now)
|
||||
answers = Faker::Lorem.words((2..4).to_a.sample).map { |answer| answer.capitalize }
|
||||
question = Poll::Question.create!(author: author,
|
||||
title: Faker::Lorem.sentence(3).truncate(60),
|
||||
description: description,
|
||||
valid_answers: Faker::Lorem.words((2..7).to_a.sample).join(', '),
|
||||
valid_answers: answers.join(', '),
|
||||
poll: poll)
|
||||
answers.each do |answer|
|
||||
Poll::Question::Answer.create!(question: question, title: answer, description: Faker::ChuckNorris.fact)
|
||||
end
|
||||
end
|
||||
|
||||
puts " ✅"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class CreatePollQuestionAnswerVideos < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :poll_question_answer_videos do |t|
|
||||
t.string :title
|
||||
t.string :url
|
||||
t.integer :answer_id, index: true
|
||||
end
|
||||
|
||||
add_foreign_key :poll_question_answer_videos, :poll_question_answers, column: :answer_id
|
||||
end
|
||||
end
|
||||
5
db/migrate/20171006145053_add_token_to_poll_voters.rb
Normal file
5
db/migrate/20171006145053_add_token_to_poll_voters.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class AddTokenToPollVoters < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :poll_voters, :token, :string
|
||||
end
|
||||
end
|
||||
12
db/schema.rb
12
db/schema.rb
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20171004151553) do
|
||||
ActiveRecord::Schema.define(version: 20171006145053) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
@@ -668,6 +668,14 @@ ActiveRecord::Schema.define(version: 20171004151553) do
|
||||
add_index "poll_partial_results", ["origin"], name: "index_poll_partial_results_on_origin", using: :btree
|
||||
add_index "poll_partial_results", ["question_id"], name: "index_poll_partial_results_on_question_id", using: :btree
|
||||
|
||||
create_table "poll_question_answer_videos", force: :cascade do |t|
|
||||
t.string "title"
|
||||
t.string "url"
|
||||
t.integer "answer_id"
|
||||
end
|
||||
|
||||
add_index "poll_question_answer_videos", ["answer_id"], name: "index_poll_question_answer_videos_on_answer_id", using: :btree
|
||||
|
||||
create_table "poll_question_answers", force: :cascade do |t|
|
||||
t.string "title"
|
||||
t.text "description"
|
||||
@@ -760,6 +768,7 @@ ActiveRecord::Schema.define(version: 20171004151553) do
|
||||
t.integer "user_id"
|
||||
t.string "origin"
|
||||
t.integer "officer_id"
|
||||
t.string "token"
|
||||
end
|
||||
|
||||
add_index "poll_voters", ["booth_assignment_id"], name: "index_poll_voters_on_booth_assignment_id", using: :btree
|
||||
@@ -1155,6 +1164,7 @@ ActiveRecord::Schema.define(version: 20171004151553) do
|
||||
add_foreign_key "poll_partial_results", "poll_officer_assignments", column: "officer_assignment_id"
|
||||
add_foreign_key "poll_partial_results", "poll_questions", column: "question_id"
|
||||
add_foreign_key "poll_partial_results", "users", column: "author_id"
|
||||
add_foreign_key "poll_question_answer_videos", "poll_question_answers", column: "answer_id"
|
||||
add_foreign_key "poll_question_answers", "poll_questions", column: "question_id"
|
||||
add_foreign_key "poll_questions", "polls"
|
||||
add_foreign_key "poll_questions", "proposals"
|
||||
|
||||
51
spec/features/admin/poll/questions/answers/answers_spec.rb
Normal file
51
spec/features/admin/poll/questions/answers/answers_spec.rb
Normal file
@@ -0,0 +1,51 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Answers' do
|
||||
|
||||
background do
|
||||
admin = create(:administrator)
|
||||
login_as (admin.user)
|
||||
end
|
||||
|
||||
scenario 'Create' do
|
||||
question = create(:poll_question)
|
||||
title = 'Whatever the question may be, the answer is always 42'
|
||||
description = "The Hitchhiker's Guide To The Universe"
|
||||
|
||||
visit admin_question_path(question)
|
||||
click_link 'Add answer'
|
||||
|
||||
fill_in 'poll_question_answer_title', with: title
|
||||
fill_in 'poll_question_answer_description', with: description
|
||||
|
||||
click_button 'Save'
|
||||
|
||||
expect(page).to have_content(title)
|
||||
expect(page).to have_content(description)
|
||||
end
|
||||
|
||||
scenario 'Update' do
|
||||
question = create(:poll_question)
|
||||
answer = create(:poll_question_answer, question: question, title: "Answer title")
|
||||
|
||||
visit admin_answer_path(answer)
|
||||
|
||||
click_link 'Edit'
|
||||
|
||||
old_title = answer.title
|
||||
new_title = 'Ex Machina'
|
||||
|
||||
fill_in 'poll_question_answer_title', with: new_title
|
||||
|
||||
click_button 'Save'
|
||||
|
||||
expect(page).to have_content('Changes saved')
|
||||
expect(page).to have_content(new_title)
|
||||
|
||||
visit admin_question_path(question)
|
||||
|
||||
expect(page).to have_content(new_title)
|
||||
expect(page).to_not have_content(old_title)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,33 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Videos' do
|
||||
|
||||
background do
|
||||
admin = create(:administrator)
|
||||
login_as(admin.user)
|
||||
end
|
||||
|
||||
scenario "Create" do
|
||||
question = create(:poll_question)
|
||||
answer = create(:poll_question_answer, question: question)
|
||||
video_title = "'Magical' by Junko Ohashi"
|
||||
video_url = "https://www.youtube.com/watch?v=-JMf43st-1A"
|
||||
|
||||
visit admin_question_path(question)
|
||||
|
||||
within("#poll_question_answer_#{answer.id}") do
|
||||
click_link "Video list"
|
||||
end
|
||||
|
||||
click_link "Add video"
|
||||
|
||||
fill_in 'poll_question_answer_video_title', with: video_title
|
||||
fill_in 'poll_question_answer_video_url', with: video_url
|
||||
|
||||
click_button "Save"
|
||||
|
||||
expect(page).to have_content(video_title)
|
||||
expect(page).to have_content(video_url)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -111,22 +111,4 @@ feature 'Admin poll questions' do
|
||||
|
||||
pending "Mark all city by default when creating a poll question from a successful proposal"
|
||||
|
||||
it_behaves_like "nested documentable",
|
||||
"administrator",
|
||||
"poll_question",
|
||||
"new_admin_question_path",
|
||||
{ },
|
||||
"documentable_fill_new_valid_poll_question",
|
||||
"Save",
|
||||
"Star Wars: Episode IV - A New Hope"
|
||||
|
||||
it_behaves_like "nested documentable",
|
||||
"administrator",
|
||||
"poll_question",
|
||||
"edit_admin_question_path",
|
||||
{ "id": "id" },
|
||||
nil,
|
||||
"Save",
|
||||
"Changes saved"
|
||||
|
||||
end
|
||||
|
||||
@@ -94,6 +94,9 @@ feature 'Polls' do
|
||||
end
|
||||
|
||||
scenario 'Level 1 users' do
|
||||
visit polls_path
|
||||
expect(page).to_not have_selector('.already-answer')
|
||||
|
||||
poll.update(geozone_restricted: true)
|
||||
poll.geozones << geozone
|
||||
|
||||
@@ -209,8 +212,7 @@ feature 'Polls' do
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(page).to have_link('Han Solo')
|
||||
expect(page).to_not have_link('Chewbacca')
|
||||
expect(page).to have_content('Chewbacca')
|
||||
expect(page).to have_link('Chewbacca')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users answering', :js do
|
||||
@@ -256,82 +258,79 @@ feature 'Polls' do
|
||||
expect(page).to have_link('Han Solo')
|
||||
end
|
||||
|
||||
scenario 'User can write comments' do
|
||||
create(:comment, commentable: poll)
|
||||
scenario 'Level 2 votes, signs out, signs in, votes again', :js do
|
||||
poll.update(geozone_restricted: true)
|
||||
poll.geozones << geozone
|
||||
|
||||
question = create(:poll_question, poll: poll)
|
||||
answer1 = create(:poll_question_answer, question: question, title: 'Han Solo')
|
||||
answer2 = create(:poll_question_answer, question: question, title: 'Chewbacca')
|
||||
|
||||
user = create(:user, :level_two, geozone: geozone)
|
||||
|
||||
login_as user
|
||||
visit poll_path(poll)
|
||||
click_link 'Han Solo'
|
||||
|
||||
expect(page).to have_css('.comment', count: 1)
|
||||
expect(page).to_not have_link('Han Solo')
|
||||
expect(page).to have_link('Chewbacca')
|
||||
|
||||
comment = Comment.last
|
||||
within first('.comment') do
|
||||
expect(page).to have_content comment.user.name
|
||||
expect(page).to have_content I18n.l(comment.created_at, format: :datetime)
|
||||
expect(page).to have_content comment.body
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'user b can access to comments from user a' do
|
||||
oliver = create(:user, username: 'Oliver Atom')
|
||||
benji = create(:user, username: 'Benji Prince')
|
||||
create(:comment, commentable: poll, user: oliver)
|
||||
|
||||
login_as(benji)
|
||||
click_link "Sign out"
|
||||
login_as user
|
||||
visit poll_path(poll)
|
||||
click_link 'Han Solo'
|
||||
|
||||
expect(page).to have_content oliver.username
|
||||
end
|
||||
expect(page).to_not have_link('Han Solo')
|
||||
expect(page).to have_link('Chewbacca')
|
||||
|
||||
scenario 'user b can reply to comments from user a', :js do
|
||||
koji = create(:user, username: 'Koji Kabuto')
|
||||
sayaka = create(:user, username: 'Sayaka')
|
||||
comment = create(:comment, commentable: poll, user: koji)
|
||||
|
||||
login_as(sayaka)
|
||||
click_link "Sign out"
|
||||
login_as user
|
||||
visit poll_path(poll)
|
||||
click_link 'Chewbacca'
|
||||
|
||||
click_link "Reply"
|
||||
|
||||
within "#js-comment-form-comment_#{comment.id}" do
|
||||
fill_in "comment-body-comment_#{comment.id}", with: 'MAZINGER!!.'
|
||||
click_button 'Publish reply'
|
||||
end
|
||||
|
||||
within "#comment_#{comment.id}" do
|
||||
expect(page).to have_content 'MAZINGER!!.'
|
||||
end
|
||||
|
||||
expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true)
|
||||
end
|
||||
|
||||
scenario 'user can upvote a comment', :js do
|
||||
goku = create(:user, username: 'Goku')
|
||||
vegeta = create(:user, username: 'Vegeta')
|
||||
comment = create(:comment, commentable: poll, user: goku)
|
||||
|
||||
login_as(vegeta)
|
||||
visit poll_path(poll)
|
||||
|
||||
within("#comment_#{comment.id}_votes") do
|
||||
find('.in_favor a').click
|
||||
|
||||
expect(page).to have_content "1 vote"
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'user can downvote a comment', :js do
|
||||
doraemon = create(:user, username: 'Doraemon')
|
||||
nobita = create(:user, username: 'Nobi Nobita')
|
||||
comment = create(:comment, commentable: poll, user: doraemon)
|
||||
|
||||
login_as(nobita)
|
||||
visit poll_path(poll)
|
||||
|
||||
within("#comment_#{comment.id}_votes") do
|
||||
find('.against a').click
|
||||
|
||||
expect(page).to have_content "1 vote"
|
||||
end
|
||||
expect(page).to_not have_link('Chewbacca')
|
||||
expect(page).to have_link('Han Solo')
|
||||
end
|
||||
end
|
||||
|
||||
context 'Booth & Website' do
|
||||
|
||||
let(:poll) { create(:poll, summary: "Summary", description: "Description") }
|
||||
let(:booth) { create(:poll_booth) }
|
||||
let(:officer) { create(:poll_officer) }
|
||||
|
||||
scenario 'Already voted on booth cannot vote on website', :js do
|
||||
|
||||
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)
|
||||
question = create(:poll_question, poll: poll)
|
||||
create(:poll_question_answer, question: question, title: 'Han Solo')
|
||||
create(:poll_question_answer, question: question, title: 'Chewbacca')
|
||||
user = create(:user, :level_two, :in_census)
|
||||
|
||||
login_as(officer.user)
|
||||
visit new_officing_residence_path
|
||||
officing_verify_residence
|
||||
click_button "Confirm vote"
|
||||
|
||||
expect(page).to have_content "Vote introduced!"
|
||||
|
||||
visit new_officing_residence_path
|
||||
click_link "Sign out"
|
||||
login_as user
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(page).to have_content "You have already participated in a physical booth. You can not participate again."
|
||||
|
||||
within("#poll_question_#{question.id}_answers") do
|
||||
expect(page).to have_content('Han Solo')
|
||||
expect(page).to have_content('Chewbacca')
|
||||
|
||||
expect(page).to_not have_link('Han Solo')
|
||||
expect(page).to_not have_link('Chewbacca')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,6 +32,11 @@ feature "Voter" do
|
||||
expect(page).to_not have_link('Yes')
|
||||
end
|
||||
|
||||
find(:css, ".js-token-message").should be_visible
|
||||
token = find(:css, ".js-question-answer")[:href].gsub(/.+?(?=token)/, '').gsub('token=', '')
|
||||
|
||||
expect(page).to have_content "You can write down this vote identifier, to check your vote on the final results: #{token}"
|
||||
|
||||
expect(Poll::Voter.count).to eq(1)
|
||||
expect(Poll::Voter.first.origin).to eq("web")
|
||||
end
|
||||
@@ -91,9 +96,34 @@ feature "Voter" do
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(page).to_not have_link('Yes')
|
||||
expect(page).to have_content "You have already participated in a booth for this poll."
|
||||
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)
|
||||
end
|
||||
|
||||
scenario "Trying to vote in web again", :js do
|
||||
login_as user
|
||||
vote_for_poll_via_web(poll, question)
|
||||
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(page).to_not have_selector('.js-token-message')
|
||||
|
||||
expect(page).to have_content "You have already participated in this poll. If you vote again it will be overwritten."
|
||||
within("#poll_question_#{question.id}_answers") do
|
||||
expect(page).to_not have_link('Yes')
|
||||
end
|
||||
|
||||
click_link "Sign out"
|
||||
|
||||
login_as user
|
||||
visit poll_path(poll)
|
||||
|
||||
within("#poll_question_#{question.id}_answers") do
|
||||
expect(page).to have_link('Yes')
|
||||
expect(page).to have_link('No')
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -46,7 +46,7 @@ describe Poll::Answer do
|
||||
answer = create(:poll_answer, question: question, author: author, answer: "Yes")
|
||||
expect(answer.poll.voters).to be_blank
|
||||
|
||||
answer.record_voter_participation
|
||||
answer.record_voter_participation('token')
|
||||
expect(poll.reload.voters.size).to eq(1)
|
||||
voter = poll.voters.first
|
||||
|
||||
@@ -57,12 +57,12 @@ describe Poll::Answer do
|
||||
|
||||
it "updates a poll_voter with user and poll data" do
|
||||
answer = create(:poll_answer, question: question, author: author, answer: "Yes")
|
||||
answer.record_voter_participation
|
||||
answer.record_voter_participation('token')
|
||||
|
||||
expect(poll.reload.voters.size).to eq(1)
|
||||
|
||||
answer = create(:poll_answer, question: question, author: author, answer: "No")
|
||||
answer.record_voter_participation
|
||||
answer.record_voter_participation('token')
|
||||
|
||||
expect(poll.reload.voters.size).to eq(1)
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ describe :voter do
|
||||
|
||||
it "should not be valid if the user has voted via web" do
|
||||
answer = create(:poll_answer)
|
||||
answer.record_voter_participation
|
||||
answer.record_voter_participation('token')
|
||||
|
||||
voter = build(:poll_voter, poll: answer.question.poll, user: answer.author)
|
||||
expect(voter).to_not be_valid
|
||||
@@ -162,11 +162,12 @@ describe :voter do
|
||||
|
||||
it "sets user info" do
|
||||
user = create(:user, document_number: "1234A", document_type: "1")
|
||||
voter = build(:poll_voter, user: user)
|
||||
voter = build(:poll_voter, user: user, token: "1234abcd")
|
||||
voter.save
|
||||
|
||||
expect(voter.document_number).to eq("1234A")
|
||||
expect(voter.document_type).to eq("1")
|
||||
expect(voter.token).to eq("1234abcd")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -191,9 +191,17 @@ shared_examples "nested documentable" do |login_as_name, documentable_factory_na
|
||||
|
||||
documentable_attach_new_file(documentable_factory_name, 0, "spec/fixtures/files/empty.pdf")
|
||||
click_on submit_button
|
||||
|
||||
documentable_redirected_to_resource_show_or_navigate_to
|
||||
|
||||
expect(page).to have_content "Documents (1)"
|
||||
expect(page).to have_content "Documents"
|
||||
|
||||
find("#tab-documents-label").click
|
||||
expect(page).to have_content "empty.pdf"
|
||||
|
||||
#Review
|
||||
#Doble check why the file is stored with a name different to empty.pdf
|
||||
expect(page).to have_css("a[href$='.pdf']")
|
||||
end
|
||||
|
||||
scenario "Should show resource with new document after successful creation with maximum allowed uploaded files", :js do
|
||||
@@ -263,7 +271,6 @@ shared_examples "nested documentable" do |login_as_name, documentable_factory_na
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -275,7 +282,7 @@ rescue
|
||||
return
|
||||
end
|
||||
|
||||
def documentable_attach_new_file(documentable_factory_name, index, path, success = true)
|
||||
def documentable_attach_new_file(_documentable_factory_name, index, path, success = true)
|
||||
click_link "Add new document"
|
||||
document = all(".document")[index]
|
||||
document_input = document.find("input[type=file]", visible: false)
|
||||
@@ -318,8 +325,3 @@ def documentable_fill_new_valid_budget_investment
|
||||
fill_in_ckeditor "budget_investment_description", with: "Budget investment description"
|
||||
check :budget_investment_terms_of_service
|
||||
end
|
||||
|
||||
def documentable_fill_new_valid_poll_question
|
||||
page.select documentable.poll.name, from: 'poll_question_poll_id'
|
||||
fill_in 'poll_question_title', with: "Star Wars: Episode IV - A New Hope"
|
||||
end
|
||||
|
||||
@@ -146,7 +146,11 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
|
||||
send(fill_resource_method_name) if fill_resource_method_name
|
||||
click_on submit_button
|
||||
|
||||
expect(page).to have_content imageable_success_notice
|
||||
if has_many_images
|
||||
skip "no need to test, there are no attributes for the parent resource"
|
||||
else
|
||||
expect(page).to have_content imageable_success_notice
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Should show successful notice when resource filled correctly and after valid file uploads", :js do
|
||||
|
||||
Reference in New Issue
Block a user