uPortal Layout Ideas

These are just some loose thoughts on layout management.

fragments.xml

The fragments.xml file is used to publish fragments into the system.

  • There is no concept of priority, fragments are processed in the order in which they appear in this file. To change priority, reorder the file.
  • When fragments.xml is published, fragments that do not appear in the file are removed from the system, this is to prevent orphan fragments.
  • This <fragments> element can contain two types of children:
    • <fragment> - a fragment that is defined later
    • <include file="chemistry.xml"/> - includes the contents of the specified file

A user interface could be built to allow the manipulation of fragments. If this interface was created, it should support the ability to export the fragment configuration so that fragments.xml can be resynced with any changes made.

Sample fragments.xml
<fragments>
  <fragment fname="guest-layout" type="pushed">
    <name>Guest Layout</name>
    <description>Layout for guest users.</description>
    <owners>
      ...
    </owners>
    <rules>
      ...
    </rules>
    <layout>
      ...
    </layout>
  </fragment>

  <include file="chemistry-layouts.xml"/>
</fragments>

Fragment Types

I've identified five types of fragment behaviors I would like to see.

Pushed

Pushed fragments have their content put into a users layout if the rules of the fragment are satisfied. Users cannot change the content. Changes made to the fragment are reflect to the user.

Pulled

Pulled fragments are fragments that a user must subscribe to through some interface. Once subscribed, the contents of the fragment are displayed to the user. The user cannot change the content. Changes made to the fragment are reflected to the user.

Dynamic

If the rules of a dynamic fragment are satisfied, a Java class specified is called to generate the contents of the fragment. The scenario in mind for this was creating a list of subtabs based on worksites in Sakai that you belong to.

New User

This type of fragment is used for new users to the system. When a new users logs on, if a newuser fragment's rules are satisfied, the contents of the fragment are copied into the user's layout.

Template

Template fragments provide starting points for tabs similar to My Yahoo!. When a user chooses to add a tab based on "template" fragment, the contents of the fragment are copied into the user's layout to modify at will. Changes made to a template fragment have no affect if someone has already created a tab based on the fragment. Only when the rules are satisfied does this template become available to a user.

Fragment Owners

Each fragment should define a list of users and groups that can modify the fragment through an interface within the portal.

<owners>
  <user>joesmith1</user>
  <group>administrators</group>
</owners>

Fragment Rules

After seeing documentation on DLM's rules, I figured there had to be an easier way to specify when fragments are loaded into a user's layout. This mechanism is modeled after e-mail client rules, which people already use and understand. Below is a very simple rules example.

<rules>
  <rule type="exclude" conditions="any">
    <condition type="is-member-of-group">alumni</condition>
  </rule>
  <rule type="include" conditions="all">
    <condition type="is-member-of-group">faculty</condition>
    <condition type="is-not-member-of-group">student"</condition>
  </rule>
</rules>
  • Rules are processed in order
  • There are two types of rules: include and exclude
    • If the conditions for an include rule are met, the fragment is included in the user's layout
    • If the conditions for an exclude rule are met, the fragment is excluded from the user's layout
    • If the conditions of a rule are not met, the system moves to the next rule
    • If none of the rules are satisfied, the fragment is excluded from the user's layout
  • There are two values for the conditions attribute: any and all
    • "any" means that if any of the conditions are true, the entire rule is true
    • "all" means that for the rule to be true, all of the conditions must be true
  • Conditions have different attributes based on the type. Here are the condition types:
    • attribute - the contents of the element are compared to attribute name of the current user using the method:
      • contains
      • does-not-contain
      • begins-with
      • ends-with
      • exists
      • does-not-exist
      • is-equal-to
      • greater-than
      • less-than
      • greater-than-equal-to
      • less-than-equal-to
    • is-member-of-group - the user must be a member of the group specified
    • is-not-member-of-group - the user must not be a member of the group specified
    • before-date - the current date/time is before the date/time specified
    • after-date - the current date/time is after the date/time specified

Example Rules

<!-- Display this fragment to users with brown hair or a GPA higher than 2.0 as long as
     it is between January 1, 2005 and December 31, 2005. -->
<rules>
    <rule type="exclude" type="all">
        <condition type="before-date">2005-01-31</condition>
        <condition type="after-date">2005-12-31</condition>
    </rule>
    <rule type="include" type="any">
        <condition type="attribute" name="hair-color" method="equals">brown</condition>
        <condition type="attribute" name="gpa" method="greater-than">2.0</condition>
    </rule>
</rules>

Fragment Layouts

Within each fragment there is a <layout> element which holds the actual content for the layout. A sample layout looks like this:

<layout>
  <folder fname="tab-welcome">
    <property name="display-name"><value>Home</value></property>
    <property name="folder-type"><value>tab</value></property>
    <folder fname="column-side">
      <property name="folder-type"><value>column</value></property>
      <property name="column-width"><value>25%</value></property>
      <portlet fname="logon"/>
      <portlet fname="logon-help"/>
    </folder>
    <folder fname="column-side">
      <property name="folder-type"><value>column</value></property>
      <property name="column-width"><value>75%</value></property>
      <portlet fname="welcome-message"/>
    </folder>
  </folder>
</layout>
  • Each folder specifies an fname attribute. This fname is used to uniquely identify this folder within a path. For the example above, the logon portlet is in the path: /layout/tab-welcome/column-side
  • The <layout> element can contain <property> and <folder> elements.
  • <folder> elements can contain <folder>, <property>, and <portlet> elements.
  • <property> elements can contain <value> elements.
  • Folders can specify arbitrary properties that can have multiple values. A use for multiple values might be designating the allowed widths for portlets in a column. For example:
    <property name="allowed-channel-widths"><value>30%</value><value>45%</value></property>

Dynamic Fragments

The <layout> element for dynamic fragments specifies a source attributethat defines a Java class that is called to generate the contents for the element. Should the generation of contents fail for any reason, the contents of the <layout> specified in the fragments.xml are used.

fragments.xml
<fragment fname="sakai-groups" type="dynamic">
  <title>Sakai Groups</title>
  <description>Groups pulled from Sakai and turned into fragments.</description>
  <rules>
    <rule type="include" conditions="any">
      <condition type="is-member-of-group">everyone</condition>
    </rule>
  </rules>
  <layout source="org.jasig.portal.layout.SakaiLayoutGenerator"/>
</fragment>

Building User Layouts

Merging Fragments

I would like to see the fragments that are added to a user's layout merged together automatically rather than appended on to the end of the existing layout.

  • When a user logs on, they receive an empty <layout>
  • As fragments are processed, the <layout> of the fragments are merged with the user's <layout> one by one
  • Folders are merged based on their fname path: layout/tab-welcome/column-side
  • Folders with the same fname have their contents merged together with the existing contents taking priority.
  • Folders with an fname that doesn't exist in the <layout> are simply added
  • If folders being merged both define a property with the same name, the existing property takes priority and the new one is ignored
  • The user's layout is merged in last
  • When a user's folder is merged with an existing folder, the ID of the folder (which is generated by the system when the layout is built) is changed to that of the user's version. This way, any customization actions target the user's version of that folder.
Layout from fragment #1
<layout>
  <folder fname="tab-welcome">
    <property name="display-name"><value>Welcome</value></property>
    <folder fname="column-left">
      <portlet fname="logon"/>
    </folder>
  </folder>
</layout>
Layout from fragment #2
<layout>
  <folder fname="tab-welcome">
    <property name="display-name"><value>Log On</value></property>
    <folder fname="column-left">
      <property fname="column-width"><value>25%</value></property>
      <portlet fname="logon-help"/>
    </folder>
  </folder>
</layout>
Merged layouts from fragments 1 and 2
<layout>
  <folder fname="tab-welcome">
    <property name="display-name"><value>Welcome</value></property>
    <folder fname="column-left">
      <property fname="column-width"><value>25%</value></property>
      <portlet fname="logon"/>
      <portlet fname="logon-help"/>
    </folder>
  </folder>
</layout>

Requests from Institutions

UC Berkeley

UC Berkeley would like to be able to push fragments to different groups and allow users to remove/edit some channels, but not others. They would also like to be able to create editable pulled fragments, which users can select to receive only if they are interested in the subject matter. Finally, they would like to be able to ensure that if a pushed fragment changes, users receive any channels added or updated, but retain any other changes they've made to the fragment. It might be nice to have a setting that allows portal managers to decide whether they want to merge user changes into an updated fragment or not. And of course it will be necessary to have a UI that allows users to manage their fragments in a coherent manner.