Add support for UiActions on Project Info Screen

Bug: issue 349
Change-Id: Ia29d08684aaf421fa0a16dd875af36667980fe2e
This commit is contained in:
David Ostrovsky 2013-08-30 08:09:53 +02:00 committed by David Pursehouse
parent 8ab4d6a845
commit 9e8b2fb8d1
17 changed files with 210 additions and 21 deletions

View File

@ -141,8 +141,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'` or `'project'`, indicating which type
the `UiAction` was bound to in the server. 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()`
@ -385,6 +385,11 @@ object instance describing the revision. Available fields of the
RevisionInfo may vary based on the options used by the UI when it RevisionInfo may vary based on the options used by the UI when it
loaded the change. loaded the change.
[[context_project]]
context.project
~~~~~~~~~~~~~~~
When the action is invoked on a specific project,
the name of the project.
Action Context HTML Helpers Action Context HTML Helpers
--------------------------- ---------------------------

View File

@ -461,7 +461,15 @@ read access to `refs/meta/config`.
}, },
"submit_type": "MERGE_IF_NECESSARY", "submit_type": "MERGE_IF_NECESSARY",
"state": "ACTIVE", "state": "ACTIVE",
"commentlinks": {} "commentlinks": {},
"actions": {
"cookbook~hello-project": {
"method": "POST",
"label": "Say hello",
"title": "Say hello in different languages",
"enabled": true
}
}
} }
---- ----
@ -1184,6 +1192,10 @@ commentlink section] of `gerrit.config`.
|`theme` |optional| |`theme` |optional|
The theme that is configured for the project as a link:#theme-info[ The theme that is configured for the project as a link:#theme-info[
ThemeInfo] entity. ThemeInfo] entity.
|`actions` |optional|
Actions the caller might be able to perform on this project. The
information is a map of view names to
link:rest-api-changes.html#action-info[ActionInfo] entities.
|========================================= |=========================================
[[config-input]] [[config-input]]

View File

@ -182,6 +182,7 @@ public interface GerritCss extends CssResource {
String patchSizeCell(); String patchSizeCell();
String pluginsTable(); String pluginsTable();
String posscore(); String posscore();
String projectActions();
String projectAdminLabelRangeLine(); String projectAdminLabelRangeLine();
String projectAdminLabelValue(); String projectAdminLabelValue();
String projectFilterLabel(); String projectFilterLabel();

View File

@ -16,25 +16,38 @@ package com.google.gerrit.client.actions;
import com.google.gerrit.client.api.ActionContext; import com.google.gerrit.client.api.ActionContext;
import com.google.gerrit.client.api.ChangeGlue; import com.google.gerrit.client.api.ChangeGlue;
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.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;
import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Button;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder; 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 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) {
this(project, null, null, action);
}
public ActionButton(ChangeInfo change, ActionInfo action) { public ActionButton(ChangeInfo change, ActionInfo action) {
this(change, null, action); this(change, null, action);
} }
public ActionButton(ChangeInfo change, RevisionInfo revision, ActionInfo action) { public ActionButton(ChangeInfo change, RevisionInfo revision,
ActionInfo action) {
this(null, change, revision, action);
}
private ActionButton(Project.NameKey project, ChangeInfo change,
RevisionInfo revision, ActionInfo action) {
super(new SafeHtmlBuilder() super(new SafeHtmlBuilder()
.openDiv() .openDiv()
.append(action.label()) .append(action.label())
@ -44,6 +57,7 @@ public class ActionButton extends Button implements ClickHandler {
setEnabled(action.enabled()); setEnabled(action.enabled());
addClickHandler(this); addClickHandler(this);
this.project = project;
this.change = change; this.change = change;
this.revision = revision; this.revision = revision;
this.action = action; this.action = action;
@ -59,8 +73,10 @@ public class ActionButton extends Button implements ClickHandler {
if (revision != null) { if (revision != null) {
RevisionGlue.onAction(change, revision, action, this); RevisionGlue.onAction(change, revision, action, this);
} else { } else if (change != null) {
ChangeGlue.onAction(change, action, this); ChangeGlue.onAction(change, action, this);
} else if (project != null) {
ProjectGlue.onAction(project, action, this);
} }
} }

View File

@ -56,6 +56,8 @@ public interface AdminConstants extends Constants {
String headingOwner(); String headingOwner();
String headingDescription(); String headingDescription();
String headingProjectOptions(); String headingProjectOptions();
String headingProjectCommands();
String headingCommands();
String headingMembers(); String headingMembers();
String headingIncludedGroups(); String headingIncludedGroups();
String noMembersInfo(); String noMembersInfo();

View File

@ -37,6 +37,8 @@ headingGroupUUID = Group UUID
headingOwner = Owners headingOwner = Owners
headingDescription = Description headingDescription = Description
headingProjectOptions = Project Options headingProjectOptions = Project Options
headingProjectCommands = Project Commands
headingCommands = Commands
headingMembers = Members headingMembers = Members
headingIncludedGroups = Included Groups headingIncludedGroups = Included Groups
noMembersInfo = Group Members can only be viewed for Gerrit internal groups. For external groups and Gerrit system groups the members cannot be displayed. noMembersInfo = Group Members can only be viewed for Gerrit internal groups. For external groups and Gerrit system groups the members cannot be displayed.

View File

@ -17,12 +17,16 @@ package com.google.gerrit.client.admin;
import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.Gerrit;
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.change.Resources;
import com.google.gerrit.client.download.DownloadPanel; import com.google.gerrit.client.download.DownloadPanel;
import com.google.gerrit.client.projects.ConfigInfo; import com.google.gerrit.client.projects.ConfigInfo;
import com.google.gerrit.client.projects.ConfigInfo.InheritedBooleanInfo; import com.google.gerrit.client.projects.ConfigInfo.InheritedBooleanInfo;
import com.google.gerrit.client.projects.ProjectApi; import com.google.gerrit.client.projects.ProjectApi;
import com.google.gerrit.client.rpc.CallbackGroup; import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.OnEditEnabler; import com.google.gerrit.client.ui.OnEditEnabler;
import com.google.gerrit.client.ui.SmallHeading; import com.google.gerrit.client.ui.SmallHeading;
@ -36,6 +40,7 @@ import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.ListBox;
@ -49,6 +54,7 @@ public class ProjectInfoScreen extends ProjectScreen {
private Project.NameKey parent; private Project.NameKey parent;
private LabeledWidgetsGrid grid; private LabeledWidgetsGrid grid;
private LabeledWidgetsGrid actionsGrid;
// Section: Project Options // Section: Project Options
private ListBox requireChangeID; private ListBox requireChangeID;
@ -75,6 +81,7 @@ public class ProjectInfoScreen extends ProjectScreen {
protected void onInitUI() { protected void onInitUI() {
super.onInitUI(); super.onInitUI();
Resources.I.style().ensureInjected();
saveProject = new Button(Util.C.buttonSaveChanges()); saveProject = new Button(Util.C.buttonSaveChanges());
saveProject.addClickHandler(new ClickHandler() { saveProject.addClickHandler(new ClickHandler() {
@Override @Override
@ -87,10 +94,12 @@ public class ProjectInfoScreen extends ProjectScreen {
initDescription(); initDescription();
grid = new LabeledWidgetsGrid(); grid = new LabeledWidgetsGrid();
actionsGrid = new LabeledWidgetsGrid();
initProjectOptions(); initProjectOptions();
initAgreements(); initAgreements();
add(grid); add(grid);
add(saveProject); add(saveProject);
add(actionsGrid);
} }
@Override @Override
@ -321,6 +330,24 @@ public class ProjectInfoScreen extends ProjectScreen {
} }
saveProject.setEnabled(false); saveProject.setEnabled(false);
initProjectActions(result);
}
private void initProjectActions(ConfigInfo info) {
NativeMap<ActionInfo> actions = info.actions();
if (actions == null || actions.isEmpty()) {
return;
}
actions.copyKeysIntoChildren("id");
actionsGrid.addHeader(new SmallHeading(Util.C.headingProjectCommands()));
FlowPanel actionsPanel = new FlowPanel();
actionsPanel.setStyleName(Gerrit.RESOURCES.css().projectActions());
actionsPanel.setVisible(true);
actionsGrid.add(Util.C.headingCommands(), actionsPanel);
for (String id : actions.keySet()) {
actionsPanel.add(new ActionButton(getProjectKey(),
actions.get(id)));
}
} }
private void doSave() { private void doSave() {

View File

@ -21,6 +21,7 @@ import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo;
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;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JavaScriptObject;
public class ActionContext extends JavaScriptObject { public class ActionContext extends JavaScriptObject {
@ -117,6 +118,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(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

@ -42,11 +42,13 @@ public class ApiGlue {
change_actions: {}, change_actions: {},
revision_actions: {}, revision_actions: {},
project_actions: {},
onAction: function (t,n,c){this._onAction(this.getPluginName(),t,n,c)}, onAction: function (t,n,c){this._onAction(this.getPluginName(),t,n,c)},
_onAction: function (p,t,n,c) { _onAction: function (p,t,n,c) {
var i = p+'~'+n; var i = p+'~'+n;
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;
}, },
url: function (d) { url: function (d) {

View File

@ -41,6 +41,27 @@ class DefaultActions {
Gerrit.display(PageLinks.toChange(id)); Gerrit.display(PageLinks.toChange(id));
} }
}; };
invoke(action, api, cb);
}
static void invokeProjectAction(ActionInfo action, RestApi api) {
AsyncCallback<JavaScriptObject> cb = new GerritCallback<JavaScriptObject>() {
@Override
public void onSuccess(JavaScriptObject msg) {
if (NativeString.is(msg)) {
NativeString str = (NativeString) msg;
if (!str.asString().isEmpty()) {
Window.alert(str.asString());
}
}
Gerrit.display(PageLinks.ADMIN_PROJECTS);
}
};
invoke(action, api, cb);
}
private static void invoke(ActionInfo action, RestApi api,
AsyncCallback<JavaScriptObject> cb) {
if ("PUT".equalsIgnoreCase(action.method())) { if ("PUT".equalsIgnoreCase(action.method())) {
api.put(JavaScriptObject.createObject(), cb); api.put(JavaScriptObject.createObject(), cb);
} else if ("DELETE".equalsIgnoreCase(action.method())) { } else if ("DELETE".equalsIgnoreCase(action.method())) {

View File

@ -0,0 +1,48 @@
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.client.api;
import com.google.gerrit.client.actions.ActionButton;
import com.google.gerrit.client.actions.ActionInfo;
import com.google.gerrit.client.projects.ProjectApi;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.JavaScriptObject;
public class ProjectGlue {
public static void onAction(
Project.NameKey project,
ActionInfo action,
ActionButton button) {
RestApi api = ProjectApi.project(project).view(action.id());
JavaScriptObject f = get(action.id());
if (f != null) {
ActionContext c = ActionContext.create(api);
c.set(action);
c.set(project);
c.button(button);
ApiGlue.invoke(f, c);
} else {
DefaultActions.invokeProjectAction(action, api);
}
}
private static final native JavaScriptObject get(String id) /*-{
return $wnd.Gerrit.project_actions[id];
}-*/;
private ProjectGlue() {
}
}

View File

@ -1383,7 +1383,9 @@ a:hover.downloadLink {
font-family: mono-font; font-family: mono-font;
font-size: small; font-size: small;
} }
.projectActions {
margin-bottom: 10px;
}
/** PublishCommentsScreen **/ /** PublishCommentsScreen **/
.publishCommentsScreen .smallHeading { .publishCommentsScreen .smallHeading {

View File

@ -14,6 +14,7 @@
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.client.rpc.NativeMap;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.Project.InheritableBoolean; import com.google.gerrit.reviewdb.client.Project.InheritableBoolean;
@ -28,6 +29,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ConfigInfo extends JavaScriptObject { public class ConfigInfo extends JavaScriptObject {
public final native String description() public final native String description()
/*-{ return this.description }-*/; /*-{ return this.description }-*/;
@ -46,6 +48,10 @@ public class ConfigInfo extends JavaScriptObject {
public final SubmitType submit_type() { public final SubmitType submit_type() {
return SubmitType.valueOf(submit_typeRaw()); return SubmitType.valueOf(submit_typeRaw());
} }
public final native NativeMap<ActionInfo> actions()
/*-{ return this.actions; }-*/;
private final native String submit_typeRaw() private final native String submit_typeRaw()
/*-{ return this.submit_type }-*/; /*-{ return this.submit_type }-*/;

View File

@ -127,7 +127,7 @@ public class ProjectApi {
} }
} }
private static RestApi project(Project.NameKey name) { public static RestApi project(Project.NameKey name) {
return new RestApi("/projects/").id(name.get()); return new RestApi("/projects/").id(name.get());
} }

View File

@ -17,10 +17,17 @@ package com.google.gerrit.server.project;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.Project.InheritableBoolean; import com.google.gerrit.reviewdb.client.Project.InheritableBoolean;
import com.google.gerrit.reviewdb.client.Project.SubmitType; import com.google.gerrit.reviewdb.client.Project.SubmitType;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.actions.ActionInfo;
import com.google.gerrit.server.extensions.webui.UiActions;
import com.google.gerrit.server.git.TransferConfig; import com.google.gerrit.server.git.TransferConfig;
import com.google.inject.Provider;
import java.util.Map; import java.util.Map;
@ -35,12 +42,17 @@ public class ConfigInfo {
public MaxObjectSizeLimitInfo maxObjectSizeLimit; public MaxObjectSizeLimitInfo maxObjectSizeLimit;
public SubmitType submitType; public SubmitType submitType;
public Project.State state; public Project.State state;
public Map<String, ActionInfo> actions;
public Map<String, CommentLinkInfo> commentlinks; public Map<String, CommentLinkInfo> commentlinks;
public ThemeInfo theme; public ThemeInfo theme;
public ConfigInfo(ProjectState state, TransferConfig config) { public ConfigInfo(ProjectControl control,
Project p = state.getProject(); ProjectState projectState,
TransferConfig config,
DynamicMap<RestView<ProjectResource>> views,
Provider<CurrentUser> currentUser) {
Project p = control.getProject();
this.description = Strings.emptyToNull(p.getDescription()); this.description = Strings.emptyToNull(p.getDescription());
InheritedBooleanInfo useContributorAgreements = InheritedBooleanInfo useContributorAgreements =
@ -49,10 +61,10 @@ public class ConfigInfo {
InheritedBooleanInfo useContentMerge = new InheritedBooleanInfo(); InheritedBooleanInfo useContentMerge = new InheritedBooleanInfo();
InheritedBooleanInfo requireChangeId = new InheritedBooleanInfo(); InheritedBooleanInfo requireChangeId = new InheritedBooleanInfo();
useContributorAgreements.value = state.isUseContributorAgreements(); useContributorAgreements.value = projectState.isUseContributorAgreements();
useSignedOffBy.value = state.isUseSignedOffBy(); useSignedOffBy.value = projectState.isUseSignedOffBy();
useContentMerge.value = state.isUseContentMerge(); useContentMerge.value = projectState.isUseContentMerge();
requireChangeId.value = state.isRequireChangeID(); requireChangeId.value = projectState.isRequireChangeID();
useContributorAgreements.configuredValue = useContributorAgreements.configuredValue =
p.getUseContributorAgreements(); p.getUseContributorAgreements();
@ -60,7 +72,8 @@ public class ConfigInfo {
useContentMerge.configuredValue = p.getUseContentMerge(); useContentMerge.configuredValue = p.getUseContentMerge();
requireChangeId.configuredValue = p.getRequireChangeID(); requireChangeId.configuredValue = p.getRequireChangeID();
ProjectState parentState = Iterables.getFirst(state.parents(), null); ProjectState parentState = Iterables.getFirst(projectState
.parents(), null);
if (parentState != null) { if (parentState != null) {
useContributorAgreements.inheritedValue = useContributorAgreements.inheritedValue =
parentState.isUseContributorAgreements(); parentState.isUseContributorAgreements();
@ -76,7 +89,7 @@ public class ConfigInfo {
MaxObjectSizeLimitInfo maxObjectSizeLimit = new MaxObjectSizeLimitInfo(); MaxObjectSizeLimitInfo maxObjectSizeLimit = new MaxObjectSizeLimitInfo();
maxObjectSizeLimit.value = maxObjectSizeLimit.value =
config.getEffectiveMaxObjectSizeLimit(state) == config config.getEffectiveMaxObjectSizeLimit(projectState) == config
.getMaxObjectSizeLimit() ? config .getMaxObjectSizeLimit() ? config
.getFormattedMaxObjectSizeLimit() : p.getMaxObjectSizeLimit(); .getFormattedMaxObjectSizeLimit() : p.getMaxObjectSizeLimit();
maxObjectSizeLimit.configuredValue = p.getMaxObjectSizeLimit(); maxObjectSizeLimit.configuredValue = p.getMaxObjectSizeLimit();
@ -88,11 +101,17 @@ public class ConfigInfo {
this.state = p.getState() != Project.State.ACTIVE ? p.getState() : null; this.state = p.getState() != Project.State.ACTIVE ? p.getState() : null;
this.commentlinks = Maps.newLinkedHashMap(); this.commentlinks = Maps.newLinkedHashMap();
for (CommentLinkInfo cl : state.getCommentLinks()) { for (CommentLinkInfo cl : projectState.getCommentLinks()) {
this.commentlinks.put(cl.name, cl); this.commentlinks.put(cl.name, cl);
} }
this.theme = state.getTheme(); actions = Maps.newTreeMap();
for (UiAction.Description d : UiActions.from(
views, new ProjectResource(control),
currentUser)) {
actions.put(d.getId(), new ActionInfo(d));
}
this.theme = projectState.getTheme();
} }
public static class InheritedBooleanInfo { public static class InheritedBooleanInfo {

View File

@ -14,21 +14,35 @@
package com.google.gerrit.server.project; package com.google.gerrit.server.project;
import com.google.gerrit.extensions.registration.DynamicMap;
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.server.CurrentUser;
import com.google.gerrit.server.git.TransferConfig; import com.google.gerrit.server.git.TransferConfig;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider;
public class GetConfig implements RestReadView<ProjectResource> { public class GetConfig implements RestReadView<ProjectResource> {
private final TransferConfig config; private final TransferConfig config;
private final DynamicMap<RestView<ProjectResource>> views;
private final Provider<CurrentUser> currentUser;
@Inject @Inject
public GetConfig(TransferConfig config) { public GetConfig(TransferConfig config,
DynamicMap<RestView<ProjectResource>> views,
Provider<CurrentUser> currentUser) {
this.config = config; this.config = config;
this.views = views;
this.currentUser = currentUser;
} }
@Override @Override
public ConfigInfo apply(ProjectResource resource) { public ConfigInfo apply(ProjectResource resource) {
return new ConfigInfo(resource.getControl().getProjectState(), config); return new ConfigInfo(resource.getControl(),
resource.getControl().getProjectState(),
config,
views,
currentUser);
} }
} }

View File

@ -15,10 +15,12 @@
package com.google.gerrit.server.project; package com.google.gerrit.server.project;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.BadRequestException; import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException; import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestModifyView; import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.Project.InheritableBoolean; import com.google.gerrit.reviewdb.client.Project.InheritableBoolean;
import com.google.gerrit.reviewdb.client.Project.SubmitType; import com.google.gerrit.reviewdb.client.Project.SubmitType;
@ -52,18 +54,24 @@ public class PutConfig implements RestModifyView<ProjectResource, Input> {
private final Provider<CurrentUser> self; private final Provider<CurrentUser> self;
private final ProjectState.Factory projectStateFactory; private final ProjectState.Factory projectStateFactory;
private final TransferConfig config; private final TransferConfig config;
private final DynamicMap<RestView<ProjectResource>> views;
private final Provider<CurrentUser> currentUser;
@Inject @Inject
PutConfig(MetaDataUpdate.User metaDataUpdateFactory, PutConfig(MetaDataUpdate.User metaDataUpdateFactory,
ProjectCache projectCache, ProjectCache projectCache,
Provider<CurrentUser> self, Provider<CurrentUser> self,
ProjectState.Factory projectStateFactory, ProjectState.Factory projectStateFactory,
TransferConfig config) { TransferConfig config,
DynamicMap<RestView<ProjectResource>> views,
Provider<CurrentUser> currentUser) {
this.metaDataUpdateFactory = metaDataUpdateFactory; this.metaDataUpdateFactory = metaDataUpdateFactory;
this.projectCache = projectCache; this.projectCache = projectCache;
this.self = self; this.self = self;
this.projectStateFactory = projectStateFactory; this.projectStateFactory = projectStateFactory;
this.config = config; this.config = config;
this.views = views;
this.currentUser = currentUser;
} }
@Override @Override
@ -131,7 +139,9 @@ public class PutConfig implements RestModifyView<ProjectResource, Input> {
throw new ResourceConflictException("Cannot update " + projectName); throw new ResourceConflictException("Cannot update " + projectName);
} }
} }
return new ConfigInfo(projectStateFactory.create(projectConfig), config); return new ConfigInfo(rsrc.getControl(),
projectStateFactory.create(projectConfig),
config, views, currentUser);
} catch (ConfigInvalidException err) { } catch (ConfigInvalidException err) {
throw new ResourceConflictException("Cannot read project " + projectName, err); throw new ResourceConflictException("Cannot read project " + projectName, err);
} catch (IOException err) { } catch (IOException err) {