Convert files to typescript The change converts the following files to typescript: * elements/gr-app-element.ts * elements/gr-app.ts Additionally, this change turns off the goog-module-id rule - it is not required anymore (migration to typescript is almost complete). Change-Id: I5f0845c03a464322500113b978722a12da7afdee
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts index 606a731..927d32f 100644 --- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts +++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
@@ -32,17 +32,15 @@ import { AccountDetailInfo, AccountId, - ChangeId, ChangeInfo, EmailAddress, - PatchRange, PreferencesInput, } from '../../../types/common'; import {RestApiService} from '../../../services/services/gr-rest-api/gr-rest-api'; import {ChangeListToggleReviewedDetail} from '../gr-change-list-item/gr-change-list-item'; import {ChangeStarToggleStarDetail} from '../../shared/gr-change-star/gr-change-star'; import {hasOwnProperty} from '../../../utils/common-util'; -import {DiffViewMode} from '../../../constants/constants'; +import {ChangeListViewState} from '../../../types/types'; const LookupQueryPatterns = { CHANGE_ID: /^\s*i?[0-9a-f]{7,40}\s*$/i, @@ -56,19 +54,6 @@ const LIMIT_OPERATOR_PATTERN = /\blimit:(\d+)/i; -export interface ChangeListViewState { - changeNum?: ChangeId; - patchRange?: PatchRange; - selectedFileIndex?: number; - showReplyDialog?: boolean; - showDownloadDialog?: boolean; - diffMode?: DiffViewMode; - numFilesShown?: number; - scrollTop?: number; - query?: string; - offset?: number; -} - export interface GrChangeListView { $: { restAPI: RestApiService & Element;
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 index 5a2b43c..3acdaf9 100644 --- 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
@@ -31,7 +31,6 @@ import { KeyboardShortcutMixin, Shortcut, - CustomKeyboardEvent, Modifier, } from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; import { @@ -56,6 +55,7 @@ hasAttention, isAttentionSetEnabled, } from '../../../utils/attention-set-util'; +import {CustomKeyboardEvent} from '../../../types/events'; const NUMBER_FIXED_COLUMNS = 3; const CLOSED_STATUS = ['MERGED', 'ABANDONED'];
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts index 7ca62d9..57d3dd9 100644 --- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts +++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
@@ -57,13 +57,10 @@ import {GrOverlay} from '../../shared/gr-overlay/gr-overlay'; import {ChangeListToggleReviewedDetail} from '../gr-change-list-item/gr-change-list-item'; import {ChangeStarToggleStarDetail} from '../../shared/gr-change-star/gr-change-star'; +import {DashboardViewState} from '../../../types/types'; const PROJECT_PLACEHOLDER_PATTERN = /\$\{project\}/g; -export interface DashboardViewState { - selectedChangeIndex: number; -} - export interface GrDashboardView { $: { restAPI: RestApiService & Element;
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts index 0a85954..6491358 100644 --- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts +++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -51,7 +51,6 @@ import { KeyboardShortcutMixin, Shortcut, - CustomKeyboardEvent, } from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; import {GrEditConstants} from '../../edit/gr-edit-constants'; import {GrCountStringFormatter} from '../../shared/gr-count-string-formatter/gr-count-string-formatter'; @@ -110,7 +109,6 @@ } from '../../../types/common'; import {GrReplyDialog, FocusTarget} from '../gr-reply-dialog/gr-reply-dialog'; import {GrIncludedInDialog} from '../gr-included-in-dialog/gr-included-in-dialog'; -import {CommentEventDetail} from '../../shared/gr-comment/gr-comment'; import {GrDownloadDialog} from '../gr-download-dialog/gr-download-dialog'; import {GrChangeMetadata} from '../gr-change-metadata/gr-change-metadata'; import { @@ -139,7 +137,13 @@ GrFileList, DEFAULT_NUM_FILES_SHOWN, } from '../gr-file-list/gr-file-list'; -import {isPolymerSpliceChange} from '../../../types/types'; +import {ChangeViewState, isPolymerSpliceChange} from '../../../types/types'; +import { + CustomKeyboardEvent, + EditableContentSaveEvent, + OpenFixPreviewEvent, + SwitchTabEvent, +} from '../../../types/events'; const CHANGE_ID_ERROR = { MISMATCH: 'mismatch', @@ -188,27 +192,6 @@ // Making the tab names more unique in case a plugin adds one with same name const ROBOT_COMMENTS_LIMIT = 10; -// Type for the custom event to switch tab. -interface SwitchTabEventDetail { - // name of the tab to set as active, from custom event - tab?: string; - // index of tab to set as active, from paper-tabs event - value?: number; - // scroll into the tab afterwards, from custom event - scrollIntoView?: boolean; -} - -export interface ChangeViewState { - diffMode?: DiffViewMode; - scrollTop?: number; - showDownloadDialog?: boolean; - showReplyDialog?: boolean; - changeNum?: NumericChangeId; - numFilesShown?: number; - patchRange?: PatchRange; - diffViewMode?: boolean; -} - export interface GrChangeView { $: { restAPI: RestApiService & Element; @@ -271,7 +254,7 @@ params?: AppElementChangeViewParams; @property({type: Object, notify: true, observer: '_viewStateChanged'}) - viewState: ChangeViewState = {}; + viewState: Partial<ChangeViewState> = {}; @property({type: String}) backPage?: string; @@ -634,30 +617,27 @@ ); this.addEventListener('change-message-deleted', () => this._reload()); this.addEventListener('editable-content-save', e => - this._handleCommitMessageSave(e as CustomEvent<{content: string}>) + this._handleCommitMessageSave(e) ); this.addEventListener('editable-content-cancel', () => this._handleCommitMessageCancel() ); - this.addEventListener('open-fix-preview', e => - this._onOpenFixPreview(e as CustomEvent<CommentEventDetail>) - ); + this.addEventListener('open-fix-preview', e => this._onOpenFixPreview(e)); this.addEventListener('close-fix-preview', () => this._onCloseFixPreview()); this.listen(window, 'scroll', '_handleScroll'); this.listen(document, 'visibilitychange', '_handleVisibilityChange'); this.addEventListener('show-primary-tab', e => - this._setActivePrimaryTab(e as CustomEvent<SwitchTabEventDetail>) + this._setActivePrimaryTab(e) ); this.addEventListener('show-secondary-tab', e => - this._setActiveSecondaryTab(e as CustomEvent<SwitchTabEventDetail>) + this._setActiveSecondaryTab(e) ); this.addEventListener('reload', e => { e.stopPropagation(); - const evt = e as CustomEvent<{clearPatchset: boolean}>; this._reload( /* isLocationChange= */ false, - /* clearPatchset= */ evt.detail && evt.detail.clearPatchset + /* clearPatchset= */ e.detail && e.detail.clearPatchset ); }); } @@ -703,7 +683,7 @@ }); } - _onOpenFixPreview(e: CustomEvent<CommentEventDetail>) { + _onOpenFixPreview(e: OpenFixPreviewEvent) { this.$.applyFixDialog.open(e); } @@ -775,7 +755,7 @@ /** * Changes active primary tab. */ - _setActivePrimaryTab(e: CustomEvent<SwitchTabEventDetail>) { + _setActivePrimaryTab(e: SwitchTabEvent) { const primaryTabs = this.shadowRoot!.querySelector( '#primaryTabs' ) as PaperTabsElement; @@ -808,7 +788,7 @@ /** * Changes active secondary tab. */ - _setActiveSecondaryTab(e: CustomEvent<SwitchTabEventDetail>) { + _setActiveSecondaryTab(e: SwitchTabEvent) { const secondaryTabs = this.shadowRoot!.querySelector( '#secondaryTabs' ) as PaperTabsElement; @@ -827,7 +807,7 @@ this.$.commitMessageEditor.focusTextarea(); } - _handleCommitMessageSave(e: CustomEvent<{content: string}>) { + _handleCommitMessageSave(e: EditableContentSaveEvent) { if (!this._change) throw new Error('missing required change property'); if (!this._changeNum) throw new Error('missing required changeNum property');
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 49f6992..3243af0 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
@@ -34,7 +34,6 @@ import {htmlTemplate} from './gr-file-list_html'; import {asyncForeach} from '../../../utils/async-util'; import { - CustomKeyboardEvent, KeyboardShortcutMixin, Modifier, Shortcut, @@ -78,6 +77,7 @@ import {UIDraft} from '../../../utils/comment-util'; import {ParsedChangeInfo} from '../../shared/gr-rest-api-interface/gr-reviewer-updates-parser'; import {PatchSetFile} from '../../../types/types'; +import {CustomKeyboardEvent} from '../../../types/events'; export const DEFAULT_NUM_FILES_SHOWN = 200;
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts index bd3c052..7a56d1c 100644 --- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts +++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts
@@ -38,6 +38,7 @@ import {RestApiService} from '../../../services/services/gr-rest-api/gr-rest-api'; import {FetchRequest} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper'; import {ErrorType, FixIronA11yAnnouncer} from '../../../types/types'; +import {AccountId} from '../../../types/common'; const HIDE_ALERT_TIMEOUT_MS = 5000; const CHECK_SIGN_IN_INTERVAL_MS = 60 * 1000; @@ -86,7 +87,7 @@ * not set, then there was no account at launch. */ @property({type: Number}) - knownAccountId?: number; + knownAccountId?: AccountId | null; @property({type: Object}) _alertElement: GrAlert | null = null;
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts index 21ff4dc..df3415d 100644 --- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts +++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -66,6 +66,7 @@ AppElementParams, AppElementAgreementParam, } from '../../gr-app-types'; +import {LocationChangeEventDetail} from '../../../types/events'; const RoutePattern = { ROOT: '/', @@ -854,12 +855,13 @@ // Fire asynchronously so that the URL is changed by the time the event // is processed. this.async(() => { + const detail: LocationChangeEventDetail = { + hash: window.location.hash, + pathname: window.location.pathname, + }; this.dispatchEvent( new CustomEvent('location-change', { - detail: { - hash: window.location.hash, - pathname: window.location.pathname, - }, + detail, composed: true, bubbles: true, })
diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.ts b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.ts index 180e4a7..68e045f 100644 --- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.ts +++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.ts
@@ -23,7 +23,6 @@ import {PolymerElement} from '@polymer/polymer/polymer-element'; import {htmlTemplate} from './gr-search-bar_html'; import { - CustomKeyboardEvent, KeyboardShortcutMixin, Shortcut, } from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; @@ -36,6 +35,7 @@ GrAutocomplete, } from '../../shared/gr-autocomplete/gr-autocomplete'; import {getDocsBaseUrl} from '../../../utils/url-util'; +import {CustomKeyboardEvent} from '../../../types/events'; // Possible static search options for auto complete, without negations. const SEARCH_OPERATORS = [
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts index 2236db2..0e73516 100644 --- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts +++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
@@ -38,9 +38,9 @@ RobotId, } from '../../../types/common'; import {GrOverlay} from '../../shared/gr-overlay/gr-overlay'; -import {CommentEventDetail} from '../../shared/gr-comment/gr-comment'; import {RestApiService} from '../../../services/services/gr-rest-api/gr-rest-api'; import {isRobot} from '../../../utils/comment-util'; +import {OpenFixPreviewEvent} from '../../../types/events'; export interface GrApplyFixDialog { $: { @@ -110,7 +110,7 @@ * @return Promise that resolves either when all * preview diffs are fetched or no fix suggestions in custom event detail. */ - open(e: CustomEvent<CommentEventDetail>) { + open(e: OpenFixPreviewEvent) { const detail = e.detail; const comment = detail.comment; if (!detail.patchNum || !comment || !isRobot(comment)) {
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 484b55d..848443a 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
@@ -37,7 +37,6 @@ import {PolymerElement} from '@polymer/polymer/polymer-element'; import {htmlTemplate} from './gr-diff-view_html'; import { - CustomKeyboardEvent, KeyboardShortcutMixin, Shortcut, } from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; @@ -98,10 +97,10 @@ import {hasOwnProperty} from '../../../utils/common-util'; import {GrApplyFixDialog} from '../gr-apply-fix-dialog/gr-apply-fix-dialog'; import {LineOfInterest} from '../gr-diff/gr-diff'; -import {CommentEventDetail} from '../../shared/gr-comment/gr-comment'; import {RevisionInfo as RevisionInfoObj} from '../../shared/revision-info/revision-info'; import {CommentMap} from '../../../utils/comment-util'; import {AppElementParams} from '../../gr-app-types'; +import {CustomKeyboardEvent, OpenFixPreviewEvent} from '../../../types/events'; const ERR_REVIEW_STATUS = 'Couldn’t change file review status.'; const MSG_LOADING_BLAME = 'Loading blame...'; @@ -343,9 +342,7 @@ this._loggedIn = loggedIn; }); - this.addEventListener('open-fix-preview', e => - this._onOpenFixPreview(e as CustomEvent<CommentEventDetail>) - ); + this.addEventListener('open-fix-preview', e => this._onOpenFixPreview(e)); this.$.cursor.push('diffs', this.$.diffHost); this._onRenderHandler = (_: Event) => { this.$.cursor.reInitCursor(); @@ -539,7 +536,7 @@ this.$.cursor.moveToVisibleArea(); } - _onOpenFixPreview(e: CustomEvent<CommentEventDetail>) { + _onOpenFixPreview(e: OpenFixPreviewEvent) { this.$.applyFixDialog.open(e); }
diff --git a/polygerrit-ui/app/elements/gr-app-element.ts b/polygerrit-ui/app/elements/gr-app-element.ts index 93b051c..6452239 100644 --- a/polygerrit-ui/app/elements/gr-app-element.ts +++ b/polygerrit-ui/app/elements/gr-app-element.ts
@@ -14,147 +14,185 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import '../styles/shared-styles.js'; -import '../styles/themes/app-theme.js'; -import {applyTheme as applyDarkTheme} from '../styles/themes/dark-theme.js'; -import './admin/gr-admin-view/gr-admin-view.js'; -import './documentation/gr-documentation-search/gr-documentation-search.js'; -import './change-list/gr-change-list-view/gr-change-list-view.js'; -import './change-list/gr-dashboard-view/gr-dashboard-view.js'; -import './change/gr-change-view/gr-change-view.js'; -import './core/gr-error-manager/gr-error-manager.js'; -import './core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.js'; -import './core/gr-main-header/gr-main-header.js'; -import './core/gr-router/gr-router.js'; -import './core/gr-smart-search/gr-smart-search.js'; -import './diff/gr-diff-view/gr-diff-view.js'; -import './edit/gr-editor-view/gr-editor-view.js'; -import './plugins/gr-endpoint-decorator/gr-endpoint-decorator.js'; -import './plugins/gr-endpoint-param/gr-endpoint-param.js'; -import './plugins/gr-endpoint-slot/gr-endpoint-slot.js'; -import './plugins/gr-external-style/gr-external-style.js'; -import './plugins/gr-plugin-host/gr-plugin-host.js'; -import './settings/gr-cla-view/gr-cla-view.js'; -import './settings/gr-registration-dialog/gr-registration-dialog.js'; -import './settings/gr-settings-view/gr-settings-view.js'; -import './shared/gr-lib-loader/gr-lib-loader.js'; -import './shared/gr-rest-api-interface/gr-rest-api-interface.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-app-element_html.js'; -import {getBaseUrl} from '../utils/url-util.js'; +import '../styles/shared-styles'; +import '../styles/themes/app-theme'; +import {applyTheme as applyDarkTheme} from '../styles/themes/dark-theme'; +import './admin/gr-admin-view/gr-admin-view'; +import './documentation/gr-documentation-search/gr-documentation-search'; +import './change-list/gr-change-list-view/gr-change-list-view'; +import './change-list/gr-dashboard-view/gr-dashboard-view'; +import './change/gr-change-view/gr-change-view'; +import './core/gr-error-manager/gr-error-manager'; +import './core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog'; +import './core/gr-main-header/gr-main-header'; +import './core/gr-router/gr-router'; +import './core/gr-smart-search/gr-smart-search'; +import './diff/gr-diff-view/gr-diff-view'; +import './edit/gr-editor-view/gr-editor-view'; +import './plugins/gr-endpoint-decorator/gr-endpoint-decorator'; +import './plugins/gr-endpoint-param/gr-endpoint-param'; +import './plugins/gr-endpoint-slot/gr-endpoint-slot'; +import './plugins/gr-external-style/gr-external-style'; +import './plugins/gr-plugin-host/gr-plugin-host'; +import './settings/gr-cla-view/gr-cla-view'; +import './settings/gr-registration-dialog/gr-registration-dialog'; +import './settings/gr-settings-view/gr-settings-view'; +import './shared/gr-lib-loader/gr-lib-loader'; +import './shared/gr-rest-api-interface/gr-rest-api-interface'; +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-app-element_html'; +import {getBaseUrl} from '../utils/url-util'; import { KeyboardShortcutMixin, Shortcut, SPECIAL_SHORTCUT, -} from '../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.js'; -import {GerritNav} from './core/gr-navigation/gr-navigation.js'; -import {appContext} from '../services/app-context.js'; +} from '../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; +import {GerritNav, GerritView} from './core/gr-navigation/gr-navigation'; +import {appContext} from '../services/app-context'; import {flush} from '@polymer/polymer/lib/utils/flush'; +import {customElement, observe, property} from '@polymer/decorators'; +import {RestApiService} from '../services/services/gr-rest-api/gr-rest-api'; +import {GrRouter} from './core/gr-router/gr-router'; +import { + AccountDetailInfo, + ElementPropertyDeepChange, + ServerInfo, +} from '../types/common'; +import {GrErrorManager} from './core/gr-error-manager/gr-error-manager'; +import {GrOverlay} from './shared/gr-overlay/gr-overlay'; +import {GrRegistrationDialog} from './settings/gr-registration-dialog/gr-registration-dialog'; +import { + AppElementJustRegisteredParams, + AppElementParams, + isAppElementJustRegisteredParams, +} from './gr-app-types'; +import {GrMainHeader} from './core/gr-main-header/gr-main-header'; +import {GrSettingsView} from './settings/gr-settings-view/gr-settings-view'; +import { + CustomKeyboardEvent, + LocationChangeEvent, + PageErrorEventDetail, + RpcLogEvent, + ShortcutTriggeredEvent, + TitleChangeEventDetail, +} from '../types/events'; +import {ViewState} from '../types/types'; -/** - * @extends PolymerElement - */ -class GrAppElement extends KeyboardShortcutMixin( - GestureEventListeners( - LegacyElementMixin(PolymerElement))) { - static get template() { return htmlTemplate; } +interface ErrorInfo { + text: string; + emoji?: string; + moreInfo?: string; +} - static get is() { return 'gr-app-element'; } +export interface GrAppElement { + $: { + restAPI: RestApiService & Element; + router: GrRouter; + errorManager: GrErrorManager; + errorView: HTMLDivElement; + mainHeader: GrMainHeader; + }; +} + +// TODO(TS): implement AppElement interface from gr-app-types.ts +@customElement('gr-app-element') +export class GrAppElement extends KeyboardShortcutMixin( + GestureEventListeners(LegacyElementMixin(PolymerElement)) +) { + static get template() { + return htmlTemplate; + } + /** * Fired when the URL location changes. * * @event location-change */ - static get properties() { - return { - /** - * @type {{ query: string, view: string, screen: string }} - */ - params: Object, - keyEventTarget: { - type: Object, - value() { return document.body; }, - }, + @property({type: Object}) + params?: AppElementParams; - _account: { - type: Object, - observer: '_accountChanged', - }, + @property({type: Object}) + keyEventTarget = document.body; - /** - * The last time the g key was pressed in milliseconds (or a keydown event - * was handled if the key is held down). - * - * @type {number|null} - */ - _lastGKeyPressTimestamp: { - type: Number, - value: null, - }, + @property({type: Object, observer: '_accountChanged'}) + _account?: AccountDetailInfo; - /** - * @type {{ plugin: Object }} - */ - _serverConfig: Object, - _version: String, - _showChangeListView: Boolean, - _showDashboardView: Boolean, - _showChangeView: Boolean, - _showDiffView: Boolean, - _showSettingsView: Boolean, - _showAdminView: Boolean, - _showCLAView: Boolean, - _showEditorView: Boolean, - _showPluginScreen: Boolean, - _showDocumentationSearch: Boolean, - /** @type {?} */ - _viewState: Object, - /** @type {?} */ - _lastError: Object, - _lastSearchPage: String, - _path: String, - _pluginScreenName: { - type: String, - computed: '_computePluginScreenName(params)', - }, - _settingsUrl: String, - _feedbackUrl: String, - // Used to allow searching on mobile - mobileSearch: { - type: Boolean, - value: false, - }, + @property({type: Number}) + _lastGKeyPressTimestamp: number | null = null; - /** - * Other elements in app must open this URL when - * user login is required. - */ - _loginUrl: { - type: String, - value: '/login', - }, + @property({type: Object}) + _serverConfig?: ServerInfo; - loadRegistrationDialog: { - type: Boolean, - value: false, - }, + @property({type: String}) + _version?: string; - loadKeyboardShortcutsDialog: { - type: Boolean, - value: false, - }, - }; - } + @property({type: Boolean}) + _showChangeListView?: boolean; - static get observers() { - return [ - '_viewChanged(params.view)', - '_paramsChanged(params.*)', - ]; - } + @property({type: Boolean}) + _showDashboardView?: boolean; + + @property({type: Boolean}) + _showChangeView?: boolean; + + @property({type: Boolean}) + _showDiffView?: boolean; + + @property({type: Boolean}) + _showSettingsView?: boolean; + + @property({type: Boolean}) + _showAdminView?: boolean; + + @property({type: Boolean}) + _showCLAView?: boolean; + + @property({type: Boolean}) + _showEditorView?: boolean; + + @property({type: Boolean}) + _showPluginScreen?: boolean; + + @property({type: Boolean}) + _showDocumentationSearch?: boolean; + + @property({type: Object}) + _viewState?: ViewState; + + @property({type: Object}) + _lastError?: ErrorInfo; + + @property({type: String}) + _lastSearchPage?: string; + + @property({type: String}) + _path?: string; + + @property({type: String, computed: '_computePluginScreenName(params)'}) + _pluginScreenName?: string; + + @property({type: String}) + _settingsUrl?: string; + + @property({type: String}) + _feedbackUrl?: string; + + @property({type: Boolean}) + mobileSearch = false; + + @property({type: String}) + _loginUrl = '/login'; + + @property({type: Boolean}) + loadRegistrationDialog = false; + + @property({type: Boolean}) + loadKeyboardShortcutsDialog = false; + + private reporting = appContext.reportingService; keyboardShortcuts() { return { @@ -167,29 +205,23 @@ }; } - constructor() { - super(); - this.reporting = appContext.reportingService; - } - /** @override */ created() { super.created(); this._bindKeyboardShortcuts(); - this.addEventListener('page-error', - e => this._handlePageError(e)); - this.addEventListener('title-change', - e => this._handleTitleChange(e)); - this.addEventListener('location-change', - e => this._handleLocationChange(e)); - this.addEventListener('rpc-log', - e => this._handleRpcLog(e)); - this.addEventListener('shortcut-triggered', - e => this._handleShortcutTriggered(e)); + this.addEventListener('page-error', e => this._handlePageError(e)); + this.addEventListener('title-change', e => this._handleTitleChange(e)); + this.addEventListener('location-change', e => + this._handleLocationChange(e) + ); + this.addEventListener('rpc-log', e => this._handleRpcLog(e)); + this.addEventListener('shortcut-triggered', e => + this._handleShortcutTriggered(e) + ); // Ideally individual views should handle this event and respond with a soft // reload. This is a catch-all for all views that cannot or have not // implemented that. - this.addEventListener('reload', e => window.location.reload()); + this.addEventListener('reload', () => window.location.reload()); } /** @override */ @@ -247,150 +279,145 @@ } _bindKeyboardShortcuts() { - this.bindShortcut(Shortcut.SEND_REPLY, - SPECIAL_SHORTCUT.DOC_ONLY, 'ctrl+enter', 'meta+enter'); - this.bindShortcut(Shortcut.EMOJI_DROPDOWN, - SPECIAL_SHORTCUT.DOC_ONLY, ':'); + this.bindShortcut( + Shortcut.SEND_REPLY, + SPECIAL_SHORTCUT.DOC_ONLY, + 'ctrl+enter', + 'meta+enter' + ); + this.bindShortcut(Shortcut.EMOJI_DROPDOWN, SPECIAL_SHORTCUT.DOC_ONLY, ':'); + this.bindShortcut(Shortcut.OPEN_SHORTCUT_HELP_DIALOG, '?'); this.bindShortcut( - Shortcut.OPEN_SHORTCUT_HELP_DIALOG, '?'); + Shortcut.GO_TO_USER_DASHBOARD, + SPECIAL_SHORTCUT.GO_KEY, + 'i' + ); this.bindShortcut( - Shortcut.GO_TO_USER_DASHBOARD, SPECIAL_SHORTCUT.GO_KEY, 'i'); + Shortcut.GO_TO_OPENED_CHANGES, + SPECIAL_SHORTCUT.GO_KEY, + 'o' + ); this.bindShortcut( - Shortcut.GO_TO_OPENED_CHANGES, SPECIAL_SHORTCUT.GO_KEY, 'o'); + Shortcut.GO_TO_MERGED_CHANGES, + SPECIAL_SHORTCUT.GO_KEY, + 'm' + ); this.bindShortcut( - Shortcut.GO_TO_MERGED_CHANGES, SPECIAL_SHORTCUT.GO_KEY, 'm'); + Shortcut.GO_TO_ABANDONED_CHANGES, + SPECIAL_SHORTCUT.GO_KEY, + 'a' + ); this.bindShortcut( - Shortcut.GO_TO_ABANDONED_CHANGES, SPECIAL_SHORTCUT.GO_KEY, 'a'); - this.bindShortcut( - Shortcut.GO_TO_WATCHED_CHANGES, SPECIAL_SHORTCUT.GO_KEY, 'w'); + Shortcut.GO_TO_WATCHED_CHANGES, + SPECIAL_SHORTCUT.GO_KEY, + 'w' + ); - this.bindShortcut( - Shortcut.CURSOR_NEXT_CHANGE, 'j'); - this.bindShortcut( - Shortcut.CURSOR_PREV_CHANGE, 'k'); - this.bindShortcut( - Shortcut.OPEN_CHANGE, 'o'); - this.bindShortcut( - Shortcut.NEXT_PAGE, 'n', ']'); - this.bindShortcut( - Shortcut.PREV_PAGE, 'p', '['); - this.bindShortcut( - Shortcut.TOGGLE_CHANGE_REVIEWED, 'r:keyup'); - this.bindShortcut( - Shortcut.TOGGLE_CHANGE_STAR, 's:keydown'); - this.bindShortcut( - Shortcut.REFRESH_CHANGE_LIST, 'shift+r:keyup'); - this.bindShortcut( - Shortcut.EDIT_TOPIC, 't'); + this.bindShortcut(Shortcut.CURSOR_NEXT_CHANGE, 'j'); + this.bindShortcut(Shortcut.CURSOR_PREV_CHANGE, 'k'); + this.bindShortcut(Shortcut.OPEN_CHANGE, 'o'); + this.bindShortcut(Shortcut.NEXT_PAGE, 'n', ']'); + this.bindShortcut(Shortcut.PREV_PAGE, 'p', '['); + this.bindShortcut(Shortcut.TOGGLE_CHANGE_REVIEWED, 'r:keyup'); + this.bindShortcut(Shortcut.TOGGLE_CHANGE_STAR, 's:keydown'); + this.bindShortcut(Shortcut.REFRESH_CHANGE_LIST, 'shift+r:keyup'); + this.bindShortcut(Shortcut.EDIT_TOPIC, 't'); + this.bindShortcut(Shortcut.OPEN_REPLY_DIALOG, 'a:keyup'); + this.bindShortcut(Shortcut.OPEN_DOWNLOAD_DIALOG, 'd:keyup'); + this.bindShortcut(Shortcut.EXPAND_ALL_MESSAGES, 'x'); + this.bindShortcut(Shortcut.COLLAPSE_ALL_MESSAGES, 'z'); + this.bindShortcut(Shortcut.REFRESH_CHANGE, 'shift+r:keyup'); + this.bindShortcut(Shortcut.UP_TO_DASHBOARD, 'u'); + this.bindShortcut(Shortcut.UP_TO_CHANGE, 'u'); + this.bindShortcut(Shortcut.TOGGLE_DIFF_MODE, 'm:keyup'); this.bindShortcut( - Shortcut.OPEN_REPLY_DIALOG, 'a:keyup'); - this.bindShortcut( - Shortcut.OPEN_DOWNLOAD_DIALOG, 'd:keyup'); - this.bindShortcut( - Shortcut.EXPAND_ALL_MESSAGES, 'x'); - this.bindShortcut( - Shortcut.COLLAPSE_ALL_MESSAGES, 'z'); - this.bindShortcut( - Shortcut.REFRESH_CHANGE, 'shift+r:keyup'); - this.bindShortcut( - Shortcut.UP_TO_DASHBOARD, 'u'); - this.bindShortcut( - Shortcut.UP_TO_CHANGE, 'u'); - this.bindShortcut( - Shortcut.TOGGLE_DIFF_MODE, 'm:keyup'); - this.bindShortcut( - Shortcut.DIFF_AGAINST_BASE, SPECIAL_SHORTCUT.V_KEY, 'down', 's'); + Shortcut.DIFF_AGAINST_BASE, + SPECIAL_SHORTCUT.V_KEY, + 'down', + 's' + ); // this keyboard shortcut is used in toast _displayDiffAgainstLatestToast // in gr-diff-view. Any updates here should be reflected there this.bindShortcut( - Shortcut.DIFF_AGAINST_LATEST, SPECIAL_SHORTCUT.V_KEY, 'up', 'w'); + Shortcut.DIFF_AGAINST_LATEST, + SPECIAL_SHORTCUT.V_KEY, + 'up', + 'w' + ); // this keyboard shortcut is used in toast _displayDiffBaseAgainstLeftToast // in gr-diff-view. Any updates here should be reflected there this.bindShortcut( - Shortcut.DIFF_BASE_AGAINST_LEFT, - SPECIAL_SHORTCUT.V_KEY, 'left', 'a'); + Shortcut.DIFF_BASE_AGAINST_LEFT, + SPECIAL_SHORTCUT.V_KEY, + 'left', + 'a' + ); this.bindShortcut( - Shortcut.DIFF_RIGHT_AGAINST_LATEST, - SPECIAL_SHORTCUT.V_KEY, 'right', 'd'); + Shortcut.DIFF_RIGHT_AGAINST_LATEST, + SPECIAL_SHORTCUT.V_KEY, + 'right', + 'd' + ); this.bindShortcut( - Shortcut.DIFF_BASE_AGAINST_LATEST, SPECIAL_SHORTCUT.V_KEY, 'b'); + Shortcut.DIFF_BASE_AGAINST_LATEST, + SPECIAL_SHORTCUT.V_KEY, + 'b' + ); - this.bindShortcut( - Shortcut.NEXT_LINE, 'j', 'down'); - this.bindShortcut( - Shortcut.PREV_LINE, 'k', 'up'); + this.bindShortcut(Shortcut.NEXT_LINE, 'j', 'down'); + this.bindShortcut(Shortcut.PREV_LINE, 'k', 'up'); if (this._isCursorManagerSupportMoveToVisibleLine()) { - this.bindShortcut( - Shortcut.VISIBLE_LINE, '.'); + this.bindShortcut(Shortcut.VISIBLE_LINE, '.'); } + this.bindShortcut(Shortcut.NEXT_CHUNK, 'n'); + this.bindShortcut(Shortcut.PREV_CHUNK, 'p'); + this.bindShortcut(Shortcut.EXPAND_ALL_DIFF_CONTEXT, 'shift+x'); + this.bindShortcut(Shortcut.NEXT_COMMENT_THREAD, 'shift+n'); + this.bindShortcut(Shortcut.PREV_COMMENT_THREAD, 'shift+p'); this.bindShortcut( - Shortcut.NEXT_CHUNK, 'n'); + Shortcut.EXPAND_ALL_COMMENT_THREADS, + SPECIAL_SHORTCUT.DOC_ONLY, + 'e' + ); this.bindShortcut( - Shortcut.PREV_CHUNK, 'p'); + Shortcut.COLLAPSE_ALL_COMMENT_THREADS, + SPECIAL_SHORTCUT.DOC_ONLY, + 'shift+e' + ); + this.bindShortcut(Shortcut.LEFT_PANE, 'shift+left'); + this.bindShortcut(Shortcut.RIGHT_PANE, 'shift+right'); + this.bindShortcut(Shortcut.TOGGLE_LEFT_PANE, 'shift+a'); + this.bindShortcut(Shortcut.NEW_COMMENT, 'c'); this.bindShortcut( - Shortcut.EXPAND_ALL_DIFF_CONTEXT, 'shift+x'); - this.bindShortcut( - Shortcut.NEXT_COMMENT_THREAD, 'shift+n'); - this.bindShortcut( - Shortcut.PREV_COMMENT_THREAD, 'shift+p'); - this.bindShortcut( - Shortcut.EXPAND_ALL_COMMENT_THREADS, - SPECIAL_SHORTCUT.DOC_ONLY, 'e'); - this.bindShortcut( - Shortcut.COLLAPSE_ALL_COMMENT_THREADS, - SPECIAL_SHORTCUT.DOC_ONLY, 'shift+e'); - this.bindShortcut( - Shortcut.LEFT_PANE, 'shift+left'); - this.bindShortcut( - Shortcut.RIGHT_PANE, 'shift+right'); - this.bindShortcut( - Shortcut.TOGGLE_LEFT_PANE, 'shift+a'); - this.bindShortcut( - Shortcut.NEW_COMMENT, 'c'); - this.bindShortcut( - Shortcut.SAVE_COMMENT, - 'ctrl+enter', 'meta+enter', 'ctrl+s', 'meta+s'); - this.bindShortcut( - Shortcut.OPEN_DIFF_PREFS, ','); - this.bindShortcut( - Shortcut.TOGGLE_DIFF_REVIEWED, 'r:keyup'); + Shortcut.SAVE_COMMENT, + 'ctrl+enter', + 'meta+enter', + 'ctrl+s', + 'meta+s' + ); + this.bindShortcut(Shortcut.OPEN_DIFF_PREFS, ','); + this.bindShortcut(Shortcut.TOGGLE_DIFF_REVIEWED, 'r:keyup'); - this.bindShortcut( - Shortcut.NEXT_FILE, ']'); - this.bindShortcut( - Shortcut.PREV_FILE, '['); - this.bindShortcut( - Shortcut.NEXT_FILE_WITH_COMMENTS, 'shift+j'); - this.bindShortcut( - Shortcut.PREV_FILE_WITH_COMMENTS, 'shift+k'); - this.bindShortcut( - Shortcut.CURSOR_NEXT_FILE, 'j', 'down'); - this.bindShortcut( - Shortcut.CURSOR_PREV_FILE, 'k', 'up'); - this.bindShortcut( - Shortcut.OPEN_FILE, 'o', 'enter'); - this.bindShortcut( - Shortcut.TOGGLE_FILE_REVIEWED, 'r:keyup'); - this.bindShortcut( - Shortcut.NEXT_UNREVIEWED_FILE, 'shift+m'); - this.bindShortcut( - Shortcut.TOGGLE_ALL_INLINE_DIFFS, 'shift+i:keyup'); - this.bindShortcut( - Shortcut.TOGGLE_INLINE_DIFF, 'i:keyup'); - this.bindShortcut( - Shortcut.TOGGLE_BLAME, 'b:keyup'); - this.bindShortcut( - Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS, 'h'); + this.bindShortcut(Shortcut.NEXT_FILE, ']'); + this.bindShortcut(Shortcut.PREV_FILE, '['); + this.bindShortcut(Shortcut.NEXT_FILE_WITH_COMMENTS, 'shift+j'); + this.bindShortcut(Shortcut.PREV_FILE_WITH_COMMENTS, 'shift+k'); + this.bindShortcut(Shortcut.CURSOR_NEXT_FILE, 'j', 'down'); + this.bindShortcut(Shortcut.CURSOR_PREV_FILE, 'k', 'up'); + this.bindShortcut(Shortcut.OPEN_FILE, 'o', 'enter'); + this.bindShortcut(Shortcut.TOGGLE_FILE_REVIEWED, 'r:keyup'); + this.bindShortcut(Shortcut.NEXT_UNREVIEWED_FILE, 'shift+m'); + this.bindShortcut(Shortcut.TOGGLE_ALL_INLINE_DIFFS, 'shift+i:keyup'); + this.bindShortcut(Shortcut.TOGGLE_INLINE_DIFF, 'i:keyup'); + this.bindShortcut(Shortcut.TOGGLE_BLAME, 'b:keyup'); + this.bindShortcut(Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS, 'h'); - this.bindShortcut( - Shortcut.OPEN_FIRST_FILE, ']'); - this.bindShortcut( - Shortcut.OPEN_LAST_FILE, '['); + this.bindShortcut(Shortcut.OPEN_FIRST_FILE, ']'); + this.bindShortcut(Shortcut.OPEN_LAST_FILE, '['); - this.bindShortcut( - Shortcut.SEARCH, '/'); + this.bindShortcut(Shortcut.SEARCH, '/'); } _isCursorManagerSupportMoveToVisibleLine() { @@ -401,30 +428,35 @@ return 'IntersectionObserver' in window; } - _accountChanged(account) { - if (!account) { return; } + _accountChanged(account?: AccountDetailInfo) { + if (!account) return; // Preferences are cached when a user is logged in; warm them. this.$.restAPI.getPreferences(); this.$.restAPI.getDiffPreferences(); this.$.restAPI.getEditPreferences(); this.$.errorManager.knownAccountId = - this._account && this._account._account_id || null; + (this._account && this._account._account_id) || null; } - _viewChanged(view) { + @observe('params.view') + _viewChanged(view?: GerritView) { this.$.errorView.classList.remove('show'); - this.set('_showChangeListView', view === GerritNav.View.SEARCH); - this.set('_showDashboardView', view === GerritNav.View.DASHBOARD); - this.set('_showChangeView', view === GerritNav.View.CHANGE); - this.set('_showDiffView', view === GerritNav.View.DIFF); - this.set('_showSettingsView', view === GerritNav.View.SETTINGS); + this.set('_showChangeListView', view === GerritView.SEARCH); + this.set('_showDashboardView', view === GerritView.DASHBOARD); + this.set('_showChangeView', view === GerritView.CHANGE); + this.set('_showDiffView', view === GerritView.DIFF); + this.set('_showSettingsView', view === GerritView.SETTINGS); // _showAdminView must be in sync with the gr-admin-view AdminViewParams type - this.set('_showAdminView', view === GerritNav.View.ADMIN || - view === GerritNav.View.GROUP || view === GerritNav.View.REPO); - this.set('_showCLAView', view === GerritNav.View.AGREEMENTS); - this.set('_showEditorView', view === GerritNav.View.EDIT); - const isPluginScreen = view === GerritNav.View.PLUGIN_SCREEN; + this.set( + '_showAdminView', + view === GerritView.ADMIN || + view === GerritView.GROUP || + view === GerritView.REPO + ); + this.set('_showCLAView', view === GerritView.AGREEMENTS); + this.set('_showEditorView', view === GerritView.EDIT); + const isPluginScreen = view === GerritView.PLUGIN_SCREEN; this.set('_showPluginScreen', false); // Navigation within plugin screens does not restamp gr-endpoint-decorator // because _showPluginScreen value does not change. To force restamp, @@ -432,15 +464,23 @@ if (isPluginScreen) { this.async(() => this.set('_showPluginScreen', true), 1); } - this.set('_showDocumentationSearch', - view === GerritNav.View.DOCUMENTATION_SEARCH); - if (this.params.justRegistered) { + this.set( + '_showDocumentationSearch', + view === GerritView.DOCUMENTATION_SEARCH + ); + if ( + this.params && + isAppElementJustRegisteredParams(this.params) && + this.params.justRegistered + ) { this.loadRegistrationDialog = true; flush(); - const registrationOverlay = - this.shadowRoot.querySelector('#registrationOverlay'); - const registrationDialog = - this.shadowRoot.querySelector('#registrationDialog'); + const registrationOverlay = this.shadowRoot!.querySelector( + '#registrationOverlay' + ) as GrOverlay; + const registrationDialog = this.shadowRoot!.querySelector( + '#registrationDialog' + ) as GrRegistrationDialog; registrationOverlay.open(); registrationDialog.loadData().then(() => { registrationOverlay.refit(); @@ -448,10 +488,10 @@ } } - _handleShortcutTriggered(event) { + _handleShortcutTriggered(event: ShortcutTriggeredEvent) { const {event: e, goKey, vKey} = event.detail; // eg: {key: "k:keydown", ..., from: "gr-diff-view"} - let key = `${e.key}:${e.type}`; + let key = `${((e as unknown) as KeyboardEvent).key}:${e.type}`; if (goKey) key = 'g+' + key; if (vKey) key = 'v+' + key; if (e.shiftKey) key = 'shift+' + key; @@ -460,12 +500,13 @@ if (e.altKey) key = 'alt+' + key; this.reporting.reportInteraction('shortcut-triggered', { key, - from: event.path && event.path[0] - && event.path[0].nodeName || 'unknown', + from: + (event.path && event.path[0] && (event.path[0] as Element).nodeName) ?? + 'unknown', }); } - _handlePageError(e) { + _handlePageError(e: CustomEvent<PageErrorEventDetail>) { const props = [ '_showChangeListView', '_showDashboardView', @@ -480,7 +521,9 @@ this.$.errorView.classList.add('show'); const response = e.detail.response; - const err = {text: [response.status, response.statusText].join(' ')}; + const err: ErrorInfo = { + text: [response.status, response.statusText].join(' '), + }; if (response.status === 404) { err.emoji = '¯\\_(ツ)_/¯'; this._lastError = err; @@ -493,7 +536,7 @@ } } - _handleLocationChange(e) { + _handleLocationChange(e: LocationChangeEvent) { this._updateLoginUrl(); const hash = e.detail.hash.substring(1); @@ -509,27 +552,38 @@ if (baseUrl) { // Strip the canonical path from the path since needing canonical in // the path is unneeded and breaks the url. - this._loginUrl = baseUrl + '/login/' + encodeURIComponent( - '/' + window.location.pathname.substring(baseUrl.length) + - window.location.search + - window.location.hash); + this._loginUrl = + baseUrl + + '/login/' + + encodeURIComponent( + '/' + + window.location.pathname.substring(baseUrl.length) + + window.location.search + + window.location.hash + ); } else { - this._loginUrl = '/login/' + encodeURIComponent( + this._loginUrl = + '/login/' + + encodeURIComponent( window.location.pathname + - window.location.search + - window.location.hash); + window.location.search + + window.location.hash + ); } } - _paramsChanged(paramsRecord) { + @observe('params.*') + _paramsChanged( + paramsRecord: ElementPropertyDeepChange<GrAppElement, 'params'> + ) { const params = paramsRecord.base; - const viewsToCheck = [GerritNav.View.SEARCH, GerritNav.View.DASHBOARD]; - if (viewsToCheck.includes(params.view)) { + const viewsToCheck = [GerritView.SEARCH, GerritView.DASHBOARD]; + if (params?.view && viewsToCheck.includes(params.view)) { this.set('_lastSearchPage', location.pathname); } } - _handleTitleChange(e) { + _handleTitleChange(e: CustomEvent<TitleChangeEventDetail>) { if (e.detail.title) { document.title = e.detail.title + ' · Gerrit Code Review'; } else { @@ -540,39 +594,48 @@ handleShowKeyboardShortcuts() { this.loadKeyboardShortcutsDialog = true; flush(); - this.shadowRoot.querySelector('#keyboardShortcuts').open(); + (this.shadowRoot!.querySelector('#keyboardShortcuts') as GrOverlay).open(); } - _showKeyboardShortcuts(e) { + _showKeyboardShortcuts(e: CustomKeyboardEvent) { // same shortcut should close the dialog if pressed again // when dialog is open this.loadKeyboardShortcutsDialog = true; flush(); - const keyboardShortcuts = - this.shadowRoot.querySelector('#keyboardShortcuts'); + const keyboardShortcuts = this.shadowRoot!.querySelector( + '#keyboardShortcuts' + ) as GrOverlay; if (!keyboardShortcuts) return; if (keyboardShortcuts.opened) { keyboardShortcuts.close(); return; } - if (this.shouldSuppressKeyboardShortcut(e)) { return; } + if (this.shouldSuppressKeyboardShortcut(e)) { + return; + } keyboardShortcuts.open(); } _handleKeyboardShortcutDialogClose() { - this.shadowRoot.querySelector('#keyboardShortcuts').close(); + (this.shadowRoot!.querySelector('#keyboardShortcuts') as GrOverlay).close(); } - _handleAccountDetailUpdate(e) { + _handleAccountDetailUpdate() { this.$.mainHeader.reload(); - if (this.params.view === GerritNav.View.SETTINGS) { - this.shadowRoot.querySelector('gr-settings-view').reloadAccountDetail(); + if (this.params?.view === GerritView.SETTINGS) { + (this.shadowRoot!.querySelector( + 'gr-settings-view' + ) as GrSettingsView).reloadAccountDetail(); } } - _handleRegistrationDialogClose(e) { - this.params.justRegistered = false; - this.shadowRoot.querySelector('#registrationOverlay').close(); + _handleRegistrationDialogClose() { + // The registration dialog is visible only if this.params is + // instanceof AppElementJustRegisteredParams + (this.params as AppElementJustRegisteredParams).justRegistered = false; + (this.shadowRoot!.querySelector( + '#registrationOverlay' + ) as GrOverlay).close(); } _goToOpenedChanges() { @@ -596,9 +659,10 @@ GerritNav.navigateToSearchQuery('is:watched is:open'); } - _computePluginScreenName({plugin, screen}) { - if (!plugin || !screen) return ''; - return `${plugin}-screen-${screen}`; + _computePluginScreenName(params: AppElementParams) { + if (params.view !== GerritView.PLUGIN_SCREEN) return ''; + if (!params.plugin || !params.screen) return ''; + return `${params.plugin}-screen-${params.screen}`; } _logWelcome() { @@ -619,21 +683,24 @@ * Note: the REST API interface cannot use gr-reporting directly because * that would create a cyclic dependency. */ - _handleRpcLog(e) { - this.reporting.reportRpcTiming(e.detail.anonymizedUrl, - e.detail.elapsed); + _handleRpcLog(e: RpcLogEvent) { + this.reporting.reportRpcTiming(e.detail.anonymizedUrl, e.detail.elapsed); } - _mobileSearchToggle(e) { + _mobileSearchToggle() { this.mobileSearch = !this.mobileSearch; } getThemeEndpoint() { // For now, we only have dark mode and light mode - return window.localStorage.getItem('dark-theme') ? - 'app-theme-dark' : - 'app-theme-light'; + return window.localStorage.getItem('dark-theme') + ? 'app-theme-dark' + : 'app-theme-light'; } } -customElements.define(GrAppElement.is, GrAppElement); +declare global { + interface HTMLElementTagNameMap { + 'gr-app-element': GrAppElement; + } +}
diff --git a/polygerrit-ui/app/elements/gr-app-types.ts b/polygerrit-ui/app/elements/gr-app-types.ts index 29eef48..b05117f 100644 --- a/polygerrit-ui/app/elements/gr-app-types.ts +++ b/polygerrit-ui/app/elements/gr-app-types.ts
@@ -74,8 +74,8 @@ export interface AppElementPluginScreenParams { view: GerritView.PLUGIN_SCREEN; - plugin: string; - screen: string; + plugin?: string; + screen?: string; } export interface AppElementSearchParam { @@ -122,7 +122,7 @@ // Otherwise, the compiler reports an error when the code tries to use // the property 'view' of AppElementParams. view?: never; - justRegistered: true; + justRegistered: boolean; } export type AppElementParams = @@ -136,5 +136,11 @@ | AppElementSearchParam | AppElementSettingsParam | AppElementAgreementParam - | AppElementJustRegisteredParams - | AppElementDiffViewParam; + | AppElementDiffViewParam + | AppElementJustRegisteredParams; + +export function isAppElementJustRegisteredParams( + p: AppElementParams +): p is AppElementJustRegisteredParams { + return (p as AppElementJustRegisteredParams).justRegistered !== undefined; +}
diff --git a/polygerrit-ui/app/elements/gr-app.ts b/polygerrit-ui/app/elements/gr-app.ts index 2801296..f19931f 100644 --- a/polygerrit-ui/app/elements/gr-app.ts +++ b/polygerrit-ui/app/elements/gr-app.ts
@@ -15,16 +15,11 @@ * limitations under the License. */ -import {safeTypesBridge} from '../utils/safe-types-util.js'; - -// We need to use goog.declareModuleId internally in google for TS-imports-JS -// case. To avoid errors when goog is not available, the empty implementation is -// added. -window.goog = window.goog || {declareModuleId(name) {}}; -import './gr-app-init.js'; -import './font-roboto-local-loader.js'; +import {safeTypesBridge} from '../utils/safe-types-util'; +import './gr-app-init'; +import './font-roboto-local-loader'; // Sets up global Polymer variable, because plugins requires it. -import '../scripts/bundled-polymer.js'; +import '../scripts/bundled-polymer'; /** * setCancelSyntheticClickEvents is set to true by @@ -32,38 +27,37 @@ * on older touch device. * See https://github.com/Polymer/polymer/issues/5289 */ -import {setPassiveTouchGestures, setCancelSyntheticClickEvents} from '@polymer/polymer/lib/utils/settings.js'; +import { + setPassiveTouchGestures, + setCancelSyntheticClickEvents, +} from '@polymer/polymer/lib/utils/settings'; setCancelSyntheticClickEvents(false); setPassiveTouchGestures(true); -import 'polymer-resin/standalone/polymer-resin.js'; -import {initGlobalVariables} from './gr-app-global-var-init.js'; -import './gr-app-element.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-app_html.js'; -import {initGerritPluginApi} from './shared/gr-js-api-interface/gr-gerrit.js'; -import {appContext} from '../services/app-context.js'; +import {initGlobalVariables} from './gr-app-global-var-init'; +import './gr-app-element'; +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-app_html'; +import {initGerritPluginApi} from './shared/gr-js-api-interface/gr-gerrit'; +import {customElement} from '@polymer/decorators'; +import {installPolymerResin} from '../scripts/polymer-resin-install'; -security.polymer_resin.install({ - allowedIdentifierPrefixes: [''], - reportHandler: security.polymer_resin.CONSOLE_LOGGING_REPORT_HANDLER, - safeTypesBridge, -}); +installPolymerResin(safeTypesBridge); -/** @extends PolymerElement */ -class GrApp extends GestureEventListeners( - LegacyElementMixin( - PolymerElement)) { - // When you are converting gr-app.js to ts, implement interface AppElement - // from the gr-app-types.ts - static get template() { return htmlTemplate; } - - static get is() { return 'gr-app'; } +@customElement('gr-app') +class GrApp extends GestureEventListeners(LegacyElementMixin(PolymerElement)) { + static get template() { + return htmlTemplate; + } } -customElements.define(GrApp.is, GrApp); +declare global { + interface HTMLElementTagNameMap { + 'gr-app': GrApp; + } +} initGlobalVariables(); -initGerritPluginApi(appContext); +initGerritPluginApi();
diff --git a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper.ts b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper.ts index 10335b8..02fcdec 100644 --- a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper.ts +++ b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper.ts
@@ -15,10 +15,6 @@ * limitations under the License. */ -export interface EventWithPath extends Event { - path?: HTMLElement[]; -} - export interface ListenOptions { event?: string; capture?: boolean; @@ -71,11 +67,11 @@ _listen( container: HTMLElement, callback: (event: Event) => boolean, - opt_options?: ListenOptions | null + options?: ListenOptions | null ) { - const capture = opt_options?.capture; - const event = opt_options?.event || 'click'; - const handler = (e: EventWithPath) => { + const capture = options?.capture; + const event = options?.event || 'click'; + const handler = (e: Event) => { if (!e.path) return; if (e.path.indexOf(this.element) !== -1) { let mayContinue = true;
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts index cd0d7b8..9f9840b 100644 --- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts +++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
@@ -67,7 +67,7 @@ import {GrGpgEditor} from '../gr-gpg-editor/gr-gpg-editor'; import {GerritView} from '../../core/gr-navigation/gr-navigation'; import {GrEmailEditor} from '../gr-email-editor/gr-email-editor'; -import {CustomKeyboardEvent} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; +import {CustomKeyboardEvent} from '../../../types/events'; const PREFS_SECTION_FIELDS: Array<keyof PreferencesInput> = [ 'changes_per_page',
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.ts b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.ts index 033b617..668ea1b 100644 --- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.ts +++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.ts
@@ -24,15 +24,12 @@ import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin'; import {PolymerElement} from '@polymer/polymer/polymer-element'; import {htmlTemplate} from './gr-autocomplete_html'; -import { - KeyboardShortcutMixin, - CustomKeyboardEvent, -} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; +import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; import {property, customElement, observe} from '@polymer/decorators'; import {GrAutocompleteDropdown} from '../gr-autocomplete-dropdown/gr-autocomplete-dropdown'; import {GrCursorManager} from '../gr-cursor-manager/gr-cursor-manager'; -import {EventWithPath} from '../../plugins/gr-event-helper/gr-event-helper'; import {PaperInputElementExt} from '../../../types/types'; +import {CustomKeyboardEvent} from '../../../types/events'; const TOKENIZE_REGEX = /(?:[^\s"]+|"[^"]*")+/g; const DEBOUNCE_WAIT_MS = 200; @@ -452,7 +449,7 @@ } } - _handleBodyClick(e: EventWithPath) { + _handleBodyClick(e: Event) { const eventPath = e.path; if (!eventPath) return; for (let i = 0; i < eventPath.length; i++) {
diff --git a/polygerrit-ui/app/elements/shared/gr-button/gr-button.ts b/polygerrit-ui/app/elements/shared/gr-button/gr-button.ts index 4d75138..7a6ce2c 100644 --- a/polygerrit-ui/app/elements/shared/gr-button/gr-button.ts +++ b/polygerrit-ui/app/elements/shared/gr-button/gr-button.ts
@@ -22,13 +22,11 @@ import {customElement, property, computed, observe} from '@polymer/decorators'; import {htmlTemplate} from './gr-button_html'; import {TooltipMixin} from '../../../mixins/gr-tooltip-mixin/gr-tooltip-mixin'; -import { - KeyboardShortcutMixin, - CustomKeyboardEvent, -} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; +import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; import {PolymerEvent, getEventPath} from '../../../utils/dom-util'; import {appContext} from '../../../services/app-context'; import {ReportingService} from '../../../services/gr-reporting/gr-reporting'; +import {CustomKeyboardEvent} from '../../../types/events'; declare global { interface HTMLElementTagNameMap {
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts index a9df3f9..878c01c 100644 --- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts +++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
@@ -23,10 +23,7 @@ import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin'; import {PolymerElement} from '@polymer/polymer/polymer-element'; import {htmlTemplate} from './gr-comment-thread_html'; -import { - CustomKeyboardEvent, - KeyboardShortcutMixin, -} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; +import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; import { isDraft, isRobot, @@ -52,6 +49,7 @@ import {GrComment} from '../gr-comment/gr-comment'; import {PolymerDeepPropertyChange} from '@polymer/polymer/interfaces'; import {GrStorage, StorageLocation} from '../gr-storage/gr-storage'; +import {CustomKeyboardEvent} from '../../../types/events'; const UNRESOLVED_EXPAND_COUNT = 5; const NEWLINE_PATTERN = /\n/g;
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts index 9a1d789..e4d520f 100644 --- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts +++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
@@ -59,6 +59,7 @@ UIDraft, UIRobot, } from '../../../utils/comment-util'; +import {OpenFixPreviewEventDetail} from '../../../types/events'; const STORAGE_DEBOUNCE_INTERVAL = 400; const TOAST_DEBOUNCE_INTERVAL = 200; @@ -103,11 +104,6 @@ }; } -export interface CommentEventDetail { - patchNum?: PatchSetNum; - comment?: UIComment; -} - @customElement('gr-comment') export class GrComment extends KeyboardShortcutMixin( GestureEventListeners(LegacyElementMixin(PolymerElement)) @@ -506,7 +502,7 @@ ); } - _getEventPayload(): CommentEventDetail { + _getEventPayload(): OpenFixPreviewEventDetail { return {comment: this.comment, patchNum: this.patchNum}; }
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts index edadfba..9e1a5bf 100644 --- a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts +++ b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts
@@ -21,15 +21,13 @@ 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 { - CustomKeyboardEvent, - KeyboardShortcutMixin, -} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; +import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin'; import {customElement, property} from '@polymer/decorators'; import {htmlTemplate} from './gr-editable-label_html'; import {IronDropdownElement} from '@polymer/iron-dropdown/iron-dropdown'; import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom'; import {PaperInputElementExt} from '../../../types/types'; +import {CustomKeyboardEvent} from '../../../types/events'; const AWAIT_MAX_ITERS = 10; const AWAIT_STEP = 5;
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper.ts b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper.ts index eee48d2..6d93604 100644 --- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper.ts +++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper.ts
@@ -32,6 +32,7 @@ RequestPayload, } from '../../../../types/common'; import {HttpMethod} from '../../../../constants/constants'; +import {RpcLogEventDetail} from '../../../../types/events'; const JSON_PREFIX = ")]}'"; @@ -270,9 +271,15 @@ ].join(' ') ); if (req.anonymizedUrl) { + const detail: RpcLogEventDetail = { + status, + method, + elapsed, + anonymizedUrl: req.anonymizedUrl, + }; this.dispatchEvent( new CustomEvent('rpc-log', { - detail: {status, method, elapsed, anonymizedUrl: req.anonymizedUrl}, + detail, composed: true, bubbles: true, })