From 856f3fc2a8365c141d1418d3cfff502be233c104 Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 21 Apr 2014 16:16:45 -0400 Subject: Overhaul menu item classes and add AdminMenuExtension point --- src/main/java/com/gitblit/models/Menu.java | 302 +++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 src/main/java/com/gitblit/models/Menu.java (limited to 'src/main/java/com/gitblit/models') diff --git a/src/main/java/com/gitblit/models/Menu.java b/src/main/java/com/gitblit/models/Menu.java new file mode 100644 index 00000000..7c949b3f --- /dev/null +++ b/src/main/java/com/gitblit/models/Menu.java @@ -0,0 +1,302 @@ +package com.gitblit.models; + +import java.io.Serializable; + +import org.apache.wicket.PageParameters; +import org.apache.wicket.markup.html.WebPage; + +import com.gitblit.utils.StringUtils; + +public class Menu { + + /** + * A MenuItem for a drop down menu. + * + * @author James Moger + * @since 1.6.0 + */ + public abstract static class MenuItem implements Serializable { + + private static final long serialVersionUID = 1L; + + final String displayText; + + MenuItem(String displayText) { + this.displayText = displayText; + } + + @Override + public int hashCode() { + return displayText.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof MenuItem) { + return hashCode() == o.hashCode(); + } + return false; + } + + @Override + public String toString() { + return displayText; + } + } + + /** + * A divider for the menu. + * + * @since 1.6.0 + */ + public static class MenuDivider extends MenuItem { + + private static final long serialVersionUID = 1L; + + public MenuDivider() { + super(""); + } + } + + + /** + * A MenuItem for setting a parameter of the current url. + * + * @author James Moger + * + */ + public static class ParameterMenuItem extends MenuItem { + + private static final long serialVersionUID = 1L; + + final PageParameters parameters; + final String parameter; + final String value; + final boolean isSelected; + + /** + * @param displayText + */ + public ParameterMenuItem(String displayText) { + this(displayText, null, null, null); + } + + /** + * @param displayText + * @param parameter + * @param value + */ + public ParameterMenuItem(String displayText, String parameter, String value) { + this(displayText, parameter, value, null); + } + + /** + * @param displayText + * @param parameter + * @param value + */ + public ParameterMenuItem(String displayText, String parameter, String value, + PageParameters params) { + super(displayText); + this.parameter = parameter; + this.value = value; + + if (params == null) { + // no parameters specified + parameters = new PageParameters(); + setParameter(parameter, value); + isSelected = false; + } else { + parameters = new PageParameters(params); + if (parameters.containsKey(parameter)) { + isSelected = params.getString(parameter).equals(value); + // set the new selection value + setParameter(parameter, value); + } else { + // not currently selected + isSelected = false; + setParameter(parameter, value); + } + } + } + + protected void setParameter(String parameter, String value) { + if (!StringUtils.isEmpty(parameter)) { + if (StringUtils.isEmpty(value)) { + this.parameters.remove(parameter); + } else { + this.parameters.put(parameter, value); + } + } + } + + public String formatParameter() { + if (StringUtils.isEmpty(parameter) || StringUtils.isEmpty(value)) { + return ""; + } + return parameter + "=" + value; + } + + public PageParameters getPageParameters() { + return parameters; + } + + public boolean isSelected() { + return isSelected; + } + + @Override + public int hashCode() { + if (StringUtils.isEmpty(displayText)) { + return value.hashCode() + parameter.hashCode(); + } + return displayText.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof MenuItem) { + return hashCode() == o.hashCode(); + } + return false; + } + + @Override + public String toString() { + if (StringUtils.isEmpty(displayText)) { + return formatParameter(); + } + return displayText; + } + } + + /** + * Menu item for toggling a parameter. + * + */ + public static class ToggleMenuItem extends ParameterMenuItem { + + private static final long serialVersionUID = 1L; + + /** + * @param displayText + * @param parameter + * @param value + */ + public ToggleMenuItem(String displayText, String parameter, String value, + PageParameters params) { + super(displayText, parameter, value, params); + if (isSelected) { + // already selected, so remove this enables toggling + parameters.remove(parameter); + } + } + } + + /** + * Menu item for linking to another Wicket page. + * + * @since 1.6.0 + */ + public static class PageLinkMenuItem extends MenuItem { + + private static final long serialVersionUID = 1L; + + private final Class pageClass; + + private final PageParameters params; + + /** + * Page Link Item links to another page. + * + * @param displayText + * @param pageClass + * @since 1.6.0 + */ + public PageLinkMenuItem(String displayText, Class pageClass) { + this(displayText, pageClass, null); + } + + /** + * Page Link Item links to another page. + * + * @param displayText + * @param pageClass + * @param params + * @since 1.6.0 + */ + public PageLinkMenuItem(String displayText, Class pageClass, PageParameters params) { + super(displayText); + this.pageClass = pageClass; + this.params = params; + } + + /** + * @return the page class + * @since 1.6.0 + */ + public Class getPageClass() { + return pageClass; + } + + /** + * @return the page parameters + * @since 1.6.0 + */ + public PageParameters getPageParameters() { + return params; + } + } + + /** + * Menu item to link to an external page. + * + * @since 1.6.0 + */ + public static class ExternalLinkMenuItem extends MenuItem { + + private static final long serialVersionUID = 1L; + + private final String href; + + private final boolean newWindow; + + /** + * External Link Item links to something else. + * + * @param displayText + * @param href + * @since 1.6.0 + */ + public ExternalLinkMenuItem(String displayText, String href) { + this(displayText, href, false); + } + + /** + * External Link Item links to something else. + * + * @param displayText + * @param href + * @since 1.6.0 + */ + public ExternalLinkMenuItem(String displayText, String href, boolean newWindow) { + super(displayText); + this.href = href; + this.newWindow = newWindow; + } + + /** + * @since 1.6.0 + */ + public String getHref() { + return href; + } + + /** + * @since 1.6.0 + */ + public boolean openInNewWindow() { + return newWindow; + } + } +} -- cgit v1.2.3 From 7a401a3ff909bf82fb4068d6dba430497f74084a Mon Sep 17 00:00:00 2001 From: James Moger Date: Tue, 22 Apr 2014 22:53:06 -0400 Subject: Allow plugins to extend the top navbar and repository navbar This change also ties the plugin manager into the Wicket framework and allows plugins to contribute and mount new pages which are linked by the top navbar and repository navbar extensions. --- .../com/gitblit/extensions/AdminMenuExtension.java | 40 ------ .../gitblit/extensions/GitblitWicketPlugin.java | 49 ++++++++ .../com/gitblit/extensions/NavLinkExtension.java | 40 ++++++ .../extensions/RepositoryNavLinkExtension.java | 42 +++++++ src/main/java/com/gitblit/models/NavLink.java | 140 +++++++++++++++++++++ .../java/com/gitblit/wicket/GitBlitWebApp.java | 106 ++++++++++++++-- .../java/com/gitblit/wicket/GitblitWicketApp.java | 72 +++++++++++ .../java/com/gitblit/wicket/PageRegistration.java | 99 --------------- .../com/gitblit/wicket/PluginClassResolver.java | 122 ++++++++++++++++++ .../gitblit/wicket/UrlExternalFormComparator.java | 39 ++++++ .../com/gitblit/wicket/pages/ActivityPage.java | 10 +- .../com/gitblit/wicket/pages/DashboardPage.java | 10 +- .../java/com/gitblit/wicket/pages/ProjectPage.java | 14 +-- .../com/gitblit/wicket/pages/ProjectsPage.java | 10 +- .../com/gitblit/wicket/pages/RepositoriesPage.java | 10 +- .../com/gitblit/wicket/pages/RepositoryPage.java | 61 +++++---- .../java/com/gitblit/wicket/pages/RootPage.java | 53 ++++---- .../java/com/gitblit/wicket/pages/UserPage.java | 10 +- .../com/gitblit/wicket/panels/DropDownMenu.java | 45 ++++++- .../com/gitblit/wicket/panels/NavigationPanel.java | 49 +++++--- src/site/plugins_extensions.mkd | 58 ++++++++- 21 files changed, 817 insertions(+), 262 deletions(-) delete mode 100644 src/main/java/com/gitblit/extensions/AdminMenuExtension.java create mode 100644 src/main/java/com/gitblit/extensions/GitblitWicketPlugin.java create mode 100644 src/main/java/com/gitblit/extensions/NavLinkExtension.java create mode 100644 src/main/java/com/gitblit/extensions/RepositoryNavLinkExtension.java create mode 100644 src/main/java/com/gitblit/models/NavLink.java create mode 100644 src/main/java/com/gitblit/wicket/GitblitWicketApp.java delete mode 100644 src/main/java/com/gitblit/wicket/PageRegistration.java create mode 100644 src/main/java/com/gitblit/wicket/PluginClassResolver.java create mode 100644 src/main/java/com/gitblit/wicket/UrlExternalFormComparator.java (limited to 'src/main/java/com/gitblit/models') diff --git a/src/main/java/com/gitblit/extensions/AdminMenuExtension.java b/src/main/java/com/gitblit/extensions/AdminMenuExtension.java deleted file mode 100644 index 8fe4288f..00000000 --- a/src/main/java/com/gitblit/extensions/AdminMenuExtension.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 administration menu items. - * - * @author James Moger - * @since 1.6.0 - * - */ -public abstract class AdminMenuExtension implements ExtensionPoint { - - /** - * @param user - * @since 1.6.0 - * @return a list of menu items - */ - public abstract List getMenuItems(UserModel user); -} diff --git a/src/main/java/com/gitblit/extensions/GitblitWicketPlugin.java b/src/main/java/com/gitblit/extensions/GitblitWicketPlugin.java new file mode 100644 index 00000000..130f4993 --- /dev/null +++ b/src/main/java/com/gitblit/extensions/GitblitWicketPlugin.java @@ -0,0 +1,49 @@ +/* + * 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 org.apache.wicket.Application; +import org.apache.wicket.IInitializer; + +import ro.fortsoft.pf4j.PluginWrapper; + +import com.gitblit.wicket.GitblitWicketApp; + +/** + * A Gitblit plugin that is allowed to extend the Wicket webapp. + * + * @author James Moger + * @since 1.6.0 + */ +public abstract class GitblitWicketPlugin extends GitblitPlugin implements IInitializer { + + public GitblitWicketPlugin(PluginWrapper wrapper) { + super(wrapper); + } + + @Override + public final void init(Application application) { + init((GitblitWicketApp) application); + } + + /** + * Allows plugins to extend the web application. + * + * @param app + * @since 1.6.0 + */ + protected abstract void init(GitblitWicketApp app); +} \ No newline at end of file diff --git a/src/main/java/com/gitblit/extensions/NavLinkExtension.java b/src/main/java/com/gitblit/extensions/NavLinkExtension.java new file mode 100644 index 00000000..c8958603 --- /dev/null +++ b/src/main/java/com/gitblit/extensions/NavLinkExtension.java @@ -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.NavLink; +import com.gitblit.models.UserModel; + +/** + * Extension point to contribute top-level navigation links. + * + * @author James Moger + * @since 1.6.0 + * + */ +public abstract class NavLinkExtension implements ExtensionPoint { + + /** + * @param user + * @since 1.6.0 + * @return a list of nav links + */ + public abstract List getNavLinks(UserModel user); +} diff --git a/src/main/java/com/gitblit/extensions/RepositoryNavLinkExtension.java b/src/main/java/com/gitblit/extensions/RepositoryNavLinkExtension.java new file mode 100644 index 00000000..2b05c5a0 --- /dev/null +++ b/src/main/java/com/gitblit/extensions/RepositoryNavLinkExtension.java @@ -0,0 +1,42 @@ +/* + * 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.NavLink; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.UserModel; + +/** + * Extension point to contribute repository page navigation links. + * + * @author James Moger + * @since 1.6.0 + * + */ +public abstract class RepositoryNavLinkExtension implements ExtensionPoint { + + /** + * @param user + * @param repository + * @since 1.6.0 + * @return a list of nav links + */ + public abstract List getNavLinks(UserModel user, RepositoryModel repository); +} diff --git a/src/main/java/com/gitblit/models/NavLink.java b/src/main/java/com/gitblit/models/NavLink.java new file mode 100644 index 00000000..993d6954 --- /dev/null +++ b/src/main/java/com/gitblit/models/NavLink.java @@ -0,0 +1,140 @@ +/* + * 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.models; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.apache.wicket.PageParameters; +import org.apache.wicket.markup.html.WebPage; + +import com.gitblit.models.Menu.MenuItem; + +/** + * Represents a navigation link for the navigation panel. + * + * @author James Moger + * + */ +public abstract class NavLink implements Serializable { + private static final long serialVersionUID = 1L; + + public final String translationKey; + public final boolean hiddenPhone; + + public NavLink(String translationKey, boolean hiddenPhone) { + this.translationKey = translationKey; + this.hiddenPhone = hiddenPhone; + } + + + /** + * Represents a Wicket page link. + * + * @author James Moger + * + */ + public static class PageNavLink extends NavLink implements Serializable { + private static final long serialVersionUID = 1L; + + public final Class pageClass; + public final PageParameters params; + + public PageNavLink(String translationKey, Class pageClass) { + this(translationKey, pageClass, null); + } + + public PageNavLink(String translationKey, Class pageClass, + PageParameters params) { + this(translationKey, pageClass, params, false); + } + + public PageNavLink(String translationKey, Class pageClass, + PageParameters params, boolean hiddenPhone) { + super(translationKey, hiddenPhone); + this.pageClass = pageClass; + this.params = params; + } + } + + /** + * Represents an explicitly href link. + * + * @author James Moger + * + */ + public static class ExternalNavLink extends NavLink implements Serializable { + + private static final long serialVersionUID = 1L; + + public final String url; + + public ExternalNavLink(String keyOrText, String url) { + super(keyOrText, false); + this.url = url; + } + + public ExternalNavLink(String keyOrText, String url, boolean hiddenPhone) { + super(keyOrText, hiddenPhone); + this.url = url; + } + } + + /** + * Represents a DropDownMenu for the current page. + * + * @author James Moger + * + */ + public static class DropDownPageMenuNavLink extends PageNavLink implements Serializable { + + private static final long serialVersionUID = 1L; + + public final List menuItems; + + public DropDownPageMenuNavLink(String keyOrText, Class pageClass) { + this(keyOrText, pageClass, false); + } + + public DropDownPageMenuNavLink(String keyOrText, Class pageClass, boolean hiddenPhone) { + super(keyOrText, pageClass, null, hiddenPhone); + menuItems = new ArrayList(); + } + } + + /** + * Represents a DropDownMenu. + * + * @author James Moger + * + */ + public static class DropDownMenuNavLink extends NavLink implements Serializable { + + private static final long serialVersionUID = 1L; + + public final List menuItems; + + public DropDownMenuNavLink(String keyOrText) { + this(keyOrText, false); + } + + public DropDownMenuNavLink(String keyOrText, boolean hiddenPhone) { + super(keyOrText, hiddenPhone); + menuItems = new ArrayList(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java index 3ca7d48f..d3aa62fd 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java @@ -28,8 +28,12 @@ import org.apache.wicket.Session; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.protocol.http.WebApplication; +import ro.fortsoft.pf4j.PluginState; +import ro.fortsoft.pf4j.PluginWrapper; + import com.gitblit.IStoredSettings; import com.gitblit.Keys; +import com.gitblit.extensions.GitblitWicketPlugin; import com.gitblit.manager.IAuthenticationManager; import com.gitblit.manager.IFederationManager; import com.gitblit.manager.IGitblit; @@ -83,7 +87,7 @@ import com.gitblit.wicket.pages.TreePage; import com.gitblit.wicket.pages.UserPage; import com.gitblit.wicket.pages.UsersPage; -public class GitBlitWebApp extends WebApplication { +public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { private final Class homePageClass = MyDashboardPage.class; @@ -210,11 +214,29 @@ public class GitBlitWebApp extends WebApplication { mount("/forks", ForksPage.class, "r"); mount("/fork", ForkPage.class, "r"); + // allow started Wicket plugins to initialize + for (PluginWrapper pluginWrapper : pluginManager.getPlugins()) { + if (PluginState.STARTED != pluginWrapper.getPluginState()) { + continue; + } + if (pluginWrapper.getPlugin() instanceof GitblitWicketPlugin) { + GitblitWicketPlugin wicketPlugin = (GitblitWicketPlugin) pluginWrapper.getPlugin(); + wicketPlugin.init(this); + } + } + + // customize the Wicket class resolver to load from plugins + PluginClassResolver classResolver = new PluginClassResolver(pluginManager); + getApplicationSettings().setClassResolver(classResolver); + getMarkupSettings().setDefaultMarkupEncoding("UTF-8"); - super.init(); } - private void mount(String location, Class clazz, String... parameters) { + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#mount(java.lang.String, java.lang.Class, java.lang.String) + */ + @Override + public void mount(String location, Class clazz, String... parameters) { if (parameters == null) { parameters = new String[] {}; } @@ -230,15 +252,26 @@ public class GitBlitWebApp extends WebApplication { } } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#getHomePage() + */ @Override public Class getHomePage() { return homePageClass; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#isCacheablePage(java.lang.String) + */ + @Override public boolean isCacheablePage(String mountPoint) { return cacheablePages.containsKey(mountPoint); } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#getCacheControl(java.lang.String) + */ + @Override public CacheControl getCacheControl(String mountPoint) { return cacheablePages.get(mountPoint); } @@ -254,15 +287,18 @@ public class GitBlitWebApp extends WebApplication { return gitBlitWebSession; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#settings() + */ + @Override public IStoredSettings settings() { return settings; } - /** - * Is Gitblit running in debug mode? - * - * @return true if Gitblit is running in debug mode + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#isDebugMode() */ + @Override public boolean isDebugMode() { return runtimeManager.isDebugMode(); } @@ -271,58 +307,114 @@ public class GitBlitWebApp extends WebApplication { * These methods look strange... and they are... but they are the first * step towards modularization across multiple commits. */ + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#getBootDate() + */ + @Override public Date getBootDate() { return runtimeManager.getBootDate(); } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#getLastActivityDate() + */ + @Override public Date getLastActivityDate() { return repositoryManager.getLastActivityDate(); } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#runtime() + */ + @Override public IRuntimeManager runtime() { return runtimeManager; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#plugins() + */ + @Override public IPluginManager plugins() { return pluginManager; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#notifier() + */ + @Override public INotificationManager notifier() { return notificationManager; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#users() + */ + @Override public IUserManager users() { return userManager; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#authentication() + */ + @Override public IAuthenticationManager authentication() { return authenticationManager; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#keys() + */ + @Override public IPublicKeyManager keys() { return publicKeyManager; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#repositories() + */ + @Override public IRepositoryManager repositories() { return repositoryManager; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#projects() + */ + @Override public IProjectManager projects() { return projectManager; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#federation() + */ + @Override public IFederationManager federation() { return federationManager; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#gitblit() + */ + @Override public IGitblit gitblit() { return gitblit; } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#tickets() + */ + @Override public ITicketService tickets() { return gitblit.getTicketService(); } + /* (non-Javadoc) + * @see com.gitblit.wicket.Webapp#getTimezone() + */ + @Override public TimeZone getTimezone() { return runtimeManager.getTimezone(); } diff --git a/src/main/java/com/gitblit/wicket/GitblitWicketApp.java b/src/main/java/com/gitblit/wicket/GitblitWicketApp.java new file mode 100644 index 00000000..a56e6996 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/GitblitWicketApp.java @@ -0,0 +1,72 @@ +package com.gitblit.wicket; + +import java.util.Date; +import java.util.TimeZone; + +import org.apache.wicket.markup.html.WebPage; + +import com.gitblit.IStoredSettings; +import com.gitblit.manager.IAuthenticationManager; +import com.gitblit.manager.IFederationManager; +import com.gitblit.manager.IGitblit; +import com.gitblit.manager.INotificationManager; +import com.gitblit.manager.IPluginManager; +import com.gitblit.manager.IProjectManager; +import com.gitblit.manager.IRepositoryManager; +import com.gitblit.manager.IRuntimeManager; +import com.gitblit.manager.IUserManager; +import com.gitblit.tickets.ITicketService; +import com.gitblit.transport.ssh.IPublicKeyManager; + +public interface GitblitWicketApp { + + public abstract void mount(String location, Class clazz, String... parameters); + + public abstract Class getHomePage(); + + public abstract boolean isCacheablePage(String mountPoint); + + public abstract CacheControl getCacheControl(String mountPoint); + + public abstract IStoredSettings settings(); + + /** + * Is Gitblit running in debug mode? + * + * @return true if Gitblit is running in debug mode + */ + public abstract boolean isDebugMode(); + + /* + * These methods look strange... and they are... but they are the first + * step towards modularization across multiple commits. + */ + public abstract Date getBootDate(); + + public abstract Date getLastActivityDate(); + + public abstract IRuntimeManager runtime(); + + public abstract IPluginManager plugins(); + + public abstract INotificationManager notifier(); + + public abstract IUserManager users(); + + public abstract IAuthenticationManager authentication(); + + public abstract IPublicKeyManager keys(); + + public abstract IRepositoryManager repositories(); + + public abstract IProjectManager projects(); + + public abstract IFederationManager federation(); + + public abstract IGitblit gitblit(); + + public abstract ITicketService tickets(); + + public abstract TimeZone getTimezone(); + +} \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/PageRegistration.java b/src/main/java/com/gitblit/wicket/PageRegistration.java deleted file mode 100644 index 9fd8f870..00000000 --- a/src/main/java/com/gitblit/wicket/PageRegistration.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.apache.wicket.PageParameters; -import org.apache.wicket.markup.html.WebPage; - -import com.gitblit.models.Menu.MenuItem; - -/** - * Represents a page link registration for the topbar. - * - * @author James Moger - * - */ -public class PageRegistration implements Serializable { - private static final long serialVersionUID = 1L; - - public final String translationKey; - public final Class pageClass; - public final PageParameters params; - public final boolean hiddenPhone; - - public PageRegistration(String translationKey, Class pageClass) { - this(translationKey, pageClass, null); - } - - public PageRegistration(String translationKey, Class pageClass, - PageParameters params) { - this(translationKey, pageClass, params, false); - } - - public PageRegistration(String translationKey, Class pageClass, - PageParameters params, boolean hiddenPhone) { - this.translationKey = translationKey; - this.pageClass = pageClass; - this.params = params; - this.hiddenPhone = hiddenPhone; - } - - /** - * Represents a page link to a non-Wicket page. Might be external. - * - * @author James Moger - * - */ - public static class OtherPageLink extends PageRegistration { - - private static final long serialVersionUID = 1L; - - public final String url; - - public OtherPageLink(String keyOrText, String url) { - super(keyOrText, null); - this.url = url; - } - - public OtherPageLink(String keyOrText, String url, boolean hiddenPhone) { - super(keyOrText, null, null, hiddenPhone); - this.url = url; - } - } - - /** - * Represents a DropDownMenu for the topbar - * - * @author James Moger - * - */ - public static class DropDownMenuRegistration extends PageRegistration { - - private static final long serialVersionUID = 1L; - - public final List menuItems; - - public DropDownMenuRegistration(String keyOrText, Class pageClass) { - super(keyOrText, pageClass); - menuItems = new ArrayList(); - } - } - -} \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/PluginClassResolver.java b/src/main/java/com/gitblit/wicket/PluginClassResolver.java new file mode 100644 index 00000000..ba53b04b --- /dev/null +++ b/src/main/java/com/gitblit/wicket/PluginClassResolver.java @@ -0,0 +1,122 @@ +/* + * 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.wicket; + +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.TreeSet; + +import org.apache.wicket.Application; +import org.apache.wicket.WicketRuntimeException; +import org.apache.wicket.application.IClassResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ro.fortsoft.pf4j.PluginState; +import ro.fortsoft.pf4j.PluginWrapper; + +import com.gitblit.manager.IPluginManager; + +/** + * Resolves plugin classes and resources. + */ +public class PluginClassResolver implements IClassResolver { + private static final Logger logger = LoggerFactory.getLogger(PluginClassResolver.class); + + private final IPluginManager pluginManager; + + public PluginClassResolver(IPluginManager pluginManager) { + this.pluginManager = pluginManager; + } + + @Override + public Class resolveClass(final String className) throws ClassNotFoundException { + boolean debugEnabled = logger.isDebugEnabled(); + + for (PluginWrapper plugin : pluginManager.getPlugins()) { + if (PluginState.STARTED != plugin.getPluginState()) { + // ignore this plugin + continue; + } + + try { + return plugin.getPluginClassLoader().loadClass(className); + } catch (ClassNotFoundException cnfx) { + if (debugEnabled) { + logger.debug("ClassResolver '{}' cannot find class: '{}'", plugin.getPluginId(), className); + } + } + } + + throw new ClassNotFoundException(className); + } + + @Override + public Iterator getResources(final String name) { + Set urls = new TreeSet(new UrlExternalFormComparator()); + + for (PluginWrapper plugin : pluginManager.getPlugins()) { + if (PluginState.STARTED != plugin.getPluginState()) { + // ignore this plugin + continue; + } + + Iterator it = getResources(name, plugin); + while (it.hasNext()) { + URL url = it.next(); + urls.add(url); + } + } + + return urls.iterator(); + } + + protected Iterator getResources(String name, PluginWrapper plugin) { + HashSet loadedFiles = new HashSet(); + try { + // Try the classloader for the wicket jar/bundle + Enumeration resources = plugin.getPluginClassLoader().getResources(name); + loadResources(resources, loadedFiles); + + // Try the classloader for the user's application jar/bundle + resources = Application.get().getClass().getClassLoader().getResources(name); + loadResources(resources, loadedFiles); + + // Try the context class loader + resources = Thread.currentThread().getContextClassLoader().getResources(name); + loadResources(resources, loadedFiles); + } catch (IOException e) { + throw new WicketRuntimeException(e); + } + + return loadedFiles.iterator(); + } + + private void loadResources(Enumeration resources, Set loadedFiles) { + if (resources != null) { + while (resources.hasMoreElements()) { + final URL url = resources.nextElement(); + if (!loadedFiles.contains(url)) { + loadedFiles.add(url); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/UrlExternalFormComparator.java b/src/main/java/com/gitblit/wicket/UrlExternalFormComparator.java new file mode 100644 index 00000000..90f4b320 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/UrlExternalFormComparator.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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; + +import java.net.URL; +import java.util.Comparator; + +/** + * A comparator of URL instances. + * + * Comparing URLs with their implementation of #equals() is + * bad because it may cause problems like DNS resolving, or other + * slow checks. This comparator uses the external form of an URL + * to make a simple comparison of two Strings. + * + * @since 1.5.6 + */ +public class UrlExternalFormComparator implements Comparator +{ + @Override + public int compare(URL url1, URL url2) + { + return url1.toExternalForm().compareTo(url2.toExternalForm()); + } +} \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/ActivityPage.java b/src/main/java/com/gitblit/wicket/pages/ActivityPage.java index 0870ff96..c505a666 100644 --- a/src/main/java/com/gitblit/wicket/pages/ActivityPage.java +++ b/src/main/java/com/gitblit/wicket/pages/ActivityPage.java @@ -32,14 +32,14 @@ import org.apache.wicket.markup.html.panel.Fragment; import com.gitblit.Keys; import com.gitblit.models.Activity; import com.gitblit.models.Menu.ParameterMenuItem; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; import com.gitblit.models.Metric; +import com.gitblit.models.NavLink; import com.gitblit.models.RepositoryModel; import com.gitblit.utils.ActivityUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.CacheControl; import com.gitblit.wicket.CacheControl.LastModified; -import com.gitblit.wicket.PageRegistration; -import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.charting.Chart; import com.gitblit.wicket.charting.Charts; @@ -135,8 +135,8 @@ public class ActivityPage extends RootPage { } @Override - protected void addDropDownMenus(List pages) { - DropDownMenuRegistration filters = new DropDownMenuRegistration("gb.filters", + protected void addDropDownMenus(List navLinks) { + DropDownPageMenuNavLink filters = new DropDownPageMenuNavLink("gb.filters", ActivityPage.class); PageParameters currentParameters = getPageParameters(); @@ -155,7 +155,7 @@ public class ActivityPage extends RootPage { // Reset Filter filters.menuItems.add(new ParameterMenuItem(getString("gb.reset"))); } - pages.add(filters); + navLinks.add(filters); } /** diff --git a/src/main/java/com/gitblit/wicket/pages/DashboardPage.java b/src/main/java/com/gitblit/wicket/pages/DashboardPage.java index 16b0b734..9c10e01b 100644 --- a/src/main/java/com/gitblit/wicket/pages/DashboardPage.java +++ b/src/main/java/com/gitblit/wicket/pages/DashboardPage.java @@ -37,7 +37,9 @@ import org.eclipse.jgit.lib.Repository; import com.gitblit.Keys; import com.gitblit.models.DailyLogEntry; import com.gitblit.models.Menu.ParameterMenuItem; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; import com.gitblit.models.Metric; +import com.gitblit.models.NavLink; import com.gitblit.models.RefLogEntry; import com.gitblit.models.RepositoryCommit; import com.gitblit.models.RepositoryModel; @@ -46,8 +48,6 @@ import com.gitblit.utils.ArrayUtils; import com.gitblit.utils.RefLogUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebApp; -import com.gitblit.wicket.PageRegistration; -import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; import com.gitblit.wicket.charting.Chart; import com.gitblit.wicket.charting.Charts; import com.gitblit.wicket.charting.Flotr2Charts; @@ -141,10 +141,10 @@ public abstract class DashboardPage extends RootPage { } @Override - protected void addDropDownMenus(List pages) { + protected void addDropDownMenus(List navLinks) { PageParameters params = getPageParameters(); - DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters", + DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters", GitBlitWebApp.get().getHomePage()); // preserve repository filter option on time choices @@ -155,7 +155,7 @@ public abstract class DashboardPage extends RootPage { menu.menuItems.add(new ParameterMenuItem(getString("gb.reset"))); } - pages.add(menu); + navLinks.add(menu); } diff --git a/src/main/java/com/gitblit/wicket/pages/ProjectPage.java b/src/main/java/com/gitblit/wicket/pages/ProjectPage.java index 6c8aa4f4..d358b775 100644 --- a/src/main/java/com/gitblit/wicket/pages/ProjectPage.java +++ b/src/main/java/com/gitblit/wicket/pages/ProjectPage.java @@ -29,6 +29,8 @@ import com.gitblit.Keys; import com.gitblit.models.Menu.MenuDivider; import com.gitblit.models.Menu.MenuItem; import com.gitblit.models.Menu.ParameterMenuItem; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; +import com.gitblit.models.NavLink; import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; @@ -40,8 +42,6 @@ import com.gitblit.wicket.CacheControl.LastModified; import com.gitblit.wicket.GitBlitWebApp; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.GitblitRedirectException; -import com.gitblit.wicket.PageRegistration; -import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.FilterableRepositoryList; @@ -161,10 +161,10 @@ public class ProjectPage extends DashboardPage { } @Override - protected void addDropDownMenus(List pages) { + protected void addDropDownMenus(List navLinks) { PageParameters params = getPageParameters(); - DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters", + DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters", ProjectPage.class); // preserve time filter option on repository choices menu.menuItems.addAll(getRepositoryFilterItems(params)); @@ -177,12 +177,12 @@ public class ProjectPage extends DashboardPage { menu.menuItems.add(new ParameterMenuItem(getString("gb.reset"), "p", WicketUtils.getProjectName(params))); } - pages.add(menu); + navLinks.add(menu); - DropDownMenuRegistration projects = new DropDownMenuRegistration("gb.projects", + DropDownPageMenuNavLink projects = new DropDownPageMenuNavLink("gb.projects", ProjectPage.class); projects.menuItems.addAll(getProjectsMenu()); - pages.add(projects); + navLinks.add(projects); } @Override diff --git a/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java b/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java index c404ae61..f04fa78a 100644 --- a/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java @@ -25,10 +25,10 @@ import org.apache.wicket.markup.repeater.data.ListDataProvider; import com.gitblit.Keys; import com.gitblit.models.Menu.ParameterMenuItem; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; +import com.gitblit.models.NavLink; import com.gitblit.models.ProjectModel; import com.gitblit.wicket.GitBlitWebSession; -import com.gitblit.wicket.PageRegistration; -import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.LinkPanel; @@ -115,10 +115,10 @@ public class ProjectsPage extends RootPage { } @Override - protected void addDropDownMenus(List pages) { + protected void addDropDownMenus(List navLinks) { PageParameters params = getPageParameters(); - DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters", + DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters", ProjectsPage.class); // preserve time filter option on repository choices menu.menuItems.addAll(getRepositoryFilterItems(params)); @@ -131,6 +131,6 @@ public class ProjectsPage extends RootPage { menu.menuItems.add(new ParameterMenuItem(getString("gb.reset"))); } - pages.add(menu); + navLinks.add(menu); } } diff --git a/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java b/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java index 41fe057c..a0b15a83 100644 --- a/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java @@ -30,14 +30,14 @@ import org.eclipse.jgit.lib.Constants; import com.gitblit.Keys; import com.gitblit.models.Menu.ParameterMenuItem; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; +import com.gitblit.models.NavLink; import com.gitblit.models.RepositoryModel; import com.gitblit.utils.MarkdownUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.CacheControl; import com.gitblit.wicket.CacheControl.LastModified; import com.gitblit.wicket.GitBlitWebSession; -import com.gitblit.wicket.PageRegistration; -import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.RepositoriesPanel; @@ -92,10 +92,10 @@ public class RepositoriesPage extends RootPage { } @Override - protected void addDropDownMenus(List pages) { + protected void addDropDownMenus(List navLinks) { PageParameters params = getPageParameters(); - DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters", + DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters", RepositoriesPage.class); // preserve time filter option on repository choices menu.menuItems.addAll(getRepositoryFilterItems(params)); @@ -108,7 +108,7 @@ public class RepositoriesPage extends RootPage { menu.menuItems.add(new ParameterMenuItem(getString("gb.reset"))); } - pages.add(menu); + navLinks.add(menu); } private String readMarkdown(String messageSource, String resource) { diff --git a/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java index 5ea99fd8..165feedf 100644 --- a/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -49,6 +48,10 @@ import org.slf4j.LoggerFactory; import com.gitblit.Constants; import com.gitblit.GitBlitException; import com.gitblit.Keys; +import com.gitblit.extensions.RepositoryNavLinkExtension; +import com.gitblit.models.NavLink; +import com.gitblit.models.NavLink.ExternalNavLink; +import com.gitblit.models.NavLink.PageNavLink; import com.gitblit.models.ProjectModel; import com.gitblit.models.RefModel; import com.gitblit.models.RepositoryModel; @@ -66,8 +69,6 @@ import com.gitblit.utils.RefLogUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.CacheControl; import com.gitblit.wicket.GitBlitWebSession; -import com.gitblit.wicket.PageRegistration; -import com.gitblit.wicket.PageRegistration.OtherPageLink; import com.gitblit.wicket.SessionlessForm; import com.gitblit.wicket.TicketsUI; import com.gitblit.wicket.WicketUtils; @@ -91,7 +92,6 @@ public abstract class RepositoryPage extends RootPage { private Map submodules; - private final Map registeredPages; private boolean showAdmin; private boolean isOwner; @@ -150,12 +150,11 @@ public abstract class RepositoryPage extends RootPage { } } - // register the available page links for this page and user - registeredPages = registerPages(); + // register the available navigation links for this page and user + List navLinks = registerNavLinks(); - // standard page links - List pages = new ArrayList(registeredPages.values()); - NavigationPanel navigationPanel = new NavigationPanel("repositoryNavPanel", getRepoNavPageClass(), pages); + // standard navigation links + NavigationPanel navigationPanel = new NavigationPanel("repositoryNavPanel", getRepoNavPageClass(), navLinks); add(navigationPanel); add(new ExternalLink("syndication", SyndicationServlet.asLink(getRequest() @@ -183,45 +182,56 @@ public abstract class RepositoryPage extends RootPage { return new BugtraqProcessor(app().settings()); } - private Map registerPages() { + private List registerNavLinks() { PageParameters params = null; if (!StringUtils.isEmpty(repositoryName)) { params = WicketUtils.newRepositoryParameter(repositoryName); } - Map pages = new LinkedHashMap(); + List navLinks = new ArrayList(); Repository r = getRepository(); RepositoryModel model = getRepositoryModel(); // standard links if (RefLogUtils.getRefLogBranch(r) == null) { - pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params)); + navLinks.add(new PageNavLink("gb.summary", SummaryPage.class, params)); } else { - pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params)); + navLinks.add(new PageNavLink("gb.summary", SummaryPage.class, params)); // pages.put("overview", new PageRegistration("gb.overview", OverviewPage.class, params)); - pages.put("reflog", new PageRegistration("gb.reflog", ReflogPage.class, params)); + navLinks.add(new PageNavLink("gb.reflog", ReflogPage.class, params)); } - pages.put("commits", new PageRegistration("gb.commits", LogPage.class, params)); - pages.put("tree", new PageRegistration("gb.tree", TreePage.class, params)); + navLinks.add(new PageNavLink("gb.commits", LogPage.class, params)); + navLinks.add(new PageNavLink("gb.tree", TreePage.class, params)); if (app().tickets().isReady() && (app().tickets().isAcceptingNewTickets(getRepositoryModel()) || app().tickets().hasTickets(getRepositoryModel()))) { PageParameters tParams = new PageParameters(params); for (String state : TicketsUI.openStatii) { tParams.add(Lucene.status.name(), state); } - pages.put("tickets", new PageRegistration("gb.tickets", TicketsPage.class, tParams)); + navLinks.add(new PageNavLink("gb.tickets", TicketsPage.class, tParams)); } - pages.put("docs", new PageRegistration("gb.docs", DocsPage.class, params, true)); + navLinks.add(new PageNavLink("gb.docs", DocsPage.class, params, true)); if (app().settings().getBoolean(Keys.web.allowForking, true)) { - pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params, true)); + navLinks.add(new PageNavLink("gb.forks", ForksPage.class, params, true)); } - pages.put("compare", new PageRegistration("gb.compare", ComparePage.class, params, true)); + navLinks.add(new PageNavLink("gb.compare", ComparePage.class, params, true)); // conditional links - // per-repository extra page links + // per-repository extra navlinks if (JGitUtils.getPagesBranch(r) != null) { - OtherPageLink pagesLink = new OtherPageLink("gb.pages", PagesServlet.asLink( + ExternalNavLink pagesLink = new ExternalNavLink("gb.pages", PagesServlet.asLink( getRequest().getRelativePathPrefixToContextRoot(), repositoryName, null), true); - pages.put("pages", pagesLink); + navLinks.add(pagesLink); + } + + UserModel user = UserModel.ANONYMOUS; + if (GitBlitWebSession.get().isLoggedIn()) { + user = GitBlitWebSession.get().getUser(); + } + + // add repository nav link extensions + List extensions = app().plugins().getExtensions(RepositoryNavLinkExtension.class); + for (RepositoryNavLinkExtension ext : extensions) { + navLinks.addAll(ext.getNavLinks(user, model)); } // Conditionally add edit link @@ -233,9 +243,8 @@ public abstract class RepositoryPage extends RootPage { showAdmin = app().settings().getBoolean(Keys.web.allowAdministration, false); } isOwner = GitBlitWebSession.get().isLoggedIn() - && (model.isOwner(GitBlitWebSession.get() - .getUsername())); - return pages; + && (model.isOwner(GitBlitWebSession.get().getUsername())); + return navLinks; } protected boolean allowForkControls() { diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java index 3003c70e..a2f3a497 100644 --- a/src/main/java/com/gitblit/wicket/pages/RootPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java @@ -50,6 +50,7 @@ import org.apache.wicket.protocol.http.WebResponse; import com.gitblit.Constants; import com.gitblit.Keys; +import com.gitblit.extensions.NavLinkExtension; import com.gitblit.extensions.UserMenuExtension; import com.gitblit.models.Menu.ExternalLinkMenuItem; import com.gitblit.models.Menu.MenuDivider; @@ -57,13 +58,14 @@ import com.gitblit.models.Menu.MenuItem; import com.gitblit.models.Menu.PageLinkMenuItem; import com.gitblit.models.Menu.ParameterMenuItem; import com.gitblit.models.Menu.ToggleMenuItem; +import com.gitblit.models.NavLink; +import com.gitblit.models.NavLink.PageNavLink; import com.gitblit.models.RepositoryModel; import com.gitblit.models.TeamModel; import com.gitblit.models.UserModel; import com.gitblit.utils.ModelUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; -import com.gitblit.wicket.PageRegistration; import com.gitblit.wicket.SessionlessForm; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.GravatarImage; @@ -174,50 +176,37 @@ public abstract class RootPage extends BasePage { } // navigation links - List pages = new ArrayList(); + List navLinks = new ArrayList(); if (!authenticateView || (authenticateView && isLoggedIn)) { - pages.add(new PageRegistration(isLoggedIn ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class, + navLinks.add(new PageNavLink(isLoggedIn ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class, getRootPageParameters())); if (isLoggedIn && app().tickets().isReady()) { - pages.add(new PageRegistration("gb.myTickets", MyTicketsPage.class)); + navLinks.add(new PageNavLink("gb.myTickets", MyTicketsPage.class)); } - pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class, + navLinks.add(new PageNavLink("gb.repositories", RepositoriesPage.class, getRootPageParameters())); - pages.add(new PageRegistration("gb.activity", ActivityPage.class, getRootPageParameters())); + navLinks.add(new PageNavLink("gb.activity", ActivityPage.class, getRootPageParameters())); if (allowLucene) { - pages.add(new PageRegistration("gb.search", LuceneSearchPage.class)); + navLinks.add(new PageNavLink("gb.search", LuceneSearchPage.class)); } - UserModel user = GitBlitWebSession.get().getUser(); - - if (showAdmin) { - // admin dropdown menu - DropDownMenuRegistration adminMenu = new DropDownMenuRegistration("gb.adminMenuItem", MyDashboardPage.class); - - adminMenu.menuItems.add(new PageLinkMenuItem(getString("gb.users"), UsersPage.class)); - - boolean showRegistrations = app().federation().canFederate() - && app().settings().getBoolean(Keys.web.showFederationRegistrations, false); - if (showRegistrations) { - adminMenu.menuItems.add(new PageLinkMenuItem(getString("gb.federation"), FederationPage.class)); - } - - // allow plugins to contribute admin menu items - List extensions = app().plugins().getExtensions(AdminMenuExtension.class); - for (AdminMenuExtension ext : extensions) { - adminMenu.menuItems.add(new MenuDivider()); - adminMenu.menuItems.addAll(ext.getMenuItems(user)); - } + if (!authenticateView || (authenticateView && isLoggedIn)) { + addDropDownMenus(navLinks); + } - pages.add(adminMenu); + UserModel user = UserModel.ANONYMOUS; + if (isLoggedIn) { + user = GitBlitWebSession.get().getUser(); } - if (!authenticateView || (authenticateView && isLoggedIn)) { - addDropDownMenus(pages); + // add nav link extensions + List extensions = app().plugins().getExtensions(NavLinkExtension.class); + for (NavLinkExtension ext : extensions) { + navLinks.addAll(ext.getNavLinks(user)); } } - NavigationPanel navPanel = new NavigationPanel("navPanel", getRootNavPageClass(), pages); + NavigationPanel navPanel = new NavigationPanel("navPanel", getRootNavPageClass(), navLinks); add(navPanel); // display an error message cached from a redirect @@ -309,7 +298,7 @@ public abstract class RootPage extends BasePage { return repositoryModels; } - protected void addDropDownMenus(List pages) { + protected void addDropDownMenus(List navLinks) { } diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 0767621c..6cb791eb 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -30,6 +30,8 @@ import org.eclipse.jgit.lib.PersonIdent; import com.gitblit.Keys; import com.gitblit.models.Menu.ParameterMenuItem; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; +import com.gitblit.models.NavLink; import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; @@ -37,8 +39,6 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebApp; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.GitblitRedirectException; -import com.gitblit.wicket.PageRegistration; -import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.GravatarImage; import com.gitblit.wicket.panels.LinkPanel; @@ -127,10 +127,10 @@ public class UserPage extends RootPage { } @Override - protected void addDropDownMenus(List pages) { + protected void addDropDownMenus(List navLinks) { PageParameters params = getPageParameters(); - DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters", + DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters", UserPage.class); // preserve time filter option on repository choices menu.menuItems.addAll(getRepositoryFilterItems(params)); @@ -143,6 +143,6 @@ public class UserPage extends RootPage { menu.menuItems.add(new ParameterMenuItem(getString("gb.reset"))); } - pages.add(menu); + navLinks.add(menu); } } diff --git a/src/main/java/com/gitblit/wicket/panels/DropDownMenu.java b/src/main/java/com/gitblit/wicket/panels/DropDownMenu.java index f561143d..4e7ae54c 100644 --- a/src/main/java/com/gitblit/wicket/panels/DropDownMenu.java +++ b/src/main/java/com/gitblit/wicket/panels/DropDownMenu.java @@ -21,24 +21,24 @@ import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.data.DataView; import org.apache.wicket.markup.repeater.data.ListDataProvider; -import com.gitblit.models.Menu.MenuDivider; import com.gitblit.models.Menu.ExternalLinkMenuItem; +import com.gitblit.models.Menu.MenuDivider; import com.gitblit.models.Menu.MenuItem; import com.gitblit.models.Menu.PageLinkMenuItem; import com.gitblit.models.Menu.ParameterMenuItem; -import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; +import com.gitblit.models.NavLink.DropDownMenuNavLink; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; import com.gitblit.wicket.WicketUtils; public class DropDownMenu extends Panel { private static final long serialVersionUID = 1L; - public DropDownMenu(String id, String label, final DropDownMenuRegistration menu) { + public DropDownMenu(String id, String label, final DropDownPageMenuNavLink menu) { super(id); add(new Label("label", label).setRenderBodyOnly(true)); - ListDataProvider items = new ListDataProvider( - menu.menuItems); + ListDataProvider items = new ListDataProvider(menu.menuItems); DataView view = new DataView("menuItems", items) { private static final long serialVersionUID = 1L; @@ -76,4 +76,39 @@ public class DropDownMenu extends Panel { add(view); setRenderBodyOnly(true); } + + public DropDownMenu(String id, String label, final DropDownMenuNavLink menu) { + super(id); + + add(new Label("label", label).setRenderBodyOnly(true)); + ListDataProvider items = new ListDataProvider(menu.menuItems); + DataView view = new DataView("menuItems", items) { + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(final Item item) { + MenuItem entry = item.getModelObject(); + if (entry instanceof PageLinkMenuItem) { + // link to another Wicket page + PageLinkMenuItem pageLink = (PageLinkMenuItem) entry; + item.add(new LinkPanel("menuItem", null, null, pageLink.toString(), pageLink.getPageClass(), + pageLink.getPageParameters(), false).setRenderBodyOnly(true)); + } else if (entry instanceof ExternalLinkMenuItem) { + // link to a specified href + ExternalLinkMenuItem extLink = (ExternalLinkMenuItem) entry; + item.add(new LinkPanel("menuItem", null, extLink.toString(), extLink.getHref(), + extLink.openInNewWindow()).setRenderBodyOnly(true)); + } else if (entry instanceof MenuDivider) { + // divider + item.add(new Label("menuItem").setRenderBodyOnly(true)); + WicketUtils.setCssClass(item, "divider"); + } else { + throw new IllegalArgumentException(String.format("Unexpected menuitem type %s", + entry.getClass().getSimpleName())); + } + } + }; + add(view); + setRenderBodyOnly(true); + } } \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/NavigationPanel.java b/src/main/java/com/gitblit/wicket/panels/NavigationPanel.java index 7db29fa2..2bc92f4c 100644 --- a/src/main/java/com/gitblit/wicket/panels/NavigationPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/NavigationPanel.java @@ -23,9 +23,11 @@ import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.data.DataView; import org.apache.wicket.markup.repeater.data.ListDataProvider; -import com.gitblit.wicket.PageRegistration; -import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; -import com.gitblit.wicket.PageRegistration.OtherPageLink; +import com.gitblit.models.NavLink; +import com.gitblit.models.NavLink.DropDownMenuNavLink; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; +import com.gitblit.models.NavLink.ExternalNavLink; +import com.gitblit.models.NavLink.PageNavLink; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.pages.BasePage; @@ -34,52 +36,59 @@ public class NavigationPanel extends Panel { private static final long serialVersionUID = 1L; public NavigationPanel(String id, final Class pageClass, - List registeredPages) { + List navLinks) { super(id); - ListDataProvider refsDp = new ListDataProvider( - registeredPages); - DataView refsView = new DataView("navLink", refsDp) { + ListDataProvider refsDp = new ListDataProvider(navLinks); + DataView linksView = new DataView("navLink", refsDp) { private static final long serialVersionUID = 1L; @Override - public void populateItem(final Item item) { - PageRegistration entry = item.getModelObject(); - String linkText = entry.translationKey; + public void populateItem(final Item item) { + NavLink navLink = item.getModelObject(); + String linkText = navLink.translationKey; try { // try to lookup translation key - linkText = getString(entry.translationKey); + linkText = getString(navLink.translationKey); } catch (Exception e) { } - if (entry.hiddenPhone) { + if (navLink.hiddenPhone) { WicketUtils.setCssClass(item, "hidden-phone"); } - if (entry instanceof OtherPageLink) { + if (navLink instanceof ExternalNavLink) { // other link - OtherPageLink link = (OtherPageLink) entry; + ExternalNavLink link = (ExternalNavLink) navLink; Component c = new LinkPanel("link", null, linkText, link.url); c.setRenderBodyOnly(true); item.add(c); - } else if (entry instanceof DropDownMenuRegistration) { + } else if (navLink instanceof DropDownPageMenuNavLink) { // drop down menu - DropDownMenuRegistration reg = (DropDownMenuRegistration) entry; + DropDownPageMenuNavLink reg = (DropDownPageMenuNavLink) navLink; Component c = new DropDownMenu("link", linkText, reg); c.setRenderBodyOnly(true); item.add(c); WicketUtils.setCssClass(item, "dropdown"); - } else { + } else if (navLink instanceof DropDownMenuNavLink) { + // drop down menu + DropDownMenuNavLink reg = (DropDownMenuNavLink) navLink; + Component c = new DropDownMenu("link", linkText, reg); + c.setRenderBodyOnly(true); + item.add(c); + WicketUtils.setCssClass(item, "dropdown"); + } else if (navLink instanceof PageNavLink) { + PageNavLink reg = (PageNavLink) navLink; // standard page link Component c = new LinkPanel("link", null, linkText, - entry.pageClass, entry.params); + reg.pageClass, reg.params); c.setRenderBodyOnly(true); - if (entry.pageClass.equals(pageClass)) { + if (reg.pageClass.equals(pageClass)) { WicketUtils.setCssClass(item, "active"); } item.add(c); } } }; - add(refsView); + add(linksView); } } \ No newline at end of file diff --git a/src/site/plugins_extensions.mkd b/src/site/plugins_extensions.mkd index 18a7e325..7bf63c17 100644 --- a/src/site/plugins_extensions.mkd +++ b/src/site/plugins_extensions.mkd @@ -52,6 +52,37 @@ public class ExamplePlugin extends GitblitPlugin { public void onUninstall() { } } + +/** + * You can also create Webapp plugins that register mounted pages. + */ +public class ExampleWicketPlugin extends GitblitWicketPlugin { + @Override + public void start() { + } + + @Override + public void stop() { + } + + @Override + public void onInstall() { + } + + @Override + public void onUpgrade(Version oldVersion) { + } + + @Override + public void onUninstall() { + } + + @Override + protected void init(GitblitWicketApp app) { + app.mount("/logo", LogoPage.class); + app.mount("/hello", HelloWorldPage.class); + } +} ``` ### SSH Dispatch Command @@ -225,7 +256,32 @@ public class MyUserMenuContributor extends UserMenuExtension { @Override public List getMenuItems(UserModel user) { - return Arrays.asList((MenuItem) new ExternalLinkMenuItem("Github", String.format("https://github.com/%s", user.username)); + MenuItem item = new ExternalLinkMenuItem("Github", String.format("https://github.com/%s", user.username)); + return Arrays.asList(item); + } +} +``` + +### Navigation Links + +*SINCE 1.6.0* + +You can provide your own top-level navigation links by subclassing the *NavLinkExtension* class. + +```java +import java.util.Arrays; +import java.util.List; +import ro.fortsoft.pf4j.Extension; +import com.gitblit.extensions.NavLinkExtension; +import com.gitblit.models.UserModel; + +@Extension +public class MyNavLink extends NavLinkExtension { + + @Override + public List getNavLinks(UserModel user) { + NavLink link = new ExternalLinkMenuItem("Github", String.format("https://github.com/%s", user.username)); + return Arrays.asList(link); } } ``` -- cgit v1.2.3 From 6537deb8b76b7a4725c40a174a7c440385f88e51 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 5 Jun 2014 10:20:59 -0400 Subject: Revise language/locale preference handling --- src/main/java/com/gitblit/ConfigUserService.java | 9 +++++--- .../java/com/gitblit/models/UserPreferences.java | 6 ++++- .../com/gitblit/wicket/GitBlitWebApp.properties | 2 +- .../java/com/gitblit/wicket/pages/UserPage.java | 26 ++++++++++++++-------- 4 files changed, 29 insertions(+), 14 deletions(-) (limited to 'src/main/java/com/gitblit/models') diff --git a/src/main/java/com/gitblit/ConfigUserService.java b/src/main/java/com/gitblit/ConfigUserService.java index 9b4dd7f1..b5dfde3b 100644 --- a/src/main/java/com/gitblit/ConfigUserService.java +++ b/src/main/java/com/gitblit/ConfigUserService.java @@ -707,8 +707,9 @@ public class ConfigUserService implements IUserService { config.setBoolean(USER, model.username, DISABLED, true); } if (model.getPreferences() != null) { - if (!StringUtils.isEmpty(model.getPreferences().locale)) { - config.setString(USER, model.username, LOCALE, model.getPreferences().locale); + if (model.getPreferences().getLocale() != null) { + String val = model.getPreferences().getLocale().getLanguage() + "_" + model.getPreferences().getLocale().getCountry(); + config.setString(USER, model.username, LOCALE, val); } } @@ -880,11 +881,13 @@ public class ConfigUserService implements IUserService { user.stateProvince = config.getString(USER, username, STATEPROVINCE); user.countryCode = config.getString(USER, username, COUNTRYCODE); user.cookie = config.getString(USER, username, COOKIE); - user.getPreferences().locale = config.getString(USER, username, LOCALE); if (StringUtils.isEmpty(user.cookie) && !StringUtils.isEmpty(user.password)) { user.cookie = StringUtils.getSHA1(user.username + user.password); } + // preferences + user.getPreferences().setLocale(config.getString(USER, username, LOCALE)); + // user roles Set roles = new HashSet(Arrays.asList(config.getStringList( USER, username, ROLE))); diff --git a/src/main/java/com/gitblit/models/UserPreferences.java b/src/main/java/com/gitblit/models/UserPreferences.java index 44e44933..61db353c 100644 --- a/src/main/java/com/gitblit/models/UserPreferences.java +++ b/src/main/java/com/gitblit/models/UserPreferences.java @@ -37,7 +37,7 @@ public class UserPreferences implements Serializable { public final String username; - public String locale; + private String locale; private final Map repositoryPreferences = new TreeMap(); @@ -58,6 +58,10 @@ public class UserPreferences implements Serializable { return new Locale(locale); } + public void setLocale(String locale) { + this.locale = locale; + } + public UserRepositoryPreferences getRepositoryPreferences(String repositoryName) { String key = repositoryName.toLowerCase(); if (!repositoryPreferences.containsKey(key)) { diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 7dc0f9b6..90d30f29 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -727,7 +727,7 @@ gb.preferences = preferences gb.accountPreferences = Account Preferences gb.accountPreferencesDescription = Specify your account preferences gb.languagePreference = Language Preference -gb.languagePreferenceDescription = Select your preferred translation for the Gitblit UI +gb.languagePreferenceDescription = Select your preferred translation for Gitblit gb.displayNameDescription = The preferred name for display gb.emailAddressDescription = The primary email address for receiving notifications gb.sshKeys = SSH Keys diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 4a955c7c..94048963 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -181,28 +181,36 @@ public class UserPage extends RootPage { new Language("Português", "pt_BR"), new Language("中文", "zh_CN")); - String lc = user.getPreferences().locale; - if (StringUtils.isEmpty(lc)) { + Locale locale = user.getPreferences().getLocale(); + if (locale == null) { // user has not specified language preference // try server default preference - lc = app().settings().getString(Keys.web.forceDefaultLocale, null); + String lc = app().settings().getString(Keys.web.forceDefaultLocale, null); if (StringUtils.isEmpty(lc)) { // server default language is not configured // try browser preference Locale sessionLocale = GitBlitWebSession.get().getLocale(); if (sessionLocale != null) { - lc = sessionLocale.getLanguage() + "_" + sessionLocale.getCountry(); + locale = sessionLocale; } + } else { + } } + Language preferredLanguage = null; - if (!StringUtils.isEmpty(lc)) { + if (locale != null) { + String localeCode = locale.getLanguage(); + if (!StringUtils.isEmpty(locale.getCountry())) { + localeCode += "_" + locale.getCountry(); + } + for (Language language : languages) { - if (language.code.equals(lc)) { + if (language.code.equals(localeCode)) { // language_COUNTRY match preferredLanguage = language; - } else if (preferredLanguage != null && lc.startsWith(language.code)) { - // language match, but not COUNTRY match + } else if (preferredLanguage != null && language.code.startsWith(locale.getLanguage())) { + // language match preferredLanguage = language; } } @@ -242,7 +250,7 @@ public class UserPage extends RootPage { Language lang = language.getObject(); if (lang != null) { - user.getPreferences().locale = lang.code; + user.getPreferences().setLocale(lang.code); } try { -- cgit v1.2.3 From afbaebde11093fae8b420aaaf71dcd56d8c0f9fd Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 5 Jun 2014 10:24:39 -0400 Subject: Add "email me on my ticket changes" preference --- src/main/java/com/gitblit/ConfigUserService.java | 4 ++++ src/main/java/com/gitblit/models/UserPreferences.java | 13 +++++++++++++ src/main/java/com/gitblit/tickets/TicketNotifier.java | 11 +++++++++-- src/main/java/com/gitblit/wicket/GitBlitWebApp.properties | 2 ++ src/main/java/com/gitblit/wicket/pages/UserPage.html | 3 ++- src/main/java/com/gitblit/wicket/pages/UserPage.java | 9 +++++++++ 6 files changed, 39 insertions(+), 3 deletions(-) (limited to 'src/main/java/com/gitblit/models') diff --git a/src/main/java/com/gitblit/ConfigUserService.java b/src/main/java/com/gitblit/ConfigUserService.java index b5dfde3b..9759eff7 100644 --- a/src/main/java/com/gitblit/ConfigUserService.java +++ b/src/main/java/com/gitblit/ConfigUserService.java @@ -96,6 +96,8 @@ public class ConfigUserService implements IUserService { private static final String LOCALE = "locale"; + private static final String EMAILONMYTICKETCHANGES = "emailMeOnMyTicketChanges"; + private static final String ACCOUNTTYPE = "accountType"; private static final String DISABLED = "disabled"; @@ -711,6 +713,7 @@ public class ConfigUserService implements IUserService { String val = model.getPreferences().getLocale().getLanguage() + "_" + model.getPreferences().getLocale().getCountry(); config.setString(USER, model.username, LOCALE, val); } + config.setBoolean(USER, model.username, EMAILONMYTICKETCHANGES, model.getPreferences().isEmailMeOnMyTicketChanges()); } // user roles @@ -887,6 +890,7 @@ public class ConfigUserService implements IUserService { // preferences user.getPreferences().setLocale(config.getString(USER, username, LOCALE)); + user.getPreferences().setEmailMeOnMyTicketChanges(config.getBoolean(USER, username, EMAILONMYTICKETCHANGES, true)); // user roles Set roles = new HashSet(Arrays.asList(config.getStringList( diff --git a/src/main/java/com/gitblit/models/UserPreferences.java b/src/main/java/com/gitblit/models/UserPreferences.java index 61db353c..c95b0da5 100644 --- a/src/main/java/com/gitblit/models/UserPreferences.java +++ b/src/main/java/com/gitblit/models/UserPreferences.java @@ -39,6 +39,8 @@ public class UserPreferences implements Serializable { private String locale; + private Boolean emailMeOnMyTicketChanges; + private final Map repositoryPreferences = new TreeMap(); public UserPreferences(String username) { @@ -100,4 +102,15 @@ public class UserPreferences implements Serializable { Collections.sort(list); return list; } + + public boolean isEmailMeOnMyTicketChanges() { + if (emailMeOnMyTicketChanges == null) { + return true; + } + return emailMeOnMyTicketChanges; + } + + public void setEmailMeOnMyTicketChanges(boolean value) { + this.emailMeOnMyTicketChanges = value; + } } diff --git a/src/main/java/com/gitblit/tickets/TicketNotifier.java b/src/main/java/com/gitblit/tickets/TicketNotifier.java index 9a5e4e1d..07371b1b 100644 --- a/src/main/java/com/gitblit/tickets/TicketNotifier.java +++ b/src/main/java/com/gitblit/tickets/TicketNotifier.java @@ -545,7 +545,6 @@ public class TicketNotifier { } } } - mailing.setRecipients(toAddresses); // // CC recipients @@ -554,7 +553,7 @@ public class TicketNotifier { // repository owners if (!ArrayUtils.isEmpty(repository.owners)) { - tos.addAll(repository.owners); + ccs.addAll(repository.owners); } // cc users mentioned in last comment @@ -595,6 +594,14 @@ public class TicketNotifier { } ccAddresses.addAll(settings.getStrings(Keys.mail.mailingLists)); + // respect the author's email preference + UserModel lastAuthor = userManager.getUserModel(lastChange.author); + if (!lastAuthor.getPreferences().isEmailMeOnMyTicketChanges()) { + toAddresses.remove(lastAuthor.emailAddress); + ccAddresses.remove(lastAuthor.emailAddress); + } + + mailing.setRecipients(toAddresses); mailing.setCCs(ccAddresses); } diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 90d30f29..c80d45ce 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -728,6 +728,8 @@ gb.accountPreferences = Account Preferences gb.accountPreferencesDescription = Specify your account preferences gb.languagePreference = Language Preference gb.languagePreferenceDescription = Select your preferred translation for Gitblit +gb.emailMeOnMyTicketChanges = Email me on my ticket changes +gb.emailMeOnMyTicketChangesDescription = Send me an email notification for changes that I make to a ticket gb.displayNameDescription = The preferred name for display gb.emailAddressDescription = The primary email address for receiving notifications gb.sshKeys = SSH Keys diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.html b/src/main/java/com/gitblit/wicket/pages/UserPage.html index d71cb2b5..017fcb1f 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.html +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.html @@ -64,7 +64,8 @@
-
+
+
diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 94048963..505f55d9 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -48,6 +48,7 @@ import com.gitblit.wicket.GitBlitWebApp; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.GitblitRedirectException; import com.gitblit.wicket.WicketUtils; +import com.gitblit.wicket.panels.BooleanOption; import com.gitblit.wicket.panels.ChoiceOption; import com.gitblit.wicket.panels.ProjectRepositoryPanel; import com.gitblit.wicket.panels.SshKeysPanel; @@ -219,6 +220,7 @@ public class UserPage extends RootPage { final IModel displayName = Model.of(user.getDisplayName()); final IModel emailAddress = Model.of(user.emailAddress == null ? "" : user.emailAddress); final IModel language = Model.of(preferredLanguage); + final IModel emailMeOnMyTicketChanges = Model.of(user.getPreferences().isEmailMeOnMyTicketChanges()); prefs.add(new TextOption("displayName", getString("gb.displayName"), @@ -236,6 +238,11 @@ public class UserPage extends RootPage { language, languages)); + prefs.add(new BooleanOption("emailMeOnMyTicketChanges", + getString("gb.emailMeOnMyTicketChanges"), + getString("gb.emailMeOnMyTicketChangesDescription"), + emailMeOnMyTicketChanges).setVisible(app().notifier().isSendingMail())); + prefs.add(new AjaxButton("save") { private static final long serialVersionUID = 1L; @@ -253,6 +260,8 @@ public class UserPage extends RootPage { user.getPreferences().setLocale(lang.code); } + user.getPreferences().setEmailMeOnMyTicketChanges(emailMeOnMyTicketChanges.getObject()); + try { app().gitblit().reviseUser(user.username, user); -- cgit v1.2.3 From 1b04d7730f56a08c935974504b2d849d01870c02 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 5 Jun 2014 14:14:54 -0400 Subject: Add clone transport user preference --- releases.moxie | 1 + src/main/java/com/gitblit/ConfigUserService.java | 9 +++++++++ src/main/java/com/gitblit/GitBlit.java | 19 +++++++++++++++++++ .../java/com/gitblit/models/UserPreferences.java | 11 +++++++++++ .../com/gitblit/wicket/GitBlitWebApp.properties | 4 +++- .../java/com/gitblit/wicket/pages/UserPage.html | 1 + .../java/com/gitblit/wicket/pages/UserPage.java | 21 +++++++++++++++++++++ 7 files changed, 65 insertions(+), 1 deletion(-) (limited to 'src/main/java/com/gitblit/models') diff --git a/releases.moxie b/releases.moxie index fc139b77..c1e11d98 100644 --- a/releases.moxie +++ b/releases.moxie @@ -43,6 +43,7 @@ r24: { - Simplified repository creation, offer simple README generation, and insertion of a pre-defined .gitignore file (ticket-76) - Added an extension point for monitoring onStartup and onShutdown (ticket-79) - Tag server-side merges when incremental push tags are enabled (issue-432, ticket-85) + - Add a user preference for the clone transport (ticket-90) - Add setting to control default thread pool size for miscellaneous background tasks (ticket-92) dependencyChanges: - Update to javax.mail 1.5.1 (issue-417, ticket-58) diff --git a/src/main/java/com/gitblit/ConfigUserService.java b/src/main/java/com/gitblit/ConfigUserService.java index 9759eff7..0c5b2a58 100644 --- a/src/main/java/com/gitblit/ConfigUserService.java +++ b/src/main/java/com/gitblit/ConfigUserService.java @@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory; import com.gitblit.Constants.AccessPermission; import com.gitblit.Constants.AccountType; +import com.gitblit.Constants.Transport; import com.gitblit.manager.IRuntimeManager; import com.gitblit.models.TeamModel; import com.gitblit.models.UserModel; @@ -98,6 +99,8 @@ public class ConfigUserService implements IUserService { private static final String EMAILONMYTICKETCHANGES = "emailMeOnMyTicketChanges"; + private static final String TRANSPORT = "transport"; + private static final String ACCOUNTTYPE = "accountType"; private static final String DISABLED = "disabled"; @@ -713,7 +716,12 @@ public class ConfigUserService implements IUserService { String val = model.getPreferences().getLocale().getLanguage() + "_" + model.getPreferences().getLocale().getCountry(); config.setString(USER, model.username, LOCALE, val); } + config.setBoolean(USER, model.username, EMAILONMYTICKETCHANGES, model.getPreferences().isEmailMeOnMyTicketChanges()); + + if (model.getPreferences().getTransport() != null) { + config.setString(USER, model.username, TRANSPORT, model.getPreferences().getTransport().name()); + } } // user roles @@ -891,6 +899,7 @@ public class ConfigUserService implements IUserService { // preferences user.getPreferences().setLocale(config.getString(USER, username, LOCALE)); user.getPreferences().setEmailMeOnMyTicketChanges(config.getBoolean(USER, username, EMAILONMYTICKETCHANGES, true)); + user.getPreferences().setTransport(Transport.fromString(config.getString(USER, username, TRANSPORT))); // user roles Set roles = new HashSet(Arrays.asList(config.getStringList( diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java index 81793850..f9d9be9f 100644 --- a/src/main/java/com/gitblit/GitBlit.java +++ b/src/main/java/com/gitblit/GitBlit.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -264,6 +265,24 @@ public class GitBlit extends GitblitManager { } }); + // consider the user's transport preference + RepositoryUrl preferredUrl = null; + Transport preferredTransport = user.getPreferences().getTransport(); + if (preferredTransport != null) { + Iterator itr = list.iterator(); + while (itr.hasNext()) { + RepositoryUrl url = itr.next(); + if (url.transport.equals(preferredTransport)) { + itr.remove(); + preferredUrl = url; + break; + } + } + } + if (preferredUrl != null) { + list.add(0, preferredUrl); + } + return list; } diff --git a/src/main/java/com/gitblit/models/UserPreferences.java b/src/main/java/com/gitblit/models/UserPreferences.java index c95b0da5..90c034fc 100644 --- a/src/main/java/com/gitblit/models/UserPreferences.java +++ b/src/main/java/com/gitblit/models/UserPreferences.java @@ -23,6 +23,7 @@ import java.util.Locale; import java.util.Map; import java.util.TreeMap; +import com.gitblit.Constants.Transport; import com.gitblit.utils.StringUtils; /** @@ -41,6 +42,8 @@ public class UserPreferences implements Serializable { private Boolean emailMeOnMyTicketChanges; + private Transport transport; + private final Map repositoryPreferences = new TreeMap(); public UserPreferences(String username) { @@ -113,4 +116,12 @@ public class UserPreferences implements Serializable { public void setEmailMeOnMyTicketChanges(boolean value) { this.emailMeOnMyTicketChanges = value; } + + public Transport getTransport() { + return transport; + } + + public void setTransport(Transport transport) { + this.transport = transport; + } } diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index c80d45ce..eb92e2d2 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -739,4 +739,6 @@ gb.key = Key gb.comment = Comment gb.sshKeyCommentDescription = Enter an optional comment. If blank, the comment will be extracted from the key data. gb.permission = Permission -gb.sshKeyPermissionDescription = Specify the access permission for the SSH key \ No newline at end of file +gb.sshKeyPermissionDescription = Specify the access permission for the SSH key +gb.transportPreference = Transport Preference +gb.transportPreferenceDescription = Set the transport that you prefer to use for cloning \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.html b/src/main/java/com/gitblit/wicket/pages/UserPage.html index 017fcb1f..8dccfee7 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.html +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.html @@ -66,6 +66,7 @@
+
diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 00a36272..306eea65 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -35,6 +35,7 @@ import org.apache.wicket.markup.repeater.data.ListDataProvider; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; +import com.gitblit.Constants.Transport; import com.gitblit.GitBlitException; import com.gitblit.Keys; import com.gitblit.models.Menu.ParameterMenuItem; @@ -221,6 +222,7 @@ public class UserPage extends RootPage { final IModel emailAddress = Model.of(user.emailAddress == null ? "" : user.emailAddress); final IModel language = Model.of(preferredLanguage); final IModel emailMeOnMyTicketChanges = Model.of(user.getPreferences().isEmailMeOnMyTicketChanges()); + final IModel transport = Model.of(user.getPreferences().getTransport()); prefs.add(new TextOption("displayName", getString("gb.displayName"), @@ -243,6 +245,24 @@ public class UserPage extends RootPage { getString("gb.emailMeOnMyTicketChangesDescription"), emailMeOnMyTicketChanges).setVisible(app().notifier().isSendingMail())); + List availableTransports = new ArrayList<>(); + if (app().gitblit().isServingSSH()) { + availableTransports.add(Transport.SSH); + } + if (app().gitblit().isServingHTTP()) { + availableTransports.add(Transport.HTTPS); + availableTransports.add(Transport.HTTP); + } + if (app().gitblit().isServingGIT()) { + availableTransports.add(Transport.GIT); + } + + prefs.add(new ChoiceOption("transport", + getString("gb.transportPreference"), + getString("gb.transportPreferenceDescription"), + transport, + availableTransports)); + prefs.add(new AjaxButton("save") { private static final long serialVersionUID = 1L; @@ -261,6 +281,7 @@ public class UserPage extends RootPage { } user.getPreferences().setEmailMeOnMyTicketChanges(emailMeOnMyTicketChanges.getObject()); + user.getPreferences().setTransport(transport.getObject()); try { app().gitblit().reviseUser(user.username, user); -- cgit v1.2.3