Merge "Add top menu extension point"
This commit is contained in:
@@ -774,6 +774,53 @@ Gerrit.install(function(self) {
|
||||
});
|
||||
----
|
||||
|
||||
[[top-menu-extensions]]
|
||||
Top Menu Extensions
|
||||
-------------------
|
||||
|
||||
Plugins can contribute items to Gerrit's top menu.
|
||||
|
||||
A single top menu extension can have multiple elements and will be put as
|
||||
the last element in Gerrit's top menu.
|
||||
|
||||
Plugins define the top menu entries by implementing `TopMenu` interface:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public class MyTopMenuExtension implements TopMenu {
|
||||
|
||||
@Override
|
||||
public List<MenuEntry> getEntries() {
|
||||
return Lists.newArrayList(
|
||||
new MenuEntry("Top Menu Entry", Lists.newArrayList(
|
||||
new MenuItem("Gerrit", "http://gerrit.googlecode.com/"))));
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
If no Guice modules are declared in the manifest, the top menu extension may use
|
||||
auto-registration by providing an `@Listen` annotation:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Listen
|
||||
public class MyTopMenuExtension implements TopMenu {
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
Otherwise the top menu extension must be bound in a plugin module:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public class HelloWorldModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
DynamicSet.bind(binder(), TopMenu.class).to(MyTopMenuExtension.class);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[[http]]
|
||||
HTTP Servlets
|
||||
-------------
|
||||
|
@@ -135,6 +135,47 @@ The entries in the map are sorted by capability ID.
|
||||
}
|
||||
----
|
||||
|
||||
[[get-top-menus]]
|
||||
Get Top Menus
|
||||
~~~~~~~~~~~~~
|
||||
[verse]
|
||||
'GET /config/server/top-menus'
|
||||
|
||||
Returns the list of additional top menu entries.
|
||||
|
||||
.Request
|
||||
----
|
||||
GET /config/server/top-menus HTTP/1.0
|
||||
----
|
||||
|
||||
As response a list of the additional top menu entries as
|
||||
link:#top-menu-entry-info[TopMenuEntryInfo] entities is returned.
|
||||
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
)]}'
|
||||
[
|
||||
{
|
||||
"name": "Top Menu Entry",
|
||||
"items": [
|
||||
{
|
||||
"url": "http://gerrit.googlecode.com/",
|
||||
"name": "Gerrit",
|
||||
"target": "_blank"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
----
|
||||
|
||||
|
||||
[[json-entities]]
|
||||
JSON Entities
|
||||
-------------
|
||||
|
||||
[[capability-info]]
|
||||
CapabilityInfo
|
||||
~~~~~~~~~~~~~~
|
||||
@@ -148,6 +189,32 @@ The `CapabilityInfo` entity contains information about a capability.
|
||||
|`name` |capability name
|
||||
|=================================
|
||||
|
||||
[[top-menu-entry-info]]
|
||||
TopMenuEntryInfo
|
||||
~~~~~~~~~~~~~~~~
|
||||
The `TopMenuEntryInfo` entity contains information about a top menu
|
||||
entry.
|
||||
|
||||
[options="header",width="50%",cols="1,5"]
|
||||
|=================================
|
||||
|Field Name |Description
|
||||
|`name` |Name of the top menu entry.
|
||||
|`items` |List of link:#top-menu-item-info[menu items].
|
||||
|=================================
|
||||
|
||||
[[top-menu-item-info]]
|
||||
TopMenuItemInfo
|
||||
~~~~~~~~~~~~~~~
|
||||
The `TopMenuItemInfo` entity contains information about a menu item in
|
||||
a top menu entry.
|
||||
|
||||
[options="header",width="50%",cols="1,5"]
|
||||
|=================================
|
||||
|Field Name |Description
|
||||
|`url` |The URL of the menu item link.
|
||||
|`name` |The name of the menu item.
|
||||
|`target` |Target attribute of the menu item link.
|
||||
|=================================
|
||||
|
||||
GERRIT
|
||||
------
|
||||
|
@@ -0,0 +1,51 @@
|
||||
// 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.extensions.webui;
|
||||
|
||||
import com.google.gerrit.extensions.annotations.ExtensionPoint;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ExtensionPoint
|
||||
public interface TopMenu {
|
||||
|
||||
public class MenuEntry {
|
||||
public final String name;
|
||||
public final List<MenuItem> items;
|
||||
|
||||
public MenuEntry(String name, List<MenuItem> items) {
|
||||
this.name = name;
|
||||
this.items = items;
|
||||
}
|
||||
}
|
||||
|
||||
public class MenuItem {
|
||||
public final String url;
|
||||
public final String name;
|
||||
public final String target;
|
||||
|
||||
public MenuItem(String name, String url) {
|
||||
this(name, url, "_blank");
|
||||
}
|
||||
|
||||
public MenuItem(String name, String url, String target) {
|
||||
this.url = url;
|
||||
this.name = name;
|
||||
this.target = target;
|
||||
}
|
||||
}
|
||||
|
||||
List<MenuEntry> getEntries();
|
||||
}
|
@@ -24,8 +24,13 @@ import com.google.gerrit.client.admin.ProjectScreen;
|
||||
import com.google.gerrit.client.api.ApiGlue;
|
||||
import com.google.gerrit.client.changes.ChangeConstants;
|
||||
import com.google.gerrit.client.changes.ChangeListScreen;
|
||||
import com.google.gerrit.client.config.ConfigServerApi;
|
||||
import com.google.gerrit.client.extensions.TopMenu;
|
||||
import com.google.gerrit.client.extensions.TopMenuItem;
|
||||
import com.google.gerrit.client.extensions.TopMenuList;
|
||||
import com.google.gerrit.client.patches.PatchScreen;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.rpc.Natives;
|
||||
import com.google.gerrit.client.ui.LinkMenuBar;
|
||||
import com.google.gerrit.client.ui.LinkMenuItem;
|
||||
import com.google.gerrit.client.ui.MorphingTabPanel;
|
||||
@@ -87,6 +92,7 @@ import com.google.gwtjsonrpc.common.AsyncCallback;
|
||||
import com.google.gwtorm.client.KeyUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Gerrit implements EntryPoint {
|
||||
public static final GerritConstants C = GWT.create(GerritConstants.class);
|
||||
@@ -789,6 +795,18 @@ public class Gerrit implements EntryPoint {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ConfigServerApi.topMenus(new GerritCallback<TopMenuList>() {
|
||||
public void onSuccess(TopMenuList result) {
|
||||
List<TopMenu> topMenuExtensions = Natives.asList(result);
|
||||
for (TopMenu menu : topMenuExtensions) {
|
||||
LinkMenuBar bar = new LinkMenuBar();
|
||||
for (TopMenuItem item : Natives.asList(menu.getItems())) {
|
||||
addExtensionLink(bar, item);
|
||||
}
|
||||
menuLeft.add(bar, menu.getName());
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public static void applyUserPreferences() {
|
||||
@@ -921,4 +939,10 @@ public class Gerrit implements EntryPoint {
|
||||
atag.setTarget("_blank");
|
||||
m.add(atag);
|
||||
}
|
||||
|
||||
private static void addExtensionLink(final LinkMenuBar m, final TopMenuItem item) {
|
||||
final Anchor atag = anchor(item.getName(), item.getUrl());
|
||||
atag.setTarget(item.getTarget());
|
||||
m.add(atag);
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@
|
||||
|
||||
package com.google.gerrit.client.config;
|
||||
|
||||
import com.google.gerrit.client.extensions.TopMenuList;
|
||||
import com.google.gerrit.client.rpc.NativeMap;
|
||||
import com.google.gerrit.client.rpc.RestApi;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
@@ -27,4 +28,8 @@ public class ConfigServerApi {
|
||||
public static void capabilities(AsyncCallback<NativeMap<CapabilityInfo>> cb) {
|
||||
new RestApi("/config/server/capabilities/").get(cb);
|
||||
}
|
||||
|
||||
public static void topMenus(AsyncCallback<TopMenuList> cb) {
|
||||
new RestApi("/config/server/top-menus").get(cb);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,28 @@
|
||||
// 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.extensions;
|
||||
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
import com.google.gwt.core.client.JsArray;
|
||||
|
||||
public class TopMenu extends JavaScriptObject {
|
||||
|
||||
protected TopMenu() {
|
||||
}
|
||||
|
||||
public final native String getName() /*-{ return this.name; }-*/;
|
||||
|
||||
public final native JsArray<TopMenuItem> getItems() /*-{ return this.items; }-*/;
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
// 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.extensions;
|
||||
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
|
||||
public class TopMenuItem extends JavaScriptObject {
|
||||
public final native String getName() /*-{ return this.name; }-*/;
|
||||
public final native String getUrl() /*-{ return this.url; }-*/;
|
||||
public final native String getTarget() /*-{ return this.target; }-*/;
|
||||
|
||||
protected TopMenuItem() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
// 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.extensions;
|
||||
|
||||
import com.google.gwt.core.client.JsArray;
|
||||
|
||||
public class TopMenuList extends JsArray<TopMenu> {
|
||||
|
||||
protected TopMenuList() {
|
||||
}
|
||||
}
|
@@ -27,6 +27,7 @@ import com.google.gerrit.extensions.events.ProjectDeletedListener;
|
||||
import com.google.gerrit.extensions.registration.DynamicItem;
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
import com.google.gerrit.extensions.webui.TopMenu;
|
||||
import com.google.gerrit.rules.PrologModule;
|
||||
import com.google.gerrit.rules.RulesCache;
|
||||
import com.google.gerrit.server.AnonymousUser;
|
||||
@@ -239,6 +240,7 @@ public class GerritGlobalModule extends FactoryModule {
|
||||
DynamicSet.setOf(binder(), MergeValidationListener.class);
|
||||
DynamicItem.itemOf(binder(), AvatarProvider.class);
|
||||
DynamicSet.setOf(binder(), LifecycleListener.class);
|
||||
DynamicSet.setOf(binder(), TopMenu.class);
|
||||
|
||||
bind(AnonymousUser.class);
|
||||
|
||||
|
@@ -0,0 +1,41 @@
|
||||
// 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.server.config;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||
import com.google.gerrit.extensions.webui.TopMenu;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class ListTopMenus implements RestReadView<ConfigResource> {
|
||||
private final DynamicSet<TopMenu> extensions;
|
||||
|
||||
@Inject
|
||||
ListTopMenus(DynamicSet<TopMenu> extensions) {
|
||||
this.extensions = extensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object apply(ConfigResource resource) {
|
||||
List<TopMenu.MenuEntry> entries = Lists.newArrayList();
|
||||
for (TopMenu extension : extensions) {
|
||||
entries.addAll(extension.getEntries());
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
}
|
@@ -14,8 +14,9 @@
|
||||
|
||||
package com.google.gerrit.server.config;
|
||||
|
||||
import static com.google.gerrit.server.config.ConfigResource.CONFIG_KIND;
|
||||
import static com.google.gerrit.server.config.CapabilityResource.CAPABILITY_KIND;
|
||||
import static com.google.gerrit.server.config.ConfigResource.CONFIG_KIND;
|
||||
import static com.google.gerrit.server.config.TopMenuResource.TOP_MENU_KIND;
|
||||
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.extensions.restapi.RestApiModule;
|
||||
@@ -24,8 +25,10 @@ public class Module extends RestApiModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
DynamicMap.mapOf(binder(), CONFIG_KIND);
|
||||
DynamicMap.mapOf(binder(), TOP_MENU_KIND);
|
||||
DynamicMap.mapOf(binder(), CAPABILITY_KIND);
|
||||
child(CONFIG_KIND, "capabilities").to(CapabilitiesCollection.class);
|
||||
child(CONFIG_KIND, "top-menus").to(TopMenuCollection.class);
|
||||
get(CONFIG_KIND, "version").to(GetVersion.class);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,52 @@
|
||||
// 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.server.config;
|
||||
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.extensions.restapi.ChildCollection;
|
||||
import com.google.gerrit.extensions.restapi.IdString;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.RestView;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
class TopMenuCollection implements
|
||||
ChildCollection<ConfigResource, TopMenuResource> {
|
||||
private final DynamicMap<RestView<TopMenuResource>> views;
|
||||
private final Provider<ListTopMenus> list;
|
||||
|
||||
@Inject
|
||||
TopMenuCollection(DynamicMap<RestView<TopMenuResource>> views,
|
||||
Provider<ListTopMenus> list) {
|
||||
this.views = views;
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestView<ConfigResource> list() throws ResourceNotFoundException {
|
||||
return list.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TopMenuResource parse(ConfigResource parent, IdString id)
|
||||
throws ResourceNotFoundException {
|
||||
throw new ResourceNotFoundException(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicMap<RestView<TopMenuResource>> views() {
|
||||
return views;
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
// 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.server.config;
|
||||
|
||||
import com.google.gerrit.extensions.restapi.RestView;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
public class TopMenuResource extends ConfigResource {
|
||||
public static final TypeLiteral<RestView<TopMenuResource>> TOP_MENU_KIND =
|
||||
new TypeLiteral<RestView<TopMenuResource>>() {};
|
||||
}
|
Reference in New Issue
Block a user