]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1473417 - Show often/recently used products/components on New Bug page
authorKohei Yoshino <kohei.yoshino@gmail.com>
Mon, 24 Sep 2018 19:55:28 +0000 (15:55 -0400)
committerDylan William Hardison <dylan@hardison.net>
Mon, 24 Sep 2018 19:55:28 +0000 (15:55 -0400)
extensions/BMO/template/en/default/global/choose-product.html.tmpl
extensions/BMO/web/js/new-bug-frequent-comp.js [new file with mode: 0644]
extensions/BMO/web/styles/choose_product.css
template/en/default/global/header.html.tmpl

index 163c71f5c68f6bba09b170ef6a2f4a66aac6f7de..74c9f7b0dae5242074da6de11abc932b334116db 100644 (file)
     "extensions/BMO/web/styles/choose_product.css",
     "extensions/ProdCompSearch/web/styles/prod_comp_search.css",
   ];
-  javascript_urls = [ "extensions/ProdCompSearch/web/js/prod_comp_search.js" ];
+  javascript_urls = [
+    "extensions/BMO/web/js/new-bug-frequent-comp.js",
+    "extensions/ProdCompSearch/web/js/prod_comp_search.js",
+  ];
 
   cgi = Bugzilla.cgi;
   classification = cgi.param('classification');
   %]
 </div>
 
+[% IF NOT is_describe %]
+<section id="frequent-components" hidden>
+  <h2>Choose from your most-used components</h2>
+  <div class="results"></div>
+</section>
+[% END %]
+
 <section id="product-list">
   <h2>or choose from the following selections</h2>
 
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 (file)
index 0000000..4ca1fcf
--- /dev/null
@@ -0,0 +1,111 @@
+/* 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;
+
+    try {
+      const results = await this.fetch();
+
+      this.$message.remove();
+      this.$results.insertAdjacentHTML('beforeend',
+        `<ul>${results.map(({ product, component }) => (
+          `<li><a href="/enter_bug.cgi?product=${encodeURIComponent(product)}&amp;component=` +
+          `${encodeURIComponent(component)}">${product.htmlEncode()} :: ${component.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 });
index 5fd8c49e7b804baa7ef16a615275a5d4dfd5a22f..a4ecf749f006b309949477337bdcc4465b7ad926 100644 (file)
   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;
 }
@@ -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;
index 9db9a1404744ea3cc61637fe2b765ae47d6ac498..4c6069c7412ec90b10e8265ee5d4f529abfd9ae8 100644 (file)
     [% END %]
 
     [%- js_BUGZILLA = {
+            user => {
+                # TODO: Move all properties form bug_modal/header.html.tmpl
+                login => user.login,
+            },
             param => {
                 maxattachmentsize => Param('maxattachmentsize'),
                 maxusermatches => Param('maxusermatches'),