2012-04-15 19:59:39 +02:00
|
|
|
# encoding: utf-8
|
|
|
|
#
|
2009-01-06 11:49:19 +01:00
|
|
|
# Methods added to this helper will be available to all templates in the application.
|
|
|
|
module ApplicationHelper
|
2019-11-01 17:25:20 +01:00
|
|
|
include PathHelper
|
2009-01-06 11:49:19 +01:00
|
|
|
|
|
|
|
def format_time(time = Time.now)
|
2009-01-12 18:26:09 +01:00
|
|
|
I18n.l(time, :format => "%d.%m.%Y %H:%M") unless time.nil?
|
2009-01-06 11:49:19 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def format_date(time = Time.now)
|
2009-01-12 18:26:09 +01:00
|
|
|
I18n.l(time.to_date) unless time.nil?
|
2009-01-06 15:45:19 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def format_datetime(time = Time.now)
|
2009-01-12 18:26:09 +01:00
|
|
|
I18n.l(time) unless time.nil?
|
2009-01-06 11:49:19 +01:00
|
|
|
end
|
2009-08-22 18:14:56 +02:00
|
|
|
|
|
|
|
def format_datetime_timespec(time, format)
|
2015-01-14 21:15:08 +01:00
|
|
|
I18n.l(time, :format => format) unless (time.nil? || format.nil?)
|
2009-08-22 18:14:56 +02:00
|
|
|
end
|
2015-04-03 17:02:55 +02:00
|
|
|
|
2018-09-16 12:05:39 +02:00
|
|
|
def format_currency(amount)
|
|
|
|
class_name = amount < 0 ? 'negative_amout' : 'positive_amount'
|
|
|
|
content_tag :span, number_to_currency(amount), class: class_name
|
|
|
|
end
|
|
|
|
|
2021-02-20 12:16:21 +01:00
|
|
|
# Splits an IBAN into groups of 4 digits displayed with margins in between
|
|
|
|
def format_iban(iban)
|
|
|
|
iban.scan(/..?.?.?/).map{ |item| content_tag(:span, item, style: "margin-right: 0.5em;") }.join.html_safe
|
|
|
|
end
|
|
|
|
|
2009-01-06 11:49:19 +01:00
|
|
|
# Creates ajax-controlled-links for pagination
|
2009-01-14 12:46:01 +01:00
|
|
|
def pagination_links_remote(collection, options = {})
|
|
|
|
per_page = options[:per_page] || @per_page
|
|
|
|
params = options[:params] || {}
|
2009-01-06 11:49:19 +01:00
|
|
|
params = params.merge({:per_page => per_page})
|
2012-10-08 15:24:32 +02:00
|
|
|
paginate collection, :params => params, :remote => true
|
2009-01-06 11:49:19 +01:00
|
|
|
end
|
2015-04-03 17:02:55 +02:00
|
|
|
|
2009-01-06 11:49:19 +01:00
|
|
|
# Link-collection for per_page-options when using the pagination-plugin
|
2009-01-14 12:46:01 +01:00
|
|
|
def items_per_page(options = {})
|
2013-08-12 14:49:23 +02:00
|
|
|
per_page_options = options[:per_page_options] || [20, 50, 100, 500]
|
2009-01-14 12:46:01 +01:00
|
|
|
current = options[:current] || @per_page
|
2011-06-10 12:03:32 +02:00
|
|
|
params = params || {}
|
2009-01-14 12:46:01 +01:00
|
|
|
|
2011-06-10 12:03:32 +02:00
|
|
|
links = per_page_options.map do |per_page|
|
|
|
|
params.merge!({:per_page => per_page})
|
2012-10-08 15:24:32 +02:00
|
|
|
link_class = 'btn'
|
|
|
|
link_class << ' disabled' if per_page == current
|
|
|
|
link_to(per_page, params, :remote => true, class: link_class)
|
|
|
|
end
|
|
|
|
|
2014-05-06 19:02:01 +02:00
|
|
|
if options[:wrap] == false
|
2012-10-08 15:24:32 +02:00
|
|
|
links.join.html_safe
|
2014-05-06 19:02:01 +02:00
|
|
|
else
|
|
|
|
content_tag :div, class: 'btn-group pull-right' do
|
|
|
|
links.join.html_safe
|
|
|
|
end
|
2009-01-06 11:49:19 +01:00
|
|
|
end
|
2012-10-08 15:24:32 +02:00
|
|
|
|
2009-01-06 11:49:19 +01:00
|
|
|
end
|
2011-05-16 11:00:52 +02:00
|
|
|
|
2009-04-03 17:16:39 +02:00
|
|
|
def sort_link_helper(text, key, options = {})
|
2012-11-10 16:44:05 +01:00
|
|
|
# Hmtl options
|
2009-04-03 17:16:39 +02:00
|
|
|
remote = options[:remote].nil? ? true : options[:remote]
|
2012-11-10 16:44:05 +01:00
|
|
|
class_name = case params[:sort]
|
|
|
|
when key then
|
|
|
|
'sortup'
|
|
|
|
when key + '_reverse' then
|
|
|
|
'sortdown'
|
|
|
|
else
|
|
|
|
nil
|
|
|
|
end
|
2009-01-06 11:49:19 +01:00
|
|
|
html_options = {
|
2013-04-10 17:29:06 +02:00
|
|
|
:title => I18n.t('helpers.application.sort_by', text: text),
|
2012-11-10 16:44:05 +01:00
|
|
|
:remote => remote,
|
|
|
|
:class => class_name
|
2009-01-06 11:49:19 +01:00
|
|
|
}
|
2009-04-03 17:16:39 +02:00
|
|
|
|
2012-11-10 16:44:05 +01:00
|
|
|
|
|
|
|
# Url options
|
|
|
|
key += "_reverse" if params[:sort] == key
|
|
|
|
per_page = options[:per_page] || @per_page
|
|
|
|
url_options = params.merge(per_page: per_page, sort: key)
|
|
|
|
url_options.merge!({page: params[:page]}) if params[:page]
|
|
|
|
url_options.merge!({query: params[:query]}) if params[:query]
|
|
|
|
|
|
|
|
link_to(text, url_for(url_options), html_options)
|
2009-01-06 11:49:19 +01:00
|
|
|
end
|
2013-10-03 16:03:13 +02:00
|
|
|
|
|
|
|
# Generates text for table heading for model attribute
|
|
|
|
# When the 'short' option is true, abbreviations will be used:
|
|
|
|
# When there is a non-empty model attribute 'foo', it looks for
|
|
|
|
# the model attribute translation 'foo_short' and use that as
|
2014-01-21 11:55:26 +01:00
|
|
|
# heading, with an abbreviation title of 'foo'. If a translation
|
|
|
|
# 'foo_desc' is present, that is used instead, but that can be
|
|
|
|
# be overridden by the option 'desc'.
|
2013-10-09 23:00:07 +02:00
|
|
|
# Other options are passed through to I18n.
|
2013-10-03 16:03:13 +02:00
|
|
|
def heading_helper(model, attribute, options = {})
|
2014-01-23 16:17:16 +01:00
|
|
|
i18nopts = {count: 2}.merge(options.select {|a| !['short', 'desc'].include?(a) })
|
2013-10-09 23:00:07 +02:00
|
|
|
s = model.human_attribute_name(attribute, i18nopts)
|
2013-10-03 16:03:13 +02:00
|
|
|
if options[:short]
|
2014-01-23 16:17:16 +01:00
|
|
|
desc = options[:desc]
|
|
|
|
desc ||= model.human_attribute_name("#{attribute}_desc".to_sym, options.merge({fallback: true, default: '', count: 2}))
|
2015-01-14 21:15:08 +01:00
|
|
|
desc.blank? && desc = s
|
2014-01-08 18:23:34 +01:00
|
|
|
sshort = model.human_attribute_name("#{attribute}_short".to_sym, options.merge({fallback: true, default: '', count: 2}))
|
2014-01-23 16:17:16 +01:00
|
|
|
s = raw "<abbr title='#{desc}'>#{sshort}</abbr>" unless sshort.blank?
|
2013-10-03 16:03:13 +02:00
|
|
|
end
|
|
|
|
s
|
|
|
|
end
|
2015-04-03 17:02:55 +02:00
|
|
|
|
2009-01-06 11:49:19 +01:00
|
|
|
# Generates a link to the top of the website
|
|
|
|
def link_to_top
|
2012-10-15 21:19:17 +02:00
|
|
|
link_to '#' do
|
|
|
|
content_tag :i, nil, class: 'icon-arrow-up icon-large'
|
|
|
|
end
|
2009-01-06 11:49:19 +01:00
|
|
|
end
|
2015-04-03 17:02:55 +02:00
|
|
|
|
2009-01-06 11:49:19 +01:00
|
|
|
# Returns the weekday. 0 is sunday, 1 is monday and so on
|
|
|
|
def weekday(dayNumber)
|
2013-04-10 17:29:06 +02:00
|
|
|
weekdays = I18n.t('date.day_names')
|
2009-01-06 11:49:19 +01:00
|
|
|
return weekdays[dayNumber]
|
|
|
|
end
|
2015-04-03 17:02:55 +02:00
|
|
|
|
2009-01-06 11:49:19 +01:00
|
|
|
# to set a title for both the h1-tag and the title in the header
|
2009-08-12 18:41:25 +02:00
|
|
|
def title(page_title, show_title = true)
|
2011-05-11 13:38:46 +02:00
|
|
|
content_for(:title) { page_title.to_s }
|
2009-08-12 18:41:25 +02:00
|
|
|
@show_title = show_title
|
|
|
|
end
|
|
|
|
|
|
|
|
def show_title?
|
|
|
|
@show_title
|
2009-01-06 11:49:19 +01:00
|
|
|
end
|
2009-01-08 16:33:27 +01:00
|
|
|
|
|
|
|
def tab_is_active?(tab)
|
2010-03-22 01:58:37 +01:00
|
|
|
tab[:active].detect {|c| controller.controller_path.match(c) }
|
2009-01-08 16:33:27 +01:00
|
|
|
end
|
2009-01-16 16:19:26 +01:00
|
|
|
|
|
|
|
def icon(name, options={})
|
2011-06-10 12:18:55 +02:00
|
|
|
icons = {
|
2013-04-10 17:29:06 +02:00
|
|
|
:delete => { :file => 'b_drop.png', :alt => I18n.t('ui.delete')},
|
|
|
|
:edit => { :file => 'b_edit.png', :alt => I18n.t('ui.edit')},
|
|
|
|
:members => { :file => 'b_users.png', :alt => I18n.t('helpers.application.edit_user')}
|
2011-06-10 12:18:55 +02:00
|
|
|
}
|
2009-10-16 21:06:55 +02:00
|
|
|
options[:alt] ||= icons[name][:alt]
|
|
|
|
options[:title] ||= icons[name][:title]
|
2009-01-16 16:19:26 +01:00
|
|
|
options.merge!({:size => '16x16',:border => "0"})
|
2015-04-03 17:02:55 +02:00
|
|
|
|
2009-01-16 16:19:26 +01:00
|
|
|
image_tag icons[name][:file], options
|
|
|
|
end
|
2009-01-29 21:28:22 +01:00
|
|
|
|
|
|
|
# Remote links with default 'loader'.gif during request
|
|
|
|
def remote_link_to(text, options={})
|
2009-02-10 13:26:10 +01:00
|
|
|
remote_options = {
|
|
|
|
:before => "Element.show('loader')",
|
|
|
|
:success => "Element.hide('loader')",
|
|
|
|
:method => :get
|
|
|
|
}
|
2012-05-12 10:55:20 +02:00
|
|
|
link_to(text, options[:url], remote_options.merge(options))
|
2009-01-29 21:28:22 +01:00
|
|
|
end
|
2009-02-02 16:35:43 +01:00
|
|
|
|
2015-04-03 17:02:55 +02:00
|
|
|
def format_roles(record, icon=false)
|
2017-11-15 23:58:11 +01:00
|
|
|
roles = %w(suppliers article_meta orders pickups finance invoices admin)
|
2015-04-03 17:02:55 +02:00
|
|
|
roles.select! {|role| record.send "role_#{role}?"}
|
|
|
|
names = Hash[roles.map{|r| [r, I18n.t("helpers.application.role_#{r}")]}]
|
|
|
|
if icon
|
|
|
|
roles.map{|r| image_tag("role-#{r}.png", size: '22x22', border: 0, alt: names[r], title: names[r])}.join(' ').html_safe
|
|
|
|
else
|
|
|
|
roles.map{|r| names[r]}.join(', ')
|
|
|
|
end
|
2009-02-02 16:35:43 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def link_to_gmaps(address)
|
2013-04-10 17:29:06 +02:00
|
|
|
link_to h(address), "http://maps.google.com/?q=#{h(address)}", :title => I18n.t('helpers.application.show_google_maps'),
|
2009-02-02 16:35:43 +01:00
|
|
|
:target => "_blank"
|
|
|
|
end
|
2015-04-03 17:02:55 +02:00
|
|
|
|
2014-09-10 13:27:45 +02:00
|
|
|
# Returns flash messages html.
|
|
|
|
#
|
|
|
|
# Use this instead of twitter-bootstrap's +bootstrap_flash+ method for safety, until
|
|
|
|
# CVE-2014-4920 is fixed.
|
|
|
|
#
|
|
|
|
# @return [String] Flash message html.
|
|
|
|
# @see http://blog.nvisium.com/2014/03/reflected-xss-vulnerability-in-twitter.html
|
|
|
|
def bootstrap_flash_patched
|
2012-10-08 11:51:56 +02:00
|
|
|
flash_messages = []
|
|
|
|
flash.each do |type, message|
|
2014-11-21 14:37:56 +01:00
|
|
|
type = :success if type == 'notice'
|
|
|
|
type = :error if type == 'alert'
|
2012-10-08 11:51:56 +02:00
|
|
|
text = content_tag(:div,
|
2013-04-10 17:34:24 +02:00
|
|
|
content_tag(:button, I18n.t('ui.marks.close').html_safe, :class => "close", "data-dismiss" => "alert") +
|
2012-10-08 11:51:56 +02:00
|
|
|
message, :class => "alert fade in alert-#{type}")
|
|
|
|
flash_messages << text if message
|
|
|
|
end
|
|
|
|
flash_messages.join("\n").html_safe
|
|
|
|
end
|
2015-04-03 17:02:55 +02:00
|
|
|
|
2013-06-26 17:56:20 +02:00
|
|
|
# render base errors in a form after failed validation
|
|
|
|
# http://railsapps.github.io/twitter-bootstrap-rails.html
|
|
|
|
def base_errors resource
|
2015-01-14 21:15:08 +01:00
|
|
|
return '' if resource.errors.empty? || resource.errors[:base].empty?
|
2013-06-26 17:56:20 +02:00
|
|
|
messages = resource.errors[:base].map { |msg| content_tag(:li, msg) }.join
|
|
|
|
render :partial => 'shared/base_errors', :locals => {:error_messages => messages}
|
|
|
|
end
|
2012-10-08 11:51:56 +02:00
|
|
|
|
2013-09-20 22:40:13 +02:00
|
|
|
# show a user, depending on settings
|
2013-09-22 02:15:35 +02:00
|
|
|
def show_user(user=@current_user, options = {})
|
2013-09-20 22:40:13 +02:00
|
|
|
if user.nil?
|
|
|
|
"?"
|
|
|
|
elsif FoodsoftConfig[:use_nick]
|
2015-01-14 21:15:08 +01:00
|
|
|
if options[:full] && options[:markup]
|
2013-09-20 22:40:13 +02:00
|
|
|
raw "<b>#{h user.nick}</b> (#{h user.first_name} #{h user.last_name})"
|
|
|
|
elsif options[:full]
|
|
|
|
"#{user.nick} (#{user.first_name} #{user.last_name})"
|
|
|
|
else
|
2013-10-29 18:58:04 +01:00
|
|
|
# when use_nick was changed from false to true, users may exist without nick
|
|
|
|
user.nick.nil? ? I18n.t('helpers.application.nick_fallback') : user.nick
|
2013-09-20 22:40:13 +02:00
|
|
|
end
|
|
|
|
else
|
|
|
|
"#{user.first_name} #{user.last_name}" + (options[:unique] ? " (\##{user.id})" : '')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-03-07 09:51:24 +01:00
|
|
|
# render user presentation linking to default action (plugins can override this)
|
2013-09-20 22:40:13 +02:00
|
|
|
def show_user_link(user=@current_user)
|
2014-03-07 09:51:24 +01:00
|
|
|
show_user user
|
2013-09-20 22:40:13 +02:00
|
|
|
end
|
2014-02-20 12:37:51 +01:00
|
|
|
|
|
|
|
# allow truncate to add title when tooltip option is given
|
|
|
|
def truncate(text, options={}, &block)
|
2015-01-14 21:15:08 +01:00
|
|
|
return text if !text || text.length <= (options[:length] || 30)
|
2014-02-20 12:37:51 +01:00
|
|
|
text_truncated = super(text, options, &block)
|
|
|
|
if options[:tooltip]
|
|
|
|
content_tag :span, text_truncated, title: text
|
|
|
|
else
|
|
|
|
text_truncated
|
|
|
|
end
|
|
|
|
end
|
2014-08-22 12:06:35 +02:00
|
|
|
|
2015-01-19 01:54:08 +01:00
|
|
|
# Expand variables in text
|
|
|
|
# @see Foodsoft::ExpansionVariables#expand
|
|
|
|
def expand(text, options={})
|
|
|
|
Foodsoft::ExpansionVariables.expand(text, options)
|
|
|
|
end
|
|
|
|
|
2015-04-10 18:58:51 +02:00
|
|
|
# @param dismiss [String, Symbol] Bootstrap dismiss value (modal, alert)
|
|
|
|
# @return [String] HTML for close button dismissing
|
|
|
|
def close_button(dismiss)
|
|
|
|
content_tag :button, type: 'button', class: 'close', data: {dismiss: dismiss} do
|
|
|
|
I18n.t('ui.marks.close').html_safe
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-08-22 12:06:35 +02:00
|
|
|
# @return [String] path to foodcoop CSS style (with MD5 parameter for caching)
|
|
|
|
def foodcoop_css_path(options={})
|
2014-09-02 14:15:59 +02:00
|
|
|
super(options.merge({md5: Digest::MD5.hexdigest(FoodsoftConfig[:custom_css].to_s)}))
|
2014-08-22 12:06:35 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
# @return [String] stylesheet tag for foodcoop CSS style (+custom_css+ foodcoop config)
|
|
|
|
# @see #foodcoop_css_path
|
|
|
|
def foodcoop_css_tag(options={})
|
|
|
|
unless FoodsoftConfig[:custom_css].blank?
|
|
|
|
stylesheet_link_tag foodcoop_css_path, media: 'all'
|
|
|
|
end
|
|
|
|
end
|
2015-04-03 17:02:55 +02:00
|
|
|
|
2009-01-06 11:49:19 +01:00
|
|
|
end
|