diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.html b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.html index f559794fed..fecb376994 100644 --- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.html +++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.html @@ -15,8 +15,8 @@ limitations under the License. --> - + @@ -28,13 +28,14 @@ limitations under the License. form { display: flex; } - input { + gr-autocomplete { + background-color: white; border: 1px solid #d1d2d3; border-radius: 2px 0 0 2px; flex: 1; font: inherit; outline: none; - padding: 0 .25em; + padding: 0 .25em 0 .25em; } gr-button { background-color: #f1f2f3; @@ -43,7 +44,14 @@ limitations under the License. }
- + Search
diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js index 7970169df0..8e52f8f83d 100644 --- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js +++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js @@ -14,6 +14,70 @@ (function() { 'use strict'; + // Possible static search options for auto complete. + var SEARCH_OPERATORS = [ + 'added', + 'age', + 'age:1week', // Give an example age + 'author', + 'branch', + 'bug', + 'change', + 'comment', + 'commentby', + 'commit', + 'committer', + 'conflicts', + 'deleted', + 'delta', + 'file', + 'from', + 'has', + 'has:draft', + 'has:edit', + 'has:star', + 'has:stars', + 'intopic', + 'is', + 'is:abandoned', + 'is:closed', + 'is:draft', + 'is:mergeable', + 'is:merged', + 'is:open', + 'is:owner', + 'is:pending', + 'is:reviewed', + 'is:reviewer', + 'is:starred', + 'is:watched', + 'label', + 'message', + 'owner', + 'ownerin', + 'parentproject', + 'project', + 'projects', + 'query', + 'ref', + 'reviewedby', + 'reviewer', + 'reviewer:self', + 'reviewerin', + 'size', + 'star', + 'status', + 'status:abandoned', + 'status:closed', + 'status:draft', + 'status:merged', + 'status:open', + 'status:pending', + 'status:reviewed', + 'topic', + 'tr', + ]; + Polymer({ is: 'gr-search-bar', @@ -22,7 +86,6 @@ ], listeners: { - 'searchInput.keydown': '_inputKeyDownHandler', 'searchButton.tap': '_preventDefaultAndNavigateToInputVal', }, @@ -37,7 +100,12 @@ type: Object, value: function() { return document.body; }, }, - + query: { + type: Function, + value: function() { + return this._getSearchSuggestions.bind(this); + }, + }, _inputVal: String, }, @@ -45,10 +113,8 @@ this._inputVal = value; }, - _inputKeyDownHandler: function(e) { - if (e.keyCode == 13) { // Enter key - this._preventDefaultAndNavigateToInputVal(e); - } + _handleInputCommit: function(e) { + this._preventDefaultAndNavigateToInputVal(e); }, _preventDefaultAndNavigateToInputVal: function(e) { @@ -58,6 +124,36 @@ page.show('/q/' + encodeURIComponent(encodeURIComponent(this._inputVal))); }, + // TODO(kaspern): Flesh this out better. + _makeSuggestion: function(str) { + return { + name: str, + value: str, + }; + }, + + // TODO(kaspern): Expand support for more complicated autocomplete features. + _getSearchSuggestions: function(input) { + return Promise.resolve(SEARCH_OPERATORS).then(function(operators) { + if (!operators) { return []; } + var lowerCaseInput = input + .substring(input.lastIndexOf(' ') + 1) + .toLowerCase(); + return operators + .filter(function(operator) { + // Disallow autocomplete values that exactly match the whole str. + var opContainsInput = operator.indexOf(lowerCaseInput) !== -1; + var inputContainsOp = lowerCaseInput.indexOf(operator) !== -1; + return opContainsInput && !inputContainsOp; + }) + // Prioritize results that start with the input. + .sort(function(operator) { + return operator.indexOf(lowerCaseInput); + }) + .map(this._makeSuggestion); + }.bind(this)); + }, + _handleKey: function(e) { if (this.shouldSupressKeyboardShortcut(e)) { return; } switch (e.keyCode) { diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html index daa0c1a4ca..0c16774732 100644 --- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html +++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html @@ -68,15 +68,33 @@ limitations under the License. assert.notEqual(getActiveElement(), element.$.searchButton); done(); }); - MockInteractions.pressAndReleaseKeyOn(element.$.searchInput, 13); + MockInteractions.pressAndReleaseKeyOn(element.$.searchInput.$.input, 13); }); test('search query should be double-escaped', function() { var showStub = sinon.stub(page, 'show'); - element._inputVal = 'fate/stay'; - MockInteractions.pressAndReleaseKeyOn(element.$.searchInput, 13); + element.$.searchInput.text = 'fate/stay'; + MockInteractions.pressAndReleaseKeyOn(element.$.searchInput.$.input, 13); assert.equal(showStub.lastCall.args[0], '/q/fate%252Fstay'); showStub.restore(); }); + + test('_getSearchSuggestions returns proper set of suggestions', + function(done) { + element._getSearchSuggestions('is:o') + .then(function(suggestions) { + assert.equal(suggestions[0].name, 'is:open'); + assert.equal(suggestions[0].value, 'is:open'); + assert.equal(suggestions[1].name, 'is:owner'); + assert.equal(suggestions[1].value, 'is:owner'); + }) + .then(function() { + element._getSearchSuggestions('asdasdasdasd') + .then(function(suggestions) { + assert.equal(suggestions.length, 0); + done(); + }); + }); + }); }); diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html index da012075c9..278f002e36 100644 --- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html +++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html @@ -22,6 +22,7 @@ limitations under the License.