summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Fearn <jfearn@redhat.com>2022-09-20 15:04:08 +1000
committerJeff Fearn <jfearn@redhat.com>2022-09-20 15:04:08 +1000
commit19100618898d5b23a8d09462517b64cb3cf10c75 (patch)
treea9fa064181e8dc657b7549e6f749a82acd9f55b5
parentBug 1668376 - select boxes go off screen (diff)
downloadbugzilla-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-xbuglist.cgi2
-rw-r--r--extensions/BayotBase/lib/Util.pm1
-rw-r--r--extensions/RedHat/web/css/redhat.css1
-rw-r--r--extensions/RedHat/web/js/redhat.js62
-rw-r--r--extensions/SelectizeJS/web/css/SelectizeJS.css45
-rw-r--r--extensions/SelectizeJS/web/js/SelectizeJS.js76
-rw-r--r--js/custom-search.js2
-rwxr-xr-xquery.cgi6
-rw-r--r--template/en/default/list/list.html.tmpl21
-rw-r--r--template/en/default/search/knob.html.tmpl118
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) +
+ '">&nbsp;</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;
diff --git a/query.cgi b/query.cgi
index c68457bd9..eddf0f106 100755
--- a/query.cgi
+++ b/query.cgi
@@ -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 != '' %]&amp;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>