diff options
Diffstat (limited to 'polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html')
-rw-r--r-- | polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html | 432 |
1 files changed, 413 insertions, 19 deletions
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html index 2ed7952a90..36507073ff 100644 --- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html +++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html @@ -1,4 +1,5 @@ <!-- +@license Copyright (C) 2017 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,8 +25,19 @@ limitations under the License. // // - Gerrit.Nav.View.CHANGE: // - `changeNum`, required, String: the numeric ID of the change. + // - `project`, optional, String: the project name. + // - `patchNum`, optional, Number: the patch for the right-hand-side of + // the diff. + // - `basePatchNum`, optional, Number: the patch for the left-hand-side + // of the diff. If `basePatchNum` is provided, then `patchNum` must + // also be provided. + // - `edit`, optional, Boolean: whether or not to load the file list with + // edit controls. // // - Gerrit.Nav.View.SEARCH: + // - `query`, optional, String: the literal search query. If provided, + // the string will be used as the query, and all other params will be + // ignored. // - `owner`, optional, String: the owner name. // - `project`, optional, String: the project name. // - `branch`, optional, String: the branch name. @@ -34,19 +46,39 @@ limitations under the License. // - `statuses`, optional, Array<String>: the list of change statuses to // search for. If more than one is provided, the search will OR them // together. + // - `offset`, optional, Number: the offset for the query. // // - Gerrit.Nav.View.DIFF: // - `changeNum`, required, String: the numeric ID of the change. // - `path`, required, String: the filepath of the diff. - // - `patchNum`, required, Number, the patch for the right-hand-side of + // - `patchNum`, required, Number: the patch for the right-hand-side of // the diff. - // - `basePatchNum`, optional, Number, the patch for the left-hand-side + // - `basePatchNum`, optional, Number: the patch for the left-hand-side // of the diff. If `basePatchNum` is provided, then `patchNum` must // also be provided. - // - `lineNum`, optional, Number, the line number to be selected on load. - // - `leftSide`, optional, Boolean, if a `lineNum` is provided, a value + // - `lineNum`, optional, Number: the line number to be selected on load. + // - `leftSide`, optional, Boolean: if a `lineNum` is provided, a value // of true selects the line from base of the patch range. False by // default. + // + // - Gerrit.Nav.View.GROUP: + // - `groupId`, required, String: the ID of the group. + // - `detail`, optional, String: the name of the group detail view. + // Takes any value from Gerrit.Nav.GroupDetailView. + // + // - Gerrit.Nav.View.REPO: + // - `repoName`, required, String: the name of the repo + // - `detail`, optional, String: the name of the repo detail view. + // Takes any value from Gerrit.Nav.RepoDetailView. + // + // - Gerrit.Nav.View.DASHBOARD + // - `repo`, optional, String. + // - `sections`, optional, Array of objects with `title` and `query` + // strings. + // - `user`, optional, String. + // + // - Gerrit.Nav.View.ROOT: + // - no possible parameters. window.Gerrit = window.Gerrit || {}; @@ -57,27 +89,122 @@ limitations under the License. console.warn('Use of uninitialized routing'); }; + const EDIT_PATCHNUM = 'edit'; const PARENT_PATCHNUM = 'PARENT'; + const USER_PLACEHOLDER_PATTERN = /\$\{user\}/g; + + // NOTE: These queries are tested in Java. Any changes made to definitions + // here require corresponding changes to: + // javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java + const DEFAULT_SECTIONS = [ + { + // Changes with unpublished draft comments. This section is omitted when + // viewing other users, so we don't need to filter anything out. + name: 'Has draft comments', + query: 'has:draft', + selfOnly: true, + hideIfEmpty: true, + suffixForDashboard: 'limit:10', + }, + { + // Changes that are assigned to the viewed user. + name: 'Assigned reviews', + query: 'assignee:${user} (-is:wip OR owner:self OR assignee:self) ' + + 'is:open -is:ignored', + hideIfEmpty: true, + }, + { + // WIP open changes owned by viewing user. This section is omitted when + // viewing other users, so we don't need to filter anything out. + name: 'Work in progress', + query: 'is:open owner:${user} is:wip', + selfOnly: true, + hideIfEmpty: true, + }, + { + // Non-WIP open changes owned by viewed user. Filter out changes ignored + // by the viewing user. + name: 'Outgoing reviews', + query: 'is:open owner:${user} -is:wip -is:ignored', + isOutgoing: true, + }, + { + // Non-WIP open changes not owned by the viewed user, that the viewed user + // is associated with (as either a reviewer or the assignee). Changes + // ignored by the viewing user are filtered out. + name: 'Incoming reviews', + query: 'is:open -owner:${user} -is:wip -is:ignored ' + + '(reviewer:${user} OR assignee:${user})', + }, + { + // Open changes the viewed user is CCed on. Changes ignored by the viewing + // user are filtered out. + name: 'CCed on', + query: 'is:open -is:ignored cc:${user}', + }, + { + name: 'Recently closed', + // Closed changes where viewed user is owner, reviewer, or assignee. + // Changes ignored by the viewing user are filtered out, and so are WIP + // changes not owned by the viewing user (the one instance of + // 'owner:self' is intentional and implements this logic). + query: 'is:closed -is:ignored (-is:wip OR owner:self) ' + + '(owner:${user} OR reviewer:${user} OR assignee:${user} ' + + 'OR cc:${user})', + suffixForDashboard: '-age:4w limit:10', + }, + ]; + window.Gerrit.Nav = { View: { ADMIN: 'admin', - CHANGE: 'change', AGREEMENTS: 'agreements', + CHANGE: 'change', DASHBOARD: 'dashboard', DIFF: 'diff', + DOCUMENTATION_SEARCH: 'documentation-search', EDIT: 'edit', + GROUP: 'group', + PLUGIN_SCREEN: 'plugin-screen', + REPO: 'repo', + ROOT: 'root', SEARCH: 'search', SETTINGS: 'settings', }, + GroupDetailView: { + MEMBERS: 'members', + LOG: 'log', + }, + + RepoDetailView: { + ACCESS: 'access', + BRANCHES: 'branches', + COMMANDS: 'commands', + DASHBOARDS: 'dashboards', + TAGS: 'tags', + }, + + WeblinkType: { + CHANGE: 'change', + FILE: 'file', + PATCHSET: 'patchset', + }, + /** @type {Function} */ _navigate: uninitialized, /** @type {Function} */ _generateUrl: uninitialized, + /** @type {Function} */ + _generateWeblinks: uninitialized, + + /** @type {Function} */ + mapCommentlinks: uninitialized, + /** * @param {number=} patchNum * @param {number|string=} basePatchNum @@ -90,17 +217,38 @@ limitations under the License. /** * Setup router implementation. - * @param {Function} navigate - * @param {Function} generateUrl + * @param {function(!string)} navigate the router-abstracted equivalent of + * `window.location.href = ...`. Takes a string. + * @param {function(!Object): string} generateUrl generates a URL given + * navigation parameters, detailed in the file header. + * @param {function(!Object): string} generateWeblinks weblinks generator + * function takes single payload parameter with type property that + * determines which + * part of the UI is the consumer of the weblinks. type property can + * be one of file, change, or patchset. + * - For file type, payload will also contain string properties: repo, + * commit, file. + * - For patchset type, payload will also contain string properties: + * repo, commit. + * - For change type, payload will also contain string properties: + * repo, commit. If server provides weblinks, those will be passed + * as options.weblinks property on the main payload object. + * @param {function(!Object): Object} mapCommentlinks provides an escape + * hatch to modify the commentlinks object, e.g. if it contains any + * relative URLs. */ - setup(navigate, generateUrl) { + setup(navigate, generateUrl, generateWeblinks, mapCommentlinks) { this._navigate = navigate; this._generateUrl = generateUrl; + this._generateWeblinks = generateWeblinks; + this.mapCommentlinks = mapCommentlinks; }, destroy() { this._navigate = uninitialized; this._generateUrl = uninitialized; + this._generateWeblinks = uninitialized; + this.mapCommentlinks = uninitialized; }, /** @@ -112,17 +260,27 @@ limitations under the License. return this._generateUrl(params); }, + getUrlForSearchQuery(query, opt_offset) { + return this._getUrlFor({ + view: Gerrit.Nav.View.SEARCH, + query, + offset: opt_offset, + }); + }, + /** * @param {!string} project The name of the project. * @param {boolean=} opt_openOnly When true, only search open changes in * the project. + * @param {string=} opt_host The host in which to search. * @return {string} */ - getUrlForProject(project, opt_openOnly) { + getUrlForProjectChanges(project, opt_openOnly, opt_host) { return this._getUrlFor({ view: Gerrit.Nav.View.SEARCH, project, statuses: opt_openOnly ? ['open'] : [], + host: opt_host, }); }, @@ -130,26 +288,30 @@ limitations under the License. * @param {string} branch The name of the branch. * @param {string} project The name of the project. * @param {string=} opt_status The status to search. + * @param {string=} opt_host The host in which to search. * @return {string} */ - getUrlForBranch(branch, project, opt_status) { + getUrlForBranch(branch, project, opt_status, opt_host) { return this._getUrlFor({ view: Gerrit.Nav.View.SEARCH, branch, project, statuses: opt_status ? [opt_status] : undefined, + host: opt_host, }); }, /** * @param {string} topic The name of the topic. + * @param {string=} opt_host The host in which to search. * @return {string} */ - getUrlForTopic(topic) { + getUrlForTopic(topic, opt_host) { return this._getUrlFor({ view: Gerrit.Nav.View.SEARCH, topic, statuses: ['open', 'merged'], + host: opt_host, }); }, @@ -166,13 +328,34 @@ limitations under the License. }, /** + * Navigate to a search for changes with the given status. + * @param {string} status + */ + navigateToStatusSearch(status) { + this._navigate(this._getUrlFor({ + view: Gerrit.Nav.View.SEARCH, + statuses: [status], + })); + }, + + /** + * Navigate to a search query + * @param {string} query + * @param {number=} opt_offset + */ + navigateToSearchQuery(query, opt_offset) { + return this._navigate(this.getUrlForSearchQuery(query, opt_offset)); + }, + + /** * @param {!Object} change The change object. * @param {number=} opt_patchNum * @param {number|string=} opt_basePatchNum The string 'PARENT' can be * used for none. + * @param {boolean=} opt_isEdit * @return {string} */ - getUrlForChange(change, opt_patchNum, opt_basePatchNum) { + getUrlForChange(change, opt_patchNum, opt_basePatchNum, opt_isEdit) { if (opt_basePatchNum === PARENT_PATCHNUM) { opt_basePatchNum = undefined; } @@ -184,6 +367,8 @@ limitations under the License. project: change.project, patchNum: opt_patchNum, basePatchNum: opt_basePatchNum, + edit: opt_isEdit, + host: change.internalHost || undefined, }); }, @@ -207,10 +392,11 @@ limitations under the License. * @param {number=} opt_patchNum * @param {number|string=} opt_basePatchNum The string 'PARENT' can be * used for none. + * @param {boolean=} opt_isEdit */ - navigateToChange(change, opt_patchNum, opt_basePatchNum) { + navigateToChange(change, opt_patchNum, opt_basePatchNum, opt_isEdit) { this._navigate(this.getUrlForChange(change, opt_patchNum, - opt_basePatchNum)); + opt_basePatchNum, opt_isEdit)); }, /** @@ -219,11 +405,12 @@ limitations under the License. * @param {number=} opt_patchNum * @param {number|string=} opt_basePatchNum The string 'PARENT' can be * used for none. + * @param {number|string=} opt_lineNum * @return {string} */ - getUrlForDiff(change, path, opt_patchNum, opt_basePatchNum) { + getUrlForDiff(change, path, opt_patchNum, opt_basePatchNum, opt_lineNum) { return this.getUrlForDiffById(change._number, change.project, path, - opt_patchNum, opt_basePatchNum); + opt_patchNum, opt_basePatchNum, opt_lineNum); }, /** @@ -259,24 +446,29 @@ limitations under the License. /** * @param {{ _number: number, project: string }} change The change object. * @param {string} path The file path. + * @param {number=} opt_patchNum * @return {string} */ - getEditUrlForDiff(change, path) { - return this.getEditUrlForDiffById(change._number, change.project, path); + getEditUrlForDiff(change, path, opt_patchNum) { + return this.getEditUrlForDiffById(change._number, change.project, path, + opt_patchNum); }, /** * @param {number} changeNum * @param {string} project The name of the project. * @param {string} path The file path. + * @param {number|string=} opt_patchNum The patchNum the file content + * should be based on, or ${EDIT_PATCHNUM} if left undefined. * @return {string} */ - getEditUrlForDiffById(changeNum, project, path) { + getEditUrlForDiffById(changeNum, project, path, opt_patchNum) { return this._getUrlFor({ view: Gerrit.Nav.View.EDIT, changeNum, project, path, + patchNum: opt_patchNum || EDIT_PATCHNUM, }); }, @@ -315,6 +507,29 @@ limitations under the License. }, /** + * @return {string} + */ + getUrlForRoot() { + return this._getUrlFor({ + view: Gerrit.Nav.View.ROOT, + }); + }, + + /** + * @param {string} repo The name of the repo. + * @param {string} dashboard The ID of the dashboard, in the form of + * '<ref>:<path>'. + * @return {string} + */ + getUrlForRepoDashboard(repo, dashboard) { + return this._getUrlFor({ + view: Gerrit.Nav.View.DASHBOARD, + repo, + dashboard, + }); + }, + + /** * Navigate to an arbitrary relative URL. * @param {string} relativeUrl */ @@ -325,9 +540,188 @@ limitations under the License. this._navigate(relativeUrl); }, + /** + * @param {string} repoName + * @return {string} + */ + getUrlForRepo(repoName) { + return this._getUrlFor({ + view: Gerrit.Nav.View.REPO, + repoName, + }); + }, + + /** + * Navigate to a repo settings page. + * @param {string} repoName + */ + navigateToRepo(repoName) { + this._navigate(this.getUrlForRepo(repoName)); + }, + + /** + * @param {string} repoName + * @return {string} + */ + getUrlForRepoTags(repoName) { + return this._getUrlFor({ + view: Gerrit.Nav.View.REPO, + repoName, + detail: Gerrit.Nav.RepoDetailView.TAGS, + }); + }, + + /** + * @param {string} repoName + * @return {string} + */ + getUrlForRepoBranches(repoName) { + return this._getUrlFor({ + view: Gerrit.Nav.View.REPO, + repoName, + detail: Gerrit.Nav.RepoDetailView.BRANCHES, + }); + }, + + /** + * @param {string} repoName + * @return {string} + */ + getUrlForRepoAccess(repoName) { + return this._getUrlFor({ + view: Gerrit.Nav.View.REPO, + repoName, + detail: Gerrit.Nav.RepoDetailView.ACCESS, + }); + }, + + /** + * @param {string} repoName + * @return {string} + */ + getUrlForRepoCommands(repoName) { + return this._getUrlFor({ + view: Gerrit.Nav.View.REPO, + repoName, + detail: Gerrit.Nav.RepoDetailView.COMMANDS, + }); + }, + + /** + * @param {string} repoName + * @return {string} + */ + getUrlForRepoDashboards(repoName) { + return this._getUrlFor({ + view: Gerrit.Nav.View.REPO, + repoName, + detail: Gerrit.Nav.RepoDetailView.DASHBOARDS, + }); + }, + + /** + * @param {string} groupId + * @return {string} + */ + getUrlForGroup(groupId) { + return this._getUrlFor({ + view: Gerrit.Nav.View.GROUP, + groupId, + }); + }, + + /** + * @param {string} groupId + * @return {string} + */ + getUrlForGroupLog(groupId) { + return this._getUrlFor({ + view: Gerrit.Nav.View.GROUP, + groupId, + detail: Gerrit.Nav.GroupDetailView.LOG, + }); + }, + + /** + * @param {string} groupId + * @return {string} + */ + getUrlForGroupMembers(groupId) { + return this._getUrlFor({ + view: Gerrit.Nav.View.GROUP, + groupId, + detail: Gerrit.Nav.GroupDetailView.MEMBERS, + }); + }, + getUrlForSettings() { return this._getUrlFor({view: Gerrit.Nav.View.SETTINGS}); }, + + /** + * @param {string} repo + * @param {string} commit + * @param {string} file + * @param {Object=} opt_options + * @return { + * Array<{label: string, url: string}>| + * {label: string, url: string} + * } + */ + getFileWebLinks(repo, commit, file, opt_options) { + const params = {type: Gerrit.Nav.WeblinkType.FILE, repo, commit, file}; + if (opt_options) { + params.options = opt_options; + } + return [].concat(this._generateWeblinks(params)); + }, + + /** + * @param {string} repo + * @param {string} commit + * @param {Object=} opt_options + * @return {{label: string, url: string}} + */ + getPatchSetWeblink(repo, commit, opt_options) { + const params = {type: Gerrit.Nav.WeblinkType.PATCHSET, repo, commit}; + if (opt_options) { + params.options = opt_options; + } + const result = this._generateWeblinks(params); + if (Array.isArray(result)) { + return result.pop(); + } else { + return result; + } + }, + + /** + * @param {string} repo + * @param {string} commit + * @param {Object=} opt_options + * @return { + * Array<{label: string, url: string}>| + * {label: string, url: string} + * } + */ + getChangeWeblinks(repo, commit, opt_options) { + const params = {type: Gerrit.Nav.WeblinkType.CHANGE, repo, commit}; + if (opt_options) { + params.options = opt_options; + } + return [].concat(this._generateWeblinks(params)); + }, + + getUserDashboard(user = 'self', sections = DEFAULT_SECTIONS, + title = '') { + sections = sections + .filter(section => (user === 'self' || !section.selfOnly)) + .map(section => Object.assign({}, section, { + name: section.name, + query: section.query.replace(USER_PLACEHOLDER_PATTERN, user), + })); + return {title, sections}; + }, }; })(window); </script> |