Navigate directly when change ID, number, or commit hash is searched

When a change ID, number, or commit hash is a complete match for the
search string, navigate directly to the corresponding change.

In some cases there will be multiple results for a truncated hash
search. In that case, still display the search screen.

Feature: Issue 5680
Change-Id: Icaa3dab3edab9f60b8dcda6ef71a75980e4b7127
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
index fc9b26f..b2e8051 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
@@ -14,6 +14,11 @@
 (function() {
   'use strict';
 
+  var LookupQueryPatterns = {
+    CHANGE_ID: /^\s*i?[0-9a-f]{8,40}\s*$/i,
+    CHANGE_NUM: /^\s*[1-9][0-9]*\s*$/g,
+  };
+
   Polymer({
     is: 'gr-change-list-view',
 
@@ -55,7 +60,10 @@
       /**
        * Currently active query.
        */
-      _query: String,
+      _query: {
+        type: String,
+        value: '',
+      },
 
       /**
        * Offset of currently visible query results.
@@ -104,6 +112,15 @@
         this._changesPerPage = prefs.changes_per_page;
         return this._getChanges();
       }.bind(this)).then(function(changes) {
+        if (this._query && changes.length === 1) {
+          for (var query in LookupQueryPatterns) {
+            if (LookupQueryPatterns.hasOwnProperty(query) &&
+                this._query.match(LookupQueryPatterns[query])) {
+              page.show('/c/' + changes[0]._number);
+              return;
+            }
+          }
+        }
         this._changes = changes;
         this._loading = false;
       }.bind(this));