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 2d5c0a74aa..d6b1505060 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 00e61d9a8a..64443ff1be 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 @@ limitations under the License. }); element = fixture('basic'); + element.change = {}; element.changeNum = '42'; element.patchNum = '2'; element.actions = { @@ -488,5 +489,79 @@ limitations under the License. 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(); + }); + }); });