diff --git a/component/api/src/main/java/org/exoplatform/commons/api/settings/ExoFeatureService.java b/component/api/src/main/java/org/exoplatform/commons/api/settings/ExoFeatureService.java index 1e1910fdac..dc5ac37dd9 100644 --- a/component/api/src/main/java/org/exoplatform/commons/api/settings/ExoFeatureService.java +++ b/component/api/src/main/java/org/exoplatform/commons/api/settings/ExoFeatureService.java @@ -18,6 +18,12 @@ public interface ExoFeatureService { + /** + * An event to trigger using ListenerService when a feature status changes + * using API + */ + public final String FEATURE_STATUS_CHANGED_EVENT = "feature.status.changed"; + /** * Check the status of a feature * diff --git a/component/api/src/main/java/org/exoplatform/portal/branding/BrandingService.java b/component/api/src/main/java/org/exoplatform/portal/branding/BrandingService.java index d8c68fc0a9..b689bbfaa9 100644 --- a/component/api/src/main/java/org/exoplatform/portal/branding/BrandingService.java +++ b/component/api/src/main/java/org/exoplatform/portal/branding/BrandingService.java @@ -65,6 +65,36 @@ public interface BrandingService { */ Long getLoginBackgroundId(); + /** + * @return Page Background File details + */ + Background getPageBackground(); + + /** + * @return Page Background File technical identifier + */ + Long getPageBackgroundId(); + + /** + * @return Page Background Color + */ + String getPageBackgroundColor(); + + /** + * @return Page Background Size + */ + String getPageBackgroundSize(); + + /** + * @return Page Background Position + */ + String getPageBackgroundPosition(); + + /** + * @return Page Background repeat directive + */ + String getPageBackgroundRepeat(); + Logo getLogo(); /** @@ -98,6 +128,21 @@ public interface BrandingService { */ String getLoginBackgroundPath(); + /** + * @return {@link Background} URL to retrieve page background + */ + String getPageBackgroundPath(); + + /** + * @return Page width + */ + String getPageWidth(); + + /** + * @return Page custom additional css + */ + String getCustomCss(); + void updateTopBarTheme(String style); /** diff --git a/component/api/src/main/java/org/exoplatform/portal/branding/model/Branding.java b/component/api/src/main/java/org/exoplatform/portal/branding/model/Branding.java index 29a431026c..acbe89cd7c 100644 --- a/component/api/src/main/java/org/exoplatform/portal/branding/model/Branding.java +++ b/component/api/src/main/java/org/exoplatform/portal/branding/model/Branding.java @@ -69,7 +69,35 @@ public class Branding implements Serializable { @Getter @Setter - private Map themeStyle = new HashMap<>(); + private Background pageBackground; + + @Getter + @Setter + private String pageBackgroundColor; + + @Getter + @Setter + private String pageBackgroundSize; + + @Getter + @Setter + private String pageBackgroundRepeat; + + @Getter + @Setter + private String pageBackgroundPosition; + + @Getter + @Setter + private String pageWidth; + + @Getter + @Setter + private String customCss; + + @Getter + @Setter + private Map themeStyle = new HashMap<>(); @Getter @Setter diff --git a/component/api/src/main/java/org/exoplatform/portal/config/model/ApplicationBackgroundStyle.java b/component/api/src/main/java/org/exoplatform/portal/config/model/ApplicationBackgroundStyle.java new file mode 100644 index 0000000000..499c2b0ed6 --- /dev/null +++ b/component/api/src/main/java/org/exoplatform/portal/config/model/ApplicationBackgroundStyle.java @@ -0,0 +1,42 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.exoplatform.portal.config.model; + +import java.io.Serializable; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class ApplicationBackgroundStyle implements Serializable { + + private String backgroundColor; + + private String backgroundImage; + + private String backgroundEffect; + + private String backgroundPosition; + + private String backgroundSize; + + private String backgroundRepeat; + +} diff --git a/component/api/src/main/java/org/exoplatform/portal/config/model/Container.java b/component/api/src/main/java/org/exoplatform/portal/config/model/Container.java index e16a47be79..6fb71efdc2 100644 --- a/component/api/src/main/java/org/exoplatform/portal/config/model/Container.java +++ b/component/api/src/main/java/org/exoplatform/portal/config/model/Container.java @@ -29,42 +29,49 @@ import org.exoplatform.portal.pom.config.Utils; import org.exoplatform.portal.pom.data.*; +import lombok.Getter; +import lombok.Setter; + /** * @author Tuan Nguyen **/ public class Container extends ModelObject implements Cloneable { - public static final String EVERYONE = "Everyone"; + public static final String EVERYONE = "Everyone"; + + public static final List DEFAULT_ACCESS_PERMISSIONS = Collections.singletonList(EVERYONE); - public static final List DEFAULT_ACCESS_PERMISSIONS = Collections.singletonList(EVERYONE); + public static final List DEFAULT_MOVE_APPLICATIONS_PERMISSIONS = Collections.singletonList(EVERYONE); - public static final List DEFAULT_MOVE_APPLICATIONS_PERMISSIONS = Collections.singletonList(EVERYONE); + public static final List DEFAULT_MOVE_CONTAINERS_PERMISSIONS = Collections.singletonList(EVERYONE); - public static final List DEFAULT_MOVE_CONTAINERS_PERMISSIONS = Collections.singletonList(EVERYONE); + protected String id; - protected String id; + protected String name; - protected String name; + protected String icon; - protected String icon; + protected String template; - protected String template; + protected String factoryId; - protected String factoryId; + protected String title; - protected String title; + protected String description; - protected String description; + protected String profiles; - protected String profiles; + protected String[] accessPermissions; - protected String[] accessPermissions; + protected String[] moveAppsPermissions; - protected String[] moveAppsPermissions; + protected String[] moveContainersPermissions; - protected String[] moveContainersPermissions; + protected ArrayList children; - protected ArrayList children; + @Getter + @Setter + protected ApplicationBackgroundStyle appBackgroundStyle; public Container() { setDefaultPermissions(); @@ -93,6 +100,7 @@ public Container(ContainerData data) { this.height = data.getHeight(); this.cssClass = data.getCssClass(); this.cssStyle = data.getCssStyle(); + this.appBackgroundStyle = data.getAppBackgroundStyle(); this.profiles = data.getProfiles(); this.accessPermissions = data.getAccessPermissions().toArray(new String[data.getAccessPermissions().size()]); List permisssions = data.getMoveAppsPermissions(); @@ -226,6 +234,7 @@ public ContainerData build() { getCssClass(), getProfiles(), getCssStyle(), + getAppBackgroundStyle(), Utils.safeImmutableList(accessPermissions), Utils.safeImmutableList(moveAppsPermissions), Utils.safeImmutableList(moveContainersPermissions), diff --git a/component/api/src/main/java/org/exoplatform/portal/config/model/ModelStyle.java b/component/api/src/main/java/org/exoplatform/portal/config/model/ModelStyle.java index 7bbed2ff10..1bdd82f003 100644 --- a/component/api/src/main/java/org/exoplatform/portal/config/model/ModelStyle.java +++ b/component/api/src/main/java/org/exoplatform/portal/config/model/ModelStyle.java @@ -65,6 +65,38 @@ public class ModelStyle implements Serializable { private String backgroundRepeat; + private String textTitleColor; + + private String textTitleFontSize; + + private String textTitleFontWeight; + + private String textTitleFontStyle; + + private String textHeaderColor; + + private String textHeaderFontSize; + + private String textHeaderFontWeight; + + private String textHeaderFontStyle; + + private String textColor; + + private String textFontSize; + + private String textFontWeight; + + private String textFontStyle; + + private String textSubtitleColor; + + private String textSubtitleFontSize; + + private String textSubtitleFontWeight; + + private String textSubtitleFontStyle; + public String getCssClass() { // NOSONAR StringBuilder cssClass = new StringBuilder(); if (marginTop != null && marginTop >= 0) { diff --git a/component/api/src/main/java/org/exoplatform/portal/config/model/Page.java b/component/api/src/main/java/org/exoplatform/portal/config/model/Page.java index 3e55c65fb5..5a1811e268 100644 --- a/component/api/src/main/java/org/exoplatform/portal/config/model/Page.java +++ b/component/api/src/main/java/org/exoplatform/portal/config/model/Page.java @@ -174,7 +174,7 @@ public PageData build() { List children = buildChildren(); return new PageData(storageId, id, name, icon, template, factoryId, title, description, width, height, cssClass, profiles, Utils.safeImmutableList(accessPermissions), children, ownerType, ownerId, editPermission, showMaxWindow, hideSharedLayout, - cssStyle, Utils.safeImmutableList(moveAppsPermissions), Utils.safeImmutableList(moveContainersPermissions), type, link); + Utils.safeImmutableList(moveAppsPermissions), Utils.safeImmutableList(moveContainersPermissions), type, link); } public static class PageSet { diff --git a/component/api/src/main/java/org/exoplatform/portal/pom/data/ContainerData.java b/component/api/src/main/java/org/exoplatform/portal/pom/data/ContainerData.java index 1a05447ce8..30853c74af 100644 --- a/component/api/src/main/java/org/exoplatform/portal/pom/data/ContainerData.java +++ b/component/api/src/main/java/org/exoplatform/portal/pom/data/ContainerData.java @@ -20,13 +20,14 @@ import java.util.List; +import org.exoplatform.portal.config.model.ApplicationBackgroundStyle; import org.exoplatform.portal.config.model.ModelStyle; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; - /** * @author Julien Viet * @version $Revision$ @@ -36,86 +37,91 @@ @NoArgsConstructor(force = true) public class ContainerData extends ComponentData { - private static final long serialVersionUID = 7328080023001711540L; - - /** . */ - private final String id; - - /** . */ - private final String name; - - /** . */ - private final String icon; - - /** . */ - private final String template; - - /** . */ - private final String factoryId; - - /** . */ - private final String title; - - /** . */ - private final String description; - - /** . */ - private final String width; - - /** . */ - private final String height; - - /** . */ - private final String cssClass; - - /** . */ - private final String profiles; - - /** . */ - private final List accessPermissions; - - private final List moveAppsPermissions; - - private final List moveContainersPermissions; - - /** . */ - private final List children; - - public ContainerData(String storageId, - String id, - String name, - String icon, - String template, - String factoryId, - String title, - String description, - String width, - String height, - String cssClass, - String profiles, - ModelStyle cssStyle, - List accessPermissions, - List moveAppsPermissions, - List moveContainersPermissions, - List children) { - super(storageId, null, cssStyle); - - // - this.id = id; - this.name = name; - this.icon = icon; - this.template = template; - this.factoryId = factoryId; - this.title = title; - this.description = description; - this.width = width; - this.height = height; - this.cssClass = cssClass; - this.profiles = profiles; - this.accessPermissions = accessPermissions; - this.moveAppsPermissions = moveAppsPermissions; - this.moveContainersPermissions = moveContainersPermissions; - this.children = children; - } + private static final long serialVersionUID = 7328080023001711540L; + + /** . */ + private final String id; + + /** . */ + private final String name; + + /** . */ + private final String icon; + + /** . */ + private final String template; + + /** . */ + private final String factoryId; + + /** . */ + private final String title; + + /** . */ + private final String description; + + /** . */ + private final String width; + + /** . */ + private final String height; + + /** . */ + private final String cssClass; + + /** . */ + private final String profiles; + + /** . */ + private final List accessPermissions; + + private final List moveAppsPermissions; + + private final List moveContainersPermissions; + + /** . */ + private final List children; + + @Getter + protected final ApplicationBackgroundStyle appBackgroundStyle; + + public ContainerData(String storageId, + String id, + String name, + String icon, + String template, + String factoryId, + String title, + String description, + String width, + String height, + String cssClass, + String profiles, + ModelStyle cssStyle, + ApplicationBackgroundStyle appBackgroundStyle, + List accessPermissions, + List moveAppsPermissions, + List moveContainersPermissions, + List children) { + super(storageId, null, cssStyle); + + // + this.id = id; + this.name = name; + this.icon = icon; + this.template = template; + this.factoryId = factoryId; + this.title = title; + this.description = description; + this.width = width; + this.height = height; + this.cssClass = cssClass; + this.appBackgroundStyle = appBackgroundStyle; + this.profiles = profiles; + this.accessPermissions = accessPermissions; + this.moveAppsPermissions = moveAppsPermissions; + this.moveContainersPermissions = moveContainersPermissions; + this.children = children; + } } diff --git a/component/api/src/main/java/org/exoplatform/portal/pom/data/MappedAttributes.java b/component/api/src/main/java/org/exoplatform/portal/pom/data/MappedAttributes.java index e40b71f0cf..643ab3d99c 100644 --- a/component/api/src/main/java/org/exoplatform/portal/pom/data/MappedAttributes.java +++ b/component/api/src/main/java/org/exoplatform/portal/pom/data/MappedAttributes.java @@ -35,79 +35,139 @@ private MappedAttributes() { } /** . */ - public static final Key ID = Key.create("id", ValueType.STRING); + public static final Key ID = Key.create("id", ValueType.STRING); /** . */ - public static final Key NAME = Key.create("name", ValueType.STRING); + public static final Key NAME = Key.create("name", ValueType.STRING); /** . */ - public static final Key SHOW_MAX_WINDOW = Key.create("show-max-window", ValueType.BOOLEAN); + public static final Key SHOW_MAX_WINDOW = Key.create("show-max-window", ValueType.BOOLEAN); - public static final Key HIDE_SHARED_LAYOUT = Key.create("hide-shared-layout", ValueType.BOOLEAN); + public static final Key HIDE_SHARED_LAYOUT = Key.create("hide-shared-layout", ValueType.BOOLEAN); /** . */ - public static final Key FACTORY_ID = Key.create("factory-id", ValueType.STRING); + public static final Key FACTORY_ID = Key.create("factory-id", ValueType.STRING); /** . */ - public static final Key CSS_CLASS = Key.create("css-class", ValueType.STRING); + public static final Key CSS_CLASS = Key.create("css-class", ValueType.STRING); - public static final Key BORDER_COLOR = Key.create("border-color", ValueType.STRING); + public static final Key BORDER_COLOR = Key.create("border-color", ValueType.STRING); - public static final Key BACKGROUND_COLOR = Key.create("background-color", ValueType.STRING); + public static final Key TEXT_TITLE_COLOR = Key.create("text-title-color", ValueType.STRING); - public static final Key BACKGROUND_IMAGE = Key.create("background-image", ValueType.STRING); + public static final Key TEXT_TITLE_FONT_SIZE = Key.create("text-title-font-size", ValueType.STRING); - public static final Key BACKGROUND_EFFECT = Key.create("background-effect", ValueType.STRING); + public static final Key TEXT_TITLE_FONT_WEIGHT = Key.create("text-title-font-weight", ValueType.STRING); - public static final Key BACKGROUND_POSITION = Key.create("background-position", ValueType.STRING); + public static final Key TEXT_TITLE_FONT_STYLE = Key.create("text-title-font-style", ValueType.STRING); - public static final Key BACKGROUND_REPEAT = Key.create("background-repeat", ValueType.STRING); + public static final Key TEXT_HEADER_COLOR = Key.create("text-header-color", ValueType.STRING); - public static final Key BACKGROUND_SIZE = Key.create("background-size", ValueType.STRING); + public static final Key TEXT_HEADER_FONT_SIZE = Key.create("text-header-font-size", ValueType.STRING); - public static final Key BORDER_SIZE = Key.create("border-size", ValueType.STRING); + public static final Key TEXT_HEADER_FONT_WEIGHT = Key.create("text-header-font-weight", ValueType.STRING); - public static final Key BOX_SHADOW = Key.create("box-shadow", ValueType.STRING); + public static final Key TEXT_HEADER_FONT_STYLE = Key.create("text-header-font-style", ValueType.STRING); + + public static final Key TEXT_COLOR = Key.create("text-color", ValueType.STRING); + + public static final Key TEXT_FONT_SIZE = Key.create("text-font-size", ValueType.STRING); + + public static final Key TEXT_FONT_WEIGHT = Key.create("text-font-weight", ValueType.STRING); + + public static final Key TEXT_FONT_STYLE = Key.create("text-font-style", ValueType.STRING); + + public static final Key TEXT_SUBTITLE_COLOR = Key.create("text-subtitle-color", ValueType.STRING); + + public static final Key TEXT_SUBTITLE_FONT_SIZE = Key.create("text-subtitle-font-size", ValueType.STRING); + + public static final Key TEXT_SUBTITLE_FONT_WEIGHT = Key.create("text-subtitle-font-weight", ValueType.STRING); + + public static final Key TEXT_SUBTITLE_FONT_STYLE = Key.create("text-subtitle-font-style", ValueType.STRING); + + public static final Key BACKGROUND_COLOR = Key.create("background-color", ValueType.STRING); + + public static final Key BACKGROUND_IMAGE = Key.create("background-image", ValueType.STRING); + + public static final Key BACKGROUND_EFFECT = Key.create("background-effect", ValueType.STRING); + + public static final Key BACKGROUND_POSITION = Key.create("background-position", ValueType.STRING); + + public static final Key BACKGROUND_REPEAT = Key.create("background-repeat", ValueType.STRING); + + public static final Key BACKGROUND_SIZE = Key.create("background-size", ValueType.STRING); + + public static final Key APP_BACKGROUND_COLOR = Key.create("app-background-color", ValueType.STRING); + + public static final Key APP_BACKGROUND_IMAGE = Key.create("app-background-image", ValueType.STRING); + + public static final Key APP_BACKGROUND_EFFECT = Key.create("app-background-effect", ValueType.STRING); + + public static final Key APP_BACKGROUND_POSITION = Key.create("app-background-position", ValueType.STRING); + + public static final Key APP_BACKGROUND_REPEAT = Key.create("app-background-repeat", ValueType.STRING); + + public static final Key APP_BACKGROUND_SIZE = Key.create("app-background-size", ValueType.STRING); + + public static final Key BORDER_SIZE = Key.create("border-size", ValueType.STRING); + + public static final Key BOX_SHADOW = Key.create("box-shadow", ValueType.STRING); + + public static final Key MARGIN_TOP = Key.create("margin-top", ValueType.STRING); + + public static final Key MARGIN_BOTTOM = Key.create("margin-bottom", ValueType.STRING); + + public static final Key MARGIN_LEFT = Key.create("margin-left", ValueType.STRING); + + public static final Key MARGIN_RIGHT = Key.create("margin-right", ValueType.STRING); + + public static final Key RADIUS_TOP_RIGHT_SHADOW = Key.create("radius-top-right", ValueType.STRING); + + public static final Key RADIUS_TOP_LEFT_SHADOW = Key.create("radius-top-left", ValueType.STRING); + + public static final Key RADIUS_BOTTOM_RIGHT_SHADOW = Key.create("radius-bottom-right", ValueType.STRING); + + public static final Key RADIUS_BOTTOM_LEFT_SHADOW = Key.create("radius-bottom-left", ValueType.STRING); /** . */ - public static final Key PROFILES = Key.create("profiles", ValueType.STRING); + public static final Key PROFILES = Key.create("profiles", ValueType.STRING); /** . */ - public static final Key PRIORITY = Key.create("priority", ValueType.INTEGER); + public static final Key PRIORITY = Key.create("priority", ValueType.INTEGER); /** . */ - public static final Key ICON = Key.create("icon", ValueType.STRING); + public static final Key ICON = Key.create("icon", ValueType.STRING); /** . */ - public static final Key URI = Key.create("uri", ValueType.STRING); + public static final Key URI = Key.create("uri", ValueType.STRING); /** . */ - public static final Key TEMPLATE = Key.create("template", ValueType.STRING); + public static final Key TEMPLATE = Key.create("template", ValueType.STRING); /** . */ - public static final Key LOCALE = Key.create("locale", ValueType.STRING); + public static final Key LOCALE = Key.create("locale", ValueType.STRING); /** . */ - public static final Key SKIN = Key.create("skin", ValueType.STRING); + public static final Key SKIN = Key.create("skin", ValueType.STRING); /** . */ - public static final Key WIDTH = Key.create("width", ValueType.STRING); + public static final Key WIDTH = Key.create("width", ValueType.STRING); /** . */ - public static final Key HEIGHT = Key.create("height", ValueType.STRING); + public static final Key HEIGHT = Key.create("height", ValueType.STRING); /** . */ - public static final Key TYPE = Key.create("type", ValueType.STRING); + public static final Key TYPE = Key.create("type", ValueType.STRING); /** . */ - public static final Key SHOW_INFO_BAR = Key.create("showinfobar", ValueType.BOOLEAN); + public static final Key SHOW_INFO_BAR = Key.create("showinfobar", ValueType.BOOLEAN); /** . */ - public static final Key SHOW_MODE = Key.create("showmode", ValueType.BOOLEAN); + public static final Key SHOW_MODE = Key.create("showmode", ValueType.BOOLEAN); /** . */ - public static final Key SHOW_WINDOW_STATE = Key.create("showwindowstate", ValueType.BOOLEAN); + public static final Key SHOW_WINDOW_STATE = Key.create("showwindowstate", ValueType.BOOLEAN); /** . */ - public static final Key THEME = Key.create("theme", ValueType.STRING); + public static final Key THEME = Key.create("theme", ValueType.STRING); } diff --git a/component/api/src/main/java/org/exoplatform/portal/pom/data/PageData.java b/component/api/src/main/java/org/exoplatform/portal/pom/data/PageData.java index d9c5e609e8..238a92381d 100644 --- a/component/api/src/main/java/org/exoplatform/portal/pom/data/PageData.java +++ b/component/api/src/main/java/org/exoplatform/portal/pom/data/PageData.java @@ -20,13 +20,10 @@ import java.util.List; -import org.exoplatform.portal.config.model.ModelStyle; - import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; - /** * @author Julien Viet * @version $Revision$ @@ -77,7 +74,6 @@ public PageData(String storageId, // NOSONAR String editPermission, boolean showMaxWindow, boolean hideSharedLayout, - ModelStyle cssStyle, List moveAppsPermissions, List moveContainersPermissions, String type, @@ -94,7 +90,8 @@ public PageData(String storageId, // NOSONAR height, cssClass, profiles, - cssStyle, + null, + null, accessPermissions, moveAppsPermissions, moveContainersPermissions, diff --git a/component/portal/src/main/java/org/exoplatform/portal/branding/BrandingRestResourcesV1.java b/component/portal/src/main/java/org/exoplatform/portal/branding/BrandingRestResourcesV1.java index 666434d71b..3de3e1d40a 100644 --- a/component/portal/src/main/java/org/exoplatform/portal/branding/BrandingRestResourcesV1.java +++ b/component/portal/src/main/java/org/exoplatform/portal/branding/BrandingRestResourcesV1.java @@ -75,25 +75,30 @@ public BrandingRestResourcesV1(BrandingService brandingService) { @RolesAllowed("users") @Operation(summary = "Get Branding information", description = "Get Branding information", method = "GET") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Request fulfilled"), - @ApiResponse(responseCode = "304", description = "Resource not modified"), - @ApiResponse(responseCode = "500", description = "Server error when retrieving branding information") + @ApiResponse(responseCode = "200", description = "Request fulfilled"), + @ApiResponse(responseCode = "304", description = "Resource not modified"), + @ApiResponse(responseCode = "500", description = "Server error when retrieving branding information") }) - public Response getBrandingInformation(@Context Request request) { + public Response getBrandingInformation( + @Context + Request request, + @Parameter(description = "Whether force refresh information from database or not") + @QueryParam("forceRefresh") + String forceRefresh) { try { + boolean refresh = StringUtils.equals("true", forceRefresh); long lastUpdated = brandingService.getLastUpdatedTime(); - EntityTag eTag = new EntityTag(String.valueOf(lastUpdated)); + EntityTag eTag = refresh ? null : new EntityTag(String.valueOf(lastUpdated)); // Response.ResponseBuilder builder = request.evaluatePreconditions(eTag); if (builder == null) { - Branding brandingInformation = brandingService.getBrandingInformation(false); + Branding brandingInformation = brandingService.getBrandingInformation(refresh); builder = Response.ok(brandingInformation); CacheControl cc = new CacheControl(); cc.setMustRevalidate(true); builder.tag(eTag); builder.lastModified(new Date(lastUpdated)); - builder.expires(new Date(System.currentTimeMillis() + CACHE_IN_MILLI_SECONDS)); builder.cacheControl(cc); } return builder.build(); @@ -109,8 +114,8 @@ public Response getBrandingInformation(@Context Request request) { @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Update Branding information", description = "Update Branding information", method = "POST") @ApiResponses(value = { - @ApiResponse(responseCode = "204", description = "Branding information updated"), - @ApiResponse(responseCode = "500", description = "Server error when updating branding information") + @ApiResponse(responseCode = "204", description = "Branding information updated"), + @ApiResponse(responseCode = "500", description = "Server error when updating branding information") }) public Response updateBrandingInformation(Branding branding) { try { @@ -127,9 +132,9 @@ public Response updateBrandingInformation(Branding branding) { @Produces(IMAGE_MIME_TYPE) @Operation(summary = "Get Branding logo", description = "Get Branding logo", method = "GET") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Branding logo retrieved"), - @ApiResponse(responseCode = "404", description = "Branding logo not found"), - @ApiResponse(responseCode = "500", description = "Server error when retrieving branding logo") + @ApiResponse(responseCode = "200", description = "Branding logo retrieved"), + @ApiResponse(responseCode = "404", description = "Branding logo not found"), + @ApiResponse(responseCode = "500", description = "Server error when retrieving branding logo") }) public Response getBrandingLogo( @Context @@ -171,14 +176,63 @@ public Response getBrandingLogo( return builder.build(); } + @GET + @Path("/pageBackground") + @Produces(IMAGE_MIME_TYPE) + @Operation(summary = "Get Default Page Background image", description = "Get Default Page Background image", method = "GET") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Request fullfilled"), + @ApiResponse(responseCode = "404", description = "Object not found"), + }) + public Response getPageBackground( + @Context + Request request, + @Parameter(description = "The value of lastModified parameter will determine whether the query should be cached by browser or not. If not set, no 'expires HTTP Header will be sent'") + @QueryParam("lastModified") + String lastModified, + @Parameter(description = "The value of version parameter will determine whether the query should be cached by browser or not. If not set, no 'expires HTTP Header will be sent'") + @QueryParam("v") + String version) { + + Background background = brandingService.getPageBackground(); + if (background == null || background.getData() == null) { + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + + // + long lastUpdated = background.getUpdatedDate(); + EntityTag eTag = new EntityTag(String.valueOf(lastUpdated)); + + // + Response.ResponseBuilder builder = request.evaluatePreconditions(eTag); + if (builder == null) { + InputStream stream = new ByteArrayInputStream(background.getData()); + builder = Response.ok(stream, IMAGE_MIME_TYPE); + // If the query has a lastModified parameter, it means that the client + // will change the lastModified entry when it really changes + // Which means that we can cache the image in browser side + // for a long time + if (StringUtils.isNotBlank(lastModified) || StringUtils.isNotBlank(version)) { + CacheControl cc = new CacheControl(); + cc.setMaxAge(CACHE_IN_SECONDS); + cc.setPrivate(false); + builder.tag(eTag); + builder.lastModified(new Date(lastUpdated)); + builder.expires(new Date(System.currentTimeMillis() + CACHE_IN_MILLI_SECONDS)); + builder.cacheControl(cc); + } + } + return builder.build(); + } + @GET @Path("/favicon") @Produces(IMAGE_MIME_TYPE) @Operation(summary = "Get Branding favicon", description = "Get Branding favicon", method = "GET") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Branding favicon retrieved"), - @ApiResponse(responseCode = "404", description = "Branding favicon not found"), - @ApiResponse(responseCode = "500", description = "Server error when retrieving branding favicon") + @ApiResponse(responseCode = "200", description = "Branding favicon retrieved"), + @ApiResponse(responseCode = "404", description = "Branding favicon not found"), + @ApiResponse(responseCode = "500", description = "Server error when retrieving branding favicon") }) public Response getBrandingFavicon( @Context @@ -220,11 +274,12 @@ public Response getBrandingFavicon( @GET @Path("/loginBackground") @Produces(IMAGE_MIME_TYPE) - @Operation(summary = "Get authentication pages left panel background", description = "Get authentication pages left panel background", method = "GET") + @Operation(summary = "Get authentication pages left panel background", + description = "Get authentication pages left panel background", method = "GET") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Request fullfilled"), - @ApiResponse(responseCode = "404", description = "Resource not found"), - @ApiResponse(responseCode = "500", description = "Server error when retrieving resource") + @ApiResponse(responseCode = "200", description = "Request fullfilled"), + @ApiResponse(responseCode = "404", description = "Resource not found"), + @ApiResponse(responseCode = "500", description = "Server error when retrieving resource") }) public Response getLoginBackground( @Context @@ -267,9 +322,9 @@ public Response getLoginBackground( @Path("/css") @Operation(summary = "Get Branding CSS content", description = "Get Branding CSS content", method = "GET") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Branding css retrieved"), - @ApiResponse(responseCode = "304", description = "Branding css not modified"), - @ApiResponse(responseCode = "500", description = "Server error when retrieving branding css") + @ApiResponse(responseCode = "200", description = "Branding css retrieved"), + @ApiResponse(responseCode = "304", description = "Branding css not modified"), + @ApiResponse(responseCode = "500", description = "Server error when retrieving branding css") }) public Response getBrandingCSS( @Context diff --git a/component/portal/src/main/java/org/exoplatform/portal/branding/BrandingServiceImpl.java b/component/portal/src/main/java/org/exoplatform/portal/branding/BrandingServiceImpl.java index 7ec88ac848..55a9b4f727 100644 --- a/component/portal/src/main/java/org/exoplatform/portal/branding/BrandingServiceImpl.java +++ b/component/portal/src/main/java/org/exoplatform/portal/branding/BrandingServiceImpl.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashMap; @@ -40,6 +41,7 @@ import com.github.sommeri.less4j.LessCompiler.Configuration; import com.github.sommeri.less4j.core.ThreadUnsafeLessCompiler; +import org.exoplatform.commons.api.settings.ExoFeatureService; import org.exoplatform.commons.api.settings.SettingService; import org.exoplatform.commons.api.settings.SettingValue; import org.exoplatform.commons.api.settings.data.Context; @@ -58,6 +60,7 @@ import org.exoplatform.portal.branding.model.BrandingFile; import org.exoplatform.portal.branding.model.Favicon; import org.exoplatform.portal.branding.model.Logo; +import org.exoplatform.services.listener.ListenerService; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.resources.LocaleConfig; @@ -79,6 +82,8 @@ public class BrandingServiceImpl implements BrandingService, Startable { public static final String BRANDING_LOGIN_BG_BASE_PATH = "/portal/rest/v1/platform/branding/loginBackground?v="; // NOSONAR + public static final String BRANDING_PAGE_BG_BASE_PATH = "/portal/rest/v1/platform/branding/pageBackground?v="; // NOSONAR + public static final String BRANDING_COMPANY_NAME_INIT_PARAM = "exo.branding.company.name"; // Will be used in Mail notification Footer by example @@ -121,6 +126,20 @@ public class BrandingServiceImpl implements BrandingService, Startable { public static final String BRANDING_LOGIN_BG_ID_SETTING_KEY = "authentication.background"; + public static final String BRANDING_PAGE_BG_ID_SETTING_KEY = "page.background"; + + public static final String BRANDING_PAGE_BG_COLOR_KEY = "page.backgroundColor"; + + public static final String BRANDING_PAGE_BG_REPEAT_KEY = "page.backgroundRepeat"; + + public static final String BRANDING_PAGE_WIDTH_KEY = "page.width"; + + public static final String BRANDING_CUSTOM_CSS = "page.customCss"; + + public static final String BRANDING_PAGE_BG_POSITION_KEY = "page.backgroundPosition"; + + public static final String BRANDING_PAGE_BG_SIZE_KEY = "page.backgroundSize"; + public static final String BRANDING_LAST_UPDATED_TIME_KEY = "branding.lastUpdatedTime"; public static final String FILE_API_NAME_SPACE = "CompanyBranding"; @@ -131,6 +150,10 @@ public class BrandingServiceImpl implements BrandingService, Startable { public static final String LOGIN_BACKGROUND_NAME = "loginBackground.png"; + public static final String PAGE_BACKGROUND_NAME = "pageBackground.png"; + + public static final String BRANDING_CUSTOM_STYLE_FEATURE = "customStylesheet"; + public static final String BRANDING_DEFAULT_LOGO_PATH = "/skin/images/logo/DefaultLogo.png"; // NOSONAR public static final String BRANDING_DEFAULT_FAVICON_PATH = "/skin/images/favicon.ico"; // NOSONAR @@ -153,6 +176,10 @@ public class BrandingServiceImpl implements BrandingService, Startable { private ConfigurationManager configurationManager; + private ExoFeatureService featureService; + + private ListenerService listenerService; + private String defaultCompanyName = ""; private String defaultSiteName = ""; @@ -185,18 +212,23 @@ public class BrandingServiceImpl implements BrandingService, Startable { private String themeCSSContent = null; + private String customCss = null; + private Logo logo = null; private Favicon favicon = null; private Background loginBackground = null; - public BrandingServiceImpl(PortalContainer container, + private Background pageBackground = null; + + public BrandingServiceImpl(PortalContainer container, // NOSONAR ConfigurationManager configurationManager, SettingService settingService, FileService fileService, UploadService uploadService, LocaleConfigService localeConfigService, + ListenerService listenerService, InitParams initParams) { this.container = container; this.configurationManager = configurationManager; @@ -204,6 +236,7 @@ public BrandingServiceImpl(PortalContainer container, this.fileService = fileService; this.uploadService = uploadService; this.localeConfigService = localeConfigService; + this.listenerService = listenerService; this.loadLanguages(); this.loadInitParams(initParams); @@ -212,6 +245,11 @@ public BrandingServiceImpl(PortalContainer container, @Override public void start() { computeThemeCSS(); + listenerService.addListener(ExoFeatureService.FEATURE_STATUS_CHANGED_EVENT, e -> { + if (StringUtils.equals(BRANDING_CUSTOM_STYLE_FEATURE, (String) e.getSource())) { + this.updateLastUpdatedTime(); + } + }); } @Override @@ -250,6 +288,13 @@ public Branding getBrandingInformation(boolean retrieveBinaries) { branding.setFavicon(getFavicon()); branding.setLoginBackground(getLoginBackground()); branding.setLoginBackgroundTextColor(getLoginBackgroundTextColor()); + branding.setPageBackground(getPageBackground()); + branding.setPageBackgroundColor(getPageBackgroundColor()); + branding.setPageBackgroundPosition(getPageBackgroundPosition()); + branding.setPageBackgroundSize(getPageBackgroundSize()); + branding.setPageBackgroundRepeat(getPageBackgroundRepeat()); + branding.setPageWidth(getPageWidth()); + branding.setCustomCss(getCustomCss()); branding.setThemeStyle(getThemeStyle()); branding.setLoginTitle(getLoginTitle()); branding.setLoginSubtitle(getLoginSubtitle()); @@ -270,6 +315,11 @@ public Branding getBrandingInformation(boolean retrieveBinaries) { brandingFile.setData(null); branding.setLoginBackground(brandingFile); } + if (branding.getPageBackground() != null && branding.getPageBackground().getData() != null) { + Background brandingFile = branding.getPageBackground().clone(); + brandingFile.setData(null); + branding.setPageBackground(brandingFile); + } } return branding; } @@ -285,6 +335,7 @@ public long getLastUpdatedTime() { @Override public void updateBrandingInformation(Branding branding) { + validateCSSInputs(branding); try { updateCompanyName(branding.getCompanyName(), false); updateSiteName(branding.getSiteName(), false); @@ -294,11 +345,18 @@ public void updateBrandingInformation(Branding branding) { updateFavicon(branding.getFavicon(), false); updateLoginBackground(branding.getLoginBackground(), false); updateLoginBackgroundTextColor(branding.getLoginBackgroundTextColor(), false); + updatePageBackground(branding.getPageBackground(), false); + updatePageBackgroundColor(branding.getPageBackgroundColor(), false); + updatePageBackgroundSize(branding.getPageBackgroundSize(), false); + updatePageBackgroundPosition(branding.getPageBackgroundPosition(), false); + updatePageBackgroundRepeat(branding.getPageBackgroundRepeat(), false); + updatePageWidth(branding.getPageWidth(), false); + updateCustomCss(branding.getCustomCss(), false); updateThemeStyle(branding.getThemeStyle(), false); updateLoginTitle(branding.getLoginTitle()); updateLoginSubtitle(branding.getLoginSubtitle()); } finally { - updateLastUpdatedTime(System.currentTimeMillis()); + updateLastUpdatedTime(); } } @@ -338,13 +396,85 @@ public String getSiteName() { } } + @Override + public String getPageBackgroundColor() { + SettingValue color = (SettingValue) settingService.get(Context.GLOBAL, + Scope.GLOBAL, + BRANDING_PAGE_BG_COLOR_KEY); + if (color != null && StringUtils.isNotBlank(color.getValue())) { + return color.getValue(); + } else { + return null; + } + } + + @Override + public String getPageBackgroundRepeat() { + SettingValue value = (SettingValue) settingService.get(Context.GLOBAL, + Scope.GLOBAL, + BRANDING_PAGE_BG_REPEAT_KEY); + if (value != null && StringUtils.isNotBlank(value.getValue())) { + return value.getValue(); + } else { + return null; + } + } + + @Override + public String getPageWidth() { + SettingValue value = (SettingValue) settingService.get(Context.GLOBAL, + Scope.GLOBAL, + BRANDING_PAGE_WIDTH_KEY); + if (value != null && StringUtils.isNotBlank(value.getValue())) { + return value.getValue(); + } else { + return null; + } + } + + @Override + public String getCustomCss() { + SettingValue value = (SettingValue) settingService.get(Context.GLOBAL, + Scope.GLOBAL, + BRANDING_CUSTOM_CSS); + if (value != null && StringUtils.isNotBlank(value.getValue())) { + return value.getValue(); + } else { + return null; + } + } + + @Override + public String getPageBackgroundPosition() { + SettingValue value = (SettingValue) settingService.get(Context.GLOBAL, + Scope.GLOBAL, + BRANDING_PAGE_BG_POSITION_KEY); + if (value != null && StringUtils.isNotBlank(value.getValue())) { + return value.getValue(); + } else { + return null; + } + } + + @Override + public String getPageBackgroundSize() { + SettingValue value = (SettingValue) settingService.get(Context.GLOBAL, + Scope.GLOBAL, + BRANDING_PAGE_BG_SIZE_KEY); + if (value != null && StringUtils.isNotBlank(value.getValue())) { + return value.getValue(); + } else { + return null; + } + } + @Override public String getLoginBackgroundTextColor() { - SettingValue brandingLoginTextColor = (SettingValue) settingService.get(Context.GLOBAL, - Scope.GLOBAL, - BRANDING_LOGIN_TEXT_COLOR_KEY); - if (brandingLoginTextColor != null && StringUtils.isNotBlank(brandingLoginTextColor.getValue())) { - return brandingLoginTextColor.getValue(); + SettingValue color = (SettingValue) settingService.get(Context.GLOBAL, + Scope.GLOBAL, + BRANDING_LOGIN_TEXT_COLOR_KEY); + if (color != null && StringUtils.isNotBlank(color.getValue())) { + return color.getValue(); } else { return null; } @@ -418,6 +548,18 @@ public Long getLoginBackgroundId() { } } + @Override + public Long getPageBackgroundId() { + SettingValue backgroundId = (SettingValue) settingService.get(Context.GLOBAL, + Scope.GLOBAL, + BRANDING_PAGE_BG_ID_SETTING_KEY); + if (backgroundId != null && backgroundId.getValue() != null) { + return Long.parseLong(backgroundId.getValue()); + } else { + return null; + } + } + @Override public Logo getLogo() { if (this.logo == null) { @@ -471,25 +613,50 @@ public Background getLoginBackground() { return this.loginBackground; } + @Override + public Background getPageBackground() { + if (this.pageBackground == null) { + try { + Long imageId = getPageBackgroundId(); + if (imageId != null) { + this.pageBackground = retrieveStoredBrandingFile(imageId, new Background()); + } else { + this.pageBackground = new Background(); + } + } catch (Exception e) { + LOG.warn("Error retrieving page background", e); + } + } + return this.pageBackground; + } + @Override public String getLogoPath() { Logo brandingLogo = getLogo(); return brandingLogo == null - || brandingLogo.getData() == null ? null : BRANDING_LOGO_BASE_PATH + Objects.hash(brandingLogo.getUpdatedDate()); + || brandingLogo.getData() == null ? null : BRANDING_LOGO_BASE_PATH + Objects.hash(brandingLogo.getUpdatedDate()); } @Override public String getFaviconPath() { Favicon brandingFavicon = getFavicon(); return brandingFavicon == null - || brandingFavicon.getData() == null ? null : BRANDING_FAVICON_BASE_PATH + Objects.hash(brandingFavicon.getUpdatedDate()); + || brandingFavicon.getData() == null ? null : + BRANDING_FAVICON_BASE_PATH + Objects.hash(brandingFavicon.getUpdatedDate()); } @Override public String getLoginBackgroundPath() { Background background = getLoginBackground(); return background == null - || background.getData() == null ? null : BRANDING_LOGIN_BG_BASE_PATH + Objects.hash(background.getUpdatedDate()); + || background.getData() == null ? null : BRANDING_LOGIN_BG_BASE_PATH + Objects.hash(background.getUpdatedDate()); + } + + @Override + public String getPageBackgroundPath() { + Background background = getPageBackground(); + return background == null + || background.getData() == null ? null : BRANDING_PAGE_BG_BASE_PATH + Objects.hash(background.getUpdatedDate()); } @Override @@ -504,6 +671,8 @@ public void updateLastUpdatedTime(long lastUpdatedTimestamp) { } else { settingService.set(Context.GLOBAL, Scope.GLOBAL, BRANDING_LAST_UPDATED_TIME_KEY, SettingValue.create(lastUpdatedTimestamp)); } + this.themeCSSContent = null; + this.customCss = null; } @Override @@ -525,6 +694,7 @@ public void updateLoginBackground(Background loginBackground) { public void updateThemeStyle(Map themeStyle) { updateThemeStyle(themeStyle, true); } + @Override public Map getThemeStyle() { if (themeVariables == null || themeVariables.isEmpty()) { @@ -536,7 +706,8 @@ public Map getThemeStyle() { for (String themeVariable : variables) { SettingValue storedStyleValue = settingService.get(BRANDING_CONTEXT, BRANDING_SCOPE, themeVariable); String styleValue = storedStyleValue == null - || storedStyleValue.getValue() == null ? themeVariables.get(themeVariable) : storedStyleValue.getValue().toString(); + || storedStyleValue.getValue() == null ? themeVariables.get(themeVariable) : + storedStyleValue.getValue().toString(); if (StringUtils.isNotBlank(styleValue)) { themeStyleVariables.put(themeVariable, styleValue); } @@ -603,7 +774,7 @@ public String getLoginSubtitle(Locale locale) { /** * Load init params * - * @param initParams + * @param initParams * @throws Exception */ private void loadInitParams(InitParams initParams) { // NOSONAR @@ -672,20 +843,21 @@ private void loadLanguages() { Locale defaultLocale = getDefaultLocale(); this.supportedLanguages = localeConfigService.getLocalConfigs() == null ? Collections.singletonMap(defaultLocale.getLanguage(), - getLocaleDisplayName(defaultLocale, defaultLocale)) - : localeConfigService.getLocalConfigs() - .stream() - .filter(localeConfig -> !StringUtils.equals(localeConfig.getLocaleName(), - "ma")) - .collect(Collectors.toMap(LocaleConfig::getLocaleName, - localeConfig -> getLocaleDisplayName(defaultLocale, - localeConfig.getLocale()))); + getLocaleDisplayName(defaultLocale, + defaultLocale)) : + localeConfigService.getLocalConfigs() + .stream() + .filter(localeConfig -> !StringUtils.equals(localeConfig.getLocaleName(), + "ma")) + .collect(Collectors.toMap(LocaleConfig::getLocaleName, + localeConfig -> getLocaleDisplayName(defaultLocale, + localeConfig.getLocale()))); } private Locale getDefaultLocale() { - return localeConfigService.getDefaultLocaleConfig() == null ? Locale.getDefault() - : localeConfigService.getDefaultLocaleConfig() - .getLocale(); + return localeConfigService.getDefaultLocaleConfig() == null ? Locale.getDefault() : + localeConfigService.getDefaultLocaleConfig() + .getLocale(); } private String getDefaultLanguage() { @@ -693,63 +865,52 @@ private String getDefaultLanguage() { } private String getLocaleDisplayName(Locale defaultLocale, Locale locale) { - return defaultLocale.equals(locale) ? defaultLocale.getDisplayName(defaultLocale) - : locale.getDisplayName(defaultLocale) + " / " + locale.getDisplayName(locale); + return defaultLocale.equals(locale) ? defaultLocale.getDisplayName(defaultLocale) : + locale.getDisplayName(defaultLocale) + " / " + locale.getDisplayName(locale); } private void updateTopBarTheme(String topBarTheme, boolean updateLastUpdatedTime) { - if (StringUtils.isBlank(topBarTheme)) { - settingService.remove(Context.GLOBAL, Scope.GLOBAL, BRANDING_TOPBAR_THEME_SETTING_KEY); - } else { - settingService.set(Context.GLOBAL, Scope.GLOBAL, BRANDING_TOPBAR_THEME_SETTING_KEY, SettingValue.create(topBarTheme)); - } - if (updateLastUpdatedTime) { - updateLastUpdatedTime(System.currentTimeMillis()); - } + updatePropertyValue(topBarTheme, updateLastUpdatedTime, BRANDING_TOPBAR_THEME_SETTING_KEY); } private void updateCompanyLink(String companyLink, boolean updateLastUpdatedTime) { - if (StringUtils.isEmpty(companyLink)) { - settingService.remove(Context.GLOBAL, Scope.GLOBAL, BRANDING_COMPANY_LINK_SETTING_KEY); - } else { - settingService.set(Context.GLOBAL, Scope.GLOBAL, BRANDING_COMPANY_LINK_SETTING_KEY, SettingValue.create(companyLink)); - } - if (updateLastUpdatedTime) { - updateLastUpdatedTime(System.currentTimeMillis()); - } + updatePropertyValue(companyLink, updateLastUpdatedTime, BRANDING_COMPANY_LINK_SETTING_KEY); } private void updateSiteName(String siteName, boolean updateLastUpdatedTime) { - if (StringUtils.isEmpty(siteName)) { - settingService.remove(Context.GLOBAL, Scope.GLOBAL, BRANDING_SITE_NAME_SETTING_KEY); - } else { - settingService.set(Context.GLOBAL, Scope.GLOBAL, BRANDING_SITE_NAME_SETTING_KEY, SettingValue.create(siteName)); - } - if (updateLastUpdatedTime) { - updateLastUpdatedTime(System.currentTimeMillis()); - } + updatePropertyValue(siteName, updateLastUpdatedTime, BRANDING_SITE_NAME_SETTING_KEY); } private void updateLoginBackgroundTextColor(String textColor, boolean updateLastUpdatedTime) { - if (StringUtils.isBlank(textColor)) { - settingService.remove(Context.GLOBAL, Scope.GLOBAL, BRANDING_LOGIN_TEXT_COLOR_KEY); - } else { - settingService.set(Context.GLOBAL, Scope.GLOBAL, BRANDING_LOGIN_TEXT_COLOR_KEY, SettingValue.create(textColor)); - } - if (updateLastUpdatedTime) { - updateLastUpdatedTime(System.currentTimeMillis()); - } + updatePropertyValue(textColor, updateLastUpdatedTime, BRANDING_LOGIN_TEXT_COLOR_KEY); + } + + private void updatePageBackgroundColor(String color, boolean updateLastUpdatedTime) { + updatePropertyValue(color, updateLastUpdatedTime, BRANDING_PAGE_BG_COLOR_KEY); + } + + private void updatePageBackgroundSize(String value, boolean updateLastUpdatedTime) { + updatePropertyValue(value, updateLastUpdatedTime, BRANDING_PAGE_BG_SIZE_KEY); + } + + private void updatePageBackgroundPosition(String value, boolean updateLastUpdatedTime) { + updatePropertyValue(value, updateLastUpdatedTime, BRANDING_PAGE_BG_POSITION_KEY); + } + + private void updatePageBackgroundRepeat(String value, boolean updateLastUpdatedTime) { + updatePropertyValue(value, updateLastUpdatedTime, BRANDING_PAGE_BG_REPEAT_KEY); + } + + private void updatePageWidth(String value, boolean updateLastUpdatedTime) { + updatePropertyValue(value, updateLastUpdatedTime, BRANDING_PAGE_WIDTH_KEY); + } + + private void updateCustomCss(String value, boolean updateLastUpdatedTime) { + updatePropertyValue(value, updateLastUpdatedTime, BRANDING_CUSTOM_CSS); } private void updateCompanyName(String companyName, boolean updateLastUpdatedTime) { - if (StringUtils.isEmpty(companyName)) { - settingService.remove(Context.GLOBAL, Scope.GLOBAL, BRANDING_COMPANY_NAME_SETTING_KEY); - } else { - settingService.set(Context.GLOBAL, Scope.GLOBAL, BRANDING_COMPANY_NAME_SETTING_KEY, SettingValue.create(companyName)); - } - if (updateLastUpdatedTime) { - updateLastUpdatedTime(System.currentTimeMillis()); - } + updatePropertyValue(companyName, updateLastUpdatedTime, BRANDING_COMPANY_NAME_SETTING_KEY); } private void updateThemeStyle(Map themeStyles, boolean updateLastUpdatedTime) { @@ -768,9 +929,8 @@ private void updateThemeStyle(Map themeStyles, boolean updateLas } // Refresh Theme - computeThemeCSS(); if (updateLastUpdatedTime) { - updateLastUpdatedTime(System.currentTimeMillis()); + updateLastUpdatedTime(); } } @@ -812,7 +972,7 @@ private void updateLogo(Logo logo, boolean updateLastUpdatedTime) { // NOSONAR updateBrandingFile(logo, LOGO_NAME, this.getLogoId(), BRANDING_LOGO_ID_SETTING_KEY); this.logo = null; if (updateLastUpdatedTime) { - updateLastUpdatedTime(System.currentTimeMillis()); + updateLastUpdatedTime(); } } @@ -820,7 +980,7 @@ private void updateFavicon(Favicon favicon, boolean updateLastUpdatedTime) { updateBrandingFile(favicon, FAVICON_NAME, this.getFaviconId(), BRANDING_FAVICON_ID_SETTING_KEY); this.favicon = null; if (updateLastUpdatedTime) { - updateLastUpdatedTime(System.currentTimeMillis()); + updateLastUpdatedTime(); } } @@ -828,7 +988,15 @@ private void updateLoginBackground(Background loginBackground, boolean updateLas updateBrandingFile(loginBackground, LOGIN_BACKGROUND_NAME, this.getLoginBackgroundId(), BRANDING_LOGIN_BG_ID_SETTING_KEY); this.loginBackground = null; if (updateLastUpdatedTime) { - updateLastUpdatedTime(System.currentTimeMillis()); + updateLastUpdatedTime(); + } + } + + private void updatePageBackground(Background background, boolean updateLastUpdatedTime) { + updateBrandingFile(background, PAGE_BACKGROUND_NAME, this.getPageBackgroundId(), BRANDING_PAGE_BG_ID_SETTING_KEY); + this.pageBackground = null; + if (updateLastUpdatedTime) { + updateLastUpdatedTime(); } } @@ -862,8 +1030,8 @@ private void updateBrandingFileByUploadId(String uploadId, String settingKey) throws Exception { InputStream inputStream = getUploadDataAsStream(uploadId); if (inputStream == null) { - throw new IllegalArgumentException("Cannot update " + fileName - + ", the object must contain the image data or an upload id"); + throw new IllegalArgumentException("Cannot update " + fileName + + ", the object must contain the image data or an upload id"); } int size = inputStream.available(); FileItem fileItem = new FileItem(fileId, @@ -901,7 +1069,8 @@ private String computeThemeCSS() {// NOSONAR for (String themeVariable : variables) { SettingValue storedColorValue = settingService.get(BRANDING_CONTEXT, BRANDING_SCOPE, themeVariable); String colorValue = storedColorValue == null - || storedColorValue.getValue() == null ? themeVariables.get(themeVariable) : storedColorValue.getValue().toString(); + || storedColorValue.getValue() == null ? themeVariables.get(themeVariable) : + storedColorValue.getValue().toString(); if (StringUtils.isNotBlank(colorValue) && StringUtils.isNotBlank(lessThemeContent)) { lessThemeContent = lessThemeContent.replaceAll("@" + themeVariable + ":[ #a-zA-Z0-9]*;?\r?\n", "@" + themeVariable + ": " + colorValue + ";\n"); @@ -920,10 +1089,24 @@ private String computeThemeCSS() {// NOSONAR } } } - + if (StringUtils.isNotBlank(getCustomCssContent()) + && getFeatureService() != null + && getFeatureService().isActiveFeature(BRANDING_CUSTOM_STYLE_FEATURE)) { + this.themeCSSContent += "\n" + this.customCss; + } return this.themeCSSContent; } + private String getCustomCssContent() { + if (this.customCss == null) { + this.customCss = getCustomCss(); + if (this.customCss == null) { + this.customCss = ""; + } + } + return this.customCss; + } + private InputStream getUploadDataAsStream(String uploadId) throws FileNotFoundException { UploadResource uploadResource = uploadService.getUploadResource(uploadId); if (uploadResource == null) { @@ -976,4 +1159,50 @@ private T retrieveDefaultBrandingFile(String imagePath, return brandingFile; } + private void updatePropertyValue(String value, boolean updateLastUpdatedTime, String key) { + if (StringUtils.isBlank(value)) { + settingService.remove(Context.GLOBAL, Scope.GLOBAL, key); + } else { + settingService.set(Context.GLOBAL, Scope.GLOBAL, key, SettingValue.create(value)); + } + if (updateLastUpdatedTime) { + updateLastUpdatedTime(); + } + } + + private void validateCSSInputs(Branding branding) { // NOSONAR + Arrays.asList(branding.getCustomCss(), + branding.getPageBackgroundColor(), + branding.getPageBackgroundPosition(), + branding.getPageBackgroundRepeat(), + branding.getPageBackgroundSize(), + branding.getLoginBackgroundTextColor(), + branding.getPageBackgroundColor(), + branding.getPageBackgroundColor(), + branding.getPageBackgroundColor(), + branding.getPageBackgroundColor(), + branding.getPageBackgroundColor()) + .forEach(this::validateCSSStyleValue); + branding.getThemeStyle().values().forEach(this::validateCSSStyleValue); + } + + private void validateCSSStyleValue(String value) { + if (StringUtils.isNotBlank(value) + && (value.contains("javascript") || value.contains("eval"))) { + throw new IllegalArgumentException(String.format("Invalid css value input %s", + value)); + } + } + + private void updateLastUpdatedTime() { + updateLastUpdatedTime(System.currentTimeMillis()); + } + + private ExoFeatureService getFeatureService() { + if (featureService == null) { + featureService = container.getComponentInstanceOfType(ExoFeatureService.class); + } + return featureService; + } + } diff --git a/component/portal/src/main/java/org/exoplatform/portal/mop/storage/AbstractPageStorage.java b/component/portal/src/main/java/org/exoplatform/portal/mop/storage/AbstractPageStorage.java index 60df50aa34..4624926ba2 100644 --- a/component/portal/src/main/java/org/exoplatform/portal/mop/storage/AbstractPageStorage.java +++ b/component/portal/src/main/java/org/exoplatform/portal/mop/storage/AbstractPageStorage.java @@ -128,7 +128,6 @@ protected PageData buildPageData(PageEntity entity) { editPermission, // editPermission entity.isShowMaxWindow(), // showMaxWindow entity.isHideSharedLayout(), - null, // cssStyle moveAppsPermissions, moveContainersPermissions, entity.getPageType() != null ? entity.getPageType().name() : null, diff --git a/component/portal/src/main/java/org/exoplatform/portal/mop/storage/LayoutStorage.java b/component/portal/src/main/java/org/exoplatform/portal/mop/storage/LayoutStorage.java index 3921361362..2e279ca64a 100644 --- a/component/portal/src/main/java/org/exoplatform/portal/mop/storage/LayoutStorage.java +++ b/component/portal/src/main/java/org/exoplatform/portal/mop/storage/LayoutStorage.java @@ -42,6 +42,7 @@ import org.exoplatform.commons.utils.Safe; import org.exoplatform.portal.config.StaleModelException; import org.exoplatform.portal.config.model.Application; +import org.exoplatform.portal.config.model.ApplicationBackgroundStyle; import org.exoplatform.portal.config.model.ApplicationState; import org.exoplatform.portal.config.model.ApplicationType; import org.exoplatform.portal.config.model.CloneApplicationState; @@ -154,9 +155,9 @@ public String getId(ApplicationState state) { } Long id; - if (state instanceof PersistentApplicationState pstate) { + if (state instanceof PersistentApplicationState pstate) { // NOSONAR id = Safe.parseLong(pstate.getStorageId()); - } else if (state instanceof CloneApplicationState cstate) { + } else if (state instanceof CloneApplicationState cstate) { // NOSONAR id = Safe.parseLong(cstate.getStorageId()); } else { throw new IllegalStateException("Unrecognized Application state class type : " + state); @@ -418,33 +419,11 @@ private ContainerEntity buildContainerEntity(ContainerEntity dst, ContainerData } ModelStyle cssStyle = src.getCssStyle(); if (cssStyle != null) { - if (StringUtils.isNotBlank(cssStyle.getBorderColor())) { - properties.put(MappedAttributes.BORDER_COLOR.getName(), cssStyle.getBorderColor()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundColor())) { - properties.put(MappedAttributes.BACKGROUND_COLOR.getName(), cssStyle.getBackgroundColor()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundImage())) { - properties.put(MappedAttributes.BACKGROUND_IMAGE.getName(), cssStyle.getBackgroundImage()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundEffect())) { - properties.put(MappedAttributes.BACKGROUND_EFFECT.getName(), cssStyle.getBackgroundEffect()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundPosition())) { - properties.put(MappedAttributes.BACKGROUND_POSITION.getName(), cssStyle.getBackgroundPosition()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundSize())) { - properties.put(MappedAttributes.BACKGROUND_SIZE.getName(), cssStyle.getBackgroundSize()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundRepeat())) { - properties.put(MappedAttributes.BACKGROUND_REPEAT.getName(), cssStyle.getBackgroundRepeat()); - } - if (StringUtils.isNotBlank(cssStyle.getBorderSize())) { - properties.put(MappedAttributes.BORDER_SIZE.getName(), cssStyle.getBorderSize()); - } - if (StringUtils.isNotBlank(cssStyle.getBoxShadow())) { - properties.put(MappedAttributes.BOX_SHADOW.getName(), cssStyle.getBoxShadow()); - } + mapStyleToProperties(cssStyle, properties); + } + ApplicationBackgroundStyle appCssStyle = src.getAppBackgroundStyle(); + if (appCssStyle != null) { + mapAppStyleToProperties(appCssStyle, properties); } dst.setProperties(properties.toJSONString()); return dst; @@ -492,33 +471,7 @@ private WindowEntity buildWindowEntity(WindowEntity dst, ApplicationData srcChil } ModelStyle cssStyle = srcChild.getCssStyle(); if (cssStyle != null) { - if (StringUtils.isNotBlank(cssStyle.getBorderColor())) { - properties.put(MappedAttributes.BORDER_COLOR.getName(), cssStyle.getBorderColor()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundColor())) { - properties.put(MappedAttributes.BACKGROUND_COLOR.getName(), cssStyle.getBackgroundColor()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundImage())) { - properties.put(MappedAttributes.BACKGROUND_IMAGE.getName(), cssStyle.getBackgroundImage()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundEffect())) { - properties.put(MappedAttributes.BACKGROUND_EFFECT.getName(), cssStyle.getBackgroundEffect()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundPosition())) { - properties.put(MappedAttributes.BACKGROUND_POSITION.getName(), cssStyle.getBackgroundPosition()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundSize())) { - properties.put(MappedAttributes.BACKGROUND_SIZE.getName(), cssStyle.getBackgroundSize()); - } - if (StringUtils.isNotBlank(cssStyle.getBackgroundRepeat())) { - properties.put(MappedAttributes.BACKGROUND_REPEAT.getName(), cssStyle.getBackgroundRepeat()); - } - if (StringUtils.isNotBlank(cssStyle.getBorderSize())) { - properties.put(MappedAttributes.BORDER_SIZE.getName(), cssStyle.getBorderSize()); - } - if (StringUtils.isNotBlank(cssStyle.getBoxShadow())) { - properties.put(MappedAttributes.BOX_SHADOW.getName(), cssStyle.getBoxShadow()); - } + mapStyleToProperties(cssStyle, properties); } dst.setProperties(properties.toJSONString()); } else { @@ -582,37 +535,10 @@ private ApplicationData buildWindow(WindowEntity windowEntity) { ModelStyle cssStyle = null; String cssClass = null; if (attrs != null) { - cssStyle = new ModelStyle(); + cssStyle = mapPropertiesToStyle(attrs); if (attrs.containsKey(MappedAttributes.CSS_CLASS.getName())) { cssClass = (String) attrs.get(MappedAttributes.CSS_CLASS.getName()); } - if (attrs.containsKey(MappedAttributes.BORDER_COLOR.getName())) { - cssStyle.setBorderColor((String) attrs.get(MappedAttributes.BORDER_COLOR.getName())); - } - if (attrs.containsKey(MappedAttributes.BORDER_SIZE.getName())) { - cssStyle.setBorderSize((String) attrs.get(MappedAttributes.BORDER_SIZE.getName())); - } - if (attrs.containsKey(MappedAttributes.BOX_SHADOW.getName())) { - cssStyle.setBoxShadow((String) attrs.get(MappedAttributes.BOX_SHADOW.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_COLOR.getName())) { - cssStyle.setBackgroundColor((String) attrs.get(MappedAttributes.BACKGROUND_COLOR.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_IMAGE.getName())) { - cssStyle.setBackgroundImage((String) attrs.get(MappedAttributes.BACKGROUND_IMAGE.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_EFFECT.getName())) { - cssStyle.setBackgroundEffect((String) attrs.get(MappedAttributes.BACKGROUND_EFFECT.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_POSITION.getName())) { - cssStyle.setBackgroundPosition((String) attrs.get(MappedAttributes.BACKGROUND_POSITION.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_SIZE.getName())) { - cssStyle.setBackgroundSize((String) attrs.get(MappedAttributes.BACKGROUND_SIZE.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_REPEAT.getName())) { - cssStyle.setBackgroundRepeat((String) attrs.get(MappedAttributes.BACKGROUND_REPEAT.getName())); - } } return new ApplicationData(String.valueOf(windowEntity.getId()), @@ -659,38 +585,13 @@ private ContainerData buildContainer(ContainerEntity entity, String cssClass = null; String profiles = null; ModelStyle cssStyle = null; + ApplicationBackgroundStyle appBackgroundStyle = null; if (attrs != null) { - cssStyle = new ModelStyle(); + cssStyle = mapPropertiesToStyle(attrs); + appBackgroundStyle = mapPropertiesToAppStyle(attrs); if (attrs.containsKey(MappedAttributes.CSS_CLASS.getName())) { cssClass = (String) attrs.get(MappedAttributes.CSS_CLASS.getName()); } - if (attrs.containsKey(MappedAttributes.BORDER_COLOR.getName())) { - cssStyle.setBorderColor((String) attrs.get(MappedAttributes.BORDER_COLOR.getName())); - } - if (attrs.containsKey(MappedAttributes.BORDER_SIZE.getName())) { - cssStyle.setBorderSize((String) attrs.get(MappedAttributes.BORDER_SIZE.getName())); - } - if (attrs.containsKey(MappedAttributes.BOX_SHADOW.getName())) { - cssStyle.setBoxShadow((String) attrs.get(MappedAttributes.BOX_SHADOW.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_COLOR.getName())) { - cssStyle.setBackgroundColor((String) attrs.get(MappedAttributes.BACKGROUND_COLOR.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_IMAGE.getName())) { - cssStyle.setBackgroundImage((String) attrs.get(MappedAttributes.BACKGROUND_IMAGE.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_EFFECT.getName())) { - cssStyle.setBackgroundEffect((String) attrs.get(MappedAttributes.BACKGROUND_EFFECT.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_POSITION.getName())) { - cssStyle.setBackgroundPosition((String) attrs.get(MappedAttributes.BACKGROUND_POSITION.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_SIZE.getName())) { - cssStyle.setBackgroundSize((String) attrs.get(MappedAttributes.BACKGROUND_SIZE.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_REPEAT.getName())) { - cssStyle.setBackgroundRepeat((String) attrs.get(MappedAttributes.BACKGROUND_REPEAT.getName())); - } if (attrs.containsKey(MappedAttributes.PROFILES.getName())) { profiles = (String) attrs.get(MappedAttributes.PROFILES.getName()); } @@ -709,6 +610,7 @@ private ContainerData buildContainer(ContainerEntity entity, cssClass, profiles, cssStyle, + appBackgroundStyle, buildPermission(access), buildPermission(moveApps), buildPermission(moveConts), @@ -736,37 +638,7 @@ private List buildChildren(JSONArray jsonBody, // NOSONAR JSONObject attrs = parseJsonObject(srcContainer.getProperties()); String ctype = (String) attrs.get(MappedAttributes.TYPE.getName()); if (BodyType.PAGE.name().equals(ctype)) { - ModelStyle cssStyle = null; - if (attrs != null) { - cssStyle = new ModelStyle(); - if (attrs.containsKey(MappedAttributes.BORDER_COLOR.getName())) { - cssStyle.setBorderColor((String) attrs.get(MappedAttributes.BORDER_COLOR.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_COLOR.getName())) { - cssStyle.setBackgroundColor((String) attrs.get(MappedAttributes.BACKGROUND_COLOR.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_IMAGE.getName())) { - cssStyle.setBackgroundImage((String) attrs.get(MappedAttributes.BACKGROUND_IMAGE.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_EFFECT.getName())) { - cssStyle.setBackgroundEffect((String) attrs.get(MappedAttributes.BACKGROUND_EFFECT.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_POSITION.getName())) { - cssStyle.setBackgroundPosition((String) attrs.get(MappedAttributes.BACKGROUND_POSITION.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_SIZE.getName())) { - cssStyle.setBackgroundSize((String) attrs.get(MappedAttributes.BACKGROUND_SIZE.getName())); - } - if (attrs.containsKey(MappedAttributes.BACKGROUND_REPEAT.getName())) { - cssStyle.setBackgroundRepeat((String) attrs.get(MappedAttributes.BACKGROUND_REPEAT.getName())); - } - if (attrs.containsKey(MappedAttributes.BORDER_SIZE.getName())) { - cssStyle.setBorderSize((String) attrs.get(MappedAttributes.BORDER_SIZE.getName())); - } - if (attrs.containsKey(MappedAttributes.BOX_SHADOW.getName())) { - cssStyle.setBoxShadow((String) attrs.get(MappedAttributes.BOX_SHADOW.getName())); - } - } + ModelStyle cssStyle = mapPropertiesToStyle(attrs); BodyData body = new BodyData(String.valueOf(id), BodyType.PAGE, cssStyle); results.add(body); } else { @@ -797,7 +669,7 @@ private List saveChildren(List children) { // NO buildContainerEntity((ContainerEntity) dstChild, containerData); containerDAO.update((ContainerEntity) dstChild); } - } else if (srcChild instanceof ApplicationData appData) { + } else if (srcChild instanceof ApplicationData appData) { // NOSONAR dstChild = findWindow(srcChildId); if (dstChild != null) { dstChild = buildWindowEntity((WindowEntity) dstChild, appData); @@ -818,7 +690,7 @@ private List saveChildren(List children) { // NO if (srcChild instanceof ContainerData srcChildContainer) { dstChild = buildContainerEntity(null, srcChildContainer); dstChild = containerDAO.create((ContainerEntity) dstChild); - } else if (srcChild instanceof ApplicationData srcChildApplication) { + } else if (srcChild instanceof ApplicationData srcChildApplication) { // NOSONAR dstChild = buildWindowEntity(null, srcChildApplication); if (dstChild == null) { continue; @@ -911,9 +783,7 @@ private Set filterBodyContainerIds(JSONArray jsonBody, TYPE type, Set + + + + diff --git a/component/portal/src/test/java/org/exoplatform/portal/branding/BrandingServiceImplTest.java b/component/portal/src/test/java/org/exoplatform/portal/branding/BrandingServiceImplTest.java index f3e1308f3a..b7461366d1 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/branding/BrandingServiceImplTest.java +++ b/component/portal/src/test/java/org/exoplatform/portal/branding/BrandingServiceImplTest.java @@ -71,6 +71,7 @@ import org.exoplatform.portal.branding.model.Branding; import org.exoplatform.portal.branding.model.Favicon; import org.exoplatform.portal.branding.model.Logo; +import org.exoplatform.services.listener.ListenerService; import org.exoplatform.services.resources.LocaleConfigService; import org.exoplatform.services.resources.impl.LocaleConfigImpl; import org.exoplatform.upload.UploadResource; @@ -105,13 +106,13 @@ public void shouldGetDefaultBrandingInformationWhenNoUpdate() { siteName.setValue("Meeds"); initParams.addParam(siteName); - BrandingService brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingService brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); // When Branding brandingInformation = brandingService.getBrandingInformation(); @@ -157,13 +158,13 @@ public void shouldGetDefaultBrandingThemeColorsWhenNoUpdate() { initParams.addParam(companyName); initParams.addParam(themeStyle); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); brandingService.start(); // When @@ -238,13 +239,13 @@ public void shouldGetSavedBrandingThemeColorsWhenUpdate() { initParams.addParam(companyName); initParams.addParam(themeStyle); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); brandingService.start(); // When @@ -295,13 +296,13 @@ public void shouldGetUpdatedBrandingInformationWhenInformationUpdated() { siteName.setValue("Meeds"); initParams.addParam(siteName); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); // When Branding brandingInformation = brandingService.getBrandingInformation(); @@ -344,13 +345,13 @@ public void shouldGetBrandingInformationWithoutBinaries() { loginBgPathParam.setValue(loginBgPath); initParams.addParam(loginBgPathParam); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); ServletContext context = mock(ServletContext.class); when(container.getPortalContext()).thenReturn(context); @@ -427,13 +428,13 @@ public void shouldUpdateCompanyNameAndTopBarThemeWhenInformationUpdated() throws themeStyle.setValues(variables); initParams.addParam(themeStyle); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); Branding newBranding = new Branding(); newBranding.setCompanyName("New Company Name"); @@ -534,13 +535,13 @@ public void shouldUpdateLogoWhenLogoUpdatedByUploadId() throws Exception { companyName.setValue("Default Company Name"); initParams.addParam(companyName); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); Branding newBranding = new Branding(); Logo logo = new Logo(); @@ -608,13 +609,13 @@ public void shouldUpdateFaviconWhenFaviconUpdatedByUploadId() throws Exception { companyName.setValue("Default Company Name"); initParams.addParam(companyName); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); Branding newBranding = new Branding(); Favicon favicon = new Favicon(); @@ -659,13 +660,13 @@ public void testGetDefaultLoginBackground() throws Exception { LocaleConfigService localeConfigService = mock(LocaleConfigService.class); InitParams initParams = new InitParams(); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); assertNull(brandingService.getLoginBackgroundPath()); @@ -676,13 +677,13 @@ public void testGetDefaultLoginBackground() throws Exception { loginBgPath.setValue(imagePath); initParams.addParam(loginBgPath); - brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); ServletContext context = mock(ServletContext.class); when(container.getPortalContext()).thenReturn(context); @@ -706,13 +707,13 @@ public void testGetDefaultFavicon() throws Exception { LocaleConfigService localeConfigService = mock(LocaleConfigService.class); InitParams initParams = new InitParams(); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); assertNull(brandingService.getFaviconPath()); @@ -723,13 +724,13 @@ public void testGetDefaultFavicon() throws Exception { faviconPathParam.setValue(imagePath); initParams.addParam(faviconPathParam); - brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); ServletContext context = mock(ServletContext.class); when(container.getPortalContext()).thenReturn(context); @@ -753,13 +754,13 @@ public void testGetDefaultLogo() throws Exception { LocaleConfigService localeConfigService = mock(LocaleConfigService.class); InitParams initParams = new InitParams(); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); assertNull(brandingService.getLogoPath()); @@ -770,13 +771,13 @@ public void testGetDefaultLogo() throws Exception { logoPathParam.setValue(imagePath); initParams.addParam(logoPathParam); - brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); ServletContext context = mock(ServletContext.class); when(container.getPortalContext()).thenReturn(context); @@ -800,13 +801,13 @@ public void testUpdateLoginBackground() throws Exception { LocaleConfigService localeConfigService = mock(LocaleConfigService.class); InitParams initParams = new InitParams(); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); assertNull(brandingService.getLoginBackgroundPath()); @@ -852,13 +853,13 @@ public void testRemoveLoginBackground() throws Exception { LocaleConfigService localeConfigService = mock(LocaleConfigService.class); InitParams initParams = new InitParams(); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); long fileId = 2l; when(settingService.get(Context.GLOBAL, @@ -907,13 +908,13 @@ public void testUpdateLoginTitle() throws Exception { when(localeConfigService.getLocalConfigs()).thenReturn(Arrays.asList(newLocaleConfig(Locale.ENGLISH), newLocaleConfig(Locale.FRENCH))); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); assertNotNull(brandingService.getLoginTitle()); assertEquals(1, brandingService.getLoginTitle().size()); @@ -983,13 +984,13 @@ public void testUpdateLoginSubtitle() throws Exception { when(localeConfigService.getLocalConfigs()).thenReturn(Arrays.asList(newLocaleConfig(Locale.ENGLISH), newLocaleConfig(Locale.FRENCH))); - BrandingServiceImpl brandingService = new BrandingServiceImpl(container, - configurationManager, - settingService, - fileService, - uploadService, - localeConfigService, - initParams); + BrandingServiceImpl brandingService = newBrandingService(settingService, + fileService, + uploadService, + localeConfigService, + configurationManager, + container, + initParams); assertNotNull(brandingService.getLoginSubtitle()); assertEquals(1, brandingService.getLoginSubtitle().size()); @@ -1050,4 +1051,21 @@ private LocaleConfigImpl newLocaleConfig(Locale locale) { return localeConfig; } + private BrandingServiceImpl newBrandingService(SettingService settingService, + FileService fileService, + UploadService uploadService, + LocaleConfigService localeConfigService, + ConfigurationManager configurationManager, + PortalContainer container, + InitParams initParams) { + return new BrandingServiceImpl(container, + configurationManager, + settingService, + fileService, + uploadService, + localeConfigService, + mock(ListenerService.class), + initParams); + } + } diff --git a/component/portal/src/test/java/org/exoplatform/portal/config/TestSerialization.java b/component/portal/src/test/java/org/exoplatform/portal/config/TestSerialization.java index 21160b6666..73d66aea1f 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/config/TestSerialization.java +++ b/component/portal/src/test/java/org/exoplatform/portal/config/TestSerialization.java @@ -21,6 +21,7 @@ import java.util.*; +import org.exoplatform.portal.config.model.ApplicationBackgroundStyle; import org.exoplatform.portal.config.model.ModelStyle; import org.exoplatform.portal.mop.PageType; import org.gatein.common.io.IOTools; @@ -50,6 +51,7 @@ public class TestSerialization extends AbstractGateInTest { "foo11", "foo12", new ModelStyle(), + new ApplicationBackgroundStyle(), Collections.singletonList("foo11"), Collections.singletonList("foo11"), Collections.singletonList("foo11"), @@ -120,7 +122,6 @@ Arrays. asList(body), "foo16", true, true, - new ModelStyle(), Collections.singletonList("foo13"), Collections.singletonList("foo13"), PageType.LINK.name(), diff --git a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestDataStorage.java b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestDataStorage.java index 7f21fcdd4d..66556bd0bd 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestDataStorage.java +++ b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestDataStorage.java @@ -948,6 +948,7 @@ protected void createSite(SiteType type, String siteName) throws Exception { "", "", null, + null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), diff --git a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJCBCNavigationServiceRebase.java b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJCBCNavigationServiceRebase.java index 9b4274ce0e..e3bb50de92 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJCBCNavigationServiceRebase.java +++ b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJCBCNavigationServiceRebase.java @@ -77,6 +77,7 @@ protected void createSite(SiteType type, String siteName) throws Exception { "", "", null, + null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), diff --git a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationService.java b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationService.java index 88b5a38af1..cb37d19733 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationService.java +++ b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationService.java @@ -72,6 +72,7 @@ protected void createSite(SiteType type, String siteName) throws Exception { "", "", null, + null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), diff --git a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceSave.java b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceSave.java index 33ad0f9e54..352173cd26 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceSave.java +++ b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceSave.java @@ -79,6 +79,7 @@ protected void createSite(SiteType type, String siteName) throws Exception { "", "", null, + null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), diff --git a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceUpdate.java b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceUpdate.java index 6bbfd4210b..f7376f5a6b 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceUpdate.java +++ b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceUpdate.java @@ -80,6 +80,7 @@ protected void createSite(SiteType type, String siteName) throws Exception { "", "", null, + null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), diff --git a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceWrapper.java b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceWrapper.java index 62016369c2..4fdb4b1309 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceWrapper.java +++ b/component/portal/src/test/java/org/exoplatform/portal/mop/storage/TestJDBCNavigationServiceWrapper.java @@ -87,6 +87,7 @@ protected void createSite(SiteType type, String siteName) throws Exception { "", "", null, + null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), diff --git a/web/portal/src/main/webapp/groovy/portal/webui/application/UIPortlet.gtmpl b/web/portal/src/main/webapp/groovy/portal/webui/application/UIPortlet.gtmpl index f05b3a9666..d533485898 100644 --- a/web/portal/src/main/webapp/groovy/portal/webui/application/UIPortlet.gtmpl +++ b/web/portal/src/main/webapp/groovy/portal/webui/application/UIPortlet.gtmpl @@ -39,9 +39,10 @@ } cssStyle = " style=\"" + cssStyle + "\""; } + String cssClass = uicomponent.getCssClass() == null ? "" : " " + uicomponent.getCssClass(); %>
-
+
<% println portletContent; %>
diff --git a/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl b/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl index 9d6f745bda..15bb6f329b 100644 --- a/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl +++ b/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl @@ -62,10 +62,10 @@ } def title = rcontext.getTitle(); + BrandingService brandingService = uicomponent.getApplicationComponent(BrandingService.class); if (portal.getSiteKey().getType() == org.exoplatform.portal.mop.SiteType.PORTAL) { ResourceBundleService resourceBundleService = uicomponent.getApplicationComponent(ResourceBundleService.class); ResourceBundle bundle = resourceBundleService.getResourceBundle("locale.portlet.Portlets", rcontext.getLocale()); - BrandingService brandingService = uicomponent.getApplicationComponent(BrandingService.class); if (portal.getSiteKey().getName().equals("public")) { title = brandingService.getCompanyName() + " - " + bundle.getString("publicSite.title.suffix"); } else if (portal.getSiteKey().getName().equals("administration")) { @@ -79,6 +79,25 @@ if (bodyClasses == null) { bodyClasses = ""; } + def bodyStyle = ""; + if (brandingService.getPageBackgroundColor() != null) { + bodyStyle += "--allPagesBackgroundColor: " + brandingService.getPageBackgroundColor() + ";"; + } + if (brandingService.getPageBackgroundPath() != null) { + bodyStyle += "--allPagesBackgroundImage: url(" + brandingService.getPageBackgroundPath() + ");"; + } + if (brandingService.getPageBackgroundRepeat() != null) { + bodyStyle += "--allPagesBackgroundRepeat: " + brandingService.getPageBackgroundRepeat() + ";"; + } + if (brandingService.getPageBackgroundSize() != null) { + bodyStyle += "--allPagesBackgroundSize: " + brandingService.getPageBackgroundSize() + ";"; + } + if (brandingService.getPageBackgroundPosition() != null) { + bodyStyle += "--allPagesBackgroundPosition: " + brandingService.getPageBackgroundPosition() + ";"; + } + if (brandingService.getPageWidth() != null) { + bodyStyle += "--allPagesWidth: " + brandingService.getPageWidth() + ";"; + } def userHomeLink = uicomponent.getUserHomePage(); def stickyMenu = false; @@ -234,7 +253,7 @@ <% _ctx.includeTemplates("UIPortalApplication-head") %> - + <%/* Include extensible templates configured by Kernel configuration to be imported in the beginning of the body section of the Page */%> <% _ctx.includeTemplates("UIPortalApplication-Start-body") %>
diff --git a/webui/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java b/webui/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java index 51098a2e8d..81b54dd787 100644 --- a/webui/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java +++ b/webui/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java @@ -47,6 +47,7 @@ import org.exoplatform.container.ExoContainerContext; import org.exoplatform.container.PortalContainer; import org.exoplatform.portal.config.*; +import org.exoplatform.portal.config.model.Page; import org.exoplatform.portal.config.model.PortalConfig; import org.exoplatform.portal.mop.SiteKey; import org.exoplatform.portal.mop.SiteType; @@ -62,7 +63,9 @@ import org.exoplatform.portal.mop.user.UserPortalContext; import org.exoplatform.portal.url.PortalURLContext; import org.exoplatform.portal.webui.page.UIPage; +import org.exoplatform.portal.webui.page.UIPageFactory; import org.exoplatform.portal.webui.portal.UIPortal; +import org.exoplatform.portal.webui.util.PortalDataMapper; import org.exoplatform.portal.webui.util.Util; import org.exoplatform.portal.webui.workspace.UIPortalApplication; import org.exoplatform.services.log.ExoLogger; @@ -205,6 +208,10 @@ public class PortalRequestContext extends WebuiRequestContext { @Setter private UIPage uiPage; + @Getter + @Setter + private Page page; + @Getter @Setter private UserNode userNode; @@ -394,6 +401,32 @@ public void refreshPortalConfig() { this.currentPortalConfig = null; } + public UIPage getUIPage(UserNode pageNode, UIPortal uiPortal) throws Exception { + PageContext pageContext = null; + String pageReference = null; + if (pageNode != null && pageNode.getPageRef() != null) { + pageReference = pageNode.getPageRef().format(); + pageContext = layoutService.getPageContext(pageNode.getPageRef()); + } + + // The page has been deleted + if (pageContext == null) { + // Clear the UIPage from cache in UIPortal + uiPortal.clearUIPage(pageReference); + return null; + } else { + setDraftPage(pageNode.getVisibility() == Visibility.DRAFT); + this.page = layoutService.getPage(pageReference); + if (uiPortal.getUIPage(pageReference) == null) { + UIPageFactory clazz = UIPageFactory.getInstance(pageContext.getState().getFactoryId()); + this.uiPage = clazz.createUIPage(this); + pageContext.update(this.page); + PortalDataMapper.toUIPage(this.uiPage, this.page); + } + return this.uiPage; + } + } + public String getInitialURI() { return request_.getRequestURI(); } diff --git a/webui/src/main/java/org/exoplatform/portal/webui/application/UIPortlet.java b/webui/src/main/java/org/exoplatform/portal/webui/application/UIPortlet.java index 27263b3463..debfabffa5 100644 --- a/webui/src/main/java/org/exoplatform/portal/webui/application/UIPortlet.java +++ b/webui/src/main/java/org/exoplatform/portal/webui/application/UIPortlet.java @@ -106,6 +106,8 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; +import lombok.Getter; +import lombok.Setter; /** * This UI component represent a portlet window on a page.
@@ -195,6 +197,10 @@ public class UIPortlet extends UIApplication { /** A field storing localized value of javax.portlet.title * */ private String configuredTitle; + @Getter + @Setter + private String cssClass; + public String getStorageId() { return storageId; } @@ -1068,8 +1074,8 @@ public Text generateRenderMarkup(PortletInvocationResponse pir, WebuiRequestCont if (pir instanceof FragmentResponse) { if (lazyResourcesLoading == null) { PortletInfo portletInfo = producedOfferedPortlet.getInfo(); - if (portletInfo instanceof ContainerPortletInfo) { - String prefetchResources = ((ContainerPortletInfo) portletInfo).getInitParameter("prefetch.resources"); + if (portletInfo instanceof ContainerPortletInfo containerPortletInfo) { + String prefetchResources = containerPortletInfo.getInitParameter("prefetch.resources"); lazyResourcesLoading = StringUtils.equals(prefetchResources, "true"); } else { lazyResourcesLoading = false; diff --git a/webui/src/main/java/org/exoplatform/portal/webui/page/UIPageActionListener.java b/webui/src/main/java/org/exoplatform/portal/webui/page/UIPageActionListener.java index bf441a294a..75ee33918d 100644 --- a/webui/src/main/java/org/exoplatform/portal/webui/page/UIPageActionListener.java +++ b/webui/src/main/java/org/exoplatform/portal/webui/page/UIPageActionListener.java @@ -19,21 +19,14 @@ package org.exoplatform.portal.webui.page; -import java.util.ArrayList; import org.exoplatform.portal.application.PortalRequestContext; import org.exoplatform.portal.config.UserPortalConfig; import org.exoplatform.portal.config.model.Container; -import org.exoplatform.portal.config.model.ModelObject; -import org.exoplatform.portal.config.model.Page; import org.exoplatform.portal.config.model.PortalConfig; import org.exoplatform.portal.mop.SiteKey; import org.exoplatform.portal.mop.SiteType; -import org.exoplatform.portal.mop.Utils; import org.exoplatform.portal.mop.navigation.NavigationContext; -import org.exoplatform.portal.mop.page.PageContext; -import org.exoplatform.portal.mop.page.PageState; -import org.exoplatform.portal.mop.service.LayoutService; import org.exoplatform.portal.mop.service.NavigationService; import org.exoplatform.portal.mop.user.UserNavigation; import org.exoplatform.portal.mop.user.UserNode; @@ -44,8 +37,6 @@ import org.exoplatform.portal.webui.util.PortalDataMapper; import org.exoplatform.portal.webui.workspace.UIPortalApplication; import org.exoplatform.portal.webui.workspace.UIWorkingWorkspace; -import org.exoplatform.web.application.ApplicationMessage; -import org.exoplatform.webui.core.UIComponent; import org.exoplatform.webui.event.Event; import org.exoplatform.webui.event.EventListener; diff --git a/webui/src/main/java/org/exoplatform/portal/webui/page/UIPageBody.java b/webui/src/main/java/org/exoplatform/portal/webui/page/UIPageBody.java index 7268701df9..9818757cd0 100644 --- a/webui/src/main/java/org/exoplatform/portal/webui/page/UIPageBody.java +++ b/webui/src/main/java/org/exoplatform/portal/webui/page/UIPageBody.java @@ -20,6 +20,7 @@ package org.exoplatform.portal.webui.page; import org.exoplatform.container.ExoContainer; +import org.exoplatform.container.ExoContainerContext; import org.exoplatform.portal.application.PortalRequestContext; import org.exoplatform.portal.config.model.Page; import org.exoplatform.portal.mop.Visibility; @@ -70,7 +71,7 @@ public void setPageBody(UserNode pageNode, UIPortal uiPortal) throws Exception { UIPage uiPage = getUIPage(); if (uiPage == null) { - uiPage = getUIPage(pageNode, uiPortal, context); + uiPage = context.getUIPage(pageNode, uiPortal); if (uiPage == null) { setUIComponent(null); return; @@ -108,51 +109,6 @@ public UIPage getUIPage() { return (UIPage) getUIComponent(); } - /** - * Return cached UIPage or a newly built UIPage - * - * @param pageReference - * @param page - * @param uiPortal - * @return - */ - private UIPage getUIPage(UserNode pageNode, UIPortal uiPortal, WebuiRequestContext context) throws Exception { - PageContext pageContext = null; - String pageReference = null; - ExoContainer appContainer = context.getApplication().getApplicationServiceContainer(); - LayoutService layoutService = appContainer.getComponentInstanceOfType(LayoutService.class); - - if (pageNode != null && pageNode.getPageRef() != null) { - pageReference = pageNode.getPageRef().format(); - pageContext = layoutService.getPageContext(pageNode.getPageRef()); - } - - // The page has been deleted - if (pageContext == null) { - // Clear the UIPage from cache in UIPortal - uiPortal.clearUIPage(pageReference); - return null; - } - - getRequestContext().setDraftPage(pageNode.getVisibility() == Visibility.DRAFT); - try { - UIPage uiPage = uiPortal.getUIPage(pageReference); - if (uiPage == null) { - UIPageFactory clazz = UIPageFactory.getInstance(pageContext.getState().getFactoryId()); - uiPage = clazz.createUIPage(context); - Page page = layoutService.getPage(pageReference); - pageContext.update(page); - PortalDataMapper.toUIPage(uiPage, page); - } - return uiPage; - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("Could not handle page '" + pageContext.getKey().format() + "'.", e); - } - throw e; - } - } - private PortalRequestContext getRequestContext() { return PortalRequestContext.getCurrentInstance(); } diff --git a/webui/src/main/java/org/exoplatform/portal/webui/util/PortalDataMapper.java b/webui/src/main/java/org/exoplatform/portal/webui/util/PortalDataMapper.java index a19d9f4ee3..a6a36f8f5f 100644 --- a/webui/src/main/java/org/exoplatform/portal/webui/util/PortalDataMapper.java +++ b/webui/src/main/java/org/exoplatform/portal/webui/util/PortalDataMapper.java @@ -24,10 +24,12 @@ import java.util.Set; import org.exoplatform.portal.mop.service.LayoutService; + import org.gatein.common.net.media.MediaType; import org.gatein.pc.api.Portlet; import org.gatein.pc.api.info.ModeInfo; import org.gatein.pc.api.info.PortletInfo; +import org.gatein.pc.portlet.impl.info.ContainerPortletInfo; import org.exoplatform.portal.config.UserPortalConfigService; import org.exoplatform.portal.config.model.Application; @@ -249,7 +251,10 @@ private static void toUIPortlet(UIPortlet uiPortlet, Application mo if (supportModes.size() > 1) supportModes.remove("view"); uiPortlet.setSupportModes(supportModes); - } + if (portletInfo instanceof ContainerPortletInfo containerPortletInfo) { + uiPortlet.setCssClass(containerPortletInfo.getInitParameter("layout-css-class")); + } + } public static void toUIContainer(UIContainer uiContainer, Container model) throws Exception { uiContainer.setStorageId(model.getStorageId());