]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1523536 - New bug's "Choose from your most-used components" list is slow to show up
authorKohei Yoshino <kohei.yoshino@gmail.com>
Mon, 20 May 2019 18:59:40 +0000 (14:59 -0400)
committerGitHub <noreply@github.com>
Mon, 20 May 2019 18:59:40 +0000 (14:59 -0400)
extensions/BMO/template/en/default/global/choose-product.html.tmpl
extensions/BMO/web/js/new-bug-frequent-comp.js [deleted file]
extensions/ProdCompSearch/lib/WebService.pm
extensions/ProdCompSearch/web/js/prod_comp_search.js

index 5615a0355fbac6db5d8e5076b67a6dc14760b236..5233ac403a6d876fb86a8a3b27911de5b94af531 100644 (file)
@@ -37,7 +37,6 @@
     "extensions/ProdCompSearch/web/styles/prod_comp_search.css",
   ];
   javascript_urls = [
-    "extensions/BMO/web/js/new-bug-frequent-comp.js",
     "extensions/ProdCompSearch/web/js/prod_comp_search.js",
   ];
 
diff --git a/extensions/BMO/web/js/new-bug-frequent-comp.js b/extensions/BMO/web/js/new-bug-frequent-comp.js
deleted file mode 100644 (file)
index 060fac2..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/* 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: `${BUGZILLA.config.basepath}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: `${BUGZILLA.config.basepath}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 2242d083d36a52553670866f003bc36639189e5c..602ec466c4d1f13147b69c462a5abe629ba21a49 100644 (file)
@@ -26,7 +26,7 @@ use constant PUBLIC_METHODS => qw(
 
 sub rest_resources {
   return [
-    qr{^/prod_comp_search/(.*)$},
+    qr{^/prod_comp_search/find/(.*)$},
     {
       GET => {
         method => 'prod_comp_search',
@@ -34,6 +34,12 @@ sub rest_resources {
           return {search => $_[0]};
         }
       }
+    },
+    qr{^/prod_comp_search/frequent},
+    {
+      GET => {
+        method => 'list_frequent_components',
+      }
     }
   ];
 }
@@ -148,6 +154,40 @@ sub prod_comp_search {
   return {products => $products};
 }
 
+# Get a list of components the user has frequently reported in the past 2 years
+sub list_frequent_components {
+  my ($self) = @_;
+  my $user = Bugzilla->user;
+
+  # Nothing to show if the user is signed out
+  return {results => []} unless $user->id;
+
+  # Select the date of 2 years ago today
+  my ($day, $month, $year) = (localtime(time))[3, 4, 5];
+  my $date = sprintf('%4d-%02d-%02d', $year + 1900 - 2, $month + 1, $day);
+
+  my $dbh  = Bugzilla->switch_to_shadow_db();
+  my $sth = $dbh->prepare('
+    SELECT products.name, components.name FROM bugs
+    INNER JOIN products ON bugs.product_id = products.id
+    INNER JOIN components ON bugs.component_id = components.id
+    WHERE bugs.reporter = ? AND bugs.creation_ts > ?
+      AND products.isactive = 1 AND components.isactive = 1
+    GROUP BY components.id ORDER BY count(bugs.bug_id) DESC LIMIT 10;
+  ');
+  $sth->execute($user->id, $date);
+
+  my $results = [];
+  while (my ($product, $component) = $sth->fetchrow_array) {
+    push @$results, {
+      product   => $self->type('string', $product),
+      component => $self->type('string', $component),
+    };
+  };
+
+  return {results => $results};
+}
+
 ###################
 # Private Methods #
 ###################
index 4953473ac366cf1b1b7dd7948b41d112d87acaab..42731912a47384f24e4636ae81fab308e81735b0 100644 (file)
@@ -69,7 +69,7 @@ $(function() {
                 appendTo: $('#main-inner'),
                 forceFixPosition: true,
                 serviceUrl: function(query) {
-                    return `${BUGZILLA.config.basepath}rest/prod_comp_search/${encodeURIComponent(query)}`;
+                    return `${BUGZILLA.config.basepath}rest/prod_comp_search/find/${encodeURIComponent(query)}`;
                 },
                 params: params,
                 deferRequestBy: 250,
@@ -149,3 +149,86 @@ $(function() {
         })
         .data('counter', 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.FrequentComponents = class FrequentComponents {
+  /**
+   * Initialize a new FrequentComponents 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: `${BUGZILLA.config.basepath}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.
+   * @returns {Promise} Results or error.
+   */
+  async fetch() {
+    return new Promise((resolve, reject) => bugzilla_ajax({
+      url: `${BUGZILLA.config.basepath}rest/prod_comp_search/frequent`
+    }, ({ results }) => {
+      if (!results) {
+        reject(new Error('Your frequent components could not be retrieved.'));
+      } else if (!results.length) {
+        reject(new Error(('Your frequent components could not be found.')));
+      } else {
+        resolve(results);
+      }
+    }, () => {
+      reject(new Error('Your frequent components could not be retrieved.'));
+    }));
+  }
+};
+
+window.addEventListener('DOMContentLoaded', () => new Bugzilla.FrequentComponents(), { once: true });