2010-05-14 15:12:31 -07:00
|
|
|
module ApplicationHelper
|
2012-12-29 22:46:36 -08:00
|
|
|
include FragmentLocalization
|
|
|
|
|
2012-07-29 13:45:12 -07:00
|
|
|
def absolute_url(path_or_url)
|
|
|
|
if path_or_url.include?('://') # already an absolute URL
|
|
|
|
path_or_url
|
|
|
|
else # a relative path
|
|
|
|
request.protocol + request.host_with_port + path_or_url
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-11-08 17:40:03 -08:00
|
|
|
def add_body_class(class_name)
|
|
|
|
@body_class ||= ''
|
|
|
|
@body_class << " #{class_name}"
|
|
|
|
end
|
2011-05-13 05:20:29 -07:00
|
|
|
|
2010-11-05 15:45:05 -07:00
|
|
|
def body_class
|
2024-02-18 20:12:14 -08:00
|
|
|
controller = params[:controller].gsub("/", "-")
|
|
|
|
"#{controller} #{controller}-#{params[:action]}".tap do |output|
|
2010-11-08 17:40:03 -08:00
|
|
|
output << @body_class if @body_class
|
|
|
|
end
|
2010-11-05 15:45:05 -07:00
|
|
|
end
|
2011-05-13 05:20:29 -07:00
|
|
|
|
2015-02-25 11:49:18 -08:00
|
|
|
def advertise_campaign_progress(campaign, &block)
|
|
|
|
if campaign && campaign.advertised?
|
|
|
|
campaign_progress(campaign, &block)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-09-24 19:39:49 -07:00
|
|
|
def cents_to_currency(cents, options={})
|
|
|
|
number_to_currency(cents / 100.0, options)
|
2015-09-22 22:19:43 -07:00
|
|
|
end
|
|
|
|
|
2014-09-11 15:40:37 -07:00
|
|
|
def campaign_progress(campaign, &block)
|
|
|
|
if campaign
|
2011-10-10 20:06:46 -07:00
|
|
|
if block_given?
|
|
|
|
content = capture(&block)
|
|
|
|
else
|
2015-09-24 19:39:49 -07:00
|
|
|
if campaign.complete?
|
|
|
|
pitch = "We've met this year's fundraising goal! Thanks, everybody!"
|
|
|
|
prompt = "Learn more"
|
|
|
|
elsif campaign.remaining < 200_00
|
2017-01-09 11:35:55 -08:00
|
|
|
estimate = (campaign.remaining.to_f / 10_00).ceil * 10_00
|
|
|
|
if estimate == campaign.remaining
|
|
|
|
pitch = "We're only #{cents_to_currency(estimate, precision: 0)} away from paying #{campaign.purpose}!"
|
|
|
|
else
|
|
|
|
pitch = "We're less than #{cents_to_currency(estimate, precision: 0)} away from paying #{campaign.purpose}!"
|
|
|
|
end
|
2015-09-22 22:19:43 -07:00
|
|
|
prompt = "Donate now"
|
|
|
|
else
|
|
|
|
pitch = "Help Dress to Impress stay online!"
|
|
|
|
prompt = "Learn more"
|
|
|
|
end
|
2014-09-11 16:09:00 -07:00
|
|
|
content = link_to(
|
2015-09-22 22:19:43 -07:00
|
|
|
content_tag(:span, pitch) +
|
|
|
|
content_tag(:span, prompt, :class => 'button'), donate_path)
|
2011-10-10 20:06:46 -07:00
|
|
|
end
|
|
|
|
|
2014-09-11 15:40:37 -07:00
|
|
|
meter = content_tag(:div, nil, :class => 'campaign-progress',
|
|
|
|
style: "width: #{campaign.progress_percent}%;")
|
|
|
|
label = content_tag(:div, content, :class => 'campaign-progress-label')
|
|
|
|
content_tag(:div, meter + label, :class => 'campaign-progress-wrapper')
|
2011-07-09 08:45:30 -07:00
|
|
|
end
|
2011-07-01 12:38:13 -07:00
|
|
|
end
|
|
|
|
|
2011-07-26 15:56:14 -07:00
|
|
|
def canonical_path(resource)
|
2013-01-25 13:09:48 -08:00
|
|
|
I18n.with_locale(I18n.default_locale) do
|
|
|
|
content_for :meta, tag(:link, :rel => 'canonical', :href => url_for(resource))
|
|
|
|
end
|
2011-07-26 15:56:14 -07:00
|
|
|
end
|
|
|
|
|
2011-07-30 21:59:29 -07:00
|
|
|
def contact_email
|
2023-11-11 15:48:05 -08:00
|
|
|
"matchu@openneo.net"
|
2011-07-30 21:59:29 -07:00
|
|
|
end
|
|
|
|
|
2024-04-12 07:14:34 -07:00
|
|
|
# SVG icon source from Chakra UI!
|
|
|
|
EXTERNAL_LINK_SVG_SOURCE = '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><path d="M15 3h6v6"></path><path d="M10 14L21 3"></path></g>'.html_safe
|
|
|
|
def external_link_icon
|
|
|
|
content_tag :svg, EXTERNAL_LINK_SVG_SOURCE, alt: "(external link)",
|
|
|
|
viewBox: "0 0 24 24", style: "width: 1em; height: 1em"
|
|
|
|
end
|
|
|
|
|
2010-05-15 10:47:46 -07:00
|
|
|
def flashes
|
2010-11-05 15:45:05 -07:00
|
|
|
raw(flash.inject('') do |html, pair|
|
2010-05-15 10:47:46 -07:00
|
|
|
key, value = pair
|
2011-07-15 14:21:18 -07:00
|
|
|
html + content_tag('p', value, :class => "flash #{key}")
|
2010-11-05 15:45:05 -07:00
|
|
|
end)
|
|
|
|
end
|
2011-05-13 05:20:29 -07:00
|
|
|
|
2010-11-30 13:52:38 -08:00
|
|
|
def hide_home_link
|
|
|
|
@hide_home_link = true
|
|
|
|
end
|
2011-05-13 05:20:29 -07:00
|
|
|
|
2010-11-30 13:52:38 -08:00
|
|
|
def home_link?
|
|
|
|
!@hide_home_link
|
|
|
|
end
|
2011-05-13 05:20:29 -07:00
|
|
|
|
2024-01-29 04:21:19 -08:00
|
|
|
def support_staff?
|
|
|
|
user_signed_in? && current_user.support_staff?
|
|
|
|
end
|
|
|
|
|
|
|
|
def impress_2020_meta_tags
|
2024-02-22 13:07:43 -08:00
|
|
|
origin = Rails.configuration.impress_2020_origin
|
2024-05-02 13:13:54 -07:00
|
|
|
support_secret = Rails.application.credentials.dig(
|
|
|
|
:impress_2020, :support_secret)
|
2024-02-22 13:07:43 -08:00
|
|
|
|
2024-01-29 04:21:19 -08:00
|
|
|
capture do
|
2024-02-22 13:07:43 -08:00
|
|
|
concat tag("meta", name: "impress-2020-origin", content: origin)
|
|
|
|
|
|
|
|
if support_staff? && support_secret.present?
|
2024-01-29 04:21:19 -08:00
|
|
|
concat tag("meta", name: "impress-2020-support-secret",
|
2024-02-22 13:07:43 -08:00
|
|
|
content: support_secret)
|
2024-01-29 04:21:19 -08:00
|
|
|
end
|
|
|
|
end
|
2024-01-28 07:00:29 -08:00
|
|
|
end
|
|
|
|
|
2010-12-06 15:50:13 -08:00
|
|
|
JAVASCRIPT_LIBRARIES = {
|
2023-10-25 15:16:46 -07:00
|
|
|
:jquery => 'https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js',
|
|
|
|
:jquery_tmpl => 'https://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js',
|
2010-12-06 15:50:13 -08:00
|
|
|
}
|
2011-05-13 05:20:29 -07:00
|
|
|
|
2010-12-06 15:50:13 -08:00
|
|
|
def include_javascript_libraries(*library_names)
|
|
|
|
raw(library_names.inject('') do |html, name|
|
2024-03-13 21:26:22 -07:00
|
|
|
html + javascript_include_tag(JAVASCRIPT_LIBRARIES[name], defer: true)
|
2010-12-06 15:50:13 -08:00
|
|
|
end)
|
|
|
|
end
|
2012-12-29 22:46:36 -08:00
|
|
|
|
2013-01-11 09:46:14 -08:00
|
|
|
def locale_options
|
2013-01-17 20:16:34 -08:00
|
|
|
current_locale_is_public = false
|
|
|
|
options = I18n.public_locales.map do |available_locale|
|
|
|
|
current_locale_is_public = true if I18n.locale == available_locale
|
2013-02-06 08:59:25 -08:00
|
|
|
# Include fallbacks data on the tag. Right now it's used in blog
|
|
|
|
# localization, but may conceivably be used for something else later.
|
|
|
|
[translate('locale_name', :locale => available_locale), available_locale,
|
|
|
|
{'data-fallbacks' => I18n.fallbacks[available_locale].join(',')}]
|
2013-01-11 09:46:14 -08:00
|
|
|
end
|
2013-01-17 20:16:34 -08:00
|
|
|
|
|
|
|
unless current_locale_is_public
|
|
|
|
name = translate('locale_name', :locale => I18n.locale) + ' (alpha)'
|
|
|
|
options << [name, I18n.locale]
|
|
|
|
end
|
|
|
|
|
|
|
|
options
|
2013-01-11 09:46:14 -08:00
|
|
|
end
|
|
|
|
|
2013-01-04 17:28:00 -08:00
|
|
|
def localized_cache(key={}, &block)
|
2012-12-29 22:46:36 -08:00
|
|
|
localized_key = localize_fragment_key(key, locale)
|
2023-07-22 12:52:53 -07:00
|
|
|
# TODO: The digest feature is handy, but it's not compatible with how we
|
|
|
|
# check for fragments existence in the controller, so skip it for now.
|
|
|
|
cache(localized_key, skip_digest: true, &block)
|
2012-12-29 22:46:36 -08:00
|
|
|
end
|
2011-05-13 05:20:29 -07:00
|
|
|
|
2023-08-06 15:52:05 -07:00
|
|
|
def auth_user_sign_in_path_with_return_to
|
|
|
|
new_auth_user_session_path :return_to => request.fullpath
|
2010-10-18 15:17:08 -07:00
|
|
|
end
|
2011-05-13 05:20:29 -07:00
|
|
|
|
2010-11-05 17:09:03 -07:00
|
|
|
def origin_tag(value)
|
|
|
|
hidden_field_tag 'origin', value, :id => nil
|
|
|
|
end
|
2012-07-29 13:45:12 -07:00
|
|
|
|
|
|
|
def open_graph(properties)
|
|
|
|
if @open_graph
|
|
|
|
@open_graph.merge! properties
|
|
|
|
else
|
|
|
|
@open_graph = properties
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def open_graph_tags
|
|
|
|
if @open_graph
|
|
|
|
@open_graph.inject('') do |output, property|
|
|
|
|
key, value = property
|
|
|
|
output + tag(:meta, :property => "og:#{key}", :content => value)
|
|
|
|
end.html_safe
|
|
|
|
end
|
|
|
|
end
|
2011-07-15 20:14:26 -07:00
|
|
|
|
2024-05-14 16:03:35 -07:00
|
|
|
# Includes a stylesheet designed for this specific page of the app, which
|
|
|
|
# should be removed when navigating to another page. We use Turbo's
|
|
|
|
# `data-turbo-track="dynamic"` option to do this.
|
|
|
|
def page_stylesheet_link_tag(src, options={})
|
|
|
|
options = {data: {"turbo-track": "dynamic"}}.deep_merge(options)
|
|
|
|
stylesheet_link_tag src, options
|
|
|
|
end
|
|
|
|
|
2011-07-29 07:52:04 -07:00
|
|
|
def secondary_nav(&block)
|
|
|
|
content_for :before_flashes,
|
|
|
|
content_tag(:nav, :id => 'secondary-nav', &block)
|
|
|
|
end
|
|
|
|
|
2011-05-13 05:20:29 -07:00
|
|
|
def show_title_header?
|
2023-10-12 17:51:44 -07:00
|
|
|
params[:controller] != 'items' && !@hide_title_header
|
|
|
|
end
|
|
|
|
|
|
|
|
def hide_title_header
|
|
|
|
@hide_title_header = true
|
2011-05-13 05:20:29 -07:00
|
|
|
end
|
|
|
|
|
2010-11-11 10:43:22 -08:00
|
|
|
def signed_in_meta_tag
|
|
|
|
%(<meta name="user-signed-in" content="#{user_signed_in?}">).html_safe
|
|
|
|
end
|
2014-01-18 19:54:11 -08:00
|
|
|
|
|
|
|
def current_user_id_meta_tag
|
|
|
|
%(<meta name="current-user-id" content="#{current_user.id}">).html_safe
|
|
|
|
end
|
2012-12-29 23:13:58 -08:00
|
|
|
|
|
|
|
def labeled_time_ago_in_words(time)
|
|
|
|
content_tag :abbr, time_ago_in_words(time), :title => time
|
|
|
|
end
|
2011-05-13 05:20:29 -07:00
|
|
|
|
2010-11-06 08:52:58 -07:00
|
|
|
def title(value)
|
|
|
|
content_for :title, value
|
|
|
|
end
|
2014-04-02 21:00:50 -07:00
|
|
|
|
|
|
|
def md(text)
|
|
|
|
RDiscount.new(text).to_html.html_safe
|
|
|
|
end
|
2024-02-29 11:22:12 -08:00
|
|
|
|
|
|
|
def terms_updated_at
|
|
|
|
Date.new(2024, 2, 29)
|
|
|
|
end
|
|
|
|
|
|
|
|
def terms_updated_timestamp
|
|
|
|
terms_updated_at.strftime("%b %Y")
|
|
|
|
end
|
|
|
|
|
|
|
|
def terms_updated_recently
|
|
|
|
terms_updated_at >= 2.months.ago
|
|
|
|
end
|
2012-12-29 22:46:36 -08:00
|
|
|
|
2013-01-04 17:28:00 -08:00
|
|
|
def translate_markdown(key, options={})
|
2023-08-03 16:37:45 -07:00
|
|
|
md translate("#{key}_markdown", **options)
|
2013-01-04 17:28:00 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
alias_method :tmd, :translate_markdown
|
|
|
|
|
2013-01-04 15:58:25 -08:00
|
|
|
def translate_with_links(key, options={})
|
|
|
|
nonlink_options = {}
|
|
|
|
link_urls = {}
|
|
|
|
|
|
|
|
options.each do |key, value|
|
|
|
|
str_key = key.to_s
|
|
|
|
if str_key.end_with? '_link_url'
|
|
|
|
link_key = str_key[0..-5] # "abcdef_link_url" => "abcdef_link"
|
|
|
|
link_urls[link_key] = value
|
|
|
|
else
|
|
|
|
nonlink_options[key] = value
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
link_options = {}
|
|
|
|
link_urls.each do |link_key, url|
|
2023-08-03 16:37:45 -07:00
|
|
|
content = translate("#{key}.#{link_key}_content", **nonlink_options)
|
2013-01-04 15:58:25 -08:00
|
|
|
link_options[link_key.to_sym] = link_to(content, url)
|
|
|
|
end
|
|
|
|
|
|
|
|
converted_options = link_options.merge(nonlink_options)
|
2023-08-03 16:37:45 -07:00
|
|
|
translate("#{key}.main_html", **converted_options)
|
2013-01-04 15:58:25 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
alias_method :twl, :translate_with_links
|
|
|
|
|
2012-12-29 22:46:36 -08:00
|
|
|
def userbar_contributions_summary(user)
|
2013-01-08 17:23:22 -08:00
|
|
|
translate_with_links '.userbar.contributions_summary',
|
|
|
|
:contributions_link_url => user_contributions_path(user),
|
|
|
|
:user_points => user.points
|
2012-12-29 22:46:36 -08:00
|
|
|
end
|
2010-05-14 15:12:31 -07:00
|
|
|
end
|
2011-05-13 05:20:29 -07:00
|
|
|
|