diff --git a/README.md b/README.md index 9b9084c32..fb89b320e 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ standard (javax.faces) | jsf | `jsf.project-stage=development` [primefaces](http://primefaces.org/) | jsf.primefaces | `jsf.primefaces.theme=overcast` [bootsfaces](http://bootsfaces.net/) | jsf.bootsfaces | `jsf.bootsfaces.usetheme=true` [butterfaces](http://butterfaces.org/) | jsf.butterfaces | `jsf.butterfaces.provide-j-query=true` +[adminfaces](http://adminfaces.github.io/site/) | jsf.adminfaces | `jsf.adminfaces.skin=skin-blue` [richfaces](https://github.com/richfaces/richfaces) | jsf.richfaces | `jsf.richfaces.resource-default-ttl=86400` [omnifaces](http://omnifaces.org/) | jsf.omnifaces | `jsf.omnifaces.faces-views-enabled=true` [angularfaces](http://angularfaces.net/) | jsf.angularfaces | `jsf.angularfaces.add-labels=true` diff --git a/joinfaces-autoconfigure/src/main/java/org/joinfaces/autoconfigure/adminfaces/AdminConfigWrapper.java b/joinfaces-autoconfigure/src/main/java/org/joinfaces/autoconfigure/adminfaces/AdminConfigWrapper.java new file mode 100644 index 000000000..f200d8cc9 --- /dev/null +++ b/joinfaces-autoconfigure/src/main/java/org/joinfaces/autoconfigure/adminfaces/AdminConfigWrapper.java @@ -0,0 +1,105 @@ +/* + * Copyright 2016-2016 the original author or authors. + * + * 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 org.joinfaces.autoconfigure.adminfaces; + +import com.github.adminfaces.template.config.AdminConfig; +import com.github.adminfaces.template.config.ControlSidebarConfig; +import lombok.Setter; + +/** + * AdminConfig Wrapper to use AdminFacesProperties. + * This class is not simpler because AdminConfig.getProperty is private. + * + * @author Marcelo Fernandes + */ +public class AdminConfigWrapper extends AdminConfig { + @Setter + private AdminfacesProperties adminfacesProperties; + + @Override + protected void loadDefaults() { + super.loadDefaults(); + configureAdminFacesProperties(); + } + + private String getAdminFacesStringProperty(String current, String fromAdminFacesProperties) { + String result = current; + if (fromAdminFacesProperties != null) { + result = fromAdminFacesProperties; + } + return result; + } + + private Boolean getAdminFacesBooleanProperty(Boolean current, Boolean fromAdminFacesProperties) { + Boolean result = current; + if (fromAdminFacesProperties != null) { + result = fromAdminFacesProperties; + } + return result; + } + + private Integer getAdminFacesIntegerProperty(Integer current, Integer fromAdminFacesProperties) { + Integer result = current; + if (fromAdminFacesProperties != null) { + result = fromAdminFacesProperties; + } + return result; + } + + private void configureAdminFacesProperties() { + setLoginPage(getAdminFacesStringProperty(getLoginPage(), this.adminfacesProperties.getLoginPage())); + setIndexPage(getAdminFacesStringProperty(getIndexPage(), this.adminfacesProperties.getIndexPage())); + setDateFormat(getAdminFacesStringProperty(getDateFormat(), this.adminfacesProperties.getDateFormat())); + setTemplatePath(getAdminFacesStringProperty(getTemplatePath(), this.adminfacesProperties.getTemplatePath())); + setBreadCrumbMaxSize(getAdminFacesIntegerProperty(getBreadCrumbMaxSize(), this.adminfacesProperties.getBreadcrumbSize())); + setRenderMessages(getAdminFacesBooleanProperty(isRenderMessages(), this.adminfacesProperties.getRenderMessages())); + setRenderAjaxStatus(getAdminFacesBooleanProperty(isRenderAjaxStatus(), this.adminfacesProperties.getRenderAjaxStatus())); + setDisableFilter(getAdminFacesBooleanProperty(isDisableFilter(), this.adminfacesProperties.getDisableFilter())); + setRenderBreadCrumb(getAdminFacesBooleanProperty(isRenderBreadCrumb(), this.adminfacesProperties.getRenderBreadCrumb())); + setEnableSlideMenu(getAdminFacesBooleanProperty(isEnableSlideMenu(), this.adminfacesProperties.getEnableSlideMenu())); + setEnableRipple(getAdminFacesBooleanProperty(isEnableRipple(), this.adminfacesProperties.getEnableRipple())); + setRippleElements(getAdminFacesStringProperty(getRippleElements(), this.adminfacesProperties.getRippleElements())); + setSkin(getAdminFacesStringProperty(getSkin(), this.adminfacesProperties.getSkin())); + setAutoShowNavbar(getAdminFacesBooleanProperty(isAutoShowNavbar(), this.adminfacesProperties.getAutoShowNavbar())); + setIgnoredResources(getAdminFacesStringProperty(getIgnoredResources(), this.adminfacesProperties.getIgnoredResources())); + setLoadingImage(getAdminFacesStringProperty(getLoadingImage(), this.adminfacesProperties.getLoadingImage())); + setExtensionLessUrls(getAdminFacesBooleanProperty(isExtensionLessUrls(), this.adminfacesProperties.getExtensionLessUrls())); + setRenderControlSidebar(getAdminFacesBooleanProperty(isRenderControlSidebar(), this.adminfacesProperties.getRenderControlSidebar())); + + setRippleMobileOnly(getAdminFacesBooleanProperty(isRippleMobileOnly(), this.adminfacesProperties.getRippleMobileOnly())); + setRenderMenuSearch(getAdminFacesBooleanProperty(isRenderMenuSearch(), this.adminfacesProperties.getRenderMenuSearch())); + setAutoHideMessages(getAdminFacesBooleanProperty(isAutoHideMessages(), this.adminfacesProperties.getAutoHideMessages())); + setMessagesHideTimeout(getAdminFacesStringProperty(getMessagesHideTimeout(), this.adminfacesProperties.getMessagesHideTimeout())); + setIconsEffect(getAdminFacesBooleanProperty(isIconsEffect(), this.adminfacesProperties.getIconsEffect())); + + configControlSideBar(); + } + + private void configControlSideBar() { + setLeftMenuTemplate(getAdminFacesBooleanProperty(isLeftMenuTemplate(), this.adminfacesProperties.getControlSidebar().getLeftMenuTemplate())); + + Boolean showOnMobile = getAdminFacesBooleanProperty(getControlSidebar().getShowOnMobile(), this.adminfacesProperties.getControlSidebar().getShowOnMobile()); + Boolean fixedLayout = getAdminFacesBooleanProperty(getControlSidebar().getFixedLayout(), this.adminfacesProperties.getControlSidebar().getFixedLayout()); + Boolean boxedLayout = getAdminFacesBooleanProperty(getControlSidebar().getBoxedLayout(), this.adminfacesProperties.getControlSidebar().getBoxedLayout()); + Boolean expandOnHover = getAdminFacesBooleanProperty(getControlSidebar().getExpandOnHover(), this.adminfacesProperties.getControlSidebar().getExpandOnHover()); + Boolean sidebarCollapsed = getAdminFacesBooleanProperty(getControlSidebar().getSidebarCollapsed(), this.adminfacesProperties.getControlSidebar().getSidebarCollapsed()); + Boolean fixed = getAdminFacesBooleanProperty(getControlSidebar().getFixed(), this.adminfacesProperties.getControlSidebar().getFixed()); + Boolean darkSkin = getAdminFacesBooleanProperty(getControlSidebar().getDarkSkin(), this.adminfacesProperties.getControlSidebar().getDarkSkin()); + + setControlSidebar(new ControlSidebarConfig(showOnMobile, fixedLayout, boxedLayout, expandOnHover, sidebarCollapsed, fixed, darkSkin)); + } +} diff --git a/joinfaces-autoconfigure/src/main/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesAutoConfiguration.java b/joinfaces-autoconfigure/src/main/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesAutoConfiguration.java index 372ed8134..63fccae57 100644 --- a/joinfaces-autoconfigure/src/main/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesAutoConfiguration.java +++ b/joinfaces-autoconfigure/src/main/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesAutoConfiguration.java @@ -19,19 +19,23 @@ import javax.faces.application.ViewExpiredException; import javax.persistence.OptimisticLockException; +import com.github.adminfaces.template.config.AdminConfig; import com.github.adminfaces.template.exception.AccessDeniedException; import com.github.adminfaces.template.session.AdminServletContextListener; import com.github.adminfaces.template.session.AdminSession; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.joinfaces.autoconfigure.primefaces.Primefaces4_0Properties; import org.joinfaces.autoconfigure.primefaces.Primefaces5_2Properties; import org.joinfaces.autoconfigure.primefaces.PrimefacesAutoConfiguration; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.boot.web.servlet.ServletComponentScan; @@ -52,8 +56,7 @@ */ @Slf4j @Configuration -// will adminfaces autoconfigure via application.yml ? -//@EnableConfigurationProperties(AdminfacesProperties.class) +@EnableConfigurationProperties(AdminfacesProperties.class) @ComponentScan({"com.github.adminfaces.template.bean", "com.github.adminfaces.template.config", "com.github.adminfaces.template.security"}) @@ -64,9 +67,14 @@ @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) public class AdminfacesAutoConfiguration { + @Autowired + private AdminfacesProperties adminfacesProperties; + @Bean public BeanPostProcessor adminfacesPrimeFacesPropertiesPostProcessor() { - return new PrimeFacesPropertiesPostProcessor(); + PrimeFacesPropertiesPostProcessor result = new PrimeFacesPropertiesPostProcessor(); + result.setAdminfacesProperties(this.adminfacesProperties); + return result; } // AdminSession does not contain @Named. @@ -100,10 +108,14 @@ public WebServerFactoryCustomizer adminface /** * Configures Primefaces to use admin theme. + * Apply adminfaces configuration from adminfaces properties. * * @author Marcelo Fernandes */ static class PrimeFacesPropertiesPostProcessor implements BeanPostProcessor { + @Setter + private AdminfacesProperties adminfacesProperties; + @Override public Object postProcessBeforeInitialization(@Nullable Object bean, @Nullable String beanName) throws BeansException { if (bean instanceof Primefaces4_0Properties) { @@ -116,6 +128,11 @@ public Object postProcessBeforeInitialization(@Nullable Object bean, @Nullable S log.warn("Changing primefaces fontAwesome from 'false' to 'true'."); properties.setFontAwesome(true); } + if (bean instanceof AdminConfig) { + AdminConfigWrapper adminConfigWrapper = new AdminConfigWrapper(); + adminConfigWrapper.setAdminfacesProperties(this.adminfacesProperties); + bean = adminConfigWrapper; + } return bean; } } diff --git a/joinfaces-autoconfigure/src/main/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesProperties.java b/joinfaces-autoconfigure/src/main/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesProperties.java new file mode 100644 index 000000000..e7efb3bbe --- /dev/null +++ b/joinfaces-autoconfigure/src/main/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesProperties.java @@ -0,0 +1,218 @@ +/* + * Copyright 2016-2016 the original author or authors. + * + * 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 org.joinfaces.autoconfigure.adminfaces; + +import java.io.Serializable; + +import lombok.Data; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Configuration properties of AdminFaces. + *

+ * Taken from + *

+ * + * @author Marcelo Fernandes + */ +@Data +@ConfigurationProperties(prefix = "jsf.adminfaces") +public class AdminfacesProperties implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * login page location (relative to webapp). It you only be used if you configure Admin Session. + */ + private String loginPage; + + /** + * index page location. User will be redirected to it when it access app root (contextPath/). + */ + private String indexPage; + + /** + * Date format used in error page (500.xhtml), by default it is JVM default format. + */ + private String dateFormat; + + /** + * Template path. + */ + private String templatePath; + + /** + * Number of breadcrumbs to queue before removing the older ones. + */ + private Integer breadcrumbSize; + + /** + * When false, p:messages defined in admin template will not be rendered. + */ + private Boolean renderMessages; + + /** + * When false ajaxStatus, which triggers the loading bar on every ajax request, + * will not be rendered. + */ + private Boolean renderAjaxStatus; + + /** + * Disables AdminFilter, responsible for redirecting user after session timeout, + * sending user to logon page when it is not logged in among other things. + */ + private Boolean disableFilter; + + /** + * When false, the breadCrumb component, declared in admin template, will not be rendered. + */ + private Boolean renderBreadCrumb; + + /** + * If true will make left menu touch enable (can be closed or opened via touch). + * Can be enable/disabled per page with . + */ + private Boolean enableSlideMenu; + + /** + * When true it will create a wave/ripple effect on elements specified by rippleElements. + */ + private Boolean enableRipple; + + /** + * A list of comma separated list of (jquery) selector which elements will be + * affected by ripple effect. + */ + private String rippleElements; + + /** + * Default template skin. + */ + private String skin; + + /** + * Automatic shows navbar when users scrolls page up (on small screens). + * Can be enable/disabled per page with . + */ + private Boolean autoShowNavbar; + + /** + * Comma separated resources (pages or urls) to be skiped by AdminFilter. + * Ex: /rest, /pages/car-list. Note that by default the filter skips pages + * under CONTEXT/public/ folder. + */ + private String ignoredResources; + + /** + * image used for the loading popup. It must be under webapp/resources/images folder. + */ + private String loadingImage; + + /** + * Removes extension suffix from breadCrumb links. + */ + private Boolean extensionLessUrls; + + /** + * When true it will activate control sidebar component. + */ + private Boolean renderControlSidebar; + + /** + * When true the ripple effect will be enabled only on mobile (small) screens. + */ + private Boolean rippleMobileOnly; + + /** + * Enables or disables menu search. + */ + private Boolean renderMenuSearch; + + /** + * If true PrimeFaces info messages will be hidden after a certain timeout. + */ + private Boolean autoHideMessages; + + /** + * Timeout to hide info messages. Note that the timeout is also composed by + * configured timeout + number of words in message. + */ + private String messagesHideTimeout; + + /** + * Enables material effect when icons (e.g modal close, calendar) are clicked. + */ + private Boolean iconsEffect; + + /** + * When true it will activate control sidebar component. + */ + private ControlSidebar controlSidebar = new ControlSidebar(); + + /** + * ControlSidebar properties. + */ + @Data + public static class ControlSidebar implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * When true control sidebar will be also rendered on mobile devices. + */ + private Boolean showOnMobile; + + /** + * Switches layout between left (default) and top menu. + */ + private Boolean leftMenuTemplate; + + /** + * Toggles fixed layout where navbar is fixed on the page. + */ + private Boolean fixedLayout; + + /** + * Boxed layout. + */ + private Boolean boxedLayout; + + /** + * When true left sidebar will be collapsed. + */ + private Boolean sidebarCollapsed; + + /** + * When true left sidebar will expand on mouse hover. + */ + private Boolean expandOnHover; + + /** + * When true control sidebar will be fixed on the page. + */ + private Boolean fixed; + + /** + * Changes control sidebar skin between dark and light. + */ + private Boolean darkSkin; + } +} diff --git a/joinfaces-autoconfigure/src/test/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesAutoConfigurationTest.java b/joinfaces-autoconfigure/src/test/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesAutoConfigurationTest.java index 0eb6afd15..dce9b566b 100644 --- a/joinfaces-autoconfigure/src/test/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesAutoConfigurationTest.java +++ b/joinfaces-autoconfigure/src/test/java/org/joinfaces/autoconfigure/adminfaces/AdminfacesAutoConfigurationTest.java @@ -54,6 +54,9 @@ public void testConfigurationProvider() { assertThat(context.getBean("adminSession", AdminSession.class)) .isNotNull(); + + assertThat(context.getBean(AdminConfigWrapper.class)) + .isNotNull(); }); } } diff --git a/joinfaces-autoconfigure/src/test/resources/admin-config.properties b/joinfaces-autoconfigure/src/test/resources/admin-config.properties deleted file mode 100644 index 8b1378917..000000000 --- a/joinfaces-autoconfigure/src/test/resources/admin-config.properties +++ /dev/null @@ -1 +0,0 @@ -