Merge "Add branch actions to Projects > Branches view"

This commit is contained in:
Shawn Pearce
2014-03-25 02:21:22 +00:00
committed by Gerrit Code Review
8 changed files with 89 additions and 15 deletions

View File

@@ -168,8 +168,9 @@ on a button associated with a server side `UiAction`.
self.onAction(type, view_name, callback); self.onAction(type, view_name, callback);
---- ----
* type: `'change'`, `'revision'` or `'project'`, indicating which type * type: `'change'`, `'revision'`, `'project'`, or `'branch'`
of resource the `UiAction` was bound to in the server. indicating which type of resource the `UiAction` was bound to
in the server.
* view_name: string appearing in URLs to name the view. This is the * view_name: string appearing in URLs to name the view. This is the
second argument of the `get()`, `post()`, `put()`, and `delete()` second argument of the `get()`, `post()`, `put()`, and `delete()`
@@ -837,8 +838,8 @@ on a button associated with a server side `UiAction`.
Gerrit.onAction(type, view_name, callback); Gerrit.onAction(type, view_name, callback);
---- ----
* type: `'change'` or `'revision'`, indicating what sort of resource * type: `'change'`, `'revision'`, `'project'` or `'branch'` indicating
the `UiAction` was bound to in the server. what sort of resource the `UiAction` was bound to in the server.
* view_name: string appearing in URLs to name the view. This is the * view_name: string appearing in URLs to name the view. This is the
second argument of the `get()`, `post()`, `put()`, and `delete()` second argument of the `get()`, `post()`, `put()`, and `delete()`

View File

@@ -20,6 +20,7 @@ import com.google.gerrit.client.api.ProjectGlue;
import com.google.gerrit.client.api.RevisionGlue; import com.google.gerrit.client.api.RevisionGlue;
import com.google.gerrit.client.changes.ChangeInfo; import com.google.gerrit.client.changes.ChangeInfo;
import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo; import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.projects.BranchInfo;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.ClickHandler;
@@ -28,13 +29,19 @@ import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
public class ActionButton extends Button implements ClickHandler { public class ActionButton extends Button implements ClickHandler {
private final Project.NameKey project; private final Project.NameKey project;
private final BranchInfo branch;
private final ChangeInfo change; private final ChangeInfo change;
private final RevisionInfo revision; private final RevisionInfo revision;
private final ActionInfo action; private final ActionInfo action;
private ActionContext ctx; private ActionContext ctx;
public ActionButton(Project.NameKey project, ActionInfo action) { public ActionButton(Project.NameKey project, ActionInfo action) {
this(project, null, null, action); this(project, null, null, null, action);
}
public ActionButton(Project.NameKey project, BranchInfo branch,
ActionInfo action) {
this(project, branch, null, null, action);
} }
public ActionButton(ChangeInfo change, ActionInfo action) { public ActionButton(ChangeInfo change, ActionInfo action) {
@@ -43,11 +50,11 @@ public class ActionButton extends Button implements ClickHandler {
public ActionButton(ChangeInfo change, RevisionInfo revision, public ActionButton(ChangeInfo change, RevisionInfo revision,
ActionInfo action) { ActionInfo action) {
this(null, change, revision, action); this(null, null, change, revision, action);
} }
private ActionButton(Project.NameKey project, ChangeInfo change, private ActionButton(Project.NameKey project, BranchInfo branch,
RevisionInfo revision, ActionInfo action) { ChangeInfo change, RevisionInfo revision, ActionInfo action) {
super(new SafeHtmlBuilder() super(new SafeHtmlBuilder()
.openDiv() .openDiv()
.append(action.label()) .append(action.label())
@@ -58,6 +65,7 @@ public class ActionButton extends Button implements ClickHandler {
addClickHandler(this); addClickHandler(this);
this.project = project; this.project = project;
this.branch = branch;
this.change = change; this.change = change;
this.revision = revision; this.revision = revision;
this.action = action; this.action = action;
@@ -75,6 +83,8 @@ public class ActionButton extends Button implements ClickHandler {
RevisionGlue.onAction(change, revision, action, this); RevisionGlue.onAction(change, revision, action, this);
} else if (change != null) { } else if (change != null) {
ChangeGlue.onAction(change, action, this); ChangeGlue.onAction(change, action, this);
} else if (branch != null) {
ProjectGlue.onAction(project, branch, action, this);
} else if (project != null) { } else if (project != null) {
ProjectGlue.onAction(project, action, this); ProjectGlue.onAction(project, action, this);
} }

View File

@@ -22,6 +22,8 @@ import com.google.gerrit.client.GitwebLink;
import com.google.gerrit.client.VoidResult; import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.access.AccessMap; import com.google.gerrit.client.access.AccessMap;
import com.google.gerrit.client.access.ProjectAccessInfo; import com.google.gerrit.client.access.ProjectAccessInfo;
import com.google.gerrit.client.actions.ActionButton;
import com.google.gerrit.client.actions.ActionInfo;
import com.google.gerrit.client.projects.BranchInfo; import com.google.gerrit.client.projects.BranchInfo;
import com.google.gerrit.client.projects.ProjectApi; import com.google.gerrit.client.projects.ProjectApi;
import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.GerritCallback;
@@ -387,10 +389,18 @@ public class ProjectBranchesScreen extends ProjectScreen {
table.setText(row, 3, ""); table.setText(row, 3, "");
} }
FlowPanel actionsPanel = new FlowPanel();
if (c != null) { if (c != null) {
table.setWidget(row, 4, new Anchor(c.getLinkName(), false, actionsPanel.add(new Anchor(c.getLinkName(), false,
c.toBranch(new Branch.NameKey(getProjectKey(), k.ref())))); c.toBranch(new Branch.NameKey(getProjectKey(), k.ref()))));
} }
if (k.actions() != null) {
k.actions().copyKeysIntoChildren("id");
for (ActionInfo a : Natives.asList(k.actions().values())) {
actionsPanel.add(new ActionButton(getProjectKey(), k, a));
}
}
table.setWidget(row, 4, actionsPanel);
final FlexCellFormatter fmt = table.getFlexCellFormatter(); final FlexCellFormatter fmt = table.getFlexCellFormatter();
String iconCellStyle = Gerrit.RESOURCES.css().iconCell(); String iconCellStyle = Gerrit.RESOURCES.css().iconCell();

View File

@@ -18,6 +18,7 @@ import com.google.gerrit.client.actions.ActionButton;
import com.google.gerrit.client.actions.ActionInfo; import com.google.gerrit.client.actions.ActionInfo;
import com.google.gerrit.client.changes.ChangeInfo; import com.google.gerrit.client.changes.ChangeInfo;
import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo; import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.projects.BranchInfo;
import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeString; import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.client.rpc.RestApi;
@@ -136,6 +137,7 @@ public class ActionContext extends JavaScriptObject {
final native void set(ActionInfo a) /*-{ this.action=a; }-*/; final native void set(ActionInfo a) /*-{ this.action=a; }-*/;
final native void set(ChangeInfo c) /*-{ this.change=c; }-*/; final native void set(ChangeInfo c) /*-{ this.change=c; }-*/;
final native void set(Project.NameKey p) /*-{ this.project=p; }-*/; final native void set(Project.NameKey p) /*-{ this.project=p; }-*/;
final native void set(BranchInfo b) /*-{ this.branch=b }-*/;
final native void set(RevisionInfo r) /*-{ this.revision=r; }-*/; final native void set(RevisionInfo r) /*-{ this.revision=r; }-*/;
final native void button(ActionButton b) /*-{ this._b=b; }-*/; final native void button(ActionButton b) /*-{ this._b=b; }-*/;

View File

@@ -43,6 +43,7 @@ public class ApiGlue {
change_actions: {}, change_actions: {},
revision_actions: {}, revision_actions: {},
project_actions: {}, project_actions: {},
branch_actions: {},
getPluginName: @com.google.gerrit.client.api.ApiGlue::getPluginName(), getPluginName: @com.google.gerrit.client.api.ApiGlue::getPluginName(),
injectCss: @com.google.gwt.dom.client.StyleInjector::inject(Ljava/lang/String;), injectCss: @com.google.gwt.dom.client.StyleInjector::inject(Ljava/lang/String;),
@@ -71,6 +72,7 @@ public class ApiGlue {
if ('change' == t) this.change_actions[i]=c; if ('change' == t) this.change_actions[i]=c;
else if ('revision' == t) this.revision_actions[i]=c; else if ('revision' == t) this.revision_actions[i]=c;
else if ('project' == t) this.project_actions[i]=c; else if ('project' == t) this.project_actions[i]=c;
else if ('branch' == t) this.branch_actions[i]=c;
else if ('screen' == t) _screen(p,t,c); else if ('screen' == t) _screen(p,t,c);
}, },
screen: function(r,c){this._screen(this.getPluginName(),r,c)}, screen: function(r,c){this._screen(this.getPluginName(),r,c)},

View File

@@ -16,18 +16,40 @@ package com.google.gerrit.client.api;
import com.google.gerrit.client.actions.ActionButton; import com.google.gerrit.client.actions.ActionButton;
import com.google.gerrit.client.actions.ActionInfo; import com.google.gerrit.client.actions.ActionInfo;
import com.google.gerrit.client.projects.BranchInfo;
import com.google.gerrit.client.projects.ProjectApi; import com.google.gerrit.client.projects.ProjectApi;
import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JavaScriptObject;
public class ProjectGlue { public class ProjectGlue {
public static void onAction(
Project.NameKey project,
BranchInfo branch,
ActionInfo action,
ActionButton button) {
RestApi api = ProjectApi.project(project)
.view("branches").id(branch.ref())
.view(action.id());
JavaScriptObject f = branchAction(action.id());
if (f != null) {
ActionContext c = ActionContext.create(api);
c.set(action);
c.set(project);
c.set(branch);
c.button(button);
ApiGlue.invoke(f, c);
} else {
DefaultActions.invoke(project, action, api);
}
}
public static void onAction( public static void onAction(
Project.NameKey project, Project.NameKey project,
ActionInfo action, ActionInfo action,
ActionButton button) { ActionButton button) {
RestApi api = ProjectApi.project(project).view(action.id()); RestApi api = ProjectApi.project(project).view(action.id());
JavaScriptObject f = get(action.id()); JavaScriptObject f = projectAction(action.id());
if (f != null) { if (f != null) {
ActionContext c = ActionContext.create(api); ActionContext c = ActionContext.create(api);
c.set(action); c.set(action);
@@ -39,10 +61,14 @@ public class ProjectGlue {
} }
} }
private static final native JavaScriptObject get(String id) /*-{ private static final native JavaScriptObject projectAction(String id) /*-{
return $wnd.Gerrit.project_actions[id]; return $wnd.Gerrit.project_actions[id];
}-*/; }-*/;
private static final native JavaScriptObject branchAction(String id) /*-{
return $wnd.Gerrit.branch_actions[id];
}-*/;
private ProjectGlue() { private ProjectGlue() {
} }
} }

View File

@@ -14,6 +14,8 @@
package com.google.gerrit.client.projects; package com.google.gerrit.client.projects;
import com.google.gerrit.client.actions.ActionInfo;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.reviewdb.client.Branch; import com.google.gerrit.reviewdb.client.Branch;
import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JavaScriptObject;
@@ -27,6 +29,7 @@ public class BranchInfo extends JavaScriptObject {
public final native String ref() /*-{ return this.ref; }-*/; public final native String ref() /*-{ return this.ref; }-*/;
public final native String revision() /*-{ return this.revision; }-*/; public final native String revision() /*-{ return this.revision; }-*/;
public final native boolean canDelete() /*-{ return this['can_delete'] ? true : false; }-*/; public final native boolean canDelete() /*-{ return this['can_delete'] ? true : false; }-*/;
public final native NativeMap<ActionInfo> actions() /*-{ return this.actions }-*/;
protected BranchInfo() { protected BranchInfo() {
} }

View File

@@ -16,11 +16,17 @@ package com.google.gerrit.server.project;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.gerrit.extensions.common.ActionInfo;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestReadView; import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.extensions.webui.UiActions;
import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.util.Providers;
import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
@@ -34,14 +40,17 @@ import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
public class ListBranches implements RestReadView<ProjectResource> { public class ListBranches implements RestReadView<ProjectResource> {
private final GitRepositoryManager repoManager; private final GitRepositoryManager repoManager;
private final DynamicMap<RestView<BranchResource>> branchViews;
@Inject @Inject
public ListBranches(GitRepositoryManager repoManager) { public ListBranches(GitRepositoryManager repoManager,
DynamicMap<RestView<BranchResource>> branchViews) {
this.repoManager = repoManager; this.repoManager = repoManager;
this.branchViews = branchViews;
} }
@Override @Override
@@ -136,17 +145,28 @@ public class ListBranches implements RestReadView<ProjectResource> {
return branches; return branches;
} }
private static BranchInfo createBranchInfo(Ref ref, RefControl refControl, private BranchInfo createBranchInfo(Ref ref, RefControl refControl,
Set<String> targets) { Set<String> targets) {
return new BranchInfo(ref.getName(), BranchInfo info = new BranchInfo(ref.getName(),
ref.getObjectId() != null ? ref.getObjectId().name() : null, ref.getObjectId() != null ? ref.getObjectId().name() : null,
!targets.contains(ref.getName()) && refControl.canDelete()); !targets.contains(ref.getName()) && refControl.canDelete());
for (UiAction.Description d : UiActions.from(
branchViews,
new BranchResource(refControl.getProjectControl(), info),
Providers.of(refControl.getCurrentUser()))) {
if (info.actions == null) {
info.actions = new TreeMap<>();
}
info.actions.put(d.getId(), new ActionInfo(d));
}
return info;
} }
public static class BranchInfo { public static class BranchInfo {
public String ref; public String ref;
public String revision; public String revision;
public Boolean canDelete; public Boolean canDelete;
public Map<String, ActionInfo> actions;
public BranchInfo(String ref, String revision, boolean canDelete) { public BranchInfo(String ref, String revision, boolean canDelete) {
this.ref = ref; this.ref = ref;