Reuse account details that are part of the change When file owners are returned from plugin they contain only the `_account_id` however there is a chance that some account details are already available in change (e.g. in reviewers set). Consult change details in order to avoid costly server round-trip. The following change's attributes are considered as account details sources: * owner * submitter * reviewers (both regular and CC) Bug: Issue 373151160 Change-Id: I0a43793b15b8f1cfd193bcbae2bf436b3f13a7f0
diff --git a/owners/web/gr-owners.ts b/owners/web/gr-owners.ts index e60e5d4..2c9eeb4 100644 --- a/owners/web/gr-owners.ts +++ b/owners/web/gr-owners.ts
@@ -26,6 +26,7 @@ LabelInfo, isDetailedLabelInfo, EmailAddress, + ReviewerState, } from '@gerritcodereview/typescript-api/rest-api'; import { FilesOwners, @@ -427,6 +428,7 @@ .owner=${owner} .approval=${approval} .info=${info} + .email=${owner.email} ></gr-owner> </div> `; @@ -469,10 +471,15 @@ } this.fileStatus = FILE_STATUS[fileOwnership.fileStatus]; + const accounts = getChangeAccounts(this.change); + // TODO for the time being filter out or group owners - to be decided what/how to display them this.owners = (fileOwnership.owners ?? []) .filter(isOwner) - .map(o => ({_account_id: o.id} as unknown as AccountInfo)); + .map( + o => + accounts.get(o.id) ?? ({_account_id: o.id} as unknown as AccountInfo) + ); } } @@ -566,3 +573,20 @@ return; } + +export function getChangeAccounts( + change?: ChangeInfo +): Map<number, AccountInfo> { + const accounts = new Map(); + if (!change) { + return accounts; + } + + [ + change.owner, + ...(change.submitter ? [change.submitter] : []), + ...(change.reviewers[ReviewerState.REVIEWER] ?? []), + ...(change.reviewers[ReviewerState.CC] ?? []), + ].forEach(account => accounts.set(account._account_id, account)); + return accounts; +}
diff --git a/owners/web/gr-owners_test.ts b/owners/web/gr-owners_test.ts index 4574c3e..43f199d 100644 --- a/owners/web/gr-owners_test.ts +++ b/owners/web/gr-owners_test.ts
@@ -19,6 +19,7 @@ import { computeApprovalAndInfo, + getChangeAccounts, getFileOwnership, shouldHide, } from './gr-owners'; @@ -30,6 +31,7 @@ ChangeStatus, DetailedLabelInfo, SubmitRequirementResultInfo, + ReviewerState, } from '@gerritcodereview/typescript-api/rest-api'; import {FilesOwners, OwnersLabels} from './owners-service'; import {deepEqual} from './utils'; @@ -352,9 +354,61 @@ ); }); }); + + suite('getChangeAccounts tests', () => { + test('getChangeAccounts - should return empty map when change is `undefined', () => { + const undefinedChange = undefined; + assert.equal(getChangeAccounts(undefinedChange).size, 0); + }); + + test('getChangeAccounts - should return map with owner when change has only owner and empty reviewers defined', () => { + const owner = account(1); + const changeWithOwner = { + owner, + reviewers: {}, + } as unknown as ChangeInfo; + assert.equal( + deepEqual(getChangeAccounts(changeWithOwner), new Map([[1, owner]])), + true + ); + }); + + test('getChangeAccounts - should return map with owner, submitter and reviewers', () => { + const owner = account(1); + const submitter = account(2); + const reviewer = account(3); + const ccReviewer = account(4); + const change = { + owner, + submitter, + reviewers: { + [ReviewerState.REVIEWER]: [reviewer], + [ReviewerState.CC]: [ccReviewer], + }, + } as unknown as ChangeInfo; + assert.equal( + deepEqual( + getChangeAccounts(change), + new Map([ + [1, owner], + [2, submitter], + [3, reviewer], + [4, ccReviewer], + ]) + ), + true + ); + }); + }); }); function getRandom<T>(...values: T[]): T { const idx = Math.floor(Math.random() * values.length); return values[idx]; } + +function account(id: number) { + return { + _account_id: id, + } as unknown as AccountInfo; +}