Merge "Add 'parentof' operator that matches parent changes for a change"
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 91fe24b..23720460 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -5189,6 +5189,13 @@
+
By default 50.
+[[suggest.skipServiceUsers]]suggest.skipServiceUsers::
++
+If link:access-control.html#service_users[service users] should be skipped when
+suggesting reviewers.
++
+By default true.
+
[[tracing]]
=== Section tracing
diff --git a/Documentation/rest-api-config.txt b/Documentation/rest-api-config.txt
index 9764c8a..a8d9b3d 100644
--- a/Documentation/rest-api-config.txt
+++ b/Documentation/rest-api-config.txt
@@ -1839,6 +1839,8 @@
Whether to enable the web UI for editing GPG keys.
|`report_bug_url` |optional|
link:config-gerrit.html#gerrit.reportBugUrl[URL to report bugs].
+|`instance_id` |optional|
+link:config-gerrit.html#gerrit.instanceId[Short identifier for this Gerrit installation].
|=================================
[[index-config-info]]
diff --git a/WORKSPACE b/WORKSPACE
index ccbc63d..c24d4f9 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -842,55 +842,55 @@
sha1 = "7e060dd5b19431e6d198e91ff670644372f60fbd",
)
-JETTY_VERS = "9.4.35.v20201120"
+JETTY_VERS = "9.4.36.v20210114"
maven_jar(
name = "jetty-servlet",
artifact = "org.eclipse.jetty:jetty-servlet:" + JETTY_VERS,
- sha1 = "3e61bcb471e1bfc545ce866cbbe33c3aedeec9b1",
+ sha1 = "b189e52a5ee55ae172e4e99e29c5c314f5daf4b9",
)
maven_jar(
name = "jetty-security",
artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VERS,
- sha1 = "80dc2f422789c78315de76d289b7a5b36c3232d5",
+ sha1 = "42030d6ed7dfc0f75818cde0adcf738efc477574",
)
maven_jar(
name = "jetty-server",
artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VERS,
- sha1 = "513502352fd689d4730b2935421b990ada8cc818",
+ sha1 = "88a7d342974aadca658e7386e8d0fcc5c0788f41",
)
maven_jar(
name = "jetty-jmx",
artifact = "org.eclipse.jetty:jetty-jmx:" + JETTY_VERS,
- sha1 = "38812031940a466d626ab5d9bbbd9d5d39e9f735",
+ sha1 = "bb3847eabe085832aeaedd30e872b40931632e54",
)
maven_jar(
name = "jetty-http",
artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VERS,
- sha1 = "45d35131a35a1e76991682174421e8cdf765fb9f",
+ sha1 = "1eee89a55e04ff94df0f85d95200fc48acb43d86",
)
maven_jar(
name = "jetty-io",
artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VERS,
- sha1 = "eb9460700b99b71ecd82a53697f5ff99f69b9e1c",
+ sha1 = "84a8faf9031eb45a5a2ddb7681e22c483d81ab3a",
)
maven_jar(
name = "jetty-util",
artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VERS,
- sha1 = "ef61b83f9715c3b5355b633d9f01d2834f908ece",
+ sha1 = "925257fbcca6b501a25252c7447dbedb021f7404",
)
maven_jar(
name = "jetty-util-ajax",
artifact = "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VERS,
- sha1 = "ebbb43912c6423bedb3458e44aee28eeb4d66f27",
- src_sha1 = "b3acea974a17493afb125a9dfbe783870ce1d2f9",
+ sha1 = "2f478130c21787073facb64d7242e06f94980c60",
+ src_sha1 = "7153d7ca38878d971fd90992c303bb7719ba7a21",
)
maven_jar(
diff --git a/java/com/google/gerrit/extensions/common/ActionInfo.java b/java/com/google/gerrit/extensions/common/ActionInfo.java
index 6ab80b2..2144ed5 100644
--- a/java/com/google/gerrit/extensions/common/ActionInfo.java
+++ b/java/com/google/gerrit/extensions/common/ActionInfo.java
@@ -15,6 +15,7 @@
package com.google.gerrit.extensions.common;
import com.google.gerrit.extensions.webui.UiAction;
+import java.util.Objects;
/**
* Representation of an action in the REST API.
@@ -55,4 +56,23 @@
title = d.getTitle();
enabled = d.isEnabled() ? true : null;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof ActionInfo) {
+ ActionInfo actionInfo = (ActionInfo) o;
+ return Objects.equals(method, actionInfo.method)
+ && Objects.equals(label, actionInfo.label)
+ && Objects.equals(title, actionInfo.title)
+ && Objects.equals(enabled, actionInfo.enabled);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(method, label, title, enabled);
+ }
+
+ protected ActionInfo() {}
}
diff --git a/java/com/google/gerrit/extensions/common/ApprovalInfo.java b/java/com/google/gerrit/extensions/common/ApprovalInfo.java
index f95ddff..bf72e83 100644
--- a/java/com/google/gerrit/extensions/common/ApprovalInfo.java
+++ b/java/com/google/gerrit/extensions/common/ApprovalInfo.java
@@ -16,6 +16,7 @@
import com.google.gerrit.common.Nullable;
import java.sql.Timestamp;
+import java.util.Objects;
/**
* Representation of an approval in the REST API.
@@ -71,4 +72,23 @@
this.date = date;
this.tag = tag;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof ApprovalInfo) {
+ ApprovalInfo approvalInfo = (ApprovalInfo) o;
+ return super.equals(o)
+ && Objects.equals(tag, approvalInfo.tag)
+ && Objects.equals(value, approvalInfo.value)
+ && Objects.equals(date, approvalInfo.date)
+ && Objects.equals(postSubmit, approvalInfo.postSubmit)
+ && Objects.equals(permittedVotingRange, approvalInfo.permittedVotingRange);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), tag, value, date, postSubmit, permittedVotingRange);
+ }
}
diff --git a/java/com/google/gerrit/extensions/common/AttentionSetInfo.java b/java/com/google/gerrit/extensions/common/AttentionSetInfo.java
index f29d32b..ba865fb 100644
--- a/java/com/google/gerrit/extensions/common/AttentionSetInfo.java
+++ b/java/com/google/gerrit/extensions/common/AttentionSetInfo.java
@@ -15,6 +15,7 @@
package com.google.gerrit.extensions.common;
import java.sql.Timestamp;
+import java.util.Objects;
/**
* Represents a single user included in the attention set. Used in the API. See {@link
@@ -36,4 +37,22 @@
this.lastUpdate = lastUpdate;
this.reason = reason;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof AttentionSetInfo) {
+ AttentionSetInfo attentionSetInfo = (AttentionSetInfo) o;
+ return Objects.equals(account, attentionSetInfo.account)
+ && Objects.equals(lastUpdate, attentionSetInfo.lastUpdate)
+ && Objects.equals(reason, attentionSetInfo.reason);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(account, lastUpdate, reason);
+ }
+
+ protected AttentionSetInfo() {}
}
diff --git a/java/com/google/gerrit/extensions/common/AvatarInfo.java b/java/com/google/gerrit/extensions/common/AvatarInfo.java
index 75665a8..b620ac2 100644
--- a/java/com/google/gerrit/extensions/common/AvatarInfo.java
+++ b/java/com/google/gerrit/extensions/common/AvatarInfo.java
@@ -14,6 +14,8 @@
package com.google.gerrit.extensions.common;
+import java.util.Objects;
+
/**
* Representation of an avatar in the REST API.
*
@@ -38,4 +40,20 @@
/** The width of the avatar image in pixels. */
public Integer width;
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof AvatarInfo) {
+ AvatarInfo avatarInfo = (AvatarInfo) o;
+ return Objects.equals(url, avatarInfo.url)
+ && Objects.equals(height, avatarInfo.height)
+ && Objects.equals(width, avatarInfo.width);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(url, height, width);
+ }
}
diff --git a/java/com/google/gerrit/extensions/common/FetchInfo.java b/java/com/google/gerrit/extensions/common/FetchInfo.java
index eda84b1..4b1e941 100644
--- a/java/com/google/gerrit/extensions/common/FetchInfo.java
+++ b/java/com/google/gerrit/extensions/common/FetchInfo.java
@@ -15,6 +15,7 @@
package com.google.gerrit.extensions.common;
import java.util.Map;
+import java.util.Objects;
public class FetchInfo {
public String url;
@@ -25,4 +26,22 @@
this.url = url;
this.ref = ref;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof FetchInfo) {
+ FetchInfo fetchInfo = (FetchInfo) o;
+ return Objects.equals(url, fetchInfo.url)
+ && Objects.equals(ref, fetchInfo.ref)
+ && Objects.equals(commands, fetchInfo.commands);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(url, ref, commands);
+ }
+
+ protected FetchInfo() {}
}
diff --git a/java/com/google/gerrit/extensions/common/GerritInfo.java b/java/com/google/gerrit/extensions/common/GerritInfo.java
index 2ae6703..3265a00 100644
--- a/java/com/google/gerrit/extensions/common/GerritInfo.java
+++ b/java/com/google/gerrit/extensions/common/GerritInfo.java
@@ -23,4 +23,5 @@
public Boolean editGpgKeys;
public String reportBugUrl;
public String primaryWeblinkName;
+ public String instanceId;
}
diff --git a/java/com/google/gerrit/extensions/common/GpgKeyInfo.java b/java/com/google/gerrit/extensions/common/GpgKeyInfo.java
index 7a5c15b..d656f22 100644
--- a/java/com/google/gerrit/extensions/common/GpgKeyInfo.java
+++ b/java/com/google/gerrit/extensions/common/GpgKeyInfo.java
@@ -15,6 +15,7 @@
package com.google.gerrit.extensions.common;
import java.util.List;
+import java.util.Objects;
public class GpgKeyInfo {
/**
@@ -43,4 +44,22 @@
public Status status;
public List<String> problems;
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof GpgKeyInfo) {
+ GpgKeyInfo gpgKeyInfo = (GpgKeyInfo) o;
+ return Objects.equals(id, gpgKeyInfo.id)
+ && Objects.equals(fingerprint, gpgKeyInfo.fingerprint)
+ && Objects.equals(userIds, gpgKeyInfo.userIds)
+ && Objects.equals(status, gpgKeyInfo.status)
+ && Objects.equals(problems, gpgKeyInfo.problems);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, fingerprint, userIds, status, problems);
+ }
}
diff --git a/java/com/google/gerrit/extensions/common/LabelInfo.java b/java/com/google/gerrit/extensions/common/LabelInfo.java
index 76dd93d..44bcdaf 100644
--- a/java/com/google/gerrit/extensions/common/LabelInfo.java
+++ b/java/com/google/gerrit/extensions/common/LabelInfo.java
@@ -16,6 +16,7 @@
import java.util.List;
import java.util.Map;
+import java.util.Objects;
public class LabelInfo {
public AccountInfo approved;
@@ -30,4 +31,37 @@
public Short defaultValue;
public Boolean optional;
public Boolean blocking;
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof LabelInfo) {
+ LabelInfo labelInfo = (LabelInfo) o;
+ return Objects.equals(approved, labelInfo.approved)
+ && Objects.equals(rejected, labelInfo.rejected)
+ && Objects.equals(recommended, labelInfo.recommended)
+ && Objects.equals(disliked, labelInfo.disliked)
+ && Objects.equals(all, labelInfo.all)
+ && Objects.equals(values, labelInfo.values)
+ && Objects.equals(value, labelInfo.value)
+ && Objects.equals(defaultValue, labelInfo.defaultValue)
+ && Objects.equals(optional, labelInfo.optional)
+ && Objects.equals(blocking, labelInfo.blocking);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ approved,
+ rejected,
+ recommended,
+ disliked,
+ all,
+ values,
+ value,
+ defaultValue,
+ optional,
+ blocking);
+ }
}
diff --git a/java/com/google/gerrit/extensions/common/PluginDefinedInfo.java b/java/com/google/gerrit/extensions/common/PluginDefinedInfo.java
index 69bfa2c..e2b1c36 100644
--- a/java/com/google/gerrit/extensions/common/PluginDefinedInfo.java
+++ b/java/com/google/gerrit/extensions/common/PluginDefinedInfo.java
@@ -14,7 +14,24 @@
package com.google.gerrit.extensions.common;
+import java.util.Objects;
+
public class PluginDefinedInfo {
public String name;
public String message;
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof PluginDefinedInfo) {
+ PluginDefinedInfo pluginDefinedInfo = (PluginDefinedInfo) o;
+ return Objects.equals(name, pluginDefinedInfo.name)
+ && Objects.equals(message, pluginDefinedInfo.message);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, message);
+ }
}
diff --git a/java/com/google/gerrit/extensions/common/PushCertificateInfo.java b/java/com/google/gerrit/extensions/common/PushCertificateInfo.java
index 9eed808..199dbd1 100644
--- a/java/com/google/gerrit/extensions/common/PushCertificateInfo.java
+++ b/java/com/google/gerrit/extensions/common/PushCertificateInfo.java
@@ -14,7 +14,24 @@
package com.google.gerrit.extensions.common;
+import java.util.Objects;
+
public class PushCertificateInfo {
public String certificate;
public GpgKeyInfo key;
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof PushCertificateInfo) {
+ PushCertificateInfo pushCertificateInfo = (PushCertificateInfo) o;
+ return Objects.equals(certificate, pushCertificateInfo.certificate)
+ && Objects.equals(key, pushCertificateInfo.key);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(certificate, key);
+ }
}
diff --git a/java/com/google/gerrit/extensions/common/ReviewerUpdateInfo.java b/java/com/google/gerrit/extensions/common/ReviewerUpdateInfo.java
index eccdc64..37e1ceb 100644
--- a/java/com/google/gerrit/extensions/common/ReviewerUpdateInfo.java
+++ b/java/com/google/gerrit/extensions/common/ReviewerUpdateInfo.java
@@ -16,10 +16,28 @@
import com.google.gerrit.extensions.client.ReviewerState;
import java.sql.Timestamp;
+import java.util.Objects;
public class ReviewerUpdateInfo {
public Timestamp updated;
public AccountInfo updatedBy;
public AccountInfo reviewer;
public ReviewerState state;
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof ReviewerUpdateInfo) {
+ ReviewerUpdateInfo reviewerUpdateInfo = (ReviewerUpdateInfo) o;
+ return Objects.equals(updated, reviewerUpdateInfo.updated)
+ && Objects.equals(updatedBy, reviewerUpdateInfo.updatedBy)
+ && Objects.equals(reviewer, reviewerUpdateInfo.reviewer)
+ && Objects.equals(state, reviewerUpdateInfo.state);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(updated, updatedBy, reviewer, state);
+ }
}
diff --git a/java/com/google/gerrit/extensions/common/RevisionInfo.java b/java/com/google/gerrit/extensions/common/RevisionInfo.java
index f262901..ea61f31 100644
--- a/java/com/google/gerrit/extensions/common/RevisionInfo.java
+++ b/java/com/google/gerrit/extensions/common/RevisionInfo.java
@@ -17,6 +17,7 @@
import com.google.gerrit.extensions.client.ChangeKind;
import java.sql.Timestamp;
import java.util.Map;
+import java.util.Objects;
public class RevisionInfo {
// ActionJson#copy(List, RevisionInfo) must be adapted if new fields are added that are not
@@ -34,4 +35,43 @@
public String commitWithFooters;
public PushCertificateInfo pushCertificate;
public String description;
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof RevisionInfo) {
+ RevisionInfo revisionInfo = (RevisionInfo) o;
+ return isCurrent == revisionInfo.isCurrent
+ && Objects.equals(kind, revisionInfo.kind)
+ && _number == revisionInfo._number
+ && Objects.equals(created, revisionInfo.created)
+ && Objects.equals(uploader, revisionInfo.uploader)
+ && Objects.equals(ref, revisionInfo.ref)
+ && Objects.equals(fetch, revisionInfo.fetch)
+ && Objects.equals(commit, revisionInfo.commit)
+ && Objects.equals(files, revisionInfo.files)
+ && Objects.equals(actions, revisionInfo.actions)
+ && Objects.equals(commitWithFooters, revisionInfo.commitWithFooters)
+ && Objects.equals(pushCertificate, revisionInfo.pushCertificate)
+ && Objects.equals(description, revisionInfo.description);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ isCurrent,
+ kind,
+ _number,
+ created,
+ uploader,
+ ref,
+ fetch,
+ commit,
+ files,
+ actions,
+ commitWithFooters,
+ pushCertificate,
+ description);
+ }
}
diff --git a/java/com/google/gerrit/extensions/common/SubmitRequirementInfo.java b/java/com/google/gerrit/extensions/common/SubmitRequirementInfo.java
index 3483de5..a13e645 100644
--- a/java/com/google/gerrit/extensions/common/SubmitRequirementInfo.java
+++ b/java/com/google/gerrit/extensions/common/SubmitRequirementInfo.java
@@ -18,9 +18,9 @@
import java.util.Objects;
public class SubmitRequirementInfo {
- public final String status;
- public final String fallbackText;
- public final String type;
+ public String status;
+ public String fallbackText;
+ public String type;
public SubmitRequirementInfo(String status, String fallbackText, String type) {
this.status = status;
@@ -55,4 +55,6 @@
.add("type", type)
.toString();
}
+
+ protected SubmitRequirementInfo() {}
}
diff --git a/java/com/google/gerrit/extensions/common/TrackingIdInfo.java b/java/com/google/gerrit/extensions/common/TrackingIdInfo.java
index 0c5ed68..3d35e08 100644
--- a/java/com/google/gerrit/extensions/common/TrackingIdInfo.java
+++ b/java/com/google/gerrit/extensions/common/TrackingIdInfo.java
@@ -14,6 +14,8 @@
package com.google.gerrit.extensions.common;
+import java.util.Objects;
+
public class TrackingIdInfo {
public String system;
public String id;
@@ -22,4 +24,20 @@
this.system = system;
this.id = id;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof TrackingIdInfo) {
+ TrackingIdInfo trackingIdInfo = (TrackingIdInfo) o;
+ return Objects.equals(system, trackingIdInfo.system) && Objects.equals(id, trackingIdInfo.id);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(system, id);
+ }
+
+ protected TrackingIdInfo() {}
}
diff --git a/java/com/google/gerrit/extensions/common/VotingRangeInfo.java b/java/com/google/gerrit/extensions/common/VotingRangeInfo.java
index 5c35a49..2f7e9e4 100644
--- a/java/com/google/gerrit/extensions/common/VotingRangeInfo.java
+++ b/java/com/google/gerrit/extensions/common/VotingRangeInfo.java
@@ -14,6 +14,8 @@
package com.google.gerrit.extensions.common;
+import java.util.Objects;
+
public class VotingRangeInfo {
public int min;
public int max;
@@ -22,4 +24,18 @@
this.min = min;
this.max = max;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof VotingRangeInfo) {
+ VotingRangeInfo votingRangeInfo = (VotingRangeInfo) o;
+ return min == votingRangeInfo.min && max == votingRangeInfo.max;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(min, max);
+ }
}
diff --git a/java/com/google/gerrit/extensions/common/WebLinkInfo.java b/java/com/google/gerrit/extensions/common/WebLinkInfo.java
index 84fd970..ba12be0 100644
--- a/java/com/google/gerrit/extensions/common/WebLinkInfo.java
+++ b/java/com/google/gerrit/extensions/common/WebLinkInfo.java
@@ -64,4 +64,6 @@
+ target
+ "}";
}
+
+ protected WebLinkInfo() {}
}
diff --git a/java/com/google/gerrit/server/patch/AutoMerger.java b/java/com/google/gerrit/server/patch/AutoMerger.java
index fe915c5..ac37411 100644
--- a/java/com/google/gerrit/server/patch/AutoMerger.java
+++ b/java/com/google/gerrit/server/patch/AutoMerger.java
@@ -109,6 +109,7 @@
ActionType.GIT_UPDATE,
"createAutoMerge",
() -> createAutoMergeCommit(repo, rw, ins, merge, mergeStrategy))
+ .defaultTimeoutMultiplier(2)
.call();
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
diff --git a/java/com/google/gerrit/server/query/change/ChangeData.java b/java/com/google/gerrit/server/query/change/ChangeData.java
index 05ecc61..f047543 100644
--- a/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -109,6 +109,13 @@
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
+/**
+ * ChangeData provides lazily loaded interface to change metadata loaded from NoteDb. It can be
+ * constructed by loading from NoteDb, or calling setters. The latter happens when ChangeData is
+ * retrieved through the change index. This happens for Applications that are performance sensitive
+ * (eg. dashboard loads, git protocol negotiation) but can tolerate staleness. In that case, setting
+ * lazyLoad=false disables loading from NoteDb, so we don't accidentally enable a slow path.
+ */
public class ChangeData {
public static List<Change> asChanges(List<ChangeData> changeDatas) {
List<Change> result = new ArrayList<>(changeDatas.size());
@@ -600,6 +607,7 @@
author = c.getAuthorIdent();
committer = c.getCommitterIdent();
parentCount = c.getParentCount();
+ merge = parentCount > 0;
} catch (IOException e) {
throw new StorageException(
String.format(
@@ -961,7 +969,7 @@
return null;
}
}
- return parentCount > 1;
+ return merge;
}
public Set<Account.Id> editsByUser() {
diff --git a/java/com/google/gerrit/server/restapi/change/PostReview.java b/java/com/google/gerrit/server/restapi/change/PostReview.java
index 562bdf8..73b38b2 100644
--- a/java/com/google/gerrit/server/restapi/change/PostReview.java
+++ b/java/com/google/gerrit/server/restapi/change/PostReview.java
@@ -1228,9 +1228,10 @@
}
private boolean isReviewer(ChangeContext ctx) {
- ChangeData cd = changeDataFactory.create(ctx.getNotes());
- ReviewerSet reviewers = cd.reviewers();
- return reviewers.byState(REVIEWER).contains(ctx.getAccountId());
+ return approvalsUtil
+ .getReviewers(ctx.getNotes())
+ .byState(REVIEWER)
+ .contains(ctx.getAccountId());
}
private boolean updateLabels(ProjectState projectState, ChangeContext ctx)
diff --git a/java/com/google/gerrit/server/restapi/change/ReviewersUtil.java b/java/com/google/gerrit/server/restapi/change/ReviewersUtil.java
index 2a55e41..38be27e 100644
--- a/java/com/google/gerrit/server/restapi/change/ReviewersUtil.java
+++ b/java/com/google/gerrit/server/restapi/change/ReviewersUtil.java
@@ -51,6 +51,7 @@
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupMembers;
+import com.google.gerrit.server.account.ServiceUserClassifier;
import com.google.gerrit.server.change.ReviewerAdder;
import com.google.gerrit.server.index.account.AccountField;
import com.google.gerrit.server.index.account.AccountIndexCollection;
@@ -130,6 +131,7 @@
private final IndexConfig indexConfig;
private final AccountControl.Factory accountControlFactory;
private final Provider<CurrentUser> self;
+ private final ServiceUserClassifier serviceUserClassifier;
@Inject
ReviewersUtil(
@@ -143,7 +145,8 @@
AccountIndexCollection accountIndexes,
IndexConfig indexConfig,
AccountControl.Factory accountControlFactory,
- Provider<CurrentUser> self) {
+ Provider<CurrentUser> self,
+ ServiceUserClassifier serviceUserClassifier) {
this.accountLoaderFactory = accountLoaderFactory;
this.accountQueryBuilder = accountQueryBuilder;
this.accountIndexRewriter = accountIndexRewriter;
@@ -155,6 +158,7 @@
this.indexConfig = indexConfig;
this.accountControlFactory = accountControlFactory;
this.self = self;
+ this.serviceUserClassifier = serviceUserClassifier;
}
public interface VisibilityControl {
@@ -200,13 +204,17 @@
reviewerState, changeNotes, suggestReviewers, projectState, candidateList);
logger.atFine().log("Sorted recommendations: %s", sortedRecommendations);
- // Filter accounts by visibility and enforce limit
+ // Filter accounts by visibility, skip service users and enforce limit
List<Account.Id> filteredRecommendations = new ArrayList<>();
try (Timer0.Context ctx = metrics.filterVisibility.start()) {
for (Account.Id reviewer : sortedRecommendations) {
if (filteredRecommendations.size() >= limit) {
break;
}
+ if (suggestReviewers.isSkipServiceUsers()
+ && serviceUserClassifier.isServiceUser(reviewer)) {
+ continue;
+ }
// Check if change is visible to reviewer and if the current user can see reviewer
if (visibilityControl.isVisibleTo(reviewer)
&& accountControlFactory.get().canSee(reviewer)) {
diff --git a/java/com/google/gerrit/server/restapi/change/SuggestReviewers.java b/java/com/google/gerrit/server/restapi/change/SuggestReviewers.java
index e071c89..71ff493 100644
--- a/java/com/google/gerrit/server/restapi/change/SuggestReviewers.java
+++ b/java/com/google/gerrit/server/restapi/change/SuggestReviewers.java
@@ -31,6 +31,8 @@
private static final int DEFAULT_MAX_SUGGESTED = 10;
+ private static final boolean DEFAULT_SKIP_SERVICE_USERS = true;
+
protected final ReviewersUtil reviewersUtil;
private final boolean suggestAccounts;
@@ -39,6 +41,7 @@
protected int limit;
protected String query;
protected final int maxSuggestedReviewers;
+ protected boolean skipServiceUsers;
@Option(
name = "--limit",
@@ -78,6 +81,10 @@
return maxAllowedWithoutConfirmation;
}
+ public boolean isSkipServiceUsers() {
+ return skipServiceUsers;
+ }
+
@Inject
public SuggestReviewers(
AccountVisibility av, @GerritServerConfig Config cfg, ReviewersUtil reviewersUtil) {
@@ -100,6 +107,9 @@
ReviewerAdder.DEFAULT_MAX_REVIEWERS_WITHOUT_CHECK);
logger.atFine().log("AccountVisibility: %s", av.name());
+
+ this.skipServiceUsers =
+ cfg.getBoolean("suggest", "skipServiceUsers", DEFAULT_SKIP_SERVICE_USERS);
}
public static GerritConfigListener configListener() {
diff --git a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
index 5459ede..0a5692e 100644
--- a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
+++ b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
@@ -304,6 +304,7 @@
info.editGpgKeys =
toBoolean(enableSignedPush && config.getBoolean("gerrit", null, "editGpgKeys", true));
info.primaryWeblinkName = config.getString("gerrit", null, "primaryWeblinkName");
+ info.instanceId = config.getString("gerrit", null, "instanceId");
return info;
}
diff --git a/java/com/google/gerrit/server/submit/MergeOp.java b/java/com/google/gerrit/server/submit/MergeOp.java
index 871d8d2..4e732a4 100644
--- a/java/com/google/gerrit/server/submit/MergeOp.java
+++ b/java/com/google/gerrit/server/submit/MergeOp.java
@@ -549,8 +549,8 @@
.listener(retryTracker)
// Up to the entire submit operation is retried, including possibly many projects.
// Multiply the timeout by the number of projects we're actually attempting to
- // submit.
- .defaultTimeoutMultiplier(filteredNoteDbChangeSet.projects().size())
+ // submit. Times 2 to retry more persistently, to increase success rate.
+ .defaultTimeoutMultiplier(filteredNoteDbChangeSet.projects().size() * 2)
// By default, we only retry lock failures. Here it's better to also retry unexpected
// runtime exceptions.
.retryOn(t -> t instanceof RuntimeException)
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
index 888878f..ffde622 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
@@ -450,6 +450,23 @@
}
@Test
+ public void suggestNoServiceAccounts() throws Exception {
+ requestScopeOperations.setApiUser(user.id());
+ String changeIdReviewed = createChangeFromApi();
+ String changeId = createChangeFromApi();
+
+ String name = name("foo");
+ TestAccount foo = accountCreator.create(name);
+ reviewChange(changeIdReviewed, foo);
+
+ assertReviewers(suggestReviewers(changeId, name), ImmutableList.of(foo), ImmutableList.of());
+
+ groupOperations.group(serviceUsersUUID()).forUpdate().addMember(foo.id()).update();
+
+ assertReviewers(suggestReviewers(changeId, name), ImmutableList.of(), ImmutableList.of());
+ }
+
+ @Test
public void suggestNoExistingReviewers() throws Exception {
requestScopeOperations.setApiUser(user.id());
String changeId = createChangeFromApi();
@@ -608,6 +625,13 @@
return user(name, fullName, name);
}
+ private AccountGroup.UUID serviceUsersUUID() {
+ return groupCache
+ .get(AccountGroup.nameKey("Service Users"))
+ .orElseThrow(() -> new IllegalStateException("unable to find 'Service Users'"))
+ .getGroupUUID();
+ }
+
private void reviewChange(String changeId, TestAccount reviewer) throws RestApiException {
gApi.changes().id(changeId).addReviewer(reviewer.id().toString());
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java b/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
index 0a84db4..4738f64 100644
--- a/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
@@ -74,6 +74,7 @@
@GerritConfig(name = "gerrit.allProjects", value = "Root")
@GerritConfig(name = "gerrit.allUsers", value = "Users")
@GerritConfig(name = "gerrit.reportBugUrl", value = "https://example.com/report")
+ @GerritConfig(name = "gerrit.instanceId", value = "devops-instance")
// suggest
@GerritConfig(name = "suggest.from", value = "3")
@@ -116,6 +117,7 @@
assertThat(i.gerrit.allProjects).isEqualTo("Root");
assertThat(i.gerrit.allUsers).isEqualTo("Users");
assertThat(i.gerrit.reportBugUrl).isEqualTo("https://example.com/report");
+ assertThat(i.gerrit.instanceId).isEqualTo("devops-instance");
// plugin
assertThat(i.plugin.jsResourcePaths).isEmpty();
@@ -184,6 +186,7 @@
assertThat(i.gerrit.allProjects).isEqualTo(AllProjectsNameProvider.DEFAULT);
assertThat(i.gerrit.allUsers).isEqualTo(AllUsersNameProvider.DEFAULT);
assertThat(i.gerrit.reportBugUrl).isNull();
+ assertThat(i.gerrit.instanceId).isNull();
// plugin
assertThat(i.plugin.jsResourcePaths).isEmpty();
diff --git a/modules/jgit b/modules/jgit
index 4560bdf..9bfb0f3 160000
--- a/modules/jgit
+++ b/modules/jgit
@@ -1 +1 @@
-Subproject commit 4560bdf7e2e3c16a7c7bb3f2fcf067bb1eee26fb
+Subproject commit 9bfb0f3a4ec856dcbebb477a1ee8803a3c47c194
diff --git a/polygerrit-ui/app/api/checks.ts b/polygerrit-ui/app/api/checks.ts
index 143fbd1..799d1f7 100644
--- a/polygerrit-ui/app/api/checks.ts
+++ b/polygerrit-ui/app/api/checks.ts
@@ -43,6 +43,12 @@
fetchPollingIntervalSeconds: number;
}
+export interface ChangeData {
+ changeNumber: number;
+ patchsetNumber: number;
+ repo: string;
+}
+
export interface ChecksProvider {
/**
* Gerrit calls this method when ...
@@ -51,7 +57,7 @@
* - ... while the tab is visible in a regular polling interval, see
* ChecksApiConfig.
*/
- fetch(change: number, patchset: number): Promise<FetchResponse>;
+ fetch(change: ChangeData): Promise<FetchResponse>;
}
export interface FetchResponse {
@@ -224,10 +230,21 @@
export type ActionCallback = (
change: number,
patchset: number,
+ /**
+ * Identical to 'attempt' property of CheckRun. Not set for top-level
+ * actions.
+ */
attempt: number | undefined,
+ /**
+ * Identical to 'externalId' property of CheckRun. Not set for top-level
+ * actions.
+ */
externalId: string | undefined,
- /** Identical to 'checkName' property of CheckRun. */
- checkName: string,
+ /**
+ * Identical to 'checkName' property of CheckRun. Not set for top-level
+ * actions.
+ */
+ checkName: string | undefined,
/** Identical to 'name' property of Action entity. */
actionName: string
) => Promise<ActionResult>;
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.ts b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.ts
index e77a5e8..4fa84eb 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.ts
+++ b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.ts
@@ -95,7 +95,7 @@
@property({type: String})
_filter = '';
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
/** @override */
attached() {
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
index 8a3e47f..f2b4c89 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
+++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
@@ -99,7 +99,7 @@
return htmlTemplate;
}
- private _account?: AccountDetailInfo;
+ private account?: AccountDetailInfo;
@property({type: Object})
params?: AdminViewParams;
@@ -173,7 +173,7 @@
@property({type: Boolean})
_showPluginList?: boolean;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
private readonly jsAPI = appContext.jsApiService;
@@ -189,7 +189,7 @@
getPluginLoader().awaitPluginsLoaded(),
];
return Promise.all(promises).then(result => {
- this._account = result[0];
+ this.account = result[0];
let options: AdminNavLinksOption | undefined = undefined;
if (this._repoName) {
options = {repoName: this._repoName};
@@ -204,7 +204,7 @@
}
return getAdminLinks(
- this._account,
+ this.account,
() =>
this.restApiService.getAccountCapabilities().then(capabilities => {
if (!capabilities) {
@@ -400,7 +400,7 @@
}
return '';
}
- // TODO(TS): The following condtion seems always false, because params
+ // TODO(TS): The following condition seems always false, because params
// never has detailType property. Remove it.
if (
((params as unknown) as AdminSubsectionLink).detailType &&
diff --git a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.ts
index b68f720..e68f6c9 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.ts
@@ -44,7 +44,7 @@
@property({type: Boolean})
_groupCreated = false;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
_computeGroupUrl(groupId: string) {
return getBaseUrl() + '/admin/groups/' + encodeURL(groupId, true);
diff --git a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.ts
index d50d7c5..6334670 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.ts
@@ -68,7 +68,7 @@
this.hasNewItemName = !!name;
}
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
handleCreateItem() {
if (!this.repoName) {
diff --git a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
index c9fd241..f708485 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
@@ -70,7 +70,7 @@
@property({type: Object})
_queryGroups: AutocompleteQuery;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
constructor() {
super();
diff --git a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.ts b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.ts
index bc4750f..201b340 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.ts
+++ b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.ts
@@ -55,7 +55,7 @@
@property({type: Boolean})
_loading = true;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
/** @override */
attached() {
diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.ts b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.ts
index 451139c..54f58c2 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.ts
+++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.ts
@@ -117,7 +117,7 @@
_itemId?: AccountId | GroupId;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
constructor() {
super();
diff --git a/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts b/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts
index 6f00445..84daef8 100644
--- a/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts
+++ b/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts
@@ -126,7 +126,7 @@
@property({type: Boolean})
_isAdmin = false;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
constructor() {
super();
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts
index 5702bfb..85ba052 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts
@@ -140,7 +140,7 @@
@property({type: Boolean})
_originalExclusiveValue?: boolean;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
constructor() {
super();
diff --git a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.ts b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.ts
index fc1ceee..f5e9a92 100644
--- a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.ts
+++ b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.ts
@@ -77,7 +77,7 @@
@property({type: String})
_filter = '';
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
/** @override */
attached() {
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 935d091..56c5733 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
@@ -118,9 +118,9 @@
@property({type: Boolean})
_loading = true;
- private _originalInheritsFrom?: ProjectInfo | null;
+ private originalInheritsFrom?: ProjectInfo | null;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
constructor() {
super();
@@ -173,7 +173,7 @@
...res.inherits_from,
}
: null;
- this._originalInheritsFrom = res.inherits_from
+ this.originalInheritsFrom = res.inherits_from
? {
...res.inherits_from,
}
@@ -306,7 +306,7 @@
}
// Restore inheritFrom.
if (this._inheritsFrom) {
- this._inheritsFrom = {...this._originalInheritsFrom};
+ this._inheritsFrom = {...this.originalInheritsFrom};
this._inheritFromFilter =
'name' in this._inheritsFrom ? this._inheritsFrom.name : undefined;
}
@@ -446,8 +446,8 @@
remove: {},
};
- const originalInheritsFromId = this._originalInheritsFrom
- ? singleDecodeURL(this._originalInheritsFrom.id)
+ const originalInheritsFromId = this.originalInheritsFrom
+ ? singleDecodeURL(this.originalInheritsFrom.id)
: null;
// TODO(TS): this._inheritsFrom as ProjectInfo might be a mistake.
// _inheritsFrom can be {}
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.ts b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.ts
index 14cf234..f209729 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.ts
@@ -91,7 +91,7 @@
@property({type: Boolean})
_runningGC = false;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
/** @override */
attached() {
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.ts b/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.ts
index 5f6cd29..7b3c7fb 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.ts
@@ -50,7 +50,7 @@
@property({type: Array})
_dashboards?: DashboardRef[];
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
_repoChanged(repo?: RepoName) {
this._loading = true;
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.ts b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.ts
index c1c8475..d6aa0e6 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.ts
@@ -88,7 +88,7 @@
return this.computeShownItems(this._repos);
}
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
/** @override */
attached() {
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts
index bcc6039..b6881ff 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts
@@ -141,7 +141,7 @@
@property({type: Array})
weblinks: WebLinkInfo[] = [];
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
/** @override */
attached() {
diff --git a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.js b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.js
index b0065d9..9cc6357 100644
--- a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.js
+++ b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.js
@@ -192,7 +192,7 @@
};
element.section = 'refs/*';
- // Typically called on ready since elements will have properies defined
+ // Typically called on ready since elements will have properties defined
// by the parent element.
element._setupValues(element.rule);
flush();
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
index 441d514..42741fa 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
@@ -111,7 +111,7 @@
@property({type: String})
_repo: string | null = null;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
/** @override */
created() {
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
index f36df84..f26cd46 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
@@ -146,7 +146,7 @@
flagsService = appContext.flagsService;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
keyboardShortcuts() {
return {
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
index 841ee6e..816c8ef 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
@@ -58,7 +58,7 @@
import {firePageError, fireTitleChange} from '../../../utils/event-util';
import {GerritView} from '../../../services/router/router-model';
-const PROJECT_PLACEHOLDER_PATTERN = /\$\{project\}/g;
+const PROJECT_PLACEHOLDER_PATTERN = /\${project}/g;
const RELOAD_DASHBOARD_INTERVAL_MS = 10 * 1000;
export interface GrDashboardView {
@@ -121,7 +121,7 @@
private reporting = appContext.reportingService;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
private lastVisibleTimestampMs = 0;
diff --git a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.ts b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.ts
index 10f65a5..cfee0cd 100644
--- a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.ts
@@ -54,7 +54,7 @@
@property({type: String})
_status = '';
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
_accountChanged(userId?: AccountId) {
if (!userId) {
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 89ca4ef..87b09c7 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
@@ -553,7 +553,7 @@
@property({type: Object})
_config?: ServerInfo;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
/** @override */
created() {
@@ -2068,10 +2068,10 @@
*
*/
_waitForChangeReachable(changeNum: NumericChangeId) {
- let attempsRemaining = AWAIT_CHANGE_ATTEMPTS;
+ let attemptsRemaining = AWAIT_CHANGE_ATTEMPTS;
return new Promise(resolve => {
const check = () => {
- attempsRemaining--;
+ attemptsRemaining--;
// Pass a no-op error handler to avoid the "not found" error toast.
this.restApiService
.getChange(changeNum, () => {})
@@ -2082,7 +2082,7 @@
return;
}
- if (attempsRemaining) {
+ if (attemptsRemaining) {
this.async(check, AWAIT_CHANGE_TIMEOUT_MS);
} else {
resolve(false);
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 6c9a27d..fbb70b7 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
@@ -2110,7 +2110,7 @@
element = basicFixture.instantiate();
// getChangeRevisionActions is not called without
- // set the following properies
+ // set the following properties
element.change = {};
element.changeNum = '42';
element.latestPatchNum = '2';
diff --git a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_html.ts b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_html.ts
index f172ccc..e02b337 100644
--- a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_html.ts
@@ -99,6 +99,9 @@
padding-left: 0;
}
</style>
+ <template is="dom-if" if="[[_isNewChangeSummaryUiEnabled]]">
+ <h3 class="metadata-title">Submit requirements</h3>
+ </template>
<template is="dom-repeat" items="[[_requirements]]">
<gr-endpoint-decorator
class="submit-requirement-endpoints"
@@ -126,9 +129,6 @@
</div>
</gr-endpoint-decorator>
</template>
- <template is="dom-if" if="[[_isNewChangeSummaryUiEnabled]]">
- <h3 class="metadata-title">Submit requirements</h3>
- </template>
<template is="dom-repeat" items="[[_requiredLabels]]">
<section>
<div class="title">
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 8f74f76..3d7646f 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
@@ -108,6 +108,9 @@
QuickLabelInfo,
ApprovalInfo,
ElementPropertyDeepChange,
+ ChangeId,
+ RelatedChangeAndCommitInfo,
+ RelatedChangesInfo,
} from '../../../types/common';
import {DiffPreferencesInfo} from '../../../types/diff';
import {GrReplyDialog, FocusTarget} from '../gr-reply-dialog/gr-reply-dialog';
@@ -2293,7 +2296,27 @@
const relatedChangesLoaded = coreDataPromise.then(() => {
this.getRelatedChangesList()?.reload();
if (this._isNewChangeSummaryUiEnabled) {
- this.getRelatedChangesListExperimental()?.reload();
+ let relatedChangesPromise:
+ | Promise<RelatedChangesInfo | undefined>
+ | undefined;
+ const patchNum = this._computeLatestPatchNum(this._allPatchSets);
+ if (this._change && patchNum) {
+ relatedChangesPromise = this.restApiService
+ .getRelatedChanges(this._change._number, patchNum)
+ .then(response => {
+ if (this._change && response) {
+ this.hasParent = this._calculateHasParent(
+ this._change.change_id,
+ response.changes
+ );
+ }
+ return response;
+ });
+ }
+ // TODO: use returned Promise
+ this.getRelatedChangesListExperimental()?.reload(
+ relatedChangesPromise
+ );
}
});
allDataPromises.push(relatedChangesLoaded);
@@ -2310,6 +2333,21 @@
}
/**
+ * Determines whether or not the given change has a parent change. If there
+ * is a relation chain, and the change id is not the last item of the
+ * relation chain, there is a parent.
+ */
+ _calculateHasParent(
+ currentChangeId: ChangeId,
+ relatedChanges: RelatedChangeAndCommitInfo[]
+ ) {
+ return (
+ relatedChanges.length > 0 &&
+ relatedChanges[relatedChanges.length - 1].change_id !== currentChangeId
+ );
+ }
+
+ /**
* Kicks off requests for resources that rely on the patch range
* (`this._patchRange`) being defined.
*/
@@ -2780,7 +2818,7 @@
/**
* Wrapper for using in the element template and computed properties
*/
- _computeLatestPatchNum(allPatchSets: PatchSet[]) {
+ _computeLatestPatchNum(allPatchSets?: PatchSet[]) {
return computeLatestPatchNum(allPatchSets);
}
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
index 10cffba..225e3e9 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
@@ -144,7 +144,7 @@
private selectedChangeIds = new Set<ChangeInfoId>();
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
constructor() {
super();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
index ff61de9..5e95e66 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
@@ -67,7 +67,7 @@
};
}
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
constructor() {
super();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts
index 9dcd849..b2b6e61 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts
@@ -89,7 +89,7 @@
@property({type: Array})
_recentChanges?: RebaseChange[];
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
constructor() {
super();
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts
index a5c0624..c2947a6 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts
@@ -803,7 +803,7 @@
}
/**
- * Handle all events from the file list dom-repeat so event handleers don't
+ * Handle all events from the file list dom-repeat so event handlers don't
* have to get registered for potentially very long lists.
*/
_handleFileListClick(e: MouseEvent) {
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js
index 285b73f..80d8729 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js
@@ -1244,7 +1244,7 @@
// are no deletions.
assert.equal(element._computeBarAdditionWidth(file, stats), 30);
- // If there are no insetions, there is no width.
+ // If there are no insertions, there is no width.
stats.maxInserted = 0;
assert.equal(element._computeBarAdditionWidth(file, stats), 0);
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.ts b/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
index 2fe409a..f913459 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
@@ -54,7 +54,7 @@
} from '../../../utils/patch-set-util';
import {isServiceUser} from '../../../utils/account-util';
-const PATCH_SET_PREFIX_PATTERN = /^(?:Uploaded\s*)?(?:P|p)atch (?:S|s)et \d+:\s*(.*)/;
+const PATCH_SET_PREFIX_PATTERN = /^(?:Uploaded\s*)?[Pp]atch [Ss]et \d+:\s*(.*)/;
const LABEL_TITLE_SCORE_PATTERN = /^(-?)([A-Za-z0-9-]+?)([+-]\d+)?[.]?$/;
const UPLOADED_NEW_PATCHSET_PATTERN = /Uploaded patch set (\d+)./;
const MERGED_PATCHSET_PATTERN = /(\d+) is the latest approved patch-set/;
@@ -484,7 +484,7 @@
_handleAnchorClick(e: Event) {
e.preventDefault();
// The element which triggers _handleAnchorClick is rendered only if
- // message.id defined: the elemenet is wrapped in dom-if if="[[message.id]]"
+ // message.id defined: the element is wrapped in dom-if if="[[message.id]]"
const detail: MessageAnchorTapDetail = {
id: this.message!.id,
};
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts
index 9877a95..bc3f167 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts
@@ -118,7 +118,7 @@
/**
* If messages have the same tag, then that influences grouping and whether
- * a message is initally hidden or not, see isImportant(). So we are applying
+ * a message is initially hidden or not, see isImportant(). So we are applying
* some "magic" rules here in order to hide exactly the right messages.
*
* 1. If a message does not have a tag, but is associated with robot comments,
@@ -263,7 +263,7 @@
_combinedMessages: CombinedMessage[] = [];
@property({type: Object, computed: '_computeLabelExtremes(labels.*)'})
- _labelExtremes: {[lableName: string]: VotingRangeInfo} = {};
+ _labelExtremes: {[labelName: string]: VotingRangeInfo} = {};
private readonly reporting = appContext.reportingService;
@@ -466,7 +466,7 @@
LabelNameToInfoMap
>
) {
- const extremes: {[lableName: string]: VotingRangeInfo} = {};
+ const extremes: {[labelName: string]: VotingRangeInfo} = {};
const labels = labelRecord.base;
if (!labels) {
return extremes;
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 fbbef12..e921979 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
@@ -16,9 +16,12 @@
*/
import {html, nothing} from 'lit-html';
import './gr-related-change';
+import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
+import '../../plugins/gr-endpoint-param/gr-endpoint-param';
+import '../../plugins/gr-endpoint-slot/gr-endpoint-slot';
import {classMap} from 'lit-html/directives/class-map';
import {GrLitElement} from '../../lit/gr-lit-element';
-import {customElement, property, css} from 'lit-element';
+import {customElement, property, css, internalProperty} from 'lit-element';
import {sharedStyles} from '../../../styles/shared-styles';
import {
SubmittedTogetherInfo,
@@ -32,7 +35,11 @@
import {ParsedChangeInfo} from '../../../types/types';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {pluralize} from '../../../utils/string-util';
-import {getRevisionKey, isChangeInfo} from '../../../utils/change-util';
+import {
+ changeIsOpen,
+ getRevisionKey,
+ isChangeInfo,
+} from '../../../utils/change-util';
/** What is the maximum number of shown changes in collapsed list? */
const MAX_CHANGES_WHEN_COLLAPSED = 3;
@@ -46,13 +53,25 @@
patchNum?: PatchSetNum;
@property()
- _submittedTogether?: SubmittedTogetherInfo = {
+ mergeable?: boolean;
+
+ @internalProperty()
+ submittedTogether?: SubmittedTogetherInfo = {
changes: [],
non_visible_changes: 0,
};
- @property()
- _relatedResponse?: RelatedChangesInfo = {changes: []};
+ @internalProperty()
+ relatedChanges: RelatedChangeAndCommitInfo[] = [];
+
+ @internalProperty()
+ conflictingChanges: ChangeInfo[] = [];
+
+ @internalProperty()
+ cherryPickChanges: ChangeInfo[] = [];
+
+ @internalProperty()
+ sameTopicChanges: ChangeInfo[] = [];
private readonly restApiService = appContext.restApiService;
@@ -62,6 +81,7 @@
css`
.note {
color: var(--error-text-color);
+ margin-left: 1.2em;
}
section {
margin-bottom: var(--spacing-m);
@@ -71,27 +91,26 @@
}
render() {
- const relatedChanges = this._relatedResponse?.changes ?? [];
let showWhenCollapsedPredicate = this.showWhenCollapsedPredicateFactory(
- relatedChanges.length,
- relatedChanges.findIndex(relatedChange =>
+ this.relatedChanges.length,
+ this.relatedChanges.findIndex(relatedChange =>
this._changesEqual(relatedChange, this.change)
)
);
const connectedRevisions = this._computeConnectedRevisions(
this.change,
this.patchNum,
- relatedChanges
+ this.relatedChanges
);
const relatedChangeSection = html` <section
class="relatedChanges"
- ?hidden=${!relatedChanges.length}
+ ?hidden=${!this.relatedChanges.length}
>
<gr-related-collapse
title="Relation chain"
- .length=${relatedChanges.length}
+ .length=${this.relatedChanges.length}
>
- ${relatedChanges.map(
+ ${this.relatedChanges.map(
(change, index) =>
html`<gr-related-change
class="${classMap({
@@ -114,9 +133,9 @@
</gr-related-collapse>
</section>`;
- const submittedTogetherChanges = this._submittedTogether?.changes ?? [];
+ const submittedTogetherChanges = this.submittedTogether?.changes ?? [];
const countNonVisibleChanges =
- this._submittedTogether?.non_visible_changes ?? 0;
+ this.submittedTogether?.non_visible_changes ?? 0;
showWhenCollapsedPredicate = this.showWhenCollapsedPredicateFactory(
submittedTogetherChanges.length,
submittedTogetherChanges.findIndex(relatedChange =>
@@ -126,7 +145,7 @@
const submittedTogetherSection = html`<section
id="submittedTogether"
?hidden=${!submittedTogetherChanges?.length &&
- !this._submittedTogether?.non_visible_changes}
+ !this.submittedTogether?.non_visible_changes}
>
<gr-related-collapse
title="Submitted together"
@@ -155,11 +174,106 @@
</div>
</section>`;
- return html`${relatedChangeSection}${submittedTogetherSection}`;
+ showWhenCollapsedPredicate = this.showWhenCollapsedPredicateFactory(
+ this.sameTopicChanges.length,
+ -1
+ );
+ const sameTopicSection = html`<section
+ id="sameTopic"
+ ?hidden=${!this.sameTopicChanges?.length}
+ >
+ <gr-related-collapse
+ title="Same topic"
+ .length=${this.sameTopicChanges.length}
+ >
+ ${this.sameTopicChanges.map(
+ (change, index) =>
+ html`<gr-related-change
+ class="${classMap({
+ ['show-when-collapsed']: showWhenCollapsedPredicate(index),
+ })}"
+ .change="${change}"
+ .href="${GerritNav.getUrlForChangeById(
+ change._number,
+ change.project
+ )}"
+ >${change.project}: ${change.branch}:
+ ${change.subject}</gr-related-change
+ >`
+ )}
+ </gr-related-collapse>
+ </section>`;
+
+ showWhenCollapsedPredicate = this.showWhenCollapsedPredicateFactory(
+ this.conflictingChanges.length,
+ -1
+ );
+ const mergeConflictsSection = html`<section
+ id="mergeConflicts"
+ ?hidden=${!this.conflictingChanges?.length}
+ >
+ <gr-related-collapse
+ title="Merge conflicts"
+ .length=${this.conflictingChanges.length}
+ >
+ ${this.conflictingChanges.map(
+ (change, index) =>
+ html`<gr-related-change
+ class="${classMap({
+ ['show-when-collapsed']: showWhenCollapsedPredicate(index),
+ })}"
+ .change="${change}"
+ .href="${GerritNav.getUrlForChangeById(
+ change._number,
+ change.project
+ )}"
+ >${change.subject}</gr-related-change
+ >`
+ )}
+ </gr-related-collapse>
+ </section>`;
+
+ showWhenCollapsedPredicate = this.showWhenCollapsedPredicateFactory(
+ this.cherryPickChanges.length,
+ -1
+ );
+ const cherryPicksSection = html`<section
+ id="cherryPicks"
+ ?hidden=${!this.cherryPickChanges?.length}
+ >
+ <gr-related-collapse
+ title="Cherry picks"
+ .length=${this.cherryPickChanges.length}
+ >
+ ${this.cherryPickChanges.map(
+ (change, index) =>
+ html`<gr-related-change
+ class="${classMap({
+ ['show-when-collapsed']: showWhenCollapsedPredicate(index),
+ })}"
+ .change="${change}"
+ .href="${GerritNav.getUrlForChangeById(
+ change._number,
+ change.project
+ )}"
+ >${change.branch}: ${change.subject}</gr-related-change
+ >`
+ )}
+ </gr-related-collapse>
+ </section>`;
+
+ return html`<gr-endpoint-decorator name="related-changes-section">
+ <gr-endpoint-param name="change" value="[[change]]"></gr-endpoint-param>
+ <gr-endpoint-slot name="top"></gr-endpoint-slot>
+ ${relatedChangeSection} ${submittedTogetherSection} ${sameTopicSection}
+ ${mergeConflictsSection} ${cherryPicksSection}
+ <gr-endpoint-slot name="bottom"></gr-endpoint-slot>
+ </gr-endpoint-decorator>`;
}
showWhenCollapsedPredicateFactory(length: number, highlightIndex: number) {
return (index: number) => {
+ if (highlightIndex === -1) return index < MAX_CHANGES_WHEN_COLLAPSED;
if (highlightIndex === 0) return index <= MAX_CHANGES_WHEN_COLLAPSED - 1;
if (highlightIndex === length - 1)
return index >= length - MAX_CHANGES_WHEN_COLLAPSED;
@@ -170,25 +284,65 @@
};
}
- reload() {
- if (!this.change) return Promise.reject(new Error('change missing'));
+ reload(getRelatedChanges?: Promise<RelatedChangesInfo | undefined>) {
+ const change = this.change;
+ if (!change) return Promise.reject(new Error('change missing'));
if (!this.patchNum) return Promise.reject(new Error('patchNum missing'));
+ if (!getRelatedChanges) {
+ getRelatedChanges = this.restApiService.getRelatedChanges(
+ change._number,
+ this.patchNum
+ );
+ }
const promises: Array<Promise<void>> = [
+ getRelatedChanges.then(response => {
+ if (!response) {
+ throw new Error('getRelatedChanges returned undefined response');
+ }
+ this.relatedChanges = response?.changes ?? [];
+ }),
this.restApiService
- .getRelatedChanges(this.change._number, this.patchNum)
+ .getChangesSubmittedTogether(change._number)
.then(response => {
- if (!response) {
- throw new Error('getRelatedChanges returned undefined response');
- }
- this._relatedResponse = response;
+ this.submittedTogether = response;
}),
this.restApiService
- .getChangesSubmittedTogether(this.change._number)
+ .getChangeCherryPicks(change.project, change.change_id, change._number)
.then(response => {
- this._submittedTogether = response;
+ this.cherryPickChanges = response || [];
}),
];
+ // Get conflicts if change is open and is mergeable.
+ // Mergeable is output of restApiServict.getMergeable from gr-change-view
+ if (changeIsOpen(change) && this.mergeable) {
+ promises.push(
+ this.restApiService
+ .getChangeConflicts(change._number)
+ .then(response => {
+ this.conflictingChanges = response ?? [];
+ })
+ );
+ }
+ if (change.topic) {
+ const changeTopic = change.topic;
+ promises.push(
+ this.restApiService.getConfig().then(config => {
+ if (config && !config.change.submit_whole_topic) {
+ return this.restApiService
+ .getChangesWithSameTopic(changeTopic, change._number)
+ .then(response => {
+ if (changeTopic === this.change?.topic) {
+ this.sameTopicChanges = response ?? [];
+ }
+ });
+ }
+ this.sameTopicChanges = [];
+ return Promise.resolve();
+ })
+ );
+ }
+
return Promise.all(promises);
}
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.ts b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.ts
index 8cb0638..9941fa9 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.ts
@@ -193,6 +193,7 @@
href$="[[_computeChangeURL(change._number, change.project)]]"
class$="[[_computeLinkClass(change)]]"
title$="[[change.subject]]"
+ on-click="_reportClick"
>
[[change.subject]]
</a>
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
index 705a402..a8e89b6 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
@@ -784,7 +784,7 @@
}
_handle400Error(r?: Response | null) {
- if (!r) throw new Error('Reponse is empty.');
+ if (!r) throw new Error('Response is empty.');
let response: Response = r;
// A call to _saveReview could fail with a server error if erroneous
// reviewers were requested. This is signalled with a 400 Bad Request
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js
index 6682bfb..0575239 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js
@@ -1276,7 +1276,7 @@
'Send and Start review');
});
- test('_handle400Error reviewrs and CCs', done => {
+ test('_handle400Error reviewers and CCs', done => {
const error1 = 'error 1';
const error2 = 'error 2';
const error3 = 'error 3';
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-results.ts b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
index 007af97..e448374 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-results.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
@@ -15,7 +15,14 @@
* limitations under the License.
*/
import {html} from 'lit-html';
-import {css, customElement, property, PropertyValues} from 'lit-element';
+import {
+ css,
+ customElement,
+ internalProperty,
+ property,
+ PropertyValues,
+ query,
+} from 'lit-element';
import {GrLitElement} from '../lit/gr-lit-element';
import {Category, CheckRun, Link, RunStatus, Tag} from '../../api/checks';
import {sharedStyles} from '../../styles/shared-styles';
@@ -26,6 +33,8 @@
iconForCategory,
isRunning,
} from '../../services/checks/checks-util';
+import {assertIsDefined} from '../../utils/common-util';
+import {whenVisible} from '../../utils/dom-util';
@customElement('gr-result-row')
class GrResultRow extends GrLitElement {
@@ -38,6 +47,9 @@
@property({type: Boolean, reflect: true})
isExpandable = false;
+ @property()
+ shouldRender = false;
+
static get styles() {
return [
sharedStyles,
@@ -81,7 +93,7 @@
}
td .summary-cell {
display: flex;
- max-width: calc(100vw - 579px);
+ max-width: calc(100vw - 700px);
}
td .summary-cell .summary {
font-weight: var(--font-weight-bold);
@@ -126,8 +138,26 @@
super.update(changedProperties);
}
+ firstUpdated() {
+ const loading = this.shadowRoot?.querySelector('.container');
+ assertIsDefined(loading, '"Loading" element');
+ whenVisible(loading, () => this.setAttribute('shouldRender', 'true'), 200);
+ }
+
render() {
if (!this.result) return '';
+ if (!this.shouldRender) {
+ return html`
+ <tr class="container">
+ <td class="iconCol"></td>
+ <td class="nameCol">
+ <div><span class="loading">Loading...</span></div>
+ </td>
+ <td class="summaryCol"></td>
+ <td class="expanderCol"></td>
+ </tr>
+ `;
+ }
return html`
<tr class="container" @click="${this.toggleExpanded}">
<td class="iconCol">
@@ -237,15 +267,31 @@
render() {
if (!this.result) return '';
return html`
- <div class="message">
- ${this.result.message}
- </div>
+ <gr-endpoint-decorator name="check-result-expanded">
+ <gr-endpoint-param
+ name="run"
+ value="${this.result}"
+ ></gr-endpoint-param>
+ <gr-endpoint-param
+ name="result"
+ value="${this.result}"
+ ></gr-endpoint-param>
+ <div class="message">
+ ${this.result.message}
+ </div>
+ </gr-endpoint-decorator>
`;
}
}
@customElement('gr-checks-results')
export class GrChecksResults extends GrLitElement {
+ @query('#filterInput')
+ filterInput?: HTMLInputElement;
+
+ @internalProperty()
+ filterRegExp = new RegExp('');
+
@property()
runs: CheckRun[] = [];
@@ -257,6 +303,11 @@
display: block;
padding: var(--spacing-xl);
}
+ input#filterInput {
+ margin-top: var(--spacing-s);
+ padding: var(--spacing-s) var(--spacing-m);
+ min-width: 400px;
+ }
.categoryHeader {
margin-top: var(--spacing-l);
margin-left: var(--spacing-l);
@@ -300,12 +351,30 @@
render() {
return html`
<div><h2 class="heading-2">Results</h2></div>
- ${this.renderNoCompleted()} ${this.renderSection(Category.ERROR)}
+ ${this.renderFilter()} ${this.renderNoCompleted()}
+ ${this.renderSection(Category.ERROR)}
${this.renderSection(Category.WARNING)}
${this.renderSection(Category.INFO)} ${this.renderSuccess()}
`;
}
+ renderFilter() {
+ if (this.runs.length === 0) return;
+ return html`
+ <input
+ id="filterInput"
+ type="text"
+ placeholder="Filter results by regular expression"
+ @input="${this.onInput}"
+ />
+ `;
+ }
+
+ onInput() {
+ assertIsDefined(this.filterInput, 'filter <input> element');
+ this.filterRegExp = new RegExp(this.filterInput.value, 'i');
+ }
+
renderNoCompleted() {
if (this.runs.some(hasCompleted)) return;
let text = 'No results';
@@ -348,6 +417,11 @@
renderRun(category: Category, run: CheckRun) {
return html`${run.results
?.filter(result => result.category === category)
+ .filter(
+ result =>
+ this.filterRegExp.test(run.checkName) ||
+ this.filterRegExp.test(result.summary)
+ )
.map(
result =>
html`<gr-result-row .result="${{...run, ...result}}"></gr-result-row>`
@@ -355,7 +429,9 @@
}
renderSuccess() {
- const runs = this.runs.filter(hasCompletedWithoutResults);
+ const runs = this.runs
+ .filter(hasCompletedWithoutResults)
+ .filter(r => this.filterRegExp.test(r.checkName));
if (runs.length === 0) return;
return html`
<h3 class="categoryHeader heading-3">
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
index 4a34700..f8584bc 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
@@ -16,12 +16,19 @@
*/
import {html} from 'lit-html';
import {classMap} from 'lit-html/directives/class-map';
-import {css, customElement, property} from 'lit-element';
+import {
+ css,
+ customElement,
+ internalProperty,
+ property,
+ query,
+} from 'lit-element';
import {GrLitElement} from '../lit/gr-lit-element';
import {Action, CheckRun, RunStatus} from '../../api/checks';
import {sharedStyles} from '../../styles/shared-styles';
import {
compareByWorstCategory,
+ fireActionTriggered,
iconForRun,
primaryRunAction,
} from '../../services/checks/checks-util';
@@ -34,15 +41,14 @@
fakeRun4,
updateStateSetResults,
} from '../../services/checks/checks-model';
+import {assertIsDefined, toggleSetMembership} from '../../utils/common-util';
+import {whenVisible} from '../../utils/dom-util';
-/* The RunSelectedEvent is only used locally to communicate from <gr-checks-run>
- to its <gr-checks-runs> parent. */
-
-interface RunSelectedEventDetail {
+export interface RunSelectedEventDetail {
checkName: string;
}
-type RunSelectedEvent = CustomEvent<RunSelectedEventDetail>;
+export type RunSelectedEvent = CustomEvent<RunSelectedEventDetail>;
declare global {
interface HTMLElementEventMap {
@@ -54,33 +60,6 @@
target.dispatchEvent(
new CustomEvent('run-selected', {
detail: {checkName},
- composed: false,
- bubbles: false,
- })
- );
-}
-
-export interface ActionTriggeredEventDetail {
- action: Action;
- run: CheckRun;
-}
-
-export type ActionTriggeredEvent = CustomEvent<ActionTriggeredEventDetail>;
-
-declare global {
- interface HTMLElementEventMap {
- 'action-triggered': ActionTriggeredEvent;
- }
-}
-
-function fireActionTriggered(
- target: EventTarget,
- action: Action,
- run: CheckRun
-) {
- target.dispatchEvent(
- new CustomEvent('action-triggered', {
- detail: {action, run},
composed: true,
bubbles: true,
})
@@ -106,6 +85,11 @@
margin-top: var(--spacing-s);
cursor: pointer;
}
+ .left {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
.name {
font-weight: var(--font-weight-bold);
}
@@ -127,6 +111,9 @@
.chip.placeholder {
border-left: var(--thick-border) solid var(--border-color);
}
+ .chip.placeholder iron-icon {
+ display: none;
+ }
.chip.error iron-icon {
color: var(--error-foreground);
}
@@ -145,9 +132,21 @@
background-color: var(--selected-background);
padding-left: calc(var(--spacing-m) + var(--thick-border) - 1px);
}
+ div.chip.deselected {
+ border: 1px solid var(--gray-foreground);
+ background-color: transparent;
+ padding-left: calc(var(--spacing-m) + var(--thick-border) - 1px);
+ }
div.chip.selected iron-icon {
color: var(--selected-foreground);
}
+ div.chip.deselected iron-icon {
+ color: var(--gray-foreground);
+ }
+ .chip.selected gr-button.action,
+ .chip.deselected gr-button.action {
+ display: none;
+ }
gr-button.action {
--padding: var(--spacing-xs) var(--spacing-m);
/* The button should fit into the 20px line-height. The negative
@@ -160,15 +159,40 @@
];
}
+ @query('.chip')
+ chipElement?: HTMLElement;
+
@property()
run!: CheckRun;
@property()
selected = false;
+ @property()
+ deselected = false;
+
+ @property()
+ shouldRender = false;
+
+ firstUpdated() {
+ assertIsDefined(this.chipElement, 'chip element');
+ whenVisible(
+ this.chipElement,
+ () => this.setAttribute('shouldRender', 'true'),
+ 200
+ );
+ }
+
render() {
- const icon = this.selected ? 'check-circle' : iconForRun(this.run);
- const classes = {chip: true, [icon]: true, selected: this.selected};
+ if (!this.shouldRender) return html`<div class="chip">Loading ...</div>`;
+
+ const icon = this.selected ? 'filter' : iconForRun(this.run);
+ const classes = {
+ chip: true,
+ [icon]: true,
+ selected: this.selected,
+ deselected: this.deselected,
+ };
const action = primaryRunAction(this.run);
return html`
@@ -206,6 +230,12 @@
@customElement('gr-checks-runs')
export class GrChecksRuns extends GrLitElement {
+ @query('#filterInput')
+ filterInput?: HTMLInputElement;
+
+ @internalProperty()
+ filterRegExp = new RegExp('');
+
@property()
runs: CheckRun[] = [];
@@ -228,6 +258,11 @@
padding-top: var(--spacing-l);
text-transform: capitalize;
}
+ input#filterInput {
+ margin-top: var(--spacing-s);
+ padding: var(--spacing-s) var(--spacing-m);
+ width: 100%;
+ }
.testing {
margin-top: var(--spacing-xxl);
color: var(--deemphasized-text-color);
@@ -248,6 +283,12 @@
render() {
return html`
<h2 class="heading-2">Runs</h2>
+ <input
+ id="filterInput"
+ type="text"
+ placeholder="Filter runs by regular expression"
+ @input="${this.onInput}"
+ />
${this.renderSection(RunStatus.COMPLETED)}
${this.renderSection(RunStatus.RUNNING)}
${this.renderSection(RunStatus.RUNNABLE)}
@@ -274,6 +315,11 @@
`;
}
+ onInput() {
+ assertIsDefined(this.filterInput, 'filter <input> element');
+ this.filterRegExp = new RegExp(this.filterInput.value, 'i');
+ }
+
none() {
updateStateSetResults('f0', []);
updateStateSetResults('f1', []);
@@ -298,6 +344,7 @@
renderSection(status: RunStatus) {
const runs = this.runs
.filter(r => r.status === status)
+ .filter(r => this.filterRegExp.test(r.checkName))
.sort(compareByWorstCategory);
if (runs.length === 0) return;
return html`
@@ -310,20 +357,17 @@
renderRun(run: CheckRun) {
const selected = this.selectedRuns.has(run.checkName);
+ const deselected = !selected && this.selectedRuns.size > 0;
return html`<gr-checks-run
.run="${run}"
.selected="${selected}"
+ .deselected="${deselected}"
@run-selected="${this.handleRunSelected}"
></gr-checks-run>`;
}
handleRunSelected(e: RunSelectedEvent) {
- const checkName = e.detail.checkName;
- if (this.selectedRuns.has(checkName)) {
- this.selectedRuns.delete(checkName);
- } else {
- this.selectedRuns.add(checkName);
- }
+ toggleSetMembership(this.selectedRuns, e.detail.checkName);
this.requestUpdate();
}
}
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-tab.ts b/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
index d31ec53..0ce81ed 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
@@ -18,13 +18,25 @@
import {css, customElement, property} from 'lit-element';
import {GrLitElement} from '../lit/gr-lit-element';
import {Action, CheckResult, CheckRun} from '../../api/checks';
-import {allResults$, allRuns$} from '../../services/checks/checks-model';
+import {
+ allActions$,
+ allResults$,
+ allRuns$,
+} from '../../services/checks/checks-model';
import './gr-checks-runs';
import './gr-checks-results';
import {sharedStyles} from '../../styles/shared-styles';
import {changeNum$, currentPatchNum$} from '../../services/change/change-model';
import {NumericChangeId, PatchSetNum} from '../../types/common';
-import {ActionTriggeredEvent} from './gr-checks-runs';
+import {
+ ActionTriggeredEvent,
+ fireActionTriggered,
+} from '../../services/checks/checks-util';
+import {
+ checkRequiredProperty,
+ toggleSetMembership,
+} from '../../utils/common-util';
+import {RunSelectedEvent} from './gr-checks-runs';
/**
* The "Checks" tab on the Gerrit change page. Gets its data from plugins that
@@ -37,15 +49,20 @@
results: CheckResult[] = [];
+ actions: Action[] = [];
+
@property()
currentPatchNum: PatchSetNum | undefined = undefined;
@property()
changeNum: NumericChangeId | undefined = undefined;
+ private selectedRuns = new Set<string>();
+
constructor() {
super();
this.subscribe('runs', allRuns$);
+ this.subscribe('actions', allActions$);
this.subscribe('results', allResults$);
this.subscribe('currentPatchNum', currentPatchNum$);
this.subscribe('changeNum', changeNum$);
@@ -63,17 +80,13 @@
display: block;
}
.header {
- display: block;
+ display: flex;
+ justify-content: space-between;
padding: var(--spacing-m) var(--spacing-l);
border-bottom: 1px solid var(--border-color);
}
- .header span {
- display: inline-block;
- color: var(--link-color);
- padding: var(--spacing-s) var(--spacing-m);
- margin-right: var(--spacing-l);
- border: 1px solid var(--border-color);
- border-radius: var(--border-radius);
+ .action {
+ margin-left: var(--spacing-m);
}
.container {
display: flex;
@@ -93,29 +106,47 @@
render() {
const ps = `Patchset ${this.currentPatchNum} (Latest)`;
+ const filteredRuns = this.runs.filter(
+ r => this.selectedRuns.size === 0 || this.selectedRuns.has(r.checkName)
+ );
return html`
<div class="header">
- <gr-dropdown-list
- value="${ps}"
- .items="${[
- {
- value: `${ps}`,
- text: `${ps}`,
- },
- ]}"
- ></gr-dropdown-list>
+ <div class="left">
+ <gr-dropdown-list
+ value="${ps}"
+ .items="${[
+ {
+ value: `${ps}`,
+ text: `${ps}`,
+ },
+ ]}"
+ ></gr-dropdown-list>
+ </div>
+ <div class="right">
+ ${this.actions.map(this.renderAction)}
+ </div>
</div>
<div class="container">
- <gr-checks-runs class="runs" .runs="${this.runs}"></gr-checks-runs>
+ <gr-checks-runs
+ class="runs"
+ .runs="${this.runs}"
+ @run-selected="${this.handleRunSelected}"
+ ></gr-checks-runs>
<gr-checks-results
class="results"
- .runs="${this.runs}"
+ .runs="${filteredRuns}"
></gr-checks-results>
</div>
`;
}
- private handleActionTriggered(action: Action, run: CheckRun) {
+ renderAction(action: Action) {
+ return html`<gr-checks-top-level-action
+ .action="${action}"
+ ></gr-checks-top-level-action>`;
+ }
+
+ handleActionTriggered(action: Action, run?: CheckRun) {
if (!this.changeNum) return;
if (!this.currentPatchNum) return;
// TODO(brohlfs): The callback is supposed to be returning a promise.
@@ -124,16 +155,45 @@
action.callback(
this.changeNum,
this.currentPatchNum as number,
- run.attempt,
- run.externalId,
- run.checkName,
+ run?.attempt,
+ run?.externalId,
+ run?.checkName,
action.name
);
}
+
+ handleRunSelected(e: RunSelectedEvent) {
+ toggleSetMembership(this.selectedRuns, e.detail.checkName);
+ this.requestUpdate();
+ }
+}
+
+@customElement('gr-checks-top-level-action')
+export class GrChecksTopLevelAction extends GrLitElement {
+ @property()
+ action!: Action;
+
+ connectedCallback() {
+ super.connectedCallback();
+ checkRequiredProperty(this.action, 'action');
+ }
+
+ render() {
+ return html`
+ <gr-button link class="action" @click="${this.handleClick}"
+ >${this.action.name}</gr-button
+ >
+ `;
+ }
+
+ handleClick() {
+ fireActionTriggered(this, this.action);
+ }
}
declare global {
interface HTMLElementTagNameMap {
'gr-checks-tab': GrChecksTab;
+ 'gr-checks-top-level-action': GrChecksTopLevelAction;
}
}
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js
index 3f6148b..092daa2 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js
@@ -21,7 +21,6 @@
import {__testOnly_ErrorType} from './gr-error-manager.js';
import {stubRestApi} from '../../../test/test-utils.js';
import {appContext} from '../../../services/app-context.js';
-import {createPreferences} from '../../../test/test-data-generators.js';
const basicFixture = fixtureFromElement('gr-error-manager');
@@ -41,8 +40,6 @@
.returns(Promise.resolve({ok: true, status: 204}));
getLoggedInStub = stubRestApi('getLoggedIn')
.callsFake(() => appContext.authService.authCheck());
- stubRestApi('getPreferences').returns(Promise.resolve(
- createPreferences()));
element = basicFixture.instantiate();
element._authService.clearCache();
toastSpy = sinon.spy(element, '_createToastAlert');
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts
index b43b3b0..bed07a6 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts
@@ -304,7 +304,7 @@
if (!config) {
throw new Error('getConfig returned undefined');
}
- this._retreiveFeedbackURL(config);
+ this._retrieveFeedbackURL(config);
this._retrieveRegisterURL(config);
return getDocsBaseUrl(config, this.restApiService);
})
@@ -325,7 +325,7 @@
});
}
- _retreiveFeedbackURL(config: ServerInfo) {
+ _retrieveFeedbackURL(config: ServerInfo) {
if (config.gerrit?.report_bug_url) {
this._feedbackURL = config.gerrit.report_bug_url;
}
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.ts b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.ts
index 7430cc0..d9c43d6 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.ts
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.ts
@@ -488,7 +488,7 @@
report_bug_url: url,
},
};
- element._retreiveFeedbackURL(config);
+ element._retrieveFeedbackURL(config);
await flush();
assert.equal(element._feedbackURL, url);
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts
index f2ee838..632ce4c 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts
@@ -249,7 +249,7 @@
export interface GenerateUrlChangeViewParameters {
view: GerritView.CHANGE;
- // TODO(TS): NumericChangeId - not sure about it, may be it can be removeds
+ // TODO(TS): NumericChangeId - not sure about it, may be it can be removed
changeNum: NumericChangeId;
project: RepoName;
patchNum?: PatchSetNum;
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 468bb97..e381213 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
@@ -100,7 +100,7 @@
private refitOverlay?: () => void;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
/**
* Given robot comment CustomEvent object, fetch diffs associated
diff --git a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts
index 19f43c2..b60a585 100644
--- a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts
+++ b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts
@@ -611,7 +611,7 @@
private readonly flagsService = appContext.flagsService;
- private _isPortingCommentsExperimentEnabled = false;
+ private isPortingCommentsExperimentEnabled = false;
/** @override */
created() {
@@ -620,7 +620,7 @@
constructor() {
super();
- this._isPortingCommentsExperimentEnabled = this.flagsService.isEnabled(
+ this.isPortingCommentsExperimentEnabled = this.flagsService.isEnabled(
KnownExperimentId.PORTING_COMMENTS
);
}
@@ -636,10 +636,10 @@
this.restApiService.getDiffComments(changeNum),
this.restApiService.getDiffRobotComments(changeNum),
this.restApiService.getDiffDrafts(changeNum),
- this._isPortingCommentsExperimentEnabled
+ this.isPortingCommentsExperimentEnabled
? this.restApiService.getPortedComments(changeNum, revision)
: Promise.resolve({}),
- this._isPortingCommentsExperimentEnabled
+ this.isPortingCommentsExperimentEnabled
? this.restApiService.getPortedDrafts(changeNum, revision)
: Promise.resolve({}),
];
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 da1b928..4943298 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
@@ -33,7 +33,7 @@
/**
* In JS, unicode code points above 0xFFFF occupy two elements of a string.
- * For example '𐀏'.length is 2. An occurence of such a code point is called a
+ * For example '𐀏'.length is 2. An occurrence of such a code point is called a
* surrogate pair.
*
* This regex segments a string along tabs ('\t') and surrogate pairs, since
@@ -80,7 +80,7 @@
readonly groups: GrDiffGroup[];
- private _blameInfo: BlameInfo[] | null;
+ private blameInfo: BlameInfo[] | null;
private readonly _layerUpdateListener: (
start: LineNumber,
@@ -104,7 +104,7 @@
this._prefs = prefs;
this._outputEl = outputEl;
this.groups = [];
- this._blameInfo = null;
+ this.blameInfo = null;
if (isNaN(prefs.tab_size) || prefs.tab_size <= 0) {
throw Error('Invalid tab size from preferences.');
@@ -765,7 +765,7 @@
* re-render its blame cell content.
*/
setBlame(blame: BlameInfo[] | null) {
- this._blameInfo = blame;
+ this.blameInfo = blame;
if (!blame) return;
// TODO(wyatta): make this loop asynchronous.
@@ -890,11 +890,11 @@
* @return The commit information.
*/
_getBlameCommitForBaseLine(lineNum: LineNumber) {
- if (!this._blameInfo) {
+ if (!this.blameInfo) {
return null;
}
- for (const blameCommit of this._blameInfo) {
+ for (const blameCommit of this.blameInfo) {
for (const range of blameCommit.ranges) {
if (range.start <= lineNum && range.end >= lineNum) {
return blameCommit;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.ts b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.ts
index 5ac37dc..cc3be07 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.ts
@@ -61,7 +61,7 @@
return htmlTemplate;
}
- private _preventAutoScrollOnManualScroll = false;
+ private preventAutoScrollOnManualScroll = false;
private lastDisplayedNavigateToNextFileToast: number | null = null;
@@ -338,10 +338,10 @@
}
private _boundHandleWindowScroll = () => {
- if (this._preventAutoScrollOnManualScroll) {
+ if (this.preventAutoScrollOnManualScroll) {
this._scrollMode = ScrollMode.NEVER;
this._focusOnMove = false;
- this._preventAutoScrollOnManualScroll = false;
+ this.preventAutoScrollOnManualScroll = false;
}
};
@@ -360,14 +360,14 @@
};
private _boundHandleDiffRenderStart = () => {
- this._preventAutoScrollOnManualScroll = true;
+ this.preventAutoScrollOnManualScroll = true;
};
private _boundHandleDiffRenderContent = () => {
this._updateStops();
// When done rendering, turn focus on move and automatic scrolling back on
this._focusOnMove = true;
- this._preventAutoScrollOnManualScroll = false;
+ this.preventAutoScrollOnManualScroll = false;
};
private _boundHandleDiffLineSelected = (event: Event) => {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.ts b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.ts
index cfe2cfe..60f2853 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.ts
@@ -60,17 +60,17 @@
this.restApiService.savePreferences({diff_view: newMode});
}
this.mode = newMode;
- let annoucement;
+ let announcement;
if (this.isUnifiedSelected(newMode)) {
- annoucement = 'Changed diff view to unified';
+ announcement = 'Changed diff view to unified';
} else if (this.isSideBySideSelected(newMode)) {
- annoucement = 'Changed diff view to side by side';
+ announcement = 'Changed diff view to side by side';
}
- if (annoucement) {
+ if (announcement) {
this.fire(
'iron-announce',
{
- text: annoucement,
+ text: announcement,
},
{bubbles: true}
);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
index 088d9cf..2c4b8f6 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
@@ -1465,9 +1465,9 @@
) {
let patchNum = patchRange.patchNum;
- const comparedAgainsParent = patchRange.basePatchNum === 'PARENT';
+ const comparedAgainstParent = patchRange.basePatchNum === 'PARENT';
- if (isBase && !comparedAgainsParent) {
+ if (isBase && !comparedAgainstParent) {
patchNum = patchRange.basePatchNum;
}
@@ -1475,7 +1475,7 @@
changeBaseURL(project, changeNum, patchNum) +
`/files/${encodeURIComponent(path)}/download`;
- if (isBase && comparedAgainsParent) {
+ if (isBase && comparedAgainstParent) {
url += '?parent=1';
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-utils.ts b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-utils.ts
index 5edd353..0ca929a 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-utils.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-utils.ts
@@ -40,7 +40,7 @@
}
export function isLongCommentRange(range: CommentRange): boolean {
- return range.end_line - range.start_line > 5;
+ return range.end_line - range.start_line > 10;
}
export function getLineNumber(lineEl?: Element | null): LineNumber | null {
@@ -88,7 +88,7 @@
// TODO: This type should be exposed to gr-diff clients in a separate type file.
// For Gerrit these are instances of GrCommentThread, but other gr-diff users
// have different HTML elements in use for comment threads.
-// TODO: Also document the required HTML attritbutes that thread elements must
+// TODO: Also document the required HTML attributes that thread elements must
// have, e.g. 'diff-side', 'range', 'line-num', 'data-value'.
export interface GrDiffThreadElement extends HTMLElement {
rootId: string;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js
index 6fef223..49eac72 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js
@@ -558,7 +558,7 @@
test('adds long range comment chip', async () => {
const range = {
start_line: 1,
- end_line: 7,
+ end_line: 12,
start_character: 0,
end_character: 0,
};
@@ -572,7 +572,7 @@
a: [],
b: [],
}, {
- ab: Array(8).fill('text'),
+ ab: Array(13).fill('text'),
}];
setupSampleDiff({content});
@@ -586,7 +586,7 @@
test('no duplicate range chip for same thread', async () => {
const range = {
start_line: 1,
- end_line: 7,
+ end_line: 12,
start_character: 0,
end_character: 0,
};
@@ -604,7 +604,7 @@
a: [],
b: [],
}, {
- ab: Array(8).fill('text'),
+ ab: Array(13).fill('text'),
}];
setupSampleDiff({content});
diff --git a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.js b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.js
index fad717d..8279ab1 100644
--- a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.js
@@ -72,7 +72,7 @@
side: 'right',
range: {
end_character: 1,
- end_line: 70,
+ end_line: 71,
start_character: 1,
start_line: 60,
},
@@ -314,10 +314,10 @@
assert.equal(element._rangesMap.left[39][0].start, 0);
assert.equal(element._rangesMap.left[39][0].end, 9);
- // The right has four ranged comments: 10-12, 55-55, 60-70, 100-100
+ // The right has four ranged comments: 10-12, 55-55, 60-71, 100-100
const rightKeys = [];
for (let i = 10; i <= 12; i++) { rightKeys.push('' + i); }
- for (let i = 60; i <= 70; i++) { rightKeys.push('' + i); }
+ for (let i = 60; i <= 71; i++) { rightKeys.push('' + i); }
rightKeys.push('55', '100');
assert.deepEqual(Object.keys(element._rangesMap.right).sort(),
rightKeys.sort());
diff --git a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.ts b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.ts
index f38824f..ee52ab6 100644
--- a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.ts
+++ b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.ts
@@ -23,7 +23,6 @@
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-selection-action-box_html';
import {fireEvent} from '../../../utils/event-util';
-import {appContext} from '../../../services/app-context';
declare global {
interface HTMLElementTagNameMap {
@@ -57,11 +56,6 @@
@property({type: Boolean})
positionBelow = false;
- @property({type: Boolean})
- disableKeyboardShortcuts = false;
-
- private restApiService = appContext.restApiService;
-
/** @override */
created() {
super.created();
@@ -70,18 +64,6 @@
this.addEventListener('mousedown', e => this._handleMouseDown(e));
}
- attached() {
- this.restApiService.getPreferences().then(prefs => {
- if (prefs?.disable_keyboard_shortcuts) {
- this.disableKeyboardShortcuts = true;
- }
- });
- }
-
- _getTextForTooltip(disableKeyboardShortcuts: boolean) {
- return disableKeyboardShortcuts ? 'Click to comment' : 'Press c to comment';
- }
-
placeAbove(el: Text | Element | Range) {
flush();
const rect = this._getTargetBoundingRect(el);
diff --git a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_html.ts b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_html.ts
index d293967..24d63b3 100644
--- a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_html.ts
+++ b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_html.ts
@@ -27,7 +27,7 @@
</style>
<gr-tooltip
id="tooltip"
- text="[[_getTextForTooltip(disableKeyboardShortcuts)]]"
+ text="Press c to comment"
position-below="[[positionBelow]]"
></gr-tooltip>
`;
diff --git a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.ts b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.ts
index da29b85..1150674 100644
--- a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.ts
+++ b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.ts
@@ -492,7 +492,7 @@
* with code it shouldn't AND to avoid executing regexes as much as
* possible.
* * These tests should document the issue clearly enough that the test can
- * be condidently removed when the issue is solved in HLJS.
+ * be confidently removed when the issue is solved in HLJS.
* * These tests should rewrite the line of code to have the same number of
* characters. This method rewrites the string that gets parsed, but NOT
* the string that gets displayed and highlighted. Thus, the positions
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts
index b36edd4..bc153ee 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts
+++ b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts
@@ -277,7 +277,8 @@
return this.restApiService
.queryChangeFiles(this.change._number, this.patchNum, input)
.then(res => {
- if (!res) throw new Error('Failed to retrieve files. Reponse not set.');
+ if (!res)
+ throw new Error('Failed to retrieve files. Response not set.');
return res.map(file => {
return {name: file};
});
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.js b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.js
index be6ffc4..bbf4790 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.js
+++ b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.js
@@ -50,14 +50,14 @@
suite('edit button CUJ', () => {
let navStubs;
- let openAutoCcmplete;
+ let openAutoComplete;
setup(() => {
navStubs = [
sinon.stub(GerritNav, 'getEditUrlForDiff'),
sinon.stub(GerritNav, 'navigateToRelativeUrl'),
];
- openAutoCcmplete = element.$.openDialog.querySelector('gr-autocomplete');
+ openAutoComplete = element.$.openDialog.querySelector('gr-autocomplete');
});
test('_isValidPath', () => {
@@ -77,9 +77,9 @@
assert.isFalse(queryStub.called);
// Setup _focused manually - in headless mode Chrome sometimes don't
// setup focus. flush and/or flushAsynchronousOperations don't help
- openAutoCcmplete._focused = true;
- openAutoCcmplete.noDebounce = true;
- openAutoCcmplete.text = 'src/test.cpp';
+ openAutoComplete._focused = true;
+ openAutoComplete.noDebounce = true;
+ openAutoComplete.text = 'src/test.cpp';
assert.isTrue(queryStub.called);
assert.isFalse(element.$.openDialog.disabled);
MockInteractions.tap(element.$.openDialog.shadowRoot
@@ -95,8 +95,8 @@
MockInteractions.tap(element.shadowRoot.querySelector('#open'));
return showDialogSpy.lastCall.returnValue.then(() => {
assert.isTrue(element.$.openDialog.disabled);
- openAutoCcmplete.noDebounce = true;
- openAutoCcmplete.text = 'src/test.cpp';
+ openAutoComplete.noDebounce = true;
+ openAutoComplete.text = 'src/test.cpp';
assert.isFalse(element.$.openDialog.disabled);
MockInteractions.tap(element.$.openDialog.shadowRoot
.querySelector('gr-button'));
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
index 1864598..1e08a5c 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
@@ -200,7 +200,7 @@
}
_handlePathChanged(e: CustomEvent<string>) {
- // TODO(TS) could be cleand up, it was added for type requirements
+ // TODO(TS) could be cleaned up, it was added for type requirements
if (this._changeNum === undefined || !this._path) {
return Promise.reject(new Error('changeNum or path undefined'));
}
diff --git a/polygerrit-ui/app/elements/gr-app-element.ts b/polygerrit-ui/app/elements/gr-app-element.ts
index e4d72e1..ec3bd0f 100644
--- a/polygerrit-ui/app/elements/gr-app-element.ts
+++ b/polygerrit-ui/app/elements/gr-app-element.ts
@@ -206,7 +206,7 @@
private reporting = appContext.reportingService;
- private restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
keyboardShortcuts() {
return {
diff --git a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js
index ea7bdc3..7ea3be3 100644
--- a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js
+++ b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js
@@ -20,7 +20,7 @@
import {GrAttributeHelper} from './gr-attribute-helper.js';
Polymer({
- is: 'gr-attrubute-helper-some-element',
+ is: 'gr-attribute-helper-some-element',
properties: {
fooBar: {
type: Object,
@@ -29,7 +29,7 @@
},
});
-const basicFixture = fixtureFromElement('gr-attrubute-helper-some-element');
+const basicFixture = fixtureFromElement('gr-attribute-helper-some-element');
suite('gr-attribute-helper tests', () => {
let element;
diff --git a/polygerrit-ui/app/elements/plugins/gr-change-metadata-api/gr-change-metadata-api.ts b/polygerrit-ui/app/elements/plugins/gr-change-metadata-api/gr-change-metadata-api.ts
index 3a61bce..a03c5dc 100644
--- a/polygerrit-ui/app/elements/plugins/gr-change-metadata-api/gr-change-metadata-api.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-change-metadata-api/gr-change-metadata-api.ts
@@ -19,24 +19,24 @@
import {HookApi} from '../../../api/hook';
export class GrChangeMetadataApi implements ChangeMetadataPluginApi {
- private _hook: HookApi | null;
+ private hook: HookApi | null;
public plugin: PluginApi;
constructor(plugin: PluginApi) {
this.plugin = plugin;
- this._hook = null;
+ this.hook = null;
}
_createHook() {
- this._hook = this.plugin.hook('change-metadata-item');
+ this.hook = this.plugin.hook('change-metadata-item');
}
onLabelsChanged(callback: (value: unknown) => void) {
- if (!this._hook) {
+ if (!this.hook) {
this._createHook();
}
- this._hook!.onAttached((element: Element) =>
+ this.hook!.onAttached((element: Element) =>
this.plugin.attributeHelper(element).bind('labels', callback)
);
return this;
diff --git a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.ts b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.ts
index d2568ad..3e8f0a4 100644
--- a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.ts
@@ -19,13 +19,13 @@
import {HookApi, HookCallback} from '../../../api/hook';
export class GrDomHooksManager {
- private _hooks: Record<string, GrDomHook>;
+ private hooks: Record<string, GrDomHook>;
- private _plugin: PluginApi;
+ private plugin: PluginApi;
constructor(plugin: PluginApi) {
- this._plugin = plugin;
- this._hooks = {};
+ this.plugin = plugin;
+ this.hooks = {};
}
_getHookName(endpointName: string, moduleName?: string) {
@@ -36,37 +36,36 @@
// TODO: this still can not prevent if plugin has invalid char
// other than uppercase, but is the first step
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
- const pluginName: string =
- this._plugin.getPluginName() || 'unknown_plugin';
+ const pluginName: string = this.plugin.getPluginName() || 'unknownplugin';
return pluginName.toLowerCase() + '-autogenerated-' + endpointName;
}
}
getDomHook(endpointName: string, moduleName?: string) {
const hookName = this._getHookName(endpointName, moduleName);
- if (!this._hooks[hookName]) {
- this._hooks[hookName] = new GrDomHook(hookName, moduleName);
+ if (!this.hooks[hookName]) {
+ this.hooks[hookName] = new GrDomHook(hookName, moduleName);
}
- return this._hooks[hookName];
+ return this.hooks[hookName];
}
}
export class GrDomHook implements HookApi {
- private _instances: HTMLElement[] = [];
+ private instances: HTMLElement[] = [];
- private _attachCallbacks: HookCallback[] = [];
+ private attachCallbacks: HookCallback[] = [];
- private _detachCallbacks: HookCallback[] = [];
+ private detachCallbacks: HookCallback[] = [];
- private _moduleName: string;
+ private moduleName: string;
- private _lastAttachedPromise: Promise<HTMLElement> | null = null;
+ private lastAttachedPromise: Promise<HTMLElement> | null = null;
constructor(hookName: string, moduleName?: string) {
if (moduleName) {
- this._moduleName = moduleName;
+ this.moduleName = moduleName;
} else {
- this._moduleName = hookName;
+ this.moduleName = hookName;
this._createPlaceholder(hookName);
}
}
@@ -89,16 +88,16 @@
}
handleInstanceDetached(instance: HTMLElement) {
- const index = this._instances.indexOf(instance);
+ const index = this.instances.indexOf(instance);
if (index !== -1) {
- this._instances.splice(index, 1);
+ this.instances.splice(index, 1);
}
- this._detachCallbacks.forEach(callback => callback(instance));
+ this.detachCallbacks.forEach(callback => callback(instance));
}
handleInstanceAttached(instance: HTMLElement) {
- this._instances.push(instance);
- this._attachCallbacks.forEach(callback => callback(instance));
+ this.instances.push(instance);
+ this.attachCallbacks.forEach(callback => callback(instance));
}
/**
@@ -106,32 +105,32 @@
* Returns a Promise, that's resolved when attachment is done.
*/
getLastAttached(): Promise<HTMLElement> {
- if (this._instances.length) {
- return Promise.resolve(this._instances.slice(-1)[0]);
+ if (this.instances.length) {
+ return Promise.resolve(this.instances.slice(-1)[0]);
}
- if (!this._lastAttachedPromise) {
+ if (!this.lastAttachedPromise) {
let resolve: HookCallback;
const promise = new Promise<HTMLElement>(r => {
resolve = r;
- this._attachCallbacks.push(resolve);
+ this.attachCallbacks.push(resolve);
});
- this._lastAttachedPromise = promise.then((element: HTMLElement) => {
- this._lastAttachedPromise = null;
- const index = this._attachCallbacks.indexOf(resolve);
+ this.lastAttachedPromise = promise.then((element: HTMLElement) => {
+ this.lastAttachedPromise = null;
+ const index = this.attachCallbacks.indexOf(resolve);
if (index !== -1) {
- this._attachCallbacks.splice(index, 1);
+ this.attachCallbacks.splice(index, 1);
}
return element;
});
}
- return this._lastAttachedPromise;
+ return this.lastAttachedPromise;
}
/**
* Get all DOM hook elements.
*/
getAllAttached() {
- return this._instances;
+ return this.instances;
}
/**
@@ -139,7 +138,7 @@
* is attached.
*/
onAttached(callback: HookCallback) {
- this._attachCallbacks.push(callback);
+ this.attachCallbacks.push(callback);
return this;
}
@@ -149,7 +148,7 @@
*
*/
onDetached(callback: HookCallback) {
- this._detachCallbacks.push(callback);
+ this.detachCallbacks.push(callback);
return this;
}
@@ -157,6 +156,6 @@
* Name of DOM hook element that will be installed into the endpoint.
*/
getModuleName() {
- return this._moduleName;
+ return this.moduleName;
}
}
diff --git a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.js b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.js
index 49223b9..883f2a6 100644
--- a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.js
+++ b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.js
@@ -45,7 +45,7 @@
});
test('getModuleName()', () => {
- const hookName = Object.keys(instance._hooks).pop();
+ const hookName = Object.keys(instance.hooks).pop();
assert.equal(hookName, 'testplugin-autogenerated-foo-bar');
assert.equal(hook.getModuleName(), 'testplugin-autogenerated-foo-bar');
});
@@ -57,7 +57,7 @@
});
test('getModuleName()', () => {
- const hookName = Object.keys(instance._hooks).pop();
+ const hookName = Object.keys(instance.hooks).pop();
assert.equal(hookName, 'foo-bar my-el');
assert.equal(hook.getModuleName(), 'my-el');
});
diff --git a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface.ts b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface.ts
index 07d11ec..dcabc80 100644
--- a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface.ts
@@ -27,23 +27,23 @@
/**
* Plugin popup API.
* Provides method for opening and closing popups from plugin.
- * opt_moduleName is a name of custom element that will be automatically
+ * optmoduleName is a name of custom element that will be automatically
* inserted on popup opening.
*/
export class GrPopupInterface implements PopupPluginApi {
- private _openingPromise: Promise<GrPopupInterface> | null = null;
+ private openingPromise: Promise<GrPopupInterface> | null = null;
- private _popup: GrPluginPopup | null = null;
+ private popup: GrPluginPopup | null = null;
constructor(
readonly plugin: PluginApi,
- private _moduleName: string | null = null
+ private moduleName: string | null = null
) {}
_getElement() {
// TODO(TS): maybe consider removing this if no one is using
// anything other than native methods on the return
- return (dom(this._popup) as unknown) as HTMLElement;
+ return (dom(this.popup) as unknown) as HTMLElement;
}
/**
@@ -52,34 +52,34 @@
* if it was provided with constructor.
*/
open(): Promise<PopupPluginApi> {
- if (!this._openingPromise) {
- this._openingPromise = this.plugin
+ if (!this.openingPromise) {
+ this.openingPromise = this.plugin
.hook('plugin-overlay')
.getLastAttached()
.then(hookEl => {
const popup = document.createElement('gr-plugin-popup');
- if (this._moduleName) {
+ if (this.moduleName) {
const el = popup.appendChild(
- document.createElement(this._moduleName) as CustomPolymerPluginEl
+ document.createElement(this.moduleName) as CustomPolymerPluginEl
);
el.plugin = this.plugin;
}
- this._popup = hookEl.appendChild(popup);
+ this.popup = hookEl.appendChild(popup);
flush();
- return this._popup.open().then(() => this);
+ return this.popup.open().then(() => this);
});
}
- return this._openingPromise;
+ return this.openingPromise;
}
/**
* Hides the popup.
*/
close() {
- if (!this._popup) {
+ if (!this.popup) {
return;
}
- this._popup.close();
- this._openingPromise = null;
+ this.popup.close();
+ this.openingPromise = null;
}
}
diff --git a/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api.ts b/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api.ts
index e42ca08..0418edb 100644
--- a/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api.ts
@@ -29,7 +29,7 @@
}
export class GrRepoApi implements RepoPluginApi {
- private _hook?: HookApi;
+ private hook?: HookApi;
constructor(readonly plugin: PluginApi) {}
@@ -43,12 +43,12 @@
}
createCommand(title: string, callback: RepoCommandCallback) {
- if (this._hook) {
+ if (this.hook) {
console.warn('Already set up.');
return this;
}
- this._hook = this._createHook(title);
- this._hook.onAttached(element => {
+ this.hook = this._createHook(title);
+ this.hook.onAttached(element => {
if (callback(element.repoName, element.config) === false) {
element.hidden = true;
}
@@ -57,11 +57,11 @@
}
onTap(callback: (event: Event) => boolean) {
- if (!this._hook) {
+ if (!this.hook) {
console.warn('Call createCommand first.');
return this;
}
- this._hook.onAttached(element => {
+ this.hook.onAttached(element => {
this.plugin.eventHelper(element).on('command-tap', callback);
});
return this;
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
index 3c00a47..809139d 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
@@ -76,7 +76,6 @@
'email_strategy',
'diff_view',
'publish_comments_on_push',
- 'disable_keyboard_shortcuts',
'work_in_progress_by_default',
'default_base_for_merges',
'signed_off_by',
@@ -115,7 +114,6 @@
workInProgressByDefault: HTMLInputElement;
showSizeBarsInFileList: HTMLInputElement;
publishCommentsOnPush: HTMLInputElement;
- disableKeyboardShortcuts: HTMLInputElement;
relativeDateInChangeTable: HTMLInputElement;
};
}
@@ -386,13 +384,6 @@
);
}
- _handleDisableKeyboardShortcutsChanged() {
- this.set(
- '_localPrefs.disable_keyboard_shortcuts',
- this.$.disableKeyboardShortcuts.checked
- );
- }
-
_handleWorkInProgressByDefault() {
this.set(
'_localPrefs.work_in_progress_by_default',
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
index b141a86..11372a1 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
@@ -278,19 +278,6 @@
</span>
</section>
<section>
- <label for="disableKeyboardShortcuts" class="title"
- >Disable all keyboard shortcuts</label
- >
- <span class="value">
- <input
- id="disableKeyboardShortcuts"
- type="checkbox"
- checked$="[[_localPrefs.disable_keyboard_shortcuts]]"
- on-change="_handleDisableKeyboardShortcutsChanged"
- />
- </span>
- </section>
- <section>
<label for="insertSignedOff" class="title">
Insert Signed-off-by Footer For Inline Edit Changes
</label>
diff --git a/polygerrit-ui/app/elements/shared/gr-button/gr-button.ts b/polygerrit-ui/app/elements/shared/gr-button/gr-button.ts
index 7a6ce2c..60b891e 100644
--- a/polygerrit-ui/app/elements/shared/gr-button/gr-button.ts
+++ b/polygerrit-ui/app/elements/shared/gr-button/gr-button.ts
@@ -61,7 +61,7 @@
tooltip = '';
// Note: don't assign a value to this, since constructor is called
- // after created, the initial value maybe overriden by this
+ // after created, the initial value maybe overridden by this
@property({type: String})
_initialTabindex?: string;
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_html.ts b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_html.ts
index 76bbd67..55408c0 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_html.ts
@@ -23,12 +23,12 @@
font-size: var(--font-size-normal);
font-weight: var(--font-weight-normal);
line-height: var(--line-height-normal);
- /* Explicitly set the background color of the diff to be white. We
+ /* Explicitly set the background color of the diff. We
* cannot use the diff content type ab because of the skip chunk preceding
* it, diff processor assumes the chunk of type skip/ab can be collapsed
* and hides our diff behind context control buttons.
* */
- --dark-add-highlight-color: white;
+ --dark-add-highlight-color: var(--background-color-primary);
}
gr-button {
margin-left: var(--spacing-m);
diff --git a/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.ts b/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.ts
index 2fbbd7c..119ed20 100644
--- a/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.ts
+++ b/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.ts
@@ -54,8 +54,8 @@
export type Stop = HTMLElement | AbortStop;
/**
- * Type guard and checker to check if a stop can be targetted.
- * Abort stops cannot be targetted.
+ * Type guard and checker to check if a stop can be targeted.
+ * Abort stops cannot be targeted.
*/
export function isTargetable(stop: Stop): stop is HTMLElement {
return !(stop instanceof AbortStop);
diff --git a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.ts b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.ts
index d2f003b..4c2a417 100644
--- a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.ts
+++ b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.ts
@@ -52,7 +52,7 @@
// TODO(TS): maybe default to [] as only used in dom-repeat
@property({type: Array})
- comamnds?: Command[];
+ commands?: Command[];
@property({type: Boolean})
_loggedIn = false;
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
index 3fce16e..888f34f 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
@@ -32,7 +32,7 @@
import {NormalizedFileInfo} from '../../change/gr-file-list/gr-file-list';
/**
- * Requred values are text and value. mobileText and triggerText will
+ * Required values are text and value. mobileText and triggerText will
* fall back to text if not provided.
*
* If bottomText is not provided, nothing will display on the second
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.ts b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.ts
index e67e1f6..b8f0161 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.ts
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.ts
@@ -110,13 +110,13 @@
@property({type: String})
containerId = 'gr-hovercard-container';
- private _hideDebouncer: Debouncer | null = null;
+ private hideDebouncer: Debouncer | null = null;
- private _showDebouncer: Debouncer | null = null;
+ private showDebouncer: Debouncer | null = null;
- private _isScheduledToShow?: boolean;
+ private isScheduledToShow?: boolean;
- private _isScheduledToHide?: boolean;
+ private isScheduledToHide?: boolean;
/** @override */
attached() {
@@ -174,24 +174,24 @@
debounceHide() {
this.cancelShowDebouncer();
- if (!this._isShowing || this._isScheduledToHide) return;
- this._isScheduledToHide = true;
- this._hideDebouncer = Debouncer.debounce(
- this._hideDebouncer,
+ if (!this._isShowing || this.isScheduledToHide) return;
+ this.isScheduledToHide = true;
+ this.hideDebouncer = Debouncer.debounce(
+ this.hideDebouncer,
timeOut.after(HIDE_DELAY_MS),
() => {
// This happens when hide immediately through click or mouse leave
// on the hovercard
- if (!this._isScheduledToHide) return;
+ if (!this.isScheduledToHide) return;
this.hide();
}
);
}
cancelHideDebouncer() {
- if (this._hideDebouncer) {
- this._hideDebouncer.cancel();
- this._isScheduledToHide = false;
+ if (this.hideDebouncer) {
+ this.hideDebouncer.cancel();
+ this.isScheduledToHide = false;
}
}
@@ -305,23 +305,23 @@
*/
debounceShowBy(delayMs: number) {
this.cancelHideDebouncer();
- if (this._isShowing || this._isScheduledToShow) return;
- this._isScheduledToShow = true;
- this._showDebouncer = Debouncer.debounce(
- this._showDebouncer,
+ if (this._isShowing || this.isScheduledToShow) return;
+ this.isScheduledToShow = true;
+ this.showDebouncer = Debouncer.debounce(
+ this.showDebouncer,
timeOut.after(delayMs),
() => {
// This happens when the mouse leaves the target before the delay is over.
- if (!this._isScheduledToShow) return;
+ if (!this.isScheduledToShow) return;
this.show();
}
);
}
cancelShowDebouncer() {
- if (this._showDebouncer) {
- this._showDebouncer.cancel();
- this._isScheduledToShow = false;
+ if (this.showDebouncer) {
+ this.showDebouncer.cancel();
+ this.isScheduledToShow = false;
}
}
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.js b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.js
index 6b2e620..628b1e9 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.js
@@ -120,18 +120,18 @@
button.dispatchEvent(new CustomEvent('mouseenter'));
await enterPromise;
- assert.isTrue(element._isScheduledToShow);
- element._showDebouncer.flush();
+ assert.isTrue(element.isScheduledToShow);
+ element.showDebouncer.flush();
assert.isTrue(element._isShowing);
- assert.isFalse(element._isScheduledToShow);
+ assert.isFalse(element.isScheduledToShow);
button.dispatchEvent(new CustomEvent('mouseleave'));
await leavePromise;
- assert.isTrue(element._isScheduledToHide);
+ assert.isTrue(element.isScheduledToHide);
assert.isTrue(element._isShowing);
- element._hideDebouncer.flush();
- assert.isFalse(element._isScheduledToShow);
+ element.hideDebouncer.flush();
+ assert.isFalse(element.isScheduledToShow);
assert.isFalse(element._isShowing);
button.removeEventListener('mouseenter', enterResolve);
@@ -152,11 +152,11 @@
button.dispatchEvent(new CustomEvent('mouseenter'));
await enterPromise;
- assert.isTrue(element._isScheduledToShow);
+ assert.isTrue(element.isScheduledToShow);
MockInteractions.tap(button);
await clickPromise;
- assert.isFalse(element._isScheduledToShow);
+ assert.isFalse(element.isScheduledToShow);
assert.isFalse(element._isShowing);
button.removeEventListener('mouseenter', enterResolve);
diff --git a/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.ts b/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.ts
index 0a3ef5b..7745da8 100644
--- a/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.ts
+++ b/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.ts
@@ -128,6 +128,8 @@
<g id="message"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"/></g>
<!-- This SVG is a copy from material.io https://material.io/icons/#launch-->
<g id="launch"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></g>
+ <!-- This SVG is a copy from material.io https://material.io/icons/#filter-->
+ <g id="filter"><path d="M0,0h24 M24,24H0" fill="none"/><path d="M4.25,5.61C6.27,8.2,10,13,10,13v6c0,0.55,0.45,1,1,1h2c0.55,0,1-0.45,1-1v-6c0,0,3.72-4.8,5.74-7.39 C20.25,4.95,19.78,4,18.95,4H5.04C4.21,4,3.74,4.95,4.25,5.61z"/><path d="M0,0h24v24H0V0z" fill="none"/></g>
<!-- This is just a placeholder, i.e. an empty icon that has the same size as a normal icon. -->
<g id="placeholder"><path d="M0 0h24v24H0z" fill="none"/></g>
</defs>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.ts
index 95252cf..a3d038d 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.ts
@@ -120,12 +120,8 @@
* Don't forget to also call disposeLayer().
*/
createLayer(path: string, changeNum: number) {
- if (!this.annotationCallback) return undefined;
- const annotationLayer = new AnnotationLayer(
- path,
- changeNum,
- this.annotationCallback
- );
+ const callbackFn = this.annotationCallback || (() => {});
+ const annotationLayer = new AnnotationLayer(path, changeNum, callbackFn);
this.annotationLayers.push(annotationLayer);
return annotationLayer;
}
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api.ts
index 2f2b5ce..a4c6974 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api.ts
@@ -60,7 +60,7 @@
}
export class GrChangeActionsInterface implements ChangeActionsPluginApi {
- private _el?: GrChangeActionsElement;
+ private el?: GrChangeActionsElement;
RevisionActions = RevisionActions;
@@ -80,7 +80,7 @@
console.warn('changeActions() is not ready');
return;
}
- this._el = el;
+ this.el = el;
}
/**
@@ -88,7 +88,7 @@
* element and retrieve if the interface was created before element.
*/
private ensureEl(): GrChangeActionsElement {
- if (!this._el) {
+ if (!this.el) {
const sharedApiElement = appContext.jsApiService;
this.setEl(
(sharedApiElement.getElement(
@@ -96,7 +96,7 @@
) as unknown) as GrChangeActionsElement
);
}
- return this._el!;
+ return this.el!;
}
addPrimaryActionKey(key: PrimaryActionKey) {
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit.ts
index 27bc591..7f9218a 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit.ts
@@ -250,7 +250,7 @@
* });
* });
*
- * // Listen on your-special-event from pluignB
+ * // Listen on your-special-event from pluginB
* Gerrit.install(pluginB => {
* Gerrit.on("your-special-event", ({plugin}) => {
* // do something, plugin is pluginA
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js
index 6a8a0dd..12a4056 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js
@@ -426,7 +426,7 @@
// eslint-disable-next-line no-invalid-this
const grPopupInterface = this;
assert.equal(grPopupInterface.plugin, plugin);
- assert.equal(grPopupInterface._moduleName, 'some-name');
+ assert.equal(grPopupInterface.moduleName, 'some-name');
});
plugin.popup('some-name');
assert.isTrue(openStub.calledOnce);
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context.ts
index 21e4876..2135c30 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context.ts
@@ -28,7 +28,7 @@
}
export class GrPluginActionContext {
- private _popups: PopupPluginApi[] = [];
+ private popups: PopupPluginApi[] = [];
constructor(
public readonly plugin: PluginApi,
@@ -44,15 +44,15 @@
throw new Error('Popup element not found');
}
popupEl.appendChild(element);
- this._popups.push(popApi);
+ this.popups.push(popApi);
});
}
hide() {
- for (const popupApi of this._popups) {
+ for (const popupApi of this.popups) {
popupApi.close();
}
- this._popups.splice(0);
+ this.popups.splice(0);
}
refresh() {
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.ts
index 2752c74..82df2fa 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.ts
@@ -51,10 +51,10 @@
private readonly _importedUrls = new Set<string>();
- private _pluginLoaded = false;
+ private pluginLoaded = false;
setPluginsReady() {
- this._pluginLoaded = true;
+ this.pluginLoaded = true;
}
onNewEndpoint(endpoint: string, callback: Callback) {
@@ -125,7 +125,7 @@
// one register before plugins ready
// the other done after, then only the later one will have the callbacks
// invoked.
- if (this._pluginLoaded && this._callbacks.has(endpoint)) {
+ if (this.pluginLoaded && this._callbacks.has(endpoint)) {
this._callbacks.get(endpoint)!.forEach(callback => callback(moduleInfo));
}
}
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.ts
index 8c0fce26..db34e5a 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.ts
@@ -74,7 +74,7 @@
const UNKNOWN_PLUGIN_PREFIX = '__$$__';
// Current API version for Plugin,
-// plugins with incompatible version will not be laoded.
+// plugins with incompatible version will not be loaded.
const API_VERSION = '0.1';
/**
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.js
index 6b62291..f5b1fca 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.js
@@ -225,7 +225,7 @@
assert.isTrue(alertStub.calledTwice);
});
- test('plugins installed failed becasue of wrong version', async () => {
+ test('plugins installed failed because of wrong version', async () => {
const plugins = [
'http://test.com/plugins/foo/static/test.js',
'http://test.com/plugins/bar/static/test.js',
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
index 45ffdcd9..e7843af 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
@@ -78,14 +78,14 @@
export class Plugin implements PluginApi {
readonly _url?: URL;
- private _domHooks: GrDomHooksManager;
+ private domHooks: GrDomHooksManager;
private readonly _name: string = PLUGIN_NAME_NOT_SET;
private readonly jsApi = appContext.jsApiService;
constructor(url?: string) {
- this._domHooks = new GrDomHooksManager(this);
+ this.domHooks = new GrDomHooksManager(this);
if (!url) {
console.warn(
@@ -151,7 +151,7 @@
const type =
options && options.replace ? EndpointType.REPLACE : EndpointType.DECORATE;
const slot = (options && options.slot) || '';
- const domHook = this._domHooks.getDomHook(endpoint, moduleName);
+ const domHook = this.domHooks.getDomHook(endpoint, moduleName);
moduleName = moduleName || domHook.getModuleName();
getPluginEndpoints().registerModule(this, {
slot,
diff --git a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
index d29cba7..20e5296 100644
--- a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
+++ b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
@@ -56,7 +56,7 @@
* @event fullscreen-overlay-opened
*/
- private _fullScreenOpen = false;
+ private fullScreenOpen = false;
private _boundHandleClose: () => void = () => super.close();
@@ -99,7 +99,7 @@
super.open.apply(this);
if (this._isMobile()) {
fireEvent(this, 'fullscreen-overlay-opened');
- this._fullScreenOpen = true;
+ this.fullScreenOpen = true;
}
this._awaitOpen(resolve, reject);
});
@@ -112,9 +112,9 @@
// called after iron-overlay is closed. Does not actually close the overlay
_overlayClosed() {
window.removeEventListener('popstate', this._boundHandleClose);
- if (this._fullScreenOpen) {
+ if (this.fullScreenOpen) {
fireEvent(this, 'fullscreen-overlay-closed');
- this._fullScreenOpen = false;
+ this.fullScreenOpen = false;
}
if (this.returnFocusTo) {
this.returnFocusTo.focus();
diff --git a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.js b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.js
index 4b6ae34..72c3399 100644
--- a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.js
@@ -57,11 +57,11 @@
await element.open();
assert.isTrue(element._isMobile.called);
- assert.isTrue(element._fullScreenOpen);
+ assert.isTrue(element.fullScreenOpen);
assert.isTrue(openHandler.called);
element._overlayClosed();
- assert.isFalse(element._fullScreenOpen);
+ assert.isFalse(element.fullScreenOpen);
assert.isTrue(closeHandler.called);
});
@@ -75,11 +75,11 @@
await element.open();
assert.isTrue(element._isMobile.called);
- assert.isFalse(element._fullScreenOpen);
+ assert.isFalse(element.fullScreenOpen);
assert.isFalse(openHandler.called);
element._overlayClosed();
- assert.isFalse(element._fullScreenOpen);
+ assert.isFalse(element.fullScreenOpen);
assert.isFalse(closeHandler.called);
});
});
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper.ts b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper.ts
index fa2a28e..89abd57 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper.ts
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper.ts
@@ -75,7 +75,7 @@
export class SiteBasedCache {
// TODO(TS): Type looks unusual. Fix it.
// Container of per-canonical-path caches.
- private readonly _data = new Map<
+ private readonly data = new Map<
string | undefined,
unknown | Map<string, ParsedJSON | null>
>();
@@ -93,13 +93,13 @@
// Returns the cache for the current canonical path.
_cache(): Map<string, unknown> {
- if (!this._data.has(window.CANONICAL_PATH)) {
- this._data.set(
+ if (!this.data.has(window.CANONICAL_PATH)) {
+ this.data.set(
window.CANONICAL_PATH,
new Map<string, ParsedJSON | null>()
);
}
- return this._data.get(window.CANONICAL_PATH) as Map<
+ return this.data.get(window.CANONICAL_PATH) as Map<
string,
ParsedJSON | null
>;
@@ -140,7 +140,7 @@
newMap.set(key, value);
}
}
- this._data.set(window.CANONICAL_PATH, newMap);
+ this.data.set(window.CANONICAL_PATH, newMap);
}
}
@@ -149,25 +149,25 @@
};
export class FetchPromisesCache {
- private _data: FetchPromisesCacheData;
+ private data: FetchPromisesCacheData;
constructor() {
- this._data = {};
+ this.data = {};
}
public testOnlyGetData() {
- return this._data;
+ return this.data;
}
/**
* @return true only if a value for a key sets and it is not undefined
*/
has(key: string): boolean {
- return !!this._data[key];
+ return !!this.data[key];
}
get(key: string) {
- return this._data[key];
+ return this.data[key];
}
/**
@@ -175,17 +175,17 @@
* mark key as deleted.
*/
set(key: string, value: Promise<ParsedJSON | undefined> | undefined) {
- this._data[key] = value;
+ this.data[key] = value;
}
invalidatePrefix(prefix: string) {
const newData: FetchPromisesCacheData = {};
- Object.entries(this._data).forEach(([key, value]) => {
+ Object.entries(this.data).forEach(([key, value]) => {
if (!key.startsWith(prefix)) {
newData[key] = value;
}
});
- this._data = newData;
+ this.data = newData;
}
}
export type FetchParams = {
@@ -457,7 +457,7 @@
* Send an XHR.
*
* @return Promise resolves to Response/ParsedJSON only if the request is successful
- * (i.e. no exception and response.ok is trsue). If response fails then
+ * (i.e. no exception and response.ok is true). If response fails then
* promise resolves either to void if errFn is set or rejects if errFn
* is not set */
send(req: SendRequest): Promise<Response | ParsedJSON | undefined> {
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.ts b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.ts
index 1a1062c..95e06c0 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.ts
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.ts
@@ -81,9 +81,9 @@
// type. This class should be refactored to avoid reassignment.
private readonly result: ChangeInfoParserInput;
- private _batch: ParserBatch | null = null;
+ private batch: ParserBatch | null = null;
- private _updateItems: {[accountId: string]: UpdateItem} | null = null;
+ private updateItems: {[accountId: string]: UpdateItem} | null = null;
private readonly _lastState: {[accountId: string]: ReviewerState} = {};
@@ -105,7 +105,7 @@
* Is a part of _groupUpdates(). Creates a new batch of updates.
*/
private _startBatch(update: ReviewerUpdateInfo): ParserBatch {
- this._updateItems = {};
+ this.updateItems = {};
return {
author: update.updated_by,
date: update.updated,
@@ -121,7 +121,7 @@
*/
private _completeBatch(batch: ParserBatch) {
const items = [];
- for (const [accountId, item] of Object.entries(this._updateItems ?? {})) {
+ for (const [accountId, item] of Object.entries(this.updateItems ?? {})) {
if (this._lastState[accountId] !== item.state) {
this._lastState[accountId] = item.state;
items.push(item);
@@ -142,27 +142,27 @@
_groupUpdates(): ParserBatchWithNonEmptyUpdates[] {
const updates = this.result.reviewer_updates;
const newUpdates = updates.reduce((newUpdates, update) => {
- if (!this._batch) {
- this._batch = this._startBatch(update);
+ if (!this.batch) {
+ this.batch = this._startBatch(update);
}
const updateDate = parseDate(update.updated).getTime();
- const batchUpdateDate = parseDate(this._batch.date).getTime();
+ const batchUpdateDate = parseDate(this.batch.date).getTime();
const reviewerId = accountKey(update.reviewer);
if (
updateDate - batchUpdateDate > REVIEWER_UPDATE_THRESHOLD_MILLIS ||
- update.updated_by._account_id !== this._batch.author._account_id
+ update.updated_by._account_id !== this.batch.author._account_id
) {
// Next sequential update should form new group.
- this._completeBatch(this._batch);
- if (isParserBatchWithNonEmptyUpdates(this._batch)) {
- newUpdates.push(this._batch);
+ this._completeBatch(this.batch);
+ if (isParserBatchWithNonEmptyUpdates(this.batch)) {
+ newUpdates.push(this.batch);
}
- this._batch = this._startBatch(update);
+ this.batch = this._startBatch(update);
}
- // _startBatch assigns _updateItems. When _groupUpdates is calling,
- // _batch and _updateItems are not set => _startBatch is called. The
- // _startBatch method assigns _updateItems
- const updateItems = this._updateItems!;
+ // _startBatch assigns updateItems. When _groupUpdates is calling,
+ // batch and updateItems are not set => _startBatch is called. The
+ // _startBatch method assigns updateItems
+ const updateItems = this.updateItems!;
updateItems[reviewerId] = {
reviewer: update.reviewer,
state: update.state,
@@ -174,8 +174,8 @@
}, [] as ParserBatchWithNonEmptyUpdates[]);
// reviewer_updates always has at least 1 item
// (otherwise parse is not created) => updates.reduce calls callback
- // at least once and callback assigns this._batch
- const batch = this._batch!;
+ // at least once and callback assigns this.batch
+ const batch = this.batch!;
this._completeBatch(batch);
if (isParserBatchWithNonEmptyUpdates(batch)) {
newUpdates.push(batch);
diff --git a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.ts b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.ts
index b0b40dd..885db2a 100644
--- a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.ts
+++ b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.ts
@@ -112,7 +112,7 @@
@property({type: Boolean})
hideBorder = false;
- /** Text input should be rendered in monspace font. */
+ /** Text input should be rendered in monospace font. */
@property({type: Boolean})
monospace = false;
diff --git a/polygerrit-ui/app/mixins/gr-tooltip-mixin/gr-tooltip-mixin.ts b/polygerrit-ui/app/mixins/gr-tooltip-mixin/gr-tooltip-mixin.ts
index 77d2d00..75ad608 100644
--- a/polygerrit-ui/app/mixins/gr-tooltip-mixin/gr-tooltip-mixin.ts
+++ b/polygerrit-ui/app/mixins/gr-tooltip-mixin/gr-tooltip-mixin.ts
@@ -69,13 +69,13 @@
// Handler for mouseenter event
private mouseenterHandler?: (e: MouseEvent) => void;
- // Hanlder for scrolling on window
+ // Handler for scrolling on window
private readonly windowScrollHandler: () => void;
- // Hanlder for showing the tooltip, will be attached to certain events
+ // Handler for showing the tooltip, will be attached to certain events
private readonly showHandler: () => void;
- // Hanlder for hiding the tooltip, will be attached to certain events
+ // Handler for hiding the tooltip, will be attached to certain events
private readonly hideHandler: () => void;
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
diff --git a/polygerrit-ui/app/mixins/iron-fit-mixin/iron-fit-mixin.ts b/polygerrit-ui/app/mixins/iron-fit-mixin/iron-fit-mixin.ts
index 662d6bf..57e034f 100644
--- a/polygerrit-ui/app/mixins/iron-fit-mixin/iron-fit-mixin.ts
+++ b/polygerrit-ui/app/mixins/iron-fit-mixin/iron-fit-mixin.ts
@@ -29,7 +29,7 @@
// is used. To ensure that this import can't be avoided, the second parameter
// is added. Usage example:
// class Element extends IronFitMixin(PolymerElement, IronFitBehavior as IronFitBehavior)
-// The code 'IronFitBehavior as IronFitBehavior' required, becuase IronFitBehavior
+// The code 'IronFitBehavior as IronFitBehavior' required, because IronFitBehavior
// defined as an object, not as IronFitBehavior instance.
export const IronFitMixin = <T extends Constructor<PolymerElement>>(
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 7050cbe..ab85b87 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
@@ -107,7 +107,6 @@
CustomKeyboardEvent,
ShortcutTriggeredEventDetail,
} from '../../types/events';
-import {appContext} from '../../services/app-context';
/** Enum for all special shortcuts */
export enum SPECIAL_SHORTCUT {
@@ -545,7 +544,7 @@
}
/**
- * Shortcut manager, holds all hosts, bindings and listners.
+ * Shortcut manager, holds all hosts, bindings and listeners.
*/
export class ShortcutManager {
private readonly activeHosts = new Map<PolymerElement, Map<string, string>>();
@@ -806,10 +805,6 @@
ShortcutSection = ShortcutSection;
- private _disableKeyboardShortcuts = false;
-
- private restApiService = appContext.restApiService;
-
modifierPressed(event: CustomKeyboardEvent) {
/* We are checking for g/v as modifiers pressed. There are cases such as
* pressing v and then /, where we want the handler for / to be triggered.
@@ -831,7 +826,6 @@
}
shouldSuppressKeyboardShortcut(event: CustomKeyboardEvent) {
- if (this._disableKeyboardShortcuts) return true;
const e = getKeyboardEvent(event);
// TODO(TS): maybe override the EventApi, narrow it down to Element always
const target = (dom(e) as EventApi).rootTarget as Element;
@@ -932,13 +926,6 @@
/** @override */
connectedCallback() {
super.connectedCallback();
-
- this.restApiService.getPreferences().then(prefs => {
- if (prefs?.disable_keyboard_shortcuts) {
- this._disableKeyboardShortcuts = true;
- }
- });
-
const shortcuts = shortcutManager.attachHost(this);
if (!shortcuts) {
return;
diff --git a/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider.ts b/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider.ts
index 7969b84..5818003 100644
--- a/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider.ts
+++ b/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider.ts
@@ -19,10 +19,10 @@
import {AccountInfo} from '../../types/common';
export class GrEmailSuggestionsProvider {
- constructor(private _restAPI: RestApiService) {}
+ constructor(private restAPI: RestApiService) {}
getSuggestions(input: string) {
- return this._restAPI.getSuggestedAccounts(`${input}`).then(accounts => {
+ return this.restAPI.getSuggestedAccounts(`${input}`).then(accounts => {
if (!accounts) {
return [];
}
diff --git a/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider.ts b/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider.ts
index 1cf1c39..ff113fb 100644
--- a/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider.ts
+++ b/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider.ts
@@ -19,10 +19,10 @@
import {GroupBaseInfo} from '../../types/common';
export class GrGroupSuggestionsProvider {
- constructor(private _restAPI: RestApiService) {}
+ constructor(private restAPI: RestApiService) {}
getSuggestions(input: string) {
- return this._restAPI.getSuggestedGroups(`${input}`).then(groups => {
+ return this.restAPI.getSuggestedGroups(`${input}`).then(groups => {
if (!groups) {
return [];
}
diff --git a/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.ts b/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.ts
index 1572ba1..45116aa 100644
--- a/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.ts
+++ b/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.ts
@@ -73,13 +73,13 @@
}
}
- private _initPromise?: Promise<void>;
+ private initPromise?: Promise<void>;
- private _config?: ServerInfo;
+ private config?: ServerInfo;
- private _loggedIn = false;
+ private loggedIn = false;
- private _initialized = false;
+ private initialized = false;
private constructor(
private readonly _restAPI: RestApiService,
@@ -87,26 +87,25 @@
) {}
init() {
- if (this._initPromise) {
- return this._initPromise;
+ if (this.initPromise) {
+ return this.initPromise;
}
const getConfigPromise = this._restAPI.getConfig().then(cfg => {
- this._config = cfg;
+ this.config = cfg;
});
const getLoggedInPromise = this._restAPI.getLoggedIn().then(loggedIn => {
- this._loggedIn = loggedIn;
+ this.loggedIn = loggedIn;
});
- this._initPromise = Promise.all([
- getConfigPromise,
- getLoggedInPromise,
- ]).then(() => {
- this._initialized = true;
- });
- return this._initPromise;
+ this.initPromise = Promise.all([getConfigPromise, getLoggedInPromise]).then(
+ () => {
+ this.initialized = true;
+ }
+ );
+ return this.initPromise;
}
getSuggestions(input: string): Promise<Suggestion[]> {
- if (!this._initialized || !this._loggedIn) {
+ if (!this.initialized || !this.loggedIn) {
return Promise.resolve([]);
}
@@ -117,7 +116,7 @@
if (isReviewerAccountSuggestion(suggestion)) {
// Reviewer is an account suggestion from getChangeSuggestedReviewers.
return {
- name: getAccountDisplayName(this._config, suggestion.account),
+ name: getAccountDisplayName(this.config, suggestion.account),
value: suggestion,
};
}
@@ -133,7 +132,7 @@
if (isAccountSuggestions(suggestion)) {
// Reviewer is an account suggestion from getSuggestedAccounts.
return {
- name: getAccountDisplayName(this._config, suggestion),
+ name: getAccountDisplayName(this.config, suggestion),
value: {account: suggestion, count: 1},
};
}
diff --git a/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.js b/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.js
index c7de24a..d3cad45 100644
--- a/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.js
+++ b/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.js
@@ -130,7 +130,7 @@
value: {account: {}},
});
- provider._config = {
+ provider.config = {
user: {
anonymous_coward_name: 'Anonymous Coward Name',
},
@@ -179,10 +179,10 @@
});
test('getSuggestions short circuits when logged out', () => {
- provider._loggedIn = false;
+ provider.loggedIn = false;
return provider.getSuggestions('').then(() => {
assert.isFalse(getChangeSuggestedReviewersStub.called);
- provider._loggedIn = true;
+ provider.loggedIn = true;
return provider.getSuggestions('').then(() => {
assert.isTrue(getChangeSuggestedReviewersStub.called);
});
diff --git a/polygerrit-ui/app/services/checks/checks-model.ts b/polygerrit-ui/app/services/checks/checks-model.ts
index 9546d0b..6705a85 100644
--- a/polygerrit-ui/app/services/checks/checks-model.ts
+++ b/polygerrit-ui/app/services/checks/checks-model.ts
@@ -17,6 +17,7 @@
import {BehaviorSubject, Observable} from 'rxjs';
import {
+ Action,
Category,
CheckResult,
CheckRun,
@@ -35,6 +36,7 @@
pluginName: string;
config?: ChecksApiConfig;
runs: CheckRun[];
+ actions: Action[];
}
interface ChecksState {
@@ -53,6 +55,18 @@
distinctUntilChanged()
);
+export const allActions$ = checksState$.pipe(
+ map(state => {
+ return Object.values(state).reduce(
+ (allActions: Action[], providerState: ChecksProviderState) => [
+ ...allActions,
+ ...providerState.actions,
+ ],
+ []
+ );
+ })
+);
+
export const allRuns$ = checksState$.pipe(
map(state => {
return Object.values(state).reduce(
@@ -94,6 +108,7 @@
pluginName,
config,
runs: [],
+ actions: [],
};
privateState$.next(nextState);
}
@@ -162,11 +177,16 @@
status: RunStatus.COMPLETED,
};
-export function updateStateSetResults(pluginName: string, runs: CheckRun[]) {
+export function updateStateSetResults(
+ pluginName: string,
+ runs: CheckRun[],
+ actions: Action[] = []
+) {
const nextState = {...privateState$.getValue()};
nextState[pluginName] = {
...nextState[pluginName],
runs: [...runs],
+ actions: [...actions],
};
privateState$.next(nextState);
}
diff --git a/polygerrit-ui/app/services/checks/checks-service.ts b/polygerrit-ui/app/services/checks/checks-service.ts
index a8dd8b8..2e63f98 100644
--- a/polygerrit-ui/app/services/checks/checks-service.ts
+++ b/polygerrit-ui/app/services/checks/checks-service.ts
@@ -23,6 +23,7 @@
withLatestFrom,
} from 'rxjs/operators';
import {
+ ChangeData,
ChecksApiConfig,
ChecksProvider,
FetchResponse,
@@ -77,13 +78,20 @@
runs: [],
});
}
- return from(
- this.providers[pluginName].fetch(change._number, patchNum)
- );
+ const data: ChangeData = {
+ changeNumber: change._number,
+ patchsetNumber: patchNum,
+ repo: change.project,
+ };
+ return from(this.providers[pluginName].fetch(data));
}
),
tap(response => {
- updateStateSetResults(pluginName, response.runs ?? []);
+ updateStateSetResults(
+ pluginName,
+ response.runs ?? [],
+ response.actions
+ );
})
)
.subscribe(() => {});
diff --git a/polygerrit-ui/app/services/checks/checks-util.ts b/polygerrit-ui/app/services/checks/checks-util.ts
index 30b82b6..176464f 100644
--- a/polygerrit-ui/app/services/checks/checks-util.ts
+++ b/polygerrit-ui/app/services/checks/checks-util.ts
@@ -135,3 +135,30 @@
return 2;
}
}
+
+export interface ActionTriggeredEventDetail {
+ action: Action;
+ run?: CheckRun;
+}
+
+export type ActionTriggeredEvent = CustomEvent<ActionTriggeredEventDetail>;
+
+declare global {
+ interface HTMLElementEventMap {
+ 'action-triggered': ActionTriggeredEvent;
+ }
+}
+
+export function fireActionTriggered(
+ target: EventTarget,
+ action: Action,
+ run?: CheckRun
+) {
+ target.dispatchEvent(
+ new CustomEvent('action-triggered', {
+ detail: {action, run},
+ composed: true,
+ bubbles: true,
+ })
+ );
+}
diff --git a/polygerrit-ui/app/services/gr-auth/gr-auth_impl.ts b/polygerrit-ui/app/services/gr-auth/gr-auth_impl.ts
index 8fe7c35..6fadfde 100644
--- a/polygerrit-ui/app/services/gr-auth/gr-auth_impl.ts
+++ b/polygerrit-ui/app/services/gr-auth/gr-auth_impl.ts
@@ -61,26 +61,26 @@
static CREDS_EXPIRED_MSG = 'Credentials expired.';
- private _authCheckPromise?: Promise<Response>;
+ private authCheckPromise?: Promise<Response>;
private _last_auth_check_time: number = Date.now();
private _status = AuthStatus.UNDETERMINED;
- private _retriesLeft = MAX_GET_TOKEN_RETRIES;
+ private retriesLeft = MAX_GET_TOKEN_RETRIES;
- private _cachedTokenPromise: Promise<Token | null> | null = null;
+ private cachedTokenPromise: Promise<Token | null> | null = null;
- private _type?: AuthType;
+ private type?: AuthType;
- private _defaultOptions: AuthRequestInit = {};
+ private defaultOptions: AuthRequestInit = {};
- private _getToken: GetTokenCallback;
+ private getToken: GetTokenCallback;
public eventEmitter: EventEmitterService;
constructor(eventEmitter: EventEmitterService) {
- this._getToken = () => Promise.resolve(this._cachedTokenPromise);
+ this.getToken = () => Promise.resolve(this.cachedTokenPromise);
this.eventEmitter = eventEmitter;
}
@@ -93,15 +93,15 @@
*/
authCheck(): Promise<boolean> {
if (
- !this._authCheckPromise ||
+ !this.authCheckPromise ||
Date.now() - this._last_auth_check_time > MAX_AUTH_CHECK_WAIT_TIME_MS
) {
// Refetch after last check expired
- this._authCheckPromise = fetch(`${this.baseUrl}/auth-check`);
+ this.authCheckPromise = fetch(`${this.baseUrl}/auth-check`);
this._last_auth_check_time = Date.now();
}
- return this._authCheckPromise
+ return this.authCheckPromise
.then(res => {
// auth-check will return 204 if authed
// treat the rest as unauthed
@@ -115,14 +115,14 @@
})
.catch(() => {
this._setStatus(AuthStatus.ERROR);
- // Reset _authCheckPromise to avoid caching the failed promise
- this._authCheckPromise = undefined;
+ // Reset authCheckPromise to avoid caching the failed promise
+ this.authCheckPromise = undefined;
return false;
});
}
clearCache() {
- this._authCheckPromise = undefined;
+ this.authCheckPromise = undefined;
}
private _setStatus(status: AuthStatus) {
@@ -149,15 +149,15 @@
* Enable cross-domain authentication using OAuth access token.
*/
setup(getToken: GetTokenCallback, defaultOptions: DefaultAuthOptions) {
- this._retriesLeft = MAX_GET_TOKEN_RETRIES;
+ this.retriesLeft = MAX_GET_TOKEN_RETRIES;
if (getToken) {
- this._type = AuthType.ACCESS_TOKEN;
- this._cachedTokenPromise = null;
- this._getToken = getToken;
+ this.type = AuthType.ACCESS_TOKEN;
+ this.cachedTokenPromise = null;
+ this.getToken = getToken;
}
- this._defaultOptions = {};
+ this.defaultOptions = {};
if (defaultOptions) {
- this._defaultOptions.credentials = defaultOptions.credentials;
+ this.defaultOptions.credentials = defaultOptions.credentials;
}
}
@@ -167,10 +167,10 @@
fetch(url: string, opt_options?: AuthRequestInit): Promise<Response> {
const options: AuthRequestInitWithHeaders = {
headers: new Headers(),
- ...this._defaultOptions,
+ ...this.defaultOptions,
...opt_options,
};
- if (this._type === AuthType.ACCESS_TOKEN) {
+ if (this.type === AuthType.ACCESS_TOKEN) {
return this._getAccessToken().then(accessToken =>
this._fetchWithAccessToken(url, options, accessToken)
);
@@ -224,17 +224,17 @@
}
private _getAccessToken(): Promise<string | null> {
- if (!this._cachedTokenPromise) {
- this._cachedTokenPromise = this._getToken();
+ if (!this.cachedTokenPromise) {
+ this.cachedTokenPromise = this.getToken();
}
- return this._cachedTokenPromise.then(token => {
+ return this.cachedTokenPromise.then(token => {
if (this._isTokenValid(token)) {
- this._retriesLeft = MAX_GET_TOKEN_RETRIES;
+ this.retriesLeft = MAX_GET_TOKEN_RETRIES;
return token.access_token;
}
- if (this._retriesLeft > 0) {
- this._retriesLeft--;
- this._cachedTokenPromise = null;
+ if (this.retriesLeft > 0) {
+ this.retriesLeft--;
+ this.cachedTokenPromise = null;
return this._getAccessToken();
}
// Fall back to anonymous access.
diff --git a/polygerrit-ui/app/services/gr-reporting/gr-reporting.ts b/polygerrit-ui/app/services/gr-reporting/gr-reporting.ts
index 4ca983a..4196513 100644
--- a/polygerrit-ui/app/services/gr-reporting/gr-reporting.ts
+++ b/polygerrit-ui/app/services/gr-reporting/gr-reporting.ts
@@ -61,7 +61,7 @@
timeEnd(name: string, eventDetails?: EventDetails): void;
/**
* Reports just line timeEnd, but additionally reports an average given a
- * denominator and a separate reporiting name for the average.
+ * denominator and a separate reporting name for the average.
*
* @param name Timing name.
* @param averageName Average timing name.
@@ -74,7 +74,7 @@
denominator: number
): void;
/**
- * Get a timer object to for reporing a user timing. The start time will be
+ * Get a timer object for reporting a user timing. The start time will be
* the time that the object has been created, and the end time will be the
* time that the "end" method is called on the object.
*/
@@ -99,7 +99,7 @@
reportExecution(id: string, details: EventDetails): void;
reportInteraction(eventName: string, details?: EventDetails): void;
/**
- * A draft interaction was started. Update the time-betweeen-draft-actions
+ * A draft interaction was started. Update the time-between-draft-actions
* timer.
*/
recordDraftInteraction(): void;
diff --git a/polygerrit-ui/app/services/gr-reporting/gr-reporting_impl.ts b/polygerrit-ui/app/services/gr-reporting/gr-reporting_impl.ts
index f80cb75..631a4e0 100644
--- a/polygerrit-ui/app/services/gr-reporting/gr-reporting_impl.ts
+++ b/polygerrit-ui/app/services/gr-reporting/gr-reporting_impl.ts
@@ -292,17 +292,17 @@
private readonly _baselines = STARTUP_TIMERS;
- private _reportRepoName: string | undefined;
+ private reportRepoName: string | undefined;
- private _reportChangeId: NumericChangeId | undefined;
+ private reportChangeId: NumericChangeId | undefined;
- private _timers: {timeBetweenDraftActions: Timer | null} = {
+ private timers: {timeBetweenDraftActions: Timer | null} = {
timeBetweenDraftActions: null,
};
- private _pending: PendingReportInfo[] = [];
+ private pending: PendingReportInfo[] = [];
- private _slowRpcList: SlowRpcCall[] = [];
+ private slowRpcList: SlowRpcCall[] = [];
/**
* Keeps track of which ids were already reported to have been executed.
@@ -321,7 +321,7 @@
}
private get slowRpcSnapshot() {
- return (this._slowRpcList || []).slice();
+ return (this.slowRpcList || []).slice();
}
private _arePluginsLoaded() {
@@ -366,16 +366,16 @@
}
// We report events immediately when metrics plugin is loaded
- if (this._isMetricsPluginLoaded() && !this._pending.length) {
+ if (this._isMetricsPluginLoaded() && !this.pending.length) {
this._reportEvent(eventInfo, noLog);
} else {
// We cache until metrics plugin is loaded
- this._pending.push([eventInfo, noLog]);
+ this.pending.push([eventInfo, noLog]);
if (this._isMetricsPluginLoaded()) {
- this._pending.forEach(([eventInfo, opt_noLog]) => {
+ this.pending.forEach(([eventInfo, opt_noLog]) => {
this._reportEvent(eventInfo, opt_noLog);
});
- this._pending = [];
+ this.pending = [];
}
}
}
@@ -417,11 +417,11 @@
eventInfo.eventDetails = JSON.stringify(eventDetails);
}
- if (this._reportRepoName) {
- eventInfo.repoName = this._reportRepoName;
+ if (this.reportRepoName) {
+ eventInfo.repoName = this.reportRepoName;
}
- if (this._reportChangeId) {
- eventInfo.changeId = `${this._reportChangeId}`;
+ if (this.reportChangeId) {
+ eventInfo.changeId = `${this.reportChangeId}`;
}
const isInBackgroundTab = document.visibilityState === 'hidden';
@@ -501,10 +501,10 @@
this.time(TIMER.DIFF_VIEW_DISPLAYED);
this.time(TIMER.DIFF_VIEW_LOAD_FULL);
this.time(TIMER.FILE_LIST_DISPLAYED);
- this._reportRepoName = undefined;
- this._reportChangeId = undefined;
+ this.reportRepoName = undefined;
+ this.reportChangeId = undefined;
// reset slow rpc list since here start page loads which report these rpcs
- this._slowRpcList = [];
+ this.slowRpcList = [];
this.hiddenDurationTimer.reset();
}
@@ -651,7 +651,7 @@
if (baseTime !== 0) {
window.performance.measure(name, `${name}-start`);
} else {
- // Microsft Edge does not handle the 2nd param correctly
+ // Microsoft Edge does not handle the 2nd param correctly
// (if undefined).
window.performance.measure(name);
}
@@ -659,7 +659,7 @@
/**
* Reports just line timeEnd, but additionally reports an average given a
- * denominator and a separate reporiting name for the average.
+ * denominator and a separate reporting name for the average.
*
* @param name Timing name.
* @param averageName Average timing name.
@@ -703,7 +703,7 @@
}
/**
- * Get a timer object to for reporing a user timing. The start time will be
+ * Get a timer object to for reporting a user timing. The start time will be
* the time that the object has been created, and the end time will be the
* time that the "end" method is called on the object.
*/
@@ -765,7 +765,7 @@
true
);
if (elapsed >= SLOW_RPC_THRESHOLD) {
- this._slowRpcList.push({anonymizedUrl, elapsed});
+ this.slowRpcList.push({anonymizedUrl, elapsed});
}
}
@@ -805,17 +805,17 @@
}
/**
- * A draft interaction was started. Update the time-betweeen-draft-actions
+ * A draft interaction was started. Update the time-between-draft-actions
* timer.
*/
recordDraftInteraction() {
// If there is no timer defined, then this is the first interaction.
// Set up the timer so that it's ready to record the intervening time when
// called again.
- const timer = this._timers.timeBetweenDraftActions;
+ const timer = this.timers.timeBetweenDraftActions;
if (!timer) {
// Create a timer with a maximum length.
- this._timers.timeBetweenDraftActions = this.getTimer(
+ this.timers.timeBetweenDraftActions = this.getTimer(
DRAFT_ACTION_TIMER
).withMaximum(DRAFT_ACTION_TIMER_MAX);
return;
@@ -848,11 +848,11 @@
}
setRepoName(repoName: string) {
- this._reportRepoName = repoName;
+ this.reportRepoName = repoName;
}
setChangeId(changeId: NumericChangeId) {
- this._reportChangeId = changeId;
+ this.reportChangeId = changeId;
}
}
diff --git a/polygerrit-ui/app/tsconfig.json b/polygerrit-ui/app/tsconfig.json
index 0d751ab..46d0173d 100644
--- a/polygerrit-ui/app/tsconfig.json
+++ b/polygerrit-ui/app/tsconfig.json
@@ -48,7 +48,7 @@
"include": [
// Items below must be in sync with the src_dirs list in the BUILD file
// Also items must be in sync with tsconfig_bazel.json, tsconfig_bazel_test.json
- // (include and exclude arrays are overriden when extends)
+ // (include and exclude arrays are overridden when extends)
"api/**/*",
"constants/**/*",
"elements/**/*",
diff --git a/polygerrit-ui/app/tsconfig_bazel.json b/polygerrit-ui/app/tsconfig_bazel.json
index 46bd926..dfd2078 100644
--- a/polygerrit-ui/app/tsconfig_bazel.json
+++ b/polygerrit-ui/app/tsconfig_bazel.json
@@ -9,7 +9,7 @@
"include": [
// Items below must be in sync with the src_dirs list in the BUILD file
// Also items must be in sync with tsconfig.json, tsconfig_bazel_test.json
- // (include and exclude arrays are overriden when extends)
+ // (include and exclude arrays are overridden when extends)
"api/**/*",
"constants/**/*",
"elements/**/*",
diff --git a/polygerrit-ui/app/tsconfig_bazel_test.json b/polygerrit-ui/app/tsconfig_bazel_test.json
index 1b6c226..9c2ff93 100644
--- a/polygerrit-ui/app/tsconfig_bazel_test.json
+++ b/polygerrit-ui/app/tsconfig_bazel_test.json
@@ -14,7 +14,7 @@
"include": [
// Items below must be in sync with the src_dirs list in the BUILD file
// Also items must be in sync with tsconfig.json, tsconfig_test.json
- // (include and exclude arrays are overriden when extends)
+ // (include and exclude arrays are overridden when extends)
"api/**/*",
"constants/**/*",
"elements/**/*",
diff --git a/polygerrit-ui/app/types/common.ts b/polygerrit-ui/app/types/common.ts
index cf7e37d..711b11b 100644
--- a/polygerrit-ui/app/types/common.ts
+++ b/polygerrit-ui/app/types/common.ts
@@ -1021,7 +1021,7 @@
*/
export interface PluginConfigInfo {
has_avatars: boolean;
- // The following 2 properies exists in Java class, but don't mention in docs
+ // The following 2 properties exists in Java class, but don't mention in docs
js_resource_paths: string[];
html_resource_paths: string[];
}
@@ -1763,7 +1763,6 @@
email_strategy: EmailStrategy;
default_base_for_merges: DefaultBase;
publish_comments_on_push?: boolean;
- disable_keyboard_shortcuts?: boolean;
work_in_progress_by_default?: boolean;
// The email_format doesn't mentioned in doc, but exists in Java class GeneralPreferencesInfo
email_format?: EmailFormat;
diff --git a/polygerrit-ui/app/utils/change-util.ts b/polygerrit-ui/app/utils/change-util.ts
index 1228863..a7f8b49 100644
--- a/polygerrit-ui/app/utils/change-util.ts
+++ b/polygerrit-ui/app/utils/change-util.ts
@@ -173,28 +173,44 @@
return states;
}
-export function isOwner(change?: ChangeInfo, account?: AccountInfo) {
+export function isOwner(change?: ChangeInfo, account?: AccountInfo): boolean {
if (!change || !account) return false;
return change.owner?._account_id === account._account_id;
}
-export function isReviewer(change?: ChangeInfo, account?: AccountInfo) {
+export function isReviewer(
+ change?: ChangeInfo,
+ account?: AccountInfo
+): boolean {
if (!change || !account) return false;
const reviewers = change.reviewers.REVIEWER ?? [];
return reviewers.some(r => r._account_id === account._account_id);
}
-export function isUploader(change?: ChangeInfo, account?: AccountInfo) {
+export function isCc(change?: ChangeInfo, account?: AccountInfo): boolean {
+ if (!change || !account) return false;
+ const ccs = change.reviewers.CC ?? [];
+ return ccs.some(r => r._account_id === account._account_id);
+}
+
+export function isUploader(
+ change?: ChangeInfo,
+ account?: AccountInfo
+): boolean {
if (!change || !account) return false;
const rev = getCurrentRevision(change);
return rev?.uploader?._account_id === account._account_id;
}
-export function isInvolved(change?: ChangeInfo, account?: AccountInfo) {
+export function isInvolved(
+ change?: ChangeInfo,
+ account?: AccountInfo
+): boolean {
const owner = isOwner(change, account);
const uploader = isUploader(change, account);
const reviewer = isReviewer(change, account);
- return owner || uploader || reviewer;
+ const cc = isCc(change, account);
+ return owner || uploader || reviewer || cc;
}
export function getCurrentRevision(change?: ChangeInfo) {
diff --git a/polygerrit-ui/app/utils/common-util.ts b/polygerrit-ui/app/utils/common-util.ts
index f95105d..f4d6d51 100644
--- a/polygerrit-ui/app/utils/common-util.ts
+++ b/polygerrit-ui/app/utils/common-util.ts
@@ -69,6 +69,18 @@
/**
* Throws an error if the property is not defined.
*/
+export function checkRequiredProperty<T>(
+ property: T,
+ propertyName: string
+): asserts property is NonNullable<T> {
+ if (property === undefined || property === null) {
+ throw new Error(`Required property '${propertyName}' not set.`);
+ }
+}
+
+/**
+ * Throws an error if the property is not defined.
+ */
export function assertIsDefined<T>(
val: T,
variableName = 'variable'
@@ -99,3 +111,14 @@
}
return true;
}
+
+/**
+ * Add value, if the set does not contain it. Otherwise remove it.
+ */
+export function toggleSetMembership<T>(set: Set<T>, value: T): void {
+ if (set.has(value)) {
+ set.delete(value);
+ } else {
+ set.add(value);
+ }
+}
diff --git a/polygerrit-ui/app/utils/common-util_test.js b/polygerrit-ui/app/utils/common-util_test.js
index 917d652b..d6d66d7 100644
--- a/polygerrit-ui/app/utils/common-util_test.js
+++ b/polygerrit-ui/app/utils/common-util_test.js
@@ -29,7 +29,7 @@
assert.isTrue(hasOwnProperty(obj, 'name with spaces'));
assert.isFalse(hasOwnProperty(obj, 'def'));
});
- test('object prototype has overriden hasOwnProperty', () => {
+ test('object prototype has overridden hasOwnProperty', () => {
const F = function() {
this.abc = 23;
};
diff --git a/polygerrit-ui/app/utils/dom-util.ts b/polygerrit-ui/app/utils/dom-util.ts
index aa83173..7f9ef72 100644
--- a/polygerrit-ui/app/utils/dom-util.ts
+++ b/polygerrit-ui/app/utils/dom-util.ts
@@ -16,6 +16,7 @@
*/
import {EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
+import {check} from './common-util';
/**
* Event emitted from polymer elements.
@@ -155,7 +156,7 @@
export function windowLocationReload() {
const e = new Error();
- console.info(`Calling window.location.realod(): ${e.stack}`);
+ console.info(`Calling window.location.reload(): ${e.stack}`);
window.location.reload();
}
@@ -258,3 +259,22 @@
(/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream)
);
}
+
+export function whenVisible(
+ element: Element,
+ callback: () => void,
+ marginPx = 0
+) {
+ const observer = new IntersectionObserver(
+ (entries: IntersectionObserverEntry[]) => {
+ check(entries.length === 1, 'Expected one intersection observer entry.');
+ const entry = entries[0];
+ if (entry.isIntersecting) {
+ observer.unobserve(entry.target);
+ callback();
+ }
+ },
+ {rootMargin: `${marginPx}px`}
+ );
+ observer.observe(element);
+}
diff --git a/polygerrit-ui/app/utils/url-util_test.js b/polygerrit-ui/app/utils/url-util_test.js
index 0658be3..b1b17f4 100644
--- a/polygerrit-ui/app/utils/url-util_test.js
+++ b/polygerrit-ui/app/utils/url-util_test.js
@@ -25,15 +25,15 @@
suite('url-util tests', () => {
suite('getBaseUrl tests', () => {
- let originialCanonicalPath;
+ let originalCanonicalPath;
suiteSetup(() => {
- originialCanonicalPath = window.CANONICAL_PATH;
+ originalCanonicalPath = window.CANONICAL_PATH;
window.CANONICAL_PATH = '/r';
});
suiteTeardown(() => {
- window.CANONICAL_PATH = originialCanonicalPath;
+ window.CANONICAL_PATH = originalCanonicalPath;
});
test('getBaseUrl', () => {