Prompt to confirm to add large group as reviewer
Depending on server configuration, a group with a certain number of
members must be marked as explicitly confirmed by the user before it
may be added as a reviewer. This change introduces an overlay on top
of the reply dialog to prompt the user for this confirmation in
advance of submission.
Change-Id: I0a61819e785c9a80aaa12ebae347907e41b24aac
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 828169d..3b792e2 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
@@ -24,6 +24,11 @@
},
change: Object,
placeholder: String,
+ pendingConfirmation: {
+ type: Object,
+ value: null,
+ notify: true,
+ },
readonly: Boolean,
filter: {
@@ -52,10 +57,22 @@
var account = Object.assign({}, reviewer.account, {_pendingAdd: true});
this.push('accounts', account);
} else if (reviewer.group) {
+ if (reviewer.confirm) {
+ this.pendingConfirmation = reviewer;
+ return;
+ }
var group = Object.assign({}, reviewer.group,
{_pendingAdd: true, _group: true});
this.push('accounts', group);
}
+ this.pendingConfirmation = null;
+ },
+
+ confirmGroup: function(group) {
+ group = Object.assign(
+ {}, group, {confirmed: true, _pendingAdd: true, _group: true});
+ this.push('accounts', group);
+ this.pendingConfirmation = null;
},
_computeChipClass: function(account) {
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 79d5e59..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
@@ -199,5 +199,38 @@
},
]);
});
+
+ test('large group confirmations', function() {
+ assert.isNull(element.pendingConfirmation);
+ assert.deepEqual(element.additions(), []);
+
+ var group = makeGroup();
+ var reviewer = {
+ group: group,
+ count: 10,
+ confirm: true,
+ };
+ element._handleAdd({
+ detail: {
+ value: reviewer,
+ },
+ });
+
+ assert.deepEqual(element.pendingConfirmation, reviewer);
+ assert.deepEqual(element.additions(), []);
+
+ element.confirmGroup(group);
+ assert.isNull(element.pendingConfirmation);
+ assert.deepEqual(element.additions(), [
+ {
+ group: {
+ id: group.id,
+ _group: true,
+ _pendingAdd: true,
+ confirmed: true,
+ },
+ },
+ ]);
+ });
});
</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 89cb4a2..e923d48 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
@@ -20,6 +20,7 @@
<link rel="import" href="../../../behaviors/rest-client-behavior.html">
<link rel="import" href="../../shared/gr-button/gr-button.html">
<link rel="import" href="../../shared/gr-js-api-interface/gr-js-api-interface.html">
+<link rel="import" href="../../shared/gr-overlay/gr-overlay.html">
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
<link rel="import" href="../gr-account-list/gr-account-list.html">
@@ -64,6 +65,19 @@
gr-account-list {
flex: 1;
}
+ #reviewerConfirmationOverlay {
+ padding: 1em;
+ text-align: center;
+ }
+ .reviewerConfirmationButtons {
+ margin-top: 1em;
+ }
+ .groupName {
+ font-weight: bold;
+ }
+ .groupSize {
+ font-style: italic;
+ }
.textareaContainer {
position: relative;
display: flex;
@@ -135,9 +149,32 @@
id="reviewers"
accounts="[[_reviewers]]"
change="[[change]]"
+ pending-confirmation="{{_reviewerPendingConfirmation}}"
placeholder="Add reviewer...">
</gr-account-list>
</div>
+ <gr-overlay
+ id="reviewerConfirmationOverlay"
+ on-iron-overlay-canceled="_cancelPendingReviewer"
+ with-backdrop>
+ <div class="reviewerConfirmation">
+ Group
+ <span class="groupName">
+ {{_reviewerPendingConfirmation.group.name}}
+ </span>
+ has
+ <span class="groupSize">
+ {{_reviewerPendingConfirmation.count}}
+ </span>
+ members.
+ <br>
+ Are you sure you want to add them all?
+ </div>
+ <div class="reviewerConfirmationButtons">
+ <gr-button on-tap="_confirmPendingReviewer">Yes</gr-button>
+ <gr-button on-tap="_cancelPendingReviewer">No</gr-button>
+ </div>
+ </gr-overlay>
</section>
<section class="textareaContainer">
<iron-autogrow-textarea
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 9c2d023..b1f5d17 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
@@ -54,6 +54,10 @@
_account: Object,
_owners: Array,
_reviewers: Array,
+ _reviewerPendingConfirmation: {
+ type: Object,
+ observer: '_reviewerPendingConfirmationUpdated',
+ },
},
FocusTarget: FocusTarget,
@@ -130,15 +134,17 @@
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});
+ obj.reviewers.push({reviewer: reviewerId, confirmed: confirmed});
});
this.disabled = true;
@@ -262,5 +268,23 @@
return this.$.restAPI.saveChangeReview(this.change._number, this.patchNum,
review);
},
+
+ _reviewerPendingConfirmationUpdated: function(reviewer) {
+ if (reviewer === null) {
+ this.$.reviewerConfirmationOverlay.close();
+ } else {
+ this.$.reviewerConfirmationOverlay.open();
+ }
+ },
+
+ _confirmPendingReviewer: function() {
+ this.$.reviewers.confirmGroup(this._reviewerPendingConfirmation.group);
+ this.focusOn(FocusTarget.REVIEWERS);
+ },
+
+ _cancelPendingReviewer: function() {
+ this._reviewerPendingConfirmation = null;
+ this.focusOn(FocusTarget.REVIEWERS);
+ },
});
})();
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 cbef78d..0456be1 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
@@ -144,5 +144,92 @@
});
});
});
+
+ function getActiveElement() {
+ return Polymer.IronOverlayManager.deepActiveElement;
+ }
+
+ function isVisible(el) {
+ assert.ok(el);
+ return getComputedStyle(el).getPropertyValue('display') != 'none';
+ }
+
+ function overlayObserver(mode) {
+ return new Promise(function(resolve) {
+ function listener() {
+ element.removeEventListener('iron-overlay-' + mode, listener);
+ resolve();
+ }
+ element.addEventListener('iron-overlay-' + mode, listener);
+ });
+ }
+
+ test('reviewer confirmation', function(done) {
+ var yesButton =
+ element.$$('.reviewerConfirmationButtons gr-button:first-child');
+ var noButton =
+ element.$$('.reviewerConfirmationButtons gr-button:last-child');
+
+ element._reviewerPendingConfirmation = null;
+ flushAsynchronousOperations();
+ assert.isFalse(isVisible(element.$.reviewerConfirmationOverlay));
+
+ // Cause the confirmation dialog to display.
+ var observer = overlayObserver('opened');
+ var group = {
+ id: 'id',
+ name: 'name',
+ count: 10,
+ };
+ element._reviewerPendingConfirmation = {
+ group: group,
+ };
+
+ observer.then(function() {
+ assert.isTrue(isVisible(element.$.reviewerConfirmationOverlay));
+ observer = overlayObserver('closed');
+ MockInteractions.tap(noButton); // close the overlay
+ return observer;
+ }).then(function() {
+ assert.isFalse(isVisible(element.$.reviewerConfirmationOverlay));
+
+ // We should be focused on account entry input.
+ assert.equal(getActiveElement().id, 'input');
+
+ // No reviewer should have been added.
+ assert.deepEqual(element.$.reviewers.additions(), []);
+
+ // Reopen confirmation dialog.
+ observer = overlayObserver('opened');
+ element._reviewerPendingConfirmation = {
+ group: group,
+ };
+ return observer;
+ }).then(function() {
+ assert.isTrue(isVisible(element.$.reviewerConfirmationOverlay));
+ observer = overlayObserver('closed');
+ MockInteractions.tap(yesButton); // confirm the group
+ return observer;
+ }).then(function() {
+ assert.isFalse(isVisible(element.$.reviewerConfirmationOverlay));
+ assert.deepEqual(
+ element.$.reviewers.additions(),
+ [
+ {
+ group: {
+ id: 'id',
+ name: 'name',
+ count: 10,
+ confirmed: true,
+ _group: true,
+ _pendingAdd: true,
+ },
+ },
+ ]);
+
+ // We should be focused on account entry input.
+ assert.equal(getActiveElement().id, 'input');
+ }).then(done);
+ });
});
</script>