app/helpers/application_helper.rb
module ApplicationHelper
# Interpret a string as markdown
# @param text the text in markdown format
# @returns an interpreted html_safe string representation of text
def markdown(text)
unless defined?(@@markdown)
parse_options = {autolink: true, underline: true, hightlight: true, strikethrough: true, tables: true, no_intra_emphasis: true, fenced_code_blocks: true, disable_indented_code_blocks: true}
renderer_options = {escape_html: true, hard_wrap: true, prettify: true}
renderer = Redcarpet::Render::HTML.new(renderer_options)
@@markdown = Redcarpet::Markdown.new(renderer, parse_options)
end
@@markdown.render(text).html_safe
end
# Display either yes or no highlighted in green or red
# @param value the boolean value being represented
# @param positive_value (optional, default true) the value to be considered positive (and displayed in green)
# @returns an HTML safe string
def yes_no(value, positive_value=true)
if positive_value == value
return "<span style=\"color: green;\">#{value ? 'yes' : 'no'}</span>".html_safe
else
return "<span style=\"color: red;\">#{value ? 'YES' : 'NO'}</span>".html_safe
end
end
# Display text highlighted in green or red
# @param value the boolean value being represented
# @param positive_value (optional, default true) the value to be considered positive (and displayed in green)
# @param text the text to display
# @returns an HTML safe string
def pos_neg(value, text, positive_value=true, alt_neg_text=nil)
if positive_value == value
return "<span style=\"color: green;\">#{text}</span>".html_safe
else
return "<span style=\"color: red;\">#{alt_neg_text || text}</span>".html_safe
end
end
# Get the date in the chosen format with the day of the month ordinalized
# @param date the time to display in the format
# @param format_string the format string to pass to the strftime methods, after replacing %d with the ordinalized day of the month
# @returns a string representing the date
def ordinalized_date(date, format_string)
return date.strftime(format_string.gsub(/(\%d|%e|%\-d)/, '\1'+date.strftime('%d').to_i.ordinal))
end
# Convert a time to duration to finish a sentance fragment starting "do this by"
# @param time the time to convert to words
# @returns a string
def do_by_time(time)
if time < Time.now
return ordinalized_date(time, '%H:%M on %-d %B %Y')
end
if time.today?
return time.strftime('%H:%M today')
end
if time.to_date == Date.tomorrow
return time.strftime('%H:%M tomorrow')
end
if time.between?(Date.today, Date.today+6.days)
return time.strftime('%H:%M on %A')
end
if time.year == Date.today.year
return ordinalized_date(time, '%H:%M on %A %-d %B')
end
return ordinalized_date(time, '%H:%M on %-d %B %Y')
end
# Create a link for sorting a table by a given column from the model
# @param column a string identifying the column to sort by
# @param title (optional) the column title to use in the link, f not provided the title is generated from column
# @returns a link generated by the link_to helper
def sortable_link(column, title=nil)
css_class = 'sortable'
title ||= column.titleize
css_class += (column == sort_column) ? " sortable_current sortable_#{sort_direction}" : ''
direction = ((column == sort_column) && sort_direction == "asc") ? "desc" : "asc"
target = params.permit(:sort_column, :sort_direction, :page)
.merge({sort_column: column, sort_direction: direction, page: nil})
link_to title, target, {class: css_class}
end
def div_for_password_strength_meter
%q{<div id="password_strength_meter" style="display: inline-block; min-width: 215px; font-weight: bold; color: black; background-color: #7777ff;">No password!</div>}.html_safe
end
# Set title for the page and insert an H1 tag
def page_title(title)
provide :title, title
content_tag 'h1', title
end
# Convert an array of (string or array of string) into a set of li tags for display to the user
def html_from_log_lines(lines)
content_tag :ol do
lines.each do |line|
next line if line.empty?
if line.is_a?(Array)
concat html_from_log_lines(line)
else
concat content_tag(:li, line)
end
end # each line
end # content_tag :ol
end
# Convert an array of (string or array of string) into a set of bulleted lines
def text_from_log_lines(lines, level=0)
output = ''
bullets = "*+>-"
lines.each do |line|
next line if line.empty?
if line.is_a?(Array)
output += text_from_log_lines(line, level+1)
else
output += ' ' * (4 * level)
output += bullets[level % bullets.size] + ' '
output += line
output += "\n"
end
end # each line
return output.chomp
end
def stylesheet_link_tag_if_exists(path, opts = {})
if asset_exists?("#{path}.css")
stylesheet_link_tag(path, opts)
end
end
def javascript_include_tag_if_exists(path, opts = {})
if asset_exists?("#{path}.js")
javascript_include_tag(path, opts)
end
end
def asset_exists?(path)
if Rails.application.config.assets.compile
# Development type environment
!!Rails.application.assets.find_asset(path)
else
# Production type environment
!!Rails.application.assets_manifest.files.values.find{ |v| v['logical_path'].eql?(path) }
end
end
def seconds_to_time(seconds)
fail ArgumentError 'time must be a positive number' if !seconds.is_a?(Numeric) || seconds < 0
parts = []
remaining = seconds
{'second' => 60, 'minute' => 60, 'hour' => 24, 'day' => 7, 'week' => nil}.each do |duration, units|
if units.nil? # Reached the end of the conversions we can do
parts.push "#{remaining} #{duration.pluralize(remaining)}" if remaining > 0
break
end
this_unit = remaining % units
remaining = remaining / units
parts.push "#{this_unit} #{duration.pluralize(this_unit)}" if this_unit > 0
break if remaining <= 0 # No more time left to split
end
parts.reverse.to_sentence
end
end