Merge "Feedback for triggered actions"
diff --git a/java/com/google/gerrit/server/ApprovalInference.java b/java/com/google/gerrit/server/ApprovalInference.java
index 572ae7a..40bf249 100644
--- a/java/com/google/gerrit/server/ApprovalInference.java
+++ b/java/com/google/gerrit/server/ApprovalInference.java
@@ -109,10 +109,10 @@
PatchSetApproval psa,
PatchSet.Id psId,
ChangeKind kind,
- PatchList patchList) {
+ LabelType type,
+ @Nullable PatchList patchList) {
int n = psa.key().patchSetId().get();
checkArgument(n != psId.get());
- LabelType type = project.getLabelTypes().byLabel(psa.labelId());
if (type == null) {
logger.atFine().log(
@@ -367,12 +367,17 @@
logger.atFine().log(
"change kind for patch set %d of change %d against prior patch set %s is %s",
ps.id().get(), ps.id().changeId().get(), priorPatchSet.getValue().id().changeId(), kind);
- PatchList patchList = getPatchList(project, ps, priorPatchSet);
+ PatchList patchList = null;
for (PatchSetApproval psa : priorApprovals) {
if (resultByUser.contains(psa.label(), psa.accountId())) {
continue;
}
- if (!canCopy(project, psa, ps.id(), kind, patchList)) {
+ LabelType type = project.getLabelTypes().byLabel(psa.labelId());
+ // Only compute patchList if there is a relevant label, since this is expensive.
+ if (patchList == null && type != null && type.isCopyAllScoresIfListOfFilesDidNotChange()) {
+ patchList = getPatchList(project, ps, priorPatchSet);
+ }
+ if (!canCopy(project, psa, ps.id(), kind, type, patchList)) {
continue;
}
resultByUser.put(psa.label(), psa.accountId(), psa.copyWithPatchSet(ps.id()));
diff --git a/java/com/google/gerrit/server/patch/SubmitWithStickyApprovalDiff.java b/java/com/google/gerrit/server/patch/SubmitWithStickyApprovalDiff.java
index 9f58aaf..63e0b7a 100644
--- a/java/com/google/gerrit/server/patch/SubmitWithStickyApprovalDiff.java
+++ b/java/com/google/gerrit/server/patch/SubmitWithStickyApprovalDiff.java
@@ -88,8 +88,10 @@
// If the latest approved patchset is the current patchset, no need to return anything.
return "";
}
- String diff =
- String.format("\n\n%d is the latest approved patch-set.\n", latestApprovedPatchsetId.get());
+ StringBuilder diff =
+ new StringBuilder(
+ String.format(
+ "\n\n%d is the latest approved patch-set.\n", latestApprovedPatchsetId.get()));
PatchList patchList =
getPatchList(
notes.getProjectName(),
@@ -103,19 +105,19 @@
.collect(Collectors.toList());
if (patchListEntryList.isEmpty()) {
- diff +=
- "No files were changed between the latest approved patch-set and the submitted one.\n";
- return diff;
+ diff.append(
+ "No files were changed between the latest approved patch-set and the submitted one.\n");
+ return diff.toString();
}
- diff += "The change was submitted with unreviewed changes in the following files:\n\n";
+ diff.append("The change was submitted with unreviewed changes in the following files:\n\n");
for (PatchListEntry patchListEntry : patchListEntryList) {
- diff +=
+ diff.append(
getDiffForFile(
- notes, currentPatchset.id(), latestApprovedPatchsetId, patchListEntry, currentUser);
+ notes, currentPatchset.id(), latestApprovedPatchsetId, patchListEntry, currentUser));
}
- return diff;
+ return diff.toString();
}
private String getDiffForFile(
@@ -126,12 +128,13 @@
CurrentUser currentUser)
throws AuthException, InvalidChangeOperationException, IOException,
PermissionBackendException {
- String diff =
- String.format(
- "The name of the file: %s\nInsertions: %d, Deletions: %d.\n\n",
- patchListEntry.getNewName(),
- patchListEntry.getInsertions(),
- patchListEntry.getDeletions());
+ StringBuilder diff =
+ new StringBuilder(
+ String.format(
+ "The name of the file: %s\nInsertions: %d, Deletions: %d.\n\n",
+ patchListEntry.getNewName(),
+ patchListEntry.getInsertions(),
+ patchListEntry.getDeletions()));
DiffPreferencesInfo diffPreferencesInfo = createDefaultDiffPreferencesInfo();
PatchScriptFactory patchScriptFactory =
patchScriptFactoryFactory.create(
@@ -145,66 +148,66 @@
try {
patchScript = patchScriptFactory.call();
} catch (LargeObjectException exception) {
- diff += "The file content is too large for showing the full diff. \n\n";
- return diff;
+ diff.append("The file content is too large for showing the full diff. \n\n");
+ return diff.toString();
}
if (patchScript.getChangeType() == ChangeType.RENAMED) {
- diff +=
+ diff.append(
String.format(
"The file %s was renamed to %s\n",
- patchListEntry.getOldName(), patchListEntry.getNewName());
+ patchListEntry.getOldName(), patchListEntry.getNewName()));
}
SparseFileContent.Accessor fileA = patchScript.getA().createAccessor();
SparseFileContent.Accessor fileB = patchScript.getB().createAccessor();
boolean editsExist = false;
if (patchScript.getEdits().stream().anyMatch(e -> e.getType() != Edit.Type.EMPTY)) {
- diff += "```\n";
+ diff.append("```\n");
editsExist = true;
}
for (Edit edit : patchScript.getEdits()) {
- diff += getDiffForEdit(fileA, fileB, edit);
+ diff.append(getDiffForEdit(fileA, fileB, edit));
}
if (editsExist) {
- diff += "```\n";
+ diff.append("```\n");
}
- return diff;
+ return diff.toString();
}
private String getDiffForEdit(Accessor fileA, Accessor fileB, Edit edit) {
- String diff = "";
+ StringBuilder diff = new StringBuilder();
Edit.Type type = edit.getType();
switch (type) {
case INSERT:
- diff += String.format("@@ +%d:%d @@\n", edit.getBeginB(), edit.getEndB());
- diff += getModifiedLines(fileB, edit.getBeginB(), edit.getEndB(), '+');
- diff += "\n";
+ diff.append(String.format("@@ +%d:%d @@\n", edit.getBeginB(), edit.getEndB()));
+ diff.append(getModifiedLines(fileB, edit.getBeginB(), edit.getEndB(), '+'));
+ diff.append("\n");
break;
case DELETE:
- diff += String.format("@@ -%d:%d @@\n", edit.getBeginA(), edit.getEndA());
- diff += getModifiedLines(fileA, edit.getBeginA(), edit.getEndA(), '-');
- diff += "\n";
+ diff.append(String.format("@@ -%d:%d @@\n", edit.getBeginA(), edit.getEndA()));
+ diff.append(getModifiedLines(fileA, edit.getBeginA(), edit.getEndA(), '-'));
+ diff.append("\n");
break;
case REPLACE:
- diff +=
+ diff.append(
String.format(
"@@ -%d:%d, +%d:%d @@\n",
- edit.getBeginA(), edit.getEndA(), edit.getBeginB(), edit.getEndB());
- diff += getModifiedLines(fileA, edit.getBeginA(), edit.getEndA(), '-');
- diff += getModifiedLines(fileB, edit.getBeginB(), edit.getEndB(), '+');
- diff += "\n";
+ edit.getBeginA(), edit.getEndA(), edit.getBeginB(), edit.getEndB()));
+ diff.append(getModifiedLines(fileA, edit.getBeginA(), edit.getEndA(), '-'));
+ diff.append(getModifiedLines(fileB, edit.getBeginB(), edit.getEndB(), '+'));
+ diff.append("\n");
break;
case EMPTY:
// do nothing since there is no change here.
}
- return diff;
+ return diff.toString();
}
private String getModifiedLines(Accessor file, int begin, int end, char modificationType) {
- String diff = "";
+ StringBuilder diff = new StringBuilder();
for (int i = begin; i < end; i++) {
- diff += String.format("%c %s\n", modificationType, file.get(i));
+ diff.append(String.format("%c %s\n", modificationType, file.get(i)));
}
- return diff;
+ return diff.toString();
}
private DiffPreferencesInfo createDefaultDiffPreferencesInfo() {
diff --git a/plugins/replication b/plugins/replication
index a379adc..14766e7 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit a379adcd2f4f1a41731818e74b2a214de3fcf5d8
+Subproject commit 14766e75f91886ab48951035d59a78c8c3f07471
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
index 816c8ef..a34bd63 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
@@ -380,6 +380,19 @@
e.detail.change._number,
e.detail.starred
);
+ // When a change is updated the same change may appear elsewhere in the
+ // dashboard (but is not the same object), so we must update other
+ // occurrences of the same change.
+ this._results?.forEach((dashboardChange, dashboardIndex) =>
+ dashboardChange.results.forEach((change, changeIndex) => {
+ if (change.id === e.detail.change.id) {
+ this.set(
+ `_results.${dashboardIndex}.results.${changeIndex}.starred`,
+ e.detail.starred
+ );
+ }
+ })
+ );
}
_handleToggleReviewed(e: CustomEvent<ChangeListToggleReviewedDetail>) {
@@ -387,6 +400,19 @@
e.detail.change._number,
e.detail.reviewed
);
+ // When a change is updated the same change may appear elsewhere in the
+ // dashboard (but is not the same object), so we must update other
+ // occurrences of the same change.
+ this._results?.forEach((dashboardChange, dashboardIndex) =>
+ dashboardChange.results.forEach((change, changeIndex) => {
+ if (change.id === e.detail.change.id) {
+ this.set(
+ `_results.${dashboardIndex}.results.${changeIndex}.reviewed`,
+ e.detail.reviewed
+ );
+ }
+ })
+ );
}
/**
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
index 47f885b..a5de72b 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
@@ -332,6 +332,56 @@
});
});
+ test('toggling star will update change everywhere', () => {
+ // It is important that the same change is represented by multiple objects
+ // and all are updated.
+ const change = {id: '5', starred: false};
+ const sameChange = {id: '5', starred: false};
+ const differentChange = {id: '4', starred: false};
+ element._results = [
+ {query: 'has:draft', results: [change]},
+ {query: 'is:open', results: [sameChange, differentChange]},
+ ];
+
+ element._handleToggleStar(
+ new CustomEvent('toggle-star', {
+ detail: {
+ change,
+ starred: true,
+ },
+ })
+ );
+
+ assert.isTrue(change.starred);
+ assert.isTrue(sameChange.starred);
+ assert.isFalse(differentChange.starred);
+ });
+
+ test('toggling reviewed will update change everywhere', () => {
+ // It is important that the same change is represented by multiple objects
+ // and all are updated.
+ const change = {id: '5', reviewed: false};
+ const sameChange = {id: '5', reviewed: false};
+ const differentChange = {id: '4', reviewed: false};
+ element._results = [
+ {query: 'has:draft', results: [change]},
+ {query: 'is:open', results: [sameChange, differentChange]},
+ ];
+
+ element._handleToggleReviewed(
+ new CustomEvent('toggle-reviewed', {
+ detail: {
+ change,
+ reviewed: true,
+ },
+ })
+ );
+
+ assert.isTrue(change.reviewed);
+ assert.isTrue(sameChange.reviewed);
+ assert.isFalse(differentChange.reviewed);
+ });
+
test('_showNewUserHelp', () => {
element._loading = false;
element._showNewUserHelp = false;
diff --git a/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts b/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts
index 538fa4969..8322f3c 100644
--- a/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts
@@ -111,13 +111,6 @@
.summaryChip.check iron-icon {
color: var(--gray-foreground);
}
- .summaryChip.info {
- border-color: var(--info-deemphasized-foreground;
- background-color: var(--info-deemphasized-background);
- }
- .summaryChip.info iron-icon {
- color: var(--info-deemphasized-foreground);
- }
`,
];
}
@@ -445,7 +438,6 @@
><gr-summary-chip
styleType=${SummaryChipStyles.WARNING}
category=${CommentTabState.UNRESOLVED}
- icon="message"
?hidden=${!countUnresolvedComments}
>
${unresolvedAuthors.map(
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 b93040b..8d03e32 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
@@ -305,7 +305,7 @@
</gr-button>
</template>
<template is="dom-if" if="[[message._revision_number]]">
- <span class="patchset">[[message._revision_number]]</span>
+ <span class="patchset">[[message._revision_number]] |</span>
</template>
<template is="dom-if" if="[[!message.id]]">
<span class="date">
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
index 1b49f8a..31f17724 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import {html} from 'lit-html';
+import {html, nothing} from 'lit-html';
import {classMap} from 'lit-html/directives/class-map';
import {
css,
@@ -29,8 +29,10 @@
import {
compareByWorstCategory,
fireActionTriggered,
+ iconForCategory,
iconForRun,
primaryRunAction,
+ worstCategory,
} from '../../services/checks/checks-util';
import {
allRuns$,
@@ -114,16 +116,16 @@
.chip.placeholder iron-icon {
display: none;
}
- .chip.error iron-icon {
+ iron-icon.error {
color: var(--error-foreground);
}
- .chip.warning iron-icon {
+ iron-icon.warning {
color: var(--warning-foreground);
}
- .chip.info-outline iron-icon {
+ iron-icon.info-outline {
color: var(--info-foreground);
}
- .chip.check-circle-outline iron-icon {
+ iron-icon.check-circle-outline {
color: var(--success-foreground);
}
/* Additional 'div' for increased specificity. */
@@ -198,7 +200,8 @@
return html`
<div @click="${this.handleChipClick}" class="${classMap(classes)}">
<div class="left">
- <iron-icon icon="gr-icons:${icon}"></iron-icon>
+ <iron-icon class="${icon}" icon="gr-icons:${icon}"></iron-icon>
+ ${this.renderAdditionalIcon()}
<span class="name">${this.run.checkName}</span>
</div>
<div class="right">
@@ -215,6 +218,20 @@
`;
}
+ /**
+ * For RUNNING we also want to render an icon representing the worst result
+ * that has been reported until now - if there are any results already.
+ */
+ renderAdditionalIcon() {
+ if (this.run.status !== RunStatus.RUNNING) return nothing;
+ const category = worstCategory(this.run);
+ if (!category) return nothing;
+ const icon = iconForCategory(category);
+ return html`
+ <iron-icon class="${icon}" icon="gr-icons:${icon}"></iron-icon>
+ `;
+ }
+
private handleChipClick(e: MouseEvent) {
e.stopPropagation();
e.preventDefault();
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_html.ts b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_html.ts
index 374cc62..0f530bf 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_html.ts
@@ -68,6 +68,11 @@
border-radius: 0 0 4px 4px;
border-color: var(--border-color);
box-shadow: var(--elevation-level-1);
+ /* slightly up to cover rounded corner of the commit msg */
+ margin-top: calc(-1 * var(--spacing-xs));
+ /* To make this bar pop over editor, since editor has relative position.
+ */
+ position: relative;
}
.show-all-container .show-all-button {
margin-right: auto;
diff --git a/polygerrit-ui/app/services/checks/checks-util.ts b/polygerrit-ui/app/services/checks/checks-util.ts
index 1613359..ea532ea 100644
--- a/polygerrit-ui/app/services/checks/checks-util.ts
+++ b/polygerrit-ui/app/services/checks/checks-util.ts
@@ -76,8 +76,12 @@
}
export function iconForRun(run: CheckRun) {
- const category = worstCategory(run);
- return category ? iconForCategory(category) : iconForStatus(run.status);
+ if (run.status !== RunStatus.COMPLETED) {
+ return iconForStatus(run.status);
+ } else {
+ const category = worstCategory(run);
+ return category ? iconForCategory(category) : iconForStatus(run.status);
+ }
}
export function iconForStatus(status: RunStatus) {
diff --git a/polygerrit-ui/app/styles/themes/app-theme.ts b/polygerrit-ui/app/styles/themes/app-theme.ts
index 2d83cf5..18c12b0 100644
--- a/polygerrit-ui/app/styles/themes/app-theme.ts
+++ b/polygerrit-ui/app/styles/themes/app-theme.ts
@@ -76,8 +76,6 @@
--info-background: var(--blue-50);
--selected-foreground: var(--blue-700);
--selected-background: var(--blue-50);
- --info-deemphasized-foreground: var(--gray-300);
- --info-deemphasized-background: var(--gray-50);
--success-foreground: var(--green-700);
--success-background: var(--green-50);
--gray-foreground: var(--gray-700);
diff --git a/polygerrit-ui/app/styles/themes/dark-theme.ts b/polygerrit-ui/app/styles/themes/dark-theme.ts
index 072ca8f..5455a24 100644
--- a/polygerrit-ui/app/styles/themes/dark-theme.ts
+++ b/polygerrit-ui/app/styles/themes/dark-theme.ts
@@ -46,8 +46,6 @@
--info-background: var(--blue-900);
--selected-foreground: var(--blue-200);
--selected-background: var(--blue-900);
- --info-deemphasized-foreground: var(--gray-700);
- --info-deemphasized-background: var(--primary-text-color);
--success-foreground: var(--green-200);
--success-background: var(--green-900);
--gray-foreground: var(--gray-100);