/*******************************************************************************
* Copyright (c) 2015 Development Gateway, Inc and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the MIT License (MIT)
* which accompanies this distribution, and is available at
* https://opensource.org/licenses/MIT
*
* Contributors:
* Development Gateway - initial API and implementation
*******************************************************************************/
package org.devgateway.toolkit.forms.wicket.page;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.apache.log4j.Logger;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.head.filter.HeaderResponseContainer;
import org.apache.wicket.markup.html.GenericWebPage;
import org.apache.wicket.markup.html.TransparentWebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.markup.html.pages.RedirectPage;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.WebSession;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.resource.JQueryResourceReference;
import org.apache.wicket.util.string.StringValue;
import org.devgateway.toolkit.forms.WebConstants;
import org.devgateway.toolkit.forms.security.SecurityConstants;
import org.devgateway.toolkit.forms.security.SecurityUtil;
import org.devgateway.toolkit.forms.wicket.page.lists.ListGroupPage;
import org.devgateway.toolkit.forms.wicket.page.lists.ListTestFormPage;
import org.devgateway.toolkit.forms.wicket.page.user.EditUserPage;
import org.devgateway.toolkit.forms.wicket.page.user.LogoutPage;
import org.devgateway.toolkit.forms.wicket.styles.BaseStyles;
import org.devgateway.toolkit.persistence.dao.Person;
import de.agilecoders.wicket.core.markup.html.bootstrap.behavior.CssClassNameAppender;
import de.agilecoders.wicket.core.markup.html.bootstrap.button.dropdown.MenuBookmarkablePageLink;
import de.agilecoders.wicket.core.markup.html.bootstrap.common.NotificationPanel;
import de.agilecoders.wicket.core.markup.html.bootstrap.html.HtmlTag;
import de.agilecoders.wicket.core.markup.html.bootstrap.image.GlyphIconType;
import de.agilecoders.wicket.core.markup.html.bootstrap.navbar.Navbar;
import de.agilecoders.wicket.core.markup.html.bootstrap.navbar.NavbarButton;
import de.agilecoders.wicket.core.markup.html.bootstrap.navbar.NavbarComponents;
import de.agilecoders.wicket.core.markup.html.bootstrap.navbar.NavbarDropDownButton;
import de.agilecoders.wicket.core.markup.html.references.RespondJavaScriptReference;
import de.agilecoders.wicket.core.markup.html.themes.bootstrap.BootstrapCssReference;
import de.agilecoders.wicket.core.util.CssClassNames;
import de.agilecoders.wicket.extensions.markup.html.bootstrap.icon.FontAwesomeCssReference;
import de.agilecoders.wicket.extensions.markup.html.bootstrap.icon.FontAwesomeIconType;
/**
* Base wicket-bootstrap {@link org.apache.wicket.Page}
*
* @author miha
*/
public abstract class BasePage extends GenericWebPage<Void> {
private static final long serialVersionUID = -4179591658828697452L;
protected static Logger logger = Logger.getLogger(BasePage.class);
protected TransparentWebMarkupContainer mainContainer;
protected Header mainHeader;
protected Footer mainFooter;
protected Label pageTitle;
private Navbar navbar;
protected NotificationPanel feedbackPanel;
/**
* Determines if this page has a fluid container for the content or not.
*/
public Boolean fluidContainer() {
return false;
}
public static class HALRedirectPage extends RedirectPage {
private static final long serialVersionUID = -750983217518258464L;
public HALRedirectPage() {
super(WebApplication.get().getServletContext().getContextPath() + "/api/browser/");
}
}
public static class JminixRedirectPage extends RedirectPage {
private static final long serialVersionUID = -750983217518258464L;
public JminixRedirectPage() {
super(WebApplication.get().getServletContext().getContextPath() + "/jminix/");
}
}
public static class UIRedirectPage extends RedirectPage {
private static final long serialVersionUID = -750983217518258464L;
public UIRedirectPage() {
super(WebApplication.get().getServletContext().getContextPath() + "/ui/index.html");
}
}
/**
* Selects/changes the default language in the current session. If the
* {@link WebConstants#LANGUAGE_PARAM} is found in the
* {@link PageParameters} then its contents is set as language in the
* session object.
*/
protected void selectLanguage() {
StringValue lang = this.getPageParameters().get(WebConstants.LANGUAGE_PARAM);
if (!lang.isEmpty()) {
WebSession.get().setLocale(new Locale(lang.toString()));
}
}
/**
* Construct.
*
* @param parameters
* current page parameters
*/
public BasePage(final PageParameters parameters) {
super(parameters);
selectLanguage();
add(new HtmlTag("html"));
// Add javascript files.
add(new HeaderResponseContainer("scripts-container", "scripts-bucket"));
feedbackPanel = createFeedbackPanel();
add(feedbackPanel);
mainContainer = new TransparentWebMarkupContainer("mainContainer");
add(mainContainer);
// Set the bootstrap container class.
// @see https://getbootstrap.com/css/#grid
if (fluidContainer()) {
mainContainer.add(new CssClassNameAppender(CssClassNames.Grid.containerFluid));
} else {
mainContainer.add(new CssClassNameAppender(CssClassNames.Grid.container));
}
mainHeader = new Header("mainHeader", this.getPageParameters());
add(mainHeader);
navbar = newNavbar("navbar");
mainHeader.add(navbar);
// Add information about navbar position on mainHeader element.
if (navbar.getPosition().equals(Navbar.Position.DEFAULT)) {
mainHeader.add(new CssClassNameAppender("with-navbar-default"));
} else {
mainHeader.add(new CssClassNameAppender("with-" + navbar.getPosition().cssClassName()));
}
mainFooter = new Footer("mainFooter");
add(mainFooter);
pageTitle = new Label("pageTitle", new ResourceModel("page.title"));
add(pageTitle);
}
protected NotificationPanel createFeedbackPanel() {
NotificationPanel notificationPanel = new NotificationPanel("feedback");
notificationPanel.setOutputMarkupId(true);
return notificationPanel;
}
public NavbarDropDownButton newLanguageMenu() {
final NavbarDropDownButton languageDropDown =
new NavbarDropDownButton(new StringResourceModel("navbar.lang", this, null)) {
private static final long serialVersionUID = 319842753824102674L;
@Override
protected List<AbstractLink> newSubMenuButtons(final String buttonMarkupId) {
final List<AbstractLink> list = new ArrayList<>();
for (final Locale l : WebConstants.AVAILABLE_LOCALES) {
final PageParameters params = new PageParameters(BasePage.this.getPageParameters());
params.set(WebConstants.LANGUAGE_PARAM, l.getLanguage());
list.add(new MenuBookmarkablePageLink<Page>(BasePage.this.getPageClass(), params,
Model.of(l.getDisplayName())));
}
return list;
}
};
languageDropDown.setIconType(GlyphIconType.flag);
return languageDropDown;
}
protected NavbarButton<LogoutPage> newLogoutMenu() {
// logout menu
NavbarButton<LogoutPage> logoutMenu =
new NavbarButton<LogoutPage>(LogoutPage.class, new StringResourceModel("navbar.logout", this, null));
logoutMenu.setIconType(GlyphIconType.logout);
MetaDataRoleAuthorizationStrategy.authorize(logoutMenu, Component.RENDER, SecurityConstants.Roles.ROLE_USER);
return logoutMenu;
}
protected NavbarButton<EditUserPage> newAccountMenu() {
PageParameters pageParametersForAccountPage = new PageParameters();
Person person = SecurityUtil.getCurrentAuthenticatedPerson();
// account menu
Model<String> account = null;
if (person != null) {
account = Model.of(person.getFirstName());
pageParametersForAccountPage.add(WebConstants.PARAM_ID, person.getId());
}
NavbarButton<EditUserPage> accountMenu =
new NavbarButton<>(EditUserPage.class, pageParametersForAccountPage, account);
accountMenu.setIconType(GlyphIconType.user);
MetaDataRoleAuthorizationStrategy.authorize(accountMenu, Component.RENDER, SecurityConstants.Roles.ROLE_USER);
return accountMenu;
}
protected NavbarButton<Homepage> newHomeMenu() {
// home
NavbarButton<Homepage> homeMenu = new NavbarButton<>(Homepage.class, Model.of("Home"));
homeMenu.setIconType(GlyphIconType.home);
MetaDataRoleAuthorizationStrategy.authorize(homeMenu, Component.RENDER, SecurityConstants.Roles.ROLE_USER);
return homeMenu;
}
protected NavbarDropDownButton newAdminMenu() {
// admin menu
NavbarDropDownButton adminMenu = new NavbarDropDownButton(new StringResourceModel("navbar.admin", this, null)) {
private static final long serialVersionUID = 1L;
@Override
protected List<AbstractLink> newSubMenuButtons(final String arg0) {
List<AbstractLink> list = new ArrayList<>();
list.add(new MenuBookmarkablePageLink<ListGroupPage>(ListGroupPage.class, null,
new StringResourceModel("navbar.groups", this, null)).setIconType(FontAwesomeIconType.tags));
list.add(new MenuBookmarkablePageLink<ListTestFormPage>(ListTestFormPage.class, null,
new StringResourceModel("navbar.testcomponents", this, null))
.setIconType(FontAwesomeIconType.android));
list.add(new MenuBookmarkablePageLink<SpringEndpointsPage>(SpringEndpointsPage.class, null,
new StringResourceModel("navbar.springendpoints", this, null))
.setIconType(FontAwesomeIconType.anchor));
list.add(new MenuBookmarkablePageLink<JminixRedirectPage>(JminixRedirectPage.class, null,
new StringResourceModel("navbar.jminix", this, null)).setIconType(FontAwesomeIconType.bug));
MenuBookmarkablePageLink<HALRedirectPage> halBrowserLink =
new MenuBookmarkablePageLink<HALRedirectPage>(HALRedirectPage.class, null,
new StringResourceModel("navbar.halbrowser", this, null)) {
private static final long serialVersionUID = 1L;
@Override
protected void onComponentTag(final ComponentTag tag) {
super.onComponentTag(tag);
tag.put("target", "_blank");
}
};
halBrowserLink.setIconType(FontAwesomeIconType.rss).setEnabled(true);
list.add(halBrowserLink);
MenuBookmarkablePageLink<UIRedirectPage> uiBrowserLink = new MenuBookmarkablePageLink<UIRedirectPage>(
UIRedirectPage.class, null, new StringResourceModel("navbar.ui", this, null)) {
private static final long serialVersionUID = 1L;
@Override
protected void onComponentTag(final ComponentTag tag) {
super.onComponentTag(tag);
tag.put("target", "_blank");
}
};
uiBrowserLink.setIconType(FontAwesomeIconType.rocket).setEnabled(true);
list.add(uiBrowserLink);
list.add(new MenuBookmarkablePageLink<Void>(EditAdminSettingsPage.class,
new StringResourceModel("navbar.adminSettings", BasePage.this, null))
.setIconType(FontAwesomeIconType.briefcase));
return list;
}
};
adminMenu.setIconType(GlyphIconType.cog);
MetaDataRoleAuthorizationStrategy.authorize(adminMenu, Component.RENDER, SecurityConstants.Roles.ROLE_ADMIN);
return adminMenu;
}
/**
* creates a new {@link Navbar} instance
*
* @param markupId
* The components markup id.
* @return a new {@link Navbar} instance
*/
protected Navbar newNavbar(final String markupId) {
Navbar navbar = new Navbar(markupId);
/**
* Make sure to update the BaseStyles when the navbar position changes.
*
* @see org.devgateway.toolkit.forms.wicket.styles.BaseStyles
*/
navbar.setPosition(Navbar.Position.TOP);
navbar.setInverted(true);
navbar.addComponents(NavbarComponents.transform(Navbar.ComponentPosition.RIGHT, newHomeMenu(), newAdminMenu(),
newAccountMenu(), newLogoutMenu()));
navbar.addComponents(NavbarComponents.transform(Navbar.ComponentPosition.LEFT, newLanguageMenu()));
return navbar;
}
@Override
public void renderHead(final IHeaderResponse response) {
super.renderHead(response);
// Load Styles.
response.render(CssHeaderItem.forReference(BaseStyles.INSTANCE));
response.render(CssHeaderItem.forReference(BootstrapCssReference.instance()));
response.render(CssHeaderItem.forReference(FontAwesomeCssReference.instance()));
// Load Scripts.
response.render(RespondJavaScriptReference.headerItem());
response.render(JavaScriptHeaderItem.forReference(JQueryResourceReference.get()));
// response.render(JavaScriptHeaderItem.forReference(
// new JavaScriptResourceReference(MainCss.class,
// "/assets/js/fileupload.js")
// ));
}
}