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.
}
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.