Hide quick-approve for your own change or if you have already given max vote

Change-Id: I7e074c9596a3364f253e55d83ec867b9ccdab000
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
index 020762c..dcfa0cd 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
@@ -46,6 +46,7 @@
 } from '../../../utils/patch-set-util';
 import {
   changeIsOpen,
+  isOwner,
   ListChangesOption,
   listChangesOptionsToHex,
 } from '../../../utils/change-util';
@@ -67,6 +68,7 @@
   ErrorCallback,
 } from '../../../services/services/gr-rest-api/gr-rest-api';
 import {
+  AccountInfo,
   ActionInfo,
   ActionNameToActionInfoMap,
   BranchName,
@@ -114,7 +116,11 @@
   UIActionInfo,
 } from '../../shared/gr-js-api-interface/gr-change-actions-js-api';
 import {fireAlert} from '../../../utils/event-util';
-import {CODE_REVIEW} from '../../../utils/label-util';
+import {
+  CODE_REVIEW,
+  getApprovalInfo,
+  getVotingRange,
+} from '../../../utils/label-util';
 
 const ERR_BRANCH_EMPTY = 'The destination branch can’t be empty.';
 const ERR_COMMIT_EMPTY = 'The commit message can’t be empty.';
@@ -403,6 +409,9 @@
   @property({type: Boolean})
   _hideQuickApproveAction = false;
 
+  @property({type: Object})
+  account?: AccountInfo;
+
   @property({type: String})
   changeNum?: NumericChangeId;
 
@@ -950,29 +959,38 @@
       }
     }
     // Allow the user to use quick approve to vote the max score on code review
-    // even if it is already granted.
+    // even if it is already granted by someone else. Does not apply if the
+    // user owns the change or has already granted the max score themselves.
+    const codeReviewLabel = this.change.labels[CODE_REVIEW];
+    const codeReviewPermittedValues = this.change.permitted_labels[CODE_REVIEW];
     if (
       !result &&
-      this.change.labels[CODE_REVIEW] &&
-      this._getLabelStatus(this.change.labels[CODE_REVIEW]) ===
-        LabelStatus.OK &&
-      this.change.permitted_labels[CODE_REVIEW]
+      codeReviewLabel &&
+      codeReviewPermittedValues &&
+      this.account?._account_id &&
+      isDetailedLabelInfo(codeReviewLabel) &&
+      this._getLabelStatus(codeReviewLabel) === LabelStatus.OK &&
+      !isOwner(this.change, this.account) &&
+      getApprovalInfo(codeReviewLabel, this.account)?.value !==
+        getVotingRange(codeReviewLabel)?.max
     ) {
       result = CODE_REVIEW;
     }
 
     if (result) {
-      const score = this.change.permitted_labels[result].slice(-1)[0];
       const labelInfo = this.change.labels[result];
       if (!isDetailedLabelInfo(labelInfo)) {
         return null;
       }
-      const maxScore = Object.keys(labelInfo.values).slice(-1)[0];
-      if (score === maxScore) {
+      const permittedValues = this.change.permitted_labels[result];
+      const usersMaxPermittedScore =
+        permittedValues[permittedValues.length - 1];
+      const maxScoreForLabel = getVotingRange(labelInfo)?.max;
+      if (Number(usersMaxPermittedScore) === maxScoreForLabel) {
         // Allow quick approve only for maximal score.
         return {
           label: result,
-          score,
+          score: usersMaxPermittedScore,
         };
       }
     }
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
index 3b6a2bf..5a06ceb 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
@@ -21,6 +21,8 @@
 import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
 import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
 import {
+  createAccountWithId,
+  createApproval,
   createChange,
   createChangeMessages,
   createRevisions,
@@ -105,6 +107,9 @@
           enabled: true,
         },
       };
+      element.account = {
+        _account_id: 123,
+      };
       sinon.stub(appContext.restApiService, 'getRepoBranches').returns(
           Promise.resolve([]));
 
@@ -1525,9 +1530,6 @@
       setup(() => {
         element.change = {
           current_revision: 'abc1234',
-        };
-        element.change = {
-          current_revision: 'abc1234',
           labels: {
             foo: {
               values: {
@@ -1734,10 +1736,66 @@
             };
             flush();
             const approveButton =
-              element.shadowRoot
-                  .querySelector('gr-button[data-action-key=\'review\']');
+                element.shadowRoot
+                    .querySelector('gr-button[data-action-key=\'review\']');
             assert.isNotNull(approveButton);
           });
+
+      test('not added when the user has already approved', () => {
+        const vote = {
+          ...createApproval(),
+          _account_id: 123,
+          name: 'name',
+          value: 2,
+        };
+        element.change = {
+          current_revision: 'abc1234',
+          labels: {
+            'Code-Review': {
+              approved: {},
+              values: {
+                ' 0': '',
+                '+1': '',
+                '+2': '',
+              },
+              all: [vote],
+            },
+          },
+          permitted_labels: {
+            'Code-Review': [' 0', '+1', '+2'],
+          },
+        };
+        flush();
+        const approveButton =
+            element.shadowRoot
+                .querySelector('gr-button[data-action-key=\'review\']');
+        assert.isNull(approveButton);
+      });
+
+      test('not added when user owns the change', () => {
+        element.change = {
+          current_revision: 'abc1234',
+          owner: createAccountWithId(123),
+          labels: {
+            'Code-Review': {
+              approved: {},
+              values: {
+                ' 0': '',
+                '+1': '',
+                '+2': '',
+              },
+            },
+          },
+          permitted_labels: {
+            'Code-Review': [' 0', '+1', '+2'],
+          },
+        };
+        flush();
+        const approveButton =
+            element.shadowRoot
+                .querySelector('gr-button[data-action-key=\'review\']');
+        assert.isNull(approveButton);
+      });
     });
 
     test('adds download revision action', () => {
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
index c4b701f..46f3a849 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
@@ -405,6 +405,7 @@
             has-parent="[[hasParent]]"
             actions="[[_change.actions]]"
             revision-actions="{{_currentRevisionActions}}"
+            account="[[_account]]"
             change-num="[[_changeNum]]"
             change-status="[[_change.status]]"
             commit-num="[[_commitInfo.commit]]"