Files
danbooru/app/helpers/application_helper.rb
evazion afa4a2c985 js: fixup issues with @rails/ujs.
Fix a couple regressions caused by the migration from jquery-ujs to
@rails/ujs in 9f4ac4c96:

* Add authenticity tokens to all remote forms. By default, Rails doesn't
  doesn't include authenticity tokens in remote forms because it can cause
  problems with fragment caching. This was fine with jquery-ujs because it
  would insert the authenticity token when the remote form was
  submitted, but apparently @rails/ujs doesn't do this. This broke
  certain remote forms nested inside of jquery UI dialogs.

* Fix dialogs to trigger remote form submissions through @rails/ujs
  instead of through jquery. This fixes a problem where remote forms that
  returned a javascript response displayed the response as plaintext
  instead of executing the returned javascript.
2020-01-10 19:16:27 -06:00

339 lines
10 KiB
Ruby

require 'dtext'
module ApplicationHelper
def diff_list_html(new, old, latest)
diff = SetDiff.new(new, old, latest)
render "diff_list", diff: diff
end
def wordbreakify(string)
lines = string.scan(/.{1,10}/)
wordbreaked_string = lines.map {|str| h(str)}.join("<wbr>")
raw(wordbreaked_string)
end
def nav_link_to(text, url, **options)
klass = options.delete(:class)
if nav_link_match(params[:controller], url)
klass = "#{klass} current"
end
li_link_to(text, url, id_prefix: "nav-", class: klass, **options)
end
def subnav_link_to(text, url, **options)
li_link_to(text, url, id_prefix: "subnav-", **options)
end
def li_link_to(text, url, id_prefix: "", **options)
klass = options.delete(:class)
id = id_prefix + text.downcase.gsub(/[^a-z ]/, "").parameterize
tag.li(link_to(text, url, id: "#{id}-link", **options), id: id, class: klass)
end
def format_text(text, **options)
raw DText.format_text(text, **options)
end
def strip_dtext(text)
DText.strip_dtext(text)
end
def error_messages_for(instance_name)
instance = instance_variable_get("@#{instance_name}")
if instance&.errors&.any?
%{<div class="error-messages ui-state-error ui-corner-all"><strong>Error</strong>: #{instance.__send__(:errors).full_messages.join(", ")}</div>}.html_safe
else
""
end
end
def time_tag(content, time, **options)
datetime = time.strftime("%Y-%m-%dT%H:%M%:z")
tag.time content || datetime, datetime: datetime, title: time.to_formatted_s, **options
end
def humanized_duration(from, to)
if to - from > 10.years
duration = "forever"
else
duration = distance_of_time_in_words(from, to)
end
datetime = from.iso8601 + "/" + to.iso8601
title = "#{from.strftime("%Y-%m-%d %H:%M")} to #{to.strftime("%Y-%m-%d %H:%M")}"
raw content_tag(:time, duration, datetime: datetime, title: title)
end
def time_ago_in_words_tagged(time, compact: false)
if time.past?
if compact
text = time_ago_in_words(time)
text = text.gsub(/almost|about|over/, "").strip
text = text.gsub(/less than a/, "<1")
text = text.gsub(/ minutes?/, "m")
text = text.gsub(/ hours?/, "h")
text = text.gsub(/ days?/, "d")
text = text.gsub(/ months?/, "mo")
text = text.gsub(/ years?/, "y")
klass = "compact-timestamp"
else
text = time_ago_in_words(time) + " ago"
klass = ""
end
time_tag(text, time, class: klass)
else
time_tag("in " + distance_of_time_in_words(Time.now, time), time)
end
end
def compact_time(time)
time_tag(time.strftime("%Y-%m-%d %H:%M"), time)
end
def external_link_to(url, text = url, truncate: nil, strip: false, **link_options)
text = text.gsub(%r!\Ahttps?://!i, "") if strip == :scheme
text = text.gsub(%r!\Ahttps?://(?:www\.)?!i, "") if strip == :subdomain
text = text.truncate(truncate) if truncate
if url =~ %r!\Ahttps?://!i
link_to text, url, rel: "external noreferrer nofollow", **link_options
else
url
end
end
def link_to_ip(ip)
link_to ip, ip_addresses_path(search: { ip_addr: ip, group_by: "user" })
end
def link_to_search(search)
link_to search, posts_path(tags: search)
end
def link_to_wiki(text, title = text, **options)
title = "~#{title}" if title =~ /\A\d+\z/
link_to text, wiki_page_path(title), class: "wiki-link", **options
end
def link_to_wikis(*wiki_titles, last_word_connector: ", or", **options)
links = wiki_titles.map do |title|
link_to_wiki title.tr("_", " "), title
end
to_sentence(links, **options)
end
def link_to_user(user, options = {})
return "anonymous" if user.blank?
user_class = "user-#{user.level_string.downcase}"
user_class += " user-post-approver" if user.can_approve_posts?
user_class += " user-post-uploader" if user.can_upload_free?
user_class += " user-super-voter" if user.is_super_voter?
user_class += " user-banned" if user.is_banned?
user_class += " with-style" if CurrentUser.user.style_usernames?
if options[:raw_name]
name = user.name
else
name = user.pretty_name
end
link_to(name, user_path(user), :class => user_class)
end
def mod_link_to_user(user, positive_or_negative)
html = ""
html << link_to_user(user)
if positive_or_negative == :positive
html << " [" + link_to("+", new_user_feedback_path(:user_feedback => {:category => "positive", :user_id => user.id})) + "]"
unless user.is_gold?
html << " [" + link_to("promote", edit_admin_user_path(user)) + "]"
end
else
html << " [" + link_to("&ndash;".html_safe, new_user_feedback_path(:user_feedback => {:category => "negative", :user_id => user.id})) + "]"
end
html.html_safe
end
def dtext_field(object, name, options = {})
options[:name] ||= name.capitalize
options[:input_id] ||= "#{object}_#{name}"
options[:input_name] ||= "#{object}[#{name}]"
options[:value] ||= instance_variable_get("@#{object}").try(name)
options[:preview_id] ||= "dtext-preview"
options[:classes] ||= ""
options[:type] ||= "text"
render "dtext/form", options
end
def dtext_preview_button(object, name, input_id: "#{object}_#{name}", preview_id: "dtext-preview")
tag.input value: "Preview", type: "button", class: "dtext-preview-button", "data-input-id": input_id, "data-preview-id": preview_id
end
def quick_search_form_for(attribute, url, name, autocomplete: nil, &block)
tag.li do
search_form_for(url, classes: "quick-search-form one-line-form") do |f|
out = f.input attribute, label: false, placeholder: "Search #{name}", input_html: { id: nil, "data-autocomplete": autocomplete }
out += tag.input type: :hidden, name: :redirect, value: 1
out += capture { yield f } if block_given?
out
end
end
end
def search_form_for(url, classes: "inline-form", method: :get, &block)
defaults = { required: false }
html_options = { autocomplete: "off", class: "search-form #{classes}" }
simple_form_for(:search, method: method, url: url, defaults: defaults, html: html_options, &block)
end
def edit_form_for(model, **options, &block)
options[:html] = { autocomplete: "off", **options[:html].to_h }
options[:authenticity_token] = true if options[:remote] == true
simple_form_for(model, **options, &block)
end
def table_for(*options, &block)
table = TableBuilder.new(*options, &block)
render "table_builder/table", table: table
end
def body_attributes(user = CurrentUser.user, current_item = nil)
current_user_data_attributes = data_attributes_for(user, "current-user", current_user_attributes)
if current_item.present?
model_name = current_item.model_name.singular.dasherize
model_attributes = current_item.html_data_attributes
current_item_data_attributes = data_attributes_for(current_item, model_name, model_attributes)
end
controller_param = params[:controller].parameterize.dasherize
action_param = params[:action].parameterize.dasherize
{
lang: "en",
class: "c-#{controller_param} a-#{action_param}",
data: {
controller: controller_param,
action: action_param,
layout: controller.class.send(:_layout),
**current_user_data_attributes,
**current_item_data_attributes.to_h
}
}
end
def current_user_attributes
%i[
id name level level_string theme always_resize_images can_upload_free
can_approve_posts disable_categorized_saved_searches
disable_mobile_gestures disable_post_tooltips enable_auto_complete
enable_post_navigation enable_safe_mode hide_deleted_posts
show_deleted_children style_usernames
] + User::Roles.map { |role| :"is_#{role}?" }
end
def data_attributes_for(record, prefix, attributes)
attributes.map do |attr|
if attr.kind_of?(Array)
name = attr.map {|sym| sym.to_s.dasherize.delete("?")}.join('-')
value = record
attr.each do |sym|
value = value.send(sym)
if value.nil?
break
end
end
else
name = attr.to_s.dasherize.delete("?")
value = record.send(attr)
end
if value.nil?
value = "null"
end
if prefix.length == 0
[:"#{name}", value]
else
[:"#{prefix}-#{name}", value]
end
end.to_h
end
def page_title
if content_for(:page_title).present?
content_for(:page_title)
elsif params[:action] == "index"
"#{params[:controller].titleize} - #{Danbooru.config.app_name}"
elsif params[:action] == "show"
"#{params[:controller].singularize.titleize} - #{Danbooru.config.app_name}"
elsif params[:action] == "new"
"New #{params[:controller].singularize.titleize} - #{Danbooru.config.app_name}"
elsif params[:action] == "edit"
"Edit #{params[:controller].singularize.titleize} - #{Danbooru.config.app_name}"
elsif params[:action] == "search"
"Search #{params[:controller].titleize} - #{Danbooru.config.app_name}"
else
"#{Danbooru.config.app_name}/#{params[:controller]}"
end
end
def show_moderation_notice?
CurrentUser.can_approve_posts? && (cookies[:moderated].blank? || Time.at(cookies[:moderated].to_i) < 72.hours.ago)
end
protected
def nav_link_match(controller, url)
url =~ case controller
when "sessions", "users", "maintenance/user/password_resets", "admin/users"
/^\/(session|users)/
when "comments"
/^\/comments/
when "notes", "note_versions"
/^\/notes/
when "posts", "uploads", "post_versions", "explore/posts", "moderator/post/dashboards", "favorites"
/^\/post/
when "artists", "artist_versions"
/^\/artist/
when "tags"
/^\/tags/
when "pools", "pool_versions"
/^\/pools/
when "moderator/dashboards"
/^\/moderator/
when "tag_aliases", "tag_alias_requests"
/^\/tag_aliases/
when "tag_implications", "tag_implication_requests"
/^\/tag_implications/
when "wiki_pages", "wiki_page_versions"
/^\/wiki_pages/
when "forum_topics", "forum_posts"
/^\/forum_topics/
else
/^\/static/
end
end
end