2019-03-26 15:32:20 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2019-07-31 20:55:34 +00:00
|
|
|
# Helpers
|
2018-01-02 17:19:25 +00:00
|
|
|
module ApplicationHelper
|
2024-05-24 16:22:28 +00:00
|
|
|
BRACKETS = /[\[\]]/.freeze
|
2024-06-03 20:45:23 +00:00
|
|
|
ALPHA_LARGE = [*'a'..'z', *'A'..'Z'].freeze
|
|
|
|
|
|
|
|
# Devuelve un indentificador aleatorio que puede usarse como atributo
|
|
|
|
# HTML. Reemplaza Nanoid. El primer caracter siempre es alfabético.
|
|
|
|
#
|
|
|
|
# @return [String]
|
|
|
|
def random_id
|
|
|
|
SecureRandom.urlsafe_base64.tap do |s|
|
|
|
|
s[0] = ALPHA_LARGE.sample
|
|
|
|
end
|
|
|
|
end
|
2024-05-23 20:47:02 +00:00
|
|
|
|
2019-08-13 19:09:23 +00:00
|
|
|
# Devuelve el atributo name de un campo anidado en el formato que
|
|
|
|
# esperan los helpers *_field
|
|
|
|
#
|
|
|
|
# [ 'post', :image, :description ]
|
|
|
|
# [ 'post[image]', :description ]
|
|
|
|
# 'post[image][description]'
|
|
|
|
def field_name_for(*names)
|
2018-06-19 20:38:43 +00:00
|
|
|
name = names.pop
|
2019-08-13 19:09:23 +00:00
|
|
|
root = names.shift
|
|
|
|
|
2018-06-19 20:38:43 +00:00
|
|
|
names.each do |n|
|
2024-05-02 19:05:35 +00:00
|
|
|
root += "[#{n}]"
|
2018-06-19 20:38:43 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
[root, name]
|
|
|
|
end
|
|
|
|
|
2024-05-23 20:47:02 +00:00
|
|
|
# Obtiene un ID
|
|
|
|
#
|
|
|
|
# @param base [String]
|
|
|
|
# @param attribute [String, Symbol]
|
|
|
|
def id_for(base, attribute)
|
|
|
|
"#{base.gsub(BRACKETS, '_')}_#{attribute}".squeeze('_')
|
|
|
|
end
|
|
|
|
|
2020-06-28 00:42:15 +00:00
|
|
|
def plain_field_name_for(*names)
|
|
|
|
root, name = field_name_for(*names)
|
|
|
|
|
2024-05-02 19:05:35 +00:00
|
|
|
"#{root}[#{name}]"
|
2020-06-28 00:42:15 +00:00
|
|
|
end
|
|
|
|
|
2019-08-02 00:20:42 +00:00
|
|
|
def distance_of_time_in_words_if_more_than_a_minute(seconds)
|
|
|
|
if seconds > 60
|
|
|
|
distance_of_time_in_words seconds
|
|
|
|
else
|
|
|
|
I18n.t('seconds', seconds: seconds)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-03-04 16:09:36 +00:00
|
|
|
# Sanitizador que elimina todo
|
|
|
|
#
|
|
|
|
# @param html [String]
|
|
|
|
# @return [String]
|
|
|
|
def text_plain(html)
|
|
|
|
sanitize(html, tags: [], attributes: [])
|
|
|
|
end
|
|
|
|
|
|
|
|
# Sanitizador con etiquetas y atributos por defecto
|
|
|
|
#
|
|
|
|
# @param html [String]
|
|
|
|
# @param options [Hash]
|
|
|
|
# @return [String]
|
|
|
|
def sanitize(html, options = {})
|
|
|
|
options[:tags] ||= Sutty::ALLOWED_TAGS
|
|
|
|
options[:attributes] ||= Sutty::ALLOWED_ATTRIBUTES
|
|
|
|
|
|
|
|
super(html, options)
|
2019-08-14 21:19:01 +00:00
|
|
|
end
|
|
|
|
|
2020-08-11 21:52:53 +00:00
|
|
|
# Genera HTML y limpia etiquetas innecesarias
|
|
|
|
#
|
|
|
|
# @param [String]
|
|
|
|
# @param [Hash]
|
|
|
|
# @return [String]
|
2019-02-16 17:30:54 +00:00
|
|
|
def sanitize_markdown(text, options = {})
|
2019-08-14 21:19:01 +00:00
|
|
|
options.merge!(attributes: %w[id href alt class])
|
|
|
|
|
|
|
|
document = CommonMarker
|
|
|
|
.render_doc(text,
|
|
|
|
%i[FOOTNOTES SMART],
|
|
|
|
%i[table strikethrough autolink])
|
|
|
|
|
|
|
|
sanitize(document.to_html, options)
|
2019-02-16 17:30:54 +00:00
|
|
|
end
|
2019-07-31 20:55:34 +00:00
|
|
|
|
|
|
|
def invalid?(model, field)
|
|
|
|
model.errors.messages[field].present?
|
|
|
|
end
|
|
|
|
|
|
|
|
def form_control(model, field)
|
|
|
|
if invalid? model, field
|
|
|
|
'form-control is-invalid'
|
|
|
|
else
|
|
|
|
'form-control'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def form_class(model)
|
|
|
|
model.errors.messages.empty? ? 'needs-validation' : 'was-validated'
|
|
|
|
end
|
2019-08-13 19:09:23 +00:00
|
|
|
|
|
|
|
# Opciones por defecto para el campo de un formulario
|
2020-05-26 21:32:46 +00:00
|
|
|
def field_options(attribute, metadata, **extra)
|
2021-02-11 14:49:15 +00:00
|
|
|
required = extra.key?(:required) ? extra[:required] : metadata.required
|
2020-06-28 00:42:15 +00:00
|
|
|
|
2019-08-13 19:09:23 +00:00
|
|
|
{
|
2020-05-26 21:32:46 +00:00
|
|
|
class: "form-control #{invalid(metadata.post, attribute)} #{extra[:class]}",
|
2020-06-28 00:42:15 +00:00
|
|
|
required: required,
|
2021-03-31 18:04:04 +00:00
|
|
|
disabled: metadata.disabled?,
|
2019-09-12 18:11:39 +00:00
|
|
|
autofocus: (metadata.post.attributes.first == attribute),
|
2019-08-13 19:09:23 +00:00
|
|
|
aria: {
|
|
|
|
describedby: id_for_help(attribute),
|
2020-06-28 00:42:15 +00:00
|
|
|
required: required
|
2019-08-13 19:09:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
# Devuelve la clase is-invalid si el campo tiene un error
|
|
|
|
def invalid(post, attribute)
|
|
|
|
'is-invalid' if post.errors[attribute].present?
|
|
|
|
end
|
|
|
|
|
|
|
|
# Busca la traducción de una etiqueta en los metadatos de un post
|
2021-02-24 19:31:57 +00:00
|
|
|
def post_label_t(*attribute, post:, **extra)
|
|
|
|
required = extra.key?(:required) ? extra[:required] : post[attribute.first].required
|
2019-08-13 19:09:23 +00:00
|
|
|
|
2021-02-24 19:31:57 +00:00
|
|
|
label = post_t(*attribute, post: post, type: :label)
|
|
|
|
label += I18n.t('posts.attributes.required.label') if required
|
2019-08-13 19:09:23 +00:00
|
|
|
|
|
|
|
label
|
|
|
|
end
|
|
|
|
|
|
|
|
def post_help_t(*attribute, post:)
|
|
|
|
post_t(*attribute, post: post, type: :help)
|
|
|
|
end
|
|
|
|
|
|
|
|
def id_for_help(*attribute)
|
|
|
|
"#{attribute.join('-')}-help"
|
|
|
|
end
|
|
|
|
|
|
|
|
def id_for_feedback(*attribute)
|
|
|
|
"#{attribute.join('-')}-feedback"
|
|
|
|
end
|
|
|
|
|
2019-08-16 23:25:07 +00:00
|
|
|
def id_for_datalist(*attribute)
|
|
|
|
"#{attribute.join('-')}-datalist"
|
|
|
|
end
|
|
|
|
|
2019-08-13 19:09:23 +00:00
|
|
|
private
|
|
|
|
|
|
|
|
def post_t(*attribute, post:, type:)
|
|
|
|
post.layout.metadata.dig(*attribute, type.to_s, I18n.locale.to_s) ||
|
2021-03-03 12:43:15 +00:00
|
|
|
post.layout.metadata.dig(*attribute, type.to_s, I18n.default_locale.to_s) ||
|
2019-08-13 19:09:23 +00:00
|
|
|
I18n.t("posts.attributes.#{attribute.join('.')}.#{type}")
|
|
|
|
end
|
2018-01-02 17:19:25 +00:00
|
|
|
end
|