[Rt-commit] rt branch 5.0/add-boolean-cf-render-type2 created. rt-5.0.3-220-g3f638f0204

BPS Git Server git at git.bestpractical.com
Wed Dec 28 22:38:24 UTC 2022


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt".

The branch, 5.0/add-boolean-cf-render-type2 has been created
        at  3f638f02042730856609ce12413674bafe887450 (commit)

- Log -----------------------------------------------------------------
commit 3f638f02042730856609ce12413674bafe887450
Author: Brian Conry <bconry at bestpractical.com>
Date:   Mon Jul 11 16:17:56 2022 -0500

    Add a Checkbox RenderType for select type custom fields
    
    This provides a single checkbox for "Yes/No" type CFs.
    A single box is a nicer display option than the previous
    approach of showing radio buttons or a dropdown with
    Yes/No options.

diff --git a/docs/initialdata.pod b/docs/initialdata.pod
index 8d81fde3a0..6911e960ee 100644
--- a/docs/initialdata.pod
+++ b/docs/initialdata.pod
@@ -219,10 +219,9 @@ common C<LookupType>.
 =item C<RenderType>
 
 Only valid when C<Type> is "Select".  Controls how the CF is displayed when
-editing it.  Valid values are: C<Select box>, C<List>, and C<Dropdown>.
+editing it. Valid values are: C<Select box>, C<List>, C<Dropdown>, and C<Checkbox>.
 
-C<List> is either a list of radio buttons or a list of checkboxes depending on
-C<MaxValues>.
+See L<RT::CustomField/SetRenderType> for details.
 
 =item C<MaxValues>
 
diff --git a/lib/RT/CustomField.pm b/lib/RT/CustomField.pm
index ac7b6d89e4..41c129b79d 100644
--- a/lib/RT/CustomField.pm
+++ b/lib/RT/CustomField.pm
@@ -88,6 +88,7 @@ our %FieldTypes = (
             single => [ 'Dropdown',                # loc
                         'Select box',              # loc
                         'List',                    # loc
+                        'Checkbox',                # loc
                       ]
         },
 
@@ -1348,6 +1349,12 @@ sub SetRenderType {
                                 $self->FriendlyType));
     }
 
+    if ( $type eq 'Checkbox' ) {
+        if ( $self->Values->Count < 2 ) {
+            return (0, $self->loc("Must have two values for Render Type Checkbox"));
+        }
+    }
+
     return $self->_Set( Field => 'RenderType', Value => $type, @_ );
 }
 
@@ -2101,8 +2108,14 @@ sub SetBasedOn {
         unless $cf->id && $cf->CurrentUserCanSee;
 
     # XXX: Remove this restriction once we support lists and cascaded selects
-    if ( $self->RenderType =~ /List/ ) {
-        return (0, $self->loc("We can't currently render as a List when basing categories on another custom field.  Please use another render type."));
+    if ( $self->RenderType =~ /List|Checkbox/ ) {
+        return (
+            0,
+            $self->loc(
+                "We can't currently render as a [_1] when basing categories on another custom field.  Please use another render type.",
+                $self->loc( $self->RenderType )
+            )
+        );
     }
 
     return $self->_Set( Field => 'BasedOn', Value => $value, @_ )
@@ -2353,6 +2366,15 @@ Set RenderType to VALUE.
 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 (In the database, RenderType will be stored as a varchar(64).)
 
+Only valid when C<Type> is "Select".  Controls how the CF is displayed when
+editing it.  Valid values are: C<Select box>, C<List>, C<Dropdown>, and
+C<Checkbox>.
+
+C<List> is rendered as radio buttons when MaxValues is 1 (accepts one value)
+or as checkboxes when MaxValues is 0 (accepts multiple values).
+
+C<Checkbox> renders as a single checkbox and expects two values, first for
+unchecked and the other for checked.
 
 =cut
 
diff --git a/share/html/Admin/CustomFields/Modify.html b/share/html/Admin/CustomFields/Modify.html
index daef955a53..6e0c16d86c 100644
--- a/share/html/Admin/CustomFields/Modify.html
+++ b/share/html/Admin/CustomFields/Modify.html
@@ -135,7 +135,8 @@ jQuery( function() {
 </&>
 
 % if ( $CustomFieldObj->SupportDefaultValues ) {
-<&| /Elements/LabeledValue, Label => loc("Default [numerate,_1,value,values]", $CustomFieldObj->MaxValues) &>
+<&| /Elements/LabeledValue, Label => loc("Default [numerate,_1,value,values]", $CustomFieldObj->MaxValues),
+    Class => $default_value_class &>
   <& /Elements/EditCustomField, NamePrefix => 'Default-', CustomField => $CustomFieldObj, ShowEmptyOption => 1 &>
 </&>
 % }
@@ -252,6 +253,7 @@ jQuery( function() {
 my ($title, @results, $added_cfv);
 
 my $CustomFieldObj = RT::CustomField->new( $session{'CurrentUser'} );
+my $default_value_class = ''; # Extra classes for default CF value input
 
 $m->callback(CallbackName => 'Initial', Pattern => \$Pattern, Results => \@results, ARGSRef => \%ARGS);
 
@@ -453,6 +455,14 @@ MaybeRedirectForResults(
     Arguments   => { id => $id },
 ) if $CustomFieldObj->id;
 
+if ( $CustomFieldObj->RenderType eq 'Checkbox' ) {
+    $default_value_class = 'cfrendertype-Checkbox';
+
+    if ( $CustomFieldObj->Values->Count < 2 ) {
+        # Remind users a Checkbox should have two values
+        push @results, 'Checkbox custom fields require two values, first for unchecked and the other for unchecked.';
+    }
+}
 
 my $EnabledChecked = qq[checked="checked"];
 $EnabledChecked = '' if $CustomFieldObj->Disabled;
diff --git a/share/html/Admin/Elements/EditCustomFieldValues b/share/html/Admin/Elements/EditCustomFieldValues
index 915b471b80..a935c66e14 100644
--- a/share/html/Admin/Elements/EditCustomFieldValues
+++ b/share/html/Admin/Elements/EditCustomFieldValues
@@ -50,9 +50,13 @@
 %    return;
 % }
 
-% # we need to allow for an extra col-2 if not combobox and categories are enabled
-% # if so, make the description cols -2 smaller to allow for categories
-% my $description_col_size = ( $CustomField->Type ne 'Combobox' && $Categories ? 4 : 6 );
+% # we need to allow for an extra col-2 for:
+% # a) Any CF with categories
+% #    The extra space is used to set the category for each value
+% # b) Any CF with the Checkbox render type
+% #    The extra space is used for the "Unchecked"/"Checked" descriptive text
+% # Note that the Combobox CF Type and Checkbox RenderType both preclude having categories,
+% my $description_col_size = ( $CustomField->Type ne 'Combobox' && $Categories ) || $render_type eq "Checkbox" ? 4 : 6;
 
 <div class="form-row">
   <div class="label col-auto">
@@ -75,8 +79,14 @@
       <&|/l&>Category</&>
     </div>
 % }
+% elsif ( $render_type eq 'Checkbox' ) {
+    <div class="label col-2 text-left">
+      <&|/l&>Checkbox Type</&>
+    </div>
+% }
 </div>
 
+% my $firstValue = 1;
 % while ( my $value = $values->Next ) {
 % my $paramtag = "CustomField-". $CustomField->Id ."-Value-". $value->Id;
 <div class="form-row">
@@ -106,6 +116,14 @@
 %   }
     </select>
   </div>
+% }
+% if ( $render_type eq 'Checkbox' ) {
+  <div class="col-2">
+    <span class="current-value">
+      <% $firstValue ? loc('Unchecked') : loc('Checked') %>
+    </span>
+%   $firstValue = 0;
+  </div>
 % }
   <div class="col-1">
     <input type="button" class="delete_custom_field_value button btn btn-primary" data-cfv-id="<% $value->id %>" value="<&|/l&>Delete</&>" onclick="delete_custom_field_value(<% $value->id %>)" />
@@ -139,6 +157,9 @@ my $Categories;
 if ($BasedOnObj and $BasedOnObj->Id) {
     $Categories = $BasedOnObj->Values;
 }
+
+my $render_type = $CustomField->RenderType;
+
 </%init>
 <%args>
 $CustomField => undef
diff --git a/share/html/Elements/EditCustomFieldSelect b/share/html/Elements/EditCustomFieldSelect
index acc8e9e5f3..833fe9c357 100644
--- a/share/html/Elements/EditCustomFieldSelect
+++ b/share/html/Elements/EditCustomFieldSelect
@@ -78,6 +78,24 @@
 %   }
 </div>
 </fieldset>
+% } elsif ( $RenderType eq 'Checkbox' ) {
+%   my $CFVs = CachedCustomFieldValues($CustomField);
+%   my $checkbox_value;
+%   my $FalseValue = ( $checkbox_value = $CFVs->First ) ? $checkbox_value->Name : 'False';
+%   my $TrueValue  = ( $checkbox_value = $CFVs->Next ) ? $checkbox_value->Name : 'True';
+%   my $isChecked = (scalar keys %default) && (not exists $default{lc $FalseValue});
+  <div class="custom-control custom-checkbox">
+    <input id="<% $name . '-Display' %>" type="checkbox" class="custom-control-input" data-checked-value="<% $TrueValue %>" data-unchecked-value="<% $FalseValue %>" value-target="#<% $name %>" <% $isChecked ? "checked" : "" %> />
+    <label class="custom-control-label" for="<% $name . '-Display' %>"></label>
+    <input type="hidden" id="<% $name %>" name="<% $name %>" class="custom-control" value="<% $isChecked ? $TrueValue : $FalseValue %>" />
+  </div>
+<script type="text/javascript">
+    var id = <% $name |n,j %>;
+    id = id.replace(/:/g,'\\:');
+    jQuery('#' + id + '-Display').change(function() {
+        jQuery('#' + id).val(jQuery(this).is(':checked') ? jQuery(this).data('checked-value') : jQuery(this).data('unchecked-value'));
+    });
+</script>
 % } else {
 % if (@category) {
 %# this hidden select is to supply a full list of values,
diff --git a/share/html/Elements/EditCustomFields b/share/html/Elements/EditCustomFields
index 02a8949418..b0d2a55bec 100644
--- a/share/html/Elements/EditCustomFields
+++ b/share/html/Elements/EditCustomFields
@@ -53,10 +53,12 @@
 % }
 % for my $CustomField ( @CustomFields ) {
 % my $Type = $CustomField->Type || 'Unknown';
+% my $RenderType = $CustomField->RenderType;
 % my @classes = (
 %   'form-row',
 %   'edit-custom-field',
 %   "cftype-$Type",
+%   $RenderType ? "cfrendertype-$RenderType" : (),
 % );
 % $m->callback( CallbackName => 'ModifyFieldClasses', CustomField => $CustomField,
 %               Object => $Object, Classes => \@classes, Grouping => $Grouping );
diff --git a/share/static/css/elevator-light/forms.css b/share/static/css/elevator-light/forms.css
index 3eca1af77a..accd4fa7a9 100644
--- a/share/static/css/elevator-light/forms.css
+++ b/share/static/css/elevator-light/forms.css
@@ -296,7 +296,10 @@ div[id^="TitleBox--_Ticket_ModifyPeople_html"] .list-group-item {
   padding-bottom: 0.25em;
 }
 
-.form-row.boolean > .value .form-row {
+/* These move horizontal radio buttons and a single checkbox down
+   to be centered next to the label, which is also pushed down */
+.form-row.boolean > .value .form-row,
+.form-row.cfrendertype-Checkbox > .value {
   margin-top: 5px;
 }
 

-----------------------------------------------------------------------


hooks/post-receive
-- 
rt


More information about the rt-commit mailing list