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"