Files
manyfold/app/helpers/application_helper.rb
T

299 lines
8.9 KiB
Ruby

module ApplicationHelper
def site_name(default: translate("application.title"))
SiteSettings.site_name.presence || default
end
def site_tagline
SiteSettings.site_tagline.presence || t("application.tagline")
end
def site_icon
SiteSettings.site_icon.presence || "roundel.svg"
end
def icon_for(klass)
case klass.name
when "Creator"
"person"
when "Collection"
"collection"
when "Library"
"boxes"
when "Model"
"box"
when "ModelFile"
"file"
when "User"
"person"
end
end
def markdownify(text)
Kramdown::Document.new(
sanitize(text),
header_offset: 2,
input: "GFM"
).to_html.html_safe # rubocop:disable Rails/OutputSafety
end
def card(style, title = nil, options = {}, &content)
id = options[:id] || "card-#{SecureRandom.hex(4)}"
card_class = ["card", "mb-4", options[:class]].join(" ")
if options[:skip_link]
skiplink = skip_link(options[:skip_link][:target], options[:skip_link][:text])
card_class += " skip-link-container"
end
tag.div class: card_class, data: options[:data], id: id do
safe_join([
if title.present?
tag.div(class: "card-header text-white bg-#{style}") do
options[:collapse] ?
safe_join([
title,
tag.span(Icon(icon: "arrows-expand", label: t("general.expand")), class: "float-end d-#{options[:collapse]}-none"),
tag.a(
nil,
class: "link-unstyled stretched-link d-#{options[:collapse]}-none",
"data-bs-toggle": "collapse",
"data-bs-target": "##{id}-collapse",
"aria-expanded": false,
"aria-controls": "#{id}-collapse"
)
]) :
title
end
end,
skiplink,
tag.div(class: "card-body #{"collapse d-#{options[:collapse]}-block" if options[:collapse]}", id: "#{id}-collapse") do
tag.div class: "card-text" do
yield
end
end
].compact)
end
end
def text_input_row(form, attribute, options = {})
TextInputRow(
form: form,
attribute: attribute,
label: options.delete(:label),
help: options.delete(:help),
options: options
)
end
def password_input_row(form, attribute, options = {})
PasswordInputRow(
form: form,
attribute: attribute,
strength_meter: options.delete(:strength_meter),
label: options.delete(:label),
help: options.delete(:help),
options: options
)
end
def url_input_row(form, attribute, options = {})
UrlInputRow(
form: form,
attribute: attribute,
label: options.delete(:label),
help: options.delete(:help),
options: options
)
end
def numeric_input_row(form, attribute, options = {})
NumericInputRow(
form: form,
attribute: attribute,
unit: options.delete(:unit),
label: options.delete(:label),
help: options.delete(:help),
options: options
)
end
def rich_text_input_row(form, attribute, options = {})
RichTextInputRow(
form: form,
attribute: attribute,
label: options.delete(:label),
help: options.delete(:help),
options: options
)
end
def checkbox_input_row(form, attribute, options = {})
CheckBoxInputRow(
form: form,
attribute: attribute,
label: options.delete(:label),
help: options.delete(:help),
options: options
)
end
def select_input_row(form, attribute, select_options, options = {})
SelectInputRow(
form: form,
attribute: attribute,
select_options: select_options,
label: options.delete(:label),
help: options.delete(:help),
options: options
)
end
def collection_select_input_row(form, attribute, collection, value_method, text_method, options = {})
CollectionSelectInputRow(
form: form,
attribute: attribute,
collection: collection,
value_method: value_method,
text_method: text_method,
label: options.delete(:label),
help: options.delete(:help),
options: options
)
end
def file_input_row(form, name, options = {})
safe_join([
content_tag(:div) do
form.label(name, options[:label], class: "col-form-label")
end,
content_tag(:div) do
safe_join [
content_tag(:div, class: "input-group") do
safe_join [
form.file_field(name, class: "form-control"),
options[:remove] ? form.check_box(:"remove_#{name}", class: "btn-check", autocomplete: "off") : nil,
options[:remove] ? form.label(:"remove_#{name}", Icon(icon: "trash", label: options[:remove_label]), class: "btn btn-outline-danger") : nil
].compact
end,
errors_for(form.object, name),
(options[:help] ? content_tag(:span, class: "form-text") { options[:help] } : nil)
].compact
end
])
end
def nav_link(ico, text, path, options = {})
link_to(
safe_join(
[
content_tag(:span, Icon(icon: ico, label: options[:title].presence || text), class: options[:icon_style]),
content_tag(:span, text, class: options[:text_style])
],
" "
),
path,
class: options[:style] || safe_join(["nav-link", (current_page?(path) ? "active" : "")], " "),
method: options[:method],
rel: options[:nofollow] ? "nofollow" : nil,
id: options[:id],
data: options[:data],
aria: {
label: options[:aria_label]
}
)
end
def errors_for(record, attribute)
return if record.nil? || attribute.nil?
return unless record.errors.include? attribute
content_tag(:div,
record.errors.full_messages_for(attribute).join("; "),
class: "invalid-feedback d-block")
end
def skip_link(target, text)
content_tag :div, class: "container-fluid skip-link text-bg-success p-2" do
link_to text, "##{target}", class: "text-reset", tabindex: 0
end
end
def translate_with_locale_wrapper(key, **options)
translate(key, **options) do |str, _key|
str&.locale ? content_tag(:span, lang: str.locale) { sanitize str } : str
end
end
alias_method :t, :translate_with_locale_wrapper
def pagination_settings
current_user&.pagination_settings || SiteSettings::UserDefaults::PAGINATION
end
def tag_cloud_settings
current_user&.tag_cloud_settings || SiteSettings::UserDefaults::TAG_CLOUD.merge(heatmap: false)
end
def renderer_settings
current_user&.renderer_settings || SiteSettings::UserDefaults::RENDERER
end
def file_list_settings
current_user&.file_list_settings || SiteSettings::UserDefaults::FILE_LIST
end
def problem_settings
current_user&.problem_settings || Problem::DEFAULT_SEVERITIES
end
def random_password
(SecureRandom.base64(32) + "!0aB").chars.shuffle.join
end
def server_indicator(object, full_address: false)
actor = object.respond_to?(:federails_actor) ? object.federails_actor : object
return if !SiteSettings.federation_enabled? || actor.local?
link_to sanitize(actor.profile_url), class: "link-primary link-underline-opacity-0 link-underline-opacity-100-hover" do
safe_join([
"⁂",
sanitize(full_address ? actor.at_address : actor.server)
], " ")
end
end
def oembed_params
params.permit(:maxwidth, :maxheight)
end
def indexable_select_options(object)
current = object.inherited_indexable? ? translate("application_helper.indexable_select_options.yes") : translate("application_helper.indexable_select_options.no")
options_for_select(
[
[translate("application_helper.indexable_select_options.inherit", inherited: current), "inherit"],
[translate("application_helper.indexable_select_options.always_no"), "no"],
[translate("application_helper.indexable_select_options.always_yes"), "yes"]
],
selected: object&.indexable || "inherit"
)
end
def ai_indexable_select_options(object)
current = object.inherited_ai_indexable? ? translate("application_helper.indexable_select_options.yes") : translate("application_helper.indexable_select_options.no")
options_for_select(
[
[translate("application_helper.ai_indexable_select_options.inherit", inherited: current), "inherit"],
[translate("application_helper.ai_indexable_select_options.always_no"), "no"],
[translate("application_helper.ai_indexable_select_options.always_yes"), "yes"]
],
selected: object&.ai_indexable || "inherit"
)
end
def tour_attributes(id:, title:, description:)
return {} if current_user.nil? || current_user.first_use?
tour_state = current_user.tour_state || User::DEFAULT_TOUR_STATE
{
"tour-id" => id,
"tour-id-completed" => (tour_state.dig("completed")&.include?(id) == true).to_s,
"tour-title" => title,
"tour-description" => description
}.compact
end
end