Add support for project aware TopMenu extensions
Currently TopMenu extensions are not context aware, which is not a
problem for most of them, but in case of the 'Projects' section this
could be problematic.
With this approach plugins cannot contribute TopMenu items that will
only be shown when a project is selected and the url (and the history
item) contains a project name.
This change improves this by adding a possibility to provide a menu
item within the 'Projects' context without the previously mentioned
limitation.
Now when a TopMenu item contains a '${projectName}' placeholder it
will be replaced with name of project that is selected in the
'Projects' section.
Change-Id: I516f129dc73b5b98fd6c2d385690e51febfc00a3
Signed-off-by: Dariusz Luksza <dariusz@luksza.org>
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index 507e0e4..d27e8ac 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -1259,6 +1259,26 @@
}
----
+`MenuItems` that are bound for the `MenuEntry` with the name
+`GerritTopMenu.PROJECTS` can contain a `${projectName}` placeholder
+which is automatically replaced by the actual project name.
+
+E.g. plugins may register an link:#http[HTTP Servlet] to handle project
+specific requests and add an menu item for this:
+
+[source,java]
+---
+ new MenuItem("My Screen", "/plugins/myplugin/project/${projectName}");
+---
+
+This also enables plugins to provide menu items for project aware
+screens:
+
+[source,java]
+---
+ new MenuItem("My Screen", "/x/my-screen/for/${projectName}");
+---
+
If no Guice modules are declared in the manifest, the top menu extension may use
auto-registration by providing an `@Listen` annotation:
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index 5b96ba0..d74b744 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -51,6 +51,7 @@
import com.google.gerrit.reviewdb.client.AccountDiffPreference;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
import com.google.gerrit.reviewdb.client.AuthType;
+import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.aria.client.Roles;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
@@ -764,14 +765,21 @@
public void onSuccess(TopMenuList result) {
List<TopMenu> topMenuExtensions = Natives.asList(result);
for (TopMenu menu : topMenuExtensions) {
- LinkMenuBar existingBar = menuBars.get(menu.getName());
+ String name = menu.getName();
+ LinkMenuBar existingBar = menuBars.get(name);
LinkMenuBar bar = existingBar != null ? existingBar : new LinkMenuBar();
- for (TopMenuItem item : Natives.asList(menu.getItems())) {
- addExtensionLink(bar, item);
+ if (GerritTopMenu.PROJECTS.menuName.equals(name)) {
+ for (TopMenuItem item : Natives.asList(menu.getItems())) {
+ addProjectLink(bar, item);
+ }
+ } else {
+ for (TopMenuItem item : Natives.asList(menu.getItems())) {
+ addExtensionLink(bar, item);
+ }
}
if (existingBar == null) {
- menuBars.put(menu.getName(), bar);
- menuLeft.add(bar, menu.getName());
+ menuBars.put(name, bar);
+ menuLeft.add(bar, name);
}
}
}
@@ -890,6 +898,40 @@
});
}
+ private static LinkMenuItem addProjectLink(LinkMenuBar m, TopMenuItem item) {
+ LinkMenuItem i = new ProjectLinkMenuItem(item.getName(), item.getUrl()) {
+ @Override
+ protected void onScreenLoad(Project.NameKey project) {
+ String p = panel.replace("${projectName}", project.get());
+ if (panel.startsWith("/x/")) {
+ setTargetHistoryToken(p);
+ } else if (isAbsolute(panel)) {
+ getElement().setPropertyString("href", p);
+ } else {
+ getElement().setPropertyString("href", selfRedirect(p));
+ }
+ }
+
+ @Override
+ public void go() {
+ String href = getElement().getPropertyString("href");
+ if (href.startsWith("#")) {
+ super.go();
+ } else {
+ Window.open(href, getElement().getPropertyString("target"), "");
+ }
+ }
+ };
+ if (item.getTarget() != null && !item.getTarget().isEmpty()) {
+ i.getElement().setAttribute("target", item.getTarget());
+ }
+ if (item.getId() != null) {
+ i.getElement().setAttribute("id", item.getId());
+ }
+ m.addItem(i);
+ return i;
+ }
+
private static void addDiffLink(final LinkMenuBar m, final String text,
final PatchScreen.Type type) {
m.addItem(new LinkMenuItem(text, "") {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLinkMenuItem.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLinkMenuItem.java
index 2917505..119f5ef 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLinkMenuItem.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLinkMenuItem.java
@@ -19,7 +19,7 @@
import com.google.gerrit.reviewdb.client.Project;
public class ProjectLinkMenuItem extends LinkMenuItem {
- private final String panel;
+ protected final String panel;
public ProjectLinkMenuItem(String text, String panel) {
super(text, "");
@@ -38,10 +38,14 @@
if (projectKey != null) {
setVisible(true);
- setTargetHistoryToken(Dispatcher.toProjectAdmin(projectKey, panel));
+ onScreenLoad(projectKey);
} else {
setVisible(false);
}
super.onScreenLoad(event);
}
+
+ protected void onScreenLoad(Project.NameKey project) {
+ setTargetHistoryToken(Dispatcher.toProjectAdmin(project, panel));
+ }
}