Merge branch 'master' into community-design

This commit is contained in:
decabeza
2017-11-21 20:52:05 +01:00
553 changed files with 14905 additions and 5928 deletions

View File

@@ -13,33 +13,33 @@ module AdminHelper
end
def menu_tags?
["tags"].include? controller_name
["tags"].include?(controller_name)
end
def menu_moderated_content?
["proposals", "debates", "comments", "hidden_users"].include? controller_name
["proposals", "debates", "comments", "hidden_users"].include?(controller_name) && controller.class.parent != Admin::Legislation
end
def menu_budget?
["spending_proposals"].include? controller_name
["spending_proposals"].include?(controller_name)
end
def menu_polls?
["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?
["administrators", "organizations", "officials", "moderators", "valuators", "managers", "users"].include? controller_name
%w[administrators organizations officials moderators valuators managers users activity].include?(controller_name)
end
def menu_banners?
["banners"].include? controller_name
["banners"].include?(controller_name)
end
def menu_customization?
["pages", "images", "content_blocks"].include? controller_name
["pages", "images", "content_blocks"].include?(controller_name)
end
def official_level_options
options = [["", 0]]
(1..5).each do |i|

View File

@@ -60,4 +60,8 @@ module ApplicationHelper
def format_price(number)
number_to_currency(number, precision: 0, locale: I18n.default_locale)
end
def kaminari_path(url)
"#{root_url.chomp("\/")}#{url}"
end
end

View File

@@ -4,4 +4,12 @@ module DebatesHelper
Debate.all.featured.count > 0
end
end
def empty_recommended_debates_message_text(user)
if user.interests.any?
t('debates.index.recommendations.without_results')
else
t('debates.index.recommendations.without_interests')
end
end
end

View File

@@ -0,0 +1,16 @@
module DirectUploadsHelper
def render_destroy_upload_link(direct_upload)
label = direct_upload.resource_relation == "image" ? "images" : "documents"
link_to t("#{label}.form.delete_button"),
direct_upload_destroy_url("direct_upload[resource_type]": direct_upload.resource_type,
"direct_upload[resource_id]": direct_upload.resource_id,
"direct_upload[resource_relation]": direct_upload.resource_relation,
"direct_upload[cached_attachment]": direct_upload.relation.cached_attachment,
format: :json),
method: :delete,
remote: true,
class: "delete remove-cached-attachment"
end
end

View File

@@ -8,12 +8,12 @@ module DocumentablesHelper
documentable.class.max_documents_allowed
end
def max_file_size(documentable)
bytes_to_mega(documentable.class.max_file_size)
def max_file_size(documentable_class)
bytes_to_mega(documentable_class.max_file_size)
end
def accepted_content_types(documentable)
documentable.class.accepted_content_types
def accepted_content_types(documentable_class)
documentable_class.accepted_content_types
end
def accepted_content_types_extensions(documentable_class)
@@ -22,20 +22,19 @@ module DocumentablesHelper
.join(",")
end
def humanized_accepted_content_types(documentable)
documentable.class.accepted_content_types
.collect{ |content_type| content_type.split("/").last }
.join(", ")
def documentable_humanized_accepted_content_types(documentable_class)
documentable_class.accepted_content_types
.collect{ |content_type| content_type.split("/").last }
.join(", ")
end
def documentables_note(documentable)
t "documents.form.note", max_documents_allowed: max_documents_allowed(documentable),
accepted_content_types: humanized_accepted_content_types(documentable),
max_file_size: max_file_size(documentable)
accepted_content_types: documentable_humanized_accepted_content_types(documentable.class),
max_file_size: max_file_size(documentable.class)
end
def max_documents_allowed?(documentable)
documentable.documents.count >= documentable.class.max_documents_allowed
end
end

View File

@@ -4,7 +4,7 @@ module DocumentsHelper
document.attachment_file_name
end
def errors_on_attachment(document)
def document_errors_on_attachment(document)
document.errors[:attachment].join(', ') if document.errors.key?(:attachment)
end
@@ -12,78 +12,53 @@ module DocumentsHelper
bytes / Numeric::MEGABYTE
end
def document_nested_field_name(document, index, field)
parent = document.documentable_type.parameterize.underscore
"#{parent.parameterize}[documents_attributes][#{index}][#{field}]"
end
def document_nested_field_id(document, index, field)
parent = document.documentable_type.parameterize.underscore
"#{parent.parameterize}_documents_attributes_#{index}_#{field}"
end
def document_nested_field_wrapper_id(index)
"document_#{index}"
end
def render_destroy_document_link(document, index)
if document.persisted?
def render_destroy_document_link(builder, document)
if !document.persisted? && document.cached_attachment.present?
link_to t('documents.form.delete_button'),
document_path(document, index: index, nested_document: true),
method: :delete,
remote: true,
data: { confirm: t('documents.actions.destroy.confirm') },
class: "delete float-right"
elsif !document.persisted? && document.cached_attachment.present?
link_to t('documents.form.delete_button'),
destroy_upload_documents_path(path: document.cached_attachment,
nested_document: true,
index: index,
documentable_type: document.documentable_type,
documentable_id: document.documentable_id),
method: :delete,
remote: true,
class: "delete float-right"
direct_upload_destroy_url("direct_upload[resource_type]": document.documentable_type,
"direct_upload[resource_id]": document.documentable_id,
"direct_upload[resource_relation]": "documents",
"direct_upload[cached_attachment]": document.cached_attachment),
method: :delete,
remote: true,
class: "delete remove-cached-attachment"
else
link_to t('documents.form.delete_button'),
"#",
class: "delete float-right remove-document"
link_to_remove_association t('documents.form.delete_button'), builder, class: "delete remove-document"
end
end
def render_attachment(document, index)
html = file_field_tag :attachment,
accept: accepted_content_types_extensions(document.documentable_type.constantize),
class: 'js-document-attachment',
data: {
url: document_direct_upload_url(document),
cached_attachment_input_field: document_nested_field_id(document, index, :cached_attachment),
multiple: false,
index: index,
nested_document: true
},
name: document_nested_field_name(document, index, :attachment),
id: document_nested_field_id(document, index, :attachment)
if document.attachment.blank? && document.cached_attachment.blank?
klass = document.errors[:attachment].any? ? "error" : ""
html += label_tag document_nested_field_id(document, index, :attachment),
t("documents.form.attachment_label"),
class: "button hollow #{klass}"
if document.errors[:attachment].any?
html += content_tag :small, class: "error" do
errors_on_attachment(document)
end
end
end
def render_attachment(builder, document)
klass = document.errors[:attachment].any? ? "error" : ""
klass = document.persisted? || document.cached_attachment.present? ? " hide" : ""
html = builder.label :attachment,
t("documents.form.attachment_label"),
class: "button hollow #{klass}"
html += builder.file_field :attachment,
label: false,
accept: accepted_content_types_extensions(document.documentable_type.constantize),
class: 'js-document-attachment',
data: {
url: document_direct_upload_url(document),
nested_document: true
}
html
end
def document_direct_upload_url(document)
upload_documents_url(
documentable_type: document.documentable_type,
documentable_id: document.documentable_id,
format: :js
)
direct_uploads_url("direct_upload[resource_type]": document.documentable_type,
"direct_upload[resource_id]": document.documentable_id,
"direct_upload[resource_relation]": "documents")
end
def document_item_link(document)
link_to "#{document.title} <small>(#{document.humanized_content_type} | \
#{number_to_human_size(document.attachment_file_size)}</small>)".html_safe,
document.attachment.url,
target: "_blank",
title: t("shared.target_blank_html")
end
end

View File

@@ -12,7 +12,7 @@ module FlagsHelper
def flagged?(flaggable)
if flaggable.is_a? Comment
@comment_flags[flaggable.id]
@comment_flags[flaggable.id] unless flaggable.commentable_type == "Poll"
else
Flag.flagged?(current_user, flaggable)
end

View File

@@ -0,0 +1,40 @@
module ImageablesHelper
def can_destroy_image?(imageable)
imageable.image.present? && can?(:destroy, imageable.image)
end
def imageable_class(imageable)
imageable.class.name.parameterize('_')
end
def imageable_max_file_size
bytes_to_megabytes(Image::MAX_IMAGE_SIZE)
end
def bytes_to_megabytes(bytes)
bytes / Numeric::MEGABYTE
end
def imageable_accepted_content_types
Image::ACCEPTED_CONTENT_TYPE
end
def imageable_accepted_content_types_extensions
Image::ACCEPTED_CONTENT_TYPE
.collect{ |content_type| ".#{content_type.split('/').last}" }
.join(",")
end
def imageable_humanized_accepted_content_types
Image::ACCEPTED_CONTENT_TYPE
.collect{ |content_type| content_type.split("/").last }
.join(", ")
end
def imageables_note(_imageable)
t "images.form.note", accepted_content_types: imageable_humanized_accepted_content_types,
max_file_size: imageable_max_file_size
end
end

View File

@@ -0,0 +1,79 @@
module ImagesHelper
def image_absolute_url(image, version)
return "" unless image
if Paperclip::Attachment.default_options[:storage] == :filesystem
URI(request.url) + image.attachment.url(version)
else
investment.image_url(version)
end
end
def image_first_recommendation(image)
t "images.#{image.imageable.class.name.parameterize.underscore}.recommendation_one_html",
title: image.imageable.title
end
def image_attachment_file_name(image)
image.attachment_file_name
end
def image_errors_on_attachment(image)
image.errors[:attachment].join(', ') if image.errors.key?(:attachment)
end
def image_bytes_to_megabytes(bytes)
bytes / Numeric::MEGABYTE
end
def image_class(image)
image.persisted? ? "persisted-image" : "cached-image"
end
def render_destroy_image_link(builder, image)
if !image.persisted? && image.cached_attachment.present?
link_to t('images.form.delete_button'),
direct_upload_destroy_url("direct_upload[resource_type]": image.imageable_type,
"direct_upload[resource_id]": image.imageable_id,
"direct_upload[resource_relation]": "image",
"direct_upload[cached_attachment]": image.cached_attachment),
method: :delete,
remote: true,
class: "delete remove-cached-attachment"
else
link_to_remove_association t('images.form.delete_button'), builder, class: "delete remove-image"
end
end
def render_image_attachment(builder, imageable, image)
klass = image.errors[:attachment].any? ? "error" : ""
klass = image.persisted? || image.cached_attachment.present? ? " hide" : ""
html = builder.label :attachment,
t("images.form.attachment_label"),
class: "button hollow #{klass}"
html += builder.file_field :attachment,
label: false,
accept: imageable_accepted_content_types_extensions,
class: 'js-image-attachment',
data: {
url: image_direct_upload_url(imageable),
nested_image: true
}
html
end
def render_image(image, version, show_caption = true)
version = image.persisted? ? version : :original
render partial: "images/image", locals: { image: image,
version: version,
show_caption: show_caption }
end
def image_direct_upload_url(imageable)
direct_uploads_url("direct_upload[resource_type]": imageable.class.name,
"direct_upload[resource_id]": imageable.id,
"direct_upload[resource_relation]": "image")
end
end

View File

@@ -1,6 +1,6 @@
module LegislationHelper
def format_date(date)
l(date, format: "%d %b %Y") if date
l(date, format: "%d %h %Y") if date
end
def format_date_for_calendar_form(date)

View File

@@ -0,0 +1,67 @@
module MapLocationsHelper
def map_location_available?(map_location)
map_location.present? && map_location.available?
end
def map_location_latitude(map_location)
map_location.present? && map_location.latitude.present? ? map_location.latitude : Setting["map_latitude"]
end
def map_location_longitude(map_location)
map_location.present? && map_location.longitude.present? ? map_location.longitude : Setting["map_longitude"]
end
def map_location_zoom(map_location)
map_location.present? && map_location.zoom.present? ? map_location.zoom : Setting["map_zoom"]
end
def map_location_input_id(prefix, attribute)
"#{prefix}_map_location_attributes_#{attribute}"
end
def map_location_remove_marker_link_id(map_location)
"remove-marker-link-#{dom_id(map_location)}"
end
def render_map(map_location, parent_class, editable, remove_marker_label)
map = content_tag_for :div,
map_location,
class: "map",
data: prepare_map_settings(map_location, editable, parent_class)
map += map_location_remove_marker(map_location, remove_marker_label) if editable
map
end
def map_location_remove_marker(map_location, text)
content_tag :div, class: "text-right" do
content_tag :a,
id: map_location_remove_marker_link_id(map_location),
href: "#",
class: "location-map-remove-marker-button delete" do
text
end
end
end
private
def prepare_map_settings(map_location, editable, parent_class)
options = {
map: "",
map_center_latitude: map_location_latitude(map_location),
map_center_longitude: map_location_longitude(map_location),
map_zoom: map_location_zoom(map_location),
map_tiles_provider: Rails.application.secrets.map_tiles_provider,
map_tiles_provider_attribution: Rails.application.secrets.map_tiles_provider_attribution,
marker_editable: editable,
marker_latitude: map_location.latitude,
marker_longitude: map_location.longitude,
marker_remove_selector: "##{map_location_remove_marker_link_id(map_location)}",
latitude_input_selector: "##{map_location_input_id(parent_class, 'latitude')}",
longitude_input_selector: "##{map_location_input_id(parent_class, 'longitude')}",
zoom_input_selector: "##{map_location_input_id(parent_class, 'zoom')}"
}
end
end

View File

@@ -1,7 +1,7 @@
module PollRecountsHelper
def total_recounts_by_booth(booth_assignment)
booth_assignment.total_results.any? ? booth_assignment.total_results.to_a.sum(&:amount) : nil
booth_assignment.recounts.any? ? booth_assignment.recounts.to_a.sum(&:total_amount) : nil
end
end

View File

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

View File

@@ -12,8 +12,8 @@ module ProposalsHelper
percentage = (proposal.total_votes.to_f * 100 / Proposal.votes_needed_for_success)
case percentage
when 0 then "0%"
when 0..(0.1) then "0.1%"
when (0.1)..100 then number_to_percentage(percentage, strip_insignificant_zeros: true, precision: 1)
when 0..0.1 then "0.1%"
when 0.1..100 then number_to_percentage(percentage, strip_insignificant_zeros: true, precision: 1)
else "100%"
end
end
@@ -32,8 +32,12 @@ module ProposalsHelper
Proposal::RETIRE_OPTIONS.collect { |option| [ t("proposals.retire_options.#{option}"), option ] }
end
def can_create_document?(document, proposal)
can?(:create, document) && proposal.documents.size < Proposal.max_documents_allowed
def empty_recommended_proposals_message_text(user)
if user.interests.any?
t('proposals.index.recommendations.without_results')
else
t('proposals.index.recommendations.without_interests')
end
end
def author_of_proposal?(proposal)
@@ -44,4 +48,4 @@ module ProposalsHelper
current_user && proposal.editable_by?(current_user)
end
end
end

View File

@@ -1,15 +1,30 @@
module ShiftsHelper
def shift_dates_select_options(polls)
options = []
(start_date(polls)..end_date(polls)).each do |date|
options << [l(date, format: :long), l(date)]
def shift_vote_collection_dates(booth, polls)
return [] if polls.blank?
date_options((start_date(polls)..end_date(polls)), Poll::Shift.tasks[:vote_collection], booth)
end
def shift_recount_scrutiny_dates(booth, polls)
return [] if polls.blank?
dates = polls.map(&:ends_at).map(&:to_date).sort.inject([]) do |total, date|
initial_date = date < Date.current ? Date.current : date
total << (initial_date..date + Poll::RECOUNT_DURATION).to_a
end
options_for_select(options, params[:date])
date_options(dates.flatten.uniq, Poll::Shift.tasks[:recount_scrutiny], booth)
end
def date_options(dates, task_id, booth)
valid_dates(dates, task_id, booth).map { |date| [l(date, format: :long), l(date)] }
end
def valid_dates(dates, task_id, booth)
dates.reject { |date| officer_shifts(task_id, booth).include?(date) }
end
def start_date(polls)
polls.map(&:starts_at).min.to_date
start_date = polls.map(&:starts_at).min.to_date
start_date < Date.current ? Date.current : start_date
end
def end_date(polls)
@@ -20,4 +35,9 @@ module ShiftsHelper
officers.collect { |officer| [officer.name, officer.id] }
end
private
def officer_shifts(task_id, booth)
@officer.shifts.where(task: task_id, booth: booth).map(&:date)
end
end

View File

@@ -8,6 +8,8 @@ module TagsHelper
proposals_path(search: tag_name)
when 'budget/investment'
budget_investments_path(@budget, search: tag_name)
when 'legislation/proposal'
legislation_process_proposals_path(@process, search: tag_name)
else
'#'
end
@@ -22,6 +24,8 @@ module TagsHelper
proposal_path(taggable)
when 'budget/investment'
budget_investment_path(taggable.budget_id, taggable)
when 'legislation/proposal'
legislation_process_proposal_path(@process, taggable)
else
'#'
end

View File

@@ -52,12 +52,8 @@ module UsersHelper
current_user && current_user.manager?
end
def current_poll_officer?
current_user && current_user.poll_officer?
end
def show_admin_menu?
current_administrator? || current_moderator? || current_valuator? || current_manager? || current_poll_officer?
current_administrator? || current_moderator? || current_valuator? || current_manager?
end
def interests_title_text(user)

View File

@@ -0,0 +1,58 @@
module WelcomeHelper
def active_class(index)
"is-active is-in" if index.zero?
end
def slide_display(index)
"display: none;" if index.positive?
end
def recommended_path(recommended)
case recommended.class.name
when "Debate"
debate_path(recommended)
when "Proposal"
proposal_path(recommended)
else
'#'
end
end
def render_recommendation_image(recommended, image_default)
image_path = calculate_image_path(recommended, image_default)
image_tag(image_path) if image_path.present?
end
def calculate_image_path(recommended, image_default)
if recommended.try(:image) && recommended.image.present? && recommended.image.attachment.exists?
recommended.image.attachment.send("url", :medium)
elsif image_default.present?
image_default
end
end
def calculate_carousel_size(debates, proposals, apply_offset)
offset = calculate_offset(debates, proposals, apply_offset)
centered = calculate_centered(debates, proposals)
"#{offset if offset} #{centered if centered}"
end
def calculate_centered(debates, proposals)
if (debates.blank? && proposals.any?) ||
(debates.any? && proposals.blank?)
centered = "medium-centered large-centered"
end
end
def calculate_offset(debates, proposals, apply_offset)
if debates.any? && proposals.any?
offset = if apply_offset
"medium-offset-2 large-offset-2"
else
"end"
end
end
end
end