Advanced

Advanced topics

Understanding the Layout Manager

This document provides information about how to control the PageSeeder user interface (UI) by editing the Layout Manager Configuration file (Layout Manager Config 1.4).

The Layout Manager is a project level option which means that all Groups in the Project have the same user interface.

The Layout Manager controls the different interface components, including the blocks and pages.

Warning!

Updating the PageSeeder layout is not for the faint-hearted; it best left for experienced PageSeeder developers and specific use cases.

Overview

The configuration file is an XML file which is always validated when it is loaded. Therefore it must follow the rules of the corresponding DTD file. The main rules are here:

  • The root element is <layout-config> plus a @version attribute.
  • The children elements are:

    • <content-security-policy> – to specify a Content Security Policy 
    • <navigation> – which describe the tabs at the top of the page
    • <blocks>, <dialogs>, <pages> – which describe the rest of the interface components.

Following is a dummy configuration file that illustrates the basic logic of the Layout Manager:

<layout-config version="1.4">
   <content-security-policy>
    ...
   </content-security-policy>
   <navigation>
    ...
   </navigation>
   <blocks>
    ...
   </blocks>
   <dialogs> 
    ... 
   </dialogs>
   <pages>
    ...
   </pages
</layout-config>

Note: Before making any changes to config.xml, please read the Developer Guidelines for customizing the user interface.

Content Security Policy

The layout manager can automatically include the Content-Security-Policy HTTP header to all pages based on your configuration.

Content Security Policy (CSP) helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement or distribution of malware.

By default, PageSeeder defines a very tight security policy, that excludes any content sourced from other sites.

  <content-security-policy>
    <directive name="default-src" value="'self'"/>
    <directive name="script-src"  value="'self' 'unsafe-inline' 'unsafe-eval'"/>
    <directive name="style-src"   value="'self' 'unsafe-inline'"/>
    <directive name="object-src"  value="'none'"/>
    <directive name="img-src"     value="'self' data:"/>
  </content-security-policy>

<content-security-policy> element

The <content-security-policy> element is a container for a list of <directive> elements.

<directive> element

The <directive> element defines the directives to include in the security policy. It supports the following attributes.

@nameThe name of the security policy directive (e.g. "default-src", "img-src", etc...)
@valueThe value for that directive

For example:

<content-security-policy>
  <directive name="default-src" value="'self'"/>
  <directive name="img-src" value="*"/>
  <directive name="media-src" value="media.example.org asset.example.net"/>
  <directive name="script-src" value="cdn.example.com"/>
</content-security-policy>

Would automatically send the following header:

Content-Security-Policy: default-src 'self'; 
                         img-src *; 
                         media-src media.example.org asset.example.net;
                         script-src cdn.example.com

(extra space added to improve readability)

For more details, see

Navigation

The navigation element contains a list of <menu> elements that each contain a list of <link> elements.

<menu> element

Each menu supports the following attributes:

@behaviourThis optional attribute specifies how the menu should redefine an existing menu (i.e. matching the same name). The attribute value "override" (default) will ignore the original menu while the value "inherit" will inherit the links from the original menu and append the new ones.
@nameA unique name for reference, when specified, this attribute acts like an ID for the menu in place of the title.
@permissionThis optional attribute defines the permission that the current user must have in order for the menu to be displayed.
@roleThis optional attribute can be used by the layout to customize the display of this menu.
@scopeDefines in which contexts this menu should be displayed. The value is a comma-separated list of any combination of the values "document""group", "project", "server".
@titleThe title of the menu that appears on the user interface. This attribute is required.

<link> elements

Menus contain links which are defined by link elements. <link> elements are empty elements and support the following attributes

@alsoA list of page IDs other than @idref that should make this link appear active.
@idrefThe ID of the page to go to when the link is clicked. It must point to a valid page ID. When the user is visiting that page this will be used to make this link appear active.
@nameA unique name for reference. When specified, this attribute acts like an ID for the link in place of the title.
@optionalAn optional boolean attribute ("true" or "false") which describes whether this link should be visible at all times or not. If the value is set to "true", the link will only be visible when the page matched with the @id attribute is the current page. Also, there is no link on an optional link. The default value is "false" (display all the time).
@permissionThis optional attribute defines the permission that the current user must have in order for the link to be displayed
@roleThis optional attribute can be used by the layout to customize the display of this menu.
@scopeDefines in which contexts this link should be displayed. The value is a comma-separated list of any combination of the values "document""group", "project", "server".
@titleThe title of the link appears in the user interface. This attribute is required.

Here are some examples of menus:

<menu title="Home">
  <link title="My Home" default="true" idref="home" />
  <link title="Group Home" scope="group,project" idref="group-home" />
  <link title="Search" scope="group,project" idref="group-search" optional="true" />
</menu>
<menu title="Comments" scope="group">
  <link title="New" idref="group-comment-new" />
  <link title="List" idref="group-comments" default="true" />
  <link title="View" idref="group-comment-thread" optional="true" />
</menu>

Interface components

A PageSeeder interface component can be a block, a dialog or a page. All three components have similar definitions.

Shared attributes

@idAn identifier for the component
@methodRestricts this component to an HTTP method GET or POST. (default is "get post")
@permissionOnly display if the specified permission is true (e.g. edit-group).
@scopeDefines in which contexts this component can be displayed. The value is a comma-separated list of any combination of the values "document""group""project""server".
@sharedThe name of the shared script or css when the same components use the same set of styles (e.g. block-account).
@style-idThe ID of another page that this component should use for its XSLT and CSS.
@titleThe title of component.

Shared elements

All user interface component can specify the following elements

  • <url> – the URL to access the UI component. There could be more than one url element in a component (and there is at least one).
  • <servlet> – there can be zero, one or multiple servlets for each component. They indicate servlets to invoke in order to produce content that is not included in the generic properties. The servlets are invoked in order.
  • <generator> – there can be none, one or multiple generators for each component. They indicate generators to invoke in order to produce content that is not included in the generic properties. The generators are invoked in order.
  • <script> – an optional element, it describes a Javascript file which should be imported when loading the page.

<url> element

This element defines which URL match the parent UI component and contains the following attributes.

@pattern

A required attribute indicating the part of the path information that is used by the engine to map this URL to a component.

This path can be an exact path (i.e.: "/document/browse") or a pattern (i.e.: "/labels{;days-ago}/{label}").

If the path is a pattern, curly brackets {...} are used to reference a variable to load from the URL, this variable can be retrieved using the '#' character in the parameter value (see below).

The wildcard character '*' is accepted but its use is discouraged whenever a pattern variable can be used instead.

@scope

An optional attribute to further qualify the scope of the component, the scope of the URL is used when the @pattern attribute is a pattern to match and it specifies the scope of the dynamic part of the path (what is matched by the '*' in the pattern).

The only value currently allowed is "group" and it is used when the dynamic part is group specific (i.e.: a file path located in the current group).

Here are examples of url elements:

<url pattern="/document/publish" />
<url pattern="/fullpath/*" />
<url pattern="/path/{+path}" scope="group" />
<url pattern="/labels{;days-ago}/{label}" />

<servlet> element

This element is used to specify a Java Servlet to invoke. The resulting data is then transformed to display the content. It can have the following attributes.

@classThe Java class name for the Servlet. This attribute is required.
@tunnelA boolean ("true" or "false" are allowed) optional ("false" is the default value) attribute used to specify that all the parameters of the main URL are to be forwarded to the Servlet URL.

A <servlet> element can have zero or several children parameter elements.

<generator> element

This element is used to specify a PageSeeder generator to invoke. The resulting data is then transformed to display the content. It can have the following attributes.

@classThe Java class name for the generator. This attribute is required.
@tunnelA boolean ("true" or "false" are allowed) optional ("false" is the default value) attribute used to specify that all the parameters of the main URL are to be forwarded to the generator.

<generator> element can have zero or several children parameter elements.

<parameter> element

This element is used to specify a parameter to transmit to a servlet or generator. It can have the following attributes.

@nameThe name of the parameter (required).
@value

The value of the parameter. This value can be dynamic, it uses the following conventions:

  • {...} (curly brackets) indicate that the value is dynamically constructed
    • @ prefixes the name of the config property which value is used
    • $ prefixes the name of an HTTP parameter which value is used
    • # prefixes the name of the url pattern match in the url which value is used
  • any other value is considered static and transmitted 'as is' to the servlet.
@defaultA fallback value in case the dynamic value is empty (optional).

Here are a few examples of parameters:

<parameter name="xformat"     value="xml" />
<parameter name="groupName"   value="" />
<parameter name="ps-docPath"  value="{@uri.docpath}"/>
<parameter name="history"     value="{$history}"  default="all"/>
<parameter name="days-ago"    value="{#days-ago}" />

<script> element

This very simple element is used to define a Javascript file used by the component on top of the default scripts for the component.

It contains only one attribute called @src which should contain the name of the script.

The default style file must be located in the script folder:

webapp/weborganic/layout/script/

and the custom style must be in:

webapp/woconfig/[style]/script

Example:

<script src="document_view.js"/>

 

Blocks

Blocks are user interface components that are designed to be included in a page and cannot be displayed on their own.

<block> element

See the following examples:

<block id="document-search-box" scope="group" title="Document search">
  <url pattern="/document/search/box"/>
  <script src="document_search_box.js"/>
</block>

<block id="group-members" scope="project,group,document" title="Members">
  <url pattern="/member/list"/>
  <generator class="com.pageseeder.membership.ListMembersForGroup" />
</block>

<block id="block-404" title="Not found!">
  <url pattern="/404"/>
</block>

<block-set> element

When the same blocks are displayed consistently on pages, it is possible to group them in a <block-set> which can be referenced in the page, instead of referencing each block individually.

A <block-set> is simply a container for a set of <block-ref> elements:

<block-set id="default-set"
  <block idref="group-members"/>
  <block idref="labels">
</block-set>

Dialog

A dialog is similar to a Page except that it is design to be displayed as a standalone component in a dialog or modal window.

Dialogs are therefore devoid of blocks or navigation components.

<dialog id="dialog-about" title="About PageSeeder" scope="server">
  <url pattern="/about"/>
  <generator class="com.pageseeder.system.About" />
  <generator class="com.pageseeder.publish.About" />
  <generator class="com.pageseeder.search.About" />
</dialog>

Pages

A page will include one or more Blocks using <block-ref> and <blockset-ref> elements. 

As many <block-ref> elements as required are used to specify the Blocks to include on the Page, however it is easier to manage this by creating, then referencing a blockset using <blockset-ref>.

There is only one attribute on a <block-ref> or <blockset-ref> element and it is required: @idref. It refers to the id of an existing block or block set in the Configuration file (@idref attribute).

Example a page listing the comments on a group:

<page id="comments" scope="server" title="Comments" style-id="group-comments">
  <url pattern="/comments"/>
  <generator class="com.pageseeder.comment.GetDiscussions">
    <parameter name="pagesize"       value="{$pagesize}" default="10" />
    <parameter name="page"           value="{$page}" />
    <parameter name="comments"       value="last" />
    <parameter name="returngroups"   value="user"/>
  </generator>
  <script src="lib/jquery.autosize.min.js"/>
  <script src="jquery.psfield.js"/>
  <blockset-ref idref="basic-server-set"/>
</page>

Example of an error page:

<page id="page-404">
  <url pattern="/404"/>
</page>

Created on , last edited on