diff options
Diffstat (limited to 'extensions/BMO/web')
-rw-r--r-- | extensions/BMO/web/js/new-bug-frequent-comp.js | 123 | ||||
-rw-r--r-- | extensions/BMO/web/js/release_tracking_report.js | 2 | ||||
-rw-r--r-- | extensions/BMO/web/js/sorttable.js | 52 | ||||
-rw-r--r-- | extensions/BMO/web/js/swag.js | 18 | ||||
-rw-r--r-- | extensions/BMO/web/styles/choose_product.css | 21 |
5 files changed, 179 insertions, 37 deletions
diff --git a/extensions/BMO/web/js/new-bug-frequent-comp.js b/extensions/BMO/web/js/new-bug-frequent-comp.js new file mode 100644 index 000000000..88879738d --- /dev/null +++ b/extensions/BMO/web/js/new-bug-frequent-comp.js @@ -0,0 +1,123 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This Source Code Form is "Incompatible With Secondary Licenses", as + * defined by the Mozilla Public License, v. 2.0. */ + +/** + * Reference or define the Bugzilla app namespace. + * @namespace + */ +var Bugzilla = Bugzilla || {}; // eslint-disable-line no-var + +/** + * Show the current user's most-used components on the New Bug page. + */ +Bugzilla.NewBugFrequentComp = class NewBugFrequentComp { + /** + * Initialize a new NewBugFrequentComp instance. + */ + constructor() { + this.$container = document.querySelector('#frequent-components'); + + if (this.$container && BUGZILLA.user.login) { + this.init(); + } + } + + /** + * Initialize the UI. + */ + async init() { + this.$results = this.$container.querySelector('.results'); + this.$message = this.$results.appendChild(document.createElement('p')); + this.$message.textContent = 'Loading...'; + this.$results.setAttribute('aria-busy', 'true'); + this.$container.hidden = false; + + // Get the current params that may contain `cloned_bug_id` and `format` + const current_params = new URLSearchParams(location.search); + + try { + const links = (await this.fetch()).map(({ product, component }) => { + const params = new URLSearchParams(current_params); + + params.append('product', product); + params.append('component', component); + + return { + href: `/enter_bug.cgi?${params.toString()}`, + text: `${product} :: ${component}`, + }; + }); + + this.$message.remove(); + this.$results.insertAdjacentHTML('beforeend', + `<ul>${links.map(({ href, text }) => + `<li><a href="${href.htmlEncode()}">${text.htmlEncode()}</a></li>` + ).join('')}</ul>` + ); + } catch (error) { + this.$message.textContent = error.message || 'Your frequent components could not be retrieved.'; + } + + this.$results.removeAttribute('aria-busy'); + } + + /** + * Retrieve frequently used components. + * @param {Number} [max=10] Maximum number of results. + * @returns {Promise} Results or error. + */ + async fetch(max = 10) { + const params = new URLSearchParams({ + email1: BUGZILLA.user.login, + emailreporter1: '1', + emailtype1: 'exact', + chfield: '[Bug creation]', + chfieldfrom: '-1y', + chfieldto: 'Now', + include_fields: 'product,component', + }); + + return new Promise((resolve, reject) => { + bugzilla_ajax({ + url: `/rest/bug?${params.toString()}` + }, response => { + if (!response.bugs) { + reject(new Error('Your frequent components could not be retrieved.')); + + return; + } + + if (!response.bugs.length) { + reject(new Error(('Your frequent components could not be found.'))); + + return; + } + + const results = []; + + for (const { product, component } of response.bugs) { + const index = results.findIndex(result => product === result.product && component === result.component); + + if (index > -1) { + results[index].count++; + } else { + results.push({ product, component, count: 1 }); + } + } + + // Sort in descending order + results.sort((a, b) => (a.count < b.count ? 1 : a.count > b.count ? -1 : 0)); + + resolve(results.slice(0, max)); + }, () => { + reject(new Error('Your frequent components could not be retrieved.')); + }); + }); + } +}; + +window.addEventListener('DOMContentLoaded', () => new Bugzilla.NewBugFrequentComp(), { once: true }); diff --git a/extensions/BMO/web/js/release_tracking_report.js b/extensions/BMO/web/js/release_tracking_report.js index c91222e0f..158cc7521 100644 --- a/extensions/BMO/web/js/release_tracking_report.js +++ b/extensions/BMO/web/js/release_tracking_report.js @@ -41,7 +41,7 @@ function onProductChange() { '<input type="checkbox" id="field_' + field.id + '_cb" ' + 'onClick="onFieldToggle(this,' + field.id + ')">' + '</td>' + - '<td class="disabled" id="field_' + field.id + '_td">' + + '<td class="disabled" id="field_' + field.id + '_td">' + '<label for="field_' + field.id + '_cb">' + field.desc.htmlEncode() + ':</label>' + '</td>' + diff --git a/extensions/BMO/web/js/sorttable.js b/extensions/BMO/web/js/sorttable.js index 0873dc20a..c20f02647 100644 --- a/extensions/BMO/web/js/sorttable.js +++ b/extensions/BMO/web/js/sorttable.js @@ -3,13 +3,13 @@ version 2 7th April 2007 Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ - + Instructions: Download this file Add <script src="sorttable.js"></script> to your HTML Add class="sortable" to any table you'd like to make sortable Click on the headers to sort - + Thanks to many, many people for contributions and suggestions. Licenced as X11: http://www.kryogenix.org/code/browser/licence.html This basically means: do what you want with it. @@ -25,20 +25,20 @@ sorttable = { arguments.callee.done = true; // kill the timer if (_timer) clearInterval(_timer); - + if (!document.createElement || !document.getElementsByTagName) return; - + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; - + forEach(document.getElementsByTagName('table'), function(table) { if (table.className.search(/\bsortable\b/) != -1) { sorttable.makeSortable(table); } }); - + }, - /* + /* * Prepares the table so that it can be sorted * */ @@ -53,9 +53,9 @@ sorttable = { } // Safari doesn't support table.tHead, sigh if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; - + //if (table.tHead.rows.length != 1) return; // can't cope with two header rows - + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as // "total" rows, for example). This is B&R, since what you're supposed // to do is put them in a tfoot. So, if there are sortbottom rows, @@ -106,7 +106,7 @@ sorttable = { table.sorttable_rows = table_rows; table.sorttable_body_size = body_size; table.sorttable_bodies = bodies; - + // work through each column and calculate its type @@ -185,7 +185,7 @@ sorttable = { _check_already_sorted: function(cell) { if (cell.className.search(/\bsorttable_sorted\b/) != -1) { - // if we're already sorted by this column, just + // if we're already sorted by this column, just // reverse the table, which is quicker sorttable.reverse_table(cell); @@ -194,7 +194,7 @@ sorttable = { } if (cell.className.search(/\bsorttable_sorted_reverse\b/) != -1) { - // if we're already sorted by this column in reverse, just + // if we're already sorted by this column in reverse, just // re-reverse the table, which is quicker sorttable.reverse_table(cell); @@ -271,7 +271,7 @@ sorttable = { return; - // First, remove sorttable_sorted classes from the other header + // First, remove sorttable_sorted classes from the other header // that is currently sorted and its marker (the simbol indicating // that its sorted. sorttable._remove_sorted_classes(this.table.tHead); @@ -285,7 +285,7 @@ sorttable = { sorttable._mark_column_as_sorted(this, '▼', 0); sorttable.sort_table(this); - + }, sort_table: function(cell) { @@ -312,7 +312,7 @@ sorttable = { body_size = cell.table.sorttable_body_size; body_index = 0; - for (var j=0; j<rows.length; j++) { + for (var j=0; j<rows.length; j++) { if (j % 2) rows[j].className = rows[j].className.replace('bz_row_even', 'bz_row_odd'); @@ -336,7 +336,7 @@ sorttable = { cell.table.sorttable_rows = rows; }, - + reverse_table: function(cell) { oldrows = cell.table.sorttable_rows; newrows = []; @@ -348,7 +348,7 @@ sorttable = { tb = cell.table.sorttable_bodies[0]; body_size = cell.table.sorttable_body_size; body_index = 0; - + var BUGLIST = ''; cell.table.sorttable_rows = []; @@ -379,17 +379,17 @@ sorttable = { delete newrows; }, - + guessType: function(table, column) { // guess the type of a column based on its first non-blank row sortfn = sorttable.sort_alpha; for (var i=0; i<table.sorttable_bodies[0].rows.length; i++) { text = sorttable.getInnerText(table.sorttable_bodies[0].rows[i].cells[column]); if (text != '') { - if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) { + if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) { return sorttable.sort_numeric; } - // check for a date: dd/mm/yyyy or dd/mm/yy + // check for a date: dd/mm/yyyy or dd/mm/yy // can have / or . or - as separator // can be mm/dd as well possdate = text.match(sorttable.DATE_RE) @@ -412,7 +412,7 @@ sorttable = { } return sortfn; }, - + getInnerText: function(node) { // gets the text we want to use for sorting for a cell. // strips leading and trailing whitespace. @@ -422,7 +422,7 @@ sorttable = { hasInputs = (typeof node.getElementsByTagName == 'function') && node.getElementsByTagName('input').length; - + if (typeof node.getAttribute != 'undefined' && node.getAttribute("sorttable_customkey") != null) { return node.getAttribute("sorttable_customkey"); } @@ -457,14 +457,14 @@ sorttable = { } } }, - + /* sort functions each sort function takes two parameters, a and b you are comparing a.sort_data and b.sort_data */ sort_numeric: function(a,b) { aa = parseFloat(a.sort_data.replace(/[^0-9.-]/g,'')); if (isNaN(aa)) aa = 0; - bb = parseFloat(b.sort_data.replace(/[^0-9.-]/g,'')); + bb = parseFloat(b.sort_data.replace(/[^0-9.-]/g,'')); if (isNaN(bb)) bb = 0; return aa-bb; }, @@ -506,7 +506,7 @@ sorttable = { if (dt1<dt2) return -1; return 1; }, - + shaker_sort: function(list, comp_func) { // A stable sort function to allow multi-level sorting of data // see: http://en.wikipedia.org/wiki/Cocktail_sort @@ -536,7 +536,7 @@ sorttable = { b++; } // while(swap) - } + } } /* ****************************************************************** diff --git a/extensions/BMO/web/js/swag.js b/extensions/BMO/web/js/swag.js index cd9561b54..2a86c90f4 100644 --- a/extensions/BMO/web/js/swag.js +++ b/extensions/BMO/web/js/swag.js @@ -24,37 +24,37 @@ function getTotal(item_array) { return total; } -function calculateTotalSwag() { - document.getElementById('Totalswag').value = +function calculateTotalSwag() { + document.getElementById('Totalswag').value = getTotal( new Array('Lanyards', 'Stickers', 'Bracelets', 'Tattoos', 'Buttons', 'Posters')); - + } -function calculateTotalMensShirts() { - document.getElementById('mens_total').value = +function calculateTotalMensShirts() { + document.getElementById('mens_total').value = getTotal( new Array('mens_s', 'mens_m', 'mens_l', 'mens_xl', 'mens_xxl', 'mens_xxxl')); - + } -function calculateTotalWomensShirts() { - document.getElementById('womens_total').value = +function calculateTotalWomensShirts() { + document.getElementById('womens_total').value = getTotal( new Array('womens_s', 'womens_m', 'womens_l', 'womens_xl', 'womens_xxl', 'womens_xxxl')); - + } diff --git a/extensions/BMO/web/styles/choose_product.css b/extensions/BMO/web/styles/choose_product.css index bcca3428e..a4ecf749f 100644 --- a/extensions/BMO/web/styles/choose_product.css +++ b/extensions/BMO/web/styles/choose_product.css @@ -16,6 +16,22 @@ text-align: left; } +#frequent-components ul { + display: flex; + flex-wrap: wrap; + justify-content: center; + margin: 8px auto; + padding: 0; + list-style-type: none; + white-space: nowrap; +} + +#frequent-components li { + flex: none; + margin: 8px 16px; + padding: 0; +} + #product-list { margin: 32px 0; } @@ -23,7 +39,7 @@ #product-list .tile { display: flex; flex-wrap: wrap; - justify-content: flex-start; + justify-content: center; margin: 0 auto; } @@ -55,6 +71,7 @@ } @media screen and (min-width: 1024px) { + #frequent-components ul, #product-list .tile { width: 960px; } @@ -65,6 +82,7 @@ } @media screen and (min-width: 768px) and (max-width: 1023px) { + #frequent-components ul, #product-list .tile { width: 720px; } @@ -75,6 +93,7 @@ } @media screen and (max-width: 767px) { + #frequent-components ul, #product-list .tile { width: auto; max-width: 480px; |