diff options
author | Jeff Fearn <jfearn@redhat.com> | 2022-09-20 15:04:08 +1000 |
---|---|---|
committer | Jeff Fearn <jfearn@redhat.com> | 2022-09-20 15:04:08 +1000 |
commit | 19100618898d5b23a8d09462517b64cb3cf10c75 (patch) | |
tree | a9fa064181e8dc657b7549e6f749a82acd9f55b5 | |
parent | Bug 1668376 - select boxes go off screen (diff) | |
download | bugzilla-19100618898d5b23a8d09462517b64cb3cf10c75.tar.gz bugzilla-19100618898d5b23a8d09462517b64cb3cf10c75.tar.bz2 bugzilla-19100618898d5b23a8d09462517b64cb3cf10c75.zip |
Bug 2124411 - Add row grouping to advanced search and URLs
Handle row groups in search urls.
Add order direction to advanced search order drop down.
Add directional_arrows selectize plugin.
Handle row group changes in save and edit buttons on bug list.
Add order fields to display columns when changing order.
Change-Id: I7b823344d007fab70d0cda6a263ff14bde5cb1de
-rwxr-xr-x | buglist.cgi | 2 | ||||
-rw-r--r-- | extensions/BayotBase/lib/Util.pm | 1 | ||||
-rw-r--r-- | extensions/RedHat/web/css/redhat.css | 1 | ||||
-rw-r--r-- | extensions/RedHat/web/js/redhat.js | 62 | ||||
-rw-r--r-- | extensions/SelectizeJS/web/css/SelectizeJS.css | 45 | ||||
-rw-r--r-- | extensions/SelectizeJS/web/js/SelectizeJS.js | 76 | ||||
-rw-r--r-- | js/custom-search.js | 2 | ||||
-rwxr-xr-x | query.cgi | 6 | ||||
-rw-r--r-- | template/en/default/list/list.html.tmpl | 21 | ||||
-rw-r--r-- | template/en/default/search/knob.html.tmpl | 118 |
10 files changed, 277 insertions, 57 deletions
diff --git a/buglist.cgi b/buglist.cgi index 4f2e175fd..fbc2c5c8d 100755 --- a/buglist.cgi +++ b/buglist.cgi @@ -96,6 +96,8 @@ if ( defined $cgi->param('format') $cgi->delete('format'); } +$cgi->delete('the_orders'); + # Treat requests for ctype=rss as requests for ctype=atom if (defined $cgi->param('ctype') && $cgi->param('ctype') eq "rss") { $cgi->param('ctype', "atom"); diff --git a/extensions/BayotBase/lib/Util.pm b/extensions/BayotBase/lib/Util.pm index 8aa50046b..7c816cbdb 100644 --- a/extensions/BayotBase/lib/Util.pm +++ b/extensions/BayotBase/lib/Util.pm @@ -171,6 +171,7 @@ use constant FIELD_OVERRIDES => { "ext_bz_bug_map.ext_status" => {immutable => 1,}, "comment_tag" => {immutable => 1,}, "agile_pool.id" => {immutable => 1,}, + "bug_agile_pool.pool_order" => {immutable => 1,}, "agile_team.name" => {immutable => 1,}, "longdescs.extra_groups" => {immutable => 1,}, "ext_bz_bug_map.ext_priority" => {immutable => 1,}, diff --git a/extensions/RedHat/web/css/redhat.css b/extensions/RedHat/web/css/redhat.css index a5619ff3e..c7ef1415d 100644 --- a/extensions/RedHat/web/css/redhat.css +++ b/extensions/RedHat/web/css/redhat.css @@ -319,6 +319,7 @@ body.new_login #bugzilla-body #saml2_container a { padding: 4px 9px; padding-top: 5px; transition: all 0.25s ease-out 0s; + line-height: 1em; } #header .form .txt:focus~.btn, diff --git a/extensions/RedHat/web/js/redhat.js b/extensions/RedHat/web/js/redhat.js index 0c9adb8a3..f655bc598 100644 --- a/extensions/RedHat/web/js/redhat.js +++ b/extensions/RedHat/web/js/redhat.js @@ -1398,7 +1398,8 @@ function update_data_hooks() { function update_bug_list_fixed(table, level) { var fIndex = group_col[0]; if (typeof fIndex === 'string') { - fIndex = $.inArray(fIndex, the_search.include_fields); + // fIndex = $.inArray(fIndex, the_search.include_fields); + fIndex = $.inArray(fIndex, real_cols); } var order = table.order(); @@ -1496,6 +1497,8 @@ function filter_rows(json) { // Clone array as we will be filtering it var fdata = json['data']; + if (typeof fdata === 'undefined') return; + $.each($('#bz_buglist').DataTable().settings()[0]._searchPanes.s.panes, function () { if (!this.s.displayed) { return; @@ -1520,8 +1523,16 @@ function filter_rows(json) { } } -function load_field_selector(current, target) { +function load_field_selector(current, target, extraPlugins, exclude) { + var reqPlugins = ['remove_button', 'minimum_search_length', 'extra_keys_control', 'drag_drop', 'auto_position']; + if (Array.isArray(extraPlugins)) $.merge(reqPlugins, extraPlugins); var selected = current.split(/,\s*/); + + $.each(selected, function (i, value) { + var tmp = value.split(/\s+/); + selected[i] = tmp[0]; + }); + var $select = $('<select id="' + target + '_select"></select>'); $select.attr('multiple', true); @@ -1532,7 +1543,7 @@ function load_field_selector(current, target) { field: 'text', direction: 'asc' }, - plugins: ['remove_button', 'minimum_search_length', 'extra_keys_control', 'drag_drop', 'auto_position'], + plugins: reqPlugins, selectOnTab: true, maxOptions: 'nolimit', minimum_search_length: 2, @@ -1557,6 +1568,9 @@ function load_field_selector(current, target) { $.each(BB_FIELDS, function (i, obj) { if (!obj['buglist']) return; + if (Array.isArray(exclude) && (exclude.indexOf(obj['name']) > -1 || exclude.indexOf(obj['internal_name']) > -1)) { + return; + } var data = {}; data['id'] = target + '_select_' + obj['name']; @@ -1581,3 +1595,45 @@ function load_field_selector(current, target) { function hide_column(table, index) { $(table).DataTable().column(index).visible(false); } + + +function complete_url(url) { + var extra = ''; + + var seen = []; + + // Row groups first + var fixed_order = table.order.fixed()['pre']; + $.each(fixed_order, function (i, data) { + if (extra == '') extra = '&order='; + extra = extra + real_cols[data[0]] + ' ' + data[1]; + seen.push(data[0]); + + if (i < fixed_order.length) { + extra = extra + ', '; + } + }); + + var order = table.order(); + + // Then other sorting + $.each(order, function (i, data) { + if (seen.indexOf(data[0]) != -1) return; + if (extra == '') extra = '&order='; + extra = extra + real_cols[data[0]] + ' ' + data[1]; + seen.push(data[0]); + + if (i < order.length) { + extra = extra + ', '; + } + }); + + if (group_col[0]) { + extra = extra + '&row_group1=1'; + if (group_col[1]) { + extra = extra + '&row_group2=1'; + } + } + + return url + extra; +} diff --git a/extensions/SelectizeJS/web/css/SelectizeJS.css b/extensions/SelectizeJS/web/css/SelectizeJS.css index 9d9029636..b6989291e 100644 --- a/extensions/SelectizeJS/web/css/SelectizeJS.css +++ b/extensions/SelectizeJS/web/css/SelectizeJS.css @@ -270,4 +270,49 @@ table#flags tr td { .invalid { color: red; font-weight: bold; +} + +.selectize-control.plugin-directional_arrows .item .direction { + color: black !important; + text-decoration: none; + vertical-align: middle; + display: inline-block; + padding: 1px 5px; + border-left: 1px solid rgba(0, 0, 0, 0); + border-right: 1px solid #efefef; + border-radius: 0 2px 2px 0; + box-sizing: border-box; + margin-left: 5px; + background-color: #dedede; + margin-right: -5px; + position: relative; + font-size: 1.2em; +} + +.selectize-control.plugin-directional_arrows .item .direction:before { + font-family: "Font Awesome 5 Free"; + font-weight: 900; + content: "\f0de"; + position: absolute; + display: inline-block; + right: 25%; + opacity: 0.6; +} + +.selectize-control.plugin-directional_arrows .item .direction:after { + font-family: "Font Awesome 5 Free"; + font-weight: 900; + content: "\f0dd"; + opacity: 0.3; + position: absolute; + display: inline-block; + right: 25%; +} + +.selectize-control.plugin-directional_arrows .item .direction.desc:after { + opacity: 0.6; +} + +.selectize-control.plugin-directional_arrows .item .direction.desc:before { + opacity: 0.3; }
\ No newline at end of file diff --git a/extensions/SelectizeJS/web/js/SelectizeJS.js b/extensions/SelectizeJS/web/js/SelectizeJS.js index ff46af3b2..4cc482558 100644 --- a/extensions/SelectizeJS/web/js/SelectizeJS.js +++ b/extensions/SelectizeJS/web/js/SelectizeJS.js @@ -212,8 +212,8 @@ Selectize.define('related_fields', function () { if (typeof RELATED_FIELDS[my_id] === 'undefined') return; - if(my_id === 'product' && $('#' + my_id).val().length){ - if($('#rh_sub_component').length){ + if (my_id === 'product' && $('#' + my_id).val().length) { + if ($('#rh_sub_component').length) { last_sub_component = $('#rh_sub_component').get_selected_item_text(); $('#component').clearComponentSearch(); update_selects(); @@ -277,6 +277,70 @@ Selectize.define('load_from_js', function () { })(); }); +Selectize.define('directional_arrows', function (options) { + + options = $.extend({ + label: '', + title: 'ASC', + className: 'direction', + append: true + }, options); + + var self = this; + + var html = '<a href="javascript:void(0)" class="' + options.className + + '" tabindex="-1" title="' + escape(options.title) + + '"> </a>'; + + /** + * Appends an element as a child (with raw HTML). + * + * @param {string} html_container + * @param {string} html_element + * @return {string} + */ + var append = function (html_container, html_element) { + var pos = html_container.search(/(<\/[^>]+>\s*)$/); + return html_container.substring(0, pos) + html_element + html_container.substring(pos); + }; + + self.setup = (function () { + var original = self.setup; + return function () { + // override the item rendering method to add the button to each + if (options.append) { + var render_item = self.settings.render.item; + self.settings.render.item = function (data) { + return append(render_item.apply(self, arguments), html); + }; + } + + original.apply(self, arguments); + + // add event listener + self.$control.on('click', '.' + options.className, function (e) { + //e.preventDefault(); + if (self.isLocked) return; + + if ($(e.currentTarget).hasClass('desc')) { + $(e.currentTarget).removeClass('desc'); + $(e.currentTarget).prop('title', 'ASC'); + } else { + $(e.currentTarget).addClass('desc'); + $(e.currentTarget).prop('title', 'DESC'); + } + + // BUGBUG can we not hard code this? +// update_rowgroups(e.currentTarget); + update_rowgroups($('#custom_orders_select.selectized')[0]); + + return false; + }); + }; + })(); + +}); + jQuery.fn.extend({ load_from_js: function () { if (!$(this).hasClass('selectized')) return; @@ -737,7 +801,7 @@ jQuery.fn.extend({ id: "v" + inner.id + "_" + id }; count = count + 1; - if(selected == inner.name) match = true; + if (selected == inner.name) match = true; } } @@ -746,12 +810,12 @@ jQuery.fn.extend({ if (count > 1) { $sel.enable(); } else { - if(data.length) $sel.setValue(data[0].value); + if (data.length) $sel.setValue(data[0].value); $sel.disable(); } $sel.settings.placeholder = ' '; $sel.updatePlaceholder(); - if(match) { + if (match) { $sel.$control.find("[data-value='" + selected + "']").removeClass('invalid'); } else { $sel.$control.find("[data-value='" + selected + "']").addClass('invalid'); @@ -1137,7 +1201,7 @@ function show_sub_components(myid) { var product = $("input[name=product]").val() || $("#product").get_sel_ids(); var component = $("#component").selectize()[0].selectize.getValue(); var select_items = get_selected_items_text($sub_comp_sel); - if(typeof last_sub_component !== 'undefined'){ + if (typeof last_sub_component !== 'undefined') { select_items = [last_sub_component]; } hide_and_clear_sub_components(myid); diff --git a/js/custom-search.js b/js/custom-search.js index 3cbd246ec..6f719edf8 100644 --- a/js/custom-search.js +++ b/js/custom-search.js @@ -226,7 +226,7 @@ function _cs_build_structure(form_member) { nested.pop(); continue; } else { - nested[nested.length - 1].push('f' + id); + if(nested.length) nested[nested.length - 1].push('f' + id); } } return structure; @@ -338,7 +338,11 @@ if ($cgi->cookie('LASTORDER')) { $vars->{'lastorder'} = $cgi->cookie('LASTORDER'); ## REDHAT EXTENSION 1443918 } -if ($cgi->param('order')) { $deforder = $cgi->param('order') } +if ($cgi->param('order')) { + #$deforder = $cgi->param('order'); + $deforder = "Reuse same sort as last time"; + $vars->{'lastorder'} = $cgi->param('order'); +} $vars->{'userdefaultquery'} = $userdefaultquery; $vars->{'orders'} = \@orders; diff --git a/template/en/default/list/list.html.tmpl b/template/en/default/list/list.html.tmpl index 6d6ff4470..e5e4b07cd 100644 --- a/template/en/default/list/list.html.tmpl +++ b/template/en/default/list/list.html.tmpl @@ -201,7 +201,7 @@ [% END %] <div class="bz_query_edit"> <button type="button" id="edit_search" - onclick="document.location='[% PROCESS edit_search_url FILTER js %]'"> + onclick="document.location=complete_url('[% PROCESS edit_search_url FILTER js %]');"> Edit Search</button> </div> @@ -216,8 +216,9 @@ [% ELSE %] <div class="bz_query_remember"> <form method="get" action="buglist.cgi"> - <input type="submit" id="remember" value="Remember search"> as - <input type="hidden" name="newquery" + <input type="submit" id="remember" value="Remember search" + onclick="$('#newquery').val(complete_url('[% urlquerypart FILTER remove_query_param('row_group1') FILTER remove_query_param('row_group2') FILTER html %]'));"> as + <input type="hidden" name="newquery" id="newquery" value="[% urlquerypart FILTER html %][% "&order=$qorder" FILTER html IF order %]"> <input type="hidden" name="cmdtype" value="doit"> <input type="hidden" name="remtype" value="asnamed"> @@ -647,6 +648,7 @@ group_col[0] = '[% field.0 FILTER js %]'; [% IF field.0 == column %] group_col_index[0] = [% loop.count %]; [% row_groups_index0 = loop.count %] +[% row_groups_index0_dir = field.1 || 'asc' %] [% LAST %] [% END %] [% END %] @@ -658,6 +660,7 @@ group_col[1] = '[% field.0 FILTER js %]'; [% IF field.0 == column %] group_col_index[1] = [% loop.count %]; [% row_groups_index1 = loop.count %] +[% row_groups_index1_dir = field.1 || 'asc' %] [% LAST %] [% END %] [% END %] @@ -669,9 +672,11 @@ update_data_hooks(); [% row_groups_index = [row_groups_index0, row_groups_index1] %] //## RED HAT EXTENSION END 2124411 +var table; + $(document).ready(function() { the_search.include_fields.push('bug_classes'); - var table = $('#bz_buglist').DataTable({ + table = $('#bz_buglist').DataTable({ //pageLength: 20, //displayStart: 40, thehash: " ", @@ -684,9 +689,9 @@ $(document).ready(function() { }, [% IF row_groups_index0 > 0 %] orderFixed: [ - [group_col_index[0], 'asc'], + [group_col_index[0], '[% row_groups_index0_dir FILTER js %]'], [% IF row_groups_index1 > 0 %] - [group_col_index[1], 'asc'], + [group_col_index[1], '[% row_groups_index1_dir FILTER js %]'], [% END %] ], [% END %] @@ -1057,7 +1062,6 @@ $(document).ready(function() { table.on( 'page.dt', function () { var info = $('#bz_buglist').DataTable().page.info(); -// filter_rows(json); update_table_info(); } ); @@ -1085,6 +1089,7 @@ $(document).ready(function() { return; } + // sort direction $.each(table.order(), function( i, data ) { if(fixed_order[0] && data[0] == fixed_order[0][0]) { fixed_order[0][1] = data[1]; @@ -1114,7 +1119,7 @@ $(document).ready(function() { [% BLOCK edit_search_url %] [% editqueryname = searchname OR defaultsavename OR '' %] - query.cgi?[% urlquerypart FILTER html %] + query.cgi?[% urlquerypart FILTER remove_query_param('row_group1') FILTER remove_query_param('row_group2') FILTER html %] [%- IF editqueryname != '' %]&known_name= [%- editqueryname FILTER uri %] [% END %] diff --git a/template/en/default/search/knob.html.tmpl b/template/en/default/search/knob.html.tmpl index f66f2da5c..9c9aa4bdc 100644 --- a/template/en/default/search/knob.html.tmpl +++ b/template/en/default/search/knob.html.tmpl @@ -73,72 +73,114 @@ <p>This list controls the ordering of bugs in the generated bug list. Select items to add them to the sorting, then drag and drop them to set - the order. If you cannot see a field you want to order by then you may - have to add it to the column list as you can only sort by columns that are - displayed in the table. Not all fields can be used for ordering.</p> + the order. If you select a field to order by that is not selected for + display then that field will be added to the display list. Not all fields + can be used for ordering.</p> <div id="custom_orders"></div> + <div class="bz_section_title"> + <a href="#">Grouping</a> + </div> <div id="row_groups"> <p>Bug lists can be grouped by the first and second ordered fields. - Grouping changes the way bug list table is displayed and allows collapsing - group rows for each field value present.</p> + Grouping changes the way the bug list table is displayed and allows + collapsing group rows for each field value present.</p> Group by <span id="row_groups1_txt">??</span> <input type="checkbox" id="row_group1" name="row_group1" value="1"[% IF row_group1 %] checked[% END %]> then - group by <span id="row_groups2_txt">??</span> <input type="checkbox" id="row_group2" name="row_group2" value="2" [% IF row_group2 %] checked[% END %]> + group by <span id="row_groups2_txt">??</span> <input type="checkbox" id="row_group2" name="row_group2" value="1" [% IF row_group2 %] checked[% END %]> </div> </div> </div> </div> <script> - const ordersdesc_fields = { - "Reuse same sort as last time": "[% lastorder FILTER js %]", - "Bug Number": "bug_id", - "Importance": "priority, bug_severity", - "Assignee": "assigned_to, bug_status, priority, bug_id", - "Last Changed": "changeddate, bug_status, priority, assigned_to, bug_id", + "Reuse same sort as last time": "[% lastorder FILTER js %]", + "Bug Number": "bug_id", + "Importance": "priority, bug_severity", + "Assignee": "assigned_to, bug_status, priority, bug_id", + "Last Changed": "delta_ts, bug_status, priority, assigned_to, bug_id", }; function update_rowgroups(target) { - if(typeof target[0] !== 'undefined') { - $('#row_groups1_txt').html(target[0].innerText); + if (typeof target[0] !== 'undefined') { + $('#row_groups1_txt').html(target[0].innerText); } else { - $('#row_groups1_txt').html('nothing'); + $('#row_groups1_txt').html('nothing'); } - if(typeof target[1] !== 'undefined') { - $('#row_groups2_txt').html(target[1].innerText); + if (typeof target[1] !== 'undefined') { + $('#row_groups2_txt').html(target[1].innerText); } else { - $('#row_groups2_txt').html('nothing'); + $('#row_groups2_txt').html('nothing'); } - $('#order').val(get_selected_items_text($('#custom_orders_select').selectize()[0].selectize).join(',')); -} - -$(document).ready(function () { - load_field_selector('[% columnlist FILTER js %]', 'column_list'); - load_field_selector(ordersdesc_fields['[% default.order.0 FILTER js %]'], 'custom_orders'); - + var order = ''; + var selected_values = $('#custom_orders_select').get_selected_items(); + var $col_sel = $('#column_list_select').selectize()[0].selectize; - $('#column_list_select').on("change", function (event, ui) { - $('#columnlist').val(get_selected_items_text($('#column_list_select').selectize()[0].selectize).join(',')); - }); + $.each(selected_values, function (index, value) { + if (value !== 'bug_id') $col_sel.addItem(value); - // Update text describing row groups on change - $('#custom_orders_select').on("change", function (event, ui) { - update_rowgroups(event.target); - }); + order = order + value; + if ($('div.item[data-value="' + value + '"] a.direction').hasClass('desc')) { + order = order + ' DESC'; + } + if (index < selected_values.length) { + order = order + ', '; + } + }); - $('#the_orders').on("change", function (event, ui) { - const indx = event.target[0].innerText; - const ordr = ordersdesc_fields[indx]; - $('#custom_orders_select').change_selections(ordr ? ordr.split(/,\s*/) : []); - }); + $('#order').val(order); +} - update_rowgroups($('#custom_orders_select.selectized')[0]); +$(document).ready(function () { + load_field_selector('[% columnlist FILTER js %]', 'column_list', undefined, ['bug_id']); + load_field_selector(ordersdesc_fields['[% default.order.0 FILTER js %]'], 'custom_orders', ['directional_arrows']); + + + $('#column_list_select').on("change", function (event, ui) { + $('#columnlist').val(get_selected_items_text($('#column_list_select').selectize()[0].selectize).join(',')); + }); + + // Update text describing row groups on change + $('#custom_orders_select').on("change", function (event, ui) { + update_rowgroups(event.target); + }); + + $('#the_orders').on("change", function (event, ui) { + const indx = event.target[0].innerText; + const ordr = ordersdesc_fields[indx]; + var field_names = []; + + // Chop off direction of sort + $.each(ordr.split(/,\s*/), function (i, value) { + var tmp = value.split(/\s+/); + + field_names.push(tmp[0]); + if (tmp[1] && tmp[1].localeCompare('DESC', undefined, { + sensitivity: 'accent' + })) { + desc.push(tmp[0]); + } + }); + + $('#custom_orders_select').change_selections(field_names); + }); + + $.each(ordersdesc_fields['[% default.order.0 FILTER js %]'].split(/,\s*/), function (i, value) { + var tmp = value.split(/\s+/); + + if (tmp[1] && tmp[1].localeCompare('DESC', undefined, { + sensitivity: 'accent' + }) == 0) { + $('div.item[data-value="' + tmp[0] + '"] a.direction').trigger('click'); + } + }); + + update_rowgroups($('#custom_orders_select.selectized')[0]); }); </script> |