Add status chip to file dropdown in diff view
Move file status-chip into its own component and show the chip in the
file list dropdown in diff view.
Screenshot: https://imgur.com/a/bFaRkIR
Issue: Bug 2866
Change-Id: I40b50bd0af004a96d77853339f7c8b2b49a5a372
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts
index cd43a89..c062188 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts
@@ -26,6 +26,7 @@
import '../../shared/gr-select/gr-select';
import '../../shared/gr-tooltip-content/gr-tooltip-content';
import '../../shared/gr-copy-clipboard/gr-copy-clipboard';
+import '../../shared/gr-file-status-chip/gr-file-status-chip';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
@@ -89,16 +90,6 @@
const EXPAND_ALL_TIMING_LABEL = 'ExpandAllDiffs';
const EXPAND_ALL_AVG_TIMING_LABEL = 'ExpandAllPerDiff';
-const FileStatus = {
- A: 'Added',
- C: 'Copied',
- D: 'Deleted',
- M: 'Modified',
- R: 'Renamed',
- W: 'Rewritten',
- U: 'Unchanged',
-};
-
const FILE_ROW_CLASS = 'file-row';
export interface GrFileList {
@@ -112,7 +103,7 @@
interface ReviewedFileInfo extends FileInfo {
isReviewed?: boolean;
}
-interface NormalizedFileInfo extends ReviewedFileInfo {
+export interface NormalizedFileInfo extends ReviewedFileInfo {
__path: string;
}
@@ -1123,12 +1114,6 @@
);
}
- _computeFileStatus(
- status?: keyof typeof FileStatus
- ): keyof typeof FileStatus {
- return status || 'M';
- }
-
_computeDiffURL(
change?: ParsedChangeInfo,
patchRange?: PatchRange,
@@ -1203,12 +1188,6 @@
return classes.join(' ');
}
- _computeStatusClass(file?: NormalizedFileInfo) {
- if (!file) return '';
- const classStr = this._computeClass('status', file.__path);
- return `${classStr} ${this._computeFileStatus(file.status)}`;
- }
-
_computePathClass(
path: string | undefined,
expandedFilesRecord: ElementPropertyDeepChange<GrFileList, '_expandedFiles'>
@@ -1364,17 +1343,6 @@
}
/**
- * Get a descriptive label for use in the status indicator's tooltip and
- * ARIA label.
- */
- _computeFileStatusLabel(status?: keyof typeof FileStatus) {
- const statusCode = this._computeFileStatus(status);
- return hasOwnProperty(FileStatus, statusCode)
- ? FileStatus[statusCode]
- : 'Status Unknown';
- }
-
- /**
* Converts any boolean-like variable to the string 'true' or 'false'
*
* This method is useful when you bind aria-checked attribute to a boolean
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.ts b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.ts
index eb20675..ec985af 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.ts
@@ -80,27 +80,6 @@
text-align: left;
width: 1.5em;
}
- .status {
- display: inline-block;
- border-radius: var(--border-radius);
- margin-left: var(--spacing-s);
- padding: 0 var(--spacing-m);
- color: var(--primary-text-color);
- font-size: var(--font-size-small);
- background-color: var(--dark-add-highlight-color);
- }
- .status.invisible,
- .status.M {
- display: none;
- }
- .status.D,
- .status.R,
- .status.W {
- background-color: var(--dark-remove-highlight-color);
- }
- .status.U {
- background-color: var(--comment-background-color);
- }
.file-row {
cursor: pointer;
}
@@ -421,14 +400,7 @@
>
[[_computeTruncatedPath(file.__path)]]
</span>
- <span
- class$="[[_computeStatusClass(file)]]"
- tabindex="0"
- title$="[[_computeFileStatusLabel(file.status)]]"
- aria-label$="[[_computeFileStatusLabel(file.status)]]"
- >
- [[_computeFileStatusLabel(file.status)]]
- </span>
+ <gr-file-status-chip file="[[file]]"></gr-file-status-chip>
<gr-copy-clipboard
hide-input=""
text="[[file.__path]]"
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js
index 3846f73..d0ae833 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js
@@ -699,16 +699,6 @@
});
});
- test('computed properties', () => {
- assert.equal(element._computeFileStatus('A'), 'A');
- assert.equal(element._computeFileStatus(undefined), 'M');
- assert.equal(element._computeFileStatus(null), 'M');
-
- assert.equal(element._computeClass('clazz', '/foo/bar/baz'), 'clazz');
- assert.equal(element._computeClass('clazz', '/COMMIT_MSG'),
- 'clazz invisible');
- });
-
test('file review status', () => {
element._reviewed = ['/COMMIT_MSG', 'myfile.txt'];
element._filesByPath = {
@@ -761,11 +751,6 @@
assert.isFalse(toggleExpandSpy.called);
});
- test('_computeFileStatusLabel', () => {
- assert.equal(element._computeFileStatusLabel('A'), 'Added');
- assert.equal(element._computeFileStatusLabel('M'), 'Modified');
- });
-
test('_handleFileListClick', () => {
element._filesByPath = {
'/COMMIT_MSG': {},
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
index 55e3b6b..828c53d 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
@@ -1314,6 +1314,7 @@
files.changeFilesByPath[path],
/* includeUnmodified= */ true
),
+ file: {...files.changeFilesByPath[path], __path: path},
});
}
return dropdownContent;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
index aa03956..72e1a8f 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
@@ -942,28 +942,43 @@
mobileText: 'chell.go',
value: 'chell.go',
bottomText: '',
+ file: {
+ __path: 'chell.go',
+ },
}, {
text: 'glados.txt',
mobileText: 'glados.txt',
value: 'glados.txt',
bottomText: '',
+ file: {
+ __path: 'glados.txt',
+ },
}, {
text: 'wheatley.md',
mobileText: 'wheatley.md',
value: 'wheatley.md',
bottomText: '',
+ file: {
+ __path: 'wheatley.md',
+ },
},
{
text: 'Commit message',
mobileText: 'Commit message',
value: '/COMMIT_MSG',
bottomText: '',
+ file: {
+ __path: '/COMMIT_MSG',
+ },
},
{
text: 'Merge list',
mobileText: 'Merge list',
value: '/MERGE_LIST',
bottomText: '',
+ file: {
+ __path: '/MERGE_LIST',
+ },
},
];
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
index 2ea72ca..37b5348 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
@@ -21,6 +21,7 @@
import '../gr-button/gr-button';
import '../gr-date-formatter/gr-date-formatter';
import '../gr-select/gr-select';
+import '../gr-file-status-chip/gr-file-status-chip';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
@@ -28,6 +29,7 @@
import {customElement, property, observe} from '@polymer/decorators';
import {IronDropdownElement} from '@polymer/iron-dropdown/iron-dropdown';
import {Timestamp} from '../../../types/common';
+import {NormalizedFileInfo} from '../../change/gr-file-list/gr-file-list';
/**
* fired when the selected value of the dropdown changes
@@ -52,6 +54,7 @@
mobileText?: string;
date?: Timestamp;
disabled?: boolean;
+ file?: NormalizedFileInfo;
}
export interface GrDropdownList {
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts
index 26a6b3f..f313174 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts
@@ -158,6 +158,9 @@
<template is="dom-if" if="[[item.date]]">
<gr-date-formatter date-str="[[item.date]]"></gr-date-formatter>
</template>
+ <template is="dom-if" if="[[item.file]]">
+ <gr-file-status-chip file="[[item.file]]"></gr-file-status-chip>
+ </template>
</div>
<template is="dom-if" if="[[item.bottomText]]">
<div class="bottomContent">
diff --git a/polygerrit-ui/app/elements/shared/gr-file-status-chip/gr-file-status-chip.ts b/polygerrit-ui/app/elements/shared/gr-file-status-chip/gr-file-status-chip.ts
new file mode 100644
index 0000000..9298fa3
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-file-status-chip/gr-file-status-chip.ts
@@ -0,0 +1,90 @@
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import '../../../styles/shared-styles';
+import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
+import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
+import {htmlTemplate} from './gr-file-status-chip_html';
+import {customElement, property} from '@polymer/decorators';
+import {PolymerElement} from '@polymer/polymer/polymer-element';
+import {SpecialFilePath} from '../../../constants/constants';
+import {NormalizedFileInfo} from '../../change/gr-file-list/gr-file-list';
+import {hasOwnProperty} from '../../../utils/common-util';
+
+const FileStatus = {
+ A: 'Added',
+ C: 'Copied',
+ D: 'Deleted',
+ M: 'Modified',
+ R: 'Renamed',
+ W: 'Rewritten',
+ U: 'Unchanged',
+};
+
+@customElement('gr-file-status-chip')
+export class GrFileStatusChip extends GestureEventListeners(
+ LegacyElementMixin(PolymerElement)
+) {
+ static get template() {
+ return htmlTemplate;
+ }
+
+ @property({type: Object})
+ file?: NormalizedFileInfo;
+
+ /**
+ * Get a descriptive label for use in the status indicator's tooltip and
+ * ARIA label.
+ */
+ _computeFileStatusLabel(status?: keyof typeof FileStatus) {
+ const statusCode = this._computeFileStatus(status);
+ return hasOwnProperty(FileStatus, statusCode)
+ ? FileStatus[statusCode]
+ : 'Status Unknown';
+ }
+
+ _computeClass(baseClass?: string, path?: string) {
+ const classes = [];
+ if (baseClass) {
+ classes.push(baseClass);
+ }
+ if (
+ path === SpecialFilePath.COMMIT_MESSAGE ||
+ path === SpecialFilePath.MERGE_LIST
+ ) {
+ classes.push('invisible');
+ }
+ return classes.join(' ');
+ }
+
+ _computeFileStatus(
+ status?: keyof typeof FileStatus
+ ): keyof typeof FileStatus {
+ return status || 'M';
+ }
+
+ _computeStatusClass(file?: NormalizedFileInfo) {
+ if (!file) return '';
+ const classStr = this._computeClass('status', file.__path);
+ return `${classStr} ${this._computeFileStatus(file.status)}`;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'gr-file-status-chip': GrFileStatusChip;
+ }
+}
diff --git a/polygerrit-ui/app/elements/shared/gr-file-status-chip/gr-file-status-chip_html.ts b/polygerrit-ui/app/elements/shared/gr-file-status-chip/gr-file-status-chip_html.ts
new file mode 100644
index 0000000..9e49868
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-file-status-chip/gr-file-status-chip_html.ts
@@ -0,0 +1,51 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {html} from '@polymer/polymer/lib/utils/html-tag';
+
+export const htmlTemplate = html`
+ <style include="shared-styles">
+ .status {
+ display: inline-block;
+ border-radius: var(--border-radius);
+ margin-left: var(--spacing-s);
+ padding: 0 var(--spacing-m);
+ color: var(--primary-text-color);
+ font-size: var(--font-size-small);
+ background-color: var(--dark-add-highlight-color);
+ }
+ .status.invisible,
+ .status.M {
+ display: none;
+ }
+ .status.D,
+ .status.R,
+ .status.W {
+ background-color: var(--dark-remove-highlight-color);
+ }
+ .status.U {
+ background-color: var(--comment-background-color);
+ }
+ </style>
+ <span
+ class$="[[_computeStatusClass(file)]]"
+ tabindex="0"
+ title$="[[_computeFileStatusLabel(file.status)]]"
+ aria-label$="[[_computeFileStatusLabel(file.status)]]"
+ >
+ [[_computeFileStatusLabel(file.status)]]
+ </span>
+`;
diff --git a/polygerrit-ui/app/elements/shared/gr-file-status-chip/gr-file-status-chip_test.ts b/polygerrit-ui/app/elements/shared/gr-file-status-chip/gr-file-status-chip_test.ts
new file mode 100644
index 0000000..0abc85f
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-file-status-chip/gr-file-status-chip_test.ts
@@ -0,0 +1,46 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../../test/common-test-setup-karma';
+import './gr-file-status-chip';
+import {GrFileStatusChip} from './gr-file-status-chip';
+
+const fixture = fixtureFromElement('gr-file-status-chip');
+
+suite('gr-file-status-chip tests', () => {
+ let element: GrFileStatusChip;
+
+ setup(() => {
+ element = fixture.instantiate();
+ });
+
+ test('computed properties', () => {
+ assert.equal(element._computeFileStatus('A'), 'A');
+ assert.equal(element._computeFileStatus(undefined), 'M');
+
+ assert.equal(element._computeClass('clazz', '/foo/bar/baz'), 'clazz');
+ assert.equal(
+ element._computeClass('clazz', '/COMMIT_MSG'),
+ 'clazz invisible'
+ );
+ });
+
+ test('_computeFileStatusLabel', () => {
+ assert.equal(element._computeFileStatusLabel('A'), 'Added');
+ assert.equal(element._computeFileStatusLabel('M'), 'Modified');
+ });
+});