Merge branch 'main' of https://code.onedev.io/onedev/server into main

This commit is contained in:
Robin Shen 2022-02-26 22:11:19 +08:00
commit de2bf2bc20
15 changed files with 133 additions and 58 deletions

View File

@ -0,0 +1,26 @@
package io.onedev.server.web.behavior;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
public abstract class CtrlAwareOnClickAjaxBehavior extends AbstractDefaultAjaxBehavior {
private static final long serialVersionUID = 1L;
@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
String script = String.format(""
+ "$('#%s').click(function(e) {\n"
+ " if (!e.ctrlKey && !e.metaKey) {\n"
+ " %s\n"
+ " return false;\n"
+ " }\n"
+ "});",
component.getMarkupId(), getCallbackScript());
response.render(OnDomReadyHeaderItem.forScript(script));
}
}

View File

@ -800,7 +800,7 @@ public abstract class BuildListPanel extends Panel {
Build build = rowModel.getObject();
Long buildId = build.getId();
AjaxLink<Void> link = new ActionablePageLink<Void>("link",
WebMarkupContainer link = new ActionablePageLink("link",
BuildDashboardPage.class, BuildDashboardPage.paramsOf(build)) {
@Override

View File

@ -489,7 +489,7 @@ public abstract class CodeCommentListPanel extends Panel {
CodeComment comment = rowModel.getObject();
WebMarkupContainer link;
if (!comment.isValid()) {
link = new ActionablePageLink<Void>("link", InvalidCodeCommentPage.class,
link = new ActionablePageLink("link", InvalidCodeCommentPage.class,
InvalidCodeCommentPage.paramsOf(comment)) {
@Override

View File

@ -1138,8 +1138,8 @@ public abstract class IssueListPanel extends Panel {
else
label = issue.getProject() + "#" + issue.getNumber();
ActionablePageLink<Void> numberLink;
fragment.add(numberLink = new ActionablePageLink<Void>("number",
ActionablePageLink numberLink;
fragment.add(numberLink = new ActionablePageLink("number",
IssueActivitiesPage.class, IssueActivitiesPage.paramsOf(issue)) {
@Override
@ -1167,9 +1167,11 @@ public abstract class IssueListPanel extends Panel {
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
String script = String.format(""
+ "$('#%s a:not(.embedded-reference)').click(function() {"
+ " $('#%s').click();"
+ " return false;"
+ "$('#%s a:not(.embedded-reference)').click(function(e) {\n"
+ " if (!e.ctrlKey && !e.metaKey) {\n"
+ " $('#%s').click();\n"
+ " return false;\n"
+ " }\n"
+ "});",
getMarkupId(), numberLink.getMarkupId());
response.render(OnDomReadyHeaderItem.forScript(script));

View File

@ -2,28 +2,46 @@ package io.onedev.server.web.component.link;
import org.apache.wicket.Page;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import io.onedev.server.web.behavior.CtrlAwareOnClickAjaxBehavior;
@SuppressWarnings("serial")
public abstract class ActionablePageLink<T> extends AjaxLink<T> {
public abstract class ActionablePageLink extends AbstractLink {
private final Class<? extends Page> pageClass;
private PageParameters params;
public ActionablePageLink(String id, Class<? extends Page> pageClass, PageParameters params) {
super(id);
this.pageClass = pageClass;
this.params = params;
}
@Override
protected void onInitialize() {
super.onInitialize();
add(new CtrlAwareOnClickAjaxBehavior() {
@Override
protected void respond(AjaxRequestTarget target) {
onClick(target);
}
});
setOutputMarkupId(true);
}
public PageParameters getPageParams() {
return params;
}
public Class<? extends Page> getPageClass() {
return pageClass;
}
@ -34,11 +52,11 @@ public abstract class ActionablePageLink<T> extends AjaxLink<T> {
tag.put("href", RequestCycle.get().urlFor(pageClass, params));
}
@Override
public void onClick(AjaxRequestTarget target) {
protected void onClick(AjaxRequestTarget target) {
doBeforeNav(target);
setResponsePage(pageClass, params);
}
protected abstract void doBeforeNav(AjaxRequestTarget target);
}

View File

@ -1040,7 +1040,7 @@ public class ProjectListPanel extends Panel {
Fragment fragment = new Fragment(componentId, "projectFrag", ProjectListPanel.this);
Project project = rowModel.getObject();
ActionablePageLink<Void> pathLink = new ActionablePageLink<Void>("path",
ActionablePageLink pathLink = new ActionablePageLink("path",
ProjectDashboardPage.class, ProjectDashboardPage.paramsOf(project)) {
@Override

View File

@ -694,8 +694,8 @@ public abstract class PullRequestListPanel extends Panel {
else
label = "#" + request.getNumber();
ActionablePageLink<Void> numberLink;
fragment.add(numberLink = new ActionablePageLink<Void>("number",
ActionablePageLink numberLink;
fragment.add(numberLink = new ActionablePageLink("number",
PullRequestActivitiesPage.class, PullRequestActivitiesPage.paramsOf(request)) {
@Override
@ -726,9 +726,11 @@ public abstract class PullRequestListPanel extends Panel {
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
String script = String.format(""
+ "$('#%s a:not(.embedded-reference)').click(function() {"
+ " $('#%s').click();"
+ " return false;"
+ "$('#%s a:not(.embedded-reference)').click(function(e) {\n"
+ " if (!e.ctrlKey && !e.metaKey) {\n"
+ " $('#%s').click();\n"
+ " return false;\n"
+ " }\n"
+ "});",
getMarkupId(), numberLink.getMarkupId());
response.render(OnDomReadyHeaderItem.forScript(script));

View File

@ -161,7 +161,7 @@ public class GroupListPage extends AdministrationPage {
public void populateItem(Item<ICellPopulator<Group>> cellItem, String componentId, IModel<Group> rowModel) {
Fragment fragment = new Fragment(componentId, "nameFrag", GroupListPage.this);
Group group = rowModel.getObject();
WebMarkupContainer link = new ActionablePageLink<Void>("link",
WebMarkupContainer link = new ActionablePageLink("link",
GroupProfilePage.class, GroupProfilePage.paramsOf(group)) {
@Override

View File

@ -159,7 +159,7 @@ public class RoleListPage extends AdministrationPage {
Role role = rowModel.getObject();
WebMarkupContainer link = new ActionablePageLink<Void>("link",
WebMarkupContainer link = new ActionablePageLink("link",
RoleDetailPage.class, RoleDetailPage.paramsOf(role)) {
@Override

View File

@ -171,7 +171,7 @@ public class UserListPage extends AdministrationPage {
IModel<User> rowModel) {
User user = rowModel.getObject();
Fragment fragment = new Fragment(componentId, "nameFrag", UserListPage.this);
WebMarkupContainer link = new ActionablePageLink<Void>("link", UserProfilePage.class, UserProfilePage.paramsOf(user)) {
WebMarkupContainer link = new ActionablePageLink("link", UserProfilePage.class, UserProfilePage.paramsOf(user)) {
@Override
protected void doBeforeNav(AjaxRequestTarget target) {

View File

@ -12,7 +12,6 @@ import org.apache.wicket.ajax.AjaxChannel.Type;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.event.Broadcast;
import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
@ -44,11 +43,12 @@ import io.onedev.server.git.BlobIdent;
import io.onedev.server.git.BlobIdentFilter;
import io.onedev.server.git.GitUtils;
import io.onedev.server.web.ajaxlistener.ConfirmLeaveListener;
import io.onedev.server.web.ajaxlistener.TrackViewStateListener;
import io.onedev.server.web.behavior.CtrlAwareOnClickAjaxBehavior;
import io.onedev.server.web.component.blob.BlobIcon;
import io.onedev.server.web.component.floating.AlignPlacement;
import io.onedev.server.web.component.floating.FloatingPanel;
import io.onedev.server.web.component.link.DropdownLink;
import io.onedev.server.web.component.link.ViewStateAwareAjaxLink;
import io.onedev.server.web.page.project.blob.ProjectBlobPage;
import io.onedev.server.web.page.project.blob.render.BlobRenderContext;
import io.onedev.server.web.page.project.blob.render.BlobRenderContext.Mode;
@ -103,18 +103,7 @@ public class BlobNavigator extends Panel {
@Override
protected void populateItem(final ListItem<BlobIdent> item) {
final BlobIdent blobIdent = item.getModelObject();
AjaxLink<Void> link = new ViewStateAwareAjaxLink<Void>("link") {
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new ConfirmLeaveListener());
}
@Override
public void onClick(AjaxRequestTarget target) {
context.onSelect(target, blobIdent, null);
}
WebMarkupContainer link = new WebMarkupContainer("link") {
@Override
protected void onComponentTag(ComponentTag tag) {
@ -125,6 +114,24 @@ public class BlobNavigator extends Panel {
}
};
link.add(new CtrlAwareOnClickAjaxBehavior() {
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.setPreventDefault(true);
attributes.getAjaxCallListeners().add(new ConfirmLeaveListener());
attributes.getAjaxCallListeners().add(new TrackViewStateListener(false));
}
@Override
protected void respond(AjaxRequestTarget target) {
context.onSelect(target, blobIdent, null);
}
});
link.setEnabled(!context.getBlobIdent().isTree() || item.getIndex() != getViewSize()-1);
if (blobIdent.path != null) {
@ -199,19 +206,7 @@ public class BlobNavigator extends Panel {
BlobIdent blobIdent = model.getObject();
Fragment fragment = new Fragment(id, "treeNodeFrag", BlobNavigator.this);
AjaxLink<Void> link = new ViewStateAwareAjaxLink<Void>("link") {
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new ConfirmLeaveListener());
}
@Override
public void onClick(AjaxRequestTarget target) {
context.onSelect(target, model.getObject(), null);
dropdown.close();
}
WebMarkupContainer link = new WebMarkupContainer("link") {
@Override
protected void onComponentTag(ComponentTag tag) {
@ -224,6 +219,24 @@ public class BlobNavigator extends Panel {
};
link.add(new CtrlAwareOnClickAjaxBehavior() {
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.setPreventDefault(true);
attributes.getAjaxCallListeners().add(new ConfirmLeaveListener());
attributes.getAjaxCallListeners().add(new TrackViewStateListener(false));
}
@Override
protected void respond(AjaxRequestTarget target) {
context.onSelect(target, model.getObject(), null);
dropdown.close();
}
});
link.add(new BlobIcon("icon", model));
if (blobIdent.path.indexOf('/') != -1)

View File

@ -9,6 +9,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.attributes.CallbackParameter;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.ComponentTag;
@ -41,7 +42,9 @@ import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.git.Blob;
import io.onedev.server.git.BlobIdent;
import io.onedev.server.security.SecurityUtils;
import io.onedev.server.web.ajaxlistener.TrackViewStateListener;
import io.onedev.server.web.behavior.AbstractPostAjaxBehavior;
import io.onedev.server.web.behavior.CtrlAwareOnClickAjaxBehavior;
import io.onedev.server.web.component.blob.BlobIcon;
import io.onedev.server.web.component.link.ViewStateAwareAjaxLink;
import io.onedev.server.web.component.markdown.MarkdownViewer;
@ -191,7 +194,7 @@ public class FolderViewPanel extends Panel {
protected void populateItem(ListItem<BlobIdent> item) {
BlobIdent blobIdent = item.getModelObject();
AjaxLink<Void> pathLink = new ViewStateAwareAjaxLink<Void>("pathLink") {
WebMarkupContainer pathLink = new WebMarkupContainer("pathLink") {
@Override
protected void onComponentTag(ComponentTag tag) {
@ -202,12 +205,23 @@ public class FolderViewPanel extends Panel {
tag.put("href", urlFor(ProjectBlobPage.class, params));
}
};
pathLink.add(new CtrlAwareOnClickAjaxBehavior() {
@Override
public void onClick(AjaxRequestTarget target) {
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.setPreventDefault(true);
attributes.getAjaxCallListeners().add(new TrackViewStateListener(false));
}
@Override
protected void respond(AjaxRequestTarget target) {
context.onSelect(target, blobIdent, null);
}
};
});
pathLink.add(new BlobIcon("icon", Model.of(blobIdent)));

View File

@ -244,8 +244,8 @@ abstract class BoardCardPanel extends GenericPanel<Issue> {
});
ActionablePageLink<Void> numberLink;
fragment.add(numberLink = new ActionablePageLink<Void>("number",
ActionablePageLink numberLink;
fragment.add(numberLink = new ActionablePageLink("number",
IssueActivitiesPage.class, IssueActivitiesPage.paramsOf(issue)) {
@Override

View File

@ -190,7 +190,7 @@ public class MilestoneListPage extends ProjectPage {
IModel<Milestone> rowModel) {
Milestone milestone = rowModel.getObject();
Fragment fragment = new Fragment(componentId, "nameFrag", MilestoneListPage.this);
WebMarkupContainer link = new ActionablePageLink<Void>("link", MilestoneIssuesPage.class,
WebMarkupContainer link = new ActionablePageLink("link", MilestoneIssuesPage.class,
MilestoneIssuesPage.paramsOf(getProject(), milestone, null)) {
@Override

View File

@ -2,7 +2,7 @@
<div class="pull-request-detail card m-2 m-sm-5">
<div wicket:id="requestHeader" class="card-header align-items-center justify-content-start flex-nowrap">
<div class="d-flex align-items-center flex-grow-1">
<div wicket:id="title" class="card-title mr-3"></div>
<div class="card-title mr-3"><span wicket:id="title"></span></div>
<a wicket:id="edit" title="Edit title" class="btn btn-xs btn-icon btn-light btn-hover-primary edit mr-3"><wicket:svg href="edit" class="icon"></wicket:svg></a>
<form wicket:id="editForm" class="form flex-grow-1 d-flex align-items-center">
<div class="clearable-wrapper mr-3 flex-grow-1">