Merge "Separate CCs from reviewers when NoteDb is enabled"
diff --git a/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry.js b/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry.js
index 23f0b13..c5827d0 100644
--- a/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry.js
+++ b/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry.js
@@ -26,6 +26,7 @@
properties: {
borderless: Boolean,
change: Object,
+ filter: Function,
placeholder: String,
suggestFrom: {
@@ -33,30 +34,14 @@
value: 3,
},
- filter: {
- type: Function,
- value: function() {
- return this.notOwnerOrReviewer.bind(this);
- },
- },
-
query: {
type: Function,
value: function() {
return this._getReviewerSuggestions.bind(this);
},
},
-
- _reviewers: {
- type: Array,
- value: function() { return []; },
- },
},
- observers: [
- '_reviewersChanged(change.reviewers.*, change.owner)',
- ],
-
get focusStart() {
return this.$.input.focusStart;
},
@@ -73,30 +58,6 @@
this.fire('add', {value: e.detail.value});
},
- _reviewersChanged: function(changeRecord, owner) {
- var reviewerSet = {};
- reviewerSet[owner._account_id] = true;
- var addReviewers = function(reviewers) {
- if (!reviewers) {
- return;
- }
- reviewers.forEach(function(reviewer) {
- reviewerSet[reviewer._account_id] = true;
- });
- };
-
- var reviewers = changeRecord.base;
- addReviewers(reviewers.CC);
- addReviewers(reviewers.REVIEWER);
- this._reviewers = reviewerSet;
- },
-
- notOwnerOrReviewer: function(reviewer) {
- var account = reviewer.account;
- if (!account) { return true; }
- return !this._reviewers[reviewer.account._account_id];
- },
-
_makeSuggestion: function(reviewer) {
if (reviewer.account) {
return {
@@ -117,6 +78,7 @@
return xhr.then(function(reviewers) {
if (!reviewers) { return []; }
+ if (!this.filter) { return reviewers.map(this._makeSuggestion); }
return reviewers
.filter(this.filter)
.map(this._makeSuggestion);
diff --git a/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry_test.html b/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry_test.html
index f9527ca..94db890 100644
--- a/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry_test.html
+++ b/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry_test.html
@@ -84,15 +84,6 @@
});
});
- test('notOwnerOrReviewer', function() {
- var account = makeAccount();
- assert.isTrue(element.notOwnerOrReviewer({}));
- assert.isTrue(element.notOwnerOrReviewer({account: account}));
- assert.isFalse(element.notOwnerOrReviewer({account: owner}));
- assert.isFalse(element.notOwnerOrReviewer({account: existingReviewer1}));
- assert.isFalse(element.notOwnerOrReviewer({account: existingReviewer2}));
- });
-
test('_makeSuggestion formats account or group accordingly', function() {
var account = makeAccount();
var suggestion = element._makeSuggestion({account: account});
@@ -111,36 +102,20 @@
test('_getReviewerSuggestions excludes owner+reviewers', function(done) {
element._getReviewerSuggestions().then(function(reviewers) {
- assert.deepEqual(reviewers, [
- element._makeSuggestion(suggestion1),
- element._makeSuggestion(suggestion2),
- element._makeSuggestion(suggestion3),
- ]);
- done();
+ // Default is no filtering.
+ assert.equal(reviewers.length, 6);
+
+ // Set up filter that only accepts suggestion1.
+ var accountId = suggestion1.account._account_id;
+ element.filter = function(suggestion) {
+ return suggestion.account &&
+ suggestion.account._account_id === accountId;
+ };
+
+ element._getReviewerSuggestions().then(function(reviewers) {
+ assert.deepEqual(reviewers, [element._makeSuggestion(suggestion1)]);
+ }).then(done);
});
});
-
- test('_updateReviewers', function() {
- // delete existingReviewer1
- element.splice('change.reviewers.CC', 0, 1);
- var expected = {};
- expected[owner._account_id] = true;
- expected[existingReviewer2._account_id] = true;
- assert.deepEqual(element._reviewers, expected);
-
- // delete existingReviewer2
- element.splice('change.reviewers.REVIEWER', 0, 1);
- delete expected[existingReviewer2._account_id];
- assert.deepEqual(element._reviewers, expected);
-
- // add two new reviewers
- var account1 = makeAccount();
- var account2 = makeAccount();
- element.push('change.reviewers.CC', account1);
- element.push('change.reviewers.REVIEWER', account2);
- expected[account1._account_id] = true;
- expected[account2._account_id] = true;
- assert.deepEqual(element._reviewers, expected);
- });
});
</script>
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 c7de5d7..9f7f43f 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
@@ -23,6 +23,7 @@
value: function() { return []; },
},
change: Object,
+ filter: Function,
placeholder: String,
pendingConfirmation: {
type: Object,
@@ -30,13 +31,6 @@
notify: true,
},
readonly: Boolean,
-
- filter: {
- type: Function,
- value: function() {
- return this._filterSuggestion.bind(this);
- },
- },
},
listeners: {
@@ -90,31 +84,6 @@
return !this.readonly && !!account._pendingAdd;
},
- _filterSuggestion: function(reviewer) {
- // If the reviewer is already on the change.
- if (!this.$.entry.notOwnerOrReviewer(reviewer)) {
- return false;
- }
-
- // If the reviewer is in the pending list to be added to the change.
- for (var i = 0; i < this.accounts.length; i++) {
- var account = this.accounts[i];
- if (!account._pendingAdd) {
- continue;
- }
- if (reviewer.group && account._group &&
- reviewer.group.id === account.id) {
- return false;
- }
- if (reviewer.account && !account._group &&
- reviewer.account._account_id === account._account_id) {
- return false;
- }
- }
-
- return true;
- },
-
_handleRemove: function(e) {
var toRemove = e.detail.account;
for (var i = 0; i < this.accounts.length; i++) {
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 1bf2a30..bb55d08 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
@@ -232,57 +232,5 @@
},
]);
});
-
- suite('_filterSuggestion', function() {
- var notOwnerOrReviewerStub;
-
- setup(function() {
- notOwnerOrReviewerStub = sinon.stub(element.$.entry,
- 'notOwnerOrReviewer');
- });
-
- teardown(function() {
- notOwnerOrReviewerStub.restore();
- });
-
-
- test('_filterSuggestion owner or reviewer', function() {
- notOwnerOrReviewerStub.returns(false);
- var reviewer = {account: makeAccount()};
-
- var result = element._filterSuggestion(reviewer);
-
- assert.isFalse(result);
- });
-
- test('_filterSuggestion new', function() {
- notOwnerOrReviewerStub.returns(true);
- var reviewer = {account: makeAccount()};
-
- var result = element._filterSuggestion(reviewer);
-
- assert.isTrue(result);
- });
-
- test('_filterSuggestion pending', function() {
- notOwnerOrReviewerStub.returns(true);
- var reviewer = {account: element.accounts[1]};
- element.accounts[1]._pendingAdd = true;
-
- var result = element._filterSuggestion(reviewer);
-
- assert.isFalse(result);
- });
-
- test('_filterSuggestion new with pending', function() {
- notOwnerOrReviewerStub.returns(true);
- var reviewer = {account: makeAccount()};
- element.accounts[1]._pendingAdd = true;
-
- var result = element._filterSuggestion(reviewer);
-
- assert.isTrue(result);
- });
- });
});
</script>
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 9ddd66d9..bda9dee 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
@@ -89,15 +89,36 @@
<gr-account-link account="[[change.owner]]"></gr-account-link>
</span>
</section>
- <section>
- <span class="title">Reviewers</span>
- <span class="value">
- <gr-reviewer-list
- change="{{change}}"
- mutable="[[mutable]]"
- suggest-from="[[serverConfig.suggest.from]]"></gr-reviewer-list>
- </span>
- </section>
+ <template is="dom-if" if="[[_showReviewersByState]]">
+ <section>
+ <span class="title">Reviewers</span>
+ <span class="value">
+ <gr-reviewer-list
+ change="{{change}}"
+ mutable="[[mutable]]"
+ reviewers-only></gr-reviewer-list>
+ </span>
+ </section>
+ <section>
+ <span class="title">CC</span>
+ <span class="value">
+ <gr-reviewer-list
+ change="{{change}}"
+ mutable="[[mutable]]"
+ ccs-only></gr-reviewer-list>
+ </span>
+ </section>
+ </template>
+ <template is="dom-if" if="[[!_showReviewersByState]]">
+ <section>
+ <span class="title">Reviewers</span>
+ <span class="value">
+ <gr-reviewer-list
+ change="{{change}}"
+ mutable="[[mutable]]"></gr-reviewer-list>
+ </span>
+ </section>
+ </template>
<section>
<span class="title">Project</span>
<span class="value">[[change.project]]</span>
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 e24cc4a..af19703 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
@@ -42,6 +42,10 @@
type: Boolean,
computed: '_computeTopicReadOnly(mutable, change)',
},
+ _showReviewersByState: {
+ type: Boolean,
+ computed: '_computeShowReviewersByState(serverConfig)',
+ },
},
behaviors: [
@@ -134,5 +138,9 @@
_computeTopicPlaceholder: function(_topicReadOnly) {
return _topicReadOnly ? 'No Topic' : 'Click to add topic';
},
+
+ _computeShowReviewersByState: function(serverConfig) {
+ return !!serverConfig.note_db_enabled;
+ },
});
})();
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 a66d020..01f0649 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
@@ -140,5 +140,17 @@
assert.equal(link, 'url-base/xx project-name xx commit-sha xx');
assert.notEqual(link, '../../link-url');
});
+
+ test('show CC section when NoteDb enabled', function() {
+ function hasCc() {
+ return element._showReviewersByState;
+ }
+
+ element.serverConfig = {};
+ assert.isFalse(hasCc());
+
+ element.serverConfig = {note_db_enabled: true};
+ assert.isTrue(hasCc());
+ });
});
</script>
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
index 08bfe77..8c22e7c 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
@@ -320,6 +320,7 @@
labels="[[_change.labels]]"
permitted-labels="[[_change.permitted_labels]]"
diff-drafts="[[_diffDrafts]]"
+ server-config="[[serverConfig]]"
on-send="_handleReplySent"
on-cancel="_handleReplyCancel"
hidden$="[[!_loggedIn]]">Reply</gr-reply-dialog>
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
index 378e588..700f162 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
@@ -318,7 +318,11 @@
},
_handleShowReplyDialog: function(e) {
- this._openReplyDialog(this.$.replyDialog.FocusTarget.REVIEWERS);
+ var target = this.$.replyDialog.FocusTarget.REVIEWERS;
+ if (e.detail.value && e.detail.value.ccsOnly) {
+ target = this.$.replyDialog.FocusTarget.CCS;
+ }
+ this._openReplyDialog(target);
},
_paramsChanged: function(value) {
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
index bba0a63..141940d 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
@@ -313,5 +313,20 @@
assert.isNull(element._change.topic);
});
});
+
+ test('reply dialog focus can be controlled', function() {
+ var FocusTarget = element.$.replyDialog.FocusTarget;
+ var openSpy = sinon.spy(element, '_openReplyDialog');
+
+ var e = {detail: {}};
+ element._handleShowReplyDialog(e);
+ assert(openSpy.lastCall.calledWithExactly(FocusTarget.REVIEWERS),
+ '_openReplyDialog should have been passed REVIEWERS');
+
+ e.detail.value = {ccsOnly: true};
+ element._handleShowReplyDialog(e);
+ assert(openSpy.lastCall.calledWithExactly(FocusTarget.CCS),
+ '_openReplyDialog should have been passed CCS');
+ });
});
</script>
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
index 66a1bd0..9e8f740 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
@@ -150,10 +150,24 @@
id="reviewers"
accounts="[[_reviewers]]"
change="[[change]]"
+ filter="[[filterReviewerSuggestion]]"
pending-confirmation="{{_reviewerPendingConfirmation}}"
placeholder="Add reviewer...">
</gr-account-list>
</div>
+ <template is="dom-if" if="[[serverConfig.note_db_enabled]]">
+ <div class="peopleList">
+ <div class="peopleListLabel">CC</div>
+ <gr-account-list
+ id="ccs"
+ accounts="[[_ccs]]"
+ change="[[change]]"
+ filter="[[filterReviewerSuggestion]]"
+ pending-confirmation="{{_ccPendingConfirmation}}"
+ placeholder="Add CC...">
+ </gr-account-list>
+ </div>
+ </template>
<gr-overlay
id="reviewerConfirmationOverlay"
on-iron-overlay-canceled="_cancelPendingReviewer"
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
index d4b0cb2..5b6bf16 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
@@ -18,6 +18,7 @@
var FocusTarget = {
BODY: 'body',
+ CCS: 'cc',
REVIEWERS: 'reviewers',
};
@@ -51,11 +52,23 @@
observer: '_draftChanged',
},
diffDrafts: Object,
+ filterReviewerSuggestion: {
+ type: Function,
+ value: function() {
+ return this._filterReviewerSuggestion.bind(this);
+ },
+ },
labels: Object,
permittedLabels: Object,
+ serverConfig: Object,
_account: Object,
- _owners: Array,
+ _ccs: Array,
+ _ccPendingConfirmation: {
+ type: Object,
+ observer: '_reviewerPendingConfirmationUpdated',
+ },
+ _owner: Object,
_reviewers: Array,
_reviewerPendingConfirmation: {
type: Object,
@@ -70,7 +83,7 @@
],
observers: [
- '_changeUpdated(change.*)',
+ '_changeUpdated(change.reviewers.*, change.owner)',
],
attached: function() {
@@ -110,6 +123,18 @@
selectorEl.selectIndex(selectorEl.indexOf(item));
},
+ _mapReviewer: function(reviewer) {
+ var reviewerId;
+ var confirmed;
+ if (reviewer.account) {
+ reviewerId = reviewer.account._account_id;
+ } else if (reviewer.group) {
+ reviewerId = reviewer.group.id;
+ confirmed = reviewer.group.confirmed;
+ }
+ return {reviewer: reviewerId, confirmed: confirmed};
+ },
+
send: function() {
var obj = {
drafts: 'PUBLISH_ALL_REVISIONS',
@@ -131,27 +156,20 @@
obj.message = this.draft;
}
- var newReviewers = this.$.reviewers.additions();
- newReviewers.forEach(function(reviewer) {
- var reviewerId;
- var confirmed;
- if (reviewer.account) {
- reviewerId = reviewer.account._account_id;
- } else if (reviewer.group) {
- reviewerId = reviewer.group.id;
- confirmed = reviewer.group.confirmed;
- }
- if (!obj.reviewers) {
- obj.reviewers = [];
- }
- obj.reviewers.push({reviewer: reviewerId, confirmed: confirmed});
- });
+ obj.reviewers = this.$.reviewers.additions().map(this._mapReviewer);
+ if (this.serverConfig.note_db_enabled) {
+ this.$$('#ccs').additions().forEach(function(reviewer) {
+ reviewer = this._mapReviewer(reviewer);
+ reviewer.state = 'CC';
+ obj.reviewers.push(reviewer);
+ }.bind(this));
+ }
this.disabled = true;
var errFn = this._handle400Error.bind(this);
return this._saveReview(obj, errFn).then(function(response) {
- if (!response.ok) {
+ if (!response || !response.ok) {
return response;
}
this.disabled = false;
@@ -170,6 +188,9 @@
} else if (section === FocusTarget.REVIEWERS) {
var reviewerEntry = this.$.reviewers.focusStart;
reviewerEntry.async(reviewerEntry.focus);
+ } else if (section === FocusTarget.CCS) {
+ var ccEntry = this.$$('#ccs').focusStart;
+ ccEntry.async(ccEntry.focus);
}
},
@@ -190,7 +211,7 @@
if (response.status !== 400) {
// This is all restAPI does when there is no custom error handling.
this.fire('server-error', {response: response});
- return;
+ return response;
}
// Process the response body, format a better error message, and fire
@@ -279,32 +300,67 @@
return permittedLabels[label];
},
- _changeUpdated: function(changeRecord) {
- if (!changeRecord.path || !changeRecord.base) {
- return;
+ _changeUpdated: function(changeRecord, owner) {
+ this._owner = owner;
+
+ var reviewers = [];
+ var ccs = [];
+
+ for (var key in changeRecord.base) {
+ if (key !== 'REVIEWER' && key !== 'CC') {
+ console.warn('unexpected reviewer state:', key);
+ continue;
+ }
+ changeRecord.base[key].forEach(function(entry) {
+ if (entry._account_id === owner._account_id) {
+ return;
+ }
+ switch (key) {
+ case 'REVIEWER':
+ reviewers.push(entry);
+ break;
+ case 'CC':
+ ccs.push(entry);
+ break;
+ }
+ });
}
- if (changeRecord.path !== 'change' &&
- changeRecord.path !== 'change.reviewers.CC.splices' &&
- changeRecord.path !== 'change.reviewers.REVIEWER.splices') {
- return;
+ if (this.serverConfig.note_db_enabled) {
+ this._ccs = ccs;
+ } else {
+ reviewers = reviewers.concat(ccs);
}
-
- var owner = changeRecord.base.owner;
- this._owners = [owner];
-
- if (!changeRecord.base.reviewers) {
- return;
- }
-
- var reviewers = changeRecord.base.reviewers.REVIEWER || [];
- reviewers = reviewers.concat(changeRecord.base.reviewers.CC);
- reviewers = reviewers.filter(function(account) {
- return account && account._account_id !== owner._account_id;
- }.bind(this));
this._reviewers = reviewers;
},
+ _accountOrGroupKey: function(entry) {
+ return entry.id || entry._account_id;
+ },
+
+ _filterReviewerSuggestion: function(suggestion) {
+ var entry;
+ if (suggestion.account) {
+ entry = suggestion.account;
+ } else if (suggestion.group) {
+ entry = suggestion.group;
+ } else {
+ console.warn('received suggestion that was neither account nor group:',
+ suggestion);
+ }
+ if (entry._account_id === this._owner._account_id) {
+ return false;
+ }
+
+ var key = this._accountOrGroupKey(entry);
+ var finder = function(entry) {
+ return this._accountOrGroupKey(entry) === key;
+ }.bind(this);
+
+ return this._reviewers.find(finder) === undefined &&
+ this._ccs.find(finder) === undefined;
+ },
+
_getAccount: function() {
return this.$.restAPI.getAccount();
},
@@ -333,13 +389,22 @@
},
_confirmPendingReviewer: function() {
- this.$.reviewers.confirmGroup(this._reviewerPendingConfirmation.group);
- this._focusOn(FocusTarget.REVIEWERS);
+ if (this._ccPendingConfirmation) {
+ this.$$('#ccs').confirmGroup(this._ccPendingConfirmation.group);
+ this._focusOn(FocusTarget.CCS);
+ } else {
+ this.$.reviewers.confirmGroup(this._reviewerPendingConfirmation.group);
+ this._focusOn(FocusTarget.REVIEWERS);
+ }
},
_cancelPendingReviewer: function() {
+ this._ccPendingConfirmation = null;
this._reviewerPendingConfirmation = null;
- this._focusOn(FocusTarget.REVIEWERS);
+
+ var target =
+ this._ccPendingConfirmation ? FocusTarget.CCS : FocusTarget.REVIEWERS;
+ this._focusOn(target);
},
_getStorageLocation: function() {
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
index 7dc601a..96b1590 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
@@ -87,6 +87,7 @@
'+1'
]
};
+ element.serverConfig = {};
getDraftCommentStub = sandbox.stub(element.$.storage, 'getDraftComment');
setDraftCommentStub = sandbox.stub(element.$.storage, 'setDraftComment');
@@ -144,7 +145,8 @@
'Code-Review': -1,
'Verified': -1
},
- message: 'I wholeheartedly disapprove'
+ message: 'I wholeheartedly disapprove',
+ reviewers: [],
});
return Promise.resolve({ok: true});
});
@@ -308,11 +310,57 @@
}
event.detail.response.text().then(function(body) {
assert.equal(body, 'first error, second error');
- done();
});
});
+ element.send().then(done);
+ });
- element.send();
+ test('ccs are displayed if NoteDb is enabled', function() {
+ function hasCc() {
+ flushAsynchronousOperations();
+ return !!element.$$('#ccs');
+ }
+
+ element.serverConfig = {};
+ assert.isFalse(hasCc());
+
+ element.serverConfig = {note_db_enabled: true};
+ assert.isTrue(hasCc());
+ });
+
+ test('filterReviewerSuggestion', function() {
+ var counter = 0;
+ function makeAccount() {
+ return {_account_id: counter++};
+ }
+ function makeGroup() {
+ return {id: counter++};
+ }
+
+ var owner = makeAccount();
+ var reviewer1 = makeAccount();
+ var reviewer2 = makeGroup();
+ var cc1 = makeAccount();
+ var cc2 = makeGroup();
+
+ element._owner = owner;
+ element._reviewers = [reviewer1, reviewer2];
+ element._ccs = [cc1, cc2];
+
+ assert.isTrue(
+ element._filterReviewerSuggestion({account: makeAccount()}));
+ assert.isTrue(element._filterReviewerSuggestion({group: makeGroup()}));
+
+ // Owner should be excluded.
+ assert.isFalse(element._filterReviewerSuggestion({account: owner}));
+
+ // Existing and pending reviewers should be excluded.
+ assert.isFalse(element._filterReviewerSuggestion({account: reviewer1}));
+ assert.isFalse(element._filterReviewerSuggestion({group: reviewer2}));
+
+ // Existing and pending CCs should be excluded.
+ assert.isFalse(element._filterReviewerSuggestion({account: cc1}));
+ assert.isFalse(element._filterReviewerSuggestion({group: cc2}));
});
});
</script>
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.html b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.html
index 99e3cd9..435b7de 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.html
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.html
@@ -68,7 +68,7 @@
link
id="addReviewer"
class="addReviewer"
- on-tap="_handleAddTap">Add reviewer</gr-button>
+ on-tap="_handleAddTap">[[_addLabel]]</gr-button>
</div>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
</template>
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
index 7037fc2..72a7c9b 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
@@ -34,9 +34,13 @@
type: Boolean,
value: false,
},
- suggestFrom: {
- type: Number,
- value: 3,
+ reviewersOnly: {
+ type: Boolean,
+ value: false,
+ },
+ ccsOnly: {
+ type: Boolean,
+ value: false,
},
_reviewers: {
@@ -47,6 +51,10 @@
type: Boolean,
value: false,
},
+ _addLabel: {
+ type: String,
+ computed: '_computeAddLabel(ccsOnly)',
+ },
// Used for testing.
_lastAutocompleteRequest: Object,
@@ -61,7 +69,13 @@
var result = [];
var reviewers = changeRecord.base;
for (var key in reviewers) {
- if (key == 'REVIEWER' || key == 'CC') {
+ if (this.reviewersOnly && key !== 'REVIEWER') {
+ continue;
+ }
+ if (this.ccsOnly && key !== 'CC') {
+ continue;
+ }
+ if (key === 'REVIEWER' || key === 'CC') {
result = result.concat(reviewers[key]);
}
}
@@ -110,11 +124,22 @@
_handleAddTap: function(e) {
e.preventDefault();
- this.fire('show-reply-dialog');
+ var value = {};
+ if (this.reviewersOnly) {
+ value.reviewersOnly = true;
+ }
+ if (this.ccsOnly) {
+ value.ccsOnly = true;
+ }
+ this.fire('show-reply-dialog', {value: value});
},
_removeReviewer: function(id) {
return this.$.restAPI.removeChangeReviewer(this.change._number, id);
},
+
+ _computeAddLabel: function(ccsOnly) {
+ return ccsOnly ? 'Add CC' : 'Add reviewer';
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
index e6f7a20..6c6125c 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
@@ -34,9 +34,11 @@
<script>
suite('gr-reviewer-list tests', function() {
var element;
+ var sandbox;
setup(function() {
element = fixture('basic');
+ sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
removeChangeReviewer: function() {
return Promise.resolve({ok: true});
@@ -44,6 +46,10 @@
});
});
+ teardown(function() {
+ sandbox.restore();
+ });
+
test('controls hidden on immutable element', function() {
element.mutable = false;
assert.isTrue(element.$$('.controlsContainer').hasAttribute('hidden'));
@@ -113,5 +119,65 @@
}
});
});
+
+ test('tracking reviewers and ccs', function() {
+ var counter = 0;
+ function makeAccount() {
+ return {_account_id: counter++};
+ }
+
+ var owner = makeAccount();
+ var reviewer = makeAccount();
+ var cc = makeAccount();
+ var reviewers = {
+ REMOVED: [makeAccount()],
+ REVIEWER: [owner, reviewer],
+ CC: [owner, cc],
+ };
+
+ element.ccsOnly = false;
+ element.reviewersOnly = false;
+ element.change = {
+ owner: owner,
+ reviewers: reviewers,
+ };
+ assert.deepEqual(element._reviewers, [reviewer, cc]);
+
+ element.reviewersOnly = true;
+ element.change = {
+ owner: owner,
+ reviewers: reviewers,
+ };
+ assert.deepEqual(element._reviewers, [reviewer]);
+
+ element.ccsOnly = true;
+ element.reviewersOnly = false;
+ element.change = {
+ owner: owner,
+ reviewers: reviewers,
+ };
+ assert.deepEqual(element._reviewers, [cc]);
+ });
+
+ test('_handleAddTap passes mode with event', function() {
+ var fireStub = sandbox.stub(element, 'fire');
+ var e = {preventDefault: function() {}};
+
+ element.ccsOnly = false;
+ element.reviewersOnly = false;
+ element._handleAddTap(e);
+ assert.isTrue(fireStub.calledWith('show-reply-dialog', {value: {}}));
+
+ element.reviewersOnly = true;
+ element._handleAddTap(e);
+ assert.isTrue(fireStub.lastCall.calledWith('show-reply-dialog',
+ {value: {reviewersOnly: true}}));
+
+ element.ccsOnly = true;
+ element.reviewersOnly = false;
+ element._handleAddTap(e);
+ assert.isTrue(fireStub.lastCall.calledWith('show-reply-dialog',
+ {value: {ccsOnly: true}}));
+ });
});
</script>