Merge changes from topic "gr-change-list-to-ts"
* changes:
Convert gr-change-list to typescript
Rename files to preserve history
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
deleted file mode 100644
index 2230c38..0000000
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
+++ /dev/null
@@ -1,441 +0,0 @@
-/**
- * @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/gr-change-list-styles.js';
-import '../../shared/gr-cursor-manager/gr-cursor-manager.js';
-import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
-import '../gr-change-list-item/gr-change-list-item.js';
-import '../../../styles/shared-styles.js';
-import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.js';
-import {afterNextRender} from '@polymer/polymer/lib/utils/render-status.js';
-import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
-import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
-import {PolymerElement} from '@polymer/polymer/polymer-element.js';
-import {htmlTemplate} from './gr-change-list_html.js';
-import {appContext} from '../../../services/app-context.js';
-import {ChangeTableMixin} from '../../../mixins/gr-change-table-mixin/gr-change-table-mixin.js';
-import {KeyboardShortcutMixin, Shortcut} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.js';
-import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
-import {getPluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';
-import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
-import {changeIsOpen} from '../../../utils/change-util.js';
-
-const NUMBER_FIXED_COLUMNS = 3;
-const CLOSED_STATUS = ['MERGED', 'ABANDONED'];
-const LABEL_PREFIX_INVALID_PROLOG = 'Invalid-Prolog-Rules-Label-Name--';
-const MAX_SHORTCUT_CHARS = 5;
-
-/**
- * @extends PolymerElement
- */
-class GrChangeList extends ChangeTableMixin(
- KeyboardShortcutMixin(GestureEventListeners(
- LegacyElementMixin(PolymerElement)))) {
- static get template() { return htmlTemplate; }
-
- static get is() { return 'gr-change-list'; }
- /**
- * Fired when next page key shortcut was pressed.
- *
- * @event next-page
- */
-
- /**
- * Fired when previous page key shortcut was pressed.
- *
- * @event previous-page
- */
-
- static get properties() {
- return {
- /**
- * The logged-in user's account, or an empty object if no user is logged
- * in.
- */
- account: {
- type: Object,
- value: null,
- },
- /**
- * An array of ChangeInfo objects to render.
- * https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#change-info
- */
- changes: {
- type: Array,
- observer: '_changesChanged',
- },
- /**
- * ChangeInfo objects grouped into arrays. The sections and changes
- * properties should not be used together.
- *
- * @type {!Array<{
- * name: string,
- * query: string,
- * results: !Array<!Object>
- * }>}
- */
- sections: {
- type: Array,
- value() { return []; },
- },
- labelNames: {
- type: Array,
- computed: '_computeLabelNames(sections)',
- },
- _dynamicHeaderEndpoints: {
- type: Array,
- },
- selectedIndex: {
- type: Number,
- notify: true,
- },
- showNumber: Boolean, // No default value to prevent flickering.
- showStar: {
- type: Boolean,
- value: false,
- },
- showReviewedState: {
- type: Boolean,
- value: false,
- },
- keyEventTarget: {
- type: Object,
- value() { return document.body; },
- },
- changeTableColumns: Array,
- visibleChangeTableColumns: Array,
- preferences: Object,
- _config: Object,
- };
- }
-
- static get observers() {
- return [
- '_sectionsChanged(sections.*)',
- '_computePreferences(account, preferences, _config)',
- ];
- }
-
- keyboardShortcuts() {
- return {
- [Shortcut.CURSOR_NEXT_CHANGE]: '_nextChange',
- [Shortcut.CURSOR_PREV_CHANGE]: '_prevChange',
- [Shortcut.NEXT_PAGE]: '_nextPage',
- [Shortcut.PREV_PAGE]: '_prevPage',
- [Shortcut.OPEN_CHANGE]: '_openChange',
- [Shortcut.TOGGLE_CHANGE_REVIEWED]: '_toggleChangeReviewed',
- [Shortcut.TOGGLE_CHANGE_STAR]: '_toggleChangeStar',
- [Shortcut.REFRESH_CHANGE_LIST]: '_refreshChangeList',
- };
- }
-
- constructor() {
- super();
- this.flagsService = appContext.flagsService;
- }
-
- /** @override */
- created() {
- super.created();
- this.addEventListener('keydown',
- e => this._scopedKeydownHandler(e));
- }
-
- /** @override */
- ready() {
- super.ready();
- this.$.restAPI.getConfig().then(config => {
- this._config = config;
- });
- }
-
- /** @override */
- attached() {
- super.attached();
- getPluginLoader().awaitPluginsLoaded()
- .then(() => {
- this._dynamicHeaderEndpoints = getPluginEndpoints().
- getDynamicEndpoints('change-list-header');
- });
- }
-
- /**
- * Iron-a11y-keys-behavior catches keyboard events globally. Some keyboard
- * events must be scoped to a component level (e.g. `enter`) in order to not
- * override native browser functionality.
- *
- * Context: Issue 7294
- */
- _scopedKeydownHandler(e) {
- if (e.keyCode === 13) {
- // Enter.
- this._openChange(e);
- }
- }
-
- _lowerCase(column) {
- return column.toLowerCase();
- }
-
- _computePreferences(account, preferences, config) {
- // Polymer 2: check for undefined
- if ([account, preferences, config].includes(undefined)) {
- return;
- }
-
- this.changeTableColumns = this.columnNames;
- this.showNumber = false;
- this.visibleChangeTableColumns = this.getEnabledColumns(this.columnNames,
- config, this.flagsService.enabledExperiments);
-
- if (account) {
- this.showNumber = !!(preferences &&
- preferences.legacycid_in_change_table);
- if (preferences.change_table &&
- preferences.change_table.length > 0) {
- const prefColumns = this.getVisibleColumns(preferences.change_table);
- this.visibleChangeTableColumns = this.getEnabledColumns(prefColumns,
- config, this.flagsService.enabledExperiments);
- }
- }
- }
-
- _computeColspan(changeTableColumns, labelNames) {
- if (!changeTableColumns || !labelNames) return;
- return changeTableColumns.length + labelNames.length +
- NUMBER_FIXED_COLUMNS;
- }
-
- _computeLabelNames(sections) {
- if (!sections) { return []; }
- let labels = [];
- const nonExistingLabel = function(item) {
- return !labels.includes(item);
- };
- for (const section of sections) {
- if (!section.results) { continue; }
- for (const change of section.results) {
- if (!change.labels) { continue; }
- const currentLabels = Object.keys(change.labels);
- labels = labels.concat(currentLabels.filter(nonExistingLabel));
- }
- }
- return labels.sort();
- }
-
- _computeLabelShortcut(labelName) {
- if (labelName.startsWith(LABEL_PREFIX_INVALID_PROLOG)) {
- labelName = labelName.slice(LABEL_PREFIX_INVALID_PROLOG.length);
- }
- return labelName.split('-')
- .reduce((a, i) => {
- if (!i) { return a; }
- return a + i[0].toUpperCase();
- }, '')
- .slice(0, MAX_SHORTCUT_CHARS);
- }
-
- _changesChanged(changes) {
- this.sections = changes ? [{results: changes}] : [];
- }
-
- _processQuery(query) {
- let tokens = query.split(' ');
- const invalidTokens = ['limit:', 'age:', '-age:'];
- tokens = tokens.filter(token => !invalidTokens
- .some(invalidToken => token.startsWith(invalidToken)));
- return tokens.join(' ');
- }
-
- _sectionHref(query) {
- return GerritNav.getUrlForSearchQuery(this._processQuery(query));
- }
-
- /**
- * Maps an index local to a particular section to the absolute index
- * across all the changes on the page.
- *
- * @param {number} sectionIndex index of section
- * @param {number} localIndex index of row within section
- * @return {number} absolute index of row in the aggregate dashboard
- */
- _computeItemAbsoluteIndex(sectionIndex, localIndex) {
- let idx = 0;
- for (let i = 0; i < sectionIndex; i++) {
- idx += this.sections[i].results.length;
- }
- return idx + localIndex;
- }
-
- _computeItemSelected(sectionIndex, index, selectedIndex) {
- const idx = this._computeItemAbsoluteIndex(sectionIndex, index);
- return idx == selectedIndex;
- }
-
- _computeTabIndex(sectionIndex, index, selectedIndex) {
- return this._computeItemSelected(sectionIndex, index, selectedIndex)
- ? 0 : undefined;
- }
-
- _computeItemNeedsReview(account, change, showReviewedState, config) {
- const isAttentionSetEnabled =
- !!config && !!config.change && config.change.enable_attention_set;
- return !isAttentionSetEnabled && showReviewedState && !change.reviewed &&
- !change.work_in_progress &&
- changeIsOpen(change) &&
- (!account || account._account_id != change.owner._account_id);
- }
-
- _computeItemHighlight(account, change) {
- // Do not show the assignee highlight if the change is not open.
- if (!change ||!change.assignee ||
- !account ||
- CLOSED_STATUS.indexOf(change.status) !== -1) {
- return false;
- }
- return account._account_id === change.assignee._account_id;
- }
-
- _nextChange(e) {
- if (this.shouldSuppressKeyboardShortcut(e) ||
- this.modifierPressed(e)) { return; }
-
- e.preventDefault();
- this.$.cursor.next();
- }
-
- _prevChange(e) {
- if (this.shouldSuppressKeyboardShortcut(e) ||
- this.modifierPressed(e)) { return; }
-
- e.preventDefault();
- this.$.cursor.previous();
- }
-
- _openChange(e) {
- if (this.shouldSuppressKeyboardShortcut(e) ||
- this.modifierPressed(e)) { return; }
-
- e.preventDefault();
- GerritNav.navigateToChange(this._changeForIndex(this.selectedIndex));
- }
-
- _nextPage(e) {
- if (this.shouldSuppressKeyboardShortcut(e) ||
- this.modifierPressed(e) && !this.isModifierPressed(e, 'shiftKey')) {
- return;
- }
-
- e.preventDefault();
- this.dispatchEvent(new CustomEvent('next-page', {
- composed: true, bubbles: true,
- }));
- }
-
- _prevPage(e) {
- if (this.shouldSuppressKeyboardShortcut(e) ||
- this.modifierPressed(e) && !this.isModifierPressed(e, 'shiftKey')) {
- return;
- }
-
- e.preventDefault();
- this.dispatchEvent(new CustomEvent('previous-page', {
- composed: true, bubbles: true,
- }));
- }
-
- _toggleChangeReviewed(e) {
- if (this.shouldSuppressKeyboardShortcut(e) ||
- this.modifierPressed(e)) { return; }
-
- e.preventDefault();
- this._toggleReviewedForIndex(this.selectedIndex);
- }
-
- _toggleReviewedForIndex(index) {
- const changeEls = this._getListItems();
- if (index >= changeEls.length || !changeEls[index]) {
- return;
- }
-
- const changeEl = changeEls[index];
- changeEl.toggleReviewed();
- }
-
- _refreshChangeList(e) {
- if (this.shouldSuppressKeyboardShortcut(e)) { return; }
-
- e.preventDefault();
- this._reloadWindow();
- }
-
- _reloadWindow() {
- window.location.reload();
- }
-
- _toggleChangeStar(e) {
- if (this.shouldSuppressKeyboardShortcut(e) ||
- this.modifierPressed(e)) { return; }
-
- e.preventDefault();
- this._toggleStarForIndex(this.selectedIndex);
- }
-
- _toggleStarForIndex(index) {
- const changeEls = this._getListItems();
- if (index >= changeEls.length || !changeEls[index]) {
- return;
- }
-
- const changeEl = changeEls[index];
- changeEl.shadowRoot
- .querySelector('gr-change-star').toggleStar();
- }
-
- _changeForIndex(index) {
- const changeEls = this._getListItems();
- if (index < changeEls.length && changeEls[index]) {
- return changeEls[index].change;
- }
- return null;
- }
-
- _getListItems() {
- return Array.from(
- this.root.querySelectorAll('gr-change-list-item'));
- }
-
- _sectionsChanged() {
- // Flush DOM operations so that the list item elements will be loaded.
- afterNextRender(this, () => {
- this.$.cursor.stops = this._getListItems();
- this.$.cursor.moveToStart();
- });
- }
-
- _getSpecialEmptySlot(section) {
- if (section.isOutgoing) return 'empty-outgoing';
- if (section.name === 'Your Turn') return 'empty-your-turn';
- return '';
- }
-
- _isEmpty(section) {
- return !section.results.length;
- }
-}
-
-customElements.define(GrChangeList.is, GrChangeList);
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
new file mode 100644
index 0000000..a05ccf4
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
@@ -0,0 +1,508 @@
+/**
+ * @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/gr-change-list-styles';
+import '../../shared/gr-cursor-manager/gr-cursor-manager';
+import '../../shared/gr-rest-api-interface/gr-rest-api-interface';
+import '../gr-change-list-item/gr-change-list-item';
+import '../../../styles/shared-styles';
+import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
+import {afterNextRender} from '@polymer/polymer/lib/utils/render-status';
+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';
+import {htmlTemplate} from './gr-change-list_html';
+import {appContext} from '../../../services/app-context';
+import {ChangeTableMixin} from '../../../mixins/gr-change-table-mixin/gr-change-table-mixin';
+import {
+ KeyboardShortcutMixin,
+ Shortcut,
+ CustomKeyboardEvent,
+ Modifier,
+} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
+import {
+ GerritNav,
+ DashboardSection,
+} from '../../core/gr-navigation/gr-navigation';
+import {getPluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
+import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
+import {changeIsOpen} from '../../../utils/change-util';
+import {customElement, property, observe} from '@polymer/decorators';
+import {RestApiService} from '../../../services/services/gr-rest-api/gr-rest-api';
+import {GrCursorManager} from '../../shared/gr-cursor-manager/gr-cursor-manager';
+import {
+ AccountInfo,
+ ChangeInfo,
+ ServerInfo,
+ PreferencesInput,
+} from '../../../types/common';
+
+const NUMBER_FIXED_COLUMNS = 3;
+const CLOSED_STATUS = ['MERGED', 'ABANDONED'];
+const LABEL_PREFIX_INVALID_PROLOG = 'Invalid-Prolog-Rules-Label-Name--';
+const MAX_SHORTCUT_CHARS = 5;
+
+export interface ChangeListSection {
+ results: ChangeInfo[];
+}
+export interface GrChangeList {
+ $: {
+ restAPI: RestApiService & Element;
+ cursor: GrCursorManager;
+ };
+}
+@customElement('gr-change-list')
+export class GrChangeList extends ChangeTableMixin(
+ KeyboardShortcutMixin(
+ GestureEventListeners(LegacyElementMixin(PolymerElement))
+ )
+) {
+ static get template() {
+ return htmlTemplate;
+ }
+
+ /**
+ * Fired when next page key shortcut was pressed.
+ *
+ * @event next-page
+ */
+
+ /**
+ * Fired when previous page key shortcut was pressed.
+ *
+ * @event previous-page
+ */
+
+ /**
+ * The logged-in user's account, or an empty object if no user is logged
+ * in.
+ */
+ @property({type: Object})
+ account: AccountInfo | undefined = undefined;
+
+ @property({type: Array, observer: '_changesChanged'})
+ changes?: ChangeInfo[];
+
+ /**
+ * ChangeInfo objects grouped into arrays. The sections and changes
+ * properties should not be used together.
+ */
+ @property({type: Array})
+ sections: ChangeListSection[] = [];
+
+ @property({type: Array, computed: '_computeLabelNames(sections)'})
+ labelNames?: string[];
+
+ @property({type: Array})
+ _dynamicHeaderEndpoints?: string[];
+
+ @property({type: Number, notify: true})
+ selectedIndex?: number;
+
+ @property({type: Boolean})
+ showNumber?: boolean; // No default value to prevent flickering.
+
+ @property({type: Boolean})
+ showStar = false;
+
+ @property({type: Boolean})
+ showReviewedState = false;
+
+ @property({type: Object})
+ keyEventTarget: HTMLElement = document.body;
+
+ @property({type: Array})
+ changeTableColumns?: string[];
+
+ @property({type: Array})
+ visibleChangeTableColumns?: string[];
+
+ @property({type: Object})
+ preferences?: PreferencesInput;
+
+ @property({type: Object})
+ _config?: ServerInfo;
+
+ flagsService = appContext.flagsService;
+
+ keyboardShortcuts() {
+ return {
+ [Shortcut.CURSOR_NEXT_CHANGE]: '_nextChange',
+ [Shortcut.CURSOR_PREV_CHANGE]: '_prevChange',
+ [Shortcut.NEXT_PAGE]: '_nextPage',
+ [Shortcut.PREV_PAGE]: '_prevPage',
+ [Shortcut.OPEN_CHANGE]: '_openChange',
+ [Shortcut.TOGGLE_CHANGE_REVIEWED]: '_toggleChangeReviewed',
+ [Shortcut.TOGGLE_CHANGE_STAR]: '_toggleChangeStar',
+ [Shortcut.REFRESH_CHANGE_LIST]: '_refreshChangeList',
+ };
+ }
+
+ /** @override */
+ created() {
+ super.created();
+ this.addEventListener('keydown', e => this._scopedKeydownHandler(e));
+ }
+
+ /** @override */
+ ready() {
+ super.ready();
+ this.$.restAPI.getConfig().then(config => {
+ this._config = config;
+ });
+ }
+
+ /** @override */
+ attached() {
+ super.attached();
+ getPluginLoader()
+ .awaitPluginsLoaded()
+ .then(() => {
+ this._dynamicHeaderEndpoints = getPluginEndpoints().getDynamicEndpoints(
+ 'change-list-header'
+ );
+ });
+ }
+
+ /**
+ * Iron-a11y-keys-behavior catches keyboard events globally. Some keyboard
+ * events must be scoped to a component level (e.g. `enter`) in order to not
+ * override native browser functionality.
+ *
+ * Context: Issue 7294
+ */
+ _scopedKeydownHandler(e: KeyboardEvent) {
+ if (e.keyCode === 13) {
+ // Enter.
+ this._openChange((e as unknown) as CustomKeyboardEvent);
+ }
+ }
+
+ _lowerCase(column: string) {
+ return column.toLowerCase();
+ }
+
+ @observe('account', 'preferences', '_config')
+ _computePreferences(
+ account?: AccountInfo,
+ preferences?: PreferencesInput,
+ config?: ServerInfo
+ ) {
+ if (!config) {
+ return;
+ }
+
+ this.changeTableColumns = this.columnNames;
+ this.showNumber = false;
+ this.visibleChangeTableColumns = this.getEnabledColumns(
+ this.columnNames,
+ config,
+ this.flagsService.enabledExperiments
+ );
+
+ if (account && preferences) {
+ this.showNumber = !!(
+ preferences && preferences.legacycid_in_change_table
+ );
+ if (preferences.change_table && preferences.change_table.length > 0) {
+ const prefColumns = this.getVisibleColumns(preferences.change_table);
+ this.visibleChangeTableColumns = this.getEnabledColumns(
+ prefColumns,
+ config,
+ this.flagsService.enabledExperiments
+ );
+ }
+ }
+ }
+
+ _computeColspan(changeTableColumns: string[], labelNames: string[]) {
+ if (!changeTableColumns || !labelNames) return;
+ return changeTableColumns.length + labelNames.length + NUMBER_FIXED_COLUMNS;
+ }
+
+ _computeLabelNames(sections: ChangeListSection[]) {
+ if (!sections) {
+ return [];
+ }
+ let labels: string[] = [];
+ const nonExistingLabel = function (item: string) {
+ return !labels.includes(item);
+ };
+ for (const section of sections) {
+ if (!section.results) {
+ continue;
+ }
+ for (const change of section.results) {
+ if (!change.labels) {
+ continue;
+ }
+ const currentLabels = Object.keys(change.labels);
+ labels = labels.concat(currentLabels.filter(nonExistingLabel));
+ }
+ }
+ return labels.sort();
+ }
+
+ _computeLabelShortcut(labelName: string) {
+ if (labelName.startsWith(LABEL_PREFIX_INVALID_PROLOG)) {
+ labelName = labelName.slice(LABEL_PREFIX_INVALID_PROLOG.length);
+ }
+ return labelName
+ .split('-')
+ .reduce((a, i) => {
+ if (!i) {
+ return a;
+ }
+ return a + i[0].toUpperCase();
+ }, '')
+ .slice(0, MAX_SHORTCUT_CHARS);
+ }
+
+ _changesChanged(changes: ChangeInfo[]) {
+ this.sections = changes ? [{results: changes}] : [];
+ }
+
+ _processQuery(query: string) {
+ let tokens = query.split(' ');
+ const invalidTokens = ['limit:', 'age:', '-age:'];
+ tokens = tokens.filter(
+ token =>
+ !invalidTokens.some(invalidToken => token.startsWith(invalidToken))
+ );
+ return tokens.join(' ');
+ }
+
+ _sectionHref(query: string) {
+ return GerritNav.getUrlForSearchQuery(this._processQuery(query));
+ }
+
+ /**
+ * Maps an index local to a particular section to the absolute index
+ * across all the changes on the page.
+ *
+ * @param sectionIndex index of section
+ * @param localIndex index of row within section
+ * @return absolute index of row in the aggregate dashboard
+ */
+ _computeItemAbsoluteIndex(sectionIndex: number, localIndex: number) {
+ let idx = 0;
+ for (let i = 0; i < sectionIndex; i++) {
+ idx += this.sections[i].results.length;
+ }
+ return idx + localIndex;
+ }
+
+ _computeItemSelected(
+ sectionIndex: number,
+ index: number,
+ selectedIndex: number
+ ) {
+ const idx = this._computeItemAbsoluteIndex(sectionIndex, index);
+ return idx === selectedIndex;
+ }
+
+ _computeTabIndex(sectionIndex: number, index: number, selectedIndex: number) {
+ return this._computeItemSelected(sectionIndex, index, selectedIndex)
+ ? 0
+ : undefined;
+ }
+
+ _computeItemNeedsReview(
+ account: AccountInfo | undefined,
+ change: ChangeInfo,
+ showReviewedState: boolean,
+ config?: ServerInfo
+ ) {
+ const isAttentionSetEnabled =
+ !!config && !!config.change && config.change.enable_attention_set;
+ return (
+ !isAttentionSetEnabled &&
+ showReviewedState &&
+ !change.reviewed &&
+ !change.work_in_progress &&
+ changeIsOpen(change) &&
+ (!account || account._account_id !== change.owner._account_id)
+ );
+ }
+
+ _computeItemHighlight(account?: AccountInfo, change?: ChangeInfo) {
+ // Do not show the assignee highlight if the change is not open.
+ if (
+ !change ||
+ !change.assignee ||
+ !account ||
+ CLOSED_STATUS.indexOf(change.status) !== -1
+ ) {
+ return false;
+ }
+ return account._account_id === change.assignee._account_id;
+ }
+
+ _nextChange(e: CustomKeyboardEvent) {
+ if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
+ return;
+ }
+
+ e.preventDefault();
+ this.$.cursor.next();
+ }
+
+ _prevChange(e: CustomKeyboardEvent) {
+ if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
+ return;
+ }
+
+ e.preventDefault();
+ this.$.cursor.previous();
+ }
+
+ _openChange(e: CustomKeyboardEvent) {
+ if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
+ return;
+ }
+
+ e.preventDefault();
+ const change = this._changeForIndex(this.selectedIndex);
+ if (change) GerritNav.navigateToChange(change);
+ }
+
+ _nextPage(e: CustomKeyboardEvent) {
+ if (
+ this.shouldSuppressKeyboardShortcut(e) ||
+ (this.modifierPressed(e) &&
+ !this.isModifierPressed(e, Modifier.SHIFT_KEY))
+ ) {
+ return;
+ }
+
+ e.preventDefault();
+ this.dispatchEvent(
+ new CustomEvent('next-page', {
+ composed: true,
+ bubbles: true,
+ })
+ );
+ }
+
+ _prevPage(e: CustomKeyboardEvent) {
+ if (
+ this.shouldSuppressKeyboardShortcut(e) ||
+ (this.modifierPressed(e) &&
+ !this.isModifierPressed(e, Modifier.SHIFT_KEY))
+ ) {
+ return;
+ }
+
+ e.preventDefault();
+ this.dispatchEvent(
+ new CustomEvent('previous-page', {
+ composed: true,
+ bubbles: true,
+ })
+ );
+ }
+
+ _toggleChangeReviewed(e: CustomKeyboardEvent) {
+ if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
+ return;
+ }
+
+ e.preventDefault();
+ this._toggleReviewedForIndex(this.selectedIndex);
+ }
+
+ _toggleReviewedForIndex(index?: number) {
+ const changeEls = this._getListItems();
+ if (index === undefined || index >= changeEls.length || !changeEls[index]) {
+ return;
+ }
+
+ const changeEl = changeEls[index];
+ changeEl.toggleReviewed();
+ }
+
+ _refreshChangeList(e: CustomKeyboardEvent) {
+ if (this.shouldSuppressKeyboardShortcut(e)) {
+ return;
+ }
+
+ e.preventDefault();
+ this._reloadWindow();
+ }
+
+ _reloadWindow() {
+ window.location.reload();
+ }
+
+ _toggleChangeStar(e: CustomKeyboardEvent) {
+ if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
+ return;
+ }
+
+ e.preventDefault();
+ this._toggleStarForIndex(this.selectedIndex);
+ }
+
+ _toggleStarForIndex(index?: number) {
+ const changeEls = this._getListItems();
+ if (index === undefined || index >= changeEls.length || !changeEls[index]) {
+ return;
+ }
+
+ const changeEl = changeEls[index];
+ const grChangeStar = changeEl?.shadowRoot?.querySelector('gr-change-star');
+ if (grChangeStar) grChangeStar.toggleStar();
+ }
+
+ _changeForIndex(index?: number) {
+ const changeEls = this._getListItems();
+ if (index !== undefined && index < changeEls.length && changeEls[index]) {
+ return changeEls[index].change;
+ }
+ return null;
+ }
+
+ _getListItems() {
+ const items = this.root?.querySelectorAll('gr-change-list-item');
+ return !items ? [] : Array.from(items);
+ }
+
+ @observe('sections.*')
+ _sectionsChanged() {
+ // Flush DOM operations so that the list item elements will be loaded.
+ afterNextRender(this, () => {
+ this.$.cursor.stops = this._getListItems();
+ this.$.cursor.moveToStart();
+ });
+ }
+
+ _getSpecialEmptySlot(section: DashboardSection) {
+ if (section.isOutgoing) return 'empty-outgoing';
+ if (section.name === 'Your Turn') return 'empty-your-turn';
+ return '';
+ }
+
+ _isEmpty(section: DashboardSection) {
+ return !section.results?.length;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'gr-change-list': GrChangeList;
+ }
+}
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js
index 0493966..56a16b5 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js
@@ -50,8 +50,8 @@
suite('test show change number not logged in', () => {
setup(() => {
element = basicFixture.instantiate();
- element.account = null;
- element.preferences = null;
+ element.account = undefined;
+ element.preferences = undefined;
element._config = {};
});
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts
index 5016c40..19e733e 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts
@@ -133,6 +133,7 @@
hideIfEmpty?: boolean;
assigneeOnly?: boolean;
isOutgoing?: boolean;
+ results?: ChangeInfo[];
}
export interface UserDashboardConfig {