Merge "Migrate GrDateFromatter to lit"
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index c8949e6..9ebee9c 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -3698,18 +3698,16 @@
TestRepository<Repo> repo = createProject("repo");
Change change = insert(repo, newChange(repo));
- AssigneeInput ain = new AssigneeInput();
- ain.assignee = user2.toString();
- gApi.changes().id(change.getId().get()).setAssignee(ain);
+ gApi.changes().id(change.getId().get()).addReviewer(user2.toString());
RequestContext adminContext = requestContext.setContext(newRequestContext(user2));
- assertQuery("assignee:self", change);
+ assertQuery("reviewer:self", change);
requestContext.setContext(adminContext);
gApi.accounts().id(user2.get()).setActive(false);
requestContext.setContext(newRequestContext(user2));
- assertQuery("assignee:self", change);
+ assertQuery("reviewer:self", change);
}
@Test
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.ts
index 6770c00..d160a28 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.ts
@@ -28,7 +28,6 @@
import '../../plugins/gr-endpoint-param/gr-endpoint-param';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-change-list-item_html';
-import {ChangeTableMixin} from '../../../mixins/gr-change-table-mixin/gr-change-table-mixin';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {getDisplayName} from '../../../utils/display-name-util';
import {getPluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
@@ -76,11 +75,8 @@
// How many reviewers should be shown with an account-label?
const PRIMARY_REVIEWERS_COUNT = 2;
-// This avoids JSC_DYNAMIC_EXTENDS_WITHOUT_JSDOC closure compiler error.
-const base = ChangeTableMixin(PolymerElement);
-
@customElement('gr-change-list-item')
-export class GrChangeListItem extends base {
+export class GrChangeListItem extends PolymerElement {
static get template() {
return htmlTemplate;
}
@@ -397,6 +393,13 @@
return change?.attention_set[account._account_id]?.last_update;
}
+ _computeIsColumnHidden(columnToCheck?: string, columnsToDisplay?: string[]) {
+ if (!columnsToDisplay || !columnToCheck) {
+ return false;
+ }
+ return !columnsToDisplay.includes(columnToCheck);
+ }
+
toggleReviewed() {
if (!this.change) return;
const newVal = !this.change?.reviewed;
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.ts
index 1b47791..f0d9268 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.ts
@@ -127,7 +127,7 @@
</td>
<td
class="cell subject"
- hidden$="[[isColumnHidden('Subject', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Subject', visibleChangeTableColumns)]]"
>
<a
title$="[[change.subject]]"
@@ -143,7 +143,7 @@
</td>
<td
class="cell status"
- hidden$="[[isColumnHidden('Status', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Status', visibleChangeTableColumns)]]"
>
<template is="dom-repeat" items="[[statuses]]" as="status">
<div class="comma">,</div>
@@ -155,7 +155,7 @@
</td>
<td
class="cell owner"
- hidden$="[[isColumnHidden('Owner', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Owner', visibleChangeTableColumns)]]"
>
<gr-account-link
highlightAttention
@@ -165,7 +165,7 @@
</td>
<td
class="cell assignee"
- hidden$="[[isColumnHidden('Assignee', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Assignee', visibleChangeTableColumns)]]"
>
<template is="dom-if" if="[[change.assignee]]">
<gr-account-link
@@ -179,7 +179,7 @@
</td>
<td
class="cell reviewers"
- hidden$="[[isColumnHidden('Reviewers', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Reviewers', visibleChangeTableColumns)]]"
>
<div>
<template
@@ -211,7 +211,7 @@
</td>
<td
class="cell comments"
- hidden$="[[isColumnHidden('Comments', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Comments', visibleChangeTableColumns)]]"
>
<iron-icon
hidden$="[[!change.unresolved_comment_count]]"
@@ -221,7 +221,7 @@
</td>
<td
class="cell repo"
- hidden$="[[isColumnHidden('Repo', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Repo', visibleChangeTableColumns)]]"
>
<a class="fullRepo" href$="[[_computeRepoUrl(change)]]">
[[_computeRepoDisplay(change, false)]]
@@ -236,7 +236,7 @@
</td>
<td
class="cell branch"
- hidden$="[[isColumnHidden('Branch', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Branch', visibleChangeTableColumns)]]"
>
<a href$="[[_computeRepoBranchURL(change)]]"> [[change.branch]] </a>
<template is="dom-if" if="[[change.topic]]">
@@ -250,7 +250,7 @@
</td>
<td
class="cell updated"
- hidden$="[[isColumnHidden('Updated', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Updated', visibleChangeTableColumns)]]"
>
<gr-date-formatter
withTooltip
@@ -259,7 +259,7 @@
</td>
<td
class="cell submitted"
- hidden$="[[isColumnHidden('Submitted', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Submitted', visibleChangeTableColumns)]]"
>
<gr-date-formatter
withTooltip
@@ -268,7 +268,7 @@
</td>
<td
class="cell waiting"
- hidden$="[[isColumnHidden('Waiting', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Waiting', visibleChangeTableColumns)]]"
>
<gr-date-formatter
withTooltip
@@ -279,7 +279,7 @@
</td>
<td
class="cell size"
- hidden$="[[isColumnHidden('Size', visibleChangeTableColumns)]]"
+ hidden$="[[_computeIsColumnHidden('Size', visibleChangeTableColumns)]]"
>
<gr-tooltip-content has-tooltip="" title="[[_computeSizeTooltip(change)]]">
<template is="dom-if" if="[[_changeSize]]">
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.ts
index ac0b929..aa04784 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.ts
@@ -29,6 +29,7 @@
TopicName,
} from '../../../types/common';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
+import {columnNames} from '../gr-change-list/gr-change-list';
import './gr-change-list-item';
import {GrChangeListItem, LabelCategory} from './gr-change-list-item';
@@ -372,7 +373,7 @@
await flush();
- for (const column of element.columnNames) {
+ for (const column of columnNames) {
const elementClass = '.' + column.toLowerCase();
assert.isFalse(
queryAndAssert(element, elementClass).hasAttribute('hidden')
@@ -395,7 +396,7 @@
await flush();
- for (const column of element.columnNames) {
+ for (const column of columnNames) {
const elementClass = '.' + column.toLowerCase();
if (column === 'Repo') {
assert.isTrue(
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 40674d4..a2a46e0 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
@@ -24,7 +24,6 @@
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-change-list_html';
import {appContext} from '../../../services/app-context';
-import {ChangeTableMixin} from '../../../mixins/gr-change-table-mixin/gr-change-table-mixin';
import {
KeyboardShortcutMixin,
Shortcut,
@@ -57,6 +56,19 @@
const LABEL_PREFIX_INVALID_PROLOG = 'Invalid-Prolog-Rules-Label-Name--';
const MAX_SHORTCUT_CHARS = 5;
+export const columnNames = [
+ 'Subject',
+ 'Status',
+ 'Owner',
+ 'Assignee',
+ 'Reviewers',
+ 'Comments',
+ 'Repo',
+ 'Branch',
+ 'Updated',
+ 'Size',
+];
+
export interface ChangeListSection {
name?: string;
query?: string;
@@ -68,7 +80,7 @@
}
// This avoids JSC_DYNAMIC_EXTENDS_WITHOUT_JSDOC closure compiler error.
-const base = ChangeTableMixin(KeyboardShortcutMixin(PolymerElement));
+const base = KeyboardShortcutMixin(PolymerElement);
@customElement('gr-change-list')
export class GrChangeList extends base {
@@ -219,32 +231,44 @@
return;
}
- this.changeTableColumns = this.columnNames;
+ this.changeTableColumns = columnNames;
this.showNumber = false;
- this.visibleChangeTableColumns = this.getEnabledColumns(
- this.columnNames,
- config,
- this.flagsService.enabledExperiments
+ this.visibleChangeTableColumns = this.changeTableColumns.filter(col =>
+ this._isColumnEnabled(col, config, this.flagsService.enabledExperiments)
);
-
if (account && preferences) {
this.showNumber = !!(
preferences && preferences.legacycid_in_change_table
);
if (preferences.change_table && preferences.change_table.length > 0) {
- const prefColumns = this.renameProjectToRepoColumn(
- preferences.change_table
+ const prefColumns = preferences.change_table.map(column =>
+ column === 'Project' ? 'Repo' : column
);
- this.visibleChangeTableColumns = this.getEnabledColumns(
- prefColumns,
- config,
- this.flagsService.enabledExperiments
+ this.visibleChangeTableColumns = prefColumns.filter(col =>
+ this._isColumnEnabled(
+ col,
+ config,
+ this.flagsService.enabledExperiments
+ )
);
}
}
}
/**
+ * Is the column disabled by a server config or experiment? For example the
+ * assignee feature might be disabled and thus the corresponding column is
+ * also disabled.
+ *
+ */
+ _isColumnEnabled(column: string, config: ServerInfo, experiments: string[]) {
+ if (!config || !config.change) return true;
+ if (column === 'Assignee') return !!config.change.enable_assignee;
+ if (column === 'Comments') return experiments.includes('comments-column');
+ return true;
+ }
+
+ /**
* This methods allows us to customize the columns per section.
*
* @param visibleColumns are the columns according to configs and user prefs
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js
index 0d2056a..7b226e7 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js
@@ -269,7 +269,7 @@
});
test('all columns visible', () => {
- for (const column of element.columnNames) {
+ for (const column of element.changeTableColumns) {
const elementClass = '.' + element._lowerCase(column);
assert.isFalse(element.shadowRoot
.querySelector(elementClass).hidden);
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 ed9820f..e940e5a 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,7 @@
} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {GrEditConstants} from '../../edit/gr-edit-constants';
import {pluralize} from '../../../utils/string-util';
-import {windowLocationReload} from '../../../utils/dom-util';
+import {windowLocationReload, querySelectorAll} from '../../../utils/dom-util';
import {
GeneratedWebLink,
GerritNav,
@@ -1172,6 +1172,9 @@
_paramsChanged(value: AppElementChangeViewParams) {
if (value.view !== GerritView.CHANGE) {
this._initialLoadComplete = false;
+ querySelectorAll(this, 'gr-overlay').forEach(overlay =>
+ (overlay as GrOverlay).close()
+ );
return;
}
diff --git a/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts b/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts
index fa590a3..fd85117 100644
--- a/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts
+++ b/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts
@@ -16,7 +16,7 @@
*/
import '../gr-submit-requirement-hovercard/gr-submit-requirement-hovercard';
import {LitElement, css, html} from 'lit';
-import {customElement, property} from 'lit/decorators';
+import {customElement, property, state} from 'lit/decorators';
import {ParsedChangeInfo} from '../../../types/types';
import {
AccountInfo,
@@ -32,7 +32,14 @@
iconForStatus,
} from '../../../utils/label-util';
import {fontStyles} from '../../../styles/gr-font-styles';
-import {charsOnly} from '../../../utils/string-util';
+import {charsOnly, pluralize} from '../../../utils/string-util';
+import {subscribe} from '../../lit/subscription-controller';
+import {
+ allRunsLatestPatchsetLatestAttempt$,
+ CheckRun,
+} from '../../../services/checks/checks-model';
+import {getResultsOf, hasResultsOf} from '../../../services/checks/checks-util';
+import {Category} from '../../../api/checks';
@customElement('gr-submit-requirements')
export class GrSubmitRequirements extends LitElement {
@@ -45,6 +52,9 @@
@property({type: Boolean})
mutable?: boolean;
+ @state()
+ runs: CheckRun[] = [];
+
static override get styles() {
return [
fontStyles,
@@ -95,10 +105,25 @@
td {
padding: var(--spacing-s);
}
+ .votes-cell {
+ display: flex;
+ }
+ .check-error {
+ margin-right: var(--spacing-l);
+ }
+ .check-error iron-icon {
+ color: var(--error-foreground);
+ vertical-align: top;
+ }
`,
];
}
+ constructor() {
+ super();
+ subscribe(this, allRunsLatestPatchsetLatestAttempt$, x => (this.runs = x));
+ }
+
override render() {
const submit_requirements = (this.change?.submit_requirements ?? []).filter(
req => req.status !== SubmitRequirementStatus.NOT_APPLICABLE
@@ -130,7 +155,12 @@
.text="${requirement.name}"
></gr-limited-text>
</td>
- <td>${this.renderVotes(requirement)}</td>
+ <td>
+ <div class="votes-cell">
+ ${this.renderVotes(requirement)}
+ ${this.renderChecks(requirement)}
+ </div>
+ </td>
</tr>`
)}
</tbody>
@@ -199,6 +229,28 @@
);
}
+ renderChecks(requirement: SubmitRequirementResultInfo) {
+ const requirementLabels = extractAssociatedLabels(requirement);
+ const requirementRuns = this.runs
+ .filter(run => hasResultsOf(run, Category.ERROR))
+ .filter(
+ run => run.labelName && requirementLabels.includes(run.labelName)
+ );
+ const runsCount = requirementRuns.reduce(
+ (sum, run) => sum + getResultsOf(run, Category.ERROR).length,
+ 0
+ );
+ if (runsCount > 0) {
+ return html`<span class="check-error"
+ ><iron-icon icon="gr-icons:error"></iron-icon>${pluralize(
+ runsCount,
+ 'error'
+ )}</span
+ >`;
+ }
+ return;
+ }
+
renderTriggerVotes(submitReqs: SubmitRequirementResultInfo[]) {
const labels = this.change?.labels ?? {};
const allLabels = Object.keys(labels);
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
index c9f07f7..c197599 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
@@ -303,9 +303,6 @@
renderStatusLink() {
const link = this.run.statusLink;
if (!link) return;
- // For COMPLETED we think that the status link are too much clutter.
- // That could be re-considered.
- if (this.run.status !== RunStatus.RUNNING) return;
return html`
<a href="${link}" target="_blank" @click="${this.onLinkClick}"
><iron-icon
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 4a6f009..8e70eb9 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -177,8 +177,8 @@
CHANGE_ID_QUERY: /^\/id\/(I[0-9a-f]{40})$/,
- // Matches /c/<changeNum>/[<basePatchNum>..][<patchNum>][/].
- CHANGE_LEGACY: /^\/c\/(\d+)\/?(((-?\d+|edit)(\.\.(\d+|edit))?))?\/?$/,
+ // Matches /c/<changeNum>/[*][/].
+ CHANGE_LEGACY: /^\/c\/(\d+)\/(.*)$/,
CHANGE_NUMBER_LEGACY: /^\/(\d+)\/?/,
// Matches
@@ -210,10 +210,6 @@
// Matches /c/<project>/+/<changeNum>/[<patchNum|edit>]/<path>,edit[#lineNum]
DIFF_EDIT: /^\/c\/(.+)\/\+\/(\d+)\/(\d+|edit)\/(.+),edit(#\d+)?$/,
- // Matches non-project-relative
- // /c/<changeNum>/[<basePatchNum>..]<patchNum>/<path>.
- DIFF_LEGACY: /^\/c\/(\d+)\/((-?\d+|edit)(\.\.(\d+|edit))?)\/(.+)/,
-
// Matches diff routes using @\d+ to specify a file name (whether or not
// the project name is included).
// eslint-disable-next-line max-len
@@ -287,15 +283,6 @@
type QueryStringItem = [string, string]; // [key, value]
-type GenerateUrlLegacyChangeViewParameters = Omit<
- GenerateUrlChangeViewParameters,
- 'project'
->;
-type GenerateUrlLegacyDiffViewParameters = Omit<
- GenerateUrlDiffViewParameters,
- 'project'
->;
-
interface PatchRangeParams {
patchNum?: PatchSetNum;
basePatchNum?: BasePatchSetNum;
@@ -679,37 +666,6 @@
}
/**
- * Given a set of params without a project, gets the project from the rest
- * API project lookup and then sets the app params.
- */
- _normalizeLegacyRouteParams(
- params: Readonly<
- | GenerateUrlLegacyChangeViewParameters
- | GenerateUrlLegacyDiffViewParameters
- >
- ) {
- if (!params.changeNum) {
- return Promise.resolve();
- }
-
- return this.restApiService
- .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.
*
@@ -1100,8 +1056,6 @@
this._mapRoute(RoutePattern.CHANGE_LEGACY, '_handleChangeLegacyRoute');
- this._mapRoute(RoutePattern.DIFF_LEGACY, '_handleDiffLegacyRoute');
-
this._mapRoute(RoutePattern.AGREEMENTS, '_handleAgreementsRoute', true);
this._mapRoute(
@@ -1666,41 +1620,26 @@
}
_handleChangeLegacyRoute(ctx: PageContextWithQueryMap) {
- // Parameter order is based on the regex group number matched.
- const params: GenerateUrlLegacyChangeViewParameters = {
- changeNum: Number(ctx.params[0]) as NumericChangeId,
- basePatchNum: convertToPatchSetNum(ctx.params[3]) as BasePatchSetNum,
- patchNum: convertToPatchSetNum(ctx.params[5]),
- view: GerritView.CHANGE,
- querystring: ctx.querystring,
- };
-
- this._normalizeLegacyRouteParams(params);
+ const changeNum = Number(ctx.params[0]) as NumericChangeId;
+ if (!changeNum) {
+ this._show404();
+ return;
+ }
+ this.restApiService.getFromProjectLookup(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;
+ }
+ this._redirect(`/c/${project}/+/${changeNum}/${ctx.params[1]}`);
+ });
}
_handleLegacyLinenum(ctx: PageContextWithQueryMap) {
this._redirect(ctx.path.replace(LEGACY_LINENUM_PATTERN, '#$1'));
}
- _handleDiffLegacyRoute(ctx: PageContextWithQueryMap) {
- // Parameter order is based on the regex group number matched.
- const params: GenerateUrlLegacyDiffViewParameters = {
- changeNum: Number(ctx.params[0]) as NumericChangeId,
- basePatchNum: convertToPatchSetNum(ctx.params[2]) as BasePatchSetNum,
- patchNum: convertToPatchSetNum(ctx.params[4]),
- path: ctx.params[5],
- view: GerritView.DIFF,
- };
-
- const address = this._parseLineAddress(ctx.hash);
- if (address) {
- params.leftSide = address.leftSide;
- params.lineNum = address.lineNum;
- }
-
- this._normalizeLegacyRouteParams(params);
- }
-
_handleDiffEditRoute(ctx: PageContextWithQueryMap) {
// Parameter order is based on the regex group number matched.
const project = ctx.params[0] as RepoName;
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.js b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.js
index 4c7855b..b91bf0c 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.js
@@ -192,7 +192,6 @@
'_handleDiffRoute',
'_handleDefaultRoute',
'_handleChangeLegacyRoute',
- '_handleDiffLegacyRoute',
'_handleDocumentationRedirectRoute',
'_handleDocumentationSearchRoute',
'_handleDocumentationSearchRedirectRoute',
@@ -536,66 +535,6 @@
});
suite('param normalization', () => {
- let projectLookupStub;
- let generateUrlStub;
-
- setup(() => {
- projectLookupStub = stubRestApi('getFromProjectLookup');
- generateUrlStub = sinon.stub(element, '_generateUrl');
- });
-
- suite('_normalizeLegacyRouteParams', () => {
- let rangeStub;
- let redirectStub;
- let show404Stub;
-
- setup(() => {
- rangeStub = sinon.stub(element, '_normalizePatchRangeParams')
- .returns(Promise.resolve());
- redirectStub = sinon.stub(element, '_redirect');
- show404Stub = sinon.stub(element, '_show404');
- });
-
- test('w/o changeNum', () => {
- projectLookupStub.returns(Promise.resolve('foo/bar'));
- const params = {};
- return element._normalizeLegacyRouteParams(params).then(() => {
- assert.isFalse(generateUrlStub.calledOnce);
- assert.isFalse(projectLookupStub.called);
- assert.isFalse(rangeStub.called);
- assert.isFalse(redirectStub.called);
- assert.isFalse(show404Stub.called);
- });
- });
-
- test('w/ changeNum', () => {
- projectLookupStub.returns(Promise.resolve('foo/bar'));
- const params = {changeNum: 1234};
-
- return element._normalizeLegacyRouteParams(params).then(() => {
- assert.isTrue(generateUrlStub.calledOnce);
- const updatedParams = generateUrlStub.lastCall.args[0];
- assert.isTrue(projectLookupStub.called);
- assert.isTrue(rangeStub.called);
- assert.equal(updatedParams.project, 'foo/bar');
- assert.isTrue(redirectStub.calledOnce);
- assert.isFalse(show404Stub.called);
- });
- });
-
- test('halts on project lookup failure', () => {
- projectLookupStub.returns(Promise.resolve(undefined));
- const params = {changeNum: 1234};
- return element._normalizeLegacyRouteParams(params).then(() => {
- assert.isFalse(generateUrlStub.calledOnce);
- assert.isTrue(projectLookupStub.called);
- assert.isFalse(rangeStub.called);
- assert.isFalse(redirectStub.called);
- assert.isTrue(show404Stub.calledOnce);
- });
- });
- });
-
suite('_normalizePatchRangeParams', () => {
test('range n..n normalizes to n', () => {
const params = {basePatchNum: 4, patchNum: 4};
@@ -1367,58 +1306,19 @@
assert.isTrue(redirectStub.calledWithExactly('/c/12345'));
});
- test('_handleChangeLegacyRoute', () => {
- const normalizeRouteStub = sinon.stub(element,
- '_normalizeLegacyRouteParams');
+ test('_handleChangeLegacyRoute', async () => {
+ stubRestApi('getFromProjectLookup').returns(Promise.resolve('project'));
const ctx = {
params: [
1234, // 0 Change number
- null, // 1 Unused
- null, // 2 Unused
- 6, // 3 Base patch number
- null, // 4 Unused
- 9, // 5 Patch number
+ 'comment/6789',
],
querystring: '',
};
element._handleChangeLegacyRoute(ctx);
- assert.isTrue(normalizeRouteStub.calledOnce);
- assert.deepEqual(normalizeRouteStub.lastCall.args[0], {
- changeNum: 1234,
- basePatchNum: 6,
- patchNum: 9,
- view: GerritView.CHANGE,
- querystring: '',
- });
- });
-
- test('_handleDiffLegacyRoute', () => {
- const normalizeRouteStub = sinon.stub(element,
- '_normalizeLegacyRouteParams');
- const ctx = {
- params: [
- 1234, // 0 Change number
- null, // 1 Unused
- 3, // 2 Base patch number
- null, // 3 Unused
- 8, // 4 Patch number
- 'foo/bar', // 5 Diff path
- ],
- path: '/c/1234/3..8/foo/bar',
- hash: 'b123',
- };
- element._handleDiffLegacyRoute(ctx);
- assert.isFalse(redirectStub.called);
- assert.isTrue(normalizeRouteStub.calledOnce);
- assert.deepEqual(normalizeRouteStub.lastCall.args[0], {
- changeNum: 1234,
- basePatchNum: 3,
- patchNum: 8,
- view: GerritView.DIFF,
- path: 'foo/bar',
- lineNum: 123,
- leftSide: true,
- });
+ await flush();
+ assert.isTrue(redirectStub.calledWithExactly('/c/project/+/1234' +
+ '/comment/6789'));
});
test('_handleLegacyLinenum w/ @321', () => {
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.ts b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.ts
index d8e43ce..96b1ded 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.ts
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.ts
@@ -20,16 +20,13 @@
import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-change-table-editor_html';
-import {ChangeTableMixin} from '../../../mixins/gr-change-table-mixin/gr-change-table-mixin';
import {customElement, property, observe} from '@polymer/decorators';
import {ServerInfo} from '../../../types/common';
import {appContext} from '../../../services/app-context';
-
-// This avoids JSC_DYNAMIC_EXTENDS_WITHOUT_JSDOC closure compiler error.
-const base = ChangeTableMixin(PolymerElement);
+import {columnNames} from '../../change-list/gr-change-list/gr-change-list';
@customElement('gr-change-table-editor')
-export class GrChangeTableEditor extends base {
+export class GrChangeTableEditor extends PolymerElement {
static get template() {
return htmlTemplate;
}
@@ -50,18 +47,33 @@
@observe('serverConfig')
_configChanged(config: ServerInfo) {
- this.defaultColumns = this.getEnabledColumns(
- this.columnNames,
- config,
- this.flagsService.enabledExperiments
+ this.defaultColumns = columnNames.filter(col =>
+ this._isColumnEnabled(col, config, this.flagsService.enabledExperiments)
);
if (!this.displayedColumns) return;
this.displayedColumns = this.displayedColumns.filter(column =>
- this.isColumnEnabled(column, config, this.flagsService.enabledExperiments)
+ this._isColumnEnabled(
+ column,
+ config,
+ this.flagsService.enabledExperiments
+ )
);
}
/**
+ * Is the column disabled by a server config or experiment? For example the
+ * assignee feature might be disabled and thus the corresponding column is
+ * also disabled.
+ *
+ */
+ _isColumnEnabled(column: string, config: ServerInfo, experiments: string[]) {
+ if (!config || !config.change) return true;
+ if (column === 'Assignee') return !!config.change.enable_assignee;
+ if (column === 'Comments') return experiments.includes('comments-column');
+ return true;
+ }
+
+ /**
* Get the list of enabled column names from whichever checkboxes are
* checked (excluding the number checkbox).
*/
@@ -78,6 +90,13 @@
.map(checkbox => checkbox.name);
}
+ _computeIsColumnHidden(columnToCheck?: string, columnsToDisplay?: string[]) {
+ if (!columnsToDisplay || !columnToCheck) {
+ return false;
+ }
+ return !columnsToDisplay.includes(columnToCheck);
+ }
+
/**
* Handle a click on a checkbox container and relay the click to the checkbox it
* contains.
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_html.ts b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_html.ts
index a05ec73..e756a20 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_html.ts
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_html.ts
@@ -74,7 +74,7 @@
type="checkbox"
name="[[item]]"
on-click="_handleTargetClick"
- checked$="[[!isColumnHidden(item, displayedColumns)]]"
+ checked$="[[!_computeIsColumnHidden(item, displayedColumns)]]"
/>
</td>
</tr>
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.ts b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.ts
index 4f61972..4f8d0a0 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.ts
@@ -117,7 +117,7 @@
test('_getDisplayedColumns', () => {
const enabledColumns = columns.filter(column =>
- element.isColumnEnabled(column, element.serverConfig!, [])
+ element._isColumnEnabled(column, element.serverConfig!, [])
);
assert.deepEqual(element._getDisplayedColumns(), enabledColumns);
const input = queryAndAssert<HTMLInputElement>(
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 de84eae..94333c7 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
@@ -46,7 +46,6 @@
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-settings-view_html';
import {getDocsBaseUrl} from '../../../utils/url-util';
-import {ChangeTableMixin} from '../../../mixins/gr-change-table-mixin/gr-change-table-mixin';
import {customElement, property, observe} from '@polymer/decorators';
import {AppElementParams} from '../../gr-app-types';
import {GrAccountInfo} from '../gr-account-info/gr-account-info';
@@ -75,6 +74,7 @@
EmailStrategy,
TimeFormat,
} from '../../../constants/constants';
+import {columnNames} from '../../change-list/gr-change-list/gr-change-list';
const PREFS_SECTION_FIELDS: Array<keyof PreferencesInput> = [
'changes_per_page',
@@ -138,11 +138,8 @@
};
}
-// This avoids JSC_DYNAMIC_EXTENDS_WITHOUT_JSDOC closure compiler error.
-const base = ChangeTableMixin(PolymerElement);
-
@customElement('gr-settings-view')
-export class GrSettingsView extends base {
+export class GrSettingsView extends PolymerElement {
static get template() {
return htmlTemplate;
}
@@ -261,8 +258,10 @@
this._localMenu = this._cloneMenu(prefs.my);
this._localChangeTableColumns =
prefs.change_table.length === 0
- ? this.columnNames
- : this.renameProjectToRepoColumn(prefs.change_table);
+ ? columnNames
+ : prefs.change_table.map(column =>
+ column === 'Project' ? 'Repo' : column
+ );
})
);
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 b214be0..fa04860 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
@@ -674,7 +674,13 @@
@observe('comment.message')
_commentMessageChanged(message: string) {
- this._messageText = message || '';
+ /*
+ * Only overwrite the message text user has typed if there is no existing
+ * text typed by the user. This prevents the bug where creating another
+ * comment triggered a recomputation of comments and the text written by
+ * the user was lost.
+ */
+ if (!this._messageText) this._messageText = message || '';
}
_messageTextChanged(_: string, oldValue: string) {
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.ts b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.ts
index 31a1614..b963d4b 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.ts
@@ -217,6 +217,29 @@
assert.isTrue(storageStub.called);
});
+ test('comment message sets messageText only when empty', () => {
+ element.changeNum = 1 as NumericChangeId;
+ element.patchNum = 1 as PatchSetNum;
+ element._messageText = '';
+ element.comment = {
+ author: {
+ name: 'Mr. Peanutbutter',
+ email: 'tenn1sballchaser@aol.com' as EmailAddress,
+ },
+ line: 5,
+ path: 'test',
+ __editing: true,
+ __draft: true,
+ message: 'hello world',
+ };
+ // messageText was empty so overwrite the message now
+ assert.equal(element._messageText, 'hello world');
+
+ element.comment!.message = 'new message';
+ // messageText was already set so do not overwrite it
+ assert.equal(element._messageText, 'hello world');
+ });
+
test('_getPatchNum', () => {
element.side = 'PARENT';
element.patchNum = 1 as PatchSetNum;
diff --git a/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin.ts b/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin.ts
deleted file mode 100644
index 9e4608f..0000000
--- a/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * @license
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import {PolymerElement} from '@polymer/polymer';
-import {Constructor} from '../../utils/common-util';
-import {property} from '@polymer/decorators';
-import {ServerInfo} from '../../types/common';
-
-/**
- * @polymer
- * @mixinFunction
- */
-export const ChangeTableMixin = <T extends Constructor<PolymerElement>>(
- superClass: T
-) => {
- /**
- * @polymer
- * @mixinClass
- */
- class Mixin extends superClass {
- @property({type: Array})
- readonly columnNames: string[] = [
- 'Subject',
- 'Status',
- 'Owner',
- 'Assignee',
- 'Reviewers',
- 'Comments',
- 'Repo',
- 'Branch',
- 'Updated',
- 'Size',
- ];
-
- isColumnHidden(columnToCheck?: string, columnsToDisplay?: string[]) {
- if (!columnsToDisplay || !columnToCheck) {
- return false;
- }
- return !columnsToDisplay.includes(columnToCheck);
- }
-
- /**
- * Is the column disabled by a server config or experiment? For example the
- * assignee feature might be disabled and thus the corresponding column is
- * also disabled.
- *
- */
- isColumnEnabled(column: string, config: ServerInfo, experiments: string[]) {
- if (!config || !config.change) return true;
- if (column === 'Assignee') return !!config.change.enable_assignee;
- if (column === 'Comments') return experiments.includes('comments-column');
- return true;
- }
-
- /**
- * @return enabled columns, see isColumnEnabled().
- */
- getEnabledColumns(
- columns: string[],
- config: ServerInfo,
- experiments: string[]
- ) {
- return columns.filter(col =>
- this.isColumnEnabled(col, config, experiments)
- );
- }
-
- /**
- * The Project column was renamed to Repo, but some users may have
- * preferences that use its old name. If that column is found, rename it
- * before use.
- *
- * @return If the column was renamed, returns a new array
- * with the corrected name. Otherwise, it returns the original param.
- */
- renameProjectToRepoColumn(columns: string[]) {
- const projectIndex = columns.indexOf('Project');
- if (projectIndex === -1) {
- return columns;
- }
- const newColumns = [...columns];
- newColumns[projectIndex] = 'Repo';
- return newColumns;
- }
- }
-
- return Mixin as T & Constructor<ChangeTableMixinInterface>;
-};
-
-export interface ChangeTableMixinInterface {
- readonly columnNames: string[];
- isColumnHidden(columnToCheck?: string, columnsToDisplay?: string[]): boolean;
- isColumnEnabled(
- column: string,
- config: ServerInfo,
- experiments: string[]
- ): boolean;
- getEnabledColumns(
- columns: string[],
- config: ServerInfo,
- experiments: string[]
- ): string[];
- renameProjectToRepoColumn(columns: string[]): string[];
-}
diff --git a/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin_test.js b/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin_test.js
deleted file mode 100644
index 8bc223f..0000000
--- a/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin_test.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * @license
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import '../../test/common-test-setup-karma.js';
-import {ChangeTableMixin} from './gr-change-table-mixin.js';
-import {PolymerElement} from '@polymer/polymer/polymer-element.js';
-
-// This avoids JSC_DYNAMIC_EXTENDS_WITHOUT_JSDOC closure compiler error.
-const base = ChangeTableMixin(PolymerElement);
-
-class GrChangeTableMixinTestElement extends base {
- static get is() { return 'gr-change-table-mixin-test-element'; }
-}
-
-customElements.define(GrChangeTableMixinTestElement.is,
- GrChangeTableMixinTestElement);
-
-const basicFixture = fixtureFromElement(
- 'gr-change-table-mixin-test-element');
-
-suite('gr-change-table-mixin tests', () => {
- let element;
-
- setup(() => {
- element = basicFixture.instantiate();
- });
-
- test('isColumnHidden', () => {
- const columnToCheck = 'Repo';
- let columnsToDisplay = [
- 'Subject',
- 'Status',
- 'Owner',
- 'Assignee',
- 'Repo',
- 'Branch',
- 'Updated',
- 'Size',
- ];
- assert.isFalse(element.isColumnHidden(columnToCheck, columnsToDisplay));
-
- columnsToDisplay = [
- 'Subject',
- 'Status',
- 'Owner',
- 'Assignee',
- 'Branch',
- 'Updated',
- 'Size',
- ];
- assert.isTrue(element.isColumnHidden(columnToCheck, columnsToDisplay));
- });
-
- test('renameProjectToRepoColumn maps Project to Repo', () => {
- const columns = [
- 'Subject',
- 'Status',
- 'Owner',
- ];
- assert.deepEqual(element.renameProjectToRepoColumn(columns),
- columns.slice(0));
- assert.deepEqual(
- element.renameProjectToRepoColumn(columns.concat(['Project'])),
- columns.slice(0).concat(['Repo']));
- });
-});
-