src/main/java/com/gitblit/extensions/UserMenuExtension.java
New file @@ -0,0 +1,40 @@ /* * Copyright 2014 gitblit.com. * * 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.gitblit.extensions; import java.util.List; import ro.fortsoft.pf4j.ExtensionPoint; import com.gitblit.models.Menu.MenuItem; import com.gitblit.models.UserModel; /** * Extension point to contribute user menu items. * * @author James Moger * @since 1.6.0 * */ public abstract class UserMenuExtension implements ExtensionPoint { /** * @param user * @since 1.6.0 * @return a list of menu items */ public abstract List<MenuItem> getMenuItems(UserModel user); } src/main/java/com/gitblit/wicket/GitBlitWebApp.java
@@ -77,6 +77,7 @@ import com.gitblit.wicket.pages.SummaryPage; import com.gitblit.wicket.pages.TagPage; import com.gitblit.wicket.pages.TagsPage; import com.gitblit.wicket.pages.TeamsPage; import com.gitblit.wicket.pages.TicketsPage; import com.gitblit.wicket.pages.TreePage; import com.gitblit.wicket.pages.UserPage; @@ -181,6 +182,7 @@ mount("/metrics", MetricsPage.class, "r"); mount("/blame", BlamePage.class, "r", "h", "f"); mount("/users", UsersPage.class); mount("/teams", TeamsPage.class); mount("/logout", LogoutPage.class); // setup ticket urls src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
@@ -680,4 +680,7 @@ gb.overdue = overdue gb.openMilestones = open milestones gb.closedMilestones = closed milestones gb.adminMenuItem = admin gb.administration = administration gb.plugins = plugins gb.extensions = extensions src/main/java/com/gitblit/wicket/PageRegistration.java
@@ -67,13 +67,13 @@ public final String url; public OtherPageLink(String translationKey, String url) { super(translationKey, null); public OtherPageLink(String keyOrText, String url) { super(keyOrText, null); this.url = url; } public OtherPageLink(String translationKey, String url, boolean hiddenPhone) { super(translationKey, null, null, hiddenPhone); public OtherPageLink(String keyOrText, String url, boolean hiddenPhone) { super(keyOrText, null, null, hiddenPhone); this.url = url; } } @@ -90,8 +90,8 @@ public final List<MenuItem> menuItems; public DropDownMenuRegistration(String translationKey, Class<? extends WebPage> pageClass) { super(translationKey, pageClass); public DropDownMenuRegistration(String keyOrText, Class<? extends WebPage> pageClass) { super(keyOrText, pageClass); menuItems = new ArrayList<MenuItem>(); } } src/main/java/com/gitblit/wicket/pages/RootPage.html
@@ -51,17 +51,19 @@ <li class="dropdown"> <a data-toggle="dropdown" class="dropdown-toggle" style="text-decoration: none;" href="#"><span wicket:id="username"></span> <b class="caret"></b></a> <ul class="dropdown-menu"> <li style="color:#ccc;padding-left:15px;font-weight:bold;"><span wicket:id="displayName"></span></li> <li class="divider"></li> <li><a wicket:id="newRepository"><wicket:message key="gb.newRepository"></wicket:message></a></li> <li><a wicket:id="myProfile"><wicket:message key="gb.myProfile"></wicket:message></a></li> <li><a wicket:id="changePassword"><wicket:message key="gb.changePassword"></wicket:message></a></li> <li class="divider"></li> <span wicket:id="standardMenu"></span> <span wicket:id="adminMenu"></span> <span wicket:id="extensionsMenu"></span> <li><a wicket:id="logout"><wicket:message key="gb.logout"></wicket:message></a></li> </ul> </li> </wicket:fragment> <wicket:fragment wicket:id="submenuFragment"> <li style="color:#ccc;padding-left:15px;font-weight:bold;"><span wicket:id="submenuTitle"></span></li> <li wicket:id="submenuItem"><span wicket:id="submenuLink"></span></li> </wicket:fragment> </wicket:extend> </body> </html> src/main/java/com/gitblit/wicket/pages/RootPage.java
@@ -41,13 +41,17 @@ import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.data.DataView; import org.apache.wicket.markup.repeater.data.ListDataProvider; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.protocol.http.WebResponse; import com.gitblit.Constants; import com.gitblit.Keys; import com.gitblit.extensions.AdminMenuExtension; import com.gitblit.extensions.UserMenuExtension; import com.gitblit.models.Menu.ExternalLinkMenuItem; import com.gitblit.models.Menu.MenuDivider; import com.gitblit.models.Menu.MenuItem; import com.gitblit.models.Menu.PageLinkMenuItem; @@ -60,10 +64,10 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.PageRegistration; import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; import com.gitblit.wicket.SessionlessForm; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.GravatarImage; import com.gitblit.wicket.panels.LinkPanel; import com.gitblit.wicket.panels.NavigationPanel; /** @@ -594,6 +598,11 @@ public UserMenu(String id, String markupId, MarkupContainer markupProvider) { super(id, markupId, markupProvider); setRenderBodyOnly(true); } @Override protected void onInitialize() { super.onInitialize(); GitBlitWebSession session = GitBlitWebSession.get(); UserModel user = session.getUser(); @@ -606,19 +615,105 @@ add(new Label("username", user.getDisplayName())); } add(new Label("displayName", user.getDisplayName())); List<MenuItem> standardItems = new ArrayList<MenuItem>(); standardItems.add(new MenuDivider()); if (user.canAdmin() || user.canCreate()) { standardItems.add(new PageLinkMenuItem("gb.newRepository", EditRepositoryPage.class)); } standardItems.add(new PageLinkMenuItem("gb.myProfile", UserPage.class, WicketUtils.newUsernameParameter(user.username))); if (editCredentials) { standardItems.add(new PageLinkMenuItem("gb.changePassword", ChangePasswordPage.class)); } standardItems.add(new MenuDivider()); add(newSubmenu("standardMenu", user.getDisplayName(), standardItems)); add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class).setVisible(user.canAdmin() || user.canCreate())); if (showAdmin) { // admin menu List<MenuItem> adminItems = new ArrayList<MenuItem>(); adminItems.add(new MenuDivider()); adminItems.add(new PageLinkMenuItem("gb.users", UsersPage.class)); adminItems.add(new PageLinkMenuItem("gb.teams", TeamsPage.class)); add(new BookmarkablePageLink<Void>("myProfile", UserPage.class, WicketUtils.newUsernameParameter(user.username))); boolean showRegistrations = app().federation().canFederate() && app().settings().getBoolean(Keys.web.showFederationRegistrations, false); if (showRegistrations) { adminItems.add(new PageLinkMenuItem("gb.federation", FederationPage.class)); } adminItems.add(new MenuDivider()); add(new BookmarkablePageLink<Void>("changePassword", ChangePasswordPage.class).setVisible(editCredentials)); add(newSubmenu("adminMenu", getString("gb.administration"), adminItems)); } else { add(new Label("adminMenu").setVisible(false)); } // plugin extension items List<MenuItem> extensionItems = new ArrayList<MenuItem>(); List<UserMenuExtension> extensions = app().plugins().getExtensions(UserMenuExtension.class); for (UserMenuExtension ext : extensions) { List<MenuItem> items = ext.getMenuItems(user); extensionItems.addAll(items); } if (extensionItems.isEmpty()) { // no extension items add(new Label("extensionsMenu").setVisible(false)); } else { // found extension items extensionItems.add(0, new MenuDivider()); add(newSubmenu("extensionsMenu", getString("gb.extensions"), extensionItems)); extensionItems.add(new MenuDivider()); } add(new BookmarkablePageLink<Void>("logout", LogoutPage.class).setVisible(standardLogin)); } /** * Creates a submenu. This is not actually submenu because we're using * an older Twitter Bootstrap which is pre-submenu. * * @param wicketId * @param submenuTitle * @param menuItems * @return a submenu fragment */ private Fragment newSubmenu(String wicketId, String submenuTitle, List<MenuItem> menuItems) { Fragment submenu = new Fragment(wicketId, "submenuFragment", this); submenu.add(new Label("submenuTitle", submenuTitle).setRenderBodyOnly(true)); ListDataProvider<MenuItem> menuItemsDp = new ListDataProvider<MenuItem>(menuItems); DataView<MenuItem> submenuItems = new DataView<MenuItem>("submenuItem", menuItemsDp) { private static final long serialVersionUID = 1L; @Override public void populateItem(final Item<MenuItem> menuItem) { final MenuItem item = menuItem.getModelObject(); String name = item.toString(); try { // try to lookup translation name = getString(name); } catch (Exception e) { } if (item instanceof PageLinkMenuItem) { // link to another Wicket page PageLinkMenuItem pageLink = (PageLinkMenuItem) item; menuItem.add(new LinkPanel("submenuLink", null, null, name, pageLink.getPageClass(), pageLink.getPageParameters(), false).setRenderBodyOnly(true)); } else if (item instanceof ExternalLinkMenuItem) { // link to a specified href ExternalLinkMenuItem extLink = (ExternalLinkMenuItem) item; menuItem.add(new LinkPanel("submenuLink", null, name, extLink.getHref(), extLink.openInNewWindow()).setRenderBodyOnly(true)); } else if (item instanceof MenuDivider) { // divider menuItem.add(new Label("submenuLink").setRenderBodyOnly(true)); WicketUtils.setCssClass(menuItem, "divider"); } } }; submenu.add(submenuItems); submenu.setRenderBodyOnly(true); return submenu; } } } src/main/java/com/gitblit/wicket/pages/TeamsPage.html
New file @@ -0,0 +1,13 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" xml:lang="en" lang="en"> <body> <wicket:extend> <div class="container"> <div wicket:id="teamsPanel">[teams panel]</div> </div> </wicket:extend> </body> </html> src/main/java/com/gitblit/wicket/pages/TeamsPage.java
New file @@ -0,0 +1,30 @@ /* * Copyright 2011 gitblit.com. * * 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.gitblit.wicket.pages; import com.gitblit.wicket.RequiresAdminRole; import com.gitblit.wicket.panels.TeamsPanel; @RequiresAdminRole public class TeamsPage extends RootPage { public TeamsPage() { super(); setupPage("", ""); add(new TeamsPanel("teamsPanel", showAdmin).setVisible(showAdmin)); } } src/main/java/com/gitblit/wicket/pages/UsersPage.html
@@ -6,8 +6,6 @@ <body> <wicket:extend> <div class="container"> <div wicket:id="teamsPanel">[teams panel]</div> <div wicket:id="usersPanel">[users panel]</div> </div> </wicket:extend> src/main/java/com/gitblit/wicket/pages/UsersPage.java
@@ -16,7 +16,6 @@ package com.gitblit.wicket.pages; import com.gitblit.wicket.RequiresAdminRole; import com.gitblit.wicket.panels.TeamsPanel; import com.gitblit.wicket.panels.UsersPanel; @RequiresAdminRole @@ -25,8 +24,6 @@ public UsersPage() { super(); setupPage("", ""); add(new TeamsPanel("teamsPanel", showAdmin).setVisible(showAdmin)); add(new UsersPanel("usersPanel", showAdmin).setVisible(showAdmin)); } src/main/java/com/gitblit/wicket/panels/NavigationPanel.java
@@ -45,25 +45,32 @@ @Override public void populateItem(final Item<PageRegistration> item) { PageRegistration entry = item.getModelObject(); String linkText = entry.translationKey; try { // try to lookup translation key linkText = getString(entry.translationKey); } catch (Exception e) { } if (entry.hiddenPhone) { WicketUtils.setCssClass(item, "hidden-phone"); } if (entry instanceof OtherPageLink) { // other link OtherPageLink link = (OtherPageLink) entry; Component c = new LinkPanel("link", null, getString(entry.translationKey), link.url); Component c = new LinkPanel("link", null, linkText, link.url); c.setRenderBodyOnly(true); item.add(c); } else if (entry instanceof DropDownMenuRegistration) { // drop down menu DropDownMenuRegistration reg = (DropDownMenuRegistration) entry; Component c = new DropDownMenu("link", getString(entry.translationKey), reg); Component c = new DropDownMenu("link", linkText, reg); c.setRenderBodyOnly(true); item.add(c); WicketUtils.setCssClass(item, "dropdown"); } else { // standard page link Component c = new LinkPanel("link", null, getString(entry.translationKey), Component c = new LinkPanel("link", null, linkText, entry.pageClass, entry.params); c.setRenderBodyOnly(true); if (entry.pageClass.equals(pageClass)) { src/site/plugins_extensions.mkd
@@ -205,23 +205,23 @@ } ``` ### Admin Menu Items ### User Menu Items *SINCE 1.6.0* You can provide your own admin menu items by subclassing the *AdminMenuExtension* class. You can provide your own user menu items by subclassing the *UserMenuExtension* class. ```java import java.util.Arrays; import java.util.List; import ro.fortsoft.pf4j.Extension; import com.gitblit.extensions.AdminMenuExtension; import com.gitblit.extensions.UserMenuExtension; import com.gitblit.models.Menu.ExternalLinkMenuItem; import com.gitblit.models.Menu.MenuItem; import com.gitblit.models.UserModel; @Extension public class MyAdminMenuContributor extends AdminMenuExtension { public class MyUserMenuContributor extends UserMenuExtension { @Override public List<MenuItem> getMenuItems(UserModel user) { @@ -229,5 +229,3 @@ } } ```