Support assignee field in PolyGerrit
Adds max-count prop to gr-account-list and utilizes it to create the
Assignee field in gr-change-metadata with autocompletion.
Feature: Issue 5229
Change-Id: Ifc796703322ff6d68040d10e0294e7aa8f6ce0ea
diff --git a/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list.html b/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list.html
index 43714f2..4ad9053 100644
--- a/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list.html
+++ b/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list.html
@@ -49,7 +49,7 @@
</template>
<gr-account-entry
borderless
- hidden$="[[readonly]]"
+ hidden$="[[_computeEntryHidden(maxCount, accounts.*, readonly)]]"
id="entry"
change="[[change]]"
filter="[[filter]]"
diff --git a/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list.js b/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list.js
index 89820fc..f7e8fde 100644
--- a/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list.js
+++ b/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list.js
@@ -31,7 +31,7 @@
value: null,
notify: true,
},
- readonly: {
+ readonly: {
type: Boolean,
value: false,
},
@@ -40,6 +40,10 @@
* undefined, all values are removable.
*/
removableValues: Array,
+ maxCount: {
+ type: Number,
+ value: 0,
+ },
},
listeners: {
@@ -198,5 +202,9 @@
}
});
},
+
+ _computeEntryHidden: function(maxCount, accountsRecord, readonly) {
+ return (maxCount && maxCount <= accountsRecord.base.length) || readonly;
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list_test.html b/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list_test.html
index 9b32856..a334b03 100644
--- a/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-account-list/gr-account-list_test.html
@@ -250,6 +250,20 @@
assert.equal(element.accounts.length, 1);
});
+ test('max-count', function() {
+ element.maxCount = 1;
+ var acct = makeAccount();
+ element._handleAdd({
+ detail: {
+ value: {
+ account: acct,
+ },
+ },
+ });
+ flushAsynchronousOperations();
+ assert.isTrue(element.$.entry.hasAttribute('hidden'));
+ });
+
suite('keyboard interactions', function() {
test('backspace at text input start removes last account', function() {
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
index ce17b3a..4cb2d19 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
@@ -107,6 +107,19 @@
</section>
<template is="dom-if" if="[[_showReviewersByState]]">
<section>
+ <span class="title">Assignee</span>
+ <span class="value">
+ <gr-account-list
+ max-count="1"
+ id="assigneeValue"
+ placeholder="Add assignee..."
+ accounts="{{_assignee}}"
+ filter="[[_filterAssigneeSuggestion]]"
+ change="[[change]]"
+ readonly="[[!mutable]]"></gr-account-list>
+ </span>
+ </section>
+ <section>
<span class="title">Reviewers</span>
<span class="value">
<gr-reviewer-list
@@ -127,6 +140,19 @@
</template>
<template is="dom-if" if="[[!_showReviewersByState]]">
<section>
+ <span class="title">Assignee</span>
+ <span class="value">
+ <gr-account-list
+ max-count="1"
+ id="assigneeValue"
+ placeholder="Add assignee..."
+ accounts="{{_assignee}}"
+ filter="[[_filterAssigneeSuggestion]]"
+ change="[[change]]"
+ readonly="[[!mutable]]"></gr-account-list>
+ </span>
+ </section>
+ <section>
<span class="title">Reviewers</span>
<span class="value">
<gr-reviewer-list
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
index b56324a..16915ab 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
@@ -41,12 +41,48 @@
type: Boolean,
computed: '_computeShowLabelStatus(change)',
},
+ /**
+ * Groups are not valid assignees.
+ */
+ _filterAssigneeSuggestion: {
+ type: Function,
+ value: function() {
+ return function(suggestion) { return suggestion.account; };
+ },
+ },
+
+ _assignee: Array,
},
behaviors: [
Gerrit.RESTClientBehavior,
],
+ observers: [
+ '_changeChanged(change)',
+ '_assigneeChanged(_assignee.*)',
+ ],
+
+ _changeChanged: function(change) {
+ this._assignee = change.assignee ? [change.assignee] : [];
+ },
+
+ _assigneeChanged: function(assigneeRecord) {
+ if (!this.change) { return; }
+ var assignee = assigneeRecord.base;
+ if (assignee.length) {
+ var acct = assignee[0];
+ if (this.change.assignee &&
+ acct._account_id === this.change.assignee._account_id) { return; }
+ this.set(['change', 'assignee'], acct);
+ this.$.restAPI.setAssignee(this.change.change_id, acct._account_id);
+ } else {
+ if (!this.change.assignee) { return; }
+ this.set(['change', 'assignee'], undefined);
+ this.$.restAPI.deleteAssignee(this.change.change_id);
+ }
+ },
+
_computeHideStrategy: function(change) {
return !this.changeIsOpen(change.status);
},
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
index d354fd7..b2c0fc9 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
@@ -182,6 +182,41 @@
assert.equal(element.change.topic, '');
assert.isTrue(topicStub.called);
});
+
+ suite('assignee field', function() {
+ var dummyAccount = {
+ _account_id: 1,
+ name: 'bojack',
+ };
+ var deleteStub;
+ var setStub;
+ setup(function() {
+ deleteStub = sandbox.stub(element.$.restAPI, 'deleteAssignee');
+ setStub = sandbox.stub(element.$.restAPI, 'setAssignee');
+ });
+
+ test('changing change recomputes _assignee', function() {
+ assert.isFalse(!!element._assignee.length);
+ var change = element.change;
+ change.assignee = dummyAccount;
+ element._changeChanged(change);
+ assert.deepEqual(element._assignee[0], dummyAccount);
+ });
+
+ test('modifying _assignee calls API', function() {
+ assert.isFalse(!!element._assignee.length);
+ element.set('_assignee', [dummyAccount]);
+ assert.isTrue(setStub.calledOnce);
+ assert.deepEqual(element.change.assignee, dummyAccount);
+ element.set('_assignee', [dummyAccount]);
+ assert.isTrue(setStub.calledOnce);
+ element.set('_assignee', []);
+ assert.isTrue(deleteStub.calledOnce);
+ assert.equal(element.change.assignee, undefined);
+ element.set('_assignee', []);
+ assert.isTrue(deleteStub.calledOnce);
+ });
+ });
});
});
</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index 4b52503..96661fd 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -952,5 +952,16 @@
return null;
});
},
+
+ setAssignee: function(changeNum, assignee) {
+ return this.send('PUT',
+ this.getChangeActionURL(changeNum, null, '/assignee'),
+ {assignee: assignee});
+ },
+
+ deleteAssignee: function(changeNum) {
+ return this.send('DELETE',
+ this.getChangeActionURL(changeNum, null, '/assignee'));
+ },
});
})();