Merge "Bump JGit to 5ae8d28"
diff --git a/Documentation/metrics.txt b/Documentation/metrics.txt
index e6494e6..974e897 100644
--- a/Documentation/metrics.txt
+++ b/Documentation/metrics.txt
@@ -202,8 +202,13 @@
* `change/count_rebases`: Total number of rebases
** `on_behalf_of_uploader`:
Whether the rebase was done on behalf of the uploader.
+ If the uploader does a rebase with '`on_behalf_of_uploader = true`', the flag
+ is ignored and a normal rebase is done, hence such rebases are recorded as
+ '`on_behalf_of_uploader` = false`'.
** `rebase_chain`:
Whether a chain was rebased.
+** `allow_conflicts`:
+ Whether the rebase was done with allowing conflicts.
* `change/submitted_with_rebaser_approval`: Number of rebased changes that were
submitted with a Code-Review approval of the rebaser that would not have been
submittable if the rebase was not done on behalf of the uploader.
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index a35f508..bf51252 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -6736,7 +6736,7 @@
|`rebase:chain`|`rebase`|
Present if the user can rebase the chain. +
This is the case if the calling user can rebase each change in the
-chain.+
+chain.
Rebasing a change is allowed for the change owner and users with the
link:access-control.html#category_submit[Submit] or
link:access-control.html#category_rebase[Rebase] permission if they
@@ -6744,7 +6744,7 @@
|`rebase:chain`|`rebase_on_behalf_of_uploader`|
Present if the user can rebase the chain on behalf of the uploader. +
This is the case if the calling user can rebase each change in the
-chain on behalf of the uploader.+
+chain on behalf of the uploader.
Rebasing a change on behalf of the uploader is allowed for the change
owner and users with the link:access-control.html#category_submit[Submit]
or link:access-control.html#category_rebase[Rebase] permission.
diff --git a/java/com/google/gerrit/server/restapi/change/Rebase.java b/java/com/google/gerrit/server/restapi/change/Rebase.java
index 3cb1870..167f784 100644
--- a/java/com/google/gerrit/server/restapi/change/Rebase.java
+++ b/java/com/google/gerrit/server/restapi/change/Rebase.java
@@ -97,6 +97,7 @@
rsrc.permissions().check(ChangePermission.REBASE_ON_BEHALF_OF_UPLOADER);
rsrc = rebaseUtil.onBehalfOf(rsrc, input);
} else {
+ input.onBehalfOfUploader = false;
rsrc.permissions().check(ChangePermission.REBASE);
}
@@ -127,7 +128,7 @@
bu.addOp(change.getId(), rebaseOp);
bu.execute();
- rebaseMetrics.countRebase(input.onBehalfOfUploader);
+ rebaseMetrics.countRebase(input.onBehalfOfUploader, input.allowConflicts);
ChangeInfo changeInfo = json.create(OPTIONS).format(change.getProject(), change.getId());
changeInfo.containsGitConflicts =
@@ -142,9 +143,7 @@
UiAction.Description description =
new UiAction.Description()
.setLabel("Rebase")
- .setTitle(
- "Rebase onto tip of branch or parent change. Makes you the uploader of this "
- + "change which can affect validity of approvals.")
+ .setTitle("Rebase onto tip of branch or parent change.")
.setVisible(false);
Change change = rsrc.getChange();
diff --git a/java/com/google/gerrit/server/restapi/change/RebaseChain.java b/java/com/google/gerrit/server/restapi/change/RebaseChain.java
index 32b5b11..b8afcb7 100644
--- a/java/com/google/gerrit/server/restapi/change/RebaseChain.java
+++ b/java/com/google/gerrit/server/restapi/change/RebaseChain.java
@@ -136,6 +136,7 @@
CurrentUser user = tipRsrc.getUser();
+ boolean anyRebaseOnBehalfOfUploader = false;
List<Change.Id> upToDateAncestors = new ArrayList<>();
Map<Change.Id, RebaseChangeOp> rebaseOps = new LinkedHashMap<>();
try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
@@ -161,6 +162,7 @@
&& !revRsrc.getPatchSet().uploader().equals(revRsrc.getAccountId())) {
revRsrc = rebaseUtil.onBehalfOf(revRsrc, input);
revRsrc.permissions().check(ChangePermission.REBASE_ON_BEHALF_OF_UPLOADER);
+ anyRebaseOnBehalfOfUploader = true;
} else {
revRsrc.permissions().check(ChangePermission.REBASE);
}
@@ -208,7 +210,7 @@
}
}
- rebaseMetrics.countRebaseChain(input.onBehalfOfUploader);
+ rebaseMetrics.countRebaseChain(anyRebaseOnBehalfOfUploader, input.allowConflicts);
RebaseChainInfo res = new RebaseChainInfo();
res.rebasedChanges = new ArrayList<>();
diff --git a/java/com/google/gerrit/server/restapi/change/RebaseMetrics.java b/java/com/google/gerrit/server/restapi/change/RebaseMetrics.java
index 114a112..d6577ea 100644
--- a/java/com/google/gerrit/server/restapi/change/RebaseMetrics.java
+++ b/java/com/google/gerrit/server/restapi/change/RebaseMetrics.java
@@ -14,7 +14,7 @@
package com.google.gerrit.server.restapi.change;
-import com.google.gerrit.metrics.Counter2;
+import com.google.gerrit.metrics.Counter3;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Field;
import com.google.gerrit.metrics.MetricMaker;
@@ -24,7 +24,7 @@
/** Metrics for the rebase REST endpoints ({@link Rebase} and {@link RebaseChain}). */
@Singleton
public class RebaseMetrics {
- private final Counter2<Boolean, Boolean> countRebases;
+ private final Counter3<Boolean, Boolean, Boolean> countRebases;
@Inject
public RebaseMetrics(MetricMaker metricMaker) {
@@ -37,18 +37,25 @@
.build(),
Field.ofBoolean("rebase_chain", (metadataBuilder, isRebaseChain) -> {})
.description("Whether a chain was rebased.")
+ .build(),
+ Field.ofBoolean("allow_conflicts", (metadataBuilder, allow_conflicts) -> {})
+ .description("Whether the rebase was done with allowing conflicts.")
.build());
}
- public void countRebase(boolean isOnBehalfOfUploader) {
- countRebase(isOnBehalfOfUploader, /* isRebaseChain= */ false);
+ public void countRebase(boolean isOnBehalfOfUploader, boolean allowConflicts) {
+ countRebase(isOnBehalfOfUploader, /* isRebaseChain= */ false, allowConflicts);
}
- public void countRebaseChain(boolean isOnBehalfOfUploader) {
- countRebase(isOnBehalfOfUploader, /* isRebaseChain= */ true);
+ public void countRebaseChain(boolean isOnBehalfOfUploader, boolean allowConflicts) {
+ countRebase(isOnBehalfOfUploader, /* isRebaseChain= */ true, allowConflicts);
}
- private void countRebase(boolean isOnBehalfOfUploader, boolean isRebaseChain) {
- countRebases.increment(/* field1= */ isOnBehalfOfUploader, /* field2= */ isRebaseChain);
+ private void countRebase(
+ boolean isOnBehalfOfUploader, boolean isRebaseChain, boolean allowConflicts) {
+ countRebases.increment(
+ /* field1= */ isOnBehalfOfUploader,
+ /* field2= */ isRebaseChain,
+ /* field3= */ allowConflicts);
}
}
diff --git a/javatests/com/google/gerrit/acceptance/api/change/RebaseChainOnBehalfOfUploaderIT.java b/javatests/com/google/gerrit/acceptance/api/change/RebaseChainOnBehalfOfUploaderIT.java
index 13f9904..785186d 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/RebaseChainOnBehalfOfUploaderIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/RebaseChainOnBehalfOfUploaderIT.java
@@ -1234,11 +1234,30 @@
RebaseInput rebaseInput = new RebaseInput();
rebaseInput.onBehalfOfUploader = true;
gApi.changes().id(changeToBeRebased2.get()).rebaseChain(rebaseInput);
- // field1 is on_behalf_of_uploader, field2 is rebase_chain
- assertThat(testMetricMaker.getCount("change/count_rebases", true, true)).isEqualTo(1);
- assertThat(testMetricMaker.getCount("change/count_rebases", true, false)).isEqualTo(0);
- assertThat(testMetricMaker.getCount("change/count_rebases", false, false)).isEqualTo(0);
- assertThat(testMetricMaker.getCount("change/count_rebases", false, true)).isEqualTo(0);
+ // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(1);
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, false, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, true, false)).isEqualTo(0);
+
+ // Create and submit another change so that we can rebase the change once again.
+ requestScopeOperations.setApiUser(approver);
+ Change.Id changeToBeTheNewBase2 =
+ changeOperations.newChange().project(project).owner(uploader).create();
+ gApi.changes().id(changeToBeTheNewBase2.get()).current().review(ReviewInput.approve());
+ gApi.changes().id(changeToBeTheNewBase2.get()).current().submit();
+
+ // Rebase the change once again, this time as the uploader.
+ // If the uploader sets on_behalf_of_uploader = true, the flag is ignored and a normal rebase is
+ // done, hence the metric should count this as a a rebase with on_behalf_of_uploader = false.
+ requestScopeOperations.setApiUser(uploader);
+ testMetricMaker.reset();
+ gApi.changes().id(changeToBeRebased2.get()).rebaseChain(rebaseInput);
+ // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, true, false)).isEqualTo(1);
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, false, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(0);
}
private void assertRebase(
diff --git a/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java b/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java
index dee8d1f..4e95032 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java
@@ -665,10 +665,15 @@
extensionRegistry.newRegistration().add(wipStateChangedListener)) {
RebaseInput rebaseInput = new RebaseInput();
rebaseInput.allowConflicts = true;
+ testMetricMaker.reset();
ChangeInfo changeInfo =
gApi.changes().id(changeId).revision(patchSet.name()).rebaseAsInfo(rebaseInput);
assertThat(changeInfo.containsGitConflicts).isTrue();
assertThat(changeInfo.workInProgress).isTrue();
+
+ // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, false, true))
+ .isEqualTo(1);
}
assertThat(wipStateChangedListener.invoked).isTrue();
assertThat(wipStateChangedListener.wip).isTrue();
@@ -790,11 +795,12 @@
// Rebase the second change
testMetricMaker.reset();
rebaseCallWithInput.call(r2.getChangeId(), new RebaseInput());
- // field1 is on_behalf_of_uploader, field2 is rebase_chain
- assertThat(testMetricMaker.getCount("change/count_rebases", false, false)).isEqualTo(1);
- assertThat(testMetricMaker.getCount("change/count_rebases", true, false)).isEqualTo(0);
- assertThat(testMetricMaker.getCount("change/count_rebases", true, true)).isEqualTo(0);
- assertThat(testMetricMaker.getCount("change/count_rebases", false, true)).isEqualTo(0);
+ // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, false, false))
+ .isEqualTo(1);
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, true, false)).isEqualTo(0);
}
@Test
@@ -1249,11 +1255,12 @@
testMetricMaker.reset();
verifyRebaseChainResponse(
gApi.changes().id(r4.getChangeId()).rebaseChain(), false, r2, r3, r4);
- // field1 is on_behalf_of_uploader, field2 is rebase_chain
- assertThat(testMetricMaker.getCount("change/count_rebases", false, true)).isEqualTo(1);
- assertThat(testMetricMaker.getCount("change/count_rebases", false, false)).isEqualTo(0);
- assertThat(testMetricMaker.getCount("change/count_rebases", true, true)).isEqualTo(0);
- assertThat(testMetricMaker.getCount("change/count_rebases", true, false)).isEqualTo(0);
+ // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, true, false)).isEqualTo(1);
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, false, false))
+ .isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(0);
}
private void verifyRebaseChainResponse(
diff --git a/javatests/com/google/gerrit/acceptance/api/change/RebaseOnBehalfOfUploaderIT.java b/javatests/com/google/gerrit/acceptance/api/change/RebaseOnBehalfOfUploaderIT.java
index 1b6956c..96e3e8e 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/RebaseOnBehalfOfUploaderIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/RebaseOnBehalfOfUploaderIT.java
@@ -1128,11 +1128,30 @@
RebaseInput rebaseInput = new RebaseInput();
rebaseInput.onBehalfOfUploader = true;
gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);
- // field1 is on_behalf_of_uploader, field2 is rebase_chain
- assertThat(testMetricMaker.getCount("change/count_rebases", true, false)).isEqualTo(1);
- assertThat(testMetricMaker.getCount("change/count_rebases", false, false)).isEqualTo(0);
- assertThat(testMetricMaker.getCount("change/count_rebases", true, true)).isEqualTo(0);
- assertThat(testMetricMaker.getCount("change/count_rebases", false, true)).isEqualTo(0);
+ // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(1);
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, false, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, true, false)).isEqualTo(0);
+
+ // Create and submit another change so that we can rebase the change once again.
+ requestScopeOperations.setApiUser(approver);
+ Change.Id changeToBeTheNewBase2 =
+ changeOperations.newChange().project(project).owner(uploader).create();
+ gApi.changes().id(changeToBeTheNewBase2.get()).current().review(ReviewInput.approve());
+ gApi.changes().id(changeToBeTheNewBase2.get()).current().submit();
+
+ // Rebase the change once again, this time as the uploader.
+ // If the uploader sets on_behalf_of_uploader = true, the flag is ignored and a normal rebase is
+ // done, hence the metric should count this as a a rebase with on_behalf_of_uploader = false.
+ requestScopeOperations.setApiUser(uploader);
+ testMetricMaker.reset();
+ gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);
+ // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, false, false)).isEqualTo(1);
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", false, true, false)).isEqualTo(0);
+ assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(0);
}
private void allowPermissionToAllUsers(String permission) {
diff --git a/polygerrit-ui/app/api/diff.ts b/polygerrit-ui/app/api/diff.ts
index d8f4942..4bf253d 100644
--- a/polygerrit-ui/app/api/diff.ts
+++ b/polygerrit-ui/app/api/diff.ts
@@ -243,12 +243,6 @@
image_diff_prefs?: ImageDiffPreferences;
responsive_mode?: DiffResponsiveMode;
num_lines_rendered_at_once?: number;
- /**
- * If enabled, then a new (experimental) diff rendering is used that is
- * based on Lit components and multiple rendering passes. This is planned to
- * be a temporary setting until the experiment is concluded.
- */
- use_lit_components?: boolean;
show_sign_col?: boolean;
/**
* The default view mode is SIDE_BY_SIDE.
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 048933b..2809d6e 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
@@ -47,6 +47,7 @@
import {createChangeUrl} from '../../../models/views/change';
import {throwingErrorCallback} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
import {createRepoUrl, RepoDetailView} from '../../../models/views/repo';
+import '../../shared/gr-weblink/gr-weblink';
const NOTHING_TO_SAVE = 'No changes to save.';
@@ -145,7 +146,7 @@
min-height: 2em;
align-items: center;
}
- .weblink {
+ gr-weblink {
margin-right: var(--spacing-xs);
}
gr-access-section {
@@ -209,7 +210,9 @@
</h3>
<div class="weblinks ${this.weblinks?.length ? 'show' : ''}">
History:
- ${this.weblinks?.map(webLink => this.renderWebLinks(webLink))}
+ ${this.weblinks?.map(
+ info => html`<gr-weblink .info=${info}></gr-weblink>`
+ )}
</div>
${this.sections?.map((section, index) =>
this.renderPermissionSections(section, index)
@@ -253,14 +256,6 @@
`;
}
- private renderWebLinks(webLink: WebLinkInfo) {
- return html`
- <a class="weblink" href=${webLink.url} rel="noopener" target="_blank">
- ${webLink.name}
- </a>
- `;
- }
-
private renderPermissionSections(
section: PermissionAccessSection,
index: number
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.ts b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.ts
index a11951d..2841598 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.ts
@@ -9,6 +9,7 @@
import '../../shared/gr-date-formatter/gr-date-formatter';
import '../../shared/gr-dialog/gr-dialog';
import '../../shared/gr-list-view/gr-list-view';
+import '../../shared/gr-weblink/gr-weblink';
import '../gr-create-pointer-dialog/gr-create-pointer-dialog';
import '../gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog';
import {GrCreatePointerDialog} from '../gr-create-pointer-dialog/gr-create-pointer-dialog';
@@ -335,12 +336,8 @@
`;
}
- private renderWeblink(link: WebLinkInfo) {
- return html`
- <a href=${link.url} class="webLink" rel="noopener" target="_blank">
- (${link.name})
- </a>
- `;
+ private renderWeblink(info: WebLinkInfo) {
+ return html`<gr-weblink .info=${info}></gr-weblink>`;
}
override willUpdate(changedProperties: PropertyValues) {
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.ts b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.ts
index a2b23b4..262c7d0 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.ts
@@ -253,14 +253,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test0"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -329,14 +322,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test1"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -405,14 +391,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test2"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -481,14 +460,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test3"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -557,14 +529,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test4"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -633,14 +598,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test5"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -709,14 +667,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test6"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -785,14 +736,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test7"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -861,14 +805,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test8"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -937,14 +874,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test9"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1013,14 +943,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test10"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1089,14 +1012,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test11"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1165,14 +1081,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test12"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1241,14 +1150,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test13"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1317,14 +1219,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test14"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1393,14 +1288,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test15"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1469,14 +1357,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test16"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1545,14 +1426,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test17"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1621,14 +1495,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test18"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1697,14 +1564,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test19"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1773,14 +1633,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test20"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1849,14 +1702,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test21"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -1925,14 +1771,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test22"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
@@ -2001,14 +1840,7 @@
<td class="hideItem message"></td>
<td class="hideItem tagger"></td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://git.example.org/branch/test;refs/heads/test23"
- rel="noopener"
- target="_blank"
- >
- (diffusion)
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="delete">
<gr-button
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 055cb30..7c8d1ce 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
@@ -5,6 +5,7 @@
*/
import '../../shared/gr-dialog/gr-dialog';
import '../../shared/gr-list-view/gr-list-view';
+import '../../shared/gr-weblink/gr-weblink';
import '../gr-create-repo-dialog/gr-create-repo-dialog';
import {ProjectInfoWithName, WebLinkInfo} from '../../../types/common';
import {GrCreateRepoDialog} from '../gr-create-repo-dialog/gr-create-repo-dialog';
@@ -169,12 +170,8 @@
return webLinks.map(link => this.renderWebLink(link));
}
- private renderWebLink(link: WebLinkInfo) {
- return html`
- <a href=${link.url} class="webLink" rel="noopener" target="_blank">
- ${link.name}
- </a>
- `;
+ private renderWebLink(info: WebLinkInfo) {
+ return html`<gr-weblink .info=${info}></gr-weblink>`;
}
override willUpdate(changedProperties: PropertyValues) {
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.ts b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.ts
index 906b733..b63d1c5 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.ts
@@ -90,14 +90,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test0"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -110,14 +103,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test1"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -130,14 +116,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test2"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -150,14 +129,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test3"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -170,14 +142,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test4"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -190,14 +155,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test5"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -210,14 +168,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test6"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -230,14 +181,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test7"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -250,14 +194,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test8"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -270,14 +207,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test9"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -290,14 +220,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test10"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -310,14 +233,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test11"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -330,14 +246,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test12"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -350,14 +259,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test13"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -370,14 +272,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test14"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -390,14 +285,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test15"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -410,14 +298,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test16"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -430,14 +311,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test17"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -450,14 +324,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test18"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -470,14 +337,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test19"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -490,14 +350,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test20"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -510,14 +363,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test21"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -530,14 +376,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test22"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -550,14 +389,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test23"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
@@ -570,14 +402,7 @@
<a href="/admin/repos/test"> test </a>
</td>
<td class="repositoryBrowser">
- <a
- class="webLink"
- href="https://phabricator.example.org/r/project/test24"
- rel="noopener"
- target="_blank"
- >
- diffusion
- </a>
+ <gr-weblink></gr-weblink>
</td>
<td class="changesLink">
<a href="/q/project:test"> view all </a>
diff --git a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.ts b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.ts
index e27274b..9c951fb 100644
--- a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.ts
@@ -12,6 +12,7 @@
import {LitElement, css, html, PropertyValues} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import {createRepoUrl} from '../../../models/views/repo';
+import '../../shared/gr-weblink/gr-weblink';
@customElement('gr-repo-header')
export class GrRepoHeader extends LitElement {
@@ -49,9 +50,7 @@
if (!webLinks) return;
return html`<div>
<span class="browse">Browse:</span>
- ${webLinks.map(
- link => html`<a target="_blank" href=${link.url}>${link.name}</a> `
- )}
+ ${webLinks.map(info => html`<gr-weblink .info=${info}></gr-weblink>`)}
</div> `;
}
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
index 0e71c1f..54752b0 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
@@ -16,6 +16,7 @@
import '../../shared/gr-limited-text/gr-limited-text';
import '../../shared/gr-linked-chip/gr-linked-chip';
import '../../shared/gr-tooltip-content/gr-tooltip-content';
+import '../../shared/gr-weblink/gr-weblink';
import '../gr-submit-requirements/gr-submit-requirements';
import '../gr-commit-info/gr-commit-info';
import '../gr-reviewer-list/gr-reviewer-list';
@@ -47,6 +48,7 @@
RepoName,
RevisionInfo,
ServerInfo,
+ WebLinkInfo,
} from '../../../types/common';
import {assertIsDefined, assertNever, unique} from '../../../utils/common-util';
import {GrEditableLabel} from '../../shared/gr-editable-label/gr-editable-label';
@@ -76,10 +78,9 @@
import {fontStyles} from '../../../styles/gr-font-styles';
import {changeMetadataStyles} from '../../../styles/gr-change-metadata-shared-styles';
import {when} from 'lit/directives/when.js';
-import {ifDefined} from 'lit/directives/if-defined.js';
import {createSearchUrl} from '../../../models/views/search';
import {createChangeUrl} from '../../../models/views/change';
-import {GeneratedWebLink, getChangeWeblinks} from '../../../utils/weblink-util';
+import {getChangeWeblinks} from '../../../utils/weblink-util';
import {throwingErrorCallback} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
const HASHTAG_ADD_MESSAGE = 'Add Hashtag';
@@ -182,7 +183,7 @@
gr-editable-label {
max-width: 9em;
}
- .webLink {
+ gr-weblink {
display: block;
}
gr-account-chip[disabled],
@@ -703,16 +704,7 @@
return html`<section id="webLinks">
<span class="title">Links</span>
<span class="value">
- ${webLinks.map(
- link => html`<a
- href=${ifDefined(link.url)}
- class="webLink"
- rel="noopener"
- target="_blank"
- >
- ${link.name}
- </a>`
- )}
+ ${webLinks.map(info => html`<gr-weblink .info=${info}></gr-weblink>`)}
</span>
</section>`;
}
@@ -741,7 +733,7 @@
}
// private but used in test
- computeWebLinks(): GeneratedWebLink[] {
+ computeWebLinks(): WebLinkInfo[] {
return getChangeWeblinks(this.commitInfo?.web_links, this.serverConfig);
}
diff --git a/polygerrit-ui/app/elements/change/gr-change-summary/gr-summary-chip.ts b/polygerrit-ui/app/elements/change/gr-change-summary/gr-summary-chip.ts
index 146ab61..5588f40 100644
--- a/polygerrit-ui/app/elements/change/gr-change-summary/gr-summary-chip.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-summary/gr-summary-chip.ts
@@ -66,7 +66,7 @@
border-color: var(--info-foreground);
background: var(--info-background);
}
- .summaryChip.info:hover {
+ button.summaryChip.info:hover {
background: var(--info-background-hover);
box-shadow: var(--elevation-level-1);
}
@@ -80,7 +80,7 @@
border-color: var(--warning-foreground);
background: var(--warning-background);
}
- .summaryChip.warning:hover {
+ button.summaryChip.warning:hover {
background: var(--warning-background-hover);
box-shadow: var(--elevation-level-1);
}
@@ -94,7 +94,7 @@
border-color: var(--gray-foreground);
background: var(--gray-background);
}
- .summaryChip.check:hover {
+ button.summaryChip.check:hover {
background: var(--gray-background-hover);
box-shadow: var(--elevation-level-1);
}
diff --git a/polygerrit-ui/app/elements/change/gr-comments-summary/gr-comments-summary.ts b/polygerrit-ui/app/elements/change/gr-comments-summary/gr-comments-summary.ts
index 3d5533c..6f83190 100644
--- a/polygerrit-ui/app/elements/change/gr-comments-summary/gr-comments-summary.ts
+++ b/polygerrit-ui/app/elements/change/gr-comments-summary/gr-comments-summary.ts
@@ -179,6 +179,7 @@
styleType=${SummaryChipStyles.CHECK}
category=${CommentTabState.SHOW_ALL}
.clickable=${this.clickableChips}
+ icon="mark_chat_read"
><gr-avatar-stack .accounts=${resolvedAuthors} imageSize="32">
<gr-icon
slot="fallback"
diff --git a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.ts b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.ts
index d6a5327..673f260 100644
--- a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.ts
+++ b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.ts
@@ -4,7 +4,13 @@
* SPDX-License-Identifier: Apache-2.0
*/
import '../../shared/gr-copy-clipboard/gr-copy-clipboard';
-import {CommitInfo, ServerInfo} from '../../../types/common';
+import '../../shared/gr-weblink/gr-weblink';
+import {
+ CommitId,
+ CommitInfo,
+ ServerInfo,
+ WebLinkInfo,
+} from '../../../types/common';
import {sharedStyles} from '../../../styles/shared-styles';
import {LitElement, css, html, nothing} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';
@@ -12,7 +18,7 @@
import {resolve} from '../../../models/dependency';
import {configModelToken} from '../../../models/config/config-model';
import {createSearchUrl} from '../../../models/views/search';
-import {getPatchSetWeblink} from '../../../utils/weblink-util';
+import {getBrowseCommitWeblink} from '../../../utils/weblink-util';
declare global {
interface HTMLElementTagNameMap {
@@ -55,9 +61,7 @@
const commit = this.commitInfo?.commit;
if (!commit) return nothing;
return html` <div class="container">
- <a target="_blank" rel="noopener" href=${this.computeCommitLink()}
- >${this.getWeblink()?.name ?? ''}</a
- >
+ <gr-weblink .info=${this.getWeblink(commit)}></gr-weblink>
<gr-copy-clipboard
hastooltip
.buttonTitle=${'Copy full SHA to clipboard'}
@@ -68,19 +72,18 @@
</div>`;
}
- getWeblink() {
- return getPatchSetWeblink(
- this.commitInfo?.commit,
+ /**
+ * Looks up the primary patchset weblink, but replaces its name by the
+ * shortened commit hash. And falls back to a search query, if no weblink
+ * is configured.
+ */
+ getWeblink(commit: CommitId): WebLinkInfo | undefined {
+ if (!commit) return undefined;
+ const name = commit.slice(0, 7);
+ const primaryLink = getBrowseCommitWeblink(
this.commitInfo?.web_links,
this.serverConfig
);
- }
-
- computeCommitLink() {
- const weblink = this.getWeblink();
- if (weblink?.url) return weblink.url;
-
- const hash = weblink?.name;
- return hash ? createSearchUrl({query: hash}) : '';
+ return {name, url: primaryLink?.url ?? createSearchUrl({query: name})};
}
}
diff --git a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.ts b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.ts
index d992ffe..41615a0 100644
--- a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.ts
@@ -12,6 +12,7 @@
} from '../../../test/test-data-generators';
import {CommitId} from '../../../types/common';
import {fixture, html, assert} from '@open-wc/testing';
+import {queryAndAssert} from '../../../utils/common-util';
suite('gr-commit-info tests', () => {
let element: GrCommitInfo;
@@ -36,13 +37,15 @@
};
await element.updateComplete;
+ const weblink = queryAndAssert(element, 'gr-weblink');
assert.shadowDom.equal(
- element,
+ weblink,
/* HTML */ `
- <div class="container">
- <a href="link-url" rel="noopener" target="_blank">sha4567</a>
- <gr-copy-clipboard hastooltip="" hideinput=""> </gr-copy-clipboard>
- </div>
+ <a href="link-url" rel="noopener" target="_blank">
+ <gr-tooltip-content>
+ <span> sha4567 </span>
+ </gr-tooltip-content>
+ </a>
`
);
});
@@ -54,13 +57,15 @@
};
await element.updateComplete;
+ const weblink = queryAndAssert(element, 'gr-weblink');
assert.shadowDom.equal(
- element,
+ weblink,
/* HTML */ `
- <div class="container">
- <a href="/q/sha4567" rel="noopener" target="_blank">sha4567</a>
- <gr-copy-clipboard hastooltip="" hideinput=""> </gr-copy-clipboard>
- </div>
+ <a href="/q/sha4567" rel="noopener" target="_blank">
+ <gr-tooltip-content>
+ <span> sha4567 </span>
+ </gr-tooltip-content>
+ </a>
`
);
});
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 27fde97..166d895 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
@@ -3,6 +3,7 @@
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
+import '../../shared/gr-account-chip/gr-account-chip';
import {css, html, LitElement, PropertyValues} from 'lit';
import {customElement, property, query, state} from 'lit/decorators.js';
import {when} from 'lit/directives/when.js';
@@ -10,6 +11,8 @@
NumericChangeId,
BranchName,
ChangeActionDialog,
+ AccountDetailInfo,
+ AccountInfo,
} from '../../../types/common';
import '../../shared/gr-dialog/gr-dialog';
import '../../shared/gr-autocomplete/gr-autocomplete';
@@ -26,6 +29,7 @@
import {resolve} from '../../../models/dependency';
import {changeModelToken} from '../../../models/change/change-model';
import {subscribe} from '../../lit/subscription-controller';
+import {userModelToken} from '../../../models/user/user-model';
export interface RebaseChange {
name: string;
@@ -86,9 +90,6 @@
@state()
allowConflicts = false;
- @state()
- isOwner = false;
-
@query('#rebaseOnParentInput')
private rebaseOnParentInput!: HTMLInputElement;
@@ -107,17 +108,30 @@
@query('#parentInput')
parentInput!: GrAutocomplete;
+ @state()
+ account?: AccountDetailInfo;
+
+ @state()
+ uploader?: AccountInfo;
+
private readonly restApiService = getAppContext().restApiService;
private readonly getChangeModel = resolve(this, changeModelToken);
+ private readonly getUserModel = resolve(this, userModelToken);
+
constructor() {
super();
this.query = input => this.getChangeSuggestions(input);
subscribe(
this,
- () => this.getChangeModel().isOwner$,
- x => (this.isOwner = x)
+ () => this.getUserModel().account$,
+ x => (this.account = x)
+ );
+ subscribe(
+ this,
+ () => this.getChangeModel().latestUploader$,
+ x => (this.uploader = x)
);
}
@@ -152,12 +166,15 @@
display: block;
width: 100%;
}
- .rebaseCheckbox:first-of-type {
+ .rebaseCheckbox {
margin-top: var(--spacing-m);
}
.rebaseOption {
margin: var(--spacing-m) 0;
}
+ .rebaseOnBehalfMsg {
+ margin-top: var(--spacing-m);
+ }
`,
];
@@ -255,7 +272,7 @@
>
</div>
${when(
- !this.isOwner && this.allowConflicts,
+ !this.isCurrentUserEqualToLatestUploader() && this.allowConflicts,
() =>
html`<span class="message"
>Rebase cannot be done on behalf of the uploader when allowing
@@ -276,6 +293,16 @@
<label for="rebaseChain">Rebase all ancestors</label>
</div>`
)}
+ ${when(
+ !this.isCurrentUserEqualToLatestUploader(),
+ () => html`<div class="rebaseOnBehalfMsg">Rebase will be done on behalf of${
+ !this.allowConflicts ? ' the uploader:' : ''
+ } <gr-account-chip
+ .account=${this.allowConflicts ? this.account : this.uploader}
+ .hideHovercard=${true}
+ ></gr-account-chip
+ ><span></div>`
+ )}
</div>
</gr-dialog>
`;
@@ -310,6 +337,11 @@
});
}
+ isCurrentUserEqualToLatestUploader() {
+ if (!this.account || !this.uploader) return true;
+ return this.account._account_id === this.uploader._account_id;
+ }
+
getRecentChanges() {
if (this.recentChanges) {
return Promise.resolve(this.recentChanges);
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.ts
index 3064014..8d907c9 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.ts
@@ -9,21 +9,34 @@
import {
pressKey,
queryAndAssert,
- stubFlags,
stubRestApi,
waitUntil,
} from '../../../test/test-utils';
-import {NumericChangeId, BranchName} from '../../../types/common';
-import {createChangeViewChange} from '../../../test/test-data-generators';
+import {NumericChangeId, BranchName, Timestamp} from '../../../types/common';
+import {
+ createAccountWithEmail,
+ createChangeViewChange,
+} from '../../../test/test-data-generators';
import {fixture, html, assert} from '@open-wc/testing';
import {Key} from '../../../utils/dom-util';
import {GrDialog} from '../../shared/gr-dialog/gr-dialog';
+import {testResolver} from '../../../test/common-test-setup';
+import {userModelToken} from '../../../models/user/user-model';
+import {
+ changeModelToken,
+ LoadingStatus,
+} from '../../../models/change/change-model';
+import {GrAccountChip} from '../../shared/gr-account-chip/gr-account-chip';
suite('gr-confirm-rebase-dialog tests', () => {
let element: GrConfirmRebaseDialog;
setup(async () => {
- stubFlags('isEnabled').returns(true);
+ const userModel = testResolver(userModelToken);
+ userModel.setAccount({
+ ...createAccountWithEmail('abc@def.com'),
+ registered_on: '2015-03-12 18:32:08.000000000' as Timestamp,
+ });
element = await fixture(
html`<gr-confirm-rebase-dialog></gr-confirm-rebase-dialog>`
);
@@ -91,6 +104,57 @@
);
});
+ suite('on behalf of uploader', () => {
+ let changeModel;
+ const change = {
+ ...createChangeViewChange(),
+ };
+ setup(async () => {
+ element.branch = 'test' as BranchName;
+ await element.updateComplete;
+ changeModel = testResolver(changeModelToken);
+ changeModel.setState({
+ loadingStatus: LoadingStatus.LOADED,
+ change,
+ });
+ });
+ test('for reviewer it shows message about on behalf', () => {
+ const rebaseOnBehalfMsg = queryAndAssert(element, '.rebaseOnBehalfMsg');
+ assert.dom.equal(
+ rebaseOnBehalfMsg,
+ /* HTML */ `<div class="rebaseOnBehalfMsg">
+ Rebase will be done on behalf of the uploader:
+ <gr-account-chip> </gr-account-chip> <span> </span>
+ </div>`
+ );
+ const accountChip: GrAccountChip = queryAndAssert(
+ rebaseOnBehalfMsg,
+ 'gr-account-chip'
+ );
+ assert.equal(
+ accountChip.account!,
+ change?.revisions[change.current_revision]?.uploader
+ );
+ });
+ test('allowConflicts', async () => {
+ element.allowConflicts = true;
+ await element.updateComplete;
+ const rebaseOnBehalfMsg = queryAndAssert(element, '.rebaseOnBehalfMsg');
+ assert.dom.equal(
+ rebaseOnBehalfMsg,
+ /* HTML */ `<div class="rebaseOnBehalfMsg">
+ Rebase will be done on behalf of
+ <gr-account-chip> </gr-account-chip> <span> </span>
+ </div>`
+ );
+ const accountChip: GrAccountChip = queryAndAssert(
+ rebaseOnBehalfMsg,
+ 'gr-account-chip'
+ );
+ assert.equal(accountChip.account, element.account);
+ });
+ });
+
test('disableActions property disables dialog confirm', async () => {
element.disableActions = false;
await element.updateComplete;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
index 8b0a5a2..9bead95 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
@@ -44,6 +44,7 @@
DiffInfo,
DiffPreferencesInfo,
IgnoreWhitespaceType,
+ WebLinkInfo,
} from '../../../types/diff';
import {
CreateCommentEventDetail,
@@ -95,7 +96,6 @@
noAwait,
} from '../../../utils/async-util';
import {subscribe} from '../../lit/subscription-controller';
-import {GeneratedWebLink} from '../../../utils/weblink-util';
import {userModelToken} from '../../../models/user/user-model';
import {pluginLoaderToken} from '../../shared/gr-js-api-interface/gr-plugin-loader';
@@ -128,7 +128,7 @@
'create-comment': CustomEvent<CreateCommentEventDetail>;
'is-blame-loaded-changed': ValueChangedEvent<boolean>;
'diff-changed': ValueChangedEvent<DiffInfo | undefined>;
- 'edit-weblinks-changed': ValueChangedEvent<GeneratedWebLink[] | undefined>;
+ 'edit-weblinks-changed': ValueChangedEvent<WebLinkInfo[] | undefined>;
'files-weblinks-changed': ValueChangedEvent<FilesWebLinks | undefined>;
'is-image-diff-changed': ValueChangedEvent<boolean>;
// Fired when the user selects a line (See gr-diff).
@@ -188,13 +188,13 @@
}
@state()
- private _editWeblinks?: GeneratedWebLink[];
+ private _editWeblinks?: WebLinkInfo[];
get editWeblinks() {
return this._editWeblinks;
}
- set editWeblinks(editWeblinks: GeneratedWebLink[] | undefined) {
+ set editWeblinks(editWeblinks: WebLinkInfo[] | undefined) {
if (this._editWeblinks === editWeblinks) return;
this._editWeblinks = editWeblinks;
fire(this, 'edit-weblinks-changed', {value: editWeblinks});
@@ -342,10 +342,6 @@
resolve(this, highlightServiceToken),
() => getAppContext().reportingService
);
- this.renderPrefs = {
- ...this.renderPrefs,
- use_lit_components: true,
- };
this.addEventListener(
// These are named inconsistently for a reason:
// The create-comment event is fired to indicate that we should
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 4207c2b..4687fc1 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
@@ -12,6 +12,7 @@
import '../../shared/gr-dropdown-list/gr-dropdown-list';
import '../../shared/gr-icon/gr-icon';
import '../../shared/gr-select/gr-select';
+import '../../shared/gr-weblink/gr-weblink';
import '../../shared/revision-info/revision-info';
import '../../../embed/diff/gr-diff-cursor/gr-diff-cursor';
import '../gr-apply-fix-dialog/gr-apply-fix-dialog';
@@ -48,7 +49,7 @@
ServerInfo,
CommentMap,
} from '../../../types/common';
-import {DiffInfo, DiffPreferencesInfo} from '../../../types/diff';
+import {DiffInfo, DiffPreferencesInfo, WebLinkInfo} from '../../../types/diff';
import {FileRange, ParsedChangeInfo} from '../../../types/types';
import {
FilesWebLinks,
@@ -89,7 +90,6 @@
ChangeChildView,
changeViewModelToken,
} from '../../../models/views/change';
-import {GeneratedWebLink} from '../../../utils/weblink-util';
import {userModelToken} from '../../../models/user/user-model';
import {modalStyles} from '../../../styles/gr-modal-styles';
import {PaperTabsElement} from '@polymer/paper-tabs/paper-tabs';
@@ -225,7 +225,7 @@
private isImageDiff?: boolean;
@state()
- private editWeblinks?: GeneratedWebLink[];
+ private editWeblinks?: WebLinkInfo[];
@state()
private filesWeblinks?: FilesWebLinks;
@@ -935,11 +935,7 @@
() => html`
<span class="separator"></span>
${this.editWeblinks!.map(
- weblink => html`
- <a target="_blank" href=${ifDefined(weblink.url)}
- >${weblink.name}</a
- >
- `
+ weblink => html`<gr-weblink .info=${weblink}></gr-weblink>`
)}
`
)}
@@ -1084,7 +1080,7 @@
}
private onEditWeblinksChanged(
- e: ValueChangedEvent<GeneratedWebLink[] | undefined>
+ e: ValueChangedEvent<WebLinkInfo[] | undefined>
) {
this.editWeblinks = e.detail.value;
}
diff --git a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.ts b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.ts
index e33c48a..e1dfd1f 100644
--- a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.ts
+++ b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.ts
@@ -5,6 +5,7 @@
*/
import '../../shared/gr-dropdown-list/gr-dropdown-list';
import '../../shared/gr-select/gr-select';
+import '../../shared/gr-weblink/gr-weblink';
import {convertToString, pluralize} from '../../../utils/string-util';
import {getAppContext} from '../../../services/app-context';
import {
@@ -27,6 +28,7 @@
RevisionInfo,
RevisionPatchSetNum,
Timestamp,
+ WebLinkInfo,
} from '../../../types/common';
import {RevisionInfo as RevisionInfoClass} from '../../shared/revision-info/revision-info';
import {ChangeComments} from '../gr-comment-api/gr-comment-api';
@@ -42,9 +44,7 @@
import {subscribe} from '../../lit/subscription-controller';
import {commentsModelToken} from '../../../models/comments/comments-model';
import {resolve} from '../../../models/dependency';
-import {ifDefined} from 'lit/directives/if-defined.js';
import {ValueChangedEvent} from '../../../types/events';
-import {GeneratedWebLink} from '../../../utils/weblink-util';
import {changeModelToken} from '../../../models/change/change-model';
import {changeViewModelToken} from '../../../models/views/change';
import {fireNoBubbleNoCompose} from '../../../utils/event-util';
@@ -65,8 +65,8 @@
export type PatchRangeChangeEvent = CustomEvent<PatchRangeChangeDetail>;
export interface FilesWebLinks {
- meta_a: GeneratedWebLink[];
- meta_b: GeneratedWebLink[];
+ meta_a: WebLinkInfo[];
+ meta_b: WebLinkInfo[];
}
declare global {
@@ -188,6 +188,9 @@
--trigger-style-text-color: var(--deemphasized-text-color);
--trigger-style-font-family: var(--font-family);
}
+ .filesWeblinks gr-weblink {
+ vertical-align: baseline;
+ }
@media screen and (max-width: 50em) {
.filesWeblinks {
display: none;
@@ -234,15 +237,11 @@
`;
}
- private renderWeblinks(fileLinks?: GeneratedWebLink[]) {
+ private renderWeblinks(fileLinks?: WebLinkInfo[]) {
if (!fileLinks) return;
return html`<span class="filesWeblinks">
${fileLinks.map(
- weblink => html`
- <a target="_blank" rel="noopener" href=${ifDefined(weblink.url)}>
- ${weblink.name}
- </a>
- `
+ weblink => html`<gr-weblink .info=${weblink}></gr-weblink>`
)}</span
> `;
}
diff --git a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.ts b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.ts
index 3813946..20d2549 100644
--- a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.ts
+++ b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.ts
@@ -9,7 +9,7 @@
import {GrPatchRangeSelect} from './gr-patch-range-select';
import {RevisionInfo as RevisionInfoClass} from '../../shared/revision-info/revision-info';
import {ChangeComments} from '../gr-comment-api/gr-comment-api';
-import {stubReporting} from '../../../test/test-utils';
+import {queryAll, stubReporting} from '../../../test/test-utils';
import {
BasePatchSetNum,
EDIT,
@@ -322,28 +322,11 @@
test('filesWeblinks', async () => {
element.filesWeblinks = {
- meta_a: [
- {
- name: 'foo',
- url: 'f.oo',
- },
- ],
- meta_b: [
- {
- name: 'bar',
- url: 'ba.r',
- },
- ],
+ meta_a: [{name: 'foo', url: 'f.oo'}],
+ meta_b: [{name: 'bar', url: 'ba.r'}],
};
await element.updateComplete;
- assert.equal(
- queryAndAssert(element, 'a[href="f.oo"]').textContent!.trim(),
- 'foo'
- );
- assert.equal(
- queryAndAssert(element, 'a[href="ba.r"]').textContent!.trim(),
- 'bar'
- );
+ assert.equal(queryAll(element, 'gr-weblink').length, 2);
});
test('computePatchSetCommentsString', () => {
diff --git a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.ts b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.ts
index 269bbea..c93cc97 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.ts
+++ b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.ts
@@ -6,12 +6,11 @@
import '../gr-icon/gr-icon';
import '../gr-tooltip-content/gr-tooltip-content';
import '../../../styles/shared-styles';
-import {ChangeInfo, ChangeStates} from '../../../types/common';
+import {ChangeInfo, ChangeStates, WebLinkInfo} from '../../../types/common';
import {sharedStyles} from '../../../styles/shared-styles';
import {LitElement, PropertyValues, html, css} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';
import {createSearchUrl} from '../../../models/views/search';
-import {GeneratedWebLink} from '../../../utils/weblink-util';
export const WIP_TOOLTIP =
"This change isn't ready to be reviewed or submitted. " +
@@ -47,7 +46,7 @@
revertedChange?: ChangeInfo;
@property({type: Object})
- resolveWeblinks?: GeneratedWebLink[] = [];
+ resolveWeblinks?: WebLinkInfo[] = [];
static override get styles() {
return [
diff --git a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.ts b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.ts
index 36615c0..89d30ee 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.ts
@@ -80,7 +80,7 @@
);
assert.equal(element.tooltipText, '');
assert.isTrue(element.classList.contains('merged'));
- element.resolveWeblinks = [{url: 'http://google.com'}];
+ element.resolveWeblinks = [{name: 'browse', url: 'http://google.com'}];
element.status = ChangeStates.MERGED;
assert.isFalse(element.showResolveIcon());
});
@@ -117,7 +117,7 @@
test('merge conflict with resolve link', () => {
const status = ChangeStates.MERGE_CONFLICT;
const url = 'http://google.com';
- const weblinks = [{url}];
+ const weblinks = [{name: 'browse', url}];
element.revertedChange = undefined;
element.resolveWeblinks = weblinks;
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 a083526..9b74e24 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
@@ -166,6 +166,9 @@
--selection-background-color
);
}
+ gr-comments-summary {
+ padding-left: var(--spacing-s);
+ }
@media only screen and (max-width: 50em) {
gr-select {
display: var(--gr-select-style-display, inline);
@@ -252,15 +255,17 @@
return html`
<paper-item ?disabled=${item.disabled} data-value=${item.value}>
<div class="topContent">
- <div>${item.text}</div>
- ${when(
- item.commentThreads,
- () => html`<gr-comments-summary
- .commentThreads=${item.commentThreads}
- emptyWhenNoComments
- showAvatarForResolved
- ></gr-comments-summary>`
- )}
+ <div>
+ <span>${item.text}</span>
+ ${when(
+ item.commentThreads,
+ () => html`<gr-comments-summary
+ .commentThreads=${item.commentThreads}
+ emptyWhenNoComments
+ showAvatarForResolved
+ ></gr-comments-summary>`
+ )}
+ </div>
${when(
item.date,
() => html`
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.ts b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.ts
index b9380cb..c148a1b 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.ts
@@ -91,7 +91,7 @@
tabindex="-1"
>
<div class="topContent">
- <div>Top Text 1</div>
+ <div><span>Top Text 1</span></div>
</div>
</paper-item>
<paper-item
@@ -103,7 +103,7 @@
tabindex="0"
>
<div class="topContent">
- <div>Top Text 2</div>
+ <div><span>Top Text 2</span></div>
</div>
<div class="bottomContent">
<div>Bottom Text 2</div>
@@ -119,7 +119,7 @@
tabindex="-1"
>
<div class="topContent">
- <div>Top Text 3</div>
+ <div><span>Top Text 3</span></div>
<gr-date-formatter> </gr-date-formatter>
</div>
<div class="bottomContent">
@@ -231,7 +231,8 @@
assert.equal(items[0].dataset.value, element.items[0].value as any);
assert.equal(mobileItems[0].value, element.items[0].value);
assert.equal(
- queryAndAssert<HTMLDivElement>(items[0], '.topContent div').innerText,
+ queryAndAssert<HTMLDivElement>(items[0], '.topContent div span')
+ .innerText,
element.items[0].text
);
@@ -250,7 +251,8 @@
assert.equal(items[1].dataset.value, element.items[1].value as any);
assert.equal(mobileItems[1].value, element.items[1].value);
assert.equal(
- queryAndAssert<HTMLDivElement>(items[1], '.topContent div').innerText,
+ queryAndAssert<HTMLDivElement>(items[1], '.topContent div span')
+ .textContent,
element.items[1].text
);
@@ -273,7 +275,8 @@
assert.equal(items[2].dataset.value, element.items[2].value as any);
assert.equal(mobileItems[2].value, element.items[2].value);
assert.equal(
- queryAndAssert<HTMLDivElement>(items[2], '.topContent div').innerText,
+ queryAndAssert<HTMLDivElement>(items[2], '.topContent div span')
+ .innerText,
element.items[2].text
);
diff --git a/polygerrit-ui/app/elements/shared/gr-weblink/gr-weblink.ts b/polygerrit-ui/app/elements/shared/gr-weblink/gr-weblink.ts
new file mode 100644
index 0000000..6d14957
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-weblink/gr-weblink.ts
@@ -0,0 +1,61 @@
+/**
+ * @license
+ * Copyright 2023 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+import '../gr-tooltip-content/gr-tooltip-content';
+import {LitElement, css, html, nothing} from 'lit';
+import {customElement, property} from 'lit/decorators.js';
+import {WebLinkInfo} from '../../../api/rest-api';
+import {ifDefined} from 'lit/directives/if-defined.js';
+import {when} from 'lit/directives/when.js';
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'gr-weblink': GrWeblink;
+ }
+}
+@customElement('gr-weblink')
+export class GrWeblink extends LitElement {
+ @property({type: Object})
+ info?: WebLinkInfo;
+
+ static override get styles() {
+ return [
+ css`
+ :host {
+ display: inline-block;
+ vertical-align: top;
+ line-height: var(--line-height-normal);
+ }
+ a {
+ color: var(--link-color);
+ }
+ img {
+ width: var(--line-height-normal);
+ height: var(--line-height-normal);
+ }
+ `,
+ ];
+ }
+
+ override render() {
+ if (!this.info?.url) return nothing;
+ if (!this.info?.name) return nothing;
+
+ return html`
+ <a href=${this.info.url} rel="noopener" target="_blank">
+ <gr-tooltip-content
+ title=${ifDefined(this.info.tooltip)}
+ ?has-tooltip=${this.info.tooltip !== undefined}
+ >
+ ${when(
+ this.info.image_url,
+ () => html`<img src=${this.info!.image_url!} />`,
+ () => html`<span>${this.info!.name}</span>`
+ )}
+ </gr-tooltip-content>
+ </a>
+ `;
+ }
+}
diff --git a/polygerrit-ui/app/elements/shared/gr-weblink/gr-weblink_test.ts b/polygerrit-ui/app/elements/shared/gr-weblink/gr-weblink_test.ts
new file mode 100644
index 0000000..acb309f
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-weblink/gr-weblink_test.ts
@@ -0,0 +1,56 @@
+/**
+ * @license
+ * Copyright 2023 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+import '../../../test/common-test-setup';
+import {fixture, assert} from '@open-wc/testing';
+import {html} from 'lit';
+import './gr-weblink';
+import {GrWeblink} from './gr-weblink';
+import {WebLinkInfo} from '../../../api/rest-api';
+
+suite('gr-weblink tests', () => {
+ test('renders with image', async () => {
+ const info: WebLinkInfo = {
+ name: 'gitiles',
+ url: 'https://www.google.com',
+ image_url: 'https://www.google.com/favicon.ico',
+ tooltip: 'Open in Gitiles',
+ };
+ const element = await fixture<GrWeblink>(
+ html`<gr-weblink .info=${info}></gr-weblink>`
+ );
+ assert.shadowDom.equal(
+ element,
+ /* HTML */ `
+ <a href="https://www.google.com" rel="noopener" target="_blank">
+ <gr-tooltip-content title="Open in Gitiles" has-tooltip>
+ <img src="https://www.google.com/favicon.ico" />
+ </gr-tooltip-content>
+ </a>
+ `
+ );
+ });
+
+ test('renders with text', async () => {
+ const info: WebLinkInfo = {
+ name: 'gitiles',
+ url: 'https://www.google.com',
+ tooltip: 'Open in Gitiles',
+ };
+ const element = await fixture<GrWeblink>(
+ html`<gr-weblink .info=${info}></gr-weblink>`
+ );
+ assert.shadowDom.equal(
+ element,
+ /* HTML */ `
+ <a href="https://www.google.com" rel="noopener" target="_blank">
+ <gr-tooltip-content title="Open in Gitiles" has-tooltip>
+ <span>gitiles</span>
+ </gr-tooltip-content>
+ </a>
+ `
+ );
+ });
+});
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts
index 71a0637..7fa6d72 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts
@@ -13,9 +13,7 @@
DiffContextExpandedEventDetail,
isImageDiffBuilder,
} from './gr-diff-builder';
-import {GrDiffBuilderSideBySide} from './gr-diff-builder-side-by-side';
import {GrDiffBuilderImage} from './gr-diff-builder-image';
-import {GrDiffBuilderUnified} from './gr-diff-builder-unified';
import {GrDiffBuilderBinary} from './gr-diff-builder-binary';
import {GrDiffBuilderLit} from './gr-diff-builder-lit';
import {CancelablePromise, makeCancelable} from '../../../utils/async-util';
@@ -428,7 +426,6 @@
}
let builder = null;
- const useLit = this.renderPrefs?.use_lit_components ?? false;
if (this.isImageDiff) {
builder = new GrDiffBuilderImage(
this.diff,
@@ -447,45 +444,25 @@
...this.renderPrefs,
view_mode: DiffViewMode.SIDE_BY_SIDE,
};
- if (useLit) {
- builder = new GrDiffBuilderLit(
- this.diff,
- localPrefs,
- this.diffElement,
- this.layersInternal,
- this.renderPrefs
- );
- } else {
- builder = new GrDiffBuilderSideBySide(
- this.diff,
- localPrefs,
- this.diffElement,
- this.layersInternal,
- this.renderPrefs
- );
- }
+ builder = new GrDiffBuilderLit(
+ this.diff,
+ localPrefs,
+ this.diffElement,
+ this.layersInternal,
+ this.renderPrefs
+ );
} else if (this.viewMode === DiffViewMode.UNIFIED) {
this.renderPrefs = {
...this.renderPrefs,
view_mode: DiffViewMode.UNIFIED,
};
- if (useLit) {
- builder = new GrDiffBuilderLit(
- this.diff,
- localPrefs,
- this.diffElement,
- this.layersInternal,
- this.renderPrefs
- );
- } else {
- builder = new GrDiffBuilderUnified(
- this.diff,
- localPrefs,
- this.diffElement,
- this.layersInternal,
- this.renderPrefs
- );
- }
+ builder = new GrDiffBuilderLit(
+ this.diff,
+ localPrefs,
+ this.diffElement,
+ this.layersInternal,
+ this.renderPrefs
+ );
}
if (!builder) {
throw Error(`Unsupported diff view mode: ${this.viewMode}`);
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element_test.ts
index 9cf9bae..ba6acfd 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element_test.ts
@@ -6,17 +6,15 @@
import '../../../test/common-test-setup';
import {
createConfig,
- createDiff,
createEmptyDiff,
} from '../../../test/test-data-generators';
import './gr-diff-builder-element';
-import {queryAndAssert, stubBaseUrl, waitUntil} from '../../../test/test-utils';
+import {stubBaseUrl, waitUntil} from '../../../test/test-utils';
import {GrAnnotation} from '../gr-diff-highlight/gr-annotation';
import {GrDiffLine, GrDiffLineType} from '../gr-diff/gr-diff-line';
import {GrDiffBuilderSideBySide} from './gr-diff-builder-side-by-side';
import {
DiffContent,
- DiffInfo,
DiffLayer,
DiffPreferencesInfo,
DiffViewMode,
@@ -30,6 +28,7 @@
import {KeyLocations} from '../gr-diff-processor/gr-diff-processor';
import {BlameInfo} from '../../../types/common';
import {fixture, html, assert} from '@open-wc/testing';
+import {GrDiffRow} from './gr-diff-row';
const DEFAULT_PREFS = createDefaultDiffPrefs();
@@ -39,7 +38,6 @@
let diffTable: HTMLTableElement;
const LINE_BREAK_HTML = '<span class="gr-diff br"></span>';
- const WBR_HTML = '<wbr class="gr-diff">';
const setBuilderPrefs = (prefs: Partial<DiffPreferencesInfo>) => {
builder = new GrDiffBuilderSideBySide(
@@ -65,15 +63,6 @@
setBuilderPrefs({});
});
- test('line_length applied with <wbr> if line_wrapping is true', () => {
- setBuilderPrefs({line_wrapping: true, tab_size: 4, line_length: 50});
- const text = 'a'.repeat(51);
- const expected = 'a'.repeat(50) + WBR_HTML + 'a';
- const result = builder.createTextEl(null, line(text)).firstElementChild
- ?.firstElementChild?.innerHTML;
- assert.equal(result, expected);
- });
-
test('line_length applied with line break if line_wrapping is false', () => {
setBuilderPrefs({line_wrapping: false, tab_size: 4, line_length: 50});
const text = 'a'.repeat(51);
@@ -691,7 +680,7 @@
assert.include(diffRows[4].textContent, 'unchanged 11');
});
- test('clicking +x common lines expands those lines', () => {
+ test('clicking +x common lines expands those lines', async () => {
const contextControls = diffTable.querySelectorAll('gr-context-controls');
const topExpandCommonButton =
contextControls[0].shadowRoot?.querySelectorAll<HTMLElement>(
@@ -699,10 +688,19 @@
)[0];
assert.isOk(topExpandCommonButton);
assert.include(topExpandCommonButton!.textContent, '+9 common lines');
+ let diffRows = diffTable.querySelectorAll('.diff-row');
+ // 5 lines:
+ // FILE, LOST, the changed line plus one line of context in each direction
+ assert.equal(diffRows.length, 5);
+
topExpandCommonButton!.click();
- const diffRows = diffTable.querySelectorAll('.diff-row');
- // The first two are LOST and FILE line
- assert.equal(diffRows.length, 2 + 10 + 1 + 1);
+
+ await waitUntil(() => {
+ diffRows = diffTable.querySelectorAll<GrDiffRow>('.diff-row');
+ return diffRows.length === 14;
+ });
+ // 14 lines: The 5 above plus the 9 unchanged lines that were expanded
+ assert.equal(diffRows.length, 14);
assert.include(diffRows[2].textContent, 'unchanged 1');
assert.include(diffRows[3].textContent, 'unchanged 2');
assert.include(diffRows[4].textContent, 'unchanged 3');
@@ -722,6 +720,11 @@
dispatchStub.reset();
element.unhideLine(4, Side.LEFT);
+ await waitUntil(() => {
+ const rows = diffTable.querySelectorAll<GrDiffRow>('.diff-row');
+ return rows.length === 2 + 5 + 1 + 1 + 1;
+ });
+
const diffRows = diffTable.querySelectorAll('.diff-row');
// The first two are LOST and FILE line
// Lines 3-5 (Line 4 plus 1 context in each direction) will be expanded
@@ -745,332 +748,6 @@
});
});
- [DiffViewMode.UNIFIED, DiffViewMode.SIDE_BY_SIDE].forEach(mode => {
- suite(`mock-diff mode:${mode}`, () => {
- let builder: GrDiffBuilderSideBySide;
- let diff: DiffInfo;
- let keyLocations: KeyLocations;
-
- setup(() => {
- element.viewMode = mode;
- diff = createDiff();
- element.diff = diff;
-
- keyLocations = {left: {}, right: {}};
-
- element.prefs = {
- ...createDefaultDiffPrefs(),
- line_length: 80,
- show_tabs: true,
- tab_size: 4,
- };
- element.render(keyLocations);
- builder = element.builder as GrDiffBuilderSideBySide;
- });
-
- test('aria-labels on added line numbers', () => {
- const deltaLineNumberButton = diffTable.querySelectorAll(
- '.lineNumButton.right'
- )[5];
-
- assert.isOk(deltaLineNumberButton);
- assert.equal(
- deltaLineNumberButton.getAttribute('aria-label'),
- '5 added'
- );
- });
-
- test('aria-labels on removed line numbers', () => {
- const deltaLineNumberButton = diffTable.querySelectorAll(
- '.lineNumButton.left'
- )[10];
-
- assert.isOk(deltaLineNumberButton);
- assert.equal(
- deltaLineNumberButton.getAttribute('aria-label'),
- '10 removed'
- );
- });
-
- test('getContentByLine', () => {
- let actual: HTMLElement | null;
-
- actual = builder.getContentByLine(2, Side.LEFT);
- assert.equal(actual?.textContent, diff.content[0].ab?.[1]);
-
- actual = builder.getContentByLine(2, Side.RIGHT);
- assert.equal(actual?.textContent, diff.content[0].ab?.[1]);
-
- actual = builder.getContentByLine(5, Side.LEFT);
- assert.equal(actual?.textContent, diff.content[2].ab?.[0]);
-
- actual = builder.getContentByLine(5, Side.RIGHT);
- assert.equal(actual?.textContent, diff.content[1].b?.[0]);
- });
-
- test('getContentTdByLineEl works both with button and td', () => {
- const diffRow = diffTable.querySelectorAll('tr.diff-row')[2];
-
- const lineNumTdLeft = queryAndAssert(diffRow, 'td.lineNum.left');
- const lineNumButtonLeft = queryAndAssert(lineNumTdLeft, 'button');
- const contentTdLeft = diffRow.querySelectorAll('.content')[0];
-
- const lineNumTdRight = queryAndAssert(diffRow, 'td.lineNum.right');
- const lineNumButtonRight = queryAndAssert(lineNumTdRight, 'button');
- const contentTdRight =
- mode === DiffViewMode.SIDE_BY_SIDE
- ? diffRow.querySelectorAll('.content')[1]
- : contentTdLeft;
-
- assert.equal(
- element.getContentTdByLineEl(lineNumTdLeft),
- contentTdLeft
- );
- assert.equal(
- element.getContentTdByLineEl(lineNumButtonLeft),
- contentTdLeft
- );
- assert.equal(
- element.getContentTdByLineEl(lineNumTdRight),
- contentTdRight
- );
- assert.equal(
- element.getContentTdByLineEl(lineNumButtonRight),
- contentTdRight
- );
- });
-
- test('findLinesByRange LEFT', () => {
- const lines: GrDiffLine[] = [];
- const elems: HTMLElement[] = [];
- const start = 1;
- const end = 44;
-
- // lines 26-29 are collapsed, so minus 4
- let count = end - start + 1 - 4;
- // Lines 14+15 are part of a 'common' chunk. And we have a bug in
- // unified diff that results in not rendering these lines for the LEFT
- // side. TODO: Fix that bug!
- if (mode === DiffViewMode.UNIFIED) count -= 2;
-
- builder.findLinesByRange(start, end, Side.LEFT, lines, elems);
-
- assert.equal(lines.length, count);
- assert.equal(elems.length, count);
-
- for (let i = 0; i < count; i++) {
- assert.instanceOf(lines[i], GrDiffLine);
- assert.instanceOf(elems[i], HTMLElement);
- assert.equal(lines[i].text, elems[i].textContent);
- }
- });
-
- test('findLinesByRange RIGHT', () => {
- const lines: GrDiffLine[] = [];
- const elems: HTMLElement[] = [];
- const start = 1;
- const end = 48;
-
- // lines 26-29 are collapsed, so minus 4
- const count = end - start + 1 - 4;
-
- builder.findLinesByRange(start, end, Side.RIGHT, lines, elems);
-
- assert.equal(lines.length, count);
- assert.equal(elems.length, count);
-
- for (let i = 0; i < count; i++) {
- assert.instanceOf(lines[i], GrDiffLine);
- assert.instanceOf(elems[i], HTMLElement);
- assert.equal(lines[i].text, elems[i].textContent);
- }
- });
-
- test('renderContentByRange', () => {
- const spy = sinon.spy(builder, 'createTextEl');
- const start = 9;
- const end = 14;
- let count = end - start + 1;
- // Lines 14+15 are part of a 'common' chunk. And we have a bug in
- // unified diff that results in not rendering these lines for the LEFT
- // side. TODO: Fix that bug!
- if (mode === DiffViewMode.UNIFIED) count -= 1;
-
- builder.renderContentByRange(start, end, Side.LEFT);
-
- assert.equal(spy.callCount, count);
- spy.getCalls().forEach((call, i: number) => {
- assert.equal(call.args[1].beforeNumber, start + i);
- });
- });
-
- test('renderContentByRange non-existent elements', () => {
- const spy = sinon.spy(builder, 'createTextEl');
-
- sinon
- .stub(builder, 'getLineNumberEl')
- .returns(document.createElement('div'));
- sinon
- .stub(builder, 'findLinesByRange')
- .callsFake((_1, _2, _3, lines, elements) => {
- // Add a line and a corresponding element.
- lines?.push(new GrDiffLine(GrDiffLineType.BOTH));
- const tr = document.createElement('tr');
- const td = document.createElement('td');
- const el = document.createElement('div');
- tr.appendChild(td);
- td.appendChild(el);
- elements?.push(el);
-
- // Add 2 lines without corresponding elements.
- lines?.push(new GrDiffLine(GrDiffLineType.BOTH));
- lines?.push(new GrDiffLine(GrDiffLineType.BOTH));
- });
-
- builder.renderContentByRange(1, 10, Side.LEFT);
- // Should be called only once because only one line had a corresponding
- // element.
- assert.equal(spy.callCount, 1);
- });
-
- test('getLineNumberEl side-by-side left', () => {
- const contentEl = builder.getContentByLine(
- 5,
- Side.LEFT,
- element.diffElement as HTMLTableElement
- );
- assert.isOk(contentEl);
- const lineNumberEl = builder.getLineNumberEl(contentEl!, Side.LEFT);
- assert.isOk(lineNumberEl);
- assert.isTrue(lineNumberEl!.classList.contains('lineNum'));
- assert.isTrue(lineNumberEl!.classList.contains(Side.LEFT));
- });
-
- test('getLineNumberEl side-by-side right', () => {
- const contentEl = builder.getContentByLine(
- 5,
- Side.RIGHT,
- element.diffElement as HTMLTableElement
- );
- assert.isOk(contentEl);
- const lineNumberEl = builder.getLineNumberEl(contentEl!, Side.RIGHT);
- assert.isOk(lineNumberEl);
- assert.isTrue(lineNumberEl!.classList.contains('lineNum'));
- assert.isTrue(lineNumberEl!.classList.contains(Side.RIGHT));
- });
-
- test('getLineNumberEl unified left', async () => {
- // Re-render as unified:
- element.viewMode = 'UNIFIED_DIFF';
- element.render(keyLocations);
- builder = element.builder as GrDiffBuilderSideBySide;
-
- const contentEl = builder.getContentByLine(
- 5,
- Side.LEFT,
- element.diffElement as HTMLTableElement
- );
- assert.isOk(contentEl);
- const lineNumberEl = builder.getLineNumberEl(contentEl!, Side.LEFT);
- assert.isOk(lineNumberEl);
- assert.isTrue(lineNumberEl!.classList.contains('lineNum'));
- assert.isTrue(lineNumberEl!.classList.contains(Side.LEFT));
- });
-
- test('getLineNumberEl unified right', async () => {
- // Re-render as unified:
- element.viewMode = 'UNIFIED_DIFF';
- element.render(keyLocations);
- builder = element.builder as GrDiffBuilderSideBySide;
-
- const contentEl = builder.getContentByLine(
- 5,
- Side.RIGHT,
- element.diffElement as HTMLTableElement
- );
- assert.isOk(contentEl);
- const lineNumberEl = builder.getLineNumberEl(contentEl!, Side.RIGHT);
- assert.isOk(lineNumberEl);
- assert.isTrue(lineNumberEl!.classList.contains('lineNum'));
- assert.isTrue(lineNumberEl!.classList.contains(Side.RIGHT));
- });
-
- test('getNextContentOnSide side-by-side left', () => {
- const startElem = builder.getContentByLine(
- 5,
- Side.LEFT,
- element.diffElement as HTMLTableElement
- );
- assert.isOk(startElem);
- const expectedStartString = diff.content[2].ab?.[0];
- const expectedNextString = diff.content[2].ab?.[1];
- assert.equal(startElem!.textContent, expectedStartString);
-
- const nextElem = builder.getNextContentOnSide(startElem!, Side.LEFT);
- assert.isOk(nextElem);
- assert.equal(nextElem!.textContent, expectedNextString);
- });
-
- test('getNextContentOnSide side-by-side right', () => {
- const startElem = builder.getContentByLine(
- 5,
- Side.RIGHT,
- element.diffElement as HTMLTableElement
- );
- const expectedStartString = diff.content[1].b?.[0];
- const expectedNextString = diff.content[1].b?.[1];
- assert.isOk(startElem);
- assert.equal(startElem!.textContent, expectedStartString);
-
- const nextElem = builder.getNextContentOnSide(startElem!, Side.RIGHT);
- assert.isOk(nextElem);
- assert.equal(nextElem!.textContent, expectedNextString);
- });
-
- test('getNextContentOnSide unified left', async () => {
- // Re-render as unified:
- element.viewMode = 'UNIFIED_DIFF';
- element.render(keyLocations);
- builder = element.builder as GrDiffBuilderSideBySide;
-
- const startElem = builder.getContentByLine(
- 5,
- Side.LEFT,
- element.diffElement as HTMLTableElement
- );
- const expectedStartString = diff.content[2].ab?.[0];
- const expectedNextString = diff.content[2].ab?.[1];
- assert.isOk(startElem);
- assert.equal(startElem!.textContent, expectedStartString);
-
- const nextElem = builder.getNextContentOnSide(startElem!, Side.LEFT);
- assert.isOk(nextElem);
- assert.equal(nextElem!.textContent, expectedNextString);
- });
-
- test('getNextContentOnSide unified right', async () => {
- // Re-render as unified:
- element.viewMode = 'UNIFIED_DIFF';
- element.render(keyLocations);
- builder = element.builder as GrDiffBuilderSideBySide;
-
- const startElem = builder.getContentByLine(
- 5,
- Side.RIGHT,
- element.diffElement as HTMLTableElement
- );
- const expectedStartString = diff.content[1].b?.[0];
- const expectedNextString = diff.content[1].b?.[1];
- assert.isOk(startElem);
- assert.equal(startElem!.textContent, expectedStartString);
-
- const nextElem = builder.getNextContentOnSide(startElem!, Side.RIGHT);
- assert.isOk(nextElem);
- assert.equal(nextElem!.textContent, expectedNextString);
- });
- });
- });
-
suite('blame', () => {
let mockBlame: BlameInfo[];
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-text_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-text_test.ts
index a0e7840..3858bed 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-text_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-text_test.ts
@@ -10,6 +10,8 @@
const LINE_BREAK = '<span class="gr-diff br"></span>';
+const LINE_BREAK_WBR = '<wbr class="gr-diff"></wbr>';
+
const TAB = '<span class="" style=""></span>';
const TAB_IGNORE = ['class', 'style'];
@@ -39,6 +41,12 @@
await check('a'.repeat(20), `aaaaaaaaaa${LINE_BREAK}aaaaaaaaaa`);
});
+ test('renderText newlines 1 responsive', async () => {
+ element.isResponsive = true;
+ await check('abcdef', 'abcdef');
+ await check('a'.repeat(20), `aaaaaaaaaa${LINE_BREAK_WBR}aaaaaaaaaa`);
+ });
+
test('renderText newlines 2', async () => {
await check(
'<span class="thumbsup">👍</span>',
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-cursor/gr-diff-cursor_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-cursor/gr-diff-cursor_test.ts
index b9db280..61f8551 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-cursor/gr-diff-cursor_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-cursor/gr-diff-cursor_test.ts
@@ -46,7 +46,6 @@
diff = createDiff();
diffElement.prefs = createDefaultDiffPrefs();
- diffElement.renderPrefs = {use_lit_components: true};
diffElement.diff = diff;
await promise;
});
@@ -661,7 +660,7 @@
// Goto second last line of the first diff
cursor.moveToLineNumber(lastLine - 1, Side.RIGHT);
assert.equal(
- cursor.getTargetLineElement()!.textContent,
+ cursor.getTargetLineElement()!.textContent?.trim(),
`${lastLine - 1}`
);
@@ -669,7 +668,7 @@
cursor.moveDown();
assert.equal(getTargetDiffIndex(), 0);
assert.equal(
- cursor.getTargetLineElement()!.textContent,
+ cursor.getTargetLineElement()!.textContent?.trim(),
lastLine.toString()
);
@@ -677,7 +676,7 @@
cursor.moveDown();
assert.equal(getTargetDiffIndex(), 0);
assert.equal(
- cursor.getTargetLineElement()!.textContent,
+ cursor.getTargetLineElement()!.textContent?.trim(),
lastLine.toString()
);
@@ -686,9 +685,10 @@
await waitForEventOnce(diffElements[1], 'render');
// Now we can go down
- cursor.moveDown();
+ cursor.moveDown(); // LOST
+ cursor.moveDown(); // FILE
assert.equal(getTargetDiffIndex(), 1);
- assert.equal(cursor.getTargetLineElement()!.textContent, 'File');
+ assert.equal(cursor.getTargetLineElement()!.textContent?.trim(), 'File');
});
});
});
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-selection/gr-diff-selection_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-selection/gr-diff-selection_test.ts
index 9e3d288..f216e04 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-selection/gr-diff-selection_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-selection/gr-diff-selection_test.ts
@@ -62,7 +62,6 @@
],
};
grDiff.prefs = createDefaultDiffPrefs();
- grDiff.renderPrefs = {use_lit_components: true};
grDiff.diff = diff;
await waitForEventOnce(grDiff, 'render');
assert.isOk(element.diffTable);
diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff_test.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff_test.ts
index 4adb1cf..227ac2d 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff_test.ts
@@ -68,18 +68,8 @@
);
});
- test('a unified diff legacy', async () => {
- element.viewMode = DiffViewMode.UNIFIED;
- await testUnified();
- });
-
test('a unified diff lit', async () => {
element.viewMode = DiffViewMode.UNIFIED;
- element.renderPrefs = {...element.renderPrefs, use_lit_components: true};
- await testUnified();
- });
-
- const testUnified = async () => {
element.prefs = {...MINIMAL_PREFS};
element.diff = createDiff();
await element.updateComplete;
@@ -1343,18 +1333,9 @@
],
}
);
- };
-
- test('a normal diff legacy', async () => {
- await testNormal();
});
test('a normal diff lit', async () => {
- element.renderPrefs = {...element.renderPrefs, use_lit_components: true};
- await testNormal();
- });
-
- const testNormal = async () => {
element.prefs = {...MINIMAL_PREFS};
element.diff = createDiff();
await element.updateComplete;
@@ -3008,7 +2989,7 @@
],
}
);
- };
+ });
});
suite('selectionchange event handling', () => {
@@ -3548,7 +3529,11 @@
await element.updateComplete;
const ROWS = 48;
const FILE_ROW = 1;
- assert.equal(element.getCursorStops().length, ROWS + FILE_ROW);
+ const LOST_ROW = 1;
+ assert.equal(
+ element.getCursorStops().length,
+ ROWS + FILE_ROW + LOST_ROW
+ );
});
test('returns an additional AbortStop when still loading', async () => {
@@ -3557,8 +3542,9 @@
await element.updateComplete;
const ROWS = 48;
const FILE_ROW = 1;
+ const LOST_ROW = 1;
const actual = element.getCursorStops();
- assert.equal(actual.length, ROWS + FILE_ROW + 1);
+ assert.equal(actual.length, ROWS + FILE_ROW + LOST_ROW + 1);
assert.isTrue(actual[actual.length - 1] instanceof AbortStop);
});
});
@@ -4050,13 +4036,13 @@
b: ['Non eram nescius, Brute, cum, quae summis ingeniis '],
},
];
- function assertDiffTableWithContent() {
+ function diffTableHasContent() {
assertIsDefined(element.diffTable);
const diffTable = element.diffTable;
- assert.isTrue(diffTable.innerText.includes(content[0].a?.[0] ?? ''));
+ return diffTable.innerText.includes(content[0].a?.[0] ?? '');
}
await setupSampleDiff({content});
- assertDiffTableWithContent();
+ await waitUntil(diffTableHasContent);
element.diff = {...element.diff!};
await element.updateComplete;
// immediately cleaned up
@@ -4066,7 +4052,7 @@
element.renderDiffTable();
await element.updateComplete;
// rendered again
- assertDiffTableWithContent();
+ await waitUntil(diffTableHasContent);
});
suite('selection test', () => {
diff --git a/polygerrit-ui/app/models/change/change-model.ts b/polygerrit-ui/app/models/change/change-model.ts
index ad5b217..b6b9de7 100644
--- a/polygerrit-ui/app/models/change/change-model.ts
+++ b/polygerrit-ui/app/models/change/change-model.ts
@@ -196,6 +196,11 @@
computeLatestPatchNumWithEdit(patchsets)
);
+ public readonly latestUploader$ = select(
+ this.change$,
+ change => change?.revisions[change.current_revision]?.uploader
+ );
+
/**
* Emits the current patchset number. If the route does not define the current
* patchset num, then this selector waits for the change to be defined and
diff --git a/polygerrit-ui/app/utils/weblink-util.ts b/polygerrit-ui/app/utils/weblink-util.ts
index 1e9315c..17ad44b 100644
--- a/polygerrit-ui/app/utils/weblink-util.ts
+++ b/polygerrit-ui/app/utils/weblink-util.ts
@@ -3,51 +3,26 @@
* Copyright 2022 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
-import {CommitId, ServerInfo} from '../api/rest-api';
-
-export interface WebLink {
- name?: string;
- label: string;
- url: string;
-}
-
-export interface GeneratedWebLink {
- name?: string;
- label?: string;
- url?: string;
-}
-
-export function getPatchSetWeblink(
- commit?: CommitId,
- weblinks?: GeneratedWebLink[],
- config?: ServerInfo
-): GeneratedWebLink | undefined {
- if (!commit) return undefined;
- const name = commit.slice(0, 7);
- const weblink = getBrowseCommitWeblink(weblinks, config);
- if (!weblink?.url) return {name};
- return {name, url: weblink.url};
-}
+import {ServerInfo, WebLinkInfo} from '../api/rest-api';
// visible for testing
-export function getCodeBrowserWeblink(weblinks: GeneratedWebLink[]) {
+export function getCodeBrowserWeblink(weblinks: WebLinkInfo[]) {
// is an ordered allowed list of web link types that provide direct
// links to the commit in the url property.
- const codeBrowserLinks = ['gitiles', 'browse', 'gitweb'];
+ const codeBrowserLinks = ['gitiles', 'browse', 'gitweb', 'code search'];
for (let i = 0; i < codeBrowserLinks.length; i++) {
const weblink = weblinks.find(
- weblink => weblink.name === codeBrowserLinks[i]
+ weblink => weblink.name?.toLowerCase() === codeBrowserLinks[i]
);
if (weblink) return weblink;
}
return undefined;
}
-// visible for testing
export function getBrowseCommitWeblink(
- weblinks?: GeneratedWebLink[],
+ weblinks?: WebLinkInfo[],
config?: ServerInfo
-): GeneratedWebLink | undefined {
+): WebLinkInfo | undefined {
if (!weblinks) return undefined;
// Use primary weblink if configured and exists.
@@ -61,9 +36,9 @@
}
export function getChangeWeblinks(
- weblinks?: GeneratedWebLink[],
+ weblinks?: WebLinkInfo[],
config?: ServerInfo
-): GeneratedWebLink[] {
+): WebLinkInfo[] {
if (!weblinks?.length) return [];
const commitWeblink = getBrowseCommitWeblink(weblinks, config);
return weblinks.filter(
diff --git a/polygerrit-ui/app/utils/weblink-util_test.ts b/polygerrit-ui/app/utils/weblink-util_test.ts
index be97cfd..63842e2 100644
--- a/polygerrit-ui/app/utils/weblink-util_test.ts
+++ b/polygerrit-ui/app/utils/weblink-util_test.ts
@@ -16,17 +16,20 @@
test('getCodeBrowserWeblink', () => {
assert.deepEqual(
getCodeBrowserWeblink([
- {name: 'gitweb'},
- {name: 'gitiles'},
- {name: 'browse'},
- {name: 'test'},
+ {name: 'gitweb', url: 'http://www.test.com'},
+ {name: 'gitiles', url: 'http://www.test.com'},
+ {name: 'browse', url: 'http://www.test.com'},
+ {name: 'test', url: 'http://www.test.com'},
]),
- {name: 'gitiles'}
+ {name: 'gitiles', url: 'http://www.test.com'}
);
assert.deepEqual(
- getCodeBrowserWeblink([{name: 'gitweb'}, {name: 'test'}]),
- {name: 'gitweb'}
+ getCodeBrowserWeblink([
+ {name: 'gitweb', url: 'http://www.test.com'},
+ {name: 'test', url: 'http://www.test.com'},
+ ]),
+ {name: 'gitweb', url: 'http://www.test.com'}
);
});