forms: fix form validation error messages.

* Fix it so that all edit forms show an error banner if the form
  has validation errors. Previously forms had to manually call
  `error_messages_for`, which not all forms did.

* Fix it so that the full validation error message is shown next to each
  input attribute that had errors. Also update the styling of these
  error messages to look better.
This commit is contained in:
evazion
2021-02-22 01:36:54 -06:00
parent b9ea9d2f5a
commit cde76e66f6
24 changed files with 24 additions and 72 deletions

View File

@@ -92,16 +92,6 @@ module ApplicationHelper
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")
@@ -256,7 +246,14 @@ module ApplicationHelper
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)
simple_form_for(model, **options) do |form|
if model.try(:errors).try(:any?)
concat tag.div(model.errors.full_messages.join("; "), class: "notice notice-error notice-small")
end
block.call(form)
end
end
def table_for(...)

View File

@@ -114,6 +114,7 @@ html {
--form-input-border-color: var(--grey-2);
--form-input-placeholder-text-color: var(--grey-4);
--form-input-validation-error-border-color: var(--red-4);
--form-input-validation-error-text-color: var(--red-5);
--form-button-text-color: var(--text-color);
--form-button-background: var(--grey-1);
@@ -246,8 +247,6 @@ html {
--keyboard-shortcut-color: var(--inverse-text-color);
--keyboard-shortcut-background-color: var(--grey-6);
--error-message-color: var(--red-5);
--login-link-color: var(--red-5);
--footer-border-color: var(--grey-1);
--details-border-color: var(--grey-2);
@@ -326,6 +325,7 @@ body[data-current-user-theme="dark"] {
--form-input-border-color: var(--grey-5);
--form-input-placeholder-text-color: var(--grey-3);
--form-input-validation-error-border-color: var(--red-4);
--form-input-validation-error-text-color: var(--red-5);
--form-button-text-color: var(--grey-9);
--form-button-background: var(--grey-2);
@@ -444,8 +444,6 @@ body[data-current-user-theme="dark"] {
--keyboard-shortcut-color: var(--grey-0);
--keyboard-shortcut-background-color: var(--grey-7);
--error-message-color: var(--red-4);
--login-link-color: var(--red-4);
--footer-border-color: var(--grey-7);
--details-border-color: var(--grey-7);

View File

@@ -1,9 +1,3 @@
span.error {
display: block;
font-weight: bold;
color: var(--error-color);
}
span.link {
color: var(--link-color);
cursor: pointer;

View File

@@ -1,13 +1,3 @@
div.error-messages {
margin: 1em 0;
padding: 1em;
h1 {
font-size: 1em;
color: var(--error-message-color);
}
}
div#notice {
padding: 0.5em;
position: fixed;

View File

@@ -44,8 +44,17 @@ form.simple_form {
}
}
&.field_with_errors input {
border: 1px solid var(--form-input-validation-error-border-color);
&.field_with_errors {
input, select, textarea {
border: 1px solid var(--form-input-validation-error-border-color);
}
span.error {
display: block;
color: var(--form-input-validation-error-text-color);
font-style: italic;
font-size: 0.8em;
}
}
&.text, &.dtext {

View File

@@ -2,8 +2,6 @@
<div id="a-new">
<h1>New Artist</h1>
<%= error_messages_for :artist %>
<%= render "form" %>
</div>
</div>

View File

@@ -1,6 +1,4 @@
<%= edit_form_for(ban) do |f| %>
<%= error_messages_for("ban") %>
<%= f.input :user_name, :as => :string, :input_html => { data: { autocomplete: "user" } } %>
<%= f.input :duration, :hint => "in days" %>
<%= f.input :reason %>

View File

@@ -3,8 +3,6 @@
<h1>Edit Ban</h1>
<%= edit_form_for(@ban) do |f| %>
<%= error_messages_for("ban") %>
<%= f.input :duration, :hint => "in days" %>
<%= f.input :reason %>
<%= f.button :submit, :value => "Ban" %>

View File

@@ -1,6 +1,4 @@
<%= edit_form_for(@bulk_update_request) do |f| %>
<%= error_messages_for("bulk_update_request") %>
<p>
Request aliases or implications using the format shown below. An <b>alias</b> makes the first tag a
synonym for the second tag. An <b>implication</b> makes the first tag automatically add the second tag.

View File

@@ -1,5 +1,3 @@
<%= error_messages_for :comment %>
<%= edit_form_for(comment, namespace: "post_#{comment&.post_id}_comment_#{comment.id || "new"}", html: { style: ("display: none;" if local_assigns[:hidden]), class: "edit_comment" }) do |f| %>
<% if comment.new_record? %>
<%= f.hidden_field :post_id %>

View File

@@ -2,8 +2,6 @@
<div id="a-edit">
<h1>Edit Favorite Group: <%= @favorite_group.pretty_name %></h1>
<%= error_messages_for "favorite_group" %>
<%= edit_form_for(@favorite_group) do |f| %>
<%= f.input :name, :as => :string, :input_html => { :value => @favorite_group.pretty_name } %>
<%= f.input :post_ids_string, label: "Posts", as: :text %>

View File

@@ -2,8 +2,6 @@
<div id="a-new">
<h1>New Favorite Group</h1>
<%= error_messages_for "favorite_group" %>
<%= edit_form_for(@favorite_group) do |f| %>
<%= f.input :name, as: :string, required: true %>
<%= f.input :post_ids_string, label: "Posts", as: :text %>

View File

@@ -1,5 +1,3 @@
<%= error_messages_for("forum_post") %>
<%= edit_form_for(forum_post, namespace: "forum_post_#{forum_post.id}") do |f| %>
<%= f.input :body, as: :dtext %>

View File

@@ -1,5 +1,3 @@
<%= error_messages_for("forum_post") %>
<%= edit_form_for(forum_post) do |f| %>
<% if forum_post.topic_id.present? %>
<%= f.input :topic_id, :as => :hidden %>

View File

@@ -1,5 +1,3 @@
<%= error_messages_for("forum_topic") %>
<div id="form-content">
<%= edit_form_for(forum_topic) do |f| %>
<%= f.input :title %>

View File

@@ -12,8 +12,6 @@
they've verified their email address.
<p>
<%= error_messages_for "ip_ban" %>
<%= edit_form_for(@ip_ban) do |f| %>
<%= f.input :ip_addr, label: "IP Address", as: :string, hint: "Add /24 to ban a subnet. Example: 1.2.3.4/24" %>
<%= f.input :reason, as: :string %>

View File

@@ -3,8 +3,6 @@
<%= edit_form_for(@pool) do |f| %>
<h1>Edit Pool: <%= @pool.pretty_name %></h1>
<%= error_messages_for "pool" %>
<%= f.input :name, :as => :string, :input_html => { :value => @pool.pretty_name } %>
<%= f.input :description, as: :dtext %>
<%= f.input :post_ids_string, as: :text, label: "Posts" %>

View File

@@ -2,8 +2,6 @@
<div id="a-edit">
<h1>Edit Saved Search</h1>
<%= error_messages_for :saved_search %>
<%= edit_form_for(@saved_search) do |f| %>
<%= f.input :query, :as => :string %>
<%= f.input :label_string, label: "Labels", hint: "A list of tags to help categorize this search. Space delimited.", input_html: { "data-autocomplete": "saved-search-label" } %>

View File

@@ -5,8 +5,6 @@
<div id="preview">
</div>
<%= error_messages_for "user_feedback" %>
<%= edit_form_for(@user_feedback) do |f| %>
<%= f.input :category, :collection => ["positive", "neutral", "negative"], :include_blank => false %>
<%= f.input :body, as: :dtext %>

View File

@@ -11,8 +11,6 @@
<div id="preview">
</div>
<%= error_messages_for "user_feedback" %>
<%= edit_form_for(@user_feedback) do |f| %>
<%= f.input :user_name, :label => "User", :input_html => { value: @user_feedback.user.try(:name), data: { autocomplete: "user" } } %>
<%= f.input :category, :collection => ["positive", "neutral", "negative"], :include_blank => false %>

View File

@@ -6,8 +6,6 @@
be visible on your profile to other Danbooru members, but they won't be visible
to search engines.</p>
<%= error_messages_for "change_request" %>
<%= edit_form_for(@change_request) do |f| %>
<%= f.input :desired_name, label: "Name" %>
<%= f.input :desired_name_confirmation, label: "Confirm name" %>

View File

@@ -1,6 +1,4 @@
<div id="form-content">
<%= error_messages_for("wiki_page") %>
<%= edit_form_for(@wiki_page, url: wiki_page_path(@wiki_page.id)) do |f| %>
<%= f.input :title, error: false, input_html: { data: { autocomplete: "tag" } }, hint: "Change to rename this wiki page. Update any wikis linking to this page first." %>

View File

@@ -9,8 +9,6 @@
</div>
<% end %>
<%= error_messages_for("wiki_page") %>
<%= edit_form_for(@wiki_page) do |f| %>
<%= f.input :title, error: false, input_html: { data: { autocomplete: "tag" } } %>
<%= f.input :other_names_string, as: :string, label: "Other names (#{link_to_wiki "help", "help:translated_tags"})".html_safe, hint: "Names used for this tag on other sites such as Pixiv. Separate with spaces." %>

View File

@@ -57,13 +57,13 @@ SimpleForm.setup do |config|
# b.use :input, class: 'input', error_class: 'is-invalid', valid_class: 'is-valid'
b.use :label_input
b.use :hint, wrap_with: { tag: :span, class: :hint }
b.use :error, wrap_with: { tag: :span, class: :error }
# b.use :error, wrap_with: { tag: :span, class: :error }
## full_messages_for
# If you want to display the full error message for the attribute, you can
# use the component :full_error, like:
#
# b.use :full_error, wrap_with: { tag: :span, class: :error }
b.use :full_error, wrap_with: { tag: :span, class: :error }
end
# The default wrapper to be used by the FormBuilder.
@@ -87,7 +87,7 @@ SimpleForm.setup do |config|
# Method used to tidy up errors. Specify any Rails Array method.
# :first lists the first message for each field.
# Use :to_sentence to list all errors for each field.
# config.error_method = :first
config.error_method = :to_sentence
# Default tag used for error notification helper.
config.error_notification_tag = :div