Add 'Quick Approve' button to change actions
Adds Quick Approve button that sets maximal review score for all
permitted labels with one click.
Feature: Issue 4484
Change-Id: I8182e05d9dc34e01ed8a253a847375afadf766c8
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
index 2d5c0a7..d6b1505 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
@@ -49,6 +49,15 @@
var ADDITIONAL_ACTION_KEY_PREFIX = '__additionalAction_';
+ var QUICK_APPROVE_ACTION = {
+ __key: 'review',
+ __type: 'change',
+ key: 'review',
+ label: 'Quick Approve',
+ method: 'POST',
+ title: 'Set maximal score to all labels you can.',
+ };
+
Polymer({
is: 'gr-change-actions',
@@ -98,7 +107,7 @@
_changeActionValues: {
type: Array,
computed: '_computeChangeActionValues(actions.*, ' +
- 'primaryActionKeys.*, _additionalActions.*)',
+ 'primaryActionKeys.*, _additionalActions.*, change)',
},
_additionalActions: {
type: Array,
@@ -243,9 +252,14 @@
},
_computeChangeActionValues: function(actionsChangeRecord,
- primariesChangeRecord, additionalActionsChangeRecord) {
- return this._getActionValues(actionsChangeRecord, primariesChangeRecord,
- additionalActionsChangeRecord, ActionType.CHANGE);
+ primariesChangeRecord, additionalActionsChangeRecord, change) {
+ var actions = this._getActionValues(
+ actionsChangeRecord, primariesChangeRecord,
+ additionalActionsChangeRecord, ActionType.CHANGE, change);
+ if (actions.length && this._canQuickApprove(change)) {
+ actions.unshift(QUICK_APPROVE_ACTION);
+ }
+ return actions;
},
_getActionValues: function(actionsChangeRecord, primariesChangeRecord,
@@ -289,6 +303,17 @@
return result.concat(additionalActions);
},
+ _canQuickApprove: function(change) {
+ if (!change || !change.labels || !change.permitted_labels) {
+ return false;
+ }
+ var missingApprovals = Object.keys(change.labels).filter(function(label) {
+ return !change.labels[label].approved;
+ });
+ return missingApprovals.some(
+ function(label) { return label in change.permitted_labels; });
+ },
+
_computeLoadingLabel: function(action) {
return ActionLoadingLabels[action] || 'Working...';
},
@@ -344,6 +369,18 @@
this.showRevertDialog();
} else if (key === ChangeActions.ABANDON) {
this._showActionDialog(this.$.confirmAbandonDialog);
+ } else if (key === QUICK_APPROVE_ACTION.key) {
+ var review = {
+ drafts: 'PUBLISH_ALL_REVISIONS',
+ labels: {},
+ };
+ var permittedLabels = this.change.permitted_labels;
+ Object.keys(permittedLabels).forEach(function(label) {
+ // Set label to maximal score permitted for it.
+ review.labels[label] = permittedLabels[label].slice(-1)[0];
+ });
+ this._fireAction(
+ this._prependSlash(key), QUICK_APPROVE_ACTION, true, review);
} else {
this._fireAction(this._prependSlash(key), this.actions[key], false);
}
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
index 00e61d9..64443ff 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
@@ -84,6 +84,7 @@
});
element = fixture('basic');
+ element.change = {};
element.changeNum = '42';
element.patchNum = '2';
element.actions = {
@@ -488,5 +489,79 @@
assert.isFalse(fireActionStub.called);
});
});
+
+ suite('quick approve', function() {
+ setup(function() {
+ element.change = {
+ current_revision: 'abc1234',
+ };
+ element.change = {
+ current_revision: 'abc1234',
+ labels: {
+ 'foo': {},
+ },
+ permitted_labels: {
+ 'foo': ['-1', '0', '+1'],
+ },
+ };
+ flushAsynchronousOperations();
+ });
+
+ test('added when can approve', function() {
+ var approveButton = element.$$('gr-button[data-action-key=\'review\']');
+ assert.isNotNull(approveButton);
+ });
+
+ test('not added when no actions available', function() {
+ element.actions = [];
+ flushAsynchronousOperations();
+ var approveButton = element.$$('gr-button[data-action-key=\'review\']');
+ assert.isNull(approveButton);
+ });
+
+ test('not added when already approved', function() {
+ element.change = {
+ current_revision: 'abc1234',
+ labels: {
+ 'foo': {
+ approved: {},
+ },
+ },
+ permitted_labels: {
+ 'foo': [],
+ },
+ };
+ flushAsynchronousOperations();
+ var approveButton = element.$$('gr-button[data-action-key=\'review\']');
+ assert.isNull(approveButton);
+ });
+
+ test('not added when can not approve', function() {
+ element.change = {
+ current_revision: 'abc1234',
+ labels: {
+ 'foo': {},
+ },
+ permitted_labels: {
+ 'bar': [],
+ },
+ };
+ flushAsynchronousOperations();
+ var approveButton = element.$$('gr-button[data-action-key=\'review\']');
+ assert.isNull(approveButton);
+ });
+
+ test('approves when taped', function() {
+ var fireActionStub = sinon.stub(element, '_fireAction');
+ MockInteractions.tap(
+ element.$$('gr-button[data-action-key=\'review\']'));
+ flushAsynchronousOperations();
+ assert.isTrue(fireActionStub.called);
+ assert.isTrue(fireActionStub.calledWith('/review'));
+ var payload = fireActionStub.lastCall.args[3];
+ assert.deepEqual(payload.labels, {foo: '+1'});
+ fireActionStub.restore();
+ });
+ });
});
</script>