Merge branch 'stable-3.4'
* stable-3.4:
gr-confirm-move-dialog: Fix _getProjectBranchesSuggestions
Clean up upload change help dialog
Fix binding of DELETE REST calls from plugins
Change-Id: I7abf2c7112f854d4bdad2191d9b227dd31ccbc62
diff --git a/Documentation/dev-release.txt b/Documentation/dev-release.txt
index a7240e2..0849c56 100644
--- a/Documentation/dev-release.txt
+++ b/Documentation/dev-release.txt
@@ -153,7 +153,7 @@
Tag the plugins:
----
- git submodule foreach '[ "$path" == "modules/jgit" ] || git tag -s -m "v$version" "v$version"'
+ git submodule foreach '[ "$sm_path" == "modules/jgit" ] || git tag -s -m "v$version" "v$version"'
----
[[build-gerrit]]
@@ -324,7 +324,7 @@
Push the new Release Tag on the plugins:
----
- git submodule foreach git push gerrit-review tag v$version
+ git submodule foreach '[ "$sm_path" == "modules/jgit" ] || git push gerrit-review tag "v$version"'
----
[[upload-documentation]]
diff --git a/Documentation/note-db.txt b/Documentation/note-db.txt
index a13cbfb..b376d6e 100644
--- a/Documentation/note-db.txt
+++ b/Documentation/note-db.txt
@@ -36,6 +36,67 @@
not available in 3.0, so any upgrade from Gerrit 2.x to 3.x must go through
2.16 to effect the NoteDb upgrade.
+== Format
+
+Each review ("change") in Gerrit is numbered. The different revisions
+("patchsets") of a change 12345 are stored under
+----
+ refs/changes/45/12345/${PATCHSET_NUMBER}
+----
+
+The revisions are stored as commits to the main project, ie. if you
+fetch this ref, you can check out the proposed change.
+
+A change 12345 has its review metadata under
+----
+ refs/changes/45/12345/meta
+----
+The metadata is a notes branch. The commit messages on the branch hold
+modifications to global data of the change (votes, global comments). The inline
+comments are in a
+link:https://git.eclipse.org/r/plugins/gitiles/jgit/jgit/\+/master/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMap.java[NoteMap],
+where the key is the commit SHA-1 of the patchset
+that the comment refers to, and the value is JSON data. The format of the
+JSON is in the
+link:https://gerrit.googlesource.com/gerrit/\+/master/java/com/google/gerrit/server/notedb/RevisionNoteData.java[RevisionNoteData]
+which contains
+link:https://gerrit.googlesource.com/gerrit/\+/master/java/com/google/gerrit/entities/Comment.java[Comment] entities.
+
+For example:
+----
+ {
+ "key": {
+ "uuid": "c7be1334_47885e36",
+ "filename":
+"java/com/google/gerrit/server/restapi/project/CommitsCollection.java",
+ "patchSetId": 7
+ },
+ "lineNbr": 158,
+ "author": {
+ "id": 1026112
+ },
+ "writtenOn": "2019-11-06T09:00:50Z",
+ "side": 1,
+ "message": "nit: factor this out in a variable, use
+toImmutableList as collector",
+ "range": {
+ "startLine": 156,
+ "startChar": 32,
+ "endLine": 158,
+ "endChar": 66
+ },
+ "revId": "071c601d6ee1a2a9f520415fd9efef8e00f9cf60",
+ "serverId": "173816e5-2b9a-37c3-8a2e-48639d4f1153",
+ "unresolved": true
+ },
+----
+
+Automated systems may post "robot comments" instead of normal
+comments, which are an extension of the previous comment, defined in
+the
+link:https://gerrit.googlesource.com/gerrit/\+/master/java/com/google/gerrit/entities/RobotComment.java[RobotComment]
+class.
+
[[migration]]
== Migration
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 516b2fe..721900f 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -3576,6 +3576,9 @@
Deletes a single vote from a change. Note, that even when the last vote of
a reviewer is removed the reviewer itself is still listed on the change.
+If another user removed a user's vote, the user with the deleted vote will be
+added to the attention set.
+
.Request
----
DELETE /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/reviewers/John%20Doe/votes/Code-Review HTTP/1.0
@@ -5940,6 +5943,9 @@
Note, that even when the last vote of a reviewer is removed the reviewer itself
is still listed on the change.
+If another user removed a user's vote, the user with the deleted vote will be
+added to the attention set.
+
.Request
----
DELETE /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/revisions/674ac754f91e64a0efb8087e59a176484bd534d1/reviewers/John%20Doe/votes/Code-Review HTTP/1.0
@@ -6118,6 +6124,7 @@
* The change is marked ready for review.
* As an owner/uploader, when someone replies on your change.
* As a reviewer, when the owner/uploader replies.
+* When the user's vote is deleted by another user.
Users are removed from the attention set if one the following apply:
diff --git a/Documentation/user-attention-set.txt b/Documentation/user-attention-set.txt
index 4697afc..ea927c7 100644
--- a/Documentation/user-attention-set.txt
+++ b/Documentation/user-attention-set.txt
@@ -47,6 +47,8 @@
attention set.
* For merged and abandoned changes the owner is added only when a human creates
an unresolved comment.
+* If another user removed a user's vote, the user with the deleted vote will be
+ added to the attention set.
* Only owner, uploader, reviewers and ccs can be in the attention set.
* The rules for service accounts are different, see link:#bots[Bots].
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteVote.java b/java/com/google/gerrit/server/restapi/change/DeleteVote.java
index 4b813df..cc73e9a 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteVote.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteVote.java
@@ -36,9 +36,11 @@
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeMessagesUtil;
+import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.account.AccountState;
+import com.google.gerrit.server.change.AddToAttentionSetOp;
import com.google.gerrit.server.change.NotifyResolver;
import com.google.gerrit.server.change.ReviewerResource;
import com.google.gerrit.server.change.VoteResource;
@@ -58,6 +60,7 @@
import com.google.gerrit.server.util.LabelVote;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
+import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.HashMap;
@@ -79,6 +82,8 @@
private final RemoveReviewerControl removeReviewerControl;
private final ProjectCache projectCache;
private final MessageIdGenerator messageIdGenerator;
+ private final AddToAttentionSetOp.Factory attentionSetOpfactory;
+ private final Provider<CurrentUser> currentUserProvider;
@Inject
DeleteVote(
@@ -92,7 +97,9 @@
NotifyResolver notifyResolver,
RemoveReviewerControl removeReviewerControl,
ProjectCache projectCache,
- MessageIdGenerator messageIdGenerator) {
+ MessageIdGenerator messageIdGenerator,
+ AddToAttentionSetOp.Factory attentionSetOpFactory,
+ Provider<CurrentUser> currentUserProvider) {
this.updateFactory = updateFactory;
this.approvalsUtil = approvalsUtil;
this.psUtil = psUtil;
@@ -104,6 +111,8 @@
this.removeReviewerControl = removeReviewerControl;
this.projectCache = projectCache;
this.messageIdGenerator = messageIdGenerator;
+ this.attentionSetOpfactory = attentionSetOpFactory;
+ this.currentUserProvider = currentUserProvider;
}
@Override
@@ -140,6 +149,14 @@
r.getReviewerUser().state(),
rsrc.getLabel(),
input));
+ if (!r.getReviewerUser().getAccountId().equals(currentUserProvider.get().getAccountId())) {
+ bu.addOp(
+ change.getId(),
+ attentionSetOpfactory.create(
+ r.getReviewerUser().getAccountId(),
+ /* reason= */ "Their vote was deleted",
+ /* notify= */ false));
+ }
bu.execute();
}
diff --git a/java/com/google/gerrit/testing/TestLoggingActivator.java b/java/com/google/gerrit/testing/TestLoggingActivator.java
index 6b5d8fd..b3ad862 100644
--- a/java/com/google/gerrit/testing/TestLoggingActivator.java
+++ b/java/com/google/gerrit/testing/TestLoggingActivator.java
@@ -48,11 +48,6 @@
.put("org.openid4java.server.RealmVerifier", Level.ERROR)
.put("org.openid4java.message.AuthSuccess", Level.ERROR)
- // Silence non-critical messages from c3p0 (if used).
- .put("com.mchange.v2.c3p0", Level.WARN)
- .put("com.mchange.v2.resourcepool", Level.WARN)
- .put("com.mchange.v2.sql", Level.WARN)
-
// Silence non-critical messages from apache.http.
.put("org.apache.http", Level.WARN)
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java b/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
index d2a48be1..6555b50 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
@@ -37,6 +37,7 @@
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.AttentionSetUpdate.Operation;
import com.google.gerrit.entities.Change;
+import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.AttentionSetInput;
@@ -1758,6 +1759,40 @@
.isEqualTo(Operation.REMOVE);
}
+ @Test
+ public void deleteSelfVotesDoesNotAddToAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+ approve(r.getChangeId());
+ gApi.changes()
+ .id(r.getChangeId())
+ .current()
+ .reviewer(admin.id().toString())
+ .deleteVote(LabelId.CODE_REVIEW);
+
+ assertThat(getAttentionSetUpdates(r.getChange().getId())).isEmpty();
+ }
+
+ @Test
+ public void deleteVotesOfOthersAddThemToAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+
+ requestScopeOperations.setApiUser(user.id());
+ recommend(r.getChangeId());
+
+ requestScopeOperations.setApiUser(admin.id());
+ gApi.changes()
+ .id(r.getChangeId())
+ .current()
+ .reviewer(user.id().toString())
+ .deleteVote(LabelId.CODE_REVIEW);
+
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet).hasAccountIdThat().isEqualTo(user.id());
+ assertThat(attentionSet).hasOperationThat().isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet).hasReasonThat().isEqualTo("Their vote was deleted");
+ }
+
private List<AttentionSetUpdate> getAttentionSetUpdatesForUser(
PushOneCommit.Result r, TestAccount account) {
return getAttentionSetUpdates(r.getChange().getId()).stream()
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index b97d9f2..cbeb59d 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
+import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
import static com.google.gerrit.extensions.client.ListChangesOption.REVIEWED;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
@@ -705,6 +706,23 @@
}
@Test
+ public void byProjectWithHidden() throws Exception {
+ TestRepository<Repo> hiddenProject = createProject("hiddenProject");
+ insert(hiddenProject, newChange(hiddenProject));
+ projectOperations
+ .project(Project.nameKey("hiddenProject"))
+ .forUpdate()
+ .add(block(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
+ .update();
+
+ TestRepository<Repo> visibleProject = createProject("visibleProject");
+ Change visibleChange = insert(visibleProject, newChange(visibleProject));
+ assertQuery("project:visibleProject", visibleChange);
+ assertQuery("project:hiddenProject");
+ assertQuery("project:visibleProject OR project:hiddenProject", visibleChange);
+ }
+
+ @Test
public void byParentOf() throws Exception {
TestRepository<Repo> repo1 = createProject("repo1");
RevCommit commit1 = repo1.parseBody(repo1.commit().message("message").create());
diff --git a/package.json b/package.json
index 7f4ac44..3c40690 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,7 @@
"prettier": "2.0.5",
"rollup": "^2.3.4",
"terser": "^4.8.0",
- "typescript": "4.0.5"
+ "typescript": "4.1.4"
},
"scripts": {
"clean": "git clean -fdx && bazel clean --expunge",
diff --git a/plugins/codemirror-editor b/plugins/codemirror-editor
index 3cd520b..30c774f 160000
--- a/plugins/codemirror-editor
+++ b/plugins/codemirror-editor
@@ -1 +1 @@
-Subproject commit 3cd520b1521ff7c558d0cd95274628a3a20de30a
+Subproject commit 30c774f30c1709f71efc250a195dd6fb50c7503b
diff --git a/plugins/delete-project b/plugins/delete-project
index bfe159d..549de03 160000
--- a/plugins/delete-project
+++ b/plugins/delete-project
@@ -1 +1 @@
-Subproject commit bfe159d3007db0f07e967473b53f679ba8f432df
+Subproject commit 549de033d60b13aaeef45ce5c4bf42be39506268
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts
index 7b43dfc..80c58ca 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts
@@ -297,9 +297,18 @@
}
// Restore inheritFrom.
if (this._inheritsFrom) {
- this._inheritsFrom = {...this.originalInheritsFrom};
- this._inheritFromFilter =
- 'name' in this._inheritsFrom ? this._inheritsFrom.name : undefined;
+ // Can't assign this._inheritsFrom = {...this.originalInheritsFrom}
+ // directly, because this._inheritsFrom is declared as
+ // '...|null|undefined` and typescript reports error when trying
+ // to access .name property (because 'name' in null and 'name' in undefined
+ // lead to runtime error)
+ // After migrating to Typescript v4.2 the code below can be rewritten as
+ // const copy = {...this.originalInheritsFrom};
+ const copy: ProjectInfo | {} = this.originalInheritsFrom
+ ? {...this.originalInheritsFrom}
+ : {};
+ this._inheritsFrom = copy;
+ this._inheritFromFilter = 'name' in copy ? copy.name : undefined;
}
if (!this._local) {
return;
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
index 42876d9..4ae3c68 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
@@ -171,7 +171,7 @@
method: HttpMethod.POST,
};
-function isQuckApproveAction(
+function isQuickApproveAction(
action: UIActionInfo
): action is QuickApproveUIActionInfo {
return (action as QuickApproveUIActionInfo).key === QUICK_APPROVE_ACTION.key;
@@ -943,9 +943,10 @@
const status = this._getLabelStatus(labelInfo);
if (status === LabelStatus.NEED) {
if (result) {
- // More than one label is missing, so it's unclear which to quick
- // approve, return null;
- return null;
+ // More than one label is missing, so check if Code Review can be
+ // given
+ result = null;
+ break;
}
result = label;
} else if (
@@ -999,7 +1000,7 @@
throw new Error('_topLevelSecondaryActions must be set');
}
this._topLevelSecondaryActions = this._topLevelSecondaryActions.filter(
- sa => !isQuckApproveAction(sa)
+ sa => !isQuickApproveAction(sa)
);
this._hideQuickApproveAction = true;
}
@@ -1271,7 +1272,7 @@
this._showActionDialog(this.$.confirmAbandonDialog);
break;
case QUICK_APPROVE_ACTION.key: {
- const action = this._allActionValues.find(isQuckApproveAction);
+ const action = this._allActionValues.find(isQuickApproveAction);
if (!action) {
return;
}
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
index 8324fdd..c193e60 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
@@ -1629,23 +1629,52 @@
assert.deepEqual(payload.labels, {foo: 1});
});
- test('not added when multiple labels are required', () => {
+ test('not added when multiple labels are required without code review',
+ () => {
+ element.change = {
+ current_revision: 'abc1234',
+ labels: {
+ foo: {values: {}},
+ bar: {values: {}},
+ },
+ permitted_labels: {
+ foo: [' 0', '+1'],
+ bar: [' 0', '+1', '+2'],
+ },
+ };
+ flush();
+ const approveButton =
+ element.shadowRoot
+ .querySelector('gr-button[data-action-key=\'review\']');
+ assert.isNull(approveButton);
+ });
+
+ test('code review shown with multiple missing approval', () => {
element.change = {
current_revision: 'abc1234',
labels: {
- foo: {values: {}},
- bar: {values: {}},
+ 'foo': {values: {}},
+ 'bar': {values: {}},
+ 'Code-Review': {
+ approved: {},
+ values: {
+ ' 0': '',
+ '+1': '',
+ '+2': '',
+ },
+ },
},
permitted_labels: {
- foo: [' 0', '+1'],
- bar: [' 0', '+1', '+2'],
+ 'foo': [' 0', '+1'],
+ 'bar': [' 0', '+1', '+2'],
+ 'Code-Review': [' 0', '+1', '+2'],
},
};
flush();
const approveButton =
element.shadowRoot
.querySelector('gr-button[data-action-key=\'review\']');
- assert.isNull(approveButton);
+ assert.isOk(approveButton);
});
test('button label for missing approval', () => {
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 aae8bb6..94324f3d 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
@@ -470,7 +470,6 @@
html`<gr-avatar
.account="${account}"
image-size="32"
- aria-label="Account avatar"
></gr-avatar>`
)}
${countUnresolvedComments} unresolved</gr-summary-chip
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 155c77b..eadcc30 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
@@ -155,6 +155,7 @@
ThreadListModifiedEvent,
TabState,
EventType,
+ CloseFixPreviewEvent,
} from '../../../types/events';
import {GrButton} from '../../shared/gr-button/gr-button';
import {GrMessagesList} from '../gr-messages-list/gr-messages-list';
@@ -676,7 +677,7 @@
this._handleCommitMessageCancel()
);
this.addEventListener('open-fix-preview', e => this._onOpenFixPreview(e));
- this.addEventListener('close-fix-preview', () => this._onCloseFixPreview());
+ this.addEventListener('close-fix-preview', e => this._onCloseFixPreview(e));
window.addEventListener('scroll', this.handleScroll);
document.addEventListener('visibilitychange', this.handleVisibilityChange);
@@ -742,8 +743,8 @@
this.$.applyFixDialog.open(e);
}
- _onCloseFixPreview() {
- this._reload();
+ _onCloseFixPreview(e: CloseFixPreviewEvent) {
+ if (e.detail.fixApplied) this._reload();
}
_handleToggleDiffMode(e: CustomKeyboardEvent) {
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list-experimental/gr-related-changes-list-experimental.ts b/polygerrit-ui/app/elements/change/gr-related-changes-list-experimental/gr-related-changes-list-experimental.ts
index ec1235e..c75b8c4 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list-experimental/gr-related-changes-list-experimental.ts
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list-experimental/gr-related-changes-list-experimental.ts
@@ -718,16 +718,15 @@
let button: TemplateResult | typeof nothing = nothing;
if (collapsible) {
- if (this.showAll) {
- button = html`<gr-button link="" @click="${this.toggle}"
- >Show less<iron-icon icon="gr-icons:expand-less"></iron-icon
- ></gr-button>`;
- } else {
- button = html`<gr-button link="" @click="${this.toggle}"
- >Show all (${this.length})
- <iron-icon icon="gr-icons:expand-more"></iron-icon
- ></gr-button>`;
+ let buttonText = 'Show less';
+ let buttonIcon = 'expand-less';
+ if (!this.showAll) {
+ buttonText = `Show all (${this.length})`;
+ buttonIcon = 'expand-more';
}
+ button = html`<gr-button link="" @click="${this.toggle}"
+ >${buttonText}<iron-icon icon="gr-icons:${buttonIcon}"></iron-icon
+ ></gr-button>`;
}
return html`<div class="container">${title}${button}</div>
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts
index 382e17c..f6bd04e 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts
@@ -128,7 +128,7 @@
on-click="_handleAllComments"
checked="[[_showAllComments(_draftsOnly, unresolvedOnly)]]"
/>
- <label for="all">
+ <label for="allRadio">
All ([[_countAllThreads(threads)]])
</label>
</template>
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
index 716d142..0bf9f1c 100644
--- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
+++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
@@ -37,12 +37,14 @@
import {isRobot} from '../../../utils/comment-util';
import {OpenFixPreviewEvent} from '../../../types/events';
import {appContext} from '../../../services/app-context';
-import {fireEvent} from '../../../utils/event-util';
+import {fireCloseFixPreview, fireEvent} from '../../../utils/event-util';
import {ParsedChangeInfo} from '../../../types/types';
+import {GrButton} from '../../shared/gr-button/gr-button';
export interface GrApplyFixDialog {
$: {
applyFixOverlay: GrOverlay;
+ nextFix: GrButton;
};
}
@@ -168,7 +170,7 @@
}
})
.catch(err => {
- this._close();
+ this._close(false);
throw err;
});
}
@@ -186,7 +188,7 @@
if (e) {
e.stopPropagation();
}
- this._close();
+ this._close(false);
}
addOneTo(_selectedFixIdx: number) {
@@ -225,12 +227,12 @@
return _selectedFixIdx === fixSuggestions.length - 1;
}
- _close() {
+ _close(fixApplied: boolean) {
this._currentFix = undefined;
this._currentPreviews = [];
this._isApplyFixLoading = false;
- fireEvent(this, 'close-fix-preview');
+ fireCloseFixPreview(this, fixApplied);
this.$.applyFixOverlay.close();
}
@@ -282,7 +284,7 @@
EditPatchSetNum,
patchNum as BasePatchSetNum
);
- this._close();
+ this._close(true);
}
this._isApplyFixLoading = false;
});
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.js b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.js
deleted file mode 100644
index d78961c..0000000
--- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.js
+++ /dev/null
@@ -1,272 +0,0 @@
-/**
- * @license
- * Copyright (C) 2019 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 './gr-apply-fix-dialog.js';
-import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
-import {stubRestApi} from '../../../test/test-utils.js';
-
-const basicFixture = fixtureFromElement('gr-apply-fix-dialog');
-
-suite('gr-apply-fix-dialog tests', () => {
- let element;
-
- const ROBOT_COMMENT_WITH_TWO_FIXES = {
- robot_id: 'robot_1',
- fix_suggestions: [{fix_id: 'fix_1'}, {fix_id: 'fix_2'}],
- };
-
- const ROBOT_COMMENT_WITH_ONE_FIX = {
- robot_id: 'robot_1',
- fix_suggestions: [{fix_id: 'fix_1'}],
- };
-
- setup(() => {
- element = basicFixture.instantiate();
- element.changeNum = '1';
- element._patchNum = 2;
- element.change = {
- _number: '1',
- project: 'project',
- revisions: {
- abcd: {_number: 1},
- efgh: {_number: 2},
- },
- current_revision: 'efgh',
- };
- element.prefs = {
- font_size: 12,
- line_length: 100,
- tab_size: 4,
- };
- });
-
- suite('dialog open', () => {
- setup(() => {
- stubRestApi('getRobotCommentFixPreview')
- .returns(Promise.resolve({
- f1: {
- meta_a: {},
- meta_b: {},
- content: [
- {
- ab: ['loqlwkqll'],
- },
- {
- b: ['qwqqsqw'],
- },
- {
- ab: ['qwqqsqw', 'qweqeqweqeq', 'qweqweq'],
- },
- ],
- },
- f2: {
- meta_a: {},
- meta_b: {},
- content: [
- {
- ab: ['eqweqweqwex'],
- },
- {
- b: ['zassdasd'],
- },
- {
- ab: ['zassdasd', 'dasdasda', 'asdasdad'],
- },
- ],
- },
- }));
- sinon.stub(element.$.applyFixOverlay, 'open')
- .returns(Promise.resolve());
- });
-
- test('dialog opens fetch and sets previews', done => {
- element.open({detail: {patchNum: 2,
- comment: ROBOT_COMMENT_WITH_TWO_FIXES}})
- .then(() => {
- assert.equal(element._currentFix.fix_id, 'fix_1');
- assert.equal(element._currentPreviews.length, 2);
- assert.equal(element._robotId, 'robot_1');
- const button = element.shadowRoot.querySelector(
- '#applyFixDialog').shadowRoot.querySelector('#confirm');
- assert.isFalse(button.hasAttribute('disabled'));
- assert.equal(button.getAttribute('title'), '');
- done();
- });
- });
-
- test('tooltip is hidden if apply fix is loading', done => {
- element.open({detail: {patchNum: 2,
- comment: ROBOT_COMMENT_WITH_TWO_FIXES}})
- .then(() => {
- element._isApplyFixLoading = true;
- const button = element.shadowRoot.querySelector(
- '#applyFixDialog').shadowRoot.querySelector('#confirm');
- assert.isTrue(button.hasAttribute('disabled'));
- assert.equal(button.getAttribute('title'), '');
- done();
- });
- });
-
- test('apply fix button is disabled on older patchset', done => {
- element.change = {
- _number: '1',
- project: 'project',
- revisions: {
- abcd: {_number: 1},
- efgh: {_number: 2},
- },
- current_revision: 'abcd',
- };
- element.open({detail: {patchNum: 2,
- comment: ROBOT_COMMENT_WITH_ONE_FIX}})
- .then(() => {
- flush(() => {
- const button = element.shadowRoot.querySelector(
- '#applyFixDialog').shadowRoot.querySelector('#confirm');
- assert.isTrue(button.hasAttribute('disabled'));
- assert.equal(button.getAttribute('title'),
- 'Fix can only be applied to the latest patchset');
- done();
- });
- });
- });
- });
-
- test('next button state updated when suggestions changed', done => {
- stubRestApi('getRobotCommentFixPreview').returns(Promise.resolve({}));
- sinon.stub(element.$.applyFixOverlay, 'open').returns(Promise.resolve());
-
- element.open({detail: {patchNum: 2, comment: ROBOT_COMMENT_WITH_ONE_FIX}})
- .then(() => assert.isTrue(element.$.nextFix.disabled))
- .then(() =>
- element.open({detail: {patchNum: 2,
- comment: ROBOT_COMMENT_WITH_TWO_FIXES}}))
- .then(() => {
- assert.isFalse(element.$.nextFix.disabled);
- done();
- });
- });
-
- test('preview endpoint throws error should reset dialog', async () => {
- stubRestApi('getRobotCommentFixPreview').returns(
- Promise.reject(new Error('backend error')));
- element.open({detail: {patchNum: 2,
- comment: ROBOT_COMMENT_WITH_TWO_FIXES}});
- await flush();
- assert.equal(element._currentFix, undefined);
- });
-
- test('apply fix button should call apply ' +
- 'and navigate to change view', () => {
- const stub = stubRestApi('applyFixSuggestion').returns(
- Promise.resolve({ok: true}));
- sinon.stub(GerritNav, 'navigateToChange');
- element._currentFix = {fix_id: '123'};
-
- return element._handleApplyFix().then(() => {
- assert.isTrue(stub.calledWithExactly('1', 2, '123'));
- assert.isTrue(GerritNav.navigateToChange.calledWithExactly({
- _number: '1',
- project: 'project',
- revisions: {
- abcd: {_number: 1},
- efgh: {_number: 2},
- },
- current_revision: 'efgh',
- }, 'edit', 2));
-
- // reset gr-apply-fix-dialog and close
- assert.equal(element._currentFix, undefined);
- assert.equal(element._currentPreviews.length, 0);
- });
- });
-
- test('should not navigate to change view if incorect reponse', done => {
- const stub = stubRestApi('applyFixSuggestion').returns(Promise.resolve({}));
- sinon.stub(GerritNav, 'navigateToChange');
- element._currentFix = {fix_id: '123'};
-
- element._handleApplyFix().then(() => {
- assert.isTrue(stub.calledWithExactly('1', 2, '123'));
- assert.isTrue(GerritNav.navigateToChange.notCalled);
-
- assert.equal(element._isApplyFixLoading, false);
- done();
- });
- });
-
- test('select fix forward and back of multiple suggested fixes', done => {
- stubRestApi('getRobotCommentFixPreview')
- .returns(Promise.resolve({
- f1: {
- meta_a: {},
- meta_b: {},
- content: [
- {
- ab: ['loqlwkqll'],
- },
- {
- b: ['qwqqsqw'],
- },
- {
- ab: ['qwqqsqw', 'qweqeqweqeq', 'qweqweq'],
- },
- ],
- },
- f2: {
- meta_a: {},
- meta_b: {},
- content: [
- {
- ab: ['eqweqweqwex'],
- },
- {
- b: ['zassdasd'],
- },
- {
- ab: ['zassdasd', 'dasdasda', 'asdasdad'],
- },
- ],
- },
- }));
- sinon.stub(element.$.applyFixOverlay, 'open').returns(Promise.resolve());
-
- element.open({detail: {patchNum: 2, comment: ROBOT_COMMENT_WITH_TWO_FIXES}})
- .then(() => {
- element._onNextFixClick();
- assert.equal(element._currentFix.fix_id, 'fix_2');
- element._onPrevFixClick();
- assert.equal(element._currentFix.fix_id, 'fix_1');
- done();
- });
- });
-
- test('server-error should throw for failed apply call', async () => {
- stubRestApi('applyFixSuggestion').returns(
- Promise.reject(new Error('backend error')));
- sinon.stub(GerritNav, 'navigateToChange');
- element._currentFix = {fix_id: '123'};
- let expectedError;
- await element._handleApplyFix().catch(e => {
- expectedError = e;
- });
- assert.isOk(expectedError);
- assert.isFalse(GerritNav.navigateToChange.called);
- });
-});
-
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts
new file mode 100644
index 0000000..d3d7615
--- /dev/null
+++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts
@@ -0,0 +1,376 @@
+/**
+ * @license
+ * Copyright (C) 2019 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-apply-fix-dialog';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation';
+import {queryAndAssert, stubRestApi} from '../../../test/test-utils';
+import {GrApplyFixDialog} from './gr-apply-fix-dialog';
+import {
+ BasePatchSetNum,
+ EditPatchSetNum,
+ PatchSetNum,
+ RobotId,
+ RobotRunId,
+ Timestamp,
+ UrlEncodedCommentId,
+} from '../../../types/common';
+import {
+ createFixSuggestionInfo,
+ createParsedChange,
+ createRevisions,
+ getCurrentRevision,
+} from '../../../test/test-data-generators';
+import {createDefaultDiffPrefs} from '../../../constants/constants';
+import {DiffInfo} from '../../../types/diff';
+import {UIRobot} from '../../../utils/comment-util';
+import {
+ CloseFixPreviewEventDetail,
+ EventType,
+ OpenFixPreviewEventDetail,
+} from '../../../types/events';
+import {GrButton} from '../../shared/gr-button/gr-button';
+
+const basicFixture = fixtureFromElement('gr-apply-fix-dialog');
+
+suite('gr-apply-fix-dialog tests', () => {
+ let element: GrApplyFixDialog;
+
+ const ROBOT_COMMENT_WITH_TWO_FIXES: UIRobot = {
+ id: '1' as UrlEncodedCommentId,
+ updated: '2018-02-08 18:49:18.000000000' as Timestamp,
+ robot_id: 'robot_1' as RobotId,
+ robot_run_id: 'run_1' as RobotRunId,
+ properties: {},
+ fix_suggestions: [
+ createFixSuggestionInfo('fix_1'),
+ createFixSuggestionInfo('fix_2'),
+ ],
+ };
+
+ const ROBOT_COMMENT_WITH_ONE_FIX: UIRobot = {
+ id: '2' as UrlEncodedCommentId,
+ updated: '2018-02-08 18:49:18.000000000' as Timestamp,
+ robot_id: 'robot_1' as RobotId,
+ robot_run_id: 'run_1' as RobotRunId,
+ properties: {},
+ fix_suggestions: [createFixSuggestionInfo('fix_1')],
+ };
+
+ function getConfirmButton(): GrButton {
+ return queryAndAssert(
+ queryAndAssert(element, '#applyFixDialog'),
+ '#confirm'
+ );
+ }
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ const change = {
+ ...createParsedChange(),
+ revisions: createRevisions(2),
+ current_revision: getCurrentRevision(1),
+ };
+ element.changeNum = change._number;
+ element._patchNum = change.revisions[change.current_revision]._number;
+ element.change = change;
+ element.prefs = {
+ ...createDefaultDiffPrefs(),
+ font_size: 12,
+ line_length: 100,
+ tab_size: 4,
+ };
+ });
+
+ suite('dialog open', () => {
+ setup(() => {
+ const diffInfo1: DiffInfo = {
+ meta_a: {
+ name: 'f1',
+ content_type: 'text',
+ lines: 10,
+ },
+ meta_b: {
+ name: 'f1',
+ content_type: 'text',
+ lines: 12,
+ },
+ content: [
+ {
+ ab: ['loqlwkqll'],
+ },
+ {
+ b: ['qwqqsqw'],
+ },
+ {
+ ab: ['qwqqsqw', 'qweqeqweqeq', 'qweqweq'],
+ },
+ ],
+ change_type: 'MODIFIED',
+ intraline_status: 'OK',
+ };
+
+ const diffInfo2: DiffInfo = {
+ meta_a: {
+ name: 'f2',
+ content_type: 'text',
+ lines: 10,
+ },
+ meta_b: {
+ name: 'f2',
+ content_type: 'text',
+ lines: 12,
+ },
+ content: [
+ {
+ ab: ['eqweqweqwex'],
+ },
+ {
+ b: ['zassdasd'],
+ },
+ {
+ ab: ['zassdasd', 'dasdasda', 'asdasdad'],
+ },
+ ],
+ change_type: 'MODIFIED',
+ intraline_status: 'OK',
+ };
+
+ stubRestApi('getRobotCommentFixPreview').returns(
+ Promise.resolve({
+ f1: diffInfo1,
+ f2: diffInfo2,
+ })
+ );
+ sinon.stub(element.$.applyFixOverlay, 'open').returns(Promise.resolve());
+ });
+
+ test('dialog opens fetch and sets previews', async () => {
+ await element.open(
+ new CustomEvent<OpenFixPreviewEventDetail>(EventType.OPEN_FIX_PREVIEW, {
+ detail: {
+ patchNum: 2 as PatchSetNum,
+ comment: ROBOT_COMMENT_WITH_TWO_FIXES,
+ },
+ })
+ );
+ assert.equal(element._currentFix!.fix_id, 'fix_1');
+ assert.equal(element._currentPreviews.length, 2);
+ assert.equal(element._robotId, 'robot_1' as RobotId);
+ const button = getConfirmButton();
+ assert.isFalse(button.hasAttribute('disabled'));
+ assert.equal(button.getAttribute('title'), '');
+ });
+
+ test('tooltip is hidden if apply fix is loading', async () => {
+ await element.open(
+ new CustomEvent<OpenFixPreviewEventDetail>(EventType.OPEN_FIX_PREVIEW, {
+ detail: {
+ patchNum: 2 as PatchSetNum,
+ comment: ROBOT_COMMENT_WITH_TWO_FIXES,
+ },
+ })
+ );
+ element._isApplyFixLoading = true;
+ const button = getConfirmButton();
+ assert.isTrue(button.hasAttribute('disabled'));
+ assert.equal(button.getAttribute('title'), '');
+ });
+
+ test('apply fix button is disabled on older patchset', async () => {
+ element.change = element.change = {
+ ...createParsedChange(),
+ revisions: createRevisions(2),
+ current_revision: getCurrentRevision(0),
+ };
+ await element.open(
+ new CustomEvent<OpenFixPreviewEventDetail>(EventType.OPEN_FIX_PREVIEW, {
+ detail: {
+ patchNum: 2 as PatchSetNum,
+ comment: ROBOT_COMMENT_WITH_ONE_FIX,
+ },
+ })
+ );
+ await flush();
+ const button = getConfirmButton();
+ assert.isTrue(button.hasAttribute('disabled'));
+ assert.equal(
+ button.getAttribute('title'),
+ 'Fix can only be applied to the latest patchset'
+ );
+ });
+ });
+
+ test('next button state updated when suggestions changed', async () => {
+ stubRestApi('getRobotCommentFixPreview').returns(Promise.resolve({}));
+ sinon.stub(element.$.applyFixOverlay, 'open').returns(Promise.resolve());
+
+ await element.open(
+ new CustomEvent<OpenFixPreviewEventDetail>(EventType.OPEN_FIX_PREVIEW, {
+ detail: {
+ patchNum: 2 as PatchSetNum,
+ comment: ROBOT_COMMENT_WITH_ONE_FIX,
+ },
+ })
+ );
+ assert.isTrue(element.$.nextFix.disabled);
+ await element.open(
+ new CustomEvent<OpenFixPreviewEventDetail>(EventType.OPEN_FIX_PREVIEW, {
+ detail: {
+ patchNum: 2 as PatchSetNum,
+ comment: ROBOT_COMMENT_WITH_TWO_FIXES,
+ },
+ })
+ );
+ assert.isFalse(element.$.nextFix.disabled);
+ });
+
+ test('preview endpoint throws error should reset dialog', async () => {
+ stubRestApi('getRobotCommentFixPreview').returns(
+ Promise.reject(new Error('backend error'))
+ );
+ element.open(
+ new CustomEvent<OpenFixPreviewEventDetail>(EventType.OPEN_FIX_PREVIEW, {
+ detail: {
+ patchNum: 2 as PatchSetNum,
+ comment: ROBOT_COMMENT_WITH_TWO_FIXES,
+ },
+ })
+ );
+ await flush();
+ assert.equal(element._currentFix, undefined);
+ });
+
+ test('apply fix button should call apply, navigate to change view and fire close', async () => {
+ const applyFixSuggestionStub = stubRestApi('applyFixSuggestion').returns(
+ Promise.resolve(new Response(null, {status: 200}))
+ );
+ const navigateToChangeStub = sinon.stub(GerritNav, 'navigateToChange');
+ element._currentFix = createFixSuggestionInfo('123');
+
+ const closeFixPreviewEventSpy = sinon.spy();
+ // Element is recreated after each test, removeEventListener isn't required
+ element.addEventListener(
+ EventType.CLOSE_FIX_PREVIEW,
+ closeFixPreviewEventSpy
+ );
+ await element._handleApplyFix(new CustomEvent('confirm'));
+
+ sinon.assert.calledOnceWithExactly(
+ applyFixSuggestionStub,
+ element.change!._number,
+ 2 as PatchSetNum,
+ '123'
+ );
+ sinon.assert.calledWithExactly(
+ navigateToChangeStub,
+ element.change!,
+ EditPatchSetNum,
+ element.change!.revisions[2]._number as BasePatchSetNum
+ );
+
+ sinon.assert.calledOnceWithExactly(
+ closeFixPreviewEventSpy,
+ new CustomEvent<CloseFixPreviewEventDetail>(EventType.CLOSE_FIX_PREVIEW, {
+ detail: {
+ fixApplied: true,
+ },
+ })
+ );
+
+ // reset gr-apply-fix-dialog and close
+ assert.equal(element._currentFix, undefined);
+ assert.equal(element._currentPreviews.length, 0);
+ });
+
+ test('should not navigate to change view if incorect reponse', async () => {
+ const applyFixSuggestionStub = stubRestApi('applyFixSuggestion').returns(
+ Promise.resolve(new Response(null, {status: 500}))
+ );
+ const navigateToChangeStub = sinon.stub(GerritNav, 'navigateToChange');
+ element._currentFix = createFixSuggestionInfo('fix_123');
+
+ await element._handleApplyFix(new CustomEvent('confirm'));
+ sinon.assert.calledWithExactly(
+ applyFixSuggestionStub,
+ element.change!._number,
+ 2 as PatchSetNum,
+ 'fix_123'
+ );
+ assert.isTrue(navigateToChangeStub.notCalled);
+
+ assert.equal(element._isApplyFixLoading, false);
+ });
+
+ test('select fix forward and back of multiple suggested fixes', async () => {
+ sinon.stub(element.$.applyFixOverlay, 'open').returns(Promise.resolve());
+
+ await element.open(
+ new CustomEvent<OpenFixPreviewEventDetail>(EventType.OPEN_FIX_PREVIEW, {
+ detail: {
+ patchNum: 2 as PatchSetNum,
+ comment: ROBOT_COMMENT_WITH_TWO_FIXES,
+ },
+ })
+ );
+ element._onNextFixClick(new CustomEvent('click'));
+ assert.equal(element._currentFix!.fix_id, 'fix_2');
+ element._onPrevFixClick(new CustomEvent('click'));
+ assert.equal(element._currentFix!.fix_id, 'fix_1');
+ });
+
+ test('server-error should throw for failed apply call', async () => {
+ stubRestApi('applyFixSuggestion').returns(
+ Promise.reject(new Error('backend error'))
+ );
+ const navigateToChangeStub = sinon.stub(GerritNav, 'navigateToChange');
+ element._currentFix = createFixSuggestionInfo('fix_123');
+
+ const closeFixPreviewEventSpy = sinon.spy();
+ // Element is recreated after each test, removeEventListener isn't required
+ element.addEventListener(
+ EventType.CLOSE_FIX_PREVIEW,
+ closeFixPreviewEventSpy
+ );
+
+ let expectedError;
+ await element._handleApplyFix(new CustomEvent('click')).catch(e => {
+ expectedError = e;
+ });
+ assert.isOk(expectedError);
+ assert.isFalse(navigateToChangeStub.called);
+ sinon.assert.notCalled(closeFixPreviewEventSpy);
+ });
+
+ test('onCancel fires close with correct parameters', () => {
+ const closeFixPreviewEventSpy = sinon.spy();
+ // Element is recreated after each test, removeEventListener isn't required
+ element.addEventListener(
+ EventType.CLOSE_FIX_PREVIEW,
+ closeFixPreviewEventSpy
+ );
+ element.onCancel(new CustomEvent('cancel'));
+ sinon.assert.calledOnceWithExactly(
+ closeFixPreviewEventSpy,
+ new CustomEvent<CloseFixPreviewEventDetail>(EventType.CLOSE_FIX_PREVIEW, {
+ detail: {
+ fixApplied: false,
+ },
+ })
+ );
+ });
+});
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts
index 24a7d78..874f572 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts
@@ -72,6 +72,7 @@
declare global {
interface HTMLElementEventMap {
'diff-context-expanded': CustomEvent<DiffContextExpandedEventDetail>;
+ 'content-load-needed': CustomEvent<ContentLoadNeededEventDetail>;
}
}
@@ -511,14 +512,14 @@
end_line: lastRange.right.end_line,
},
};
- fire<ContentLoadNeededEventDetail>(button, 'content-load-needed', {
+ fire(button, 'content-load-needed', {
lineRange,
});
});
} else {
button.addEventListener('click', e => {
e.stopPropagation();
- fire<DiffContextExpandedEventDetail>(button, 'diff-context-expanded', {
+ fire(button, 'diff-context-expanded', {
groups,
section,
numLines,
diff --git a/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts b/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts
index 85931b4..746d101 100644
--- a/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts
+++ b/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts
@@ -837,8 +837,9 @@
// mark-reviewed and then press ] to go to the next file'.
(tagName === 'INPUT' && type !== 'checkbox') ||
tagName === 'TEXTAREA' ||
- // Suppress shortcuts if the key is 'enter' and target is an anchor.
- (e.keyCode === 13 && tagName === 'A')
+ // Suppress shortcuts if the key is 'enter'
+ // and target is an anchor or button.
+ (e.keyCode === 13 && (tagName === 'A' || tagName === 'BUTTON'))
) {
return true;
}
diff --git a/polygerrit-ui/app/styles/themes/dark-theme.ts b/polygerrit-ui/app/styles/themes/dark-theme.ts
index f877771..01cee4c 100644
--- a/polygerrit-ui/app/styles/themes/dark-theme.ts
+++ b/polygerrit-ui/app/styles/themes/dark-theme.ts
@@ -174,7 +174,7 @@
--header-text-color: var(--primary-text-color);
/* diff colors */
- --dark-add-highlight-color: #133820;
+ --dark-add-highlight-color: var(--green-tonal);
--dark-rebased-add-highlight-color: rgba(11, 255, 155, 0.15);
--dark-rebased-remove-highlight-color: rgba(255, 139, 6, 0.15);
--dark-remove-highlight-color: #62110f;
@@ -187,7 +187,7 @@
--diff-selection-background-color: #3a71d8;
--diff-tab-indicator-color: var(--deemphasized-text-color);
--diff-trailing-whitespace-indicator: #ff9ad2;
- --light-add-highlight-color: #0f401f;
+ --light-add-highlight-color: #182b1f;
--light-rebased-add-highlight-color: #487165;
--diff-moved-in-background: #1d4042;
--diff-moved-out-background: #230e34;
diff --git a/polygerrit-ui/app/test/test-data-generators.ts b/polygerrit-ui/app/test/test-data-generators.ts
index 3bfe743..778e58d 100644
--- a/polygerrit-ui/app/test/test-data-generators.ts
+++ b/polygerrit-ui/app/test/test-data-generators.ts
@@ -65,6 +65,8 @@
RelatedChangeAndCommitInfo,
SubmittedTogetherInfo,
RelatedChangesInfo,
+ FixSuggestionInfo,
+ FixId,
} from '../types/common';
import {
AccountsVisibility,
@@ -614,3 +616,11 @@
non_visible_changes: 0,
};
}
+
+export function createFixSuggestionInfo(fixId = 'fix_1'): FixSuggestionInfo {
+ return {
+ fix_id: fixId as FixId,
+ description: `Fix ${fixId}`,
+ replacements: [],
+ };
+}
diff --git a/polygerrit-ui/app/types/events.ts b/polygerrit-ui/app/types/events.ts
index 11155c1..7bde788 100644
--- a/polygerrit-ui/app/types/events.ts
+++ b/polygerrit-ui/app/types/events.ts
@@ -32,6 +32,7 @@
MOVED_LINK_CLICKED = 'moved-link-clicked',
NETWORK_ERROR = 'network-error',
OPEN_FIX_PREVIEW = 'open-fix-preview',
+ CLOSE_FIX_PREVIEW = 'close-fix-preview',
PAGE_ERROR = 'page-error',
RELOAD = 'reload',
REPLY = 'reply',
@@ -54,6 +55,7 @@
'iron-announce': IronAnnounceEvent;
'moved-link-clicked': MovedLinkClickedEvent;
'open-fix-preview': OpenFixPreviewEvent;
+ 'close-fix-preview': CloseFixPreviewEvent;
/* prettier-ignore */
'reload': ReloadEvent;
/* prettier-ignore */
@@ -133,6 +135,11 @@
}
export type OpenFixPreviewEvent = CustomEvent<OpenFixPreviewEventDetail>;
+export interface CloseFixPreviewEventDetail {
+ fixApplied: boolean;
+}
+export type CloseFixPreviewEvent = CustomEvent<CloseFixPreviewEventDetail>;
+
export interface PageErrorEventDetail {
response?: Response;
}
diff --git a/polygerrit-ui/app/utils/change-metadata-util.ts b/polygerrit-ui/app/utils/change-metadata-util.ts
index c3eb846..d39b10b 100644
--- a/polygerrit-ui/app/utils/change-metadata-util.ts
+++ b/polygerrit-ui/app/utils/change-metadata-util.ts
@@ -41,11 +41,11 @@
Metadata.REVIEWERS,
Metadata.REPO_BRANCH,
Metadata.SUBMITTED,
+ Metadata.TOPIC,
],
SHOW_IF_SET: [
Metadata.CC,
Metadata.HASHTAGS,
- Metadata.TOPIC,
Metadata.UPLOADER,
Metadata.AUTHOR,
Metadata.COMMITTER,
diff --git a/polygerrit-ui/app/utils/date-util.ts b/polygerrit-ui/app/utils/date-util.ts
index 3af8c59..a780af5 100644
--- a/polygerrit-ui/app/utils/date-util.ts
+++ b/polygerrit-ui/app/utils/date-util.ts
@@ -90,15 +90,6 @@
const diff = now.valueOf() - date.valueOf();
return diff < 180 * Duration.DAY;
}
-interface Options {
- month?: string;
- year?: string;
- day?: string;
- hour?: string;
- hour12?: boolean;
- minute?: string;
- second?: string;
-}
// TODO(dmfilippov): TS-Fix review this type. All fields here must be optional,
// but this require some changes in the code. During JS->TS migration
@@ -118,7 +109,7 @@
}
export function formatDate(date: Date, format: string) {
- const options: Options = {};
+ const options: Intl.DateTimeFormatOptions = {};
if (format.includes('MM')) {
if (format.includes('MMM')) {
options.month = 'short';
diff --git a/polygerrit-ui/app/utils/event-util.ts b/polygerrit-ui/app/utils/event-util.ts
index 080955f..da075f1 100644
--- a/polygerrit-ui/app/utils/event-util.ts
+++ b/polygerrit-ui/app/utils/event-util.ts
@@ -20,15 +20,8 @@
import {
DialogChangeEventDetail,
EventType,
- IronAnnounceEventDetail,
- NetworkErrorEventDetail,
- PageErrorEventDetail,
- ServerErrorEventDetail,
- ShowAlertEventDetail,
SwitchTabEventDetail,
TabState,
- ThreadListModifiedDetail,
- TitleChangeEventDetail,
} from '../types/events';
export function fireEvent(target: EventTarget, type: string) {
@@ -40,6 +33,34 @@
);
}
+type HTMLElementEventDetailType<
+ K extends keyof HTMLElementEventMap
+> = HTMLElementEventMap[K] extends CustomEvent<infer DT>
+ ? unknown extends DT
+ ? never
+ : DT
+ : never;
+
+type DocumentEventDetailType<
+ K extends keyof DocumentEventMap
+> = DocumentEventMap[K] extends CustomEvent<infer DT>
+ ? unknown extends DT
+ ? never
+ : DT
+ : never;
+
+export function fire<K extends keyof DocumentEventMap>(
+ target: Document,
+ type: K,
+ detail: DocumentEventDetailType<K>
+): void;
+
+export function fire<K extends keyof HTMLElementEventMap>(
+ target: EventTarget,
+ type: K,
+ detail: HTMLElementEventDetailType<K>
+): void;
+
export function fire<T>(target: EventTarget, type: string, detail: T) {
target.dispatchEvent(
new CustomEvent<T>(type, {
@@ -51,27 +72,27 @@
}
export function fireAlert(target: EventTarget, message: string) {
- fire<ShowAlertEventDetail>(target, EventType.SHOW_ALERT, {message});
+ fire(target, EventType.SHOW_ALERT, {message});
}
export function firePageError(response?: Response | null) {
if (response === null) response = undefined;
- fire<PageErrorEventDetail>(document, EventType.PAGE_ERROR, {response});
+ fire(document, EventType.PAGE_ERROR, {response});
}
export function fireServerError(response: Response, request?: FetchRequest) {
- fire<ServerErrorEventDetail>(document, EventType.SERVER_ERROR, {
+ fire(document, EventType.SERVER_ERROR, {
response,
request,
});
}
export function fireNetworkError(error: Error) {
- fire<NetworkErrorEventDetail>(document, EventType.NETWORK_ERROR, {error});
+ fire(document, EventType.NETWORK_ERROR, {error});
}
export function fireTitleChange(target: EventTarget, title: string) {
- fire<TitleChangeEventDetail>(target, EventType.TITLE_CHANGE, {title});
+ fire(target, EventType.TITLE_CHANGE, {title});
}
// TODO(milutin) - remove once new gr-dialog will do it out of the box
@@ -80,11 +101,11 @@
target: EventTarget,
detail: DialogChangeEventDetail
) {
- fire<DialogChangeEventDetail>(target, EventType.DIALOG_CHANGE, detail);
+ fire(target, EventType.DIALOG_CHANGE, detail);
}
export function fireIronAnnounce(target: EventTarget, text: string) {
- fire<IronAnnounceEventDetail>(target, EventType.IRON_ANNOUNCE, {text});
+ fire(target, EventType.IRON_ANNOUNCE, {text});
}
export function fireThreadListModifiedEvent(
@@ -92,7 +113,7 @@
rootId: UrlEncodedCommentId,
path: string
) {
- fire<ThreadListModifiedDetail>(target, EventType.THREAD_LIST_MODIFIED, {
+ fire(target, EventType.THREAD_LIST_MODIFIED, {
rootId,
path,
});
@@ -105,7 +126,11 @@
tabState?: TabState
) {
const detail: SwitchTabEventDetail = {tab, scrollIntoView, tabState};
- fire<SwitchTabEventDetail>(target, EventType.SHOW_PRIMARY_TAB, detail);
+ fire(target, EventType.SHOW_PRIMARY_TAB, detail);
+}
+
+export function fireCloseFixPreview(target: EventTarget, fixApplied: boolean) {
+ fire(target, EventType.CLOSE_FIX_PREVIEW, {fixApplied});
}
export function waitForEventOnce<K extends keyof HTMLElementEventMap>(
diff --git a/resources/log4j.properties b/resources/log4j.properties
index 39246b3..2898cfc 100644
--- a/resources/log4j.properties
+++ b/resources/log4j.properties
@@ -41,11 +41,5 @@
log4j.logger.org.openid4java.server.RealmVerifier=ERROR
log4j.logger.org.openid4java.message.AuthSuccess=ERROR
-# Silence non-critical messages from c3p0 (if used).
-#
-log4j.logger.com.mchange.v2.c3p0=WARN
-log4j.logger.com.mchange.v2.resourcepool=WARN
-log4j.logger.com.mchange.v2.sql=WARN
-
# Silence non-critical messages from apache.http
log4j.logger.org.apache.http=WARN
diff --git a/tools/maven/gerrit-acceptance-framework_pom.xml b/tools/maven/gerrit-acceptance-framework_pom.xml
index 718f8d0..3705407 100644
--- a/tools/maven/gerrit-acceptance-framework_pom.xml
+++ b/tools/maven/gerrit-acceptance-framework_pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-acceptance-framework</artifactId>
- <version>3.4.0-SNAPSHOT</version>
+ <version>3.5.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Gerrit Code Review - Acceptance Test Framework</name>
<description>Framework for Gerrit's acceptance tests</description>
diff --git a/tools/maven/gerrit-extension-api_pom.xml b/tools/maven/gerrit-extension-api_pom.xml
index a415f24..ba35ca2 100644
--- a/tools/maven/gerrit-extension-api_pom.xml
+++ b/tools/maven/gerrit-extension-api_pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-extension-api</artifactId>
- <version>3.4.0-SNAPSHOT</version>
+ <version>3.5.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Gerrit Code Review - Extension API</name>
<description>API for Gerrit Extensions</description>
diff --git a/tools/maven/gerrit-plugin-api_pom.xml b/tools/maven/gerrit-plugin-api_pom.xml
index 5e58fdd..b7954c7 100644
--- a/tools/maven/gerrit-plugin-api_pom.xml
+++ b/tools/maven/gerrit-plugin-api_pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-plugin-api</artifactId>
- <version>3.4.0-SNAPSHOT</version>
+ <version>3.5.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Gerrit Code Review - Plugin API</name>
<description>API for Gerrit Plugins</description>
diff --git a/tools/maven/gerrit-war_pom.xml b/tools/maven/gerrit-war_pom.xml
index 3b3a055..118cf39 100644
--- a/tools/maven/gerrit-war_pom.xml
+++ b/tools/maven/gerrit-war_pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-war</artifactId>
- <version>3.4.0-SNAPSHOT</version>
+ <version>3.5.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Gerrit Code Review - WAR</name>
<description>Gerrit WAR</description>
diff --git a/tools/node_tools/package.json b/tools/node_tools/package.json
index bfc5191..2f33078 100644
--- a/tools/node_tools/package.json
+++ b/tools/node_tools/package.json
@@ -16,7 +16,7 @@
"rollup": "^2.3.4",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-terser": "^5.1.3",
- "typescript": "4.0.5"
+ "typescript": "4.1.4"
},
"devDependencies": {},
"license": "Apache-2.0",
diff --git a/tools/node_tools/yarn.lock b/tools/node_tools/yarn.lock
index 767f285..abb54b0 100644
--- a/tools/node_tools/yarn.lock
+++ b/tools/node_tools/yarn.lock
@@ -7893,10 +7893,10 @@
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-typescript@4.0.5:
- version "4.0.5"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389"
- integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==
+typescript@4.1.4:
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.4.tgz#f058636e2f4f83f94ddaae07b20fd5e14598432f"
+ integrity sha512-+Uru0t8qIRgjuCpiSPpfGuhHecMllk5Zsazj5LZvVsEStEjmIRRBZe+jHjGQvsgS7M1wONy2PQXd67EMyV6acg==
typical@^2.6.0, typical@^2.6.1:
version "2.6.1"
diff --git a/version.bzl b/version.bzl
index 066d07e..f2e0d0c 100644
--- a/version.bzl
+++ b/version.bzl
@@ -2,4 +2,4 @@
# Used by :api_install and :api_deploy targets
# when talking to the destination repository.
#
-GERRIT_VERSION = "3.4.0-SNAPSHOT"
+GERRIT_VERSION = "3.5.0-SNAPSHOT"
diff --git a/yarn.lock b/yarn.lock
index adb731c..d18d5fd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9680,10 +9680,10 @@
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-typescript@4.0.5:
- version "4.0.5"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389"
- integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==
+typescript@4.1.4:
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.4.tgz#f058636e2f4f83f94ddaae07b20fd5e14598432f"
+ integrity sha512-+Uru0t8qIRgjuCpiSPpfGuhHecMllk5Zsazj5LZvVsEStEjmIRRBZe+jHjGQvsgS7M1wONy2PQXd67EMyV6acg==
typical@^2.6.1:
version "2.6.1"