Merge "Fix typo in owners docs"
diff --git a/owners/src/main/resources/Documentation/config.md b/owners/src/main/resources/Documentation/config.md
index 89c6248..5b85b7e 100644
--- a/owners/src/main/resources/Documentation/config.md
+++ b/owners/src/main/resources/Documentation/config.md
@@ -69,7 +69,7 @@
> Please also note, that project's `rules.pl` should be removed in this
> case so that it doesn't interfere with a change evaluation.
>
- > The minial configuration looks like below (see
+ > The minimal configuration looks like below (see
> [submit requirements documentation](/Documentation/config-submit-requirements.html) for more details):
> ```
> [submit-requirement "Owner-Approval"]
diff --git a/owners/web/gr-owned-files.ts b/owners/web/gr-owned-files.ts
index 969d91c..56274d4 100644
--- a/owners/web/gr-owned-files.ts
+++ b/owners/web/gr-owned-files.ts
@@ -23,6 +23,7 @@
AccountInfo,
ChangeInfo,
ChangeStatus,
+ EmailAddress,
RevisionInfo,
EDIT,
} from '@gerritcodereview/typescript-api/rest-api';
@@ -70,11 +71,36 @@
@customElement(OWNED_FILES_TAB_HEADER)
export class OwnedFilesTabHeader extends OwnedFilesCommon {
static override get styles() {
- return [...OwnedFilesCommon.commonStyles()];
+ return [
+ ...OwnedFilesCommon.commonStyles(),
+ css`
+ [hidden] {
+ display: none;
+ }
+ `,
+ ];
}
override render() {
- if (this.hidden) return nothing;
+ // even if `nothing` is returned Gerrit still shows the pointer and allows
+ // clicking at it, redirecting to the empty tab when done; traverse through
+ // the shadowRoots down to the tab and disable/enable it when needed
+ const tabParent = document
+ .querySelector('#pg-app')
+ ?.shadowRoot?.querySelector('#app-element')
+ ?.shadowRoot?.querySelector('main > gr-change-view')
+ ?.shadowRoot?.querySelector(
+ '#tabs > paper-tab[data-name="change-view-tab-header-owners"]'
+ );
+ if (this.hidden) {
+ if (tabParent && !tabParent.getAttribute('disabled')) {
+ tabParent.setAttribute('disabled', 'disabled');
+ }
+ return nothing;
+ }
+ if (tabParent && tabParent.getAttribute('disabled')) {
+ tabParent.removeAttribute('disabled');
+ }
return html`<div>Owned Files</div>`;
}
}
@@ -296,12 +322,22 @@
return;
}
+ const groupPrefix = 'group/';
+ const emailWithoutDomain = toEmailWithoutDomain(owner.email);
const ownedFiles = [];
for (const file of Object.keys(files)) {
if (
- files[file].find(
- fileOwner => isOwner(fileOwner) && fileOwner.id === owner._account_id
- )
+ files[file].find(fileOwner => {
+ if (isOwner(fileOwner)) {
+ return fileOwner.id === owner._account_id;
+ }
+
+ return (
+ !fileOwner.name?.startsWith(groupPrefix) &&
+ (fileOwner.name === emailWithoutDomain ||
+ fileOwner.name === owner.name)
+ );
+ })
) {
ownedFiles.push(file);
}
@@ -329,3 +365,8 @@
return `${getBaseUrl()}/c/${repo}${change._number}${range}${path}`;
}
+
+function toEmailWithoutDomain(email?: EmailAddress): string | undefined {
+ const startDomainIndex = email?.indexOf('@');
+ return startDomainIndex ? email?.substring(0, startDomainIndex) : undefined;
+}
diff --git a/owners/web/gr-owned-files_test.ts b/owners/web/gr-owned-files_test.ts
index 0437ab9..f9c7f3a 100644
--- a/owners/web/gr-owned-files_test.ts
+++ b/owners/web/gr-owned-files_test.ts
@@ -17,6 +17,7 @@
import {assert} from '@open-wc/testing';
import {
+ AccountId,
AccountInfo,
ChangeInfo,
ChangeStatus,
@@ -25,7 +26,7 @@
SubmitRequirementResultInfo,
} from '@gerritcodereview/typescript-api/rest-api';
import {ownedFiles, shouldHide} from './gr-owned-files';
-import {OwnedFiles, Owner} from './owners-service';
+import {GroupOwner, OwnedFiles, Owner} from './owners-service';
import {deepEqual} from './utils';
import {User, UserRole} from './owners-model';
import {getRandom} from './test-utils';
@@ -59,6 +60,27 @@
test('ownedFiles - should return owned files', () => {
assert.equal(deepEqual(ownedFiles(owner, files), [ownedFile]), true);
});
+
+ test('ownedFiles - should match file owner through email without domain name', () => {
+ const files = {
+ [ownedFile]: [fileOwnerWithNameOnly(`${ownerAccountId}_email`)],
+ 'some.text': [fileOwnerWithNameOnly('random_joe')],
+ } as unknown as OwnedFiles;
+ assert.equal(deepEqual(ownedFiles(owner, files), [ownedFile]), true);
+ });
+
+ test('ownedFiles - should match file owner through full name', () => {
+ const files = {
+ [ownedFile]: [fileOwnerWithNameOnly(`${ownerAccountId}_name`)],
+ 'some.text': [fileOwnerWithNameOnly('random_joe')],
+ } as unknown as OwnedFiles;
+ assert.equal(deepEqual(ownedFiles(owner, files), [ownedFile]), true);
+ });
+
+ test('ownedFiles - should NOT match file owner over email without domain or full name when account id is different', () => {
+ const notFileOwner = {...owner, _account_id: 2 as unknown as AccountId};
+ assert.equal(deepEqual(ownedFiles(notFileOwner, files), []), true);
+ });
});
suite('shouldHide tests', () => {
@@ -174,12 +196,18 @@
function account(id: number): AccountInfo {
return {
_account_id: id,
+ email: `${id}_email@example.com`,
+ name: `${id}_name`,
} as unknown as AccountInfo;
}
function fileOwner(id: number): Owner {
return {
id,
- name: `name for account: ${id}`,
+ name: `${id}_name`,
} as unknown as Owner;
}
+
+function fileOwnerWithNameOnly(name: string): GroupOwner {
+ return {name} as unknown as GroupOwner;
+}