Merge "Only allow involved users to change the attention set"
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts
index a6c4201..a6e881f 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts
@@ -30,6 +30,7 @@
import {ChangeInfo, AccountInfo, ServerInfo} from '../../../types/common';
import {hasOwnProperty} from '../../../utils/common-util';
import {fireEvent} from '../../../utils/event-util';
+import {isInvolved} from '../../../utils/change-util';
@customElement('gr-account-label')
export class GrAccountLabel extends GestureEventListeners(
@@ -260,15 +261,39 @@
};
}
+ _computeAttentionButtonEnabled(
+ config: ServerInfo | undefined,
+ highlight: boolean,
+ account: AccountInfo,
+ change: ChangeInfo,
+ selfAccount: AccountInfo
+ ) {
+ return (
+ this._hasUnforcedAttention(config, highlight, account, change) &&
+ isInvolved(change, selfAccount)
+ );
+ }
+
_computeAttentionIconTitle(
config: ServerInfo | undefined,
highlight: boolean,
account: AccountInfo,
- change: ChangeInfo
+ change: ChangeInfo,
+ selfAccount: AccountInfo,
+ force: boolean
) {
- return this._hasUnforcedAttention(config, highlight, account, change)
+ const enabled = this._computeAttentionButtonEnabled(
+ config,
+ highlight,
+ account,
+ change,
+ selfAccount
+ );
+ return enabled
? 'Click to remove the user from the attention set'
- : 'Disabled. Use "Modify" to make changes.';
+ : force
+ ? 'Disabled. Use "Modify" to make changes.'
+ : 'Disabled. Only involved users can change.';
}
}
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.ts b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.ts
index b62df9e..39447ad 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.ts
@@ -109,9 +109,9 @@
link=""
aria-label="Remove user from attention set"
on-click="_handleRemoveAttentionClick"
- disabled="[[!_hasUnforcedAttention(_config, highlightAttention, account, change)]]"
- has-tooltip="[[_hasUnforcedAttention(_config, highlightAttention, account, change)]]"
- title="[[_computeAttentionIconTitle(_config, highlightAttention, account, change)]]"
+ disabled="[[!_computeAttentionButtonEnabled(_config, highlightAttention, account, change, _selfAccount)]]"
+ has-tooltip="[[_computeAttentionButtonEnabled(_config, highlightAttention, account, change, _selfAccount)]]"
+ title="[[_computeAttentionIconTitle(_config, highlightAttention, account, change, _selfAccount, forceAttention)]]"
><iron-icon class="attention" icon="gr-icons:attention"></iron-icon>
</gr-button>
</template>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.js b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.js
index 42b1dd7..6912776 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.js
@@ -82,16 +82,21 @@
});
suite('attention set', () => {
- setup(() => {
+ setup(async () => {
+ const kermit = createAccount('kermit', 31);
element.highlightAttention = true;
element._config = {
change: {enable_attention_set: true},
user: {anonymous_coward_name: 'Anonymous Coward'},
};
- element._selfAccount = createAccount('kermit', 31);
+ element._selfAccount = kermit;
element.account = createAccount('ernie', 42);
- element.change = {attention_set: {42: {}}};
- flush();
+ element.change = {
+ attention_set: {42: {}},
+ owner: kermit,
+ reviewers: {},
+ };
+ await flush();
});
test('show attention button', () => {
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.ts
index 761e670..f6c4c1c 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.ts
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.ts
@@ -43,8 +43,8 @@
isAttentionSetEnabled,
} from '../../../utils/attention-set-util';
import {ReviewerState} from '../../../constants/constants';
-import {isRemovableReviewer} from '../../../utils/change-util';
import {CURRENT} from '../../../utils/patch-set-util';
+import {isInvolved, isRemovableReviewer} from '../../../utils/change-util';
@customElement('gr-hovercard-account')
export class GrHovercardAccount extends GestureEventListeners(
@@ -219,15 +219,13 @@
}
_computeShowActionAddToAttentionSet() {
- return (
- this._selfAccount && this.isAttentionEnabled && !this.hasUserAttention
- );
+ const involved = isInvolved(this.change, this._selfAccount);
+ return involved && this.isAttentionEnabled && !this.hasUserAttention;
}
_computeShowActionRemoveFromAttentionSet() {
- return (
- this._selfAccount && this.isAttentionEnabled && this.hasUserAttention
- );
+ const involved = isInvolved(this.change, this._selfAccount);
+ return involved && this.isAttentionEnabled && this.hasUserAttention;
}
_handleClickAddToAttentionSet() {
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts
index 99d3d6c..42bd76c 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts
@@ -144,7 +144,7 @@
</template>
<template
is="dom-if"
- if="[[_computeShowActionAddToAttentionSet(_config, highlightAttention, account, change)]]"
+ if="[[_computeShowActionAddToAttentionSet(_config, highlightAttention, account, change, _selfAccount)]]"
>
<div class="action">
<gr-button
@@ -159,7 +159,7 @@
</template>
<template
is="dom-if"
- if="[[_computeShowActionRemoveFromAttentionSet(_config, highlightAttention, account, change)]]"
+ if="[[_computeShowActionRemoveFromAttentionSet(_config, highlightAttention, account, change, _selfAccount)]]"
>
<div class="action">
<gr-button
@@ -172,7 +172,10 @@
</gr-button>
</div>
</template>
- <template is="dom-if" if="[[_showReviewerOrCCActions(account, change)]]">
+ <template
+ is="dom-if"
+ if="[[_showReviewerOrCCActions(account, change, _selfAccount)]]"
+ >
<div class="action">
<gr-button
class="removeReviewerOrCC"
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js
index c8b4b42..8d1f499 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js
@@ -19,6 +19,7 @@
import './gr-hovercard-account.js';
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
import {ReviewerState} from '../../../constants/constants.js';
+import {appContext} from '../../../services/app-context.js';
const basicFixture = fixtureFromTemplate(html`
<gr-hovercard-account class="hovered"></gr-hovercard-account>
@@ -34,22 +35,22 @@
_account_id: '31415926535',
};
- setup(() => {
- element = basicFixture.instantiate();
- sinon.stub(element.restApiService, 'getAccount').returns(
- new Promise(resolve => { '2'; })
+ setup(async () => {
+ sinon.stub(appContext.restApiService, 'getAccount').returns(
+ Promise.resolve({...ACCOUNT})
);
-
- element._selfAccount = {...ACCOUNT};
+ sinon.stub(appContext.restApiService, 'getConfig').returns(
+ Promise.resolve({change: {enable_attention_set: true}})
+ );
+ element = basicFixture.instantiate();
element.account = {...ACCOUNT};
- element._config = {
- change: {enable_attention_set: true},
- };
element.change = {
attention_set: {},
+ reviewers: {},
+ owner: {...ACCOUNT},
};
element.show({});
- flush();
+ await flush();
});
teardown(() => {
@@ -242,7 +243,11 @@
sinon.stub(element.restApiService, 'removeFromAttentionSet')
.callsFake(() => apiPromise);
element.highlightAttention = true;
- element.change = {attention_set: {31415926535: {}}};
+ element.change = {
+ attention_set: {31415926535: {}},
+ reviewers: {},
+ owner: {...ACCOUNT},
+ };
element._target = document.createElement('div');
flush();
const showAlertListener = sinon.spy();
diff --git a/polygerrit-ui/app/utils/change-util.ts b/polygerrit-ui/app/utils/change-util.ts
index 47924e6..ff9fff8 100644
--- a/polygerrit-ui/app/utils/change-util.ts
+++ b/polygerrit-ui/app/utils/change-util.ts
@@ -177,6 +177,30 @@
return change.owner?._account_id === account._account_id;
}
+export function isReviewer(change?: ChangeInfo, account?: AccountInfo) {
+ if (!change || !account) return false;
+ const reviewers = change.reviewers.REVIEWER ?? [];
+ return reviewers.some(r => r._account_id === account._account_id);
+}
+
+export function isUploader(change?: ChangeInfo, account?: AccountInfo) {
+ if (!change || !account) return false;
+ const rev = getCurrentRevision(change);
+ return rev?.uploader._account_id === account._account_id;
+}
+
+export function isInvolved(change?: ChangeInfo, account?: AccountInfo) {
+ const owner = isOwner(change, account);
+ const uploader = isUploader(change, account);
+ const reviewer = isReviewer(change, account);
+ return owner || uploader || reviewer;
+}
+
+export function getCurrentRevision(change?: ChangeInfo) {
+ if (!change?.revisions || !change?.current_revision) return undefined;
+ return change.revisions[change.current_revision];
+}
+
export function changeStatusString(change: ChangeInfo) {
return changeStatuses(change).join(', ');
}