Convert files to typescript
The change converts the following files to typescript:
* elements/core/gr-router/gr-router.ts
Change-Id: I827da7e6ed664b3d2188a849b863cf53c5844758
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 8c0e4d3..74de20d 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -14,16 +14,57 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-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 {page} from '../../../utils/page-wrapper-utils.js';
-import {htmlTemplate} from './gr-router_html.js';
-import {encodeURL, getBaseUrl} from '../../../utils/url-util.js';
-import {GerritNav} from '../gr-navigation/gr-navigation.js';
-import {appContext} from '../../../services/app-context.js';
-import {patchNumEquals} from '../../../utils/patch-set-util.js';
+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 {
+ page,
+ PageContext,
+ PageNextCallback,
+} from '../../../utils/page-wrapper-utils';
+import {htmlTemplate} from './gr-router_html';
+import {encodeURL, getBaseUrl} from '../../../utils/url-util';
+import {
+ DashboardSection,
+ GenerateUrlChangeViewParameters,
+ GenerateUrlDashboardViewParameters,
+ GenerateUrlDiffViewParameters,
+ GenerateUrlEditViewParameters,
+ GenerateUrlGroupViewParameters,
+ GenerateUrlParameters,
+ GenerateUrlRepoViewParameters,
+ GenerateUrlSearchViewParameters,
+ GenerateWebLinksChangeParameters,
+ GenerateWebLinksFileParameters,
+ GenerateWebLinksParameters,
+ GenerateWebLinksPatchsetParameters,
+ GerritView,
+ isGenerateUrlDiffViewParameters,
+ RepoDetailView,
+ WeblinkType,
+ GroupDetailView,
+ GerritNav,
+ GeneratedWebLink,
+} from '../gr-navigation/gr-navigation';
+import {appContext} from '../../../services/app-context';
+import {patchNumEquals} from '../../../utils/patch-set-util';
+import {customElement, property} from '@polymer/decorators';
+import {assertNever} from '../../../utils/common-util';
+import {
+ GroupId,
+ NumericChangeId,
+ PatchSetNum,
+ RepoName,
+ ServerInfo,
+ UrlEncodedCommentId,
+} from '../../../types/common';
+import {GrRestApiInterface} from '../../shared/gr-rest-api-interface/gr-rest-api-interface';
+import {
+ AppElement,
+ AppElementParams,
+ AppElementAgreementParam,
+} from '../../gr-app-types';
const RoutePattern = {
ROOT: '/',
@@ -93,13 +134,12 @@
BRANCH_LIST_OFFSET: /^\/admin\/repos\/(.+),branches(,(.+))?$/,
BRANCH_LIST_FILTER: '/admin/repos/:repo,branches/q/filter::filter',
BRANCH_LIST_FILTER_OFFSET:
- '/admin/repos/:repo,branches/q/filter::filter,:offset',
+ '/admin/repos/:repo,branches/q/filter::filter,:offset',
// Matches /admin/repos/<repo>,tags[,<offset>].
TAG_LIST_OFFSET: /^\/admin\/repos\/(.+),tags(,(.+))?$/,
TAG_LIST_FILTER: '/admin/repos/:repo,tags/q/filter::filter',
- TAG_LIST_FILTER_OFFSET:
- '/admin/repos/:repo,tags/q/filter::filter,:offset',
+ TAG_LIST_FILTER_OFFSET: '/admin/repos/:repo,tags/q/filter::filter,:offset',
PLUGINS: /^\/plugins\/(.+)$/,
@@ -213,113 +253,148 @@
}
// Setup listeners outside of the router component initialization.
-(function() {
+(function () {
window.addEventListener('WebComponentsReady', () => {
appContext.reportingService.timeEnd('WebComponentsReady');
});
})();
-/**
- * @extends PolymerElement
- */
-class GrRouter extends GestureEventListeners(
- LegacyElementMixin(PolymerElement)) {
- static get template() { return htmlTemplate; }
+export interface GrRouter {
+ $: {
+ restAPI: GrRestApiInterface;
+ };
+}
- static get is() { return 'gr-router'; }
+export interface PageContextWithQueryMap extends PageContext {
+ queryMap: Map<string, string> | URLSearchParams;
+}
- static get properties() {
- return {
- _app: {
- type: Object,
- value: app,
- },
- _isRedirecting: Boolean,
- // This variable is to differentiate between internal navigation (false)
- // and for first navigation in app after loaded from server (true).
- _isInitialLoad: {
- type: Boolean,
- value: true,
- },
- };
+type QueryStringItem = [string, string]; // [key, value]
+
+type GenerateUrlLegacyChangeViewParameters = Omit<
+ GenerateUrlChangeViewParameters,
+ 'project'
+>;
+type GenerateUrlLegacyDiffViewParameters = Omit<
+ GenerateUrlDiffViewParameters,
+ 'project'
+>;
+
+interface PatchRangeParams {
+ patchNum?: PatchSetNum | null;
+ basePatchNum?: PatchSetNum | null;
+}
+
+@customElement('gr-router')
+export class GrRouter extends GestureEventListeners(
+ LegacyElementMixin(PolymerElement)
+) {
+ static get template() {
+ return htmlTemplate;
}
+ @property({type: Object})
+ readonly _app = app;
+
+ @property({type: Boolean})
+ _isRedirecting?: boolean;
+
+ // This variable is to differentiate between internal navigation (false)
+ // and for first navigation in app after loaded from server (true).
+ @property({type: Boolean})
+ _isInitialLoad = true;
+
+ private readonly reporting = appContext.reportingService;
+
constructor() {
super();
- this.reporting = appContext.reportingService;
}
start() {
- if (!this._app) { return; }
+ if (!this._app) {
+ return;
+ }
this._startRouter();
}
- _setParams(params) {
+ _setParams(params: AppElementParams | GenerateUrlParameters) {
this._appElement().params = params;
}
- _appElement() {
+ _appElement(): AppElement {
// In Polymer2 you have to reach through the shadow root of the app
// element. This obviously breaks encapsulation.
// TODO(brohlfs): Make this more elegant, e.g. by exposing app-element
// explicitly in app, or by delegating to it.
- return document.getElementById('app-element') ||
- document.getElementById('app').shadowRoot.getElementById(
- 'app-element');
+
+ // It is expected that application has a GrAppElement(id=='app-element')
+ // at the document level or inside the shadow root of the GrApp (id='app')
+ // element.
+ return (document.getElementById('app-element') ||
+ document
+ .getElementById('app')!
+ .shadowRoot!.getElementById('app-element')!) as AppElement;
}
- _redirect(url) {
+ _redirect(url: string) {
this._isRedirecting = true;
page.redirect(url);
}
/**
- * @param {!Object} params
- * @return {string}
+ * @param params
+ * @return
*/
- _generateUrl(params) {
+ _generateUrl(params: GenerateUrlParameters) {
const base = getBaseUrl();
let url = '';
- const Views = GerritNav.View;
- if (params.view === Views.SEARCH) {
+ if (params.view === GerritView.SEARCH) {
url = this._generateSearchUrl(params);
- } else if (params.view === Views.CHANGE) {
+ } else if (params.view === GerritView.CHANGE) {
url = this._generateChangeUrl(params);
- } else if (params.view === Views.DASHBOARD) {
+ } else if (params.view === GerritView.DASHBOARD) {
url = this._generateDashboardUrl(params);
- } else if (params.view === Views.DIFF || params.view === Views.EDIT) {
+ } else if (
+ params.view === GerritView.DIFF ||
+ params.view === GerritView.EDIT
+ ) {
url = this._generateDiffOrEditUrl(params);
- } else if (params.view === Views.GROUP) {
+ } else if (params.view === GerritView.GROUP) {
url = this._generateGroupUrl(params);
- } else if (params.view === Views.REPO) {
+ } else if (params.view === GerritView.REPO) {
url = this._generateRepoUrl(params);
- } else if (params.view === Views.ROOT) {
+ } else if (params.view === GerritView.ROOT) {
url = '/';
- } else if (params.view === Views.SETTINGS) {
- url = this._generateSettingsUrl(params);
+ } else if (params.view === GerritView.SETTINGS) {
+ url = this._generateSettingsUrl();
} else {
- throw new Error('Can\'t generate');
+ assertNever(params, "Can't generate");
}
return base + url;
}
- _generateWeblinks(params) {
- const type = params.type;
- switch (type) {
- case GerritNav.WeblinkType.FILE:
+ _generateWeblinks(
+ params: GenerateWebLinksParameters
+ ): GeneratedWebLink[] | GeneratedWebLink {
+ switch (params.type) {
+ case WeblinkType.FILE:
return this._getFileWebLinks(params);
- case GerritNav.WeblinkType.CHANGE:
+ case WeblinkType.CHANGE:
return this._getChangeWeblinks(params);
- case GerritNav.WeblinkType.PATCHSET:
+ case WeblinkType.PATCHSET:
return this._getPatchSetWeblink(params);
default:
- console.warn(`Unsupported weblink ${type}!`);
+ console.warn(`Unsupported weblink ${(params as any).type}!`);
+ // TODO(TS): use assertNever(params.type)
+ return [];
}
}
- _getPatchSetWeblink(params) {
+ _getPatchSetWeblink(
+ params: GenerateWebLinksPatchsetParameters
+ ): GeneratedWebLink {
const {commit, options} = params;
const {weblinks, config} = options || {};
const name = commit && commit.slice(0, 7);
@@ -331,62 +406,70 @@
}
}
- _firstCodeBrowserWeblink(weblinks) {
+ _firstCodeBrowserWeblink(weblinks: GeneratedWebLink[]) {
// This is an ordered allowed list of web link types that provide direct
// links to the commit in the url property.
const codeBrowserLinks = ['gitiles', 'browse', 'gitweb'];
for (let i = 0; i < codeBrowserLinks.length; i++) {
- const weblink =
- weblinks.find(weblink => weblink.name === codeBrowserLinks[i]);
- if (weblink) { return weblink; }
+ const weblink = weblinks.find(
+ weblink => weblink.name === codeBrowserLinks[i]
+ );
+ if (weblink) {
+ return weblink;
+ }
}
return null;
}
- _getBrowseCommitWeblink(weblinks, config) {
- if (!weblinks) { return null; }
+ _getBrowseCommitWeblink(weblinks?: GeneratedWebLink[], config?: ServerInfo) {
+ if (!weblinks) {
+ return null;
+ }
let weblink;
// Use primary weblink if configured and exists.
if (config && config.gerrit && config.gerrit.primary_weblink_name) {
- weblink = weblinks.find(
- weblink => weblink.name === config.gerrit.primary_weblink_name
- );
+ const primaryWeblinkName = config.gerrit.primary_weblink_name;
+ weblink = weblinks.find(weblink => weblink.name === primaryWeblinkName);
}
if (!weblink) {
weblink = this._firstCodeBrowserWeblink(weblinks);
}
- if (!weblink) { return null; }
+ if (!weblink) {
+ return null;
+ }
return weblink;
}
- _getChangeWeblinks({repo, commit, options: {weblinks, config}}) {
+ _getChangeWeblinks(
+ params: GenerateWebLinksChangeParameters
+ ): GeneratedWebLink[] {
+ const weblinks = params.options?.weblinks;
+ const config = params.options?.config;
if (!weblinks || !weblinks.length) return [];
const commitWeblink = this._getBrowseCommitWeblink(weblinks, config);
- return weblinks.filter(weblink =>
- !commitWeblink ||
- !commitWeblink.name ||
- weblink.name !== commitWeblink.name);
+ return weblinks.filter(
+ weblink =>
+ !commitWeblink ||
+ !commitWeblink.name ||
+ weblink.name !== commitWeblink.name
+ );
}
- _getFileWebLinks({repo, commit, file, options: {weblinks}}) {
- return weblinks;
+ _getFileWebLinks(params: GenerateWebLinksFileParameters): GeneratedWebLink[] {
+ return params.options?.weblinks || [];
}
- /**
- * @param {!Object} params
- * @return {string}
- */
- _generateSearchUrl(params) {
+ _generateSearchUrl(params: GenerateUrlSearchViewParameters) {
let offsetExpr = '';
if (params.offset && params.offset > 0) {
- offsetExpr = ',' + params.offset;
+ offsetExpr = `,${params.offset}`;
}
if (params.query) {
return '/q/' + encodeURL(params.query, true) + offsetExpr;
}
- const operators = [];
+ const operators: string[] = [];
if (params.owner) {
operators.push('owner:' + encodeURL(params.owner, false));
}
@@ -400,32 +483,32 @@
operators.push('topic:"' + encodeURL(params.topic, false) + '"');
}
if (params.hashtag) {
- operators.push('hashtag:"' +
- encodeURL(params.hashtag.toLowerCase(), false) + '"');
+ operators.push(
+ 'hashtag:"' + encodeURL(params.hashtag.toLowerCase(), false) + '"'
+ );
}
if (params.statuses) {
if (params.statuses.length === 1) {
- operators.push(
- 'status:' + encodeURL(params.statuses[0], false));
+ operators.push('status:' + encodeURL(params.statuses[0], false));
} else if (params.statuses.length > 1) {
operators.push(
- '(' +
- params.statuses.map(s => `status:${encodeURL(s, false)}`)
- .join(' OR ') +
- ')');
+ '(' +
+ params.statuses
+ .map(s => `status:${encodeURL(s, false)}`)
+ .join(' OR ') +
+ ')'
+ );
}
}
return '/q/' + operators.join('+') + offsetExpr;
}
- /**
- * @param {!Object} params
- * @return {string}
- */
- _generateChangeUrl(params) {
+ _generateChangeUrl(params: GenerateUrlChangeViewParameters) {
let range = this._getPatchRangeExpression(params);
- if (range.length) { range = '/' + range; }
+ if (range.length) {
+ range = '/' + range;
+ }
let suffix = `${range}`;
if (params.querystring) {
suffix += '?' + params.querystring;
@@ -443,16 +526,14 @@
}
}
- /**
- * @param {!Object} params
- * @return {string}
- */
- _generateDashboardUrl(params) {
- const repoName = params.repo || params.project || null;
+ _generateDashboardUrl(params: GenerateUrlDashboardViewParameters) {
+ const repoName = params.repo || params.project || undefined;
if (params.sections) {
// Custom dashboard.
- const queryParams = this._sectionsToEncodedParams(params.sections,
- repoName);
+ const queryParams = this._sectionsToEncodedParams(
+ params.sections,
+ repoName
+ );
if (params.title) {
queryParams.push('title=' + encodeURIComponent(params.title));
}
@@ -468,42 +549,44 @@
}
}
- /**
- * @param {!Array<!{name: string, query: string}>} sections
- * @param {string=} opt_repoName
- * @return {!Array<string>}
- */
- _sectionsToEncodedParams(sections, opt_repoName) {
+ _sectionsToEncodedParams(sections: DashboardSection[], repoName?: RepoName) {
return sections.map(section => {
// If there is a repo name provided, make sure to substitute it into the
// ${repo} (or legacy ${project}) query tokens.
- const query = opt_repoName ?
- section.query.replace(REPO_TOKEN_PATTERN, opt_repoName) :
- section.query;
- return encodeURIComponent(section.name) + '=' +
- encodeURIComponent(query);
+ const query = repoName
+ ? section.query.replace(REPO_TOKEN_PATTERN, repoName)
+ : section.query;
+ return encodeURIComponent(section.name) + '=' + encodeURIComponent(query);
});
}
/**
- * @param {!Object} params
- * @return {string}
+ * @param params
+ * @return
*/
- _generateDiffOrEditUrl(params) {
+ _generateDiffOrEditUrl(
+ params: GenerateUrlDiffViewParameters | GenerateUrlEditViewParameters
+ ) {
let range = this._getPatchRangeExpression(params);
- if (range.length) { range = '/' + range; }
+ if (range.length) {
+ range = '/' + range;
+ }
let suffix = `${range}/${encodeURL(params.path || '', true)}`;
- if (params.view === GerritNav.View.EDIT) { suffix += ',edit'; }
+ if (params.view === GerritView.EDIT) {
+ suffix += ',edit';
+ }
if (params.lineNum) {
suffix += '#';
- if (params.leftSide) { suffix += 'b'; }
+ if (isGenerateUrlDiffViewParameters(params) && params.leftSide) {
+ suffix += 'b';
+ }
suffix += params.lineNum;
}
- if (params.commentId) {
+ if (isGenerateUrlDiffViewParameters(params) && params.commentId) {
suffix = `/comment/${params.commentId}` + suffix;
}
@@ -515,45 +598,33 @@
}
}
- /**
- * @param {!Object} params
- * @return {string}
- */
- _generateGroupUrl(params) {
- let url = `/admin/groups/${encodeURL(params.groupId + '', true)}`;
- if (params.detail === GerritNav.GroupDetailView.MEMBERS) {
+ _generateGroupUrl(params: GenerateUrlGroupViewParameters) {
+ let url = `/admin/groups/${encodeURL(`${params.groupId}`, true)}`;
+ if (params.detail === GroupDetailView.MEMBERS) {
url += ',members';
- } else if (params.detail === GerritNav.GroupDetailView.LOG) {
+ } else if (params.detail === GroupDetailView.LOG) {
url += ',audit-log';
}
return url;
}
- /**
- * @param {!Object} params
- * @return {string}
- */
- _generateRepoUrl(params) {
- let url = `/admin/repos/${encodeURL(params.repoName + '', true)}`;
- if (params.detail === GerritNav.RepoDetailView.ACCESS) {
+ _generateRepoUrl(params: GenerateUrlRepoViewParameters) {
+ let url = `/admin/repos/${encodeURL(`${params.repoName}`, true)}`;
+ if (params.detail === RepoDetailView.ACCESS) {
url += ',access';
- } else if (params.detail === GerritNav.RepoDetailView.BRANCHES) {
+ } else if (params.detail === RepoDetailView.BRANCHES) {
url += ',branches';
- } else if (params.detail === GerritNav.RepoDetailView.TAGS) {
+ } else if (params.detail === RepoDetailView.TAGS) {
url += ',tags';
- } else if (params.detail === GerritNav.RepoDetailView.COMMANDS) {
+ } else if (params.detail === RepoDetailView.COMMANDS) {
url += ',commands';
- } else if (params.detail === GerritNav.RepoDetailView.DASHBOARDS) {
+ } else if (params.detail === RepoDetailView.DASHBOARDS) {
url += ',dashboards';
}
return url;
}
- /**
- * @param {!Object} params
- * @return {string}
- */
- _generateSettingsUrl(params) {
+ _generateSettingsUrl() {
return '/settings';
}
@@ -561,62 +632,73 @@
* Given an object of parameters, potentially including a `patchNum` or a
* `basePatchNum` or both, return a string representation of that range. If
* no range is indicated in the params, the empty string is returned.
- *
- * @param {!Object} params
- * @return {string}
*/
- _getPatchRangeExpression(params) {
+ _getPatchRangeExpression(params: PatchRangeParams) {
let range = '';
- if (params.patchNum) { range = '' + params.patchNum; }
- if (params.basePatchNum) { range = params.basePatchNum + '..' + range; }
+ if (params.patchNum) {
+ range = `${params.patchNum}`;
+ }
+ if (params.basePatchNum) {
+ range = `${params.basePatchNum}..${range}`;
+ }
return range;
}
/**
* Given a set of params without a project, gets the project from the rest
* API project lookup and then sets the app params.
- *
- * @param {?Object} params
*/
- _normalizeLegacyRouteParams(params) {
- if (!params.changeNum) { return Promise.resolve(); }
+ _normalizeLegacyRouteParams(
+ params: Readonly<
+ | GenerateUrlLegacyChangeViewParameters
+ | GenerateUrlLegacyDiffViewParameters
+ >
+ ) {
+ if (!params.changeNum) {
+ return Promise.resolve();
+ }
- return this.$.restAPI.getFromProjectLookup(params.changeNum)
- .then(project => {
- // Show a 404 and terminate if the lookup request failed. Attempting
- // to redirect after failing to get the project loops infinitely.
- if (!project) {
- this._show404();
- return;
- }
-
- params.project = project;
- this._normalizePatchRangeParams(params);
- this._redirect(this._generateUrl(params));
- });
+ return this.$.restAPI
+ .getFromProjectLookup(params.changeNum)
+ .then(project => {
+ // Show a 404 and terminate if the lookup request failed. Attempting
+ // to redirect after failing to get the project loops infinitely.
+ if (!project) {
+ this._show404();
+ return;
+ }
+ const updatedParams:
+ | GenerateUrlChangeViewParameters
+ | GenerateUrlDiffViewParameters = {...params, project};
+ this._normalizePatchRangeParams(updatedParams);
+ this._redirect(this._generateUrl(updatedParams));
+ });
}
/**
* Normalizes the params object, and determines if the URL needs to be
* modified to fit the proper schema.
*
- * @param {*} params
- * @return {boolean} whether or not the URL needs to be upgraded.
+ * @param params
+ * @return whether or not the URL needs to be upgraded.
*/
- _normalizePatchRangeParams(params) {
- const hasBasePatchNum = params.basePatchNum !== null &&
- params.basePatchNum !== undefined;
- const hasPatchNum = params.patchNum !== null &&
- params.patchNum !== undefined;
+ _normalizePatchRangeParams(params: PatchRangeParams) {
+ if (params.basePatchNum === null || params.basePatchNum === undefined) {
+ return false;
+ }
+ const hasPatchNum =
+ params.patchNum !== null && params.patchNum !== undefined;
let needsRedirect = false;
// Diffing a patch against itself is invalid, so if the base and revision
// patches are equal clear the base.
- if (hasBasePatchNum &&
- patchNumEquals(params.basePatchNum, params.patchNum)) {
+ if (
+ params.patchNum &&
+ patchNumEquals(params.basePatchNum, params.patchNum)
+ ) {
needsRedirect = true;
params.basePatchNum = null;
- } else if (hasBasePatchNum && !hasPatchNum) {
+ } else if (!hasPatchNum) {
// Regexes set basePatchNum instead of patchNum when only one is
// specified. Redirect is not needed in this case.
params.patchNum = params.basePatchNum;
@@ -629,12 +711,11 @@
* Redirect the user to login using the given return-URL for redirection
* after authentication success.
*
- * @param {string} returnUrl
+ * @param returnUrl
*/
- _redirectToLogin(returnUrl) {
+ _redirectToLogin(returnUrl: string) {
const basePath = getBaseUrl() || '';
- page(
- '/login/' + encodeURIComponent(returnUrl.substring(basePath.length)));
+ page('/login/' + encodeURIComponent(returnUrl.substring(basePath.length)));
}
/**
@@ -642,17 +723,17 @@
* is parsed to have a hash of "b" rather than "b#c". Instead, this method
* parses hashes correctly. Will return an empty string if there is no hash.
*
- * @param {!string} canonicalPath
- * @return {!string} Everything after the first '#' ("a#b#c" -> "b#c").
+ * @return Everything after the first '#' ("a#b#c" -> "b#c").
*/
- _getHashFromCanonicalPath(canonicalPath) {
- return canonicalPath.split('#').slice(1)
- .join('#');
+ _getHashFromCanonicalPath(canonicalPath: string) {
+ return canonicalPath.split('#').slice(1).join('#');
}
- _parseLineAddress(hash) {
+ _parseLineAddress(hash: string) {
const match = hash.match(LINE_ADDRESS_PATTERN);
- if (!match) { return null; }
+ if (!match) {
+ return null;
+ }
return {
leftSide: !!match[1],
lineNum: parseInt(match[2], 10),
@@ -664,11 +745,10 @@
* resolves if the user is logged in. If the user us not logged in, the
* promise is rejected and the page is redirected to the login flow.
*
- * @param {!Object} data The parsed route data.
- * @return {!Promise<!Object>} A promise yielding the original route data
- * (if it resolves).
+ * @return A promise yielding the original route data
+ * (if it resolves).
*/
- _redirectIfNotLoggedIn(data) {
+ _redirectIfNotLoggedIn(data: PageContext) {
return this.$.restAPI.getLoggedIn().then(loggedIn => {
if (loggedIn) {
return Promise.resolve();
@@ -680,13 +760,15 @@
}
/** Page.js middleware that warms the REST API's logged-in cache line. */
- _loadUserMiddleware(ctx, next) {
- this.$.restAPI.getLoggedIn().then(() => { next(); });
+ _loadUserMiddleware(_: PageContext, next: PageNextCallback) {
+ this.$.restAPI.getLoggedIn().then(() => {
+ next();
+ });
}
/** Page.js middleware that try parse the querystring into queryMap. */
- _queryStringMiddleware(ctx, next) {
- let queryMap = new Map();
+ _queryStringMiddleware(ctx: PageContext, next: PageNextCallback) {
+ let queryMap: Map<string, string> | URLSearchParams = new Map();
if (ctx.querystring) {
// https://caniuse.com/#search=URLSearchParams
if (window.URLSearchParams) {
@@ -695,38 +777,46 @@
queryMap = new Map(this._parseQueryString(ctx.querystring));
}
}
- ctx.queryMap = queryMap;
+ (ctx as PageContextWithQueryMap).queryMap = queryMap;
next();
}
/**
* Map a route to a method on the router.
*
- * @param {!string|!RegExp} pattern The page.js pattern for the route.
- * @param {!string} handlerName The method name for the handler. If the
- * route is matched, the handler will be executed with `this` referring
- * to the component. Its return value will be discarded so that it does
- * not interfere with page.js.
- * @param {?boolean=} opt_authRedirect If true, then auth is checked before
- * executing the handler. If the user is not logged in, it will redirect
- * to the login flow and the handler will not be executed. The login
- * redirect specifies the matched URL to be used after successfull auth.
+ * @param pattern The page.js pattern for the route.
+ * @param handlerName The method name for the handler. If the
+ * route is matched, the handler will be executed with `this` referring
+ * to the component. Its return value will be discarded so that it does
+ * not interfere with page.js.
+ * @param authRedirect If true, then auth is checked before
+ * executing the handler. If the user is not logged in, it will redirect
+ * to the login flow and the handler will not be executed. The login
+ * redirect specifies the matched URL to be used after successfull auth.
*/
- _mapRoute(pattern, handlerName, opt_authRedirect) {
+ _mapRoute(
+ pattern: string | RegExp,
+ handlerName: keyof GrRouter,
+ authRedirect?: boolean
+ ) {
if (!this[handlerName]) {
- console.error('Attempted to map route to unknown method: ',
- handlerName);
+ console.error('Attempted to map route to unknown method: ', handlerName);
return;
}
- page(pattern,
- (ctx, next) => this._loadUserMiddleware(ctx, next),
- (ctx, next) => this._queryStringMiddleware(ctx, next),
- data => {
- this.reporting.locationChanged(handlerName);
- const promise = opt_authRedirect ?
- this._redirectIfNotLoggedIn(data) : Promise.resolve();
- promise.then(() => { this[handlerName](data); });
+ page(
+ pattern,
+ (ctx, next) => this._loadUserMiddleware(ctx, next),
+ (ctx, next) => this._queryStringMiddleware(ctx, next),
+ data => {
+ this.reporting.locationChanged(handlerName);
+ const promise = authRedirect
+ ? this._redirectIfNotLoggedIn(data)
+ : Promise.resolve();
+ promise.then(() => {
+ this[handlerName](data as PageContextWithQueryMap);
});
+ }
+ );
}
_startRouter() {
@@ -736,19 +826,19 @@
}
GerritNav.setup(
- (url, opt_redirect) => {
- if (opt_redirect) {
- page.redirect(url);
- } else {
- page.show(url);
- }
- },
- this._generateUrl.bind(this),
- params => this._generateWeblinks(params),
- x => x
+ (url, redirect?) => {
+ if (redirect) {
+ page.redirect(url);
+ } else {
+ page.show(url);
+ }
+ },
+ params => this._generateUrl(params),
+ params => this._generateWeblinks(params),
+ x => x
);
- page.exit('*', (ctx, next) => {
+ page.exit('*', (_, next) => {
if (!this._isRedirecting) {
this.reporting.beforeLocationChanged();
}
@@ -772,13 +862,16 @@
// Fire asynchronously so that the URL is changed by the time the event
// is processed.
this.async(() => {
- this.dispatchEvent(new CustomEvent('location-change', {
- detail: {
- hash: window.location.hash,
- pathname: window.location.pathname,
- },
- composed: true, bubbles: true,
- }));
+ this.dispatchEvent(
+ new CustomEvent('location-change', {
+ detail: {
+ hash: window.location.hash,
+ pathname: window.location.pathname,
+ },
+ composed: true,
+ bubbles: true,
+ })
+ );
}, 1);
next();
});
@@ -787,103 +880,150 @@
this._mapRoute(RoutePattern.DASHBOARD, '_handleDashboardRoute');
- this._mapRoute(RoutePattern.CUSTOM_DASHBOARD,
- '_handleCustomDashboardRoute');
+ this._mapRoute(
+ RoutePattern.CUSTOM_DASHBOARD,
+ '_handleCustomDashboardRoute'
+ );
- this._mapRoute(RoutePattern.PROJECT_DASHBOARD,
- '_handleProjectDashboardRoute');
+ this._mapRoute(
+ RoutePattern.PROJECT_DASHBOARD,
+ '_handleProjectDashboardRoute'
+ );
this._mapRoute(RoutePattern.GROUP_INFO, '_handleGroupInfoRoute', true);
- this._mapRoute(RoutePattern.GROUP_AUDIT_LOG, '_handleGroupAuditLogRoute',
- true);
+ this._mapRoute(
+ RoutePattern.GROUP_AUDIT_LOG,
+ '_handleGroupAuditLogRoute',
+ true
+ );
- this._mapRoute(RoutePattern.GROUP_MEMBERS, '_handleGroupMembersRoute',
- true);
+ this._mapRoute(
+ RoutePattern.GROUP_MEMBERS,
+ '_handleGroupMembersRoute',
+ true
+ );
- this._mapRoute(RoutePattern.GROUP_LIST_OFFSET,
- '_handleGroupListOffsetRoute', true);
+ this._mapRoute(
+ RoutePattern.GROUP_LIST_OFFSET,
+ '_handleGroupListOffsetRoute',
+ true
+ );
- this._mapRoute(RoutePattern.GROUP_LIST_FILTER_OFFSET,
- '_handleGroupListFilterOffsetRoute', true);
+ this._mapRoute(
+ RoutePattern.GROUP_LIST_FILTER_OFFSET,
+ '_handleGroupListFilterOffsetRoute',
+ true
+ );
- this._mapRoute(RoutePattern.GROUP_LIST_FILTER,
- '_handleGroupListFilterRoute', true);
+ this._mapRoute(
+ RoutePattern.GROUP_LIST_FILTER,
+ '_handleGroupListFilterRoute',
+ true
+ );
- this._mapRoute(RoutePattern.GROUP_SELF, '_handleGroupSelfRedirectRoute',
- true);
+ this._mapRoute(
+ RoutePattern.GROUP_SELF,
+ '_handleGroupSelfRedirectRoute',
+ true
+ );
this._mapRoute(RoutePattern.GROUP, '_handleGroupRoute', true);
- this._mapRoute(RoutePattern.PROJECT_OLD,
- '_handleProjectsOldRoute');
+ this._mapRoute(RoutePattern.PROJECT_OLD, '_handleProjectsOldRoute');
- this._mapRoute(RoutePattern.REPO_COMMANDS,
- '_handleRepoCommandsRoute', true);
+ this._mapRoute(
+ RoutePattern.REPO_COMMANDS,
+ '_handleRepoCommandsRoute',
+ true
+ );
- this._mapRoute(RoutePattern.REPO_ACCESS,
- '_handleRepoAccessRoute');
+ this._mapRoute(RoutePattern.REPO_ACCESS, '_handleRepoAccessRoute');
- this._mapRoute(RoutePattern.REPO_DASHBOARDS,
- '_handleRepoDashboardsRoute');
+ this._mapRoute(RoutePattern.REPO_DASHBOARDS, '_handleRepoDashboardsRoute');
- this._mapRoute(RoutePattern.BRANCH_LIST_OFFSET,
- '_handleBranchListOffsetRoute');
+ this._mapRoute(
+ RoutePattern.BRANCH_LIST_OFFSET,
+ '_handleBranchListOffsetRoute'
+ );
- this._mapRoute(RoutePattern.BRANCH_LIST_FILTER_OFFSET,
- '_handleBranchListFilterOffsetRoute');
+ this._mapRoute(
+ RoutePattern.BRANCH_LIST_FILTER_OFFSET,
+ '_handleBranchListFilterOffsetRoute'
+ );
- this._mapRoute(RoutePattern.BRANCH_LIST_FILTER,
- '_handleBranchListFilterRoute');
+ this._mapRoute(
+ RoutePattern.BRANCH_LIST_FILTER,
+ '_handleBranchListFilterRoute'
+ );
- this._mapRoute(RoutePattern.TAG_LIST_OFFSET,
- '_handleTagListOffsetRoute');
+ this._mapRoute(RoutePattern.TAG_LIST_OFFSET, '_handleTagListOffsetRoute');
- this._mapRoute(RoutePattern.TAG_LIST_FILTER_OFFSET,
- '_handleTagListFilterOffsetRoute');
+ this._mapRoute(
+ RoutePattern.TAG_LIST_FILTER_OFFSET,
+ '_handleTagListFilterOffsetRoute'
+ );
- this._mapRoute(RoutePattern.TAG_LIST_FILTER,
- '_handleTagListFilterRoute');
+ this._mapRoute(RoutePattern.TAG_LIST_FILTER, '_handleTagListFilterRoute');
- this._mapRoute(RoutePattern.LEGACY_CREATE_GROUP,
- '_handleCreateGroupRoute', true);
+ this._mapRoute(
+ RoutePattern.LEGACY_CREATE_GROUP,
+ '_handleCreateGroupRoute',
+ true
+ );
- this._mapRoute(RoutePattern.LEGACY_CREATE_PROJECT,
- '_handleCreateProjectRoute', true);
+ this._mapRoute(
+ RoutePattern.LEGACY_CREATE_PROJECT,
+ '_handleCreateProjectRoute',
+ true
+ );
- this._mapRoute(RoutePattern.REPO_LIST_OFFSET,
- '_handleRepoListOffsetRoute');
+ this._mapRoute(RoutePattern.REPO_LIST_OFFSET, '_handleRepoListOffsetRoute');
- this._mapRoute(RoutePattern.REPO_LIST_FILTER_OFFSET,
- '_handleRepoListFilterOffsetRoute');
+ this._mapRoute(
+ RoutePattern.REPO_LIST_FILTER_OFFSET,
+ '_handleRepoListFilterOffsetRoute'
+ );
- this._mapRoute(RoutePattern.REPO_LIST_FILTER,
- '_handleRepoListFilterRoute');
+ this._mapRoute(RoutePattern.REPO_LIST_FILTER, '_handleRepoListFilterRoute');
this._mapRoute(RoutePattern.REPO, '_handleRepoRoute');
this._mapRoute(RoutePattern.PLUGINS, '_handlePassThroughRoute');
- this._mapRoute(RoutePattern.PLUGIN_LIST_OFFSET,
- '_handlePluginListOffsetRoute', true);
+ this._mapRoute(
+ RoutePattern.PLUGIN_LIST_OFFSET,
+ '_handlePluginListOffsetRoute',
+ true
+ );
- this._mapRoute(RoutePattern.PLUGIN_LIST_FILTER_OFFSET,
- '_handlePluginListFilterOffsetRoute', true);
+ this._mapRoute(
+ RoutePattern.PLUGIN_LIST_FILTER_OFFSET,
+ '_handlePluginListFilterOffsetRoute',
+ true
+ );
- this._mapRoute(RoutePattern.PLUGIN_LIST_FILTER,
- '_handlePluginListFilterRoute', true);
+ this._mapRoute(
+ RoutePattern.PLUGIN_LIST_FILTER,
+ '_handlePluginListFilterRoute',
+ true
+ );
this._mapRoute(RoutePattern.PLUGIN_LIST, '_handlePluginListRoute', true);
- this._mapRoute(RoutePattern.QUERY_LEGACY_SUFFIX,
- '_handleQueryLegacySuffixRoute');
+ this._mapRoute(
+ RoutePattern.QUERY_LEGACY_SUFFIX,
+ '_handleQueryLegacySuffixRoute'
+ );
this._mapRoute(RoutePattern.QUERY, '_handleQueryRoute');
this._mapRoute(RoutePattern.DIFF_LEGACY_LINENUM, '_handleLegacyLinenum');
- this._mapRoute(RoutePattern.CHANGE_NUMBER_LEGACY,
- '_handleChangeNumberLegacyRoute');
+ this._mapRoute(
+ RoutePattern.CHANGE_NUMBER_LEGACY,
+ '_handleChangeNumberLegacyRoute'
+ );
this._mapRoute(RoutePattern.DIFF_EDIT, '_handleDiffEditRoute', true);
@@ -901,11 +1041,17 @@
this._mapRoute(RoutePattern.AGREEMENTS, '_handleAgreementsRoute', true);
- this._mapRoute(RoutePattern.NEW_AGREEMENTS, '_handleNewAgreementsRoute',
- true);
+ this._mapRoute(
+ RoutePattern.NEW_AGREEMENTS,
+ '_handleNewAgreementsRoute',
+ true
+ );
- this._mapRoute(RoutePattern.SETTINGS_LEGACY,
- '_handleSettingsLegacyRoute', true);
+ this._mapRoute(
+ RoutePattern.SETTINGS_LEGACY,
+ '_handleSettingsLegacyRoute',
+ true
+ );
this._mapRoute(RoutePattern.SETTINGS, '_handleSettingsRoute', true);
@@ -913,21 +1059,29 @@
this._mapRoute(RoutePattern.LOG_IN_OR_OUT, '_handlePassThroughRoute');
- this._mapRoute(RoutePattern.IMPROPERLY_ENCODED_PLUS,
- '_handleImproperlyEncodedPlusRoute');
+ this._mapRoute(
+ RoutePattern.IMPROPERLY_ENCODED_PLUS,
+ '_handleImproperlyEncodedPlusRoute'
+ );
this._mapRoute(RoutePattern.PLUGIN_SCREEN, '_handlePluginScreen');
- this._mapRoute(RoutePattern.DOCUMENTATION_SEARCH_FILTER,
- '_handleDocumentationSearchRoute');
+ this._mapRoute(
+ RoutePattern.DOCUMENTATION_SEARCH_FILTER,
+ '_handleDocumentationSearchRoute'
+ );
// redirects /Documentation/q/* to /Documentation/q/filter:*
- this._mapRoute(RoutePattern.DOCUMENTATION_SEARCH,
- '_handleDocumentationSearchRedirectRoute');
+ this._mapRoute(
+ RoutePattern.DOCUMENTATION_SEARCH,
+ '_handleDocumentationSearchRedirectRoute'
+ );
// Makes sure /Documentation/* links work (doin't return 404)
- this._mapRoute(RoutePattern.DOCUMENTATION,
- '_handleDocumentationRedirectRoute');
+ this._mapRoute(
+ RoutePattern.DOCUMENTATION,
+ '_handleDocumentationRedirectRoute'
+ );
// Note: this route should appear last so it only catches URLs unmatched
// by other patterns.
@@ -937,11 +1091,10 @@
}
/**
- * @param {!Object} data
- * @return {Promise|null} if handling the route involves asynchrony, then a
- * promise is returned. Otherwise, synchronous handling returns null.
+ * @return if handling the route involves asynchrony, then a
+ * promise is returned. Otherwise, synchronous handling returns null.
*/
- _handleRootRoute(data) {
+ _handleRootRoute(data: PageContextWithQueryMap) {
if (data.querystring.match(/^closeAfterLogin/)) {
// Close child window on redirect after login.
window.close();
@@ -980,10 +1133,10 @@
/**
* Decode an application/x-www-form-urlencoded string.
*
- * @param {string} qs The application/x-www-form-urlencoded string.
- * @return {string} The decoded string.
+ * @param qs The application/x-www-form-urlencoded string.
+ * @return The decoded string.
*/
- _decodeQueryString(qs) {
+ _decodeQueryString(qs: string) {
return decodeURIComponent(qs.replace(PLUS_PATTERN, ' '));
}
@@ -991,16 +1144,16 @@
* Parse a query string (e.g. window.location.search) into an array of
* name/value pairs.
*
- * @param {string} qs The application/x-www-form-urlencoded query string.
- * @return {!Array<!Array<string>>} An array of name/value pairs, where each
- * element is a 2-element array.
+ * @param qs The application/x-www-form-urlencoded query string.
+ * @return An array of name/value pairs, where each
+ * element is a 2-element array.
*/
- _parseQueryString(qs) {
+ _parseQueryString(qs: string): Array<QueryStringItem> {
qs = qs.replace(QUESTION_PATTERN, '');
if (!qs) {
return [];
}
- const params = [];
+ const params: Array<[string, string]> = [];
qs.split('&').forEach(param => {
const idx = param.indexOf('=');
let name;
@@ -1021,10 +1174,8 @@
/**
* Handle dashboard routes. These may be user, or project dashboards.
- *
- * @param {!Object} data The parsed route data.
*/
- _handleDashboardRoute(data) {
+ _handleDashboardRoute(data: PageContextWithQueryMap) {
// User dashboard. We require viewing user to be logged in, else we
// redirect to login for self dashboard or simple owner search for
// other user dashboard.
@@ -1037,7 +1188,7 @@
}
} else {
this._setParams({
- view: GerritNav.View.DASHBOARD,
+ view: GerritView.DASHBOARD,
user: data.params[0],
});
}
@@ -1047,31 +1198,37 @@
/**
* Handle custom dashboard routes.
*
- * @param {!Object} data The parsed route data.
- * @param {string=} opt_qs Optional query string associated with the route.
- * If not given, window.location.search is used. (Used by tests).
+ * @param qs Optional query string associated with the route.
+ * If not given, window.location.search is used. (Used by tests).
*/
- _handleCustomDashboardRoute(data, opt_qs) {
- // opt_qs may be provided by a test, and it may have a falsy value
- const qs = opt_qs !== undefined ? opt_qs : window.location.search;
+ _handleCustomDashboardRoute(
+ _: PageContextWithQueryMap,
+ qs: string = window.location.search
+ ) {
const queryParams = this._parseQueryString(qs);
let title = 'Custom Dashboard';
const titleParam = queryParams.find(
- elem => elem[0].toLowerCase() === 'title');
+ elem => elem[0].toLowerCase() === 'title'
+ );
if (titleParam) {
title = titleParam[1];
}
// Dashboards support a foreach param which adds a base query to any
// additional query.
const forEachParam = queryParams.find(
- elem => elem[0].toLowerCase() === 'foreach');
- let forEachQuery = null;
+ elem => elem[0].toLowerCase() === 'foreach'
+ );
+ let forEachQuery: string | null = null;
if (forEachParam) {
forEachQuery = forEachParam[1];
}
const sectionParams = queryParams.filter(
- elem => elem[0] && elem[1] && elem[0].toLowerCase() !== 'title' &&
- elem[0].toLowerCase() !== 'foreach');
+ elem =>
+ elem[0] &&
+ elem[1] &&
+ elem[0].toLowerCase() !== 'title' &&
+ elem[0].toLowerCase() !== 'foreach'
+ );
const sections = sectionParams.map(elem => {
const query = forEachQuery ? `${forEachQuery} ${elem[1]}` : elem[1];
return {
@@ -1083,7 +1240,7 @@
if (sections.length > 0) {
// Custom dashboard view.
this._setParams({
- view: GerritNav.View.DASHBOARD,
+ view: GerritView.DASHBOARD,
user: 'self',
sections,
title,
@@ -1096,50 +1253,50 @@
return Promise.resolve();
}
- _handleProjectDashboardRoute(data) {
- const project = data.params[0];
+ _handleProjectDashboardRoute(data: PageContextWithQueryMap) {
+ const project = data.params[0] as RepoName;
this._setParams({
- view: GerritNav.View.DASHBOARD,
+ view: GerritView.DASHBOARD,
project,
dashboard: decodeURIComponent(data.params[1]),
});
this.reporting.setRepoName(project);
}
- _handleGroupInfoRoute(data) {
+ _handleGroupInfoRoute(data: PageContextWithQueryMap) {
this._redirect('/admin/groups/' + encodeURIComponent(data.params[0]));
}
- _handleGroupSelfRedirectRoute(data) {
+ _handleGroupSelfRedirectRoute(_: PageContextWithQueryMap) {
this._redirect('/settings/#Groups');
}
- _handleGroupRoute(data) {
+ _handleGroupRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.GROUP,
- groupId: data.params[0],
+ view: GerritView.GROUP,
+ groupId: data.params[0] as GroupId,
});
}
- _handleGroupAuditLogRoute(data) {
+ _handleGroupAuditLogRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.GROUP,
- detail: GerritNav.GroupDetailView.LOG,
- groupId: data.params[0],
+ view: GerritView.GROUP,
+ detail: GroupDetailView.LOG,
+ groupId: data.params[0] as GroupId,
});
}
- _handleGroupMembersRoute(data) {
+ _handleGroupMembersRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.GROUP,
- detail: GerritNav.GroupDetailView.MEMBERS,
- groupId: data.params[0],
+ view: GerritView.GROUP,
+ detail: GroupDetailView.MEMBERS,
+ groupId: data.params[0] as GroupId,
});
}
- _handleGroupListOffsetRoute(data) {
+ _handleGroupListOffsetRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.ADMIN,
+ view: GerritView.ADMIN,
adminView: 'gr-admin-group-list',
offset: data.params[1] || 0,
filter: null,
@@ -1147,127 +1304,126 @@
});
}
- _handleGroupListFilterOffsetRoute(data) {
+ _handleGroupListFilterOffsetRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.ADMIN,
+ view: GerritView.ADMIN,
adminView: 'gr-admin-group-list',
- offset: data.params.offset,
- filter: data.params.filter,
+ offset: data.params['offset'],
+ filter: data.params['filter'],
});
}
- _handleGroupListFilterRoute(data) {
+ _handleGroupListFilterRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.ADMIN,
+ view: GerritView.ADMIN,
adminView: 'gr-admin-group-list',
- filter: data.params.filter || null,
+ filter: data.params['filter'] || null,
});
}
- _handleProjectsOldRoute(data) {
+ _handleProjectsOldRoute(data: PageContextWithQueryMap) {
let params = '';
if (data.params[1]) {
params = encodeURIComponent(data.params[1]);
if (data.params[1].includes(',')) {
- params =
- encodeURIComponent(data.params[1]).replace('%2C', ',');
+ params = encodeURIComponent(data.params[1]).replace('%2C', ',');
}
}
this._redirect(`/admin/repos/${params}`);
}
- _handleRepoCommandsRoute(data) {
- const repo = data.params[0];
+ _handleRepoCommandsRoute(data: PageContextWithQueryMap) {
+ const repo = data.params[0] as RepoName;
this._setParams({
- view: GerritNav.View.REPO,
- detail: GerritNav.RepoDetailView.COMMANDS,
+ view: GerritView.REPO,
+ detail: RepoDetailView.COMMANDS,
repo,
});
this.reporting.setRepoName(repo);
}
- _handleRepoAccessRoute(data) {
- const repo = data.params[0];
+ _handleRepoAccessRoute(data: PageContextWithQueryMap) {
+ const repo = data.params[0] as RepoName;
this._setParams({
- view: GerritNav.View.REPO,
- detail: GerritNav.RepoDetailView.ACCESS,
+ view: GerritView.REPO,
+ detail: RepoDetailView.ACCESS,
repo,
});
this.reporting.setRepoName(repo);
}
- _handleRepoDashboardsRoute(data) {
- const repo = data.params[0];
+ _handleRepoDashboardsRoute(data: PageContextWithQueryMap) {
+ const repo = data.params[0] as RepoName;
this._setParams({
- view: GerritNav.View.REPO,
- detail: GerritNav.RepoDetailView.DASHBOARDS,
+ view: GerritView.REPO,
+ detail: RepoDetailView.DASHBOARDS,
repo,
});
this.reporting.setRepoName(repo);
}
- _handleBranchListOffsetRoute(data) {
+ _handleBranchListOffsetRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.REPO,
- detail: GerritNav.RepoDetailView.BRANCHES,
- repo: data.params[0],
+ view: GerritView.REPO,
+ detail: RepoDetailView.BRANCHES,
+ repo: data.params[0] as RepoName,
offset: data.params[2] || 0,
filter: null,
});
}
- _handleBranchListFilterOffsetRoute(data) {
+ _handleBranchListFilterOffsetRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.REPO,
- detail: GerritNav.RepoDetailView.BRANCHES,
- repo: data.params.repo,
- offset: data.params.offset,
- filter: data.params.filter,
+ view: GerritView.REPO,
+ detail: RepoDetailView.BRANCHES,
+ repo: data.params['repo'] as RepoName,
+ offset: data.params['offset'],
+ filter: data.params['filter'],
});
}
- _handleBranchListFilterRoute(data) {
+ _handleBranchListFilterRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.REPO,
- detail: GerritNav.RepoDetailView.BRANCHES,
- repo: data.params.repo,
- filter: data.params.filter || null,
+ view: GerritView.REPO,
+ detail: RepoDetailView.BRANCHES,
+ repo: data.params['repo'] as RepoName,
+ filter: data.params['filter'] || null,
});
}
- _handleTagListOffsetRoute(data) {
+ _handleTagListOffsetRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.REPO,
- detail: GerritNav.RepoDetailView.TAGS,
- repo: data.params[0],
+ view: GerritView.REPO,
+ detail: RepoDetailView.TAGS,
+ repo: data.params[0] as RepoName,
offset: data.params[2] || 0,
filter: null,
});
}
- _handleTagListFilterOffsetRoute(data) {
+ _handleTagListFilterOffsetRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.REPO,
- detail: GerritNav.RepoDetailView.TAGS,
- repo: data.params.repo,
- offset: data.params.offset,
- filter: data.params.filter,
+ view: GerritView.REPO,
+ detail: RepoDetailView.TAGS,
+ repo: data.params['repo'] as RepoName,
+ offset: data.params['offset'],
+ filter: data.params['filter'],
});
}
- _handleTagListFilterRoute(data) {
+ _handleTagListFilterRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.REPO,
- detail: GerritNav.RepoDetailView.TAGS,
- repo: data.params.repo,
- filter: data.params.filter || null,
+ view: GerritView.REPO,
+ detail: RepoDetailView.TAGS,
+ repo: data.params['repo'] as RepoName,
+ filter: data.params['filter'] || null,
});
}
- _handleRepoListOffsetRoute(data) {
+ _handleRepoListOffsetRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.ADMIN,
+ view: GerritView.ADMIN,
adminView: 'gr-repo-list',
offset: data.params[1] || 0,
filter: null,
@@ -1275,101 +1431,102 @@
});
}
- _handleRepoListFilterOffsetRoute(data) {
+ _handleRepoListFilterOffsetRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.ADMIN,
+ view: GerritView.ADMIN,
adminView: 'gr-repo-list',
- offset: data.params.offset,
- filter: data.params.filter,
+ offset: data.params['offset'],
+ filter: data.params['filter'],
});
}
- _handleRepoListFilterRoute(data) {
+ _handleRepoListFilterRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.ADMIN,
+ view: GerritView.ADMIN,
adminView: 'gr-repo-list',
- filter: data.params.filter || null,
+ filter: data.params['filter'] || null,
});
}
- _handleCreateProjectRoute(data) {
+ _handleCreateProjectRoute(_: PageContextWithQueryMap) {
// Redirects the legacy route to the new route, which displays the project
// list with a hash 'create'.
this._redirect('/admin/repos#create');
}
- _handleCreateGroupRoute(data) {
+ _handleCreateGroupRoute(_: PageContextWithQueryMap) {
// Redirects the legacy route to the new route, which displays the group
// list with a hash 'create'.
this._redirect('/admin/groups#create');
}
- _handleRepoRoute(data) {
- const repo = data.params[0];
+ _handleRepoRoute(data: PageContextWithQueryMap) {
+ const repo = data.params[0] as RepoName;
this._setParams({
- view: GerritNav.View.REPO,
+ view: GerritView.REPO,
repo,
});
this.reporting.setRepoName(repo);
}
- _handlePluginListOffsetRoute(data) {
+ _handlePluginListOffsetRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.ADMIN,
+ view: GerritView.ADMIN,
adminView: 'gr-plugin-list',
offset: data.params[1] || 0,
filter: null,
});
}
- _handlePluginListFilterOffsetRoute(data) {
+ _handlePluginListFilterOffsetRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.ADMIN,
+ view: GerritView.ADMIN,
adminView: 'gr-plugin-list',
- offset: data.params.offset,
- filter: data.params.filter,
+ offset: data.params['offset'],
+ filter: data.params['filter'],
});
}
- _handlePluginListFilterRoute(data) {
+ _handlePluginListFilterRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.ADMIN,
+ view: GerritView.ADMIN,
adminView: 'gr-plugin-list',
- filter: data.params.filter || null,
+ filter: data.params['filter'] || null,
});
}
- _handlePluginListRoute(data) {
+ _handlePluginListRoute(_: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.ADMIN,
+ view: GerritView.ADMIN,
adminView: 'gr-plugin-list',
});
}
- _handleQueryRoute(data) {
+ _handleQueryRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.SEARCH,
+ view: GerritView.SEARCH,
query: data.params[0],
offset: data.params[2],
});
}
- _handleQueryLegacySuffixRoute(ctx) {
+ _handleQueryLegacySuffixRoute(ctx: PageContextWithQueryMap) {
this._redirect(ctx.path.replace(LEGACY_QUERY_SUFFIX_PATTERN, ''));
}
- _handleChangeNumberLegacyRoute(ctx) {
+ _handleChangeNumberLegacyRoute(ctx: PageContextWithQueryMap) {
this._redirect('/c/' + encodeURIComponent(ctx.params[0]));
}
- _handleChangeRoute(ctx) {
+ _handleChangeRoute(ctx: PageContextWithQueryMap) {
// Parameter order is based on the regex group number matched.
- const params = {
- project: ctx.params[0],
- changeNum: ctx.params[1],
- basePatchNum: ctx.params[4],
- patchNum: ctx.params[6],
- view: GerritNav.View.CHANGE,
+ const params: GenerateUrlChangeViewParameters = {
+ project: ctx.params[0] as RepoName,
+ // TODO(TS): remove as unknown
+ changeNum: (ctx.params[1] as unknown) as NumericChangeId,
+ basePatchNum: ctx.params[4] as PatchSetNum,
+ patchNum: ctx.params[6] as PatchSetNum,
+ view: GerritView.CHANGE,
queryMap: ctx.queryMap,
};
@@ -1377,27 +1534,27 @@
this._redirectOrNavigate(params);
}
- _handleCommentRoute(ctx) {
- const params = {
- project: ctx.params[0],
- changeNum: ctx.params[1],
- commentId: ctx.params[2],
- view: GerritNav.View.DIFF,
+ _handleCommentRoute(ctx: PageContextWithQueryMap) {
+ const params: GenerateUrlDiffViewParameters = {
+ project: ctx.params[0] as RepoName,
+ changeNum: (ctx.params[1] as unknown) as NumericChangeId,
+ commentId: ctx.params[2] as UrlEncodedCommentId,
+ view: GerritView.DIFF,
commentLink: true,
};
this.reporting.setRepoName(params.project);
this._redirectOrNavigate(params);
}
- _handleDiffRoute(ctx) {
+ _handleDiffRoute(ctx: PageContextWithQueryMap) {
// Parameter order is based on the regex group number matched.
- const params = {
- project: ctx.params[0],
- changeNum: ctx.params[1],
- basePatchNum: ctx.params[4],
- patchNum: ctx.params[6],
+ const params: GenerateUrlDiffViewParameters = {
+ project: ctx.params[0] as RepoName,
+ changeNum: (ctx.params[1] as unknown) as NumericChangeId,
+ basePatchNum: ctx.params[4] as PatchSetNum,
+ patchNum: ctx.params[6] as PatchSetNum,
path: ctx.params[8],
- view: GerritNav.View.DIFF,
+ view: GerritView.DIFF,
};
const address = this._parseLineAddress(ctx.hash);
if (address) {
@@ -1408,31 +1565,32 @@
this._redirectOrNavigate(params);
}
- _handleChangeLegacyRoute(ctx) {
+ _handleChangeLegacyRoute(ctx: PageContextWithQueryMap) {
// Parameter order is based on the regex group number matched.
- const params = {
- changeNum: ctx.params[0],
- basePatchNum: ctx.params[3],
- patchNum: ctx.params[5],
- view: GerritNav.View.CHANGE,
+ const params: GenerateUrlLegacyChangeViewParameters = {
+ changeNum: (ctx.params[0] as unknown) as NumericChangeId,
+ basePatchNum: ctx.params[3] as PatchSetNum,
+ patchNum: ctx.params[5] as PatchSetNum,
+ view: GerritView.CHANGE,
querystring: ctx.querystring,
};
this._normalizeLegacyRouteParams(params);
}
- _handleLegacyLinenum(ctx) {
+ _handleLegacyLinenum(ctx: PageContextWithQueryMap) {
this._redirect(ctx.path.replace(LEGACY_LINENUM_PATTERN, '#$1'));
}
- _handleDiffLegacyRoute(ctx) {
+ _handleDiffLegacyRoute(ctx: PageContextWithQueryMap) {
// Parameter order is based on the regex group number matched.
- const params = {
- changeNum: ctx.params[0],
- basePatchNum: ctx.params[2],
- patchNum: ctx.params[4],
+ const params: GenerateUrlLegacyDiffViewParameters = {
+ // TODO(TS): remove "as unknown"
+ changeNum: (ctx.params[0] as unknown) as NumericChangeId,
+ basePatchNum: ctx.params[2] as PatchSetNum,
+ patchNum: ctx.params[4] as PatchSetNum,
path: ctx.params[5],
- view: GerritNav.View.DIFF,
+ view: GerritView.DIFF,
};
const address = this._parseLineAddress(ctx.hash);
@@ -1444,28 +1602,29 @@
this._normalizeLegacyRouteParams(params);
}
- _handleDiffEditRoute(ctx) {
+ _handleDiffEditRoute(ctx: PageContextWithQueryMap) {
// Parameter order is based on the regex group number matched.
- const project = ctx.params[0];
+ const project = ctx.params[0] as RepoName;
this._redirectOrNavigate({
project,
- changeNum: ctx.params[1],
- patchNum: ctx.params[2],
+ changeNum: (ctx.params[1] as unknown) as NumericChangeId,
+ patchNum: ctx.params[2] as PatchSetNum,
path: ctx.params[3],
lineNum: ctx.hash,
- view: GerritNav.View.EDIT,
+ view: GerritView.EDIT,
});
this.reporting.setRepoName(project);
}
- _handleChangeEditRoute(ctx) {
+ _handleChangeEditRoute(ctx: PageContextWithQueryMap) {
// Parameter order is based on the regex group number matched.
- const project = ctx.params[0];
+ const project = ctx.params[0] as RepoName;
this._redirectOrNavigate({
project,
- changeNum: ctx.params[1],
- patchNum: ctx.params[3],
- view: GerritNav.View.CHANGE,
+ // TODO(TS): remove "as unknown"
+ changeNum: (ctx.params[1] as unknown) as NumericChangeId,
+ patchNum: ctx.params[3] as PatchSetNum,
+ view: GerritView.CHANGE,
edit: true,
});
this.reporting.setRepoName(project);
@@ -1475,7 +1634,7 @@
* Normalize the patch range params for a the change or diff view and
* redirect if URL upgrade is needed.
*/
- _redirectOrNavigate(params) {
+ _redirectOrNavigate(params: GenerateUrlParameters & PatchRangeParams) {
const needsRedirect = this._normalizePatchRangeParams(params);
if (needsRedirect) {
this._redirect(this._generateUrl(params));
@@ -1488,34 +1647,39 @@
this._redirect('/settings/#Agreements');
}
- _handleNewAgreementsRoute(data) {
- data.params.view = GerritNav.View.AGREEMENTS;
- this._setParams(data.params);
+ _handleNewAgreementsRoute(data: PageContextWithQueryMap) {
+ data.params['view'] = GerritView.AGREEMENTS;
+ // TODO(TS): create valid object
+ this._setParams((data.params as unknown) as AppElementAgreementParam);
}
- _handleSettingsLegacyRoute(data) {
+ _handleSettingsLegacyRoute(data: PageContextWithQueryMap) {
// email tokens may contain '+' but no space.
// The parameter parsing replaces all '+' with a space,
// undo that to have valid tokens.
const token = data.params[0].replace(/ /g, '+');
this._setParams({
- view: GerritNav.View.SETTINGS,
+ view: GerritView.SETTINGS,
emailToken: token,
});
}
- _handleSettingsRoute(data) {
- this._setParams({view: GerritNav.View.SETTINGS});
+ _handleSettingsRoute(_: PageContextWithQueryMap) {
+ this._setParams({view: GerritView.SETTINGS});
}
- _handleRegisterRoute(ctx) {
+ _handleRegisterRoute(ctx: PageContextWithQueryMap) {
this._setParams({justRegistered: true});
let path = ctx.params[0] || '/';
// Prevent redirect looping.
- if (path.startsWith('/register')) { path = '/'; }
+ if (path.startsWith('/register')) {
+ path = '/';
+ }
- if (path[0] !== '/') { return; }
+ if (path[0] !== '/') {
+ return;
+ }
this._redirect(getBaseUrl() + path);
}
@@ -1531,32 +1695,35 @@
* URL may sometimes have /+/ encoded to / /.
* Context: Issue 6888, Issue 7100
*/
- _handleImproperlyEncodedPlusRoute(ctx) {
+ _handleImproperlyEncodedPlusRoute(ctx: PageContextWithQueryMap) {
let hash = this._getHashFromCanonicalPath(ctx.canonicalPath);
- if (hash.length) { hash = '#' + hash; }
+ if (hash.length) {
+ hash = '#' + hash;
+ }
this._redirect(`/c/${ctx.params[0]}/+/${ctx.params[1]}${hash}`);
}
- _handlePluginScreen(ctx) {
- const view = GerritNav.View.PLUGIN_SCREEN;
+ _handlePluginScreen(ctx: PageContextWithQueryMap) {
+ const view = GerritView.PLUGIN_SCREEN;
const plugin = ctx.params[0];
const screen = ctx.params[1];
this._setParams({view, plugin, screen});
}
- _handleDocumentationSearchRoute(data) {
+ _handleDocumentationSearchRoute(data: PageContextWithQueryMap) {
this._setParams({
- view: GerritNav.View.DOCUMENTATION_SEARCH,
- filter: data.params.filter || null,
+ view: GerritView.DOCUMENTATION_SEARCH,
+ filter: data.params['filter'] || null,
});
}
- _handleDocumentationSearchRedirectRoute(data) {
- this._redirect('/Documentation/q/filter:' +
- encodeURIComponent(data.params[0]));
+ _handleDocumentationSearchRedirectRoute(data: PageContextWithQueryMap) {
+ this._redirect(
+ '/Documentation/q/filter:' + encodeURIComponent(data.params[0])
+ );
}
- _handleDocumentationRedirectRoute(data) {
+ _handleDocumentationRedirectRoute(data: PageContextWithQueryMap) {
if (data.params[1]) {
location.reload();
} else {
@@ -1582,9 +1749,14 @@
// Note: the app's 404 display is tightly-coupled with catching 404
// network responses, so we simulate a 404 response status to display it.
// TODO: Decouple the gr-app error view from network responses.
- this._appElement().dispatchEvent(new CustomEvent('page-error',
- {detail: {response: {status: 404}}}));
+ this._appElement().dispatchEvent(
+ new CustomEvent('page-error', {detail: {response: {status: 404}}})
+ );
}
}
-customElements.define(GrRouter.is, GrRouter);
+declare global {
+ interface HTMLElementTagNameMap {
+ 'gr-router': GrRouter;
+ }
+}