IBM Support

How to perform basic Rational Portfolio Manager TeamMember Layout customizations

Question & Answer


Question

How do you modify existing IBM Rational Portfolio Manager TeamMember web user interface layouts, or, create new ones based on the default layouts?

Cause

While TeamMember is capable of handling multiple layouts, it, as of Release 7.1, does not include a layout editor, nor does it share those created with the rich client. TeamMember Applications: Timesheet, Scheduled Work, Scope Elements and Documents have a grid/table view with a layout selector control. In addition, these applications, as well as, Personal Record also have a properties pane with a layout selector control.

Answer

Objective

In lieu of a proprietary layout editor, Rational Portfolio Manager administrators can create their own layouts with the text, or, XML editor of their choice. This technote will cover the basics of layout customization. Subsequent ones will address modifying labels and the more complex issues of adding Custom Fields and creating Rational Portfolio Manager Security Role specific layouts.

You'll Learn How to:

  1. Prepare the absolute basic development environment
  2. Map TeamMember application layouts to Rational Portfolio Manager Objects
  3. Re-order Properties Pane tabs
  4. Re-order Properties Pane tabbed fields
  5. Re-order Grid columns
  6. Copy Property Pane tabbed fields into new Grid columns
  7. Productionize, or, copy your changes to another server

Prerequisites

  1. Basic knowledge of Rational Portfolio Manager usage and administration is required.
  2. Basic knowledge of web application administration is required.
  3. Knowledge of web application development is helpful but not required.
  4. Knowledge of Extensible Markup Language (XML) is helpful but not required.
  5. Development environment: (See Related Information below)
    1. You need to have Rational Portfolio Manager deployed - preferably in a test environment
    2. While a simple text editor and access to the application server's file system is all you need, a development environment with source change management is preferable, such as eclipse, or, Rational Application Developer and Rational ClearCase.
    3. For the sole purpose of demonstration, I'll use Notepad and Apache Tomcat on my local machine.
  6. You must maintain a backup of the original layout folder packaged under the web application's ...\rpm-middleware\WEB-INF\classes folder.

Limitations

  1. Please note that any modifications, or, additions to the layouts may have a lifespan limited to the current layout engine. Going forward, Rational Portfolio Manager may not support layout customization backward compatibility, or, migration.
  2. In order to preserve your changes during the current layout engine lifespan and subsequent Rational Portfolio Manager package updates, you should Save As... you changes to another file, thereby leaving Default Layout in its original state.
  3. While Rational Portfolio Manager Customer Support will offer their best-effort to support any layout customizations, they may require you to revert back to the out-of-the-box layouts (see Prerequisite #5) for problem resolution.
  4. Not all Property Pane tabbed fields can be copied into Grids. Unpredictable results may occur when adding:
    1. Fields with unlimited content. For example: Documents.
    2. Unsupported field types that will break the grid. For example: RTF fields.
    3. Fields from related objects. This will have a negative impact on performance. For example: Time Codes.

Duration

Assuming you have the prerequisite environment setup, each of the subsequent steps should take approximately 10-30 minutes to complete.

Step-By-Step Instructions

  1. Prepare the absolute basic development environment
    1. Backup: I'll be using a development machine with Rational Portfolio Manager Release 7.1 installed with Tomcat , so my layouts are contained in the folder is: C:\Program Files\Apache Software Foundation\Tomcat 5.5\webapps\rpm-middleware\WEB-INF\classes. Make a backup copy of this directory & store it somewhere on your file system that will not get overwritten by subsequent installations. For example: C:\Documents and Settings\milstein\My Documents\My Layouts Customizations\backup .
    2. Test Development Environment: Ensure your Tomcat server is running (as seen below)

      and you're able to access the layouts you want to customize. For example: Personal Record / Employee Information tab below:
    3. Sign out
  2. Map TeamMember application layouts to Rational Portfolio Manager Objects
    1. The TeamMember web user interface is a collections of applications, such as, Timesheet, Scheduled Work, Scope Elements, Documents and Personal Record. Each of these application, with the exception of Personal Record, contain a Grid and a Properties Pane view. The application's grid presents a list of multiple Rational Portfolio Manager Object types. Once a grid's row is selected, then the properties pane is populated based upon the selected row's Rational Portfolio Manager Object type's associated layout. These objects can also have multiple layouts.
    2. In the layouts folder referred to in Step 1.1 - ...\rpm-middleware\WEB-INF\classes, open the default.xml file.
    3. This is the one file that controls the relationships between applications, grids, properties, layouts and Rational Portfolio Manager Objects. The following is a crosstab of the file:

      The bold indicate the changes we're going to make in this article to Personal Record and Scope Elements.
    4. Grids contain fields that are common among their associated Rational Portfolio Manager Objects' Properties Panes. Unexpected results may occur by breaking this pattern.
    5. If you plan on copying fields from Properties Panes to their Grid, please ensure you copy them to their respective tag - if available. Step 6. Copy Property Pane tabbed fields into new Grid columns, actually copies a new tag into the Grid.
    6. Many related object fields, such as, Time Codes, were specifically omitted from the Grid to their negative impact on performance.
  3. Re-order Properties Pane tabs
    1. Properties Pane Modifications: Move Address tab after Employee Information tab.
      1. In the layouts folder referred to in Step 1.1 - ...\rpm-middleware\WEB-INF\classes, open PersonalRecord_PPane.xml with Notepad.

      2. Find Address and notice the mapping between the browser and the XML file. <container> tags have an attribute ui = "PropertiesPage" - which are the properties pane tabs. The order of these tabs depends on the <container>'s zero-based position attribute. In the case of Postal Address the position is 3 and Identification is zero.

        Note: What's important here is the value of the position attribute and not it's placement in the file. Also, please note that the values do not have to be contiguous. So values 10,20, 21, 100001 will yield the same results as 1, 2, 3, 4.
      3. Save the file as a new name. For example: PersonalRecord_PPane_MyLayout.xml
      4. Make the following changes to your new layout file:
      5. Container id
        position Value Before
        position Value After
        PersonalRecord_Address_0
        3
        2
        PersonalRecord_Rates_0
        2
        3
      6. When you're done, the file should resemble the one attached below.
      7. Save your changes (You don't have to close it because we'll need it later on.)
    2. Layout Selector Options Modifications: Add new layout to drop-down options.
      1. In the layouts folder referred to in Step 1.1 - ...\rpm-middleware\WEB-INF\classes, make a backup copy of the file default.xml. For example: default_original71.xml
      2. Open default.xml in Notepad. This is the directory that associates all of the layouts with their respective Rational Portfolio Manager objects, so please modify carefully.
      3. Find the PersonalRecord_PPane.xml layout tag and note how it's within the PersonalRecord tag. Now add your new layout & assign it to be the default layout as in bold
          1. Note: In Rational Portfolio Manager 7.1.0.1, the labelId attribute in bold

            <PersonalRecord>
            <Layout name="Default Layout"
             
            labelId="layout_common_defaultLayout"
             file="PersonalRecord_PPane.xml" default="true" />
            </PersonalRecord>


            was added for Globalization purposes. If the content is a key in the current dictionary (to be discussed further in subsequent articles, the dictionary content will be displayed. If not, the labelId attribute value is displayed.
          2. Before (7.1)

              <PersonalRecord>

                   <Layout name = "Default Layout" file = "PersonalRecord_PPane.xml" default = "false"/>
               </PersonalRecord>
            After (7.1)

               <PersonalRecord>

                    <Layout name = "Default Layout" file = "PersonalRecord_PPane.xml" default = "false"/>
                    <Layout name = "My Layout" file = "PersonalRecord_PPane_MyLayout.xml" default = "true"/>
                </PersonalRecord>
      4. When you're done, the file should resemble the one attached below
      5. Save and close the file
    3. Test
      1. Restart your application server
      2. Sign into TeamMember. If you browser is cookie enabled then you should return to the Personal Record application. Otherwise, select it.
      3. If everything works according to plan then you should see:
        1. My Layout as the new default layout option in the selector
        2. The tabs in the following order:
          1. Identification
          2. Employee Information
          3. Postal address
          4. Rates
          5. Documents
      4. Sign out
  4. Re-order Properties Pane tabbed fields
    1. Properties Pane Modifications: Move Full name and Nick name after Family name.
      1. Return to your Notepad with PersonalRecord_PPane_MyLayout.xml open
      2. Find fullname and nickName in the Identification tab's container and notice the mapping between the browser and the XML file. Each of these tags is a field in the properties pane tab. The order of these fields depends on their respective tag's zero-based position attribute. In the case of fullname and nickName their positions are 11 and 12 respectively.
      3. We want to position Full name and Nick name right after Family Name so let's make the following bold changes to your layout file:
        Note: It's not important to have contiguous index range values - just the sequence. Therefore, the values 1, 100, and 1000 have the same effect as 1, 2 and 3.
      4. tag
        position Value Before
        position Value After
        userName
        0
        0
        givenName
        1
        1
        middleName
        2
        2
        familyName
        3
        3
        active
        4
        6
        emailAddress
        5
        7
        effectiveStartDate
        6
        8
        discontinueDate
        7
        9
        password
        8
        10
        securityGroup
        9
        11
        calendar
        10
        12
        fullName
        11
        4
        nickName
        12
        5
        executiveSecurityRole
        13
        13
        externalID
        14
        14
      5. When you're done, the file should resemble the figure below
      6. Save your changes & close the file
    2. Test:
      1. Restart your application server
      2. Sign into TeamMember. If you browser is cookie enabled then you should return to the Personal Record application. Otherwise, select it.
      3. If everything works according to plan then you should see the fields in the following order:
        1. User name
        2. Given name
        3. Middle name
        4. Family name
        5. Full name
        6. Nick name
        7. Active
        8. E-mail address
        9. Effective start date
        10. Discontinue date
        11. Security role
        12. Calendar
        13. Exec access level
        14. External Identifier
  5. Re-order Grid columns
    1. Properties Pane Modifications: Move Scope Element Initiative band and Name header before Client band and Name header.
      1. Sign into TeamMember and select Scope Elements
      2. In the layouts folder referred to in Step 1.1 - ...\rpm-middleware\WEB-INF\classes, open the file ScopeManagement_Grid.xml with Notepad.
      3. Find Client and notice the mapping between the browser and the XML file. <container> tags have an attribute ui = "Band" - which are the grid column's first header. The order of these bands depend on the <container>'s zero-based position attribute. In the case of Client, the position is 1 and Initiative is 2.
      4. Save the file as a new name. For example: ScopeManagement_Grid_MyLayout.xml
      5. Make the following bold changes to your new layout file:When you're done, the file should resemble the one attached.
      6. Container id
        position Value Before
        position Value After
        ScopeManagement_Client_0
        1
        2
        ScopeManagement_Initiative_0
        2
        1
      7. Save your changes (You don't have to close it because we'll need it later on.)
    2. Layout Selector Options Modifications: Add new layout to drop-down options.
      1. Reminder: In the layouts folder referred to in Step 1.1 - ...\rpm-middleware\WEB-INF\classes, make a backup copy of the file default.xml . For example: default_original71.xml
      2. Open default.xml in Notepad.
      3. Find the ScopeManagement_Grid.xml layout tag and note how it's within the ScopeManagement tag. Now add your new layout & assign it to be the default layout as in bold
      4. Before

           <ScopeManagement>

                <Layout name = "Default Layout" file = "ScopeManagement_Grid.xml" default = "true"/>
            </ScopeManagement>
        After

           <ScopeManagement>

                <Layout name = "Default Layout" file = "ScopeManagement_Grid.xml" default = "false"/>
                <Layout name = "My Layout" file = "ScopeManagement_Grid_MyLayout.xml" default = "true"/>
            </ScopeManagement>
      5. When you're done, the file should resemble the one attached below
      6. Save and close the file
    3. Test
      1. Restart your application server
      2. Sign into TeamMember. If you browser is cookie enabled then you should return to the Personal Record application. Otherwise, select it.
      3. If everything works according to plan then you should see:
        1. My Layout as the new default layout option in the selector
        2. The Band/Column headers in the following order:
          1. Initiative/Name
          2. Client/Name
    4. Sign out
  6. Copy Property Pane tabbed fields into new Grid columns
    1. Grid Modification: Copy Service Request Properties Pane tabbed fields Rank and Priority to new Grid Layout:
      1. Sign back into TeamMember, select Scope Elements, restore the Properties Pane and select a Service Request in the grid. Note that it doesn't have to be a Service Request. Any Scope Element should have Rank and Priority. Its just that all Property Panes' layouts are based on specific types, such as, Service Request, Defect, etc.
      2. In the layouts folder referred to in Step 1.1 - ...\rpm-middleware\WEB-INF\classes, open the file ScopeManagement_PPane_ServiceRequest.xml with Notepad.
      3. Find rank and priority fields and notice the mapping between the browser and the XML file.
      4. Now note the tab's id and label Id
         <container id = "Scope_Identification_0" ui = "PropertiesPage" position = "0" labelId = "layout_scopeelements_ppane_identification">
        We're going to need those for the new column's banner below.
      5. Return to your Notepad with ScopeManagement_Grid_MyLayout.xml open
      6. Find Initiative. Now let's insert a new banner/header before Initiative/Name and reorder the other columns by making the following changes bold:
      7. Before

        ...

        <container id="ScopeManagement_Client_0" ui="Band" position="2" labelId="layout_scope_grid_client">


          <RpmObjects>
            <AbstractAggregateScope>
              <clientCostCenter type="ClientCostCenter">
                <name type="String" position="0" ui="TreePicker" mandatory="false" labelId="layout_scope_grid_client_name"/>
              </clientCostCenter>
            </AbstractAggregateScope>
          </RpmObjects>
        </container>
        <!- New columns goes here (This line is here for demonstration purposes. Comment tags will break the parsing engine!!)>  <container id="ScopeManagement_Initiative_0" ui="Band" position="1" labelId="layout_scope_grid_initiative">
          <RpmObjects>
            <ScopeElement>
              <project type="GenericProject">
                <name type="String" position="0" ui="Text" mandatory="false" labelId="layout_scope_grid_initiative_name"/>
              </project>
            </ScopeElement>
          </RpmObjects>
        </container>
        <container id="ScopeManagement_Version_0" ui="Band" position="3" labelId="layout_scope_grid_version">
        ...
        After

        ...

        <container id="ScopeManagement_Client_0" ui="Band" position="3" labelId="layout_scope_grid_client">


          <RpmObjects>
            <AbstractAggregateScope>
              <clientCostCenter type="ClientCostCenter">
                <name type="String" position="0" ui="TreePicker" mandatory="false" labelId="layout_scope_grid_client_name"/>
              </clientCostCenter>
            </AbstractAggregateScope>
          </RpmObjects>
        </container>
        <container id="Scope_Identification_0" ui="Band" position="1" labelId="layout_scopeelements_ppane_identification">
        </container>
        <container id="ScopeManagement_Initiative_0" ui="Band" position="2" labelId="layout_scope_grid_initiative">
          <RpmObjects>
            <ScopeElement>
              <project type="GenericProject">
                <name type="String" position="0" ui="Text" mandatory="false" labelId="layout_scope_grid_initiative_name"/>
              </project>
            </ScopeElement>
          </RpmObjects>
        </container>
        <container id="ScopeManagement_Version_0" ui="Band" position="4" labelId="layout_scope_grid_version">
        ...
      8. Now go back to the ScopeManagement_PPane_ServiceRequest.xml and copy the tags and Rank and Priority fields in bold:
      9. ScopeManagement_PPane_ServiceRequest.xml

        ...

        <RpmObjects>
          <AbstractScope>
            <clientCostCenter type = "ClientCostCenter">
              <name type = "String" position = "5" ui = "TreePicker" mandatory = "false" labelId =      "layout_scopeelements_ppane_identification_clientname"/>
            </clientCostCenter>
            <rank type = "Integer" position = "1" ui = "Text" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_rank"/>
            <externalReferenceNumber type = "String" position = "4" ui = "Text" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_externalrefnum"/>
            <asset type = "Asset">
              <name type = "String" position = "6" ui = "TreePicker" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_assetname"/>
            </asset>
            <assetCode type = "AssetFinancialCategory">
              <value type = "String" position = "7" ui = "ComboBox" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_assetcode"/>
            </assetCode>
            <duplicateNumber type = "String" position = "10" ui = "Text" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_duplicatenumber"/>
            <targetDate type = "Calendar" position = "10" ui = "Calendar" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_targetdate"/>
            <state type = "DatafieldState">
              <value type = "String" position = "13" ui = "ComboBox" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_state"/>
            </state>
          </AbstractScope>
          <AbstractRequest>
            <occuredDateTime type = "Calendar" position = "8" ui = "Calendar" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_occurreddatetime"/>
            <numberTimesReassigned type = "Integer" position = "9" ui = "Text" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_numtimereassigned"/>
          </AbstractRequest>
          <AbstractAggregateScope>
            <priority type = "Integer" position = "2" ui = "Text" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_priority"/>
            <referenceNumber type = "String" position = "3" ui = "Text" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_refnum"/>
            <estimatedStartDate type = "Calendar" position = "11" ui = "Calendar" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_estimatestart"/>
            <estimatedFinishDate type = "Calendar" position = "12" ui = "Calendar" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_estimatefinish"/>
          </AbstractAggregateScope>
        ...
        </RpmObjects>
        ...
      10. Insert the copied tags and fields in between the newly inserted container tags in ScopeManagement_Grid_MyLayout.xml, as in the bold below:
      11. Before

        ...

        <container id="ScopeManagement_Client_0" ui="Band" position="3" labelId="layout_scope_grid_client">


          <RpmObjects>
            <AbstractAggregateScope>
              <clientCostCenter type="ClientCostCenter">
                <name type="String" position="0" ui="TreePicker" mandatory="false" labelId="layout_scope_grid_client_name"/>
              </clientCostCenter>
            </AbstractAggregateScope>
          </RpmObjects>
        </container>
        <container id="Scope_Identification_0" ui="Band" position="1" labelId="layout_scopeelements_ppane_identification">
        <!-  New fields go here  (This line is here for demonstration purposes. Comment tags will break the parsing engine!!) >
        </container>
        <container id="ScopeManagement_Initiative_0" ui="Band" position="2" labelId="layout_scope_grid_initiative">
          <RpmObjects>
            <ScopeElement>
              <project type="GenericProject">
                <name type="String" position="0" ui="Text" mandatory="false" labelId="layout_scope_grid_initiative_name"/>
              </project>
            </ScopeElement>
          </RpmObjects>
        </container>
        <container id="ScopeManagement_Version_0" ui="Band" position="4" labelId="layout_scope_grid_version">
        ...
        After

        ...

        <container id="ScopeManagement_Client_0" ui="Band" position="3" labelId="layout_scope_grid_client">


          <RpmObjects>
            <AbstractAggregateScope>
              <clientCostCenter type="ClientCostCenter">
                <name type="String" position="0" ui="TreePicker" mandatory="false" labelId="layout_scope_grid_client_name"/>
              </clientCostCenter>
            </AbstractAggregateScope>
          </RpmObjects>
        </container>
        <container id="Scope_Identification_0" ui="Band" position="1" labelId="layout_scopeelements_ppane_identification">
        <RpmObjects>
          <AbstractScope>
            <rank type = "Integer" position = "1" ui = "Text" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_rank"/>
          </AbstractScope>
          <AbstractAggregateScope>
            <priority type = "Integer" position = "2" ui = "Text" mandatory = "false" labelId = "layout_scopeelements_ppane_identification_priority"/>
          </AbstractAggregateScope>
        </RpmObjects>
        </container>
        <container id="ScopeManagement_Initiative_0" ui="Band" position="2" labelId="layout_scope_grid_initiative">
          <RpmObjects>
            <ScopeElement>
              <project type="GenericProject">
                <name type="String" position="0" ui="Text" mandatory="false" labelId="layout_scope_grid_initiative_name"/>
              </project>
            </ScopeElement>
          </RpmObjects>
        </container>
        <container id="ScopeManagement_Version_0" ui="Band" position="4" labelId="layout_scope_grid_version">
        ...
      12. Save your changes
    2. Test:
      1. Restart your application server
      2. Sign into TeamMember. If you browser is cookie enabled then you should return to the Scope Elements application. Otherwise, select it.
      3. If everything works according to plan then you should see the following:
    3. Labels: Close but no cigar. The problem is the field label IDs we used return the English label appended with a colon (":"). For the sake of completeness, I'll show you how to add the new labels we need but, this is only a temporary solution. The next How-To will explain how the multilingual labeling engine works, thereby enabling you to properly customize all your labels. For now lets, just take the easy way out.
    4. Grid Layout Modifications: Replace Property Pane Labels IDs with new Grid Label IDs.
      1. Return to your Notepad with ScopeManagement_Grid_MyLayout.xml open
      2. Replace _scopeelements_ppane_ with the actual labels of choice, as in bold below:
      3. labelId After
        labelId After
        layout_scopeelements_ppane_identification_rank Rank
        layout_scopeelements_ppane_identification_priority Priority
      4. Save your changes and close the file
    5. Test again
      1. Restart your application server
      2. Sign into TeamMember. If you browser is cookie enabled then you should return to the Scope Elements application. Otherwise, select it.
      3. If everything works according to plan then you should see the following:

  7. Productionize, or, copy your changes to another server
    1. Copy all the changed and new files to your target server
    2. Restart your target application server
    3. Test

Disclaimer

All source code and/or binaries attached to this document are referred to here as "the Program". IBM is not providing program services of any kind for the Program. IBM is providing the Program on an "AS IS" basis without warranty of any kind. IBM WILL NOT BE LIABLE FOR ANY ACTUAL, DIRECT, SPECIAL, INCIDENTAL, OR INDIRECT DAMAGES OR FOR ANY ECONOMIC CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), EVEN IF IBM, OR ITS RESELLER, HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.


RPMTeamMemberLayoutCustomizationPart1.zip

[{"Product":{"code":"SSRR2G","label":"Rational Portfolio Manager"},"Business Unit":{"code":"BU053","label":"Cloud & Data Platform"},"Component":"TeamMember: Installation and Configuration - Client","Platform":[{"code":"PF002","label":"AIX"},{"code":"PF010","label":"HP-UX"},{"code":"PF016","label":"Linux"},{"code":"PF027","label":"Solaris"},{"code":"PF033","label":"Windows"}],"Version":"7.1","Edition":"","Line of Business":{"code":"LOB45","label":"Automation"}}]

Document Information

Modified date:
16 June 2018

UID

swg21266644