Merge "Remove gitweb providing edit weblink"
diff --git a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
index ea9495c..4c26f89 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
@@ -37,7 +37,7 @@
declare global {
interface HTMLElementEventMap {
- 'text-changed': CustomEvent;
+ 'text-changed': CustomEvent<string>;
'value-changed': CustomEvent;
}
interface HTMLElementTagNameMap {
diff --git a/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts b/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts
index 8faa5e7..6054d9c 100644
--- a/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts
+++ b/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts
@@ -57,7 +57,7 @@
declare global {
interface HTMLElementEventMap {
- 'text-changed': CustomEvent;
+ 'text-changed': CustomEvent<string>;
'value-changed': CustomEvent;
}
interface HTMLElementTagNameMap {
diff --git a/polygerrit-ui/app/elements/change/gr-message-scores/gr-message-scores.ts b/polygerrit-ui/app/elements/change/gr-message-scores/gr-message-scores.ts
new file mode 100644
index 0000000..9492fa9
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-message-scores/gr-message-scores.ts
@@ -0,0 +1,169 @@
+/**
+ * @license
+ * Copyright (C) 2021 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 {LitElement, css, html} from 'lit';
+import {customElement, property} from 'lit/decorators';
+import {
+ ChangeMessage,
+ LabelExtreme,
+ PATCH_SET_PREFIX_PATTERN,
+} from '../../../utils/comment-util';
+import {hasOwnProperty} from '../../../utils/common-util';
+
+const VOTE_RESET_TEXT = '0 (vote reset)';
+
+interface Score {
+ label?: string;
+ value?: string;
+}
+
+export const LABEL_TITLE_SCORE_PATTERN =
+ /^(-?)([A-Za-z0-9-]+?)([+-]\d+)?[.:]?$/;
+
+@customElement('gr-message-scores')
+export class GrMessageScores extends LitElement {
+ @property()
+ labelExtremes?: LabelExtreme;
+
+ @property({type: Object})
+ message?: ChangeMessage;
+
+ static override get styles() {
+ return css`
+ .score {
+ box-sizing: border-box;
+ border-radius: var(--border-radius);
+ color: var(--vote-text-color);
+ display: inline-block;
+ padding: 0 var(--spacing-s);
+ text-align: center;
+ margin-right: var(--spacing-s);
+ min-width: 115px;
+ }
+ .score.removed {
+ background-color: var(--vote-color-neutral);
+ }
+ .score.negative {
+ background-color: var(--vote-color-disliked);
+ border: 1px solid var(--vote-outline-disliked);
+ line-height: calc(var(--line-height-normal) - 2px);
+ color: var(--chip-color);
+ }
+ .score.negative.min {
+ background-color: var(--vote-color-rejected);
+ border: none;
+ padding-top: 1px;
+ padding-bottom: 1px;
+ color: var(--vote-text-color);
+ }
+ .score.positive {
+ background-color: var(--vote-color-recommended);
+ border: 1px solid var(--vote-outline-recommended);
+ line-height: calc(var(--line-height-normal) - 2px);
+ color: var(--chip-color);
+ }
+ .score.positive.max {
+ background-color: var(--vote-color-approved);
+ border: none;
+ padding-top: 1px;
+ padding-bottom: 1px;
+ color: var(--vote-text-color);
+ }
+
+ @media screen and (max-width: 50em) {
+ .score {
+ min-width: 0px;
+ }
+ }
+ `;
+ }
+
+ override render() {
+ const scores = this._getScores(this.message, this.labelExtremes);
+ return scores.map(score => this.renderScore(score));
+ }
+
+ private renderScore(score: Score) {
+ return html`<span
+ class="score ${this._computeScoreClass(score, this.labelExtremes)}"
+ >
+ ${score.label} ${score.value}
+ </span>`;
+ }
+
+ _computeScoreClass(score?: Score, labelExtremes?: LabelExtreme) {
+ // Polymer 2: check for undefined
+ if (score === undefined || labelExtremes === undefined) {
+ return '';
+ }
+ if (!score.value) {
+ return '';
+ }
+ if (score.value.includes(VOTE_RESET_TEXT)) {
+ return 'removed';
+ }
+ const classes = [];
+ if (Number(score.value) > 0) {
+ classes.push('positive');
+ } else if (Number(score.value) < 0) {
+ classes.push('negative');
+ }
+ if (score.label) {
+ const extremes = labelExtremes[score.label];
+ if (extremes) {
+ const intScore = Number(score.value);
+ if (intScore === extremes.max) {
+ classes.push('max');
+ } else if (intScore === extremes.min) {
+ classes.push('min');
+ }
+ }
+ }
+ return classes.join(' ');
+ }
+
+ _getScores(message?: ChangeMessage, labelExtremes?: LabelExtreme): Score[] {
+ if (!message || !message.message || !labelExtremes) {
+ return [];
+ }
+ const line = message.message.split('\n', 1)[0];
+ const patchSetPrefix = PATCH_SET_PREFIX_PATTERN;
+ if (!line.match(patchSetPrefix)) {
+ return [];
+ }
+ const scoresRaw = line.split(patchSetPrefix)[1];
+ if (!scoresRaw) {
+ return [];
+ }
+ return scoresRaw
+ .split(' ')
+ .map(s => s.match(LABEL_TITLE_SCORE_PATTERN))
+ .filter(
+ ms => ms && ms.length === 4 && hasOwnProperty(labelExtremes, ms[2])
+ )
+ .map(ms => {
+ const label = ms?.[2];
+ const value = ms?.[1] === '-' ? VOTE_RESET_TEXT : ms?.[3];
+ return {label, value};
+ });
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'gr-message-scores': GrMessageScores;
+ }
+}
diff --git a/polygerrit-ui/app/elements/change/gr-message-scores/gr-message-scores_test.ts b/polygerrit-ui/app/elements/change/gr-message-scores/gr-message-scores_test.ts
new file mode 100644
index 0000000..7398909
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-message-scores/gr-message-scores_test.ts
@@ -0,0 +1,136 @@
+/**
+ * @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';
+import './gr-message-scores';
+import {createChangeMessage} from '../../../test/test-data-generators';
+import {queryAll} from '../../../test/test-utils';
+import {GrMessageScores} from './gr-message-scores';
+
+const basicFixture = fixtureFromElement('gr-message-scores');
+
+suite('gr-message-score tests', () => {
+ let element: GrMessageScores;
+
+ setup(async () => {
+ element = basicFixture.instantiate();
+ await element.updateComplete;
+ });
+
+ test('votes', async () => {
+ element.message = {
+ ...createChangeMessage(),
+ author: {},
+ expanded: false,
+ message: 'Patch Set 1: Verified+1 Code-Review-2 Trybot-Label3+1 Blub+1',
+ };
+ element.labelExtremes = {
+ Verified: {max: 1, min: -1},
+ 'Code-Review': {max: 2, min: -2},
+ 'Trybot-Label3': {max: 3, min: 0},
+ };
+ await element.updateComplete;
+ const scoreChips = queryAll(element, '.score');
+ assert.equal(scoreChips.length, 3);
+
+ assert.isTrue(scoreChips[0].classList.contains('positive'));
+ assert.isTrue(scoreChips[0].classList.contains('max'));
+
+ assert.isTrue(scoreChips[1].classList.contains('negative'));
+ assert.isTrue(scoreChips[1].classList.contains('min'));
+
+ assert.isTrue(scoreChips[2].classList.contains('positive'));
+ assert.isFalse(scoreChips[2].classList.contains('min'));
+ });
+
+ test('Uploaded patch set X', async () => {
+ element.message = {
+ ...createChangeMessage(),
+ author: {},
+ expanded: false,
+ message:
+ 'Uploaded patch set 1:' +
+ 'Verified+1 Code-Review-2 Trybot-Label3+1 Blub+1',
+ };
+ element.labelExtremes = {
+ Verified: {max: 1, min: -1},
+ 'Code-Review': {max: 2, min: -2},
+ 'Trybot-Label3': {max: 3, min: 0},
+ };
+ await element.updateComplete;
+ const scoreChips = queryAll(element, '.score');
+ assert.equal(scoreChips.length, 3);
+
+ assert.isTrue(scoreChips[0].classList.contains('positive'));
+ assert.isTrue(scoreChips[0].classList.contains('max'));
+
+ assert.isTrue(scoreChips[1].classList.contains('negative'));
+ assert.isTrue(scoreChips[1].classList.contains('min'));
+
+ assert.isTrue(scoreChips[2].classList.contains('positive'));
+ assert.isFalse(scoreChips[2].classList.contains('min'));
+ });
+
+ test('Uploaded and rebased', async () => {
+ element.message = {
+ ...createChangeMessage(),
+ author: {},
+ expanded: false,
+ message: 'Uploaded patch set 4: Commit-Queue+1: Patch Set 3 was rebased.',
+ };
+ element.labelExtremes = {
+ 'Commit-Queue': {max: 2, min: -2},
+ };
+ await element.updateComplete;
+ const scoreChips = queryAll(element, '.score');
+ assert.equal(scoreChips.length, 1);
+ assert.isTrue(scoreChips[0].classList.contains('positive'));
+ });
+
+ test('removed votes', async () => {
+ element.message = {
+ ...createChangeMessage(),
+ author: {},
+ expanded: false,
+ message: 'Patch Set 1: Verified+1 -Code-Review -Commit-Queue',
+ };
+ element.labelExtremes = {
+ Verified: {max: 1, min: -1},
+ 'Code-Review': {max: 2, min: -2},
+ 'Commit-Queue': {max: 3, min: 0},
+ };
+ await element.updateComplete;
+ const scoreChips = queryAll(element, '.score');
+ assert.equal(scoreChips.length, 3);
+
+ assert.isTrue(scoreChips[1].classList.contains('removed'));
+ assert.isTrue(scoreChips[2].classList.contains('removed'));
+ });
+
+ test('false negative vote', async () => {
+ element.message = {
+ ...createChangeMessage(),
+ author: {},
+ expanded: false,
+ message: 'Patch Set 1: Cherry Picked from branch stable-2.14.',
+ };
+ element.labelExtremes = {};
+ await element.updateComplete;
+ const scoreChips = element.shadowRoot?.querySelectorAll('.score');
+ assert.equal(scoreChips?.length, 0);
+ });
+});
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.ts b/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
index cc7cf88..8664de3 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
@@ -22,26 +22,29 @@
import '../../shared/gr-date-formatter/gr-date-formatter';
import '../../shared/gr-formatted-text/gr-formatted-text';
import '../../../styles/shared-styles';
+import '../gr-message-scores/gr-message-scores';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-message_html';
import {MessageTag, SpecialFilePath} from '../../../constants/constants';
import {customElement, property, computed, observe} from '@polymer/decorators';
import {
ChangeInfo,
- ChangeMessageInfo,
ServerInfo,
ConfigInfo,
RepoName,
ReviewInputTag,
- VotingRangeInfo,
NumericChangeId,
ChangeMessageId,
PatchSetNum,
AccountInfo,
BasePatchSetNum,
} from '../../../types/common';
-import {CommentThread} from '../../../utils/comment-util';
-import {hasOwnProperty} from '../../../utils/common-util';
+import {
+ ChangeMessage,
+ CommentThread,
+ LabelExtreme,
+ PATCH_SET_PREFIX_PATTERN,
+} from '../../../utils/comment-util';
import {getAppContext} from '../../../services/app-context';
import {pluralize} from '../../../utils/string-util';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
@@ -52,12 +55,8 @@
} from '../../../utils/patch-set-util';
import {isServiceUser, replaceTemplates} from '../../../utils/account-util';
-const PATCH_SET_PREFIX_PATTERN = /^(?:Uploaded\s*)?[Pp]atch [Ss]et \d+:\s*(.*)/;
-const LABEL_TITLE_SCORE_PATTERN = /^(-?)([A-Za-z0-9-]+?)([+-]\d+)?[.:]?$/;
const UPLOADED_NEW_PATCHSET_PATTERN = /Uploaded patch set (\d+)./;
const MERGED_PATCHSET_PATTERN = /(\d+) is the latest approved patch-set/;
-const VOTE_RESET_TEXT = '0 (vote reset)';
-
declare global {
interface HTMLElementTagNameMap {
'gr-message': GrMessage;
@@ -68,20 +67,6 @@
id: ChangeMessageId;
}
-export interface ChangeMessage extends ChangeMessageInfo {
- // TODO(TS): maybe should be an enum instead
- type: string;
- expanded: boolean;
- commentThreads: CommentThread[];
-}
-
-export type LabelExtreme = {[labelName: string]: VotingRangeInfo};
-
-interface Score {
- label?: string;
- value?: string;
-}
-
@customElement('gr-message')
export class GrMessage extends PolymerElement {
static get template() {
@@ -444,63 +429,6 @@
return message.type === 'REVIEWER_UPDATE';
}
- _getScores(message?: ChangeMessage, labelExtremes?: LabelExtreme): Score[] {
- if (!message || !message.message || !labelExtremes) {
- return [];
- }
- const line = message.message.split('\n', 1)[0];
- const patchSetPrefix = PATCH_SET_PREFIX_PATTERN;
- if (!line.match(patchSetPrefix)) {
- return [];
- }
- const scoresRaw = line.split(patchSetPrefix)[1];
- if (!scoresRaw) {
- return [];
- }
- return scoresRaw
- .split(' ')
- .map(s => s.match(LABEL_TITLE_SCORE_PATTERN))
- .filter(
- ms => ms && ms.length === 4 && hasOwnProperty(labelExtremes, ms[2])
- )
- .map(ms => {
- const label = ms?.[2];
- const value = ms?.[1] === '-' ? VOTE_RESET_TEXT : ms?.[3];
- return {label, value};
- });
- }
-
- _computeScoreClass(score?: Score, labelExtremes?: LabelExtreme) {
- // Polymer 2: check for undefined
- if (score === undefined || labelExtremes === undefined) {
- return '';
- }
- if (!score.value) {
- return '';
- }
- if (score.value.includes(VOTE_RESET_TEXT)) {
- return 'removed';
- }
- const classes = [];
- if (Number(score.value) > 0) {
- classes.push('positive');
- } else if (Number(score.value) < 0) {
- classes.push('negative');
- }
- if (score.label) {
- const extremes = labelExtremes[score.label];
- if (extremes) {
- const intScore = Number(score.value);
- if (intScore === extremes.max) {
- classes.push('max');
- } else if (intScore === extremes.min) {
- classes.push('min');
- }
- }
- }
- return classes.join(' ');
- }
-
_computeClass(expanded?: boolean, author?: AccountInfo) {
const classes = [];
classes.push(expanded ? 'expanded' : 'collapsed');
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message_html.ts b/polygerrit-ui/app/elements/change/gr-message/gr-message_html.ts
index 8def279..628af83 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message_html.ts
@@ -144,15 +144,6 @@
cursor: pointer;
vertical-align: top;
}
- .score {
- box-sizing: border-box;
- border-radius: var(--border-radius);
- color: var(--vote-text-color);
- display: inline-block;
- padding: 0 var(--spacing-s);
- text-align: center;
- }
- .score,
.commentsSummary {
margin-right: var(--spacing-s);
min-width: 115px;
@@ -163,35 +154,6 @@
.commentsIcon {
vertical-align: top;
}
- .score.removed {
- background-color: var(--vote-color-neutral);
- }
- .score.negative {
- background-color: var(--vote-color-disliked);
- border: 1px solid var(--vote-outline-disliked);
- line-height: calc(var(--line-height-normal) - 2px);
- color: var(--chip-color);
- }
- .score.negative.min {
- background-color: var(--vote-color-rejected);
- border: none;
- padding-top: 1px;
- padding-bottom: 1px;
- color: var(--vote-text-color);
- }
- .score.positive {
- background-color: var(--vote-color-recommended);
- border: 1px solid var(--vote-outline-recommended);
- line-height: calc(var(--line-height-normal) - 2px);
- color: var(--chip-color);
- }
- .score.positive.max {
- background-color: var(--vote-color-approved);
- border: none;
- padding-top: 1px;
- padding-bottom: 1px;
- color: var(--vote-text-color);
- }
gr-account-label::part(gr-account-label-text) {
font-weight: var(--font-weight-bold);
}
@@ -203,7 +165,6 @@
.expanded .content {
padding-left: 0;
}
- .score,
.commentsSummary {
min-width: 0px;
}
@@ -226,15 +187,10 @@
account="[[author]]"
class="authorLabel"
></gr-account-label>
- <template
- is="dom-repeat"
- items="[[_getScores(message, labelExtremes)]]"
- as="score"
- >
- <span class$="score [[_computeScoreClass(score, labelExtremes)]]">
- [[score.label]] [[score.value]]
- </span>
- </template>
+ <gr-message-scores
+ label-extremes="[[labelExtremes]]"
+ message="[[message]]"
+ ></gr-message-scores>
</div>
<template is="dom-if" if="[[_commentCountText]]">
<div class="commentsSummary">
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.ts b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.ts
index 0fd39d2..2acc2a8 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.ts
@@ -28,7 +28,6 @@
import {
mockPromise,
query,
- queryAll,
queryAndAssert,
stubRestApi,
} from '../../../test/test-utils';
@@ -463,109 +462,6 @@
assert.equal(actual, expected);
});
});
-
- test('votes', () => {
- element.message = {
- ...createChangeMessage(),
- author: {},
- expanded: false,
- message: 'Patch Set 1: Verified+1 Code-Review-2 Trybot-Label3+1 Blub+1',
- };
- element.labelExtremes = {
- Verified: {max: 1, min: -1},
- 'Code-Review': {max: 2, min: -2},
- 'Trybot-Label3': {max: 3, min: 0},
- };
- flush();
- const scoreChips = queryAll(element, '.score');
- assert.equal(scoreChips.length, 3);
-
- assert.isTrue(scoreChips[0].classList.contains('positive'));
- assert.isTrue(scoreChips[0].classList.contains('max'));
-
- assert.isTrue(scoreChips[1].classList.contains('negative'));
- assert.isTrue(scoreChips[1].classList.contains('min'));
-
- assert.isTrue(scoreChips[2].classList.contains('positive'));
- assert.isFalse(scoreChips[2].classList.contains('min'));
- });
-
- test('Uploaded patch set X', () => {
- element.message = {
- ...createChangeMessage(),
- author: {},
- expanded: false,
- message:
- 'Uploaded patch set 1:' +
- 'Verified+1 Code-Review-2 Trybot-Label3+1 Blub+1',
- };
- element.labelExtremes = {
- Verified: {max: 1, min: -1},
- 'Code-Review': {max: 2, min: -2},
- 'Trybot-Label3': {max: 3, min: 0},
- };
- flush();
- const scoreChips = queryAll(element, '.score');
- assert.equal(scoreChips.length, 3);
-
- assert.isTrue(scoreChips[0].classList.contains('positive'));
- assert.isTrue(scoreChips[0].classList.contains('max'));
-
- assert.isTrue(scoreChips[1].classList.contains('negative'));
- assert.isTrue(scoreChips[1].classList.contains('min'));
-
- assert.isTrue(scoreChips[2].classList.contains('positive'));
- assert.isFalse(scoreChips[2].classList.contains('min'));
- });
-
- test('Uploaded and rebased', () => {
- element.message = {
- ...createChangeMessage(),
- author: {},
- expanded: false,
- message:
- 'Uploaded patch set 4: Commit-Queue+1: Patch Set 3 was rebased.',
- };
- element.labelExtremes = {
- 'Commit-Queue': {max: 2, min: -2},
- };
- flush();
- const scoreChips = queryAll(element, '.score');
- assert.equal(scoreChips.length, 1);
- assert.isTrue(scoreChips[0].classList.contains('positive'));
- });
-
- test('removed votes', () => {
- element.message = {
- ...createChangeMessage(),
- author: {},
- expanded: false,
- message: 'Patch Set 1: Verified+1 -Code-Review -Commit-Queue',
- };
- element.labelExtremes = {
- Verified: {max: 1, min: -1},
- 'Code-Review': {max: 2, min: -2},
- 'Commit-Queue': {max: 3, min: 0},
- };
- flush();
- const scoreChips = queryAll(element, '.score');
- assert.equal(scoreChips.length, 3);
-
- assert.isTrue(scoreChips[1].classList.contains('removed'));
- assert.isTrue(scoreChips[2].classList.contains('removed'));
- });
-
- test('false negative vote', () => {
- element.message = {
- ...createChangeMessage(),
- author: {},
- expanded: false,
- message: 'Patch Set 1: Cherry Picked from branch stable-2.14.',
- };
- element.labelExtremes = {};
- const scoreChips = element.root!.querySelectorAll('.score');
- assert.equal(scoreChips.length, 0);
- });
});
suite('when not logged in', () => {
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts
index 3c1baa6..851cf9a 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts
@@ -41,7 +41,11 @@
ReviewerUpdateInfo,
VotingRangeInfo,
} from '../../../types/common';
-import {CommentThread, isRobot} from '../../../utils/comment-util';
+import {
+ CommentThread,
+ isRobot,
+ LabelExtreme,
+} from '../../../utils/comment-util';
import {GrMessage, MessageAnchorTapDetail} from '../gr-message/gr-message';
import {PolymerDeepPropertyChange} from '@polymer/polymer/interfaces';
import {DomRepeat} from '@polymer/polymer/lib/elements/dom-repeat';
@@ -249,7 +253,7 @@
_combinedMessages: CombinedMessage[] = [];
@property({type: Object, computed: '_computeLabelExtremes(labels.*)'})
- _labelExtremes: {[labelName: string]: VotingRangeInfo} = {};
+ _labelExtremes: LabelExtreme = {};
private readonly userModel = getAppContext().userModel;
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 15a971a1..8fa2fa4 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,9 +16,10 @@
*/
import '../../shared/gr-label-info/gr-label-info';
import '../gr-submit-requirement-hovercard/gr-submit-requirement-hovercard';
-import '../gr-trigger-vote-hovercard/gr-trigger-vote-hovercard';
+import '../gr-trigger-vote/gr-trigger-vote';
import '../gr-change-summary/gr-change-summary';
import '../../shared/gr-limited-text/gr-limited-text';
+import '../../shared/gr-vote-chip/gr-vote-chip';
import {LitElement, css, html, TemplateResult} from 'lit';
import {customElement, property, state} from 'lit/decorators';
import {ParsedChangeInfo} from '../../../types/types';
@@ -26,7 +27,6 @@
AccountInfo,
isDetailedLabelInfo,
isQuickLabelInfo,
- LabelInfo,
LabelNameToInfoMap,
SubmitRequirementResultInfo,
SubmitRequirementStatus,
@@ -47,7 +47,6 @@
import {CheckRun} from '../../../models/checks/checks-model';
import {getResultsOf, hasResultsOf} from '../../../models/checks/checks-util';
import {Category} from '../../../api/checks';
-import '../../shared/gr-vote-chip/gr-vote-chip';
import {fireShowPrimaryTab} from '../../../utils/event-util';
import {PrimaryTab} from '../../../constants/constants';
import {submitRequirementsStyles} from '../../../styles/gr-submit-requirements-styles';
@@ -371,103 +370,8 @@
}
}
-@customElement('gr-trigger-vote')
-export class GrTriggerVote extends LitElement {
- @property()
- label?: string;
-
- @property({type: Object})
- labelInfo?: LabelInfo;
-
- @property({type: Object})
- change?: ParsedChangeInfo;
-
- @property({type: Object})
- account?: AccountInfo;
-
- @property({type: Boolean})
- mutable?: boolean;
-
- static override get styles() {
- return css`
- :host {
- display: block;
- }
- .container {
- box-sizing: border-box;
- border: 1px solid var(--border-color);
- border-radius: calc(var(--border-radius) + 2px);
- background-color: var(--background-color-primary);
- display: flex;
- padding: 0;
- padding-left: var(--spacing-s);
- padding-right: var(--spacing-xxs);
- align-items: center;
- }
- .label {
- padding-right: var(--spacing-s);
- font-weight: var(--font-weight-bold);
- }
- gr-vote-chip {
- --gr-vote-chip-width: 14px;
- --gr-vote-chip-height: 14px;
- margin-right: 0px;
- margin-left: var(--spacing-xs);
- }
- gr-vote-chip:first-of-type {
- margin-left: 0px;
- }
- `;
- }
-
- override render() {
- if (!this.labelInfo) return;
- return html`
- <div class="container">
- <gr-trigger-vote-hovercard
- .labelName=${this.label}
- .labelInfo=${this.labelInfo}
- >
- <gr-label-info
- slot="label-info"
- .change=${this.change}
- .account=${this.account}
- .mutable=${this.mutable}
- .label=${this.label}
- .labelInfo=${this.labelInfo}
- .showAllReviewers=${false}
- ></gr-label-info>
- </gr-trigger-vote-hovercard>
- <span class="label">${this.label}</span>
- ${this.renderVotes()}
- </div>
- `;
- }
-
- private renderVotes() {
- const {labelInfo} = this;
- if (!labelInfo) return;
- if (isDetailedLabelInfo(labelInfo)) {
- const approvals = getAllUniqueApprovals(labelInfo).filter(
- approval => !hasNeutralStatus(labelInfo, approval)
- );
- return approvals.map(
- approvalInfo => html`<gr-vote-chip
- .vote="${approvalInfo}"
- .label="${labelInfo}"
- ></gr-vote-chip>`
- );
- } else if (isQuickLabelInfo(labelInfo)) {
- return [html`<gr-vote-chip .label="${this.labelInfo}"></gr-vote-chip>`];
- } else {
- return html``;
- }
- }
-}
-
declare global {
interface HTMLElementTagNameMap {
'gr-submit-requirements': GrSubmitRequirements;
- 'gr-trigger-vote': GrTriggerVote;
}
}
diff --git a/polygerrit-ui/app/elements/change/gr-trigger-vote/gr-trigger-vote.ts b/polygerrit-ui/app/elements/change/gr-trigger-vote/gr-trigger-vote.ts
new file mode 100644
index 0000000..d920b46
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-trigger-vote/gr-trigger-vote.ts
@@ -0,0 +1,132 @@
+/**
+ * @license
+ * Copyright (C) 2021 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 '../../shared/gr-label-info/gr-label-info';
+import '../../shared/gr-vote-chip/gr-vote-chip';
+import '../gr-trigger-vote-hovercard/gr-trigger-vote-hovercard';
+import {LitElement, css, html} from 'lit';
+import {customElement, property} from 'lit/decorators';
+import {ParsedChangeInfo} from '../../../types/types';
+import {
+ AccountInfo,
+ isDetailedLabelInfo,
+ isQuickLabelInfo,
+ LabelInfo,
+} from '../../../api/rest-api';
+import {
+ getAllUniqueApprovals,
+ hasNeutralStatus,
+} from '../../../utils/label-util';
+
+@customElement('gr-trigger-vote')
+export class GrTriggerVote extends LitElement {
+ @property()
+ label?: string;
+
+ @property({type: Object})
+ labelInfo?: LabelInfo;
+
+ @property({type: Object})
+ change?: ParsedChangeInfo;
+
+ @property({type: Object})
+ account?: AccountInfo;
+
+ @property({type: Boolean})
+ mutable?: boolean;
+
+ static override get styles() {
+ return css`
+ :host {
+ display: block;
+ }
+ .container {
+ box-sizing: border-box;
+ border: 1px solid var(--border-color);
+ border-radius: calc(var(--border-radius) + 2px);
+ background-color: var(--background-color-primary);
+ display: flex;
+ padding: 0;
+ padding-left: var(--spacing-s);
+ padding-right: var(--spacing-xxs);
+ align-items: center;
+ }
+ .label {
+ padding-right: var(--spacing-s);
+ font-weight: var(--font-weight-bold);
+ }
+ gr-vote-chip {
+ --gr-vote-chip-width: 14px;
+ --gr-vote-chip-height: 14px;
+ margin-right: 0px;
+ margin-left: var(--spacing-xs);
+ }
+ gr-vote-chip:first-of-type {
+ margin-left: 0px;
+ }
+ `;
+ }
+
+ override render() {
+ if (!this.labelInfo) return;
+ return html`
+ <div class="container">
+ <gr-trigger-vote-hovercard
+ .labelName=${this.label}
+ .labelInfo=${this.labelInfo}
+ >
+ <gr-label-info
+ slot="label-info"
+ .change=${this.change}
+ .account=${this.account}
+ .mutable=${this.mutable}
+ .label=${this.label}
+ .labelInfo=${this.labelInfo}
+ .showAllReviewers=${false}
+ ></gr-label-info>
+ </gr-trigger-vote-hovercard>
+ <span class="label">${this.label}</span>
+ ${this.renderVotes()}
+ </div>
+ `;
+ }
+
+ private renderVotes() {
+ const {labelInfo} = this;
+ if (!labelInfo) return;
+ if (isDetailedLabelInfo(labelInfo)) {
+ const approvals = getAllUniqueApprovals(labelInfo).filter(
+ approval => !hasNeutralStatus(labelInfo, approval)
+ );
+ return approvals.map(
+ approvalInfo => html`<gr-vote-chip
+ .vote="${approvalInfo}"
+ .label="${labelInfo}"
+ ></gr-vote-chip>`
+ );
+ } else if (isQuickLabelInfo(labelInfo)) {
+ return [html`<gr-vote-chip .label="${this.labelInfo}"></gr-vote-chip>`];
+ } else {
+ return html``;
+ }
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'gr-trigger-vote': GrTriggerVote;
+ }
+}
diff --git a/polygerrit-ui/app/elements/change/gr-trigger-vote/gr-trigger-vote_test.ts b/polygerrit-ui/app/elements/change/gr-trigger-vote/gr-trigger-vote_test.ts
new file mode 100644
index 0000000..cd25da0
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-trigger-vote/gr-trigger-vote_test.ts
@@ -0,0 +1,90 @@
+/**
+ * @license
+ * Copyright (C) 2021 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';
+import {fixture} from '@open-wc/testing-helpers';
+import {html} from 'lit';
+import './gr-trigger-vote';
+import {GrTriggerVote} from './gr-trigger-vote';
+import {
+ createAccountWithIdNameAndEmail,
+ createApproval,
+ createDetailedLabelInfo,
+ createParsedChange,
+ createSubmitRequirementExpressionInfo,
+ createSubmitRequirementResultInfo,
+ createNonApplicableSubmitRequirementResultInfo,
+} from '../../../test/test-data-generators';
+import {SubmitRequirementResultInfo} from '../../../api/rest-api';
+import {ParsedChangeInfo} from '../../../types/types';
+
+suite('gr-trigger-vote tests', () => {
+ let element: GrTriggerVote;
+ setup(async () => {
+ const submitRequirement: SubmitRequirementResultInfo = {
+ ...createSubmitRequirementResultInfo(),
+ description: 'Test Description',
+ submittability_expression_result: {
+ ...createSubmitRequirementExpressionInfo(),
+ expression: 'label:Verified=MAX -label:Verified=MIN',
+ },
+ };
+ const change: ParsedChangeInfo = {
+ ...createParsedChange(),
+ submit_requirements: [
+ submitRequirement,
+ createNonApplicableSubmitRequirementResultInfo(),
+ ],
+ labels: {
+ Verified: {
+ ...createDetailedLabelInfo(),
+ all: [
+ {
+ ...createApproval(),
+ value: 2,
+ },
+ ],
+ },
+ },
+ };
+ const account = createAccountWithIdNameAndEmail();
+ const label = 'Verified';
+ const labelInfo = change?.labels?.[label];
+ element = await fixture<GrTriggerVote>(
+ html`<gr-trigger-vote
+ .label="${label}"
+ .labelInfo="${labelInfo}"
+ .change="${change}"
+ .account="${account}"
+ .mutable="${false}"
+ ></gr-trigger-vote>`
+ );
+ });
+
+ test('renders', () => {
+ expect(element).shadowDom.to.equal(`<div class="container">
+ <gr-trigger-vote-hovercard>
+ <gr-label-info slot="label-info"></gr-label-info>
+ </gr-trigger-vote-hovercard>
+ <span class="label">
+ Verified
+ </span>
+ <gr-vote-chip>
+ </gr-vote-chip>
+ </div>`);
+ });
+});
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.ts b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.ts
index 85f29cb..753835d 100644
--- a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.ts
+++ b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.ts
@@ -16,24 +16,19 @@
*/
import '../gr-autocomplete/gr-autocomplete';
import '../../../styles/shared-styles';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-labeled-autocomplete_html';
-import {customElement, property} from '@polymer/decorators';
+import {LitElement, css, html, PropertyValues} from 'lit';
+import {customElement, property, query} from 'lit/decorators';
import {
GrAutocomplete,
AutocompleteQuery,
} from '../gr-autocomplete/gr-autocomplete';
+import {assertIsDefined} from '../../../utils/common-util';
+import {fire} from '../../../utils/event-util';
-export interface GrLabeledAutocomplete {
- $: {
- autocomplete: GrAutocomplete;
- };
-}
@customElement('gr-labeled-autocomplete')
-export class GrLabeledAutocomplete extends PolymerElement {
- static get template() {
- return htmlTemplate;
- }
+export class GrLabeledAutocomplete extends LitElement {
+ @query('#autocomplete')
+ autocomplete?: GrAutocomplete;
/**
* Fired when a value is chosen.
@@ -44,7 +39,7 @@
@property({type: Object})
query: AutocompleteQuery = () => Promise.resolve([]);
- @property({type: String, notify: true})
+ @property({type: String})
text = '';
@property({type: String})
@@ -56,15 +51,73 @@
@property({type: Boolean})
disabled = false;
- _handleTriggerClick(e: Event) {
+ static override get styles() {
+ return css`
+ :host {
+ display: block;
+ width: 12em;
+ }
+ #container {
+ background: var(--chip-background-color);
+ border-radius: 1em;
+ padding: var(--spacing-m);
+ }
+ #header {
+ color: var(--deemphasized-text-color);
+ font-weight: var(--font-weight-bold);
+ font-size: var(--font-size-small);
+ }
+ #body {
+ display: flex;
+ }
+ #trigger {
+ color: var(--deemphasized-text-color);
+ cursor: pointer;
+ padding-left: var(--spacing-s);
+ }
+ #trigger:hover {
+ color: var(--primary-text-color);
+ }
+ `;
+ }
+
+ override render() {
+ return html`
+ <div id="container">
+ <div id="header">${this.label}</div>
+ <div id="body">
+ <gr-autocomplete
+ id="autocomplete"
+ threshold="0"
+ .query="${this.query}"
+ ?disabled="${this.disabled}"
+ .placeholder="${this.placeholder}"
+ borderless=""
+ ></gr-autocomplete>
+ <div id="trigger" @click="${this._handleTriggerClick}">▼</div>
+ </div>
+ </div>
+ `;
+ }
+
+ override willUpdate(changedProperties: PropertyValues) {
+ if (changedProperties.has('text')) {
+ fire(this, 'text-changed', this.text);
+ }
+ }
+
+ // Private but used in tests.
+ _handleTriggerClick = (e: Event) => {
// Stop propagation here so we don't confuse gr-autocomplete, which
// listens for taps on body to try to determine when it's blurred.
e.stopPropagation();
- this.$.autocomplete.focus();
- }
+ assertIsDefined(this.autocomplete);
+ this.autocomplete.focus();
+ };
setText(text: string) {
- this.$.autocomplete.setText(text);
+ assertIsDefined(this.autocomplete);
+ this.autocomplete.setText(text);
}
clear() {
@@ -73,6 +126,9 @@
}
declare global {
+ interface HTMLElementEventMap {
+ 'text-changed': CustomEvent<string>;
+ }
interface HTMLElementTagNameMap {
'gr-labeled-autocomplete': GrLabeledAutocomplete;
}
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_html.ts b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_html.ts
deleted file mode 100644
index 934ab84..0000000
--- a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_html.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 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 {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
- <style include="shared-styles">
- :host {
- display: block;
- width: 12em;
- }
- #container {
- background: var(--chip-background-color);
- border-radius: 1em;
- padding: var(--spacing-m);
- }
- #header {
- color: var(--deemphasized-text-color);
- font-weight: var(--font-weight-bold);
- font-size: var(--font-size-small);
- }
- #body {
- display: flex;
- }
- #trigger {
- color: var(--deemphasized-text-color);
- cursor: pointer;
- padding-left: var(--spacing-s);
- }
- #trigger:hover {
- color: var(--primary-text-color);
- }
- </style>
- <div id="container">
- <div id="header">[[label]]</div>
- <div id="body">
- <gr-autocomplete
- id="autocomplete"
- threshold="0"
- query="[[query]]"
- disabled="[[disabled]]"
- placeholder="[[placeholder]]"
- borderless=""
- ></gr-autocomplete>
- <div id="trigger" on-click="_handleTriggerClick">▼</div>
- </div>
- </div>
-`;
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.ts b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.ts
index d6fc45f..49b14b4 100644
--- a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.ts
@@ -18,28 +18,51 @@
import '../../../test/common-test-setup-karma';
import './gr-labeled-autocomplete';
import {GrLabeledAutocomplete} from './gr-labeled-autocomplete';
+import {assertIsDefined} from '../../../utils/common-util';
const basicFixture = fixtureFromElement('gr-labeled-autocomplete');
suite('gr-labeled-autocomplete tests', () => {
let element: GrLabeledAutocomplete;
- setup(() => {
+ setup(async () => {
element = basicFixture.instantiate();
+ await element.updateComplete;
});
test('tapping trigger focuses autocomplete', () => {
const e = {stopPropagation: () => undefined};
const stopPropagationStub = sinon.stub(e, 'stopPropagation');
- const autocompleteStub = sinon.stub(element.$.autocomplete, 'focus');
+ assertIsDefined(element.autocomplete);
+ const autocompleteStub = sinon.stub(element.autocomplete, 'focus');
element._handleTriggerClick(e as Event);
assert.isTrue(stopPropagationStub.calledOnce);
assert.isTrue(autocompleteStub.calledOnce);
});
test('setText', () => {
- const setTextStub = sinon.stub(element.$.autocomplete, 'setText');
+ assertIsDefined(element.autocomplete);
+ const setTextStub = sinon.stub(element.autocomplete, 'setText');
element.setText('foo-bar');
assert.isTrue(setTextStub.calledWith('foo-bar'));
});
+
+ test('shadowDom', async () => {
+ element.label = 'Some label';
+ await element.updateComplete;
+
+ expect(element).shadowDom.to.equal(`
+ <div id="container">
+ <div id="header">Some label</div>
+ <div id="body">
+ <gr-autocomplete
+ id="autocomplete"
+ threshold="0"
+ borderless=""
+ ></gr-autocomplete>
+ <div id="trigger">▼</div>
+ </div>
+ </div>
+ `);
+ });
});
diff --git a/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.ts b/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.ts
index 31efa73..99aebb1 100644
--- a/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.ts
@@ -26,8 +26,9 @@
suite('gr-repo-branch-picker tests', () => {
let element: GrRepoBranchPicker;
- setup(() => {
+ setup(async () => {
element = basicFixture.instantiate();
+ await flush();
});
suite('_getRepoSuggestions', () => {
diff --git a/polygerrit-ui/app/test/test-data-generators.ts b/polygerrit-ui/app/test/test-data-generators.ts
index 0fa2673..1abb0b9 100644
--- a/polygerrit-ui/app/test/test-data-generators.ts
+++ b/polygerrit-ui/app/test/test-data-generators.ts
@@ -103,6 +103,7 @@
import {CommitInfoWithRequiredCommit} from '../elements/change/gr-change-metadata/gr-change-metadata';
import {WebLinkInfo} from '../types/diff';
import {
+ ChangeMessage,
CommentThread,
createCommentThreads,
DraftInfo,
@@ -111,7 +112,6 @@
import {GerritView} from '../services/router/router-model';
import {ChangeComments} from '../elements/diff/gr-comment-api/gr-comment-api';
import {EditRevisionInfo, ParsedChangeInfo} from '../types/types';
-import {ChangeMessage} from '../elements/change/gr-message/gr-message';
import {
GenerateUrlEditViewParameters,
GenerateUrlTopicViewParams,
diff --git a/polygerrit-ui/app/types/events.ts b/polygerrit-ui/app/types/events.ts
index 3a46e60..6ad9e71 100644
--- a/polygerrit-ui/app/types/events.ts
+++ b/polygerrit-ui/app/types/events.ts
@@ -15,11 +15,10 @@
* limitations under the License.
*/
import {PatchSetNum} from './common';
-import {Comment} from '../utils/comment-util';
+import {ChangeMessage, Comment} from '../utils/comment-util';
import {FetchRequest} from './types';
import {LineNumberEventDetail, MovedLinkClickedEventDetail} from '../api/diff';
import {Category, RunStatus} from '../api/checks';
-import {ChangeMessage} from '../elements/change/gr-message/gr-message';
export enum EventType {
BIND_VALUE_CHANGED = 'bind-value-changed',
diff --git a/polygerrit-ui/app/utils/comment-util.ts b/polygerrit-ui/app/utils/comment-util.ts
index ee26915..501da7d 100644
--- a/polygerrit-ui/app/utils/comment-util.ts
+++ b/polygerrit-ui/app/utils/comment-util.ts
@@ -29,6 +29,8 @@
RevisionPatchSetNum,
AccountInfo,
AccountDetailInfo,
+ ChangeMessageInfo,
+ VotingRangeInfo,
} from '../types/common';
import {CommentSide, SpecialFilePath} from '../constants/constants';
import {parseDate} from './date-util';
@@ -89,6 +91,18 @@
id: UrlEncodedCommentId;
}
+export interface ChangeMessage extends ChangeMessageInfo {
+ // TODO(TS): maybe should be an enum instead
+ type: string;
+ expanded: boolean;
+ commentThreads: CommentThread[];
+}
+
+export type LabelExtreme = {[labelName: string]: VotingRangeInfo};
+
+export const PATCH_SET_PREFIX_PATTERN =
+ /^(?:Uploaded\s*)?[Pp]atch [Ss]et \d+:\s*(.*)/;
+
export function sortComments<T extends SortableComment>(comments: T[]): T[] {
return comments.slice(0).sort((c1, c2) => {
const d1 = isDraft(c1);
diff --git a/tools/deps.bzl b/tools/deps.bzl
index 3dff9ce9..86eb872 100644
--- a/tools/deps.bzl
+++ b/tools/deps.bzl
@@ -17,7 +17,7 @@
GITILES_REPO = GERRIT
# When updating Bouncy Castle, also update it in bazlets.
-BC_VERS = "1.61"
+BC_VERS = "1.64"
HTTPCOMP_VERS = "4.5.2"
JETTY_VERS = "9.4.36.v20210114"
BYTE_BUDDY_VERSION = "1.10.7"
@@ -575,19 +575,19 @@
maven_jar(
name = "bcprov",
artifact = "org.bouncycastle:bcprov-jdk15on:" + BC_VERS,
- sha1 = "00df4b474e71be02c1349c3292d98886f888d1f7",
+ sha1 = "1467dac1b787b5ad2a18201c0c281df69882259e",
)
maven_jar(
name = "bcpg",
artifact = "org.bouncycastle:bcpg-jdk15on:" + BC_VERS,
- sha1 = "422656435514ab8a28752b117d5d2646660a0ace",
+ sha1 = "56956a8c63ccadf62e7c678571cf86f30bd84441",
)
maven_jar(
name = "bcpkix",
artifact = "org.bouncycastle:bcpkix-jdk15on:" + BC_VERS,
- sha1 = "89bb3aa5b98b48e584eee2a7401b7682a46779b4",
+ sha1 = "3dac163e20110817d850d17e0444852a6d7d0bd7",
)
maven_jar(