eXo Platform 3.5

## Chapter 2. Create Your Own Portal

When working with eXo Platform, it is important not to modify the source code. This will ensure compatibility with future upgrades, and support will be simplified. To customize your portal, you need to create an extension project by providing your own artifacts as a set of wars/jars/ears.

This chapter will show you how to create a portal via the following topics:

- Create your extension project

- Define a default portal

- Structure of portal, pages and menus

- Enable/Disable a drive creation during the portal creation

- Add/Remove a language

- Create a custom look and feel

- Add JavaScript to your portal

- Create custom templates for pages

## 2.1. Create your extension project

A custom extension contains two mandatory items:

- extension webapp contains resources and kernel configurations.

- extension activator jar identifies your webapp as a dependency of the portal container.

To see the sample extension package, visit here.

Once you have modified the sample extension to build your own portal, use the maven clean install command to create the archive files.

Deploy your extension in Tomcat

1. Add the sample-ext.war file from the sample/extension/war/target/ to the tomcat/webapps directory.

2. Add the starter folder from starter/war/target/ to the tomcat/webapps directory.

3. Rename the starter directory (unzipped folder) to starter.war.

### Note

This will only work if the starter.war is the last .war file to be loaded, so you may need to rename it if your war files are loaded in the alphabetical order.

4. Add the .jar file named exo.portal.sample.extension.config-X.Y.Z.jar from sample/extension/config/target/ to the tomcat/lib directory.

5. Add the .jar file named exo.portal.sample.extension.jar-X.Y.Z.jar from sample/extension/jar/target/ to the tomcat/lib directory.

6. Create a sample-ext.xml file (this file is a Context Descriptor to configure a context within Tomcat server and to ensure that the extension gets loaded before the starter.war). Then add this file to the tomcat/conf/Catalina/localhost directory with the following content.

    <Context crossContext="true" debug="0" docBase="sample-ext" path="/sample-ext" reloadable="true"/>

For the JBoss deployment with more details, refer to the GateIn Reference Guide.

## 2.2. Define a default portal

When entering the link of the portal in the address bar of the browser without defining a specific portal (e.g. localhost:8080/portal/), you will be directed to a default portal.

To configure the default portal, the portal must already exist first. Then, you just use the NewPortalConfigListener plugin as the sample code below.

To use this plugin in the component configuration, you must use the following target-component:

    <target-component>org.exoplatform.portal.config.UserPortalConfigService</target-component>

The sample code below is the configuration of the portal named "default".

    <external-component-plugins>

            <target-component>org.exoplatform.portal.config.UserPortalConfigService</target-component>

            <component-plugin>

                <name>default.portal.config.user.listener</name>

                <set-method>initListener</set-method>

                <type>org.exoplatform.portal.config.NewPortalConfigListener</type>

                <description>this listener init the portal configuration</description>

                <init-params>

                    <value-param>

                        <name>default.portal</name>

                        <description>The default portal for checking db is empty or not</description>

                        <value>default</value>

                    </value-param>

                    <object-param>

                        ....

                    </object-param>

                </init-params>

            </component-plugin>

        </external-component-plugins>

Init-param

Name | Type | Value | Description
--- | --- | --- | ---
default.portal | String | default | The name of the default portal to which you are redirected when accessing the portal.

## 2.3. Structure of portal, pages and menus

You can create multiple pages within a single portal. Permissions can be defined to make them visible only to specific groups and/or users. This chapter describes how to define this structure.

### 2.3.1. Portal navigation

The portal navigation incorporates the pages that can be accessed even when the user is not logged in assuming the applicable permissions allow the public access). For example, several portal navigations are used when a company owns multiple trademarks, and sets up a website for each of them.

The configuration of the "classic" portal can be found in the /src/main/WEB-INF/conf/portal/portal/classic directory of your extension webapp.

portal.xml

The portal.xml file describes the layout and portlets that will be shown on all pages. The layout usually contains the banner, footer, menu and breadcrumbs portlets. eXo Platform 3.5 is extremely configurable as every view element (even the banner and footer) is a portlet.

    <portal-config xmlns="http://www.gatein.org/xml/ns/gatein_objects_1_0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gatein.org/xml/ns/gatein_objects_1_0 http://www.gatein.org/xml/ns/gatein_objects_1_0">

       <portal-name>classic</portal-name>

       <locale>en</locale>

       <access-permissions>Everyone</access-permissions>

       <edit-permission>*:/platform/administrators</edit-permission>

       <properties>

          <entry key="sessionAlive">onDemand</entry>

          <entry key="showPortletInfo">1</entry>

       </properties>

       <portal-layout>

          <portlet-application>

             <portlet>

                <application-ref>web</application-ref>

                <portlet-ref>BannerPortlet</portlet-ref>

                <preferences>

                   <preference>

                      <name>template</name>

                      <value>par:/groovy/groovy/webui/component/UIBannerPortlet.gtmpl</value>

                      <read-only>false</read-only>

                   </preference>

                </preferences>

             </portlet>

             <access-permissions>Everyone</access-permissions>

             <show-info-bar>false</show-info-bar>

          </portlet-application>

          <portlet-application>

             <portlet>

                <application-ref>web</application-ref>

                <portlet-ref>NavigationPortlet</portlet-ref>

             </portlet>

             <access-permissions>Everyone</access-permissions>

             <show-info-bar>false</show-info-bar>

          </portlet-application>

          <portlet-application>

             <portlet>

                <application-ref>web</application-ref>

                <portlet-ref>BreadcumbsPortlet</portlet-ref>

             </portlet>

             <access-permissions>Everyone</access-permissions>

             <show-info-bar>false</show-info-bar>

          </portlet-application>

          <page-body> </page-body>

          <portlet-application>

             <portlet>

                <application-ref>web</application-ref>

                <portlet-ref>FooterPortlet</portlet-ref>

                <preferences>

                   <preference>

                      <name>template</name>

                      <value>par:/groovy/groovy/webui/component/UIFooterPortlet.gtmpl</value>

                      <read-only>false</read-only>

                   </preference>

                </preferences>

             </portlet>

             <access-permissions>Everyone</access-permissions>

             <show-info-bar>false</show-info-bar>

          </portlet-application>

       </portal-layout>

    </portal-config>

Each portlet can be configured with a set of preferences, which will be further detailed in the Work With Applications chapter.

It is also possible to apply a nested container that can also contain portlets. Row, column or tab containers are then responsible for the layout of their child portlets.

Each application references a portlet using the id: portal#{portalName}:/{portletWarName}/{portletName}/{uniqueId}

The <page-body> </page-body> tag is a placeholder for the different pages of your portal, it defines where Platform should render the current page. When the user opens a new portal page, all portlets of the portal layout (portal.xml) are remained, whereas the content of <page-body> switches to the page opened by the user.

The defined "classic" portal is accessible to "Everyone" (at /portal/classic) but only members of the group /platform/administrators can edit it.

pages.xml

The structure of the pages.xml configuration file is very similar to that in the portal.xml of the "classic" portal and it can also contain container tags. Each application can decide whether to render the portlet border, the window state, the icons or portlet's mode.

This is the example of the pages.xml file of the "classic" portal.

    <page-set xmlns="http://www.gatein.org/xml/ns/gatein_objects_1_0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gatein.org/xml/ns/gatein_objects_1_0 http://www.gatein.org/xml/ns/gatein_objects_1_0">

       <page>

          <name>homepage</name>

          <title>Home Page</title>

          <access-permissions>Everyone</access-permissions>

          <edit-permission>*:/platform/administrators</edit-permission>

          <portlet-application>

             <portlet>

                <application-ref>web</application-ref>

                <portlet-ref>HomePagePortlet</portlet-ref>

                <preferences>

                   <preference>

                      <name>template</name>

                      <value>system:/templates/groovy/webui/component/UIHomePagePortlet.gtmpl</value>

                      <read-only>false</read-only>

                   </preference>

                </preferences>

             </portlet>

             <title>Home Page portlet</title>

             <access-permissions>Everyone</access-permissions>

             <show-info-bar>false</show-info-bar>

             <show-application-state>false</show-application-state>

             <show-application-mode>false</show-application-mode>

          </portlet-application>

       </page>

       <page>

          <name>sitemap</name>

          <title>Site Map</title>

          <access-permissions>Everyone</access-permissions>

          <edit-permission>*:/platform/administrators</edit-permission>

          <portlet-application>

             <portlet>

                <application-ref>web</application-ref>

                <portlet-ref>SiteMapPortlet</portlet-ref>

             </portlet>

             <title>SiteMap</title>

             <access-permissions>Everyone</access-permissions>

             <show-info-bar>false</show-info-bar>

          </portlet-application>

       </page>

       .......

    </page-set>

### Note

See the Work With Applications chapter to learn more about the portlet configuration within the pages.xml file.

navigation.xml

The navigation.xml file defines all the navigation nodes of the portal. The syntax is simply using the nested node tags. Each node refers to a page defined in the pages.xml file that will be explained later.

If the administrator wants to create node labels for each language, he will have to use xml:lang attribute in the label tag with the value of xml:lang is set to the relevant locale.

Otherwise, if the administrator wants the node label is localized by resource bundle files, the #{...} syntax will be used. The enclosed property name serves as a key that is automatically passed to the internationalization mechanism. Thus, the emphasis property name is replaced with a localized value taken from the associated properties file matching the current locale.

    <node-navigation>

      <owner-type>portal</owner-type>

      <owner-id>classic</owner-id>

      <priority>1</priority>

      <page-nodes>

        <node>

          <uri>home</uri>

          <name>home</name>

          <label>#{portal.classic.home}</label>

          <page-reference>portal::classic::homepage</page-reference>

        </node>

        <node>

          <uri>webexplorer</uri>

          <name>webexplorer</name>

          <label>#{portal.classic.webexplorer}</label>

          <page-reference>portal::classic::webexplorer</page-reference>

        </node>

      </page-nodes>

    </node-navigation>

This navigation tree is shown and reused in different portlets, such as sitemap, navigation or breadcrumbs. The breadcrumbs portlet renders the position of the current navigation node.

### Note

For the top nodes, the URI and the navigation node name must have the same value. For other nodes, the URI is composed like <uri>contentmanagement/fileexplorer</uri> where 'contentmanagement' is the name of the parent node, and 'fileexplorer' is the name of node (<name>fileexplorer</name>).

### 2.3.2. Visibility of pages

When you configure the navigation.xml file, sometimes you need to set the visibility of page (node).

To configure the page visibility, simply put <visibility>type_of_visibility</visibility> as a child of the <node> tag.

eXo Platform supports 4 types of page visibility, including:

- DISPLAYED: The page will be displayed.

- HIDDEN: The page is not visible in the navigation but can be accessed directly with its URL.

- SYSTEM: It is a system page which is visible to superusers. In particular, only superusers can change or delete this system page.

- TEMPORAL: The page is displayed in related time range. When the visibility of TEMPORAL page is configured, the start and end date can be specified by using <startpublicationdate> and <endpublicationdate>. For example:

    <node>

      ...

      <visibility>TEMPORAL</visibility>

      <startpublicationdate>01/13/2011 12:46:38</startpublicationdate>

      <endpublicationdate>01/20/2011 18:46:42</endpublicationdate>

    </node>

- To hide a page from menu and navigation, use <visibility>HIDDEN</visibility>:

    <node-navigation xmlns="http://www.gatein.org/xml/ns/gatein_objects_1_0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gatein.org/xml/ns/gatein_objects_1_0 http://www.gatein.org/xml/ns/gatein_objects_1_0">

      <page-nodes>

        <node>

          <uri>sitemap</uri>

          <name>sitemap</name>

          <label>#{portal.classic.sitemap}</label>

          <visibility>HIDDEN</visibility>

          <page-reference>portal::classic::sitemap</page-reference>

        </node>

        ...

      </page-nodes>

    </node-navigation>

### 2.3.3. Page access permission

You can easily restrict the access of selected pages and navigation nodes to certain groups and users. You just need to create pages.xml and navigation.xml files in folders named after groups and users to which you want to give permission:

- sample-ext/portal/group/group-name/your files

- sample-ext/portal/user/username/your files

As you know, the permission on a page has two types: access (view the page) and edit.

To configure them, edit the pages.xml file and put tags: <access-permissions> and <edit-permission>.

Currently, eXo Platform supports several access permissions but only one edit permission. It means that you can configure to make many groups to have the access permission but you can only set one group for edit permission.

For example:

    <page>

      <name>newStaff</name>

      <title>New Staff</title>

      <access-permissions>manager:/organization/management/executive-board;member:/organization/management/executive-board</access-permissions>

      <edit-permission>manager:/organization/management/executive-board</edit-permission>

      ...

    </page>

## 2.4. Enable/Disable a drive creation during the portal creation

When a portal is created, a drive with the same name as the portal is also automatically created. However, you can decide if such a drive is automatically created or not by using two parameters named autoCreatedDrive, and targetDrives in the CreateLivePortalEventListener external component plugin.

    <external-component-plugins>

        <target-component>org.exoplatform.services.listener.ListenerService</target-component>

        <component-plugin>

            <name>org.exoplatform.portal.config.DataStorage.portalConfigCreated</name>

            <set-method>addListener</set-method>

            <type>org.exoplatform.services.wcm.portal.listener.CreateLivePortalEventListener</type>

            <description>this listener creates a new live portal content storage.</description>

            <init-params>

                <value-param>

                    <name>autoCreatedDrive</name>

                    <description>A drive will be automatically created during the portal creation.</description>

                    <value>false</value>

                </value-param>

                <values-param>

                    <name>targetDrives</name>

                    <description>The list of drives which are automatically created during the portal creation with

                        "autoCreatedDrive=false".

                    </description>

                    <value>acme</value>

                </values-param>

            </init-params>

        </component-plugin>

    </external-component-plugins>

- If autoCreatedDrive=true, a drive will be automatically created during the portal creation regardless of targetDrives. In case autoCreatedDrive is not specified, then its default value is true.

- If autoCreatedDrive=false, only drives listed in targetDrives are created. In case targetDrives is not specified, no drives are created.

## 2.5. Add/Remove a language

Developer can define new or remove a defined language through the locale configuration file. The resource is managed by org.exoplatform.services.resources.LocaleConfigService as following:

    <component>

        <key>org.exoplatform.services.resources.LocaleConfigService</key>

        <type>org.exoplatform.services.resources.impl.LocaleConfigServiceImpl</type>

          <init-params>

            <value-param>

              <name>locale.config.file</name>

              <value>war:/conf/common/locales-config.xml</value>

            </value-param>

          </init-params>

      </component>

All languages defined in the locale-config.xml file are listed in the Interface Language Settings window.

### 2.5.1. Add a new language

To add a new language, you need to add the corresponding language node in the locale-config.xml file. Next, you must create a new resource bundle file containing the suffix name as the key of the added node.

For example, to add Italian, do as follows:

1. Add the following node to the locale-config.xml file.

    <locale-config>

      <locale>it</locale>

      <output-encoding>UTF-8</output-encoding>

      <input-encoding>UTF-8</input-encoding>

      <description>Default configuration for Italian locale</description>

    </locale-config>

2. Create a new resource bundle as webui_it.properties in the myextension.war/WEB-INF/classes/locale/portal folder.

### Note

This step is necessary because the Resource Bundle Service of the portal will find keys and values in the resource bundle of each corresponding language.

3. Restart the server.

To check if the added language takes effect, hover the mouse over your username on the Administration bar and click Change Language. In the Interface Language Settings window that appears, you will see the Italian is listed as below:

### 2.5.2. Remove a language

To remove an existing language, you need to delete the relevant language node in the locale-config.xml file and all files containing the suffix name as the key of language.

For example, to remove French, do as follows:

1. Find and remove the following node from the locale-config.xml file.

    <locale-config>

      <locale>fr</locale>

      <output-encoding>UTF-8</output-encoding>

      <input-encoding>UTF-8</input-encoding>

      <description>Default configuration for france locale</description>

    </locale-config>

2. Continue removing all resource bundle files containing the suffix name as fr in all folders.

### Note

It is recommended this step be done to delete unnecessary data in the application.

3. Restart the server.

To check if French is removed, hover the mouse over your username on the Administration bar and click the Change Language.

In the Interface Language Settings window that appears, French is no longer listed.

## 2.6. Create a custom look and feel

### 2.6.1. Platform skin elements

Platform provides support for skinning the entire portal User Interface (UI) including your own portlets. Skins are designed to help you pack and reuse common graphic resources.

The complete skinning of can be decomposed into three main parts: Portal skin, Window style, Portlet skin.

Portal skin

The portal skin contains styles for the HTML tags (for example, div, th, td) and the portal UI (including the toolbar). This should include all UI components, except for window decorators and portlet specific styles.

Window style

The CSS styles are associated with the portlet window decorators. The window decorators contain control buttons and borders surrounding each portlet. Individual portlets can have their own window decorators selected, or be rendered without one.

Portlet skin

The portlet skins affect how portlets are rendered on the page. The portlet skins can affect in two main ways described in the following sections.

Portlet Specification CSS Classes

The portlet specification defines a set of CSS classes that should be available to portlets. eXo Platform provides these classes as a part of the portal skin. This enables each portal skin to define its own look and feel for these default values.

Portlet skins

eXo Platform provides a means for portlet CSS files to be loaded that is based on the current portal skin. This enables a portlet to provide different CSS styles to better match the current portal's look and feel.

### Note

The window decorators and the default portlet specification CSS classes should be considered as separate types of skinning components, but they need to be included as a part of the overall portal skin. The portal skin must include CSS classes of these components or they will not be displayed correctly. A portlet skin does not need to be included as a part of the portal skin and can be included within the portlets web application.

#### SkinService

Platform skin is processed by the SkinService. It is used to discover and deploy skins into the portal.

- Configure skins

In eXo Platform 3.5 has a file descriptor for skins (WEB-INF/gatein-resources.xml) which is to specify which portal, portlet and window decorators will be deployed into the skin service. Platform can automatically discover web archives containing this file gatein-resource.xml. The full schema can be found in the lib directory: exo.portal.component.portal.jar/gatein_resources_1_0.xsd.

Here is the gatein-resources.xml file of a sample skin (called "MySkin") which defines the portal skin with its CSS location, window style and its portlet skins:

    <gatein-resources>

    <!-- define the portal skin -->

    <portal-skin>

        <skin-name>MySkin</skin-name>

        <css-path>/skin/myskin.css</css-path>

        <overwrite>false</overwrite>

    </portal-skin>

    <!-- define the portlet skin -->

    <portlet-skin>

      <application-name>web</application-name>

      <portlet-name>HomePagePortlet</portlet-name>

      <skin-name>Default</skin-name>

      <css-path>/templates/skin/webui/component/UIHomePagePortlet/DefaultStylesheet.css</css-path>

        <overwrite>false</overwrite>

    </portlet-skin>

      <!-- define the window style -->

    <window-style>

        <style-name>MyThemeCategory</style-name>

        <style-theme>

          <theme-name>MyThemeBlue</theme-name>

        </style-theme>

        <style-theme>

          <theme-name>MyThemeRed</theme-name>

        </style-theme>

    </window-style>

    </gatein-resources>

#### ResourceRequestFilter

The ResourceRequestFilter is used to map process skin request mapping from portal, portlet to the exact skin that was defined in portal. ResourceRequestFilter is configured in the web.xml file in the skin web archive.

    <webapp>

    <display-name>eXoResources</display-name>

    <filter>

      <filter-name>ResourceRequestFilter</filter-name>

      <filter-class>org.exoplatform.portal.application.ResourceRequestFilter</filter-class>

    </filter>

    <filter-mapping>

      <filter-name>ResourceRequestFilter</filter-name>

      <url-pattern>*.css</url-pattern>

    </filter-mapping>

    </webapp>

### Note

The configuration of Portlet Skin takes an optional parameter application-name, which is the web application wrapping skinned portlet. Hence, the display-name element in web.xml needs to be coherent with the application-name in the gatein-resources.xml file.

#### The default skin

The default skin of eXo Platform 3.5 is in the eXoResource.war file. The main files associated with the skin are:

- WEB-INF/gatein-resources.xml defines the skin settings to use.

- WEB-INF/web.xml contains the resource filter with the display-name set.

- skin/Stylesheet.css contains the CSS class definitions for this skin.

### Note

To get a new portal skin declared in gatein-resources.xml loaded successfully, display-name of the extension webapp (in web.xml) should be identical to the context path of the extension webapp.

The following block of CSS illustrates content of the skin/Stylesheet.css file:

    @import url(DefaultSkin/portal/webui/component/UIPortalApplicationSkin.css); (1)
    @import url(DefaultSkin/webui/component/Stylesheet.css); (2)
    @import url(PortletThemes/Stylesheet.css); (3)
    @import url(Portlet/Stylesheet.css); (4)

In which:

- (1) Skin of the portal page. The UIPortalApplicationSkin.css defines CSS classes shared by all the portal pages.

- (2) Skins of various portal-owned components, such as WorkingWorkspace, MaskWorkspace, PortalForm, and more.

- (3) Window decorator skins.

- (4) The portlet specification CSS classes. (The CSS styles defined in Portlet Specification JSR286)

To make a default skin flexible and highly reusable, instead of defining all CSS classes in this file, CSS classes are arranged in nested stylesheet files, based on the @import statement. This makes easier for new skins to reuse parts of the default skin. To reuse a CSS stylesheet from the default portal skin, you need to refer to the default skin from eXoResources. For example, to include the window decorators from the default skin within a new portal skin, you need to use the following import:

    @import url(/eXoResources/skin/Portlet/Stylesheet.css);

### Note

When the portal skin is added to the page, it merges all CSS stylesheets into a single file.

### 2.6.2. Override skins with extension

The extension mechanism of eXo Platform 3.5 enables the skin definition to be replaced with the skin resource configured in the extension-deployed web application. This is the example where the CSS path of default portal skin needs to be modified without touching the Platform's files.

    <gatein-resources>

      <portal-skin>

        <skin-name>Default</skin-name>

        <css-path>/skin/Defaultskin/Stylesheet.css</css-path>

        <overwrite>false</overwrite>

        <css-priority>0</css-priority>

      </portal-skin>

    </gatein-resources>

(The css-path specifies the stylesheet of the new skin.)

Override skins with extension

1. Create a web application whose gatein-resources.xml contains the same content as the above xml block, except the element <css-path> is modified.

2. Ensure that once the server has deployed the artifact, it does not load any web application with gatein-resources.xml configuring the same portal skin.

### 2.6.3. Create new skins

#### Create a new skin web archive

Create new portal skins

To create a new skin (called "MySkin"), you should create a new skin web archive with the following structure:

- The web.xml is the file that you will define the ResourceRequestFilter.

- The gatein-resource.xml will define your new skin (for portal, portlet or window style).

- The skin folder will contain images and stylesheets of your skin.

Configure portal skins

You need to specify the new portal skin in the gatein-resources.xml file. You also need to specify the name of new skin, where to locate its CSS stylesheet file and whether to overwrite the existing portal theme with the same name.

    <gatein-resources>

      <portal-skin>

        <skin-name>MySkin</skin-name>

        <css-path>/skin/myskin.css</css-path>

        <overwrite>false</overwrite>

        <css-priority>0</css-priority>

      </portal-skin>

    </gatein-resources>

The default portal skin and window styles are defined in the eXoResources.war/WEB-INF/gatein-resources.xml file.

### Note

The CSS for the portal skin needs to contain CSS for all window decorators and portlet specification CSS classes.

eXo Platform provides the "CSS priority" concept which controls the loading order of skins. The skin with lower "css-priority" value will be loaded first.

#### Create the skin preview icon

When selecting a skin it is possible to see a preview of what the skin will look like. The current skin needs to know about the skin icons for all the available skins, otherwise it will not be able to show the previews. When creating a new portal it is recommended to include the preview icons of the other skins and to update the other skins with your new portal skin preview.

For any portal skin, the paths to the preview images are specified in CSS class UIChangeSkinForm:

- eXoResources/src/main/webapp/skin/DefaultSkin/portal/webui/component/customization/UIChangeSkinForm/Stylesheet.css

For the portal named MySkin, it is required to define the following CSS classes:

    .UIChangeSkinForm .UIItemSelector .TemplateContainer .MySkinImage

The default skin would be aware of skin icons if the preview screenshot is placed in:

- eXoResources.war:/skin/DefaultSkin/portal/webui/component/customization/UIChangeSkinForm/background.

The CSS stylesheet for the default portal needs to have the following updated with the preview icon CSS class. For the skin named MySkin, it is required to update the following:

- eXoResources.war:/skin/DefaultSkin/portal/webui/component/customization/UIChangeSkinForm/Stylesheet.css.

Now, amending the deployed package eXoResources is inevitable (modifying the default war/jar breaches development convention of Platform-based products). The problem would be resolved in future eXo Platform versions in which different skin modules are fully independent, for example, there will be no preview image duplication.

    .UIChangeSkinForm .UIItemSelector .TemplateContainer .MySkinImage {
    margin: auto;
    width: 329px; height:204px;
    background: url('background/MySkin.jpg') no-repeat top;
    cursor: pointer ;
    }

#### Skin the window style

Window style is the CSS applied to the window decorator. When the administrator selects a new application to add to a page, he can decide which style of decorator surrounding the window if any.

Configure window styles

Window style is defined within the gatein-resources.xml file used by the SkinService to deploy the window style. Window styles can belong to a window style category. This category and window styles need to be specified in the resources file. For example, the following gatein-resource.xml fragment will add MyThemeBlue and MyThemeRed to the MyTheme category.

    <window-style>

      <style-name>MyTheme</style-name>

      <style-theme>

        <theme-name>MyThemeBlue</theme-name>

      </style-theme>

      <style-theme>

        <theme-name>MyThemeRed</theme-name>

      </style-theme>

    </window-style>

The windows style of the default skin is configured in the eXoResources.war/WEB-INF/gatein-resources.xml file.

### Note

When a window style is defined in the gatein-resources.xml file, it will be available to all portlets regardless of whether the current portal skin supports the window decorator or not. When a new window decorator is added, it should be added to all portal skins or the portal skins should share a common stylesheet for window decorators.

Window style CSS

In order for the SkinService to display the window decorators, it must have CSS classes with the specific naming related to the window style name. The service will try and display CSS based on this naming. The CSS class must be included as part of the current portal skin for the window decorators to be displayed. The window decorator CSS classes for the default portal theme are located at eXoResources.war/skin/PortletThemes/Stylesheet.css.

Set the default window style

To set the default window style for a portal, you need to specify the CSS classes for a theme called DefaultTheme.

### Note

You do not need to specify the DefaultTheme in the gatein-resources.xml file.

#### Configure the right-to-left skin

The SkinService handles stylesheet rewriting to accommodate the orientation. It works by appending -lt or -rt to the stylesheet name. For example, /web/skin/portal/webui/component/UIFooterPortlet/DefaultStylesheet-rt.css will return the same stylesheet as /web/skin/portal/webui/component/UIFooterPortlet/DefaultStylesheet.css but processed for the RT orientation. The -lt suffix is optional. Stylesheet authors can annotate their stylesheet to create content that depends on the orientation.

Example 1. This example uses the orientation to modify the float attribute that will make the horizontal tabs either float on left or on right:

    float: left; /* orientation=lt */
    float: right; /* orientation=rt */
    font-weight: bold;
    text-align: center;
    white-space: nowrap;

The LT produced output will be:

    float: left; /* orientation=lt */
    font-weight: bold;
    text-align: center;
    white-space: nowrap;

The RT produced output will be:

    float: right; /* orientation=rt */
    font-weight: bold;
    text-align: center;
    white-space: nowrap;

Example 2. In this example, you need to modify the padding based on the orientation:

    color: white;
    line-height: 24px;
    padding: 0px 5px 0px 0px; /* orientation=lt */
    padding: 0px 0px 0px 5px; /* orientation=rt */

The LT produced output will be:

    color: white;
    line-height: 24px;
    padding: 0px 5px 0px 0px; /* orientation=lt */

The RT produced output will be:

    color: white;
    line-height: 24px;
    padding: 0px 0px 0px 5px; /* orientation=rt */

### 2.6.4. Skin the portlet

Portlets often require additional styles that may not be defined by the portal skin. eXo Platform 3.5 defines additional stylesheets for each portlet and will append the corresponding link tags to the head. The ID attribute of <link> element will be in the portletAppName/PortletName form. For example, the ContentPortlet in content.war takes "content/ContentPortlet" as ID. To define a new CSS file to be included whenever a portlet is available on a portal page, the following fragment needs to be added in the gatein-resources.xml file.

    <portlet-skin>

      <application-name>portletAppName</application-name>

      <portlet-name>PortletName</portlet-name>

      <skin-name>Default</skin-name>

      <css-path>/skin/DefaultStylesheet.css</css-path>

    </portlet-skin>

    <portlet-skin>

      <application-name>portletAppName</application-name>

      <portlet-name>PortletName</portlet-name>

      <skin-name>OtherSkin</skin-name>

      <css-path>/skin/OtherSkinStylesheet.css</css-path>

    </portlet-skin>

This action will load DefaultStylesheet.css or OtherSkinStylesheet.css when the DefaultSkin or OtherSkin is used respectively.

### Note

If the current portal skin is not defined as part of the supported skins, the portlet CSS class will not be loaded. The portlet skins should be updated whenever a new portal skin is created.

Change portlet icons

Each portlet can be represented by a unique icon that you can see in the portlet registry or page editor. This icon can be changed by adding an image to the directory of portlet web application: skin/DefaultSkin/portletIcons/icon_name.png. The icon must be named after the portlet. For example, the icon of account portlet must be named AccountPortlet and located at: skin/DefaultSkin/portletIcons/AccountPortlet.png.

### Note

You must use skin/DefaultSkin/portletIcons/ for the directory to store the portlet icon regardless of using any skins.

### 2.6.5. Configure Platform skin

#### Select skins within the configuration files

The default skin can be set in the portal configuration files. The skin configured as default is used by Platform as the administrator starts/restarts the server.

Simply add a skin tag to the portal.war/WEB-INF/conf/portal/portal/classic/portal.xml configuration file.

To change skin to YourSkin, use the following code:

    <portal-config>

      <portal-name>classic</portal-name>

      <locale>en</locale>

      <access-permissions>Everyone</access-permissions>

      <edit-permission>*:/platform/administrators</edit-permission>

      <skin>MySkin</skin>

      ...

    </portal-config>

#### Skins in the page markup

The eXo Platform 3.5 skin not only contains CSS styles for the portal's components, but also shares components that may be reused in portlets. When eXo Platform 3.5 generates the page markup of portal, stylesheet links will be inserted in the page's head tag. There are two main types of CSS links which appear in the head tag: one to the portal skin CSS file and the other to the portlet skin CSS file.

- Portal Skin appears as a single link to a CSS file. This link contains contents from all portal skin classes merged into one file. The portal skin will be transferred more quickly as a single file instead of multiple smaller files.

- Portlet Skin only appears as the link on the page if that portlet is loaded on the current page. A page may contain many CSS links of portlet skins or none.

In the code fragment below, you can see two types of links:

    <head>
      ...
      <!-- The portal skin -->
      <link id="CoreSkin" rel="stylesheet" type="text/css" href="/eXoResources/skin/Stylesheet.css" />
      <!-- The portlet skins -->
      <link id="web_FooterPortlet" rel="stylesheet" type="text/css"
        href="/web/skin/portal/webui/
    component/UIFooterPortlet/DefaultStylesheet.css" />
      <link id="web_NavigationPortlet" rel="stylesheet" type="text/css"
        href="/web/skin/portal/webui/
    component/UINavigationPortlet/DefaultStylesheet.css" />
      <link id="web_HomePagePortlet" rel="stylesheet" type="text/css"
        href="/portal/templates/skin/
    webui/component/UIHomePagePortlet/DefaultStylesheet.css" />
      <link id="web_BannerPortlet" rel="stylesheet" type="text/css"
        href="/web/skin/portal/webui/
    component/UIBannerPortlet/DefaultStylesheet.css" />
      ...
    </head>

### Note

Window styles and portlet specification CSS classes are included within the portal skin.

#### Customize portal's layout

### Note

This section is related to the configuration. You can see a sample here. You can leave all the portlet's preferences as blank, that means the default value will be taken and you do not need to care about it at this time.

For example, you will have a layout like this:

In which:

- Branding: A branding application

- Top navigation: A top navigation application

A table column container with three nested containers:

- Left Column and Right Column: Contain one application for each.

- Main content: Contain the page body.

And here is the fragment of portal.xml located in this path: <myportal_path>/src/main/webapp/WEB-INF/conf/myportal/portal/portal/mysite/portal.xml.

    <!-- ... -->

    <portlet-application>

      <!-- Branding application. You can use WCM web content *exo:webContent* for the content and SCV portlet to display -->

    </portlet-application>

    <portlet-application>

      <!-- navigation application. You can use WCM web content *exo:webContent* for the content and SCV portlet to display -->

    </portlet-application>

    <container id="MySite" template="system:/groovy/portal/webui/container/UITableColumnContainer.gtmpl">

      <container id="LeftColumn" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">

        <!-- One or more application(s) here -->

        <portlet-application>

        </portlet-application>

      </container>

      <container template="system:/groovy/portal/webui/container/UIContainer.gtmpl">

        <page-body>

        </page-body>

      </container>

      <container id="RightColumn" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">

        <!-- One or more application(s) here -->

        <portlet-application>

        </portlet-application>

      </container>

    </container>

    <portlet-application>

      <!-- Footer application. You can use WCM web content *exo:webContent* for the content and SCV portlet to display -->

    </portlet-application>

    <!-- ... -->

As you see in the portal.xml file above, every container tag has an id attribute, for example "<container id = 'RightColumn'>". When you create a CSS file, the property applied for this container should have the following name manner:

    ${container_id}TDContainer

and the details of this container:

    RightColumnTDContainer

The reason is, when you have a look in the file system: /groovy/portal/webui/container/UITableColumnContainer.gtmpl shown above, you will see this code fragment:

    <table class="UITableColumnContainer"
      style="table-layout: fixed; margin: 0px auto;">
      <tr class="TRContainer">
        <% for(uiChild in uicomponent.getChildren()) {%>
        <td class="${uiChild.id}TDContainer TDContainer"><%
          uicomponent.renderUIComponent(uiChild) %></td> <% } %>
      </tr>
    </table>

So, in the table element (which represents the outer container), there are many td elements, each of which has the class attribute that equals to the id of the corresponding child component plus the "TDContainer" string literal.

#### Customize page's layouts

### Note

This section is related to the configuration. You can see a sample here. You can leave all the portlet's preferences as blank, that means the default value will be taken and you do not need to care about it at this time.

- Like portal.xml, you can define the layout for each page in your site as shown in the following example:

    <!-- ... -->

    <portlet-application> <!-- A custom document for content and SCV portlet to display -->

    </portlet-application>

    <portlet-application> <!-- A CLV portlet with a custom template. -->

    </portlet-application>

    <portlet-application> <!-- A CLV portlet with another custom template. -->

    </portlet-application>

    <!-- ... -->

#### Customize the Admin bar

This section shows you how to customize the Admin bar via the following topics:

- sharedlayout.xml

- Remove a content from the Admin bar

- Add a content to the Admin bar

- Change the color scheme

##### sharedlayout.xml

The Admin bar is a special container composed of portlets and defined in WEB-INF/conf/portal/portal/sharedlayout.xml.

If you want to redefine these portlets, you need to override this file by creating your own sharedlayout.xml located into your extension: custom-extension.war!WEB-INF/conf/portal/portal/sharedlayout.xml.

Followings are two examples of configuration, one to remove a portlet, the other to add a new portlet to the Admin bar.

##### Remove a content from the Admin bar

Portlets on the Admin bar

In the illustration above, each circle represents a portlet defined in the Admin bar and configured in sharedlayout.xml.

The sharedlayout.xml file configures the current displayed portlets on the Admin bar. For example, to remove the Dashboard menu, you will need to remove the following block:

    ...

    <container id="UserToolBarDashboardPortlet" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">

      <portlet-application>

        <portlet>

          <application-ref>exoadmin</application-ref>

          <portlet-ref>UserToolbarDashboardPortlet</portlet-ref>

        </portlet>

        <access-permissions>Everyone</access-permissions>

        <show-info-bar>false</show-info-bar>

      </portlet-application>

    </container>

     ...

##### Add content to the Admin bar

Add a portlet to the Admin bar to logout user

In the same way you removed a portlet from the admin bar, you can add your own portlet by editing your sharedlayout.xml.

    ...

    <container id="UILogoutPortlet" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">

      <access-permissions>*:/platform/users</access-permissions>

      <portlet-application>

        <portlet>

          <application-ref>platformNavigation</application-ref>

          <portlet-ref>UILogoutPortlet</portlet-ref>

        </portlet>

        <access-permissions>*:/platform/users</access-permissions>

        <show-info-bar>false</show-info-bar>

      </portlet-application>

    </container>

    ...

Style of portlet container can be changed by editing this css file:

eXoResources/skin/DefaultSkin/portal/webui/component/view/UIToolbarContainer/Stylesheet.css

    .UIToolbarContainer .UILogoutPortletTDContainer {
    	float: right; /* orientation=lt */
    	float: left; /* orientation=rt */
    }

##### Change the color scheme

The current color of the Admin bar is gray gradient. However, you can change the color to match your brand colors.

The default Administration style:

The style of the Admin bar is defined in the stylesheet.css located in extension/resources/src/main/webapp/skin/platformSkin/UIToolbarContainer.

Edit this CSS file to customize the Admin bar to your preferred color scheme.

The CSS code below shows how to modify the Admin bar to look like this:

    .UIWorkingWorkspace #UIToolbarContainer .HomeLinkTDContainer {
    	line-height: 31px;
        margin: 0px 5px;
        vertical-align: middle;
    }

    .UIWorkingWorkspace .UIToolbarContainer .ToolbarContainer {
    	/*background: url(background/BgToolbarContainer.gif) repeat-x left top;*/
    	height: 31px;
    	border: none;
    }

    .UIWorkingWorkspace .UIToolbarContainer .ToolbarContainer .UITab .MenuItemContainer .MenuItem a {
    	padding: 0 22px 0 22px;
    	font-size: 12px!important;
    	color: #4c4c4c;
    	display: block;
    	font-weight: normal;
    	white-space: nowrap;
    }

    .UIToolbarContainer .ToolbarContainer .PinLink {
        padding: 0px;
    }

    .UIWorkingWorkspace .UIToolbarContainer .ToolbarContainer a.TBIcon {
    	/*color: #2f3334;*/
    	font-weight: normal;
    	padding: 0 20px;
    	display: block;
    	white-space: nowrap;
    	background: none;
    	margin-left: 0;
    	zoom: 1;
    	font-size:14px!important;
    	font-family: verdana;
    	border: 1px solid transparent;
    	border-bottom: none;
    	line-height: 29px;
    	height: 29px;
    }

    .UIWorkingWorkspace .UIToolbarContainer .ToolbarContainer a.SetupMenuItem  {
    	padding: 0 8px;
    	line-height:25px;
     }

### 2.6.6. Configure skin in WCM

This tutorial will help you to create a new layout and skin, and give some best practices when creating a new layout and skin for your portal and page. Instructions described here are based on the following assumptions:

- You have an extension named "MyPortal", and you need to create a site called "MySite" inside this portal.

- The <myportal_path> below is replaced with the based path of your "MyPortal" extension.

- If you see any folder/file which does not exist, you should create a new one.

#### Customize CLV portlet's template

### Note

This section is related to the configuration. You can see a sample here.

- Apply your HTML/Groovy template code for this template.

For example:

<myportal_path>/src/main/webapp/WEB-INF/conf/myportal/customized/template/list/ACustomizedCLVTemplate.gtmpl

    <div id="$uicomponent.id" class="ACustomizedCLVTemplate">
      <div class="ListContents">
        <!-- something here -->
      </div>
    </div>

- Now, you need to import this template to the database.

<myportal_path>/src/main/webapp/WEB-INF/conf/myportal/customized/template/configuration.xml

    <external-component-plugins>

      <target-component>org.exoplatform.services.cms.views.ApplicationTemplateManagerService</target-component>

      <component-plugin>

        <name>ACustomizedCLVTemplate</name>

        <set-method>addPlugin</set-method>

        <type>org.exoplatform.services.cms.views.PortletTemplatePlugin</type>

        <description>This is a sample customized CLV template</description>

        <init-params>

          <value-param>

            <name>portletName</name>

            <value>Content List Viewer</value>

          </value-param>

          <value-param>

            <name>portlet.template.path</name>

            <value>war:/conf/myportal/customized/template</value>

          </value-param>

          <object-param>

            <name>default.folder.list.viewer</name>

            <description>Default folder list viewer groovy template</description>

            <object type="org.exoplatform.services.cms.views.PortletTemplatePlugin$PortletTemplateConfig">

              <field name="templateName">

                <string>ACustomizedCLVTemplate.gtmpl</string>

              </field>

              <field name="category">

                <string>list</string>

              </field>

            </object>

          </object-param>

        </init-params>

      </component-plugin>

    </external-component-plugins>

#### Customize CLV template's style

1. Go to Sites explorer portlet --> Sites management drive --> MySite/css folder.

2. Create a new CSS document which contains your stylesheet for the portal and the page layout. You can use any name for this document and put a priority number.

### Note

This document should contain ONLY one stylesheet for THIS template. If you have another template, you should create a new CSS document.

- The following is the sample stylesheet:

    /* ... */
    .ACustomizedCLVTemplate {
    /* ... */

    }

    .ListContents {
    /* ... */

    }

    /* ... */

3. Export the document and now you have an XML file.

Please check out this tutorial to know how to import this XML into the database.

### 2.6.7. Customize Document's skin

### Note

This section is related to the configuration. You can see a sample here.

First, you need to create a new document definition.

- <myportal_path>/src/main/webapp/WEB-INF/conf/myportal/customized/document/ACustomizedDocument.xml

    	node type name :exo:customizedDocument
    	properties: exo:name(type : String), exo:title(type : String), exo:content(type : String)

You also need to configure it to make sure it is imported to the database.

- <myportal_path>/src/main/webapp/WEB-INF/conf/myportal/customized/document/definition-configuration.xml

    <external-component-plugins>

      <target-component>org.exoplatform.services.jcr.RepositoryService</target-component>

      <component-plugin>

        <name>ACustomizedDocument</name>

        <set-method>addPlugin</set-method>

        <type>org.exoplatform.services.jcr.impl.AddNodeTypePlugin</type>

        <priority>200</priority>

        <init-params>

          <values-param>

            <name>autoCreatedInNewRepository</name>

            <description>ACustomizedDocument document definition</description>

            <value>war:/conf/myportal/customized/document/ACustomizedDocument.xml</value>

          </values-param>

        </init-params>

      </component-plugin>

    </external-component-plugins>

Next, create the templates for this document, including:

- Dialog: see the sample here.

<myportal_path>/src/main/webapp/WEB-INF/conf/myportal/customized/document/dialog.gtmpl

    <div class="UIForm ACustomizedDocument">
      <% uiform.begin() %>
      <!-- Document dialog content is here -->
      <% uiform.end() %>

- View: see the sample here.

<myportal_path>/src/main/webapp/WEB-INF/conf/myportal/customized/document/view.gtmpl

    <style>
      <% _ctx.include(uicomponent.getTemplateSkin("exo:customizedDocument", "Stylesheet")); %>
    </style>
    <!-- Document view template content is here -->

- Stylesheet: see the sample here.

### Note

This document should contain ONLY the stylesheet for THIS template.

<myportal_path>/src/main/webapp/WEB-INF/conf/myportal/customized/document/stylesheet.css

    /* ... */

    .ACustomizedDocument {
      /* ... */
    }

    /* ... */

- You also need to import them to the database.

<myportal_path>/src/main/webapp/WEB-INF/conf/myportal/customized/document/template-configuration.xml

    <external-component-plugins>

      <target-component>org.exoplatform.services.cms.templates.TemplateService</target-component>

      <component-plugin>

        <name>addTemplates</name>

        <set-method>addTemplates</set-method>

        <type>org.exoplatform.services.cms.templates.impl.TemplatePlugin</type>

        <init-params>

          <value-param>

            <name>autoCreateInNewRepository</name>

            <value>true</value>

          </value-param>

          <value-param>

            <name>storedLocation</name>

            <value>war:/conf/myportal/customized/document</value>

          </value-param>

          <value-param>

            <name>repository</name>

            <value>repository</value>

          </value-param>

          <object-param>

            <name>template.configuration</name>

            <description>configuration for the localtion of nodetypes templates to inject in jcr</description>

            <object type="org.exoplatform.services.cms.templates.impl.TemplateConfig">

              <field name="nodeTypes">

                <collection type="java.util.ArrayList">

                  <value>

                    <object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$NodeType">

                      <field name="nodetypeName">

                        <string>exo:customizedDocument</string>

                      </field>

                      <field name="documentTemplate">

                        <boolean>true</boolean>

                      </field>

                      <field name="label">

                        <string>Customized Document</string>

                      </field>

                      <field name="referencedView">

                        <collection type="java.util.ArrayList">

                          <value>

                            <object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">

                              <field name="templateFile">

                                <string>view.gtmpl</string>

                              </field>

                              <field name="roles">

                                <string>*</string>

                              </field>

                            </object>

                          </value>

                        </collection>

                      </field>

                      <field name="referencedDialog">

                        <collection type="java.util.ArrayList">

                          <value>

                            <object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">

                              <field name="templateFile">

                                <string>dialog.gtmpl</string>

                              </field>

                              <field name="roles">

                                <string>webdesigner:/platform/web-contributors</string>

                              </field>

                            </object>

                          </value>

                        </collection>

                      </field>

                      <field name="referencedSkin">

                        <collection type="java.util.ArrayList">

                          <value>

                            <object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">

                              <field name="templateFile">

                                <string>stylesheet.css</string>

                              </field>

                              <field name="roles">

                                <string>*</string>

                              </field>

                            </object>

                          </value>

                        </collection>

                      </field>

                    </object>

                  </value>

                </collection>

              </field>

            </object>

          </object-param>

        </init-params>

      </component-plugin>

    </external-component-plugins>

Finally, you should create some initial contents and export them to XML files.

To import this XML into database, you can set up the deployment like this:

    <external-component-plugins>

      <target-component>org.exoplatform.services.wcm.deployment.WCMContentInitializerService</target-component>

      <component-plugin>

        <name>Content Initializer Service</name>

        <set-method>addPlugin</set-method>

        <type>org.exoplatform.services.wcm.deployment.plugins.XMLDeploymentPlugin</type>

        <description>XML Deployment Plugin</description>

        <init-params>

          <object-param>

            <name>ACME Logo data</name>

            <description>Deployment Descriptor</description>

            <object type="org.exoplatform.services.deployment.DeploymentDescriptor">

              <field name="target">

                <object type="org.exoplatform.services.deployment.DeploymentDescriptor$Target">

                  <field name="repository">

                    <string>repository</string>

                  </field>

                  <field name="workspace">

                    <string>collaboration</string>

                  </field>

                  <field name="nodePath">

                    <string>/sites content/live/acme/web contents/site artifacts</string>

                  </field>

                </object>

              </field>

              <field name="sourcePath">

                <string>war:/conf/wcm/artifacts/site-resources/acme/Logo.xml</string>

              </field>

            </object>

          </object-param>

        </init-params>

      </component-plugin>

    </external-component-plugins>

### 2.6.8. Best practices to customize a skin

The skin folder structure must be prepared once you start the design. Follow these conventions and best practices to ease the integration of your design in eXo Platform.

Name files and folders

The id and class names are defined after the WebUI components name and portlets name with the 'UI-' as prefix. The same rule is applied for folder that contains components and portlets. It will help you find and edit correct files easily. For example, the UI portlet will be named as UIFooterPortlet, or UIBannerPortlet and the UI component will be named as UIToolbarContainer, or UIVerticalTab.

Folder structure

Portal skins

The portal skin will appear as a single link to a CSS file. This link will contain contents from all the portal skin classes merged into one file. This enables the portal skin to be transferred more quickly as a single file instead of many smaller files included with every page render.

- The general folder structure for portal skin:

`/webapp/skin/NameOfPortalSkin/portal`

For example:

`/webapp/skin/DefaultSkin/portal`

- The main entry CSS file:

The main entry CSS file should be placed right in the main portal skin folder. The file is the main entry point to the CSS class definitions for the skin:

`/webapp/skin/NameOfPortalSkin/Stylesheet.css`

For example:

`/webapp/skin/SkinBlue/Stylesheet.css`

- The folder structure for WebUI components:

`/webapp/skin/SkinBlue/webui/component/YourUIComponentName`

For example:

`/webapp/skin/SkinBlue/webui/component/UIToolbarContainer`

- Window decorator CSS is put in:

`webapp/skin/PortletThemes/Stylesheet.css`

- Where to put images for portal skin?

The images for portal skin should be put in the background folder right in the Portal skin folder and for each UI component.

For example:

`/webapp/skin/SkinBlue/webui/component/UIProfileUser/SkinBlue/background`

In summary, the folder structure for a new portal skin should be:

    webapp
    |- skin
    |--- NameOfPortalSkin
    |----- stylesheet.css
    |------- webui
    |---------- component
    |------------ UIComponentName
    |--------------- NameOfPortalSkin.css
    |--------------- NameOfPortalSkin
    |------------------ background

Portlet skin

Each portlet on a page may contribute its own style. The link to the portlet skin will only appear on the page if that portlet is loaded on the current page. A page may contain many portlet skin CSS links or none. The link ID will be named like {portletAppName}{PortletName}. For example, ContentPortlet in content.war will have the id="contentContentPortlet".

General folder structure for portlet skin: /webapp/skin/portlet/webui/component/YourUIPortletName

and for the Groovy skin: /webapp/groovy/portlet/webui/component/YourUIPortletName/

For example:

- /webapp/skin/portlet/webui/component/UIBannerPortlet

- /webapp/groovy/portlet/webui/component/UIBannerPortlet

Portlet images folder: /webapp/skin/portlet/YourUIPortletName/PortalSkinName/background

For example:

- /webapp/skin/portlet/UIBannerPortlet/BlueSkin/background

Portlet themes

Main entry CSS:

- /webapp/skin/PortletThemes/Stylesheet.css

- /webapp/skin/PortletThemes/background

- /webapp/skin/PortletThemes/icons

## 2.7. Add JavaScript to your portal

This can be done entirely within your extension by customizing the gatein-resources.xml configuration.

To add a JavaScript library, for example jQuery, create the war:/WEB-INF/gatein-resources.xml_ file.

    <javascript>

      <param>

        <js-module>jQuery</js-module>

        <js-path>/javascript/jQuery.js</js-path>

        <js-priority>0</js-priority>

      </param>

    </javascript>

In which:

- <js-module> is the namespace of your JavaScript.

- <js-path> is the path to your JavaScript file.

- <js-priority> is an optional tag. This tag is used to indicate the loading order of JavaScript files across all eXo Platform. Its value is of the integer type. If its value is not negative (>=0), the loading priority is sorted by the descending order. If its value is negative (<0), the loading priority of the JavaScript file depends on the loading order of the web app (.war file) containing the JavaScript file.

## 2.8. Create custom templates for pages

eXo Platform 3.5 provides you with some built-in templates when you create a new page via Page Creation Wizard. In this section, you will learn how to create a custom page template for Page Creation Wizard.

You should use the extension to add the page layout configuration. In this guide, you are going to work with the /examples/extension project.

Create a custom page template

1. Add your sample template "FourRowsLayout" by overriding the PageConfigOptions.groovy file (portal.war).

Add it to this path: /examples/extension/war/src/main/webapp/WEB-INF/conf/uiconf/portal/webui/page/PageConfigOptions.groovy

Sample code:

    ...

    SelectItemCategory samplePageConfigs = new SelectItemCategory("samplePageConfigs"):

    categories.add(samplePageConfigs):

    samplePageConfigs.addSelectItemOption(new SelectItemOption("samplePage.FourRowsLayout","four-rows","FourRowsLayout:"));

    ...

2. Add your template file into the /examples/extension/war/src/main/webapp/WEB-INF/conf/portal/template/pages/four-rows/page.xml file.

Sample code:

    <page
    xmlns:xsi="http://www.w3.org.2001/XMLSchema-instance"
    xsi:schemaLocation="httlp://www.gatein.org/xml/ns/gatein_object_1_2.xsd http://gatein.org/xml/ns/gatein_object_1_2.xsd"
    xmlns:"http://gatein.org/xml/ns/gatein_object_1_2.xsd">
    <name></name>
    <container template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
    <access-permission>Everyone<access-permission>
    </container>

    <container template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
    <access-permission>Everyone<access-permission>
    </container>

    <container template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
    <access-permission>Everyone<access-permission>
    </container>

    <container template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
    <access-permission>Everyone<access-permission>
    </container>
    </page>

You can refer to the default template of eXo Platform in this path: /web/portal/src/main/webapp/WEB-INF/conf/portal/template/pages

3. Add the stylesheet to make the template preview image.

Add your own stylesheet in your extension webapp:

    .UIItemSelector .<FourRowsLayout>{
     width: 270px; height: 170px;
     margin: auto;
     background: url('background/ItemSelector.gif') no-repeat left -1700px;
    }

You can refer to the eXo Platform 3.5's default stylesheet in this path: /web/eXoResources/src/main/webapp/skin/DefaultSkin/webui/component/UISelector/UIItemSelector/Stylesheet.css

4. Deploy your extension project. You will see the template and its preview image in the Page Creation Wizard.

Copyright © 2009-2012. All rights reserved. eXo Platform SAS