]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1541133 - Bug type field should be a radio button
authorKohei Yoshino <kohei.yoshino@gmail.com>
Mon, 8 Apr 2019 21:06:15 +0000 (17:06 -0400)
committerGitHub <noreply@github.com>
Mon, 8 Apr 2019 21:06:15 +0000 (17:06 -0400)
extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl
extensions/BugModal/template/en/default/bug_modal/field.html.tmpl
extensions/BugModal/web/bug_modal.css
extensions/BugModal/web/bug_modal.js
qa/t/test_bug_edit.t
qa/t/test_custom_fields.t
skins/standard/enter_bug.css
skins/standard/global.css
template/en/default/bug/create/create.html.tmpl
template/en/default/bug/field-label.html.tmpl
template/en/default/bug/field.html.tmpl

index 5db09f6331131c33942b5bb7cc7c1232d2c7c4b6..d518c31f19a851700fa95b09761637278ceb31d6 100644 (file)
     [% WRAPPER bug_modal/field.html.tmpl
         field      = bug_fields.bug_type
         field_type = constants.FIELD_TYPE_SINGLE_SELECT
+        use_buttons  = 1
         help       = "https://wiki.mozilla.org/BMO/UserGuide/BugFields#bug_type"
     %]
       <span class="bug-type-label iconic-text" data-type="[% bug.bug_type FILTER html %]">
index e6933ef29024e4e6e27e9bcf19ec46f09366d699..cadfe7c632482595397506b7d7105bd7bc330cd2 100644 (file)
@@ -97,6 +97,7 @@ END;
 <div class="field
             [%~ " indent" IF no_label && !no_indent %]
             [%~ " inline" IF inline %]
+            [%~ " contains-buttons" IF use_buttons ~%]
             [%~ " edit-hide" IF hide_on_edit %]
             [%~ " edit-show" IF hide_on_view && !hide_on_edit %]"
   [% IF name %] id="field-[% name FILTER html %]"[% END %]
@@ -187,6 +188,43 @@ END;
         [% CASE constants.FIELD_TYPE_SINGLE_SELECT %]
           [%# single value select %]
           <input type="hidden" id="[% name FILTER html %]-dirty">
+          [% IF use_buttons %]
+          <div role="radiogroup" class="buttons toggle" id="[% name FILTER html %]" [% aria_labelledby_html FILTER none %]>
+            [% IF values.defined %]
+              [% FOREACH v IN values %]
+                [% NEXT IF NOT v.is_active AND NOT value.contains(v.name).size %]
+                [% NEXT IF NOT bug.check_can_change_field(name, bug.${field_name}, v.name) %]
+                <div class="item">
+                  <input id="v[% v.id FILTER html %]_[% name FILTER html %]" type="radio" name="[% name FILTER html %]"
+                         value="[% v.name FILTER html %]" [% " checked" IF value.contains(v.name).size %]>
+                  <label for="v[% v.id FILTER html %]_[% name FILTER html %]">
+                    [% IF name == 'bug_type' %]
+                      <span class="bug-type-label iconic-text" data-type="[% v.name FILTER html %]">
+                        <span class="icon" aria-hidden="true"></span>[% v.name FILTER html %]
+                      </span>
+                    [% ELSE %]
+                      [%~ v.name FILTER html ~%]
+                    [% END %]
+                  </label>
+                </div>
+              [% END %]
+            [% ELSE %]
+            <div class="item">
+              <input id="[% name FILTER html %]_[% value FILTER html %]_radio" type="radio"
+                     name="[% name FILTER html %]" value="[% value FILTER html %]" checked>
+              <label for="[% name FILTER html %]_[% value FILTER html %]_radio">
+                [% IF name == 'bug_type' %]
+                  <span class="bug-type-label iconic-text" data-type="[% value FILTER html %]">
+                    <span class="icon" aria-hidden="true"></span>[% value FILTER html %]
+                  </span>
+                [% ELSE %]
+                  [%~ value FILTER html ~%]
+                [% END %]
+              </label>
+            </div>
+            [% END %]
+          </div>
+          [% ELSE %]
           <select name="[% name FILTER html %]" id="[% name FILTER html %]" [% aria_labelledby_html FILTER none %]>
             [% IF values.defined %]
               [% FOREACH v IN values %]
@@ -201,6 +239,7 @@ END;
               <option value="[% value FILTER html %]" selected>[% value FILTER html %]</option>
             [% END %]
           </select>
+          [% END %]
 
         [% CASE constants.FIELD_TYPE_MULTI_SELECT %]
           [%# multi value select %]
index 82b0d67d473b28f238834d481b073a9b268f63d7..2666a340031776df2e51fbc573a1226c249cad35 100644 (file)
@@ -221,6 +221,14 @@ a.activity-ref {
     width: 170px;
 }
 
+.module .field.contains-buttons {
+    margin: 8px 0;
+}
+
+.module .field.contains-buttons .name {
+    vertical-align: middle;
+}
+
 .field-button {
     float: right;
     margin-left: 8px;
index ad8d3ba749ae23e55b7e84f75436542ee84ee6f6..5c5d029b1fc661ac50d7c6b3fc6968cd8b605a7f 100644 (file)
@@ -538,17 +538,36 @@ $(function() {
                     $('#mode-btn').hide();
 
                     // populate select menus
-                    $.each(data.options, function(key, value) {
-                        var el = $('#' + key);
-                        if (!el) return;
-                        var selected = el.val();
-                        el.empty();
-                        $(value).each(function(i, v) {
-                            el.append($('<option>', { value: v.name, text: v.name }));
+                    Object.entries(data.options).forEach(([key, value]) => {
+                        const $select = document.querySelector(`#${key}`);
+                        if (!$select) return;
+                        // It can be radio-button-like UI
+                        const use_buttons = $select.matches('.buttons.toggle');
+                        const selected = use_buttons ? $select.querySelector('input').value : $select.value;
+                        $select.innerHTML = '';
+                        value.forEach(({ name }) => {
+                            if (use_buttons) {
+                                $select.insertAdjacentHTML('beforeend', `
+                                  <div class="item">
+                                    <input id="${$select.id}_${name}_radio" type="radio" name="${$select.id}"
+                                           value="${name}" ${name === selected ? 'checked' : ''}>
+                                    <label for="${$select.id}_${name}_radio">
+                                    ${$select.id === 'bug_type' ? `
+                                      <span class="bug-type-label iconic-text" data-type="${name}">
+                                        <span class="icon" aria-hidden="true"></span>${name}
+                                      </span>
+                                    ` : `${name}`}
+                                    </label>
+                                  </div>
+                                `);
+                            } else {
+                                $select.insertAdjacentHTML('beforeend', `
+                                  <option value="${name}" ${name === selected ? 'selected' : ''}>${name}</option>
+                                `);
+                            }
                         });
-                        el.val(selected);
-                        if (el.attr('multiple') && value.length < 5) {
-                            el.attr('size', value.length);
+                        if ($select.matches('[multiple]') && value.length < 5) {
+                            $select.size = value.length;
                         }
                     });
 
index e2457057f8485ac915905a1a266ca90dbb0b1cc9..b9fcd3d93286300089dd1140b0cbe12d03505b91 100644 (file)
@@ -49,7 +49,7 @@ logout($sel);
 
 log_in($sel, $config, 'QA_Selenium_TEST');
 file_bug_in_product($sel, 'TestProduct');
-$sel->select_ok("bug_type",     "label=defect");
+$sel->check_ok('//input[@name="bug_type" and @value="defect"]');
 $sel->select_ok("bug_severity", "label=critical");
 $sel->type_ok("short_desc", "Test bug editing");
 $sel->type_ok("comment",    "ploc");
@@ -377,7 +377,7 @@ logout($sel);
 
 log_in($sel, $config, 'QA_Selenium_TEST');
 file_bug_in_product($sel, 'TestProduct');
-$sel->select_ok("bug_type", "label=defect");
+$sel->check_ok('//input[@name="bug_type" and @value="defect"]');
 $sel->select_ok("bug_severity", "label=blocker");
 $sel->type_ok("short_desc", "New bug from me");
 
index 85f2fe3a23cf6753d01da090e36b4378fbb485fe..5c0a09e404700466eedb26ecf35459267ee467bf 100644 (file)
@@ -342,7 +342,7 @@ go_to_bug($sel, $bug1_id);
 my @labels = $sel->get_select_options("cf_qa_list_$bug1_id");
 ok(grep(/^ghost$/, @labels), "ghost is in the DOM of the page...");
 my $disabled = $sel->get_attribute("v4_cf_qa_list_$bug1_id\@disabled");
-ok($disabled, "... but is not available for selection by default");
+ok(defined $disabled, "... but is not available for selection by default");
 $sel->select_ok("bug_status",          "label=RESOLVED");
 $sel->select_ok("resolution",          "label=FIXED");
 $sel->select_ok("cf_qa_list_$bug1_id", "label=ghost");
index 7f610b82b0625bbf313a632f116e3839b44475b4..936b51f113e64f78a36e4fe99965b4de458cecd6 100644 (file)
     max-width: 35em;
 }
 
+/* Adjust style for fields using radio-button-like UI */
+#Create .field_label.for-buttons {
+    vertical-align: middle;
+}
+
+#Create .field_value.contains-buttons {
+    padding: .5em .25em;
+}
+
 /* Text inputs need to be a little shorter on enter_bug
  * than the 100% that they are on show_bug.
  */
index 76b24942f538e3c101eb1171759e19c88a54544b..22c14207438c751f6987b1880970dcdf423f3833 100644 (file)
@@ -1242,11 +1242,13 @@ select, select[multiple] {
 }
 
 .buttons.toggle[role="radiogroup"] .item:first-child label {
-  border-radius: 4px 0 0 4px;
+  border-top-left-radius: 4px;
+  border-bottom-left-radius: 4px;
 }
 
 .buttons.toggle[role="radiogroup"] .item:last-child label {
-  border-radius: 0 4px 4px 0;
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 4px;
 }
 
 .buttons.toggle[role="radiogroup"] .item:not(:first-child) label {
index cb92f137ddb65ce2b5fba7c0fb8619e3ecf3bb46..fa9729cf0d454c1afb0687d650474263960597aa 100644 (file)
@@ -51,6 +51,10 @@ function init() {
   initCrashSignatureField();
   init_take_handler('[% user.login FILTER js %]');
   bz_attachment_form.update_requirements(false);
+
+  document.querySelector('#bug_type').addEventListener('change', () => {
+    bug_type_changed = true;
+  }, { once: true });
 }
 
 function initCrashSignatureField() {
@@ -67,6 +71,7 @@ function initCrashSignatureField() {
 var initialowners = new Array([% product.components.size %]);
 var last_initialowner;
 var default_bug_types = new Array([% product.components.size %]);
+let bug_type_changed = false;
 var initialccs = new Array([% product.components.size %]);
 var components = new Array([% product.components.size %]);
 var comp_desc = new Array([% product.components.size %]);
@@ -131,7 +136,10 @@ function set_assign_to() {
             last_initialowner = owner;
         }
 
-        form.bug_type.value = default_bug_types[index];
+        if (!bug_type_changed) {
+          form.bug_type.value = default_bug_types[index];
+        }
+
         document.getElementById('initial_cc').innerHTML = initialccs[index];
         document.getElementById('comp_desc').innerHTML = comp_desc[index];
 
@@ -318,7 +326,7 @@ TUI_hide_default('expert_fields');
     </td>
 
     [% INCLUDE bug/field.html.tmpl
-      bug = default, field = bug_fields.bug_type, editable = 1,
+      bug = default, field = bug_fields.bug_type, editable = 1, use_buttons = 1,
       value = default.bug_type %]
   </tr>
 
index 851935283f28f6cc1a96c99276b748402c13a97c..5d5c5452cedf0e2634cdff1aa3fe84d7cf7249aa 100644 (file)
@@ -29,7 +29,7 @@
 
 [% DEFAULT tag_name = "th" %]
 <[% tag_name FILTER html %] class="field_label [% ' bz_hidden_field' IF hidden %]
-           [%- ' required' IF field.is_mandatory && NOT bug.id %]"
+           [%- ' required' IF field.is_mandatory && NOT bug.id; ' for-buttons' IF use_buttons %]"
     id="field_label_[% field.name FILTER html %]"
     [% IF rowspan %] rowspan="[% rowspan FILTER html %]"[% END %]>
 
index 5e674f7b2cee3ef7f0e4ead4e96f1a07af052116..a38a5a07c0dba702fa4a43dfcd4bc127d11d8f40 100644 (file)
@@ -44,7 +44,7 @@
 
 [% IF NOT no_tds %]
   [% PROCESS "bug/field-label.html.tmpl" %]
-  <td class="field_value [% ' bz_hidden_field' IF hidden %]"
+  <td class="field_value [% ' bz_hidden_field' IF hidden; ' contains-buttons' IF use_buttons %]"
       id="field_container_[% field.name FILTER html %]"
       [% " colspan=\"$value_span\"" FILTER none IF value_span %]>
 [% END %]
     [% CASE [ constants.FIELD_TYPE_SINGLE_SELECT
               constants.FIELD_TYPE_MULTI_SELECT ] %]
         <input type="hidden" id="[% field.name FILTER html %]_dirty">
+        [% IF use_buttons %]
+        <div role="radiogroup" class="buttons toggle" id="[% field.name FILTER html %]">
+        [% ELSE %]
         <select id="[% field.name FILTER html %]"
                 name="[% field.name FILTER html %]"
                 [% IF field.type == constants.FIELD_TYPE_MULTI_SELECT %]
               [% dontchange FILTER html %]
             </option>
           [% END %]
+        [% END %]
           [% IF override_legal_values %]
             [% legal_values = override_legal_values %]
           [% ELSE %]
             [% legal_values = field.legal_values %]
           [% END %]
           [% FOREACH legal_value = legal_values %]
-            [% NEXT IF NOT legal_value.is_active AND NOT value.contains(legal_value.name).size %]
+            [%
+              selected = value.contains(legal_value.name).size;
+              NEXT IF NOT legal_value.is_active AND NOT selected;
+              option_id = "v" _ legal_value.id _ "_" _ field.name;
+              disabled = bug AND !legal_value.is_visible_on_bug(bug);
+            %]
 
             [%# Purpose: hide field values from those who can't change them %]
             [% IF field.name.match("^cf_blocking_") OR
                   field.name == "cf_cab_review" OR
                   field.name == "resolution" %]
               [% NEXT UNLESS bug.check_can_change_field(field.name, '---', legal_value.name) OR
-                             value.contains(legal_value.name).size %]
+                             selected %]
             [% END %]
 
             [% IF field.name == "resolution" &&
               [% NEXT IF r == "EXPIRED" %]
             [% END %]
 
-            <option value="[% legal_value.name FILTER html %]"
-                    id="v[% legal_value.id FILTER html %]_
-                        [%- field.name FILTER html %]"
-              [%# We always show selected values, even if they should be
-                # hidden %]
-              [% IF value.contains(legal_value.name).size %]
-                selected="selected"
-              [% ELSIF bug AND !legal_value.is_visible_on_bug(bug) %]
-                class="bz_hidden_option" disabled="disabled"
-              [% END %]>
+            [% IF use_buttons %]
+            <div class="item">
+              <input id="[% option_id FILTER html %]" type="radio"
+                     name="[% field.name FILTER html %]" value="[% legal_value.name FILTER html %]"
+                     [%# We always show selected values, even if they should be hidden %]
+                     [% IF selected %]checked[% ELSIF disabled %]disabled class="bz_hidden_option"[% END %]>
+              <label for="[% option_id FILTER html %]">
+                [% IF field.name == 'bug_type'%]
+                  <span class="bug-type-label iconic-text" data-type="[% legal_value.name FILTER html %]">
+                    <span class="icon" aria-hidden="true"></span>[% legal_value.name FILTER html %]
+                  </span>
+                [% ELSE %]
+                  [%- display_value(field.name, legal_value.name) FILTER html ~%]
+                [% END %]
+              </label>
+            </div>
+            [% ELSE %]
+            <option id="[% option_id FILTER html %]" value="[% legal_value.name FILTER html %]"
+                    [%# We always show selected values, even if they should be hidden %]
+                    [% IF selected %]selected[% ELSIF disabled %]disabled class="bz_hidden_option"[% END %]>
               [%- display_value(field.name, legal_value.name) FILTER html ~%]
             </option>
+            [% END %]
           [% END %]
+        [% IF use_buttons %]
+        </div>
+        [% ELSE %]
         </select>
+        [% END %]
         [%# When you pass an empty multi-select in the web interface,
           # it doesn't appear at all in the CGI object. Instead of
           # forcing all users of process_bug to always specify every