diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index bf9639bcbb8..1b185c53ac0 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -6479,6 +6479,38 @@ sub GetDefaultDashboard {
return $dashboard;
}
+=head2 GetInvalidFields Object => $Object
+
+Returns a list of fields that are marked as invalid by server.
+
+=cut
+
+sub GetInvalidFields {
+ my %args = @_;
+ my @fields;
+ foreach my $note ( keys %{$m->notes} ) {
+ if ( $note =~ /^InvalidField\-(\d+)(?:-(.+))?/ ) {
+ my $cf_id = $1;
+ my $grouping = $2;
+ my $cf = RT::CustomField->new($session{'CurrentUser'});
+ my ($ok, $msg) = $cf->Load($cf_id);
+ if ( $cf->Id ) {
+ push @fields,
+ GetCustomFieldInputName(
+ CustomField => $cf,
+ Grouping => $grouping,
+ # Do not pass misleading ticket object in case it's a txn cf.
+ $cf->ObjectTypeFromLookupType eq ref $args{Object} ? ( Object => $args{Object} ) : (),
+ );
+ }
+ else {
+ RT->Logger->error("Unable to load custom field $cf_id: $msg") unless $ok;
+ }
+ }
+ }
+ return @fields;
+}
+
package RT::Interface::Web;
RT::Base->_ImportOverlays();
diff --git a/share/html/Asset/Create.html b/share/html/Asset/Create.html
index f439df7fb89..b43b7aa6b4f 100644
--- a/share/html/Asset/Create.html
+++ b/share/html/Asset/Create.html
@@ -155,6 +155,17 @@
}
} else {
push @results, @cf_errors;
+
+ if ( !$cf_ok && RT::Interface::Web::RequestENV('HTTP_HX_BOOSTED') ) {
+ $r->headers_out->{'HX-Trigger'} = JSON(
+ {
+ actionsChanged => { messages => \@results, isWarning => 1 },
+ validationFailed => [ GetInvalidFields( Object => RT::Asset->new( $session{CurrentUser} ) ) ],
+ },
+ ascii => 1,
+ );
+ Abort( loc("Validation error"), Code => HTTP::Status::HTTP_UNPROCESSABLE_CONTENT );
+ }
}
}
diff --git a/share/html/Elements/EditCustomField b/share/html/Elements/EditCustomField
index 38eec673c07..32323a9be04 100644
--- a/share/html/Elements/EditCustomField
+++ b/share/html/Elements/EditCustomField
@@ -63,13 +63,15 @@ $m->comp(
CustomField => $CustomField,
Name => $Name,
$CustomField->BasedOn && $Name ? ( BasedOnName => GetCustomFieldInputName(Object => $Object, CustomField => $CustomField->BasedOnObj, Grouping => $Grouping) ) : (),
+ DescribedBy => $CFHintId,
+ AddClass => $AddClass,
);
-if (my $msg = $m->notes('InvalidField-' . $CustomField->Id)) {
+if ( $error_msg ) {
%perl>
- <% $msg %>
+ <% $error_msg %>
% } elsif ($ShowHints and $CustomField->FriendlyPattern) {
-
+
<% $CustomField->FriendlyPattern %>
% }
@@ -106,6 +108,13 @@ if ( !$NamePrefix ) {
$Name = GetCustomFieldInputName(Object => $Object, CustomField => $CustomField, Grouping => $Grouping );
}
+my $CFHintId;
+my $cf_name_prefix = GetCustomFieldInputNamePrefix(Object => $Object, CustomField => $CustomField, Grouping => $Grouping );
+
+if ($ShowHints and $CustomField->FriendlyPattern) {
+ $CFHintId = $cf_name_prefix . 'Hint';
+}
+
# Always fill $Default with submited values if it's empty
if ( ( !defined $Default || !length $Default ) && $DefaultsFromTopArguments ) {
my %TOP = %$DECODED_ARGS;
@@ -116,8 +125,7 @@ if ( ( !defined $Default || !length $Default ) && $DefaultsFromTopArguments ) {
// $TOP{ $NamePrefix . $CustomField->Id . '-Value' };
}
else {
- my $prefix = GetCustomFieldInputNamePrefix(Object => $Object, CustomField => $CustomField, Grouping => $Grouping );
- $Default //= $TOP{ $prefix . 'Values' } // $TOP{ $prefix . 'Value' };
+ $Default //= $TOP{ $cf_name_prefix . 'Values' } // $TOP{ $cf_name_prefix . 'Value' };
}
}
@@ -164,6 +172,12 @@ if ( RT->Config->Get('ExternalInfoPriority') && $Object && $Object->isa('RT::Use
}
}
+my ($error_msg, $AddClass);
+if ( $m->notes('InvalidField-' . $CustomField->Id . ($Grouping ? "-$Grouping" : '') ) ) {
+ $error_msg = $m->notes( 'InvalidField-' . $CustomField->Id . ($Grouping ? "-$Grouping" : '') );
+ $AddClass = 'is-invalid';
+}
+
my $EditComponent = "EditCustomField$Type";
$m->callback( %ARGS, CallbackName => 'EditComponentName', Name => \$EditComponent, CustomField => $CustomField, Object => $Object, Rows => \$Rows, Cols => \$Cols);
$EditComponent = "EditCustomField$Type" unless $m->comp_exists($EditComponent);
diff --git a/share/html/Elements/EditCustomFieldAutocomplete b/share/html/Elements/EditCustomFieldAutocomplete
index 78e6baa46a3..998ae48d994 100644
--- a/share/html/Elements/EditCustomFieldAutocomplete
+++ b/share/html/Elements/EditCustomFieldAutocomplete
@@ -53,7 +53,10 @@ cols="<% $Cols %>" \
% if ( defined $Rows ) {
rows="<% $Rows %>" \
% }
-name="<% $name %>" id="<% $name %>" class="CF-<%$CustomField->id%>-Edit form-control"><% $Default || '' %>
+% if ( defined $DescribedBy ) {
+aria-describedby="<% $DescribedBy %>" \
+% }
+name="<% $name %>" id="<% $name %>" class="CF-<%$CustomField->id%>-Edit form-control <% $AddClass // '' %>"><% $Default || '' %>