Quantcast
Channel: Sasank's PeopleSoft Log
Viewing all 132 articles
Browse latest View live

PeopleTools 8.54+ - Branding - Part 4A - Customizing DEFAULT_THEME_TANGERINE_ALT Theme

$
0
0
If you have been following my previous posts on Branding PeopleTools 8.54+ applications (Part 1, Part 2, Part 3), then you would know that all my examples so far uses a delivered theme called DEFAULT_THEME_TANGERINE to perform customizations.

DEFAULT_THEME_TANGERINE as delivered:



There is no issue with using DEFAULT_THEME_TANGERINE. Whatever we learnt in my previous branding posts provides great value to understand how HTML, css and javascript work together and how the latest PeopleTools configuration helps with achieving branding requirements in a much more simplified fashion.

I have had several folks enquire about the DEFAULT_THEME_TANGERINE_ALT theme and how to customize it? Well, my answer is that it is exactly the same process as we did with the DEFAULT_THEME_TANGERINE theme.

DEFAULT_THEME_TANGERINE_ALT as delivered:



You will notice that the theme is more or less the same as DEFAULT_THEME_TANGERINE. The only additions are the 'Add To' (drop down), the 'Notification' icon and the 'NavBar' icon.

In general with the advent of more recent PUM Images (HCM 9.2 PUM 12) and the associate delivered FLUID pages, it appears that DEFAULT_THEME_TANGERINE_ALT might be a better theme to use particularly when we get to a stage where we are ready to roll out some of the delivered FLUID pages.

With that said, I would like to experiment with customizing the DEFAULT_THEME_TANGERINE_ALT theme in this post - titled PART 4A. The reason I titled this post as Part 4A is because initially I only intend to provide the basic details to get started with DEFAULT_THEME_TANGERINE_ALT. As time permits, I would follow up this post with a Part 4B which would cover much more detailed customizations (as we have seen in Part 1, Part 2 and Part 3).

Note: At the time of writing this post, I am using HCM 9.2 PUM Image 12 - PeopleTools 8.54.08.

Step 1: Clone DEFAULT_THEME_TANGERINE_ALT Theme

Navigation: Main Menu > PeopleTools > Portal > Branding > Assemble Themes

Select: DEFAULT_THEME_TANGERINE_ALT

Click on the 'Save As' Button and save the theme with a custom name (e.g.: CSK_THEME_TANGERINE_ALT).




Step 2: Clone DEFAULT_HEADER_TANGERINE_ALT Header Definition

Navigation: Main Menu > PeopleTools > Portal > Branding > Define Headers and Footers

Select: DEFAULT_HEADER_TANGERINE_ALT

Click on the 'Save As' Button and save the header with a custom name (e.g.: CSK_HEADER_TANGERINE_ALT).



Step 3: Update custom theme (Step 1) to reference custom header (Step 2)

Navigation: Main Menu > PeopleTools > Portal > Branding > Assemble Themes

Select: CSK_THEME_TANGERINE_ALT

Update Home Page Header to CSK_HEADER_TANGERINE_ALT.




Step 4: Upload Custom Branding Objects (Images, Style Sheets, etc)

Navigation: Main Menu > PeopleTools > Portal > Branding > Branding Objects

Upload Logo Image:




Upload Style Sheet:




Style Sheet for reference:


Step 5: Update the custom header definition

Navigation: Main Menu > PeopleTools > Portal > Branding > Define Headers and Footers

Select: CSK_HEADER_TANGERINE_ALT

Delete the 'pthdr2logoswan' leaf under the 'pthdr2container' folder.



Add a new leaf element under the 'pthdr2container' folder to reference the custom logo.







Step 6: Update Branding System Options to use Custom Theme and Style Sheet

Navigation: Main Menu > PeopleTools > Portal > Branding > Branding System Options

Update 'Default Branding Theme' to CSK_THEME_TANGERINE_ALT and add CSK_BRANDING_CSS under 'Addtional Style Sheet Objects'.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).


You can see that the logo has been updated to the custom image using the DEFAULT_THEME_TANGERINE_ALT theme.

Stay tuned for Part 4B - Customizing DEFAULT_THEME_TANGERINE_ALT Theme (continued) and Part 5 - Branding Fluid!

PeopleTools 8.54+ - Branding - Part 5A - Fluid Branding

$
0
0
PeopleTools 8.54 has been around for a while now and it is about time that we jump on the Fluid UI bandwagon as there are more and more delivered Fluid Components that are made available.

Before we get started though, we obviously need to review the Branding on the Fluid Pages to make sure that it is consistent with our organization's Branding theme and not referencing any Oracle delivered colors, images and styles.

This post is intended to provide high level guidelines to help with achieving a consistent Branding experience in Fluid Homepages and Fluid Content pages. I titled this post as Part 5A because I would like to follow up with a Part 5B if I missed anything right now.

At the time of writing this post, I am using HCM 9.2 PUM Image 12 (PeopleTools 8.54.08).

If you have been following my previous multi-part series on PeopleTools 8.54+ Branding (Part 1, Part 2, Part 3, Part 4A), then you would find that I most recently cloned the theme DEFAULT_THEME_TANGERINE_ALT as CSK_THEME_TANGERINE_ALT in a HCM 9.2 PUM Image 12 environment (refer Part 4A). This was to keep it consistent with the Fluid UI and also bring in additional features like the NavBar into the Classic Branding Header.

End result of using CSK_THEME_TANGERINE_ALT for the Classic Branding would appear as shown in the following screenshot.



We can see that the NavBar and other new icons are available on the Classic Branding Header. All is good - as of now! Enter Fluid UI!!!

Either click on the NavBar and select Fluid Home or navigate from Main Menu > Fluid Home.



OR



Fluid Homepage:



First thoughts? Dude where's my logo??? :)

Couple of key pieces of information that would help us with Fluid Branding:
  1. Classic Branding and Fluid Branding are completely different and mutually exclusive.
  2. Fluid Branding (unlike Classic Branding which uses frame-based HTML templates) is entirely within the content frame. Notice the URL for the Fluid Homepage http://pi012.hcm92.com:8000/psc/ps/EMPLOYEE/HRMS/c/NUI_FRAMEWORK.PT_LANDINGPAGE.GBL contains /psc/ instead of /psp/? Basically, the Fluid Branding is entirely self contained within the component that is currently displayed. In this case - Fluid Homepage - it is PT_LANDINGPAGE.GBL.
Very well! Let us move along and try to override the Oracle Logo on the Fluid Homepage.

Note: Since Fluid Branding is essentially at the component level, we might be switching back and forth between configuration and customizations (using App Designer). So dust off your "developer hats" as you might need them intermittently.

Disclaimer added on 06/10/2015:
  1. The customizations suggested in this post are merely provided as a proof of concept. The obvious approach would be to try to tackle the changes using CSS (in combination with javascript/jquery if necessary) to avoid customizations. The customizations detailed are only to provide an idea of where the images are referenced. If I find a good way to avoid customizations, I will include it in a future post. I am still researching and evaluating various options.
  2. Any theme (color/contrast/images/any other styling) changes suggested in this post (as well as my previous Branding articles) are again done as a proof of concept. Please be sure to work with your UX and/or Functional teams to make sure that user experience and accessibility requirements are met.



To update the logo for the Fluid Homepage Logo, we must first understand where it is coming from. We can see in the following screenshot that the image is getting generated as part of a page field PTNUI_LP_HEADER.PTNUI_LOGO (Component: PT_LANDINGPAGE, Page: PT_LANDINGPAGE).



Now that we know where the logo is coming from, we just need to update the page field properties to reference the appropriate custom image.

Speaking of images, you will notice that the delivered image that is used for the Fluid Homepage Logo is a SVG (Scalable Vector Graphics) image. This again is another great move by Oracle to adopt SVG images particularly for the responsive Fluid UI. I don't want to go into too much of the details of SVG images but as you start using them you will notice that you can very easily modify the images (by editing the XML of the SVG using a text editor) without having to use software/editors like PhotoShop.

That said, let us upload a custom image to replace the delivered logo for the Fluid Homepage. Note: I am using a SVG image for my Fluid Homepage logo. For best results and scaling it is highly recommended that we move towards using SVG images.

Navigation: Main Menu > PeopleTools > Portal > Branding > Branding Objects



You could also do this using App Designer but always a good idea to have these Branding Objects configurable online.

Now that we have the logo uploaded, let us open App Designer to update the image referenced and replace with the custom logo.

App Designer > File > Open > Page > Select: PTNUI_LP_HEADER



On PTNUI_LP_HEADER Page, open the Page Field PTNUI_LP_HEADER.PTNUI_LOGO and update the properties to appropriate custom values and 'Save' the page:
- Label Tab > Alt tag for image (Type and Text)
- Label Image > Image ID



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



We can see that the delivered logo on the Fluid Homepage is now replaced with the custom logo. Although we are making progress, the image does not look great due to the background color. Let us see how we can go about applying a few style sheet overrides to further customize the Fluid Branding.

Notes:
  1. I found that SVG images and their usage in Responsive Web Design (RWD) is a very interesting topic. There are plenty of online resources and content that provide a lot of information and opinions. Here is one of the many articles that I enjoyed reading: http://www.smashingmagazine.com/2014/03/05/rethinking-responsive-svg/
  2. I am sure some of you (just like me) might be wondering why we need to fall back to customizing objects in App Designer particularly with all the configurations that has helped us with Branding the Classic Homepage/UI? I gave this quite some thought. I was trying to see if there are easy options to override the image using CSS without too much overhead. I see some options of using Javascript or JQuery to perform these overrides but the question is "Is the juice worth the squeeze?". Right now, for the sake of simplicity and providing a proof of concept I decided to update the images using App Designer. In more complex use cases, we might need to dynamically change these images. For example, an environment with different themes for different user types such as Manager Self Service, Employer Self Service, etc. I plan to research this topic further and write a separate article on it if I find a good way to approach this requirement. If anyone has any suggestions then please feel free to leave a comment!

Getting ready to override Fluid Styles:

Before we go ahead and start applying custom style sheet overrides for Fluid UI/Branding, we need to do a few housekeeping tasks so that our custom style sheet(s) get injected while the Fluid Pages are rendered.

Step 1: Create Custom Style Sheet(s)

Navigation: Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Upload your style sheet(s) as appropriate. For now, I am just creating a place holder style sheet to first complete the housekeeping activities.





Step 2: Applying Custom Style Sheet as an Override for Fluid Components on the Theme Definition

Navigation: Main Menu > PeopleTools > Portal > Branding > Assemble Themes



In my case, I updated the theme CSK_THEME_TANGERINE_ALT because that is the "current" theme definition referenced in my Branding System Options. You can see that I assigned the new style CSK_FLUID_CSS as the Global Override Style Sheet (in the Fluid Components section). This configuration would inject the custom style sheet while rendering Fluid pages globally. We could also use the Theme Style Sheet Mapping at the node level but that would be an advanced topic which I don't intend to cover in this post (could be handy for interaction hub scenarios where there are multiple applications).

Now that we set the above configuration in place, we can add styles to the custom style sheet (CSK_FLUID_CSS) to override the delivered fluid styles.

Overriding the Fluid Header Bar Background Color:

Let us change the background color of the Fluid Header Bar by adding the following style class to CSK_FLUID_CSS.

/* Fluid Header Bar Background Color */
.ps_header-banner, .ps_header_bar {
  %BV(background-image:linear-gradient(rgb(240, 238, 80),rgb(219, 204, 47)));
}

Navigation:  Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Notes:

  1. %BV is a new Meta-HTML function delivered in PT 8.54 that would expand the generic style into a browser specific style and add the browser specific prefix to the CSS property value.Refer: PeopleBooks.
  2. linear-gradient is a CSS3 Gradient property that allows us to provide a smooth transition of two or more colors. This allows us to use css for background colors instead of using images. Refer: W3Schools.

Update Hover Over, Active Background Color for Home, Notification and Drop Down Menu Icons:

If you hover over the Home, Notification, Drop Down Menu icons on the right hand side of the header you will notice that the background color for those icons need to be modified for the Hover Over and Active events.

Let us add the following styles to CSK_FLUID_CSS to override the delivered style.

/* Fluid Header - Hover Over, Active Background Color for Icons (Home, Notification, Drop Down Menu) */
.ps_header_bar .ps_box-button:not(.psc_disabled) .ps-button:hover
{
  background-color: #F0EE50;
  %BP(box-shadow:none);
}
.ps_header_bar  .ps_box-button:not(.psc_disabled) .ps-button:active,
.ps_header_bar  .ps_box-button:not(.psc_disabled) .ps-button:hover:active
{
  background-color: #F0EE50;
  %BP(box-shadow:none);
}
.ps_header_bar .ps_box-button:not(.psc_disabled) .ps-button:hover
{
  background-color: #F0EE50;
  %BP(box-shadow:none);
}

Navigation:  Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



You can see how the hover over background color for the Home icon has changed to a more desirable custom color!

Notes:
  1. %BP similar to %BV is a new Meta-HTML function delivered in PT 8.54 that would expand the generic style into a browser specific style and add the browser specific prefix to the CSS property name.Refer: PeopleBooks.
  2.  box-shadow is a CSS3 property that attaches one or more shadows to an element. Refer: W3Schools.

Update NavBar Icon Background and Hover Over Background Color:

We can see that the NavBar icon is still using a different background color. Let us add some styles to CSK_FLUID_CSS to override the delivered styles.

/* Fluid Header - NavBar Background Color */
.ps_header_bar .ps_actions_cont .ps_system_cont .ps_header-navbar .ps-button {
  %BV(background-image:linear-gradient(rgb(240, 238, 80),rgb(219, 204, 47)));
  %BP(box-sizing:none);
}

/* Fluid Header - NavBar Hover Over Background Color */
.ps_header_bar .ps_actions_cont .ps_system_cont .ps_header-navbar .ps-button:hover {
  background: #F0EE50;
  %BP(box-shadow:none);
}

Navigation:  Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



We can see that the NavBar icon background and hover over background colors have changed.

Notes:
  1. box-sizing is a CSS3 property used to tell the browser what the sizing properties (width and height) should include. Refer: W3Schools.

Update NavBar Icon Left Border:

We can see from the screenshot above that there is still a left border on the NavBar icon. Let us update CSK_FLUID_CSS to take care of this.

/* Fluid Header - NavBar Background Color and Border Left */
.ps_header_bar .ps_actions_cont .ps_system_cont .ps_header-navbar .ps-button {
  border-left: 1px solid rgb(219, 205, 48);
  %BV(background-image:linear-gradient(rgb(240, 238, 80),rgb(219, 204, 47)));
  %BP(box-sizing:none);
}

/* Fluid Header - NavBar Hover Over Background Color */
.ps_header_bar .ps_actions_cont .ps_system_cont .ps_header-navbar .ps-button:hover {
  background: #F0EE50;
  %BP(box-shadow:none);
}

Navigation:  Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Update the Fluid Landing Page - Background Color for the Content Portion:

Let us now try to update the background color for the content portion (area where tiles are present) by adding the following style to CSK_FLUID_CSS.

/* Fluid Landing Page - Content Portion Background Color */
#PT_LANDINGPAGE .ps_content {
  background-color: #E8E29E !important;
}

The reason why I used !important rule above (which might not be best practice) is because the delivered style also has the !important rule and the only way to override the delivered style is to use the !important rule again.

Navigation:  Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



We can see that the background color of the content area has changed. But there is still a blue line (bottom header) between the Branding Header and the content area. Let us fix that in the next section.

Update Fluid Header Bottom Border:

Let us add the following style to CSK_FLUID_CSS to take care of this.

/* Fluid Landing Page - Header Border Bottom */
.ps_header_bar {
  border-bottom: 1px solid rgb(240, 238, 80);
}

Navigation:  Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Update Fluid Landing Page - Homepage Drop Down Text Color:

Let us now add the following style to update the color of the Homepage Drop Down text color.

/* Fluid Landing Page - Homepage Drop Down Text Color */
.nuihdr_hpbtn > span > a > span.ps-text {
  color: #1d418c;
}

Navigation:  Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Update Fluid Landing Page - Footer Background Color:

/* Fluid Landing Page - Footer Background Color */
.lpfooter {
  background-color: transparent;
  background: rgba(216, 206, 93, 0.8);
}

Navigation:  Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Notes:
  1. rbga is a new feature in CSS3 where 'a' parameter/property stands for alpha. It allows us to specify the opacity of the color. Refer: W3Schools. You can see that the footer background color is slightly transparent because the alpha property is set to 0.8.

Update Fluid Landing Page - Footer Dot Styling:

/* Fluid Landing Page - Footer Dot Styling */
.lpfooter .dot.on {
  background: #EEEB4D;
}
.lpfooter .dot {
  background: #E8E29E;
  border: 2px solid #1d418c;
}

Navigation:  Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Update Fluid Homepage - Icons:

You can see that there are several icons on the Fluid Homepage - Home, Notification, Drop-Down Action Menu (hamburger icon), NavBar, Homepage Selection Drop-Down Arrow and Footer Refresh - that don't seem to share the same theme as that of our custom CSK theme.

Let us see how we can update these icons to be consistent with our custom theme.

Home Icon:

The home icon is generated by the page field PT_WORK.PT_BUTTON_HOME (Header Page: PT_HEADERPAGE) as part of the Push Button > Label Image Property.





You will notice that the image PT_HEADER_HOME is actually in SVG format. As I have previously mentioned, I am really excited at the prospects of using SVG images. One of the primary reasons aside from the general benefits of using scalable images in RWD is that I find it extremely easy to modify them using a text editor. Previously, modifying images for Branding would require a significant effort and involves using image editing tools such as Photoshop.

To take a look at the image, export the object PT_HEADER_HOME from App Designer (File > Export Image) to your computer and then open the image in a text editor. You will see the following XML:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="25px" height="25px" viewBox="0 0 25 25" enable-background="new 0 0 25 25" xml:space="preserve">
<g>
    <path opacity="0.35" fill="#231F20" d="M22.3,15.3l-9.8-9.8l-9.8,9.8L0,12.7L12.5,0.2L25,12.7L22.3,15.3z M2,12.7l0.7,0.7l9.8-9.8
        l9.8,9.8l0.7-0.7L12.5,2.1L2,12.7z"/>
    <path opacity="0.35" fill="#231F20" d="M21.3,24.8h-6.9v-5h-3.9v5H3.7V14.4l8.8-8.8l8.8,8.8V24.8z M15.8,23.5H20v-9.1l-7.5-7.3
        l-7.5,7.3v9.1h4.1v-5h6.6V23.5z"/>
    <polygon fill="#FFFFFF" points="12.5,4.5 22.3,14.3 24,12.7 12.5,1.1 1,12.7 2.7,14.3     "/>
    <polygon fill="#FFFFFF" points="12.5,6.1 4.4,14.1 4.4,24.1 9.9,24.1 9.9,19.2 15.1,19.2 15.1,24.1 20.6,24.1 20.6,14.1     "/>
</g>
</svg>


Replace #FFFFFF (Hex for White - delivered home icon color) to #1d418c (desired custom color) and save the file as CSK_HEADER_HOME (custom home icon).

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="25px" height="25px" viewBox="0 0 25 25" enable-background="new 0 0 25 25" xml:space="preserve">
<g>
    <path opacity="0.35" fill="#231F20" d="M22.3,15.3l-9.8-9.8l-9.8,9.8L0,12.7L12.5,0.2L25,12.7L22.3,15.3z M2,12.7l0.7,0.7l9.8-9.8
        l9.8,9.8l0.7-0.7L12.5,2.1L2,12.7z"/>
    <path opacity="0.35" fill="#231F20" d="M21.3,24.8h-6.9v-5h-3.9v5H3.7V14.4l8.8-8.8l8.8,8.8V24.8z M15.8,23.5H20v-9.1l-7.5-7.3
        l-7.5,7.3v9.1h4.1v-5h6.6V23.5z"/>
    <polygon fill="#1d418c" points="12.5,4.5 22.3,14.3 24,12.7 12.5,1.1 1,12.7 2.7,14.3     "/>
    <polygon fill="#1d418c" points="12.5,6.1 4.4,14.1 4.4,24.1 9.9,24.1 9.9,19.2 15.1,19.2 15.1,24.1 20.6,24.1 20.6,14.1     "/>
</g>
</svg>


Now I have my own CSK Home icon. Here is how it looks when I open the image (use any browser).



You can see how easy it is to modify the image. Now let us update PT_WORK.PT_BUTTON_HOME page to reference this custom SVG image.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Notification, Drop-Down Action Menu (Hamburger) and NavBar Icons:

Similarly, we can clone the following delivered SVG images:

Notification: PT_HEADER_ALERTS > CSK_HEADER_ALERTS
Action Menu: PT_HEADER_ACTIONS > CSK_HEADER_ACTIONS
NavBar: PT_HEADER_NAVBAR > CSK_HEADER_NAVBAR

Update page field PT_WORK.PT_BUTTON_NOTIFY (Header Page: PT_HEADERPAGE) to replace PT_HEADER_ALERTS with CSK_HEADER_ALERTS.



Update page field PTLAYOUT.HEADER_ACTIONGROUP (Subpage: PT_HEADER_ACTION) to replace PT_HEADER_ACTIONS with CSK_HEADER_ACTIONS.



Update page field PT_WORK.PT_BUTTON_NAVBAR (Header Page: PT_HEADERPAGE) to replace PT_HEADER_NAVBAR with CSK_HEADER_NAVBAR.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Homepage Selection Drop-Down Arrow Icon:

The Fluid homepage selection drop-down arrow icon is generated by the page field PTNUI_LAND_WRK.GROUPBOX14 (Subpage: PTNUI_SELLP_POP) as part of the Group Box Use Properties > Display Options > Label Image for Collaped State.



We can see that PTNUI_DOWN_ARW image is a PNG. To keep all the icon image formats consistent I decided to use a SVG image for all the custom icons. I found a Down Arrow SVG image online which has the following XML:

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN""http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="14px" height="10px" viewBox="0 0 404.308 404.309" style="enable-background:new 0 0 404.308 404.309;"
     xml:space="preserve" fill="#1d418c">
<g>
    <path d="M0,101.08h404.308L202.151,303.229L0,101.08z"/>
</g>
</svg>


Let us save this image as CSK_NUI_DOWN_ARW.SVG and update the page PTNUI_SELLP_POP to reference it.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Homepage Footer Refresh Icon:

The Fluid homepage footer refresh icon is generated by page field PTNUI_LP_FOOTER.REFRESH_BTN (Footer Page: PTNUI_LP_FOOTER) as part of the Push Button/Hyperlink > Label Image property.



PTNUI_REFRESH_ICN is also in PNG format as delivered. I found a refresh icon SVG image online with the following XML:

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN""http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="23px" height="35px" viewBox="0 0 408 408" style="enable-background:new 0 0 408 408;" xml:space="preserve" fill="#1d418c">
<g>
    <g id="refresh">
        <path d="M346.8,61.2C311.1,22.95,260.1,0,204,0C91.8,0,0,91.8,0,204s91.8,204,204,204c94.35,0,173.4-66.3,196.35-153H346.8
            C326.4,313.65,270.3,357,204,357c-84.15,0-153-68.85-153-153c0-84.15,68.85-153,153-153c43.35,0,79.05,17.85,107.1,45.9
            l-81.6,81.6H408V0L346.8,61.2z"/>
    </g>
</g>
</svg>


Let us save this image as CSK_NUI_REFRESH_ICN.SVG and update the page PTNUI_LP_FOOTER to reference it.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Now our Fluid Homepage has a completely custom look and feel. Let us take a look at any Fluid Content Page (e.g.: My Team under Manager Self Service) to make sure that the theme is consistent.



We can see that there is still a little bit more work to be done on the Fluid Content Page Header.

Fluid Content Page - Title Text Color:

Let us add some additional styles to CSK_FLUID_CSS style sheet to address the page title text color.

/* Fluid Content Page(s) - Page Title Text Color */
.ps_header-banner, .ps_header_bar {
  color: #1d418c;
}

Navigation:  Main Menu > PeopleTools > Portal > Branding > Branding Objects > Style Sheet (Tab)

Update the style sheet CSK_FLUID_CSS:




Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Now the only thing that looks a bit odd is the 'Return to Homepage' Button on the Fluid Content Page. We will try to fix the look and feel of this button in the next section.

Fluid Content Page - 'Return to Homepage' Button:

The Return button on the Fluid content pages is a combination of an image, text and push button/hyperlink styling.

Update Image:

Let us first update the image which is generated by the page field PT_WORK.PT_BUTTON_BACK (Subpage: PT_HEADERPAGE) as part of Push Button/Hyperlink > Label Image Property.



PT_NUI_BACK_PRIM_IMG is delivered in SVG format. We can update the XML of this SVG as appropriate:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="18px" height="18px" viewBox="0 0 18 18" enable-background="new 0 0 18 18" xml:space="preserve">
<g>
    <path fill="#F0EC12" d="M9,17.5c-4.7,0-8.5-3.8-8.5-8.5c0-4.7,3.8-8.5,8.5-8.5c4.7,0,8.5,3.8,8.5,8.5C17.5,13.7,13.7,17.5,9,17.5z"
        />
    <path fill="#F2EE29" d="M9,1c4.4,0,8,3.6,8,8s-3.6,8-8,8s-8-3.6-8-8S4.6,1,9,1 M9,0C4,0,0,4,0,9s4,9,9,9s9-4,9-9S14,0,9,0L9,0z"/>
</g>
<polygon fill="#1d418c" points="7.8,9 11.6,5.1 9.9,3.5 4.3,9 9.9,14.5 11.7,12.9 "/>
</svg>


Save the image as CSK_NUI_BACK_PRIM_IMG.SVG.



Update the page PT_HEADERPAGE to reference the custom image.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Another test with lesser real estate on the page causing the image to scale (RWD styling).



Update CSS:

Finally, let us see how we can apply some style overrides on the 'Return to Home' button.

/* Fluid Content Page(s) - Return Button */
.ps_box-button.ps_button_backnav .ps-button,
.ps_box-button.ps_button_backnav .ps-button:link,
.ps_box-button.ps_button_backnav .ps-button:not(.psc_disabled) .ps-button:hover,
.ps_box-button.ps_button_stdheader .ps-button,
.ps_box-button.ps_button_stdheader .ps-button:link,
.ps_box-button.ps_button_stdheader .ps-button:not(.psc_disabled) .ps-button:hover {
  font-size: 0.95em;
  box-shadow: inset 0 1px 0 0 #CBD015;
  padding: 0.6em 1em 0.6em 0.5em;
  border: 1px solid #F2EE29;
  border-bottom-color: #F0EC12;
  background-image: linear-gradient(rgb(240, 238, 80),rgb(219, 204, 47));
  text-align: left;
  display: inline-block;
}

.ps_header_bar .ps_box-button .ps-button, .ps_header_bar .ps_box-button .ps-button:link, .ps_header_bar .ps_box-button .ps-button:hover {
  color: #1d418c;
  font-size: 0.95em;
}

.ps_box-button.ps_button_backnav:not(.psc_disabled) .ps-button:hover,
.ps_box-button.ps_button_stdheader:not(.psc_disabled) .ps-button:hover
{
  background-color: #F0EE50;
  %BP(box-shadow:none);
  background-image: none;
  border-color: none;
  border-image: none;
  border-style: none;
  border-width: none;
  color: #1d418c;
}

.ps_box-button.ps_button_backnav:not(.psc_disabled) .ps-button:active,
.ps_box-button.ps_button_backnav:not(.psc_disabled) .ps-button:hover:active,
.ps_box-button.ps_button_stdheader:not(.psc_disabled) .ps-button:active,
.ps_box-button.ps_button_stdheader:not(.psc_disabled) .ps-button:hover:active
{
  background-color: #F0EE50;
  %BP(box-shadow:none);
  background-image: none;
  border-color: none;
  border-image: none;
  border-style: none;
  border-width: none;
  color: #1d418c;
}

The above CSS was identified as the styles that were affecting the 'Return to Home' button on the Fluid Content Page(s).

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).

Return Button:



Return Button Hover Action Style:



Return Button with page width less that 680 px (testing Responsive Styling):



We can see that although the button styling looks good for the original size and hover over action, it looks out of place for the responsive styling (smaller screen width). Let us see how we can fix this issue using some additional responsive styling.

Update CSS further:

@media only screen and  (max-width: 680px) {
    .ps_header_bar .psc_hide-BP3 { display: none !important; }
    .ps_menutype-act .psc_show-BP3:not(.psc_hidden) { display: block; }
    .ps_header_bar .ps_button_backnav > .ps-button-wrapper > .ps-button > .ps-text {
      display:none !important;
    }
    .ps_header_bar .ps_button_backnav > .ps-button-wrapper > .ps-button > .ps-img {
      max-height:none !important;
      height:1.8em;
      width:1.8em;
      padding:0;
    }
    .ps_header_bar .ps_button_backnav > .ps-button-wrapper > .ps-button {
      padding:0.4em;
    }
    .ps_header_bar  .ps_pagetitle > .ps-text { /*01A - Added for banner changes only */
        max-width:49vw;
      }
}

I found the above RWD related CSS in the delivered style sheet PSSTYLEDEF_FMODE. This seems to be controlling the background, background image scaling and text of the 'Return to Home' push button. So I included this in the custom CSK_FLUID_CSS to make sure that our custom style sheet is not inadvertently overriding the delivered style.

Update the style sheet CSK_FLUID_CSS:



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



You can see from the screenshot that the 'Return to Home' button is responsive to the screen width (less that 680 px).

This concludes Part 5A - Fluid Branding. I think we covered several Fluid Branding topics that should provide a good initial introduction and help us personalize and further customize the Fluid UI as per our own requirements.

Thanks for reading this article and as always I welcome all feedback and/or questions. Please feel free to let me know if anything stated in this post can be done in a better way!

I intend to follow up this post with other additional Fluid UI Branding and Customization techniques. Stay tuned for Part 5B!

Updated on November 29th, 2015:
Please review my latest posts on PeopleTools Fluid Branding:
PeopleTools 8.54+ - Branding - Part 5B - Fluid Branding
PeopleTools 8.54+ - Branding - Part 5C - Fluid Branding 

PeopleTools 8.54+ - Branding - Part 4B - Customizing DEFAULT_THEME_TANGERINE_ALT Theme (Continued)

$
0
0
This post (Part 4B) is a continuation of one of my previous Branding articles on customizing the DEFAULT_THEME_TANGERINE_ALT theme (Part 4A).

In part 4A, we saw how we could override the logo image while using the DEFAULT_THEME_TANGERINE_ALT theme.

Result:



In this post we will see how we can further customize this theme which was cloned from DEFAULT_THEME_TANGERINE_ALT.

Override Branding Header Background Image:

The background image on the Branding Header is generated by the following style.



Let us override this style to use a custom image.

Custom Image: CSK_HEADERBG_ALT








Custom Style:

/* Branding Header Background Color */
#ptbr_header_container #pthdr2container.pthdr2container {
  background-image: url(%image(CSK_HEADERBG_ALT));
}

The additional custom selector (highlighted above) was added to provide a higher precedence to the custom style.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



We can see that the branding header background color change has taken effect.

Overriding the NavBar Background Image:

The NavBar background image is generated by the following style.



Custom Image: CSK_NAVBARLINK_BG_ALT






 Main Menu > PeopleTools > Portal > Branding > Branding Objects (Image Tab)



Custom Style:

/* NavBar Background Color */
#pthdr2navbarlinks.pthdr2navbarlinks #pthdr2navbar_div #pthdr2navbar {
  background: url(%image(CSK_NAVBARLINK_BG_ALT)) repeat-x scroll 0 0 transparent; 
}

The additional custom selector (highlighted above) was added to provide a higher precedence to the custom style.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Overriding the Drop Down Menu Background Image:

The drop down menu background image is generated by the following style.



Custome Image: CSK_BREADCRUMB_ALT






Custom Style:

/* Drop Down Menu  Background Color */
#ptdropdownmenu.ptdropdownmenu {
  background: url(%image(CSK_BREADCRUMB_ALT)) repeat scroll 0 0 transparent;
 }

The additional custom selector (highlighted above) was added to provide a higher precedence to the custom style.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Override Drop Down Menu Font Color:

The drop down menu font color is generated by the following style.



Custom Style:

/* Drop Down Menu Font Color */
#ptdropdownmenu .pthnav a.pthnavbcanchor, #ptdropdownmenu .pthnav a.pthnavbcanchor:hover, #ptdropdownmenu .pthnav a.pthnavbcanchor:focus, #ptdropdownmenu .pthnav #pthnavbc li a, #ptdropdownmenu .pthnav #pthnavbc li a:hover, #ptdropdownmenu .pthnav #pthnavbc li a:focus {
  color: #284562 !important;
}

The additional custom selector (highlighted above) was added to provide a higher precedence to the custom style.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Override System Links Font Color:

The system links font color is generated by the following style.



Custom Style:

/* System Header Links Font Color */
#pthdr2container.pthdr2container a.PSHYPERLINK, #pthdr2container.pthdr2container a.PSHYPERLINK:hover, #pthdr2container.pthdr2container a.PSHYPERLINK:visited {
  color: #284562;
}

The additional custom selector (highlighted above) was added to provide a higher precedence to the custom style.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).

 


Override Drop Down Menu and 'Add To' Menu - Active Background Color:





Custom Styles:

/* Add To Drop Down Background Color (Active) */
#pthdr2navbarlinks.pthdr2navbarlinks #pthdr2addto_div.active {
  background-color: #FFFFFF;
  border: 1px solid #666666;
}

/* Drop Down Menu Navigation Background Color (Active) */
.pthnav .pthnavbaropen {
  background-color: #FFFFFF;
}

The additional custom selector (highlighted above) was added to provide a higher precedence to the custom styles.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).





Override Drop Down Menu Icon Images:




Custom Images:

CSK_HNAV_ALT_FAV_SEP





CSK_HNAV_ALT_BC_DOWN_ARROW




CSK_HNAV_ALT_HIERARCHY_SEP




Custom Styles:

/* Drop Down Menu Down Arrow Image */
#ptdropdownmenu.ptdropdownmenu .pthnavbarfldr:after {
  content: url(%image(CSK_HNAV_ALT_BC_DOWN_ARROW));
}

/* Drop Down Menu Fav Icon Separator Image */
#ptdropdownmenu.ptdropdownmenu li#pthnavfavsep {
  background-image: url(%image(CSK_HNAV_ALT_FAV_SEP));
}

/* Drop Down Menu Hierarchy Separator Image */
#ptdropdownmenu.ptdropdownmenu li.pthnavhiearchysep:before {
  content: url(%image(CSK_HNAV_ALT_HIEARCHY_SEP));
}

The additional custom selector (highlighted above) was added to provide a higher precedence to the custom styles.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Override System Link Icons and NavBar Icon Images:




Custom System Link Icon Images:

CSK_HEADERLINK_HOME_ALT:





CSK_HEADERLINK_SEP_ALT:
 






Custom NavBar Icon Images:

CSK_ADDTOLINK_ARROW:




CSK_HEADER_ALERTS (SVG image):


CSK_HEADER_NAVBAR (SVG image):



Custom Styles:

/* Home Icon Image */
#pthdr2container.pthdr2container #pthdr2home {
  background: url(%image(CSK_HEADERLINK_HOME_ALT)) no-repeat scroll left center transparent;
}

/* System Header Links Separator */
#pthdr2container.pthdr2container .pthdr2sep {
  background: url(%image(CSK_HEADERLINK_SEP_ALT)) no-repeat scroll center center transparent;
}

/* Add To Drop Down List Down Arrow Image */
#pthdr2navbarlinks.pthdr2navbarlinks #pthdr2addto:after {
  content: url(%image(CSK_ADDTOLINK_ARROW));
}

/* Notification Icon Image */
#pthdr2navbarlinks #pthdr2notify_div #pthdr2notify span {
  background: url(%image(CSK_HEADER_ALERTS)) no-repeat scroll center 8px transparent;
}

/* NavBar Icon Image */
#pthdr2navbarlinks #pthdr2navbar_div #pthdr2navbar span {
  background: url(%image(CSK_HEADER_NAVBAR)) no-repeat scroll center 8px transparent;
}

The additional custom selector (highlighted above) was added to provide a higher precedence to the custom styles.



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Add a Hyperlink to the Branding Logo:

In this section we will see how we can add a hyperlink to the branding logo. This would be useful in cases where we might want to link the logo to another website.

Create Custom URL:



Modify existing style for the Branding Logo:

Comment the content property.




Modify the logo element in the custom Header Definition:

PeopleTools > Portal > Branding > Define Headers and Footers




We replaced the existing Static HTML (which was a non-breaking space - &nbsp;) with an anchor element referencing the URL Definition (href), Image Object (img element) and URL Definition Description (title).

HTML for reference:
<a href='%URL(CSK_LOGO_URL)'>
   <img src='%image(CSK_LOGO)' title='%URL(CSK_LOGO_URL, DESCR)' style='border: none;'></img>  
</a>

Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Display Database Name on the Branding Header:

Most organizations would like to print the name of the database on the branding header for test environments (e.g.: DEV, TST, UAT, etc). Let us see how we can display the database name on the branding header.

Additionally, we will use a custom javascript object to write some conditional logic to only display the database name if it is a non-production environment. This helps us to keep the header "clean" for production but display the database name only for testing (non-production) environments.

Create Custom Javascript Object:


if ("%dbname" !== "PROD_DBNAME")
{

   // create div for dbname
   var dbname = document.createElement("div");

   // set attributes and innerHTML
   dbname.setAttribute("id","cskdbname");
   dbname.setAttribute("class","cskdbname");
   dbname.innerHTML = "<p>%dbname</p>";

   // insert dbname div after the cskhdrlogo div
   var logo = document.getElementById("cskhdrlogo");
   document.getElementById("pthdr2container").insertBefore(dbname, logo.nextSibling);

}

Note: In the javascript, replace PROD_DBNAME with the actual name of your Production Database.

Create Custom Style for Database Name:

/* Database Name Text Style */
#pthdr2container.pthdr2container #cskdbname.cskdbname {
    display: inline-block;
    color: #284562;
    margin: 0 5em;
    vertical-align: super;
    font-family: Arial,Helvetica,sans-serif;
    font-size: 12pt;
    font-weight: bold;
    float: left;
}



 Add a new leaf element to represent the database name on the Branding Header Definition:

We will add a new child element under the pthdr2container. This element is a basic javascript type (cskdbname) which is ordered after the cskhdrlogo element.
 






Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Display Dynamic and User Specific Greeting Message:

In this section, let us see how we can modify the Branding Header definition to display a dynamic greeting message for the users.

The personalized greeting message would display the text "Welcome to CSK " appended with the User's Description text using the %UserDescription system variable.

Let us assume we want to display this greeting message at the bottom of the 'Add To' menu.



Before we add the message, let us make a little bit of room by moving the 'Add To' menu to the top.

Move elements using CSS:

Custom Style:

/* Add To Drop Down Menu Position (Align to the top) */
#pthdr2navbarlinks.pthdr2navbarlinks #pthdr2addto_div {
  vertical-align: top;
}



Result:



Add a Child Element under pthdr2navbarlinks:

This will serve as a container for holding both the 'Add To' menu and the new custom greeting message.





Custom Style for cskhdr2navbarcontainer:

/* Style for custom container in navbar */
#cskhdr2navbarcontainer.cskhdr2navbarcontainer {
  position: relative;
  float: left;
  height: 57px;
}



Move 'Add To' Drop Down Menu under cskhdr2navbarcontainer:

Let us set the parent for 'pthdr2addto' element as 'cskhdr2navbarcontainer'.



Result:



Create Custom Branding Element Type for Greeting Message:

Main Menu > PeopleTools > Portal > Branding > System Data > Define Element Types



Note: The implementation details for the Custom App Class CSKGreetingText is exactly the same as in my previous post - PeopleTools 8.54 - Branding - Part 3 (Please refer Display Dynamic and User Specific Greeting Message using Custom Branding Elements section).

Add custom 'Greeting Message' element to the Branding Header:

Add 'cskgreetingmessage' element under 'cskhdr2navbarcontainer' using 'CSK Personalized User Greeting' as the element type.







Add custom style for the Greeting Message:

/* CSK Personalized Greeting Message */
#pthdr2navbarlinks.pthdr2navbarlinks #cskgreetingmessage.cskgreeting {
  position: absolute;
  bottom: 0px;
  right: 10px;
  color: #284562;
  font-family: Arial,Helvetica,sans-serif;
  font-size: 12pt;
  font-weight: normal;
}



Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Add Custom Links to the Branding Header System Links:

In this section let us see how we can add some useful links (for pages of interest such as Process Monitor and Report Manager) to the System Links section on the Branding Header.



Create Custom Element Types for Process Monitor and Report Manager Links:

Main Menu > PeopleTools > Portal > Branding > System Data > Define Element Types

Process Monitor:



Report Manager:



Note: The implementation details for the Custom App Classes ProcessMonitorLink and ReportManagerLink are exactly the same as in my previous post - PeopleTools 8.54 - Branding - Part 3 (Please refer Application Class Implementation for Process Monitor AND Application Class Implementation for Report Manager sections).

Add Process Monitor and Report Monitor Elements to Branding Header:









Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).



Adjusting the width of the Navigation Breadcrumb Scroll to accommodate the additional links on the Branding Header System Links:

Special thanks to Cache Staheli (see comments below) who pointed out an issue with adding custom links to the System Links. It appears that when we add custom links to System Links, the Navigation Breadcrumb Scroll (which can be seen when the browser width is reduced/limited) overlays with the System Links causing the entire header to render poorly.



Upon inspecting the HTML further, we will find that there is a hard-coded offset (set to 150) injected as part of a javascript.



Let us see how we can override this hard-coding to accommodate our additional custom links. This offset value is set in a javascript that is associated as part of the header definition. Note: This javascript would not be available as a PeopleTools managed object as it is added directly as a static javascript (meaning it cannot be found in App Designer).





Let us go ahead and update this offset value to something that is more appropriate to the current header design.



If you would like to make the offset variable a bit more dynamic then you can use the following JavaScript to replace the Static JavaScript:

// ptHNavSideOffset = 150;
ptHNavSideOffset = document.getElementById("pthdr2syslinks").clientWidth;

This would ensure that the offset is set to the width of the pthdr2syslinks (the container DIV for the Branding Header - System Links).

Test Changes:



Additional Customizations:

Please refer PeopleTools 8.54 - Branding - Part 3 for the following changes (implementation steps are exactly the same):

- Branding the Timeout Popup Warning Message
- Implementing Google Analytics
- Migrating Branding to other environments

Note: For 'Migrating Branding Objects to other environments' please also refer the following links:
Branding Objects - Migration Issue and Workaround
E-PORTAL: Managed Branding Objects are not Accessible in the Target Environment After Migration (Doc ID 2011383.1) 

Adding/Updating the FavIcon for Classic (Included on 2016/04/01):
Refer: FavIcon for Classic

Invoke PeopleCode Event from Javascript (in a HTMLAREA)

$
0
0
Let us walk through an example on how to invoke a peoplecode event from a javascript in a HTMLAREA.

Here is a test page which contains a push button that display a winmessage on FieldChange.


Let us see what happens behind the scenes when we click on the push button by inspecting the HTML.


We can see that the onclick event on the push button invokes the javascript function (delivered) submitAction_win0(document.win0, this.id, event). In this case, this.id would be equal to CSK_TEST_WRK_TEST. The general format for the id field would be <RECORD_NAME>_<FIELD_NAME>. This would translate to <RECORD_NAME> = CSK_TEST_WRK and <FIELD_NAME> = TEST.

Now let us include a HTMLAREA on the page.


Include the following HTML and javascript in the HTMLAREA properties. Note: I am using a constant HTML value for the purposes of this example.


HTML Code:

<script>
function myFunction() {
   submitAction_win0(document.win0,"CSK_TEST_WRK_TEST", event);
}
</script>

<a href="#" onclick="myFunction()">Push Button in HTMLAREA</a>

Updated HTML Code - 20151105 - Thanks to @Santiago.gmerino's comment below:

<script>
function myFunction() {
   // submitAction_win0(document.win0,"CSK_TEST_WRK_TEST", event);
   // Use %formname to resolve _win# dynamically.
   submitAction_%formname(document.%formname,"CSK_TEST_WRK_TEST",event);
}
</script>

<a href="#" onclick="myFunction()">Push Button in HTMLAREA</a>

Now let us test the javascript in the HTMLAREA.


We can see the hyperlink that we added in the HTMLAREA appear on the page. Let us click the hyperlink 'Push Button in HTMLAREA'. This should trigger the FieldChange event on the push button CSK_TEST_WRK.TEST.


Note: At the time of writing this post, I am using HCM 9.2 PUM Image 12 - PeopleTools 8.54.08.

PeopleTools 8.54+ - Branding - Part 4C - Customizing DEFAULT_THEME_TANGERINE_ALT Theme (Continued)

$
0
0

This post (Part 4C) is a continuation of one of my previous Branding articles on customizing the DEFAULT_THEME_TANGERINE_ALT theme (Part 4B).

Adding A Content Reference To The Header Using A 'Basic Link':

Previously, we added links to the System Header Links section by using the same approach as some of the delivered System Header Links such as 'Worklist' and 'MultiChannel Console' links. This involved creating our own custom Branding Elements with associated App Classes.

Now, let us use an alternative approach to add links to the Branding Header using a 'Basic Link' and 'Portal/Content URL'.

Let us add the 'My Personalizations' Content Reference - PT_USER_SELF_PERSONAL_GBL - in this example.








Note: Use 'Portal URL' for Content Reference to display within the Portal Frame. Use 'Content URL' for the Content Reference to display without the Portal Frame.






Save the Header Definition.

Test Changes:

Recommendations if you are experiencing caching issues.
  1. Clear local browser cache.
  2. Shutdown, purge and reboot the web server(s).


Oracle SQL: String Aggregation to Convert Rows of Data into a Single Column - LISTAGG Function

$
0
0
I recently learnt about this cool Oracle SQL function called LISTAGG. I am sure some of you must have come across this function already. I found it very useful for a lot of cases to perform string aggregation to convert rows of data into a single column.

Here is an example to aggregate multiple rows of fields for a particular record (PSRECFIELD) into a single column.

SQL which returns multiple FIELDNAME rows per RECNAME on PSRECFIELD:

select RECNAME, FIELDNAME from PSRECFIELD where recname = 'PSOPRDEFN' ORDER BY FIELDNUM;

 
Now let us convert these rows of fields into a single column using string aggregation (LISTAGG).

SQL using LISTAGG which returns one row with all fields per RECNAME on PSRECFIELD:


select RECNAME, LISTAGG(FIELDNAME, ', ') WITHIN GROUP (ORDER BY FIELDNUM) "Field_Listing" from PSRECFIELD where recname = 'PSOPRDEFN' group by RECNAME;



We can see that the list of fields were all aggregated and separated by a comma. This function is very useful for several reasons. I use the above SQL specifically for selecting all columns from a particular table/view instead of having to type them out by hand.

E.g.: I can copy the results of Field_Listing column and use it in my select statement.

select OPRID, VERSION, OPRDEFNDESC, EMPLID, EMAILID, OPRCLASS, ROWSECCLASS, OPERPSWD, OPERPSWDSALT, ENCRYPTED, SYMBOLICID, LANGUAGE_CD, MULTILANG, CURRENCY_CD, LASTPSWDCHANGE, ACCTLOCK, PRCSPRFLCLS, DEFAULTNAVHP, FAILEDLOGINS, EXPENT, OPRTYPE, USERIDALIAS, LASTSIGNONDTTM, LASTUPDDTTM, LASTUPDOPRID, PTALLOWSWITCHUSER
from PSOPRDEFN;

Another good example:

SQL using LISTAGG to return list of key fields (comma separated) for particular record definition in a single row.


SELECT A.RECNAME, Listagg(A.FIELDNAME, ', ') within GROUP (ORDER BY A.FIELDNUM) "RECORD_KEY_FIELDS" FROM   PSRECFIELD A WHERE  A.RECNAME = 'NAMES' AND Bitand(A.USEEDIT, 1) > 0 GROUP  BY A.RECNAME;


HCM/Campus Solutions Address Validations

$
0
0
If anyone has worked on a CI or a web service (e.g.: CWS - Constituent Web Service, AAWS - Admission Applications Web Service) that involves loading data related to addresses into HCM/Campus Solutions applications then you must have run into the address validation problem. The problem with the validation on the addresses component/page is that the fields displayed on the address subpage (specific to a country) would vary depending on the country.

This complicates the process of dynamically identifying the list fields that need to be populated depending on the current country that is being used for data entry. Let us take the example of the Admission Applications Web Service to put things into perspective. Typically, there would a web front-end for the admission applications and that would in turn invoke the AAWS web service to create and save applications into Campus Solutions. Now, the problem for the web front-end application is to dynamically figure out the list of fields that need to be populated on the AAWS request message based on the current country. Once we determine the list of fields that need to be populated, we would additionally run into the problem where the validation on the fields (required/translate/prompt edits) would differ per country.

Here is a list of logical steps and SQLs that would help with building some of that dynamic address validation logic. I was able to write some SQL that looks into PeopeTools metadata and pulls out the information we need.

E.g.:


Address Formatting:

To identify the list of fields to display and populate (CIs/Web Service calls) data use PS_EO_ADDR_FMT_TBL.

E.g.:

select * from PS_EO_ADDR_FMT_TBL where COUNTRY = 'ESP';


The address format data could be found online as well.



Address Validations:

Required Fields:

Only the following fields are required:
-    COUNTRY
-    ADDRESS1* or ADDRESS2* or ADDDRESS3* or ADDRESS4*: At least one of these fields is required depending on how many exist in SQL1.

* The SQL1 provided must return the fields listed.

E.g.:

For ESP (Spain), SQL1 only returns ADDRESS1 and ADDRESS2 fields. Therefore, at least one of ADDRESS1 or ADDRESS2 fields is required for Spain.
For BRA (Brazil), SQL1 returns all fields ADDRESS1, ADDRESS2, ADDRESS3 and ADDRESS4. Therefore, at least one of ADDRESS1 or ADDRESS2 or ADDRESS3 or ADDRESS4 fields is required for Brazil.

Fields With Translate Edits:

The SQL1 provided must return ‘Y’ for TRANSLATE_EDIT value for the corresponding COUNTRY, FIELDNAME.

E.g.:

ADDR_FIELD1 for Spain (ESP) is based on a translate edit.


Note: For List of Translates Values for a particular field use SQL2.

Fields With Prompt Table Edits:

The SQL1 provided must return ‘Y’ for PROMPT_EDIT value for the corresponding COUNTRY, FIELDNAME.

E.g.:

STATE field for BRA (Brazil) has a prompt table of STATE_TBL. The key fields on the prompt table are COUNTRY, STATE.
CITY field for BRA (Brazil) has a prompt table of CODE_CITY_BRA. The key fields on the prompt table are STATE, CITY.


Note: For List of Values for a particular field use the prompt table (PROMPT_TABLE) with the associated prompt table keys (PROMPT_TABLE_KEYS).

Other Scenario:

If a field exists in PS_EO_ADDR_FMT_TBL and does not fall into any of the above scenarios then there is NO field validation.

SQL1 - Address Format Sub Page Information Based On PeopleTools MetaData:

SELECT Substr(A.pnlname, 9, 3) AS COUNTRY,
       A.fieldname,
       CASE
         WHEN Bitand(B.useedit, 512) > 0 THEN 'Y'
         ELSE 'N'
       END AS TRANSLATE_EDIT,
       CASE
         WHEN Bitand(B.useedit, 16384) > 0 THEN 'Y
         ELSE 'N'
       END AS PROMPT_EDIT,
       editable AS PROMPT_TABLE,
       (SELECT Listagg(Y.fieldname, ', ')
                 within GROUP (ORDER BY y.fieldnum) "PROMPT_TABLE_KEYS"
        FROM   psrecfield Y
        WHERE  Y.recname = B.edittable
               AND Bitand(Y.useedit, 1) > 0
        GROUP  BY Y.recname)   AS PROMPT_TABLE_KEYS
FROM   pspnlfield A,
       psrecfield B
WHERE  A.pnlname IN (SELECT X.pnlname
                     FROM   ps_eo_addr_subpage X)
       AND A.recname <> ''
       AND A.fieldname <> ''
       AND MOD(A.fielduse, 2) = 0
       AND A.recname = B.recname
       AND A.fieldname = B.fieldname
--and substr(A.PNLNAME, 9,3) = 'BRA'
ORDER  BY country,
          A.fieldnum; 


SQL2– List Translate Values For A Field:

SELECT A.fieldname,
       A.fieldvalue,
       A.xlatlongname  AS DESCR,
       A.xlatshortname AS DESCR_SHORT
FROM   psxlatitem A
WHERE  A.fieldname = 'ADDR_FIELD1'
       AND A.effdt = (SELECT Max(A_ED.effdt)
                      FROM   psxlatitem A_ED
                      WHERE  A.fieldname = A_ED.fieldname
                             AND A.fieldvalue = A_ED.fieldvalue
                             AND A_ED.effdt <= SYSDATE)
       AND A.eff_status = 'A';

Working with Rich Text Editor - Custom Configuration, Toolbars and Plugins

$
0
0
Rich Text Editors (RTE) are being used more commonly with the latest PeopleTools versions. There are several pages that contain Rich Text Editor fields (generally for configuration) which are then used for display on other transactional pages using HTMLAREAs, used as the content for Rich Text enabled emails or used as the content for Rich Text enabled BI Publisher reports (to name a few use cases).

Note: The Rich Text Editor provided by PeopleTools is powered by CKEditor.

Page With Rich Text Editor Enabled Field:

Here is an example of a simple page that contains a Rich Text Editor field. 



The page contains a Long EditBox (CSK_RTE_DATA.DESCRLONG) with the following properties.


We are currently using the default Rich Text Options (Note: Configuration Settings Id is blank). The page appears as follows with the Rich Text Editor for the DESCRLONG Long EditBox. The Rich Text Toolbar is generated based on the default configuration.



Page Displaying Rich Text Data:

Here is an example of a simple page that displays data stored in a Rich Text enabled field using a HTMLAREA.


Page Activate PeopleCode to display the Rich Text data field in the HTMLAREA:


The page display the Rich Text data in the HTMLAREA as follows:



Adding Custom Rich Text Options - Templates, Plugins:

I recently came across an interesting question on the OTN forums. The question was "how to use Rich Text to display an iframe with a link to a youtube video?". If you look at the above Rich Text Editor field that uses the default Toolbar, it does not have the ability to add any HTML tags or specifically IFRAME content.

To enable additional/custom Toolbar items on the Rich Text Editor, we must first create our own custom Rich Text Editor Configuration.

Creating a Custom RTE Configuration:

We need to create a new HTML definition with a name that starts with 'PT_RTE_CFG'. Let us create a custom HTML definition called PT_RTE_CFG_CSK cloned from PT_RTE_CFG_PTPPB (delivered RTE Configuration).


Now to enable a custom Toolbar item for embedding an IFRAME, we must make use of additional plugins. To find the list of all available plugins as delivered, we can look in the following directory on the web server:

<PIA_HOME>/webserv/<domainname>/applications/peoplesoft/PORTAL.war/<sitename>/ckeditor/plugins

Fortunately, in this case the IFRAME plugin for CKEditor is already available as delivered (if not we must download and place the required plugins in the above folder path).


Let us now add the custom IFRAME Toolbar to our Custom RTE Configuration (PT_RTE_CFG_CSK). Let us include the following additional line in the configuration (note the comma in the screenshot).

  { name: 'insert', items : [ 'Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak','Iframe' ] }



Moving ahead, let us reference this Custom RTE Configuration in the Page Field Properties of the Rich Text enabled field.



Now let us take a look at the page with the Rich Text enabled field.


We can see the additional/custom Toolbar that we added to our Custom RTE Configuration. This would help us with embedding an IFRAME element that links to a youtube video.




This results in an embedded IFRAME as follows:


Testing IFRAME on the Display Page:


Similarly, we can add additional custom Toolbars to our Custom RTE Configuration. Hope you find this useful!

Environment details at the time of writing this post:
HCM 9.2 PUM Image 12 (PeopleTools 8.54.08)

Reference:
PeopleBooks - Modifying the Rich Text User Interface 

Regular Expression Pattern Matching for PeopleSoft Trace/Log Files

$
0
0
Have you ever wondered how to remove some of the timing and other environment specific information from a trace/log file so that we only see the SQL and PeopleCode?

The timing and other information that I am referring to are:

SQL:


PeopleCode:



Why?

While these timing and other information in the trace file are great for performance tuning activities, they seem to cause several issues (at least for me) when doing a comparative analysis. By comparative analysis, I mean comparing the trace files across different scenarios to identify a problem. For example, an issue might only occur for user A but does not occur for user B. Then we would be inclined towards comparing the trace files generated for user A and user B in an effort to identify the problem. Similarly, an issue might only occur in a particular environment (say TEST) whereas it works fine in another environment (say DEVELOPMENT). Again we would be inclined towards comparing the trace files generated in TEST and DEVELOPMENT to identify the problem.

Now that I detailed the scenario/activity, I would like to describe the problem. When we try to compare two different trace files using any file compare tools (such as WinMerge), the results would identify a difference on almost every single line! Most of them would be false positives due to the timing and other information which is not really useful in such cases.

E.g.:



Regular Expressions (RegEx) Pattern Matching for PeopleSoft Trace/Log Files:

So, if we get rid of (or mask the unncessary information) then we can determine the "actual" differences more efficiently.

That is where Regular Expression (RegEx) pattern matching helps in identifying and removing/masking unncessary information.

Note: I generally use notepad++ for text editing. I am sure most text editors would have a similar RegEx find/replace functionality.

RegEx Pattern for SQL:

Find: ^[a-z]{8}\.\d+ +\(\d+\) +\t +\d+-\d+ +\d{2}\.\d{2}\.\d{2} +\d+\.\d{6} Cur#\d+\.\d+\.[a-zA-Z0-9_]+ RC=\d+ Dur=\d+.\d{6}
Replace: SQL---------------


RegEx Pattern for PeopleCode: 

Find: ^[a-z]{8}\.\d+ +\(\d+\) +\t +\d+-\d+ +\d{2}\.\d{2}\.\d{2} +\d+.\d{6}
Replace: PeopleCode--------


Benefits of Regex Pattern Matching Find/Replace During Comparative Analysis:

Now, if we remove all the unnecessary information and then compare, we would be able to determine the differences quickly and easily. Here is an example of how I used the RegEx Find/Replace (detailed above) and then compared two different trace files using WinMerge.


Similarly, we can use Regex Pattern Matching to intelligently find and replace specific portions of the trace/log files to improve readability!

Fluid - WYSIHTML5 Editor Prototype!

$
0
0
I recently answered a question on the OTN forums related to rich text editor in PeopleSoft. Since PeopleTools 8.50, PeopleSoft has leveraged using CKEditor for rich text editor (aka RTE) configurations options in App Designer. As a follow up to the OTN, I wrote a small post on how to create and use custom RTE configurations, toolbars and plugins.

CKEditor in PeopleTools provides a way to create and work with a WYSIWYG (What You See Is What You Get) rich text editor.

This has found its way to several use cases ranging from but not limited to:
-    Rich text configuration fields which are then used for rich text display in HTMLAREAs
-    Content source for rich text enabled emails
-    Content source for rich text enabled BI Publisher reports
-    Content source for Enterprise Components Forms Builder – Instructions
-    Content source for rich text enabled Student Activity Guide (Configurable) Pages such as Agreement Pages, Start and Complete Pages

While this is a great utility, it is a WYSIWYG editor which means that it might only be appropriate for Classic pages and might not be suitable for Fluid. I was curious to see how a rich text enabled field appears on a Fluid page and based on my tests it appears that Fluid does not support rich text enabled fields.

RTE Field on a Fluid Page:



Results: RTE toolbar does not appear in Fluid.


We can also confirm that rich text is not supported for Fluid in PeopleBooks.

Home > PeopleSoft > PeopleTools 8.54 > Fluid User Interface Developer’s Guide > Considerations for PeopleSoft Fluid Application Implementation


We can imagine how RTE powered by CKEditor (WYSIWYG) would introduce several challenges when it comes to incorporating the editor in Fluid. But why not WYSIHTML5 - What You See Is HTML5? :)

So that is how I got started on this little pet project!

I wanted to take the same concept and create a rich text editor that is also responsive (WYSIHTML5). I used an open source project (http://wysihtml.com/) to develop a prototype for a WYSIHTML5 Editor in PeopleSoft (Fluid) that enables Responsive Rich Text.

It is still a prototype so it has a few quirks to be worked around and it is also not a fully functional RTE yet. But I think it is a great start!

Step 1: Load Open Source Project to the Web Server

Based on instructions in the http://wysihtml.com/ I downloaded the open source project (zip file), extracted/unzipped the contents and placed it on the web server.

Path:

<PIA_HOME>/webserv/<DOMAIN>/applications/peoplesoft/PORTAL.war/<site_name>


Contents:


This completes the first step to make the necessary javascripts and stylesheets (amongst other things) available on the web server.

Now moving on to incorporating this in PeopleTools.

Step 2: Create Fluid Page with WYSIHTML5 Editor (Configuration)


Legend:

1. Static HTMLAREA (1) is used to store a javascript function and a button which when invoked transfers the WYSIHTML5 contents in HTMLAREA (4) to an invisible - modifiable by javascript - long edit field (2).


The "csk_div" ID used in var x = document.getElementByID("csk_div"); is referencing an input field (WYSIHTML5 editor) in HTMLAREA (4).

2. Invisible (Modifiable by Javascript) field to temporarily store/move (PreSave) the WYSIHTML5 contents from HTMLAREA (4) to the component buffer. This helps with sending the HTML5 contents to the server during the save (3). This is kind of a hack/temporary workaround and there should be a cleaner way to get this to work. It is a "to-do" item to make this more efficient.


 
3. Save button to push data (component buffer) in the page to the server.



4. HTMLAREA that holds the WYSIHTML5 contents with an input/editable field (and other associated wysihtml toolbar items, styling and scripts). HTMLAREA is populated using PageActivate PeopleCode using a HTML object (CSK_WYSIHTML5).



CSK_WYSIHTML5 HTML object was built primarily based on the HTML in this example page:
http://voog.github.io/wysihtml/examples/advanced.html

Few things to note about CSK_WYSIHTML5 HTML:

- An ID attribute ("csk_div") was added to a DIV that represents the input/editable element for the HTML5 editor. This is needed because it is used in the javascript function that is part of the Static HTMLAREA (1).
- The contents in the HTML5 editor field (csk_div) are passed in using a bind variable (via Page PeopleCode).
- The script sources were appropriately adjusted to refer to the directory on the web server (where the wysihtml project is located).


Step 3: Create Fluid Page for WYSIHTML5 Display (Viewer)



This is a very simple Fluid page with a single HTMLAREA that is loaded on PageActivate as shown above. During the load,  the HTML5 contents that was created and stored using the previous page (CSK_WYSIHTML5_CFG) is retrieved and used as a parameter to HTML object (CSK_WYSIHTML5_DISP). The HTML retrieved from CSK_WYSIHTML5_DISP is them assigned to the HTMLAREA field.

CSK_WYSIHTML5_DISP was also primarily built using the following page:
http://voog.github.io/wysihtml/examples/advanced.html

Only differences are:
- Toolbar was removed (as it is a display only page).
- Made the editor display only (non-editable).
- Added a bind value to place the HTML5 contents using PageActivate code.


Let us see this in action!! 

I created a custom Fluid Hompage (Sasank's WYSIHTML5) and added the two Fluid Pages as tiles.



Fluid Page with WYSIHTML5 Editor Prototype:

- Enter "Rich Text"/Responsive contents in the editor.
- Click on "PreSave (Load to Buffer)" button.
- Click on "Final Save" button.


Legend:
1. Push buttons to save responsive rich text data.
2. Responsive rich text toolbar.
3. Responsive rich text editor.

Quirks:
- Right now, the page just refreshes if we press ENTER/carriage return on the editor. ENTER/carriage return only works when the cursor is on text that does not contain any styling. This is also a "to-do" task.
- We must click the "PreSave (Load to Buffer)" button first before clicking the "Final Save" button, otherwise the changes made in the editor will not get transferred to the server as part of the component buffer.

Fluid Page with WYSIHTML5 Display Prototype:



We can see how the rich text displayed on this page in a HTMLAREA is responsive!

Demo Videos!!

WYSIHTML5 Responsive Rich Text Editor (click here to view video in a new tab):

WYSIHTML5 Responsive Rich Text Display (click here to view video in a new tab):

I just wanted to share this project with the PeopleSoft community! A lot of javascript hacking and app designer cheats (workarounds if you will) were required to get this prototype to function. I would love to work with anyone who would like to collaborate on improving this project and see where the results take us! Perhaps a truly integrated Responsive Rich Text Editor… Perhaps a futuristic Web Based Responsive Page Development Utility… Perhaps a case for productization and potential incorporation into the PeopleSoft solution!?!?!?

Project Details:

Disclaimer: I am sharing the project primarily to seek collaborators and others who might be interested in playing with or extending this prototype. If you choose to perform any of below steps then it is at your own risk! :)

Project Environment: HCM 9.2 PUM Image 9 - PeopleTools 8.54.08

1. Download the project by clicking here.
2. Unzip/extract the project and copy it to a testing/play environment (using 'Copy From File' option in App Designer).
3. Build project.
4. Explore! Test! Explore! Test!

Notes:

1. This project which contains the WYSIHTML5 editor prototype for PeopleSoft should be considered a proof of concept only. Please do not load this into your production environment. This was purely intended for experimentation and evaluation purposes.
2. I, the author, will not assume any liability for any problems resulting from the implementation of this project.
3. All objects in the project are custom and start with the prefix "CSK_".
4. A role (CSK_WYSIHTML5_TEST) in the project should give access to both the pages above.

Please feel free to comment on this post if you have any questions/concerns/suggestions.

Oracle OpenWorld 2015 Conference

$
0
0
Oracle OpenWorld is starting on Sunday, October 25th!!

I will be presenting the following session on Sunday, Oct 25, 9:00 a.m. | Moscone West—3009:
WhenIntegrationBroker Is Not Enough [UGF1786] 

I look forward to catching up with any fellow bloggers/readers who are also attending/presenting!

PeopleTools 8.54+ - Branding - Part 4D - Customizing DEFAULT_THEME_TANGERINE_ALT Theme (Continued)

$
0
0
A very interesting and valid question was asked in one of my previous branding articles.

In short, how to conditionally hide certain parts of the branding (such as drop down navigation, greetings messages, etc.) based on the PeopleSoft site that is being accessed. This is specifically to address tailored branding for external sites such as the Candidate Gateway for HCM 9.2, the Supplier Portal for FSCM 9.2, etc.

Traditionally such external sites are created as separate site on the web server (which uses a different web profile as well). Additionally, the hostname of these sites might also be different.

E.g.:

Regular URI:
https://test.com/psp/HCMPRD/EMPLOYEE/HRMS/...
External URI:
https://test.com/psp/HCMPRD_CG/EMPLOYEE/HRMS/...
or
https://test-cg.com/psp/HCMPRD_CG/EMPLOYEE/HRMS/...

I am not aware of a delivered method to assign different styles/themes using the Branding Configuration options in PeopleTools 8.54 (at the application level without using Interaction Hub).

Here is one method to achieve this requirement.

Note: I am using a custom theme based on DEFAULT_THEME_TANGERINE_ALT (continuing on my Branding Part 4 series). The same steps should work for anyone using a custom theme based on DEFAULT_THEME_TANGERINE.

Using conditional javascript based on request URI

- Create Custom Javascript Object


Script:

// Conditionally hide the Navigation Menu (Breadcrumb) for external site

var uriString = location.href;

// Search for something unique (hostname/sitename) to the external site in the URI
if (uriString.indexOf("pi012.hcm92.com:8000/psp/ps_") >= 0) {

   var menu = document.getElementById("ptdropdownmenu");
   menu.style.display = "none";

}


Updated on Nov 15, 2015 - Start:

Optional Script using jQuery:

   
var $jq = jQuery.noConflict();

$jq(document).ready(function(){


   // Conditionally hide the Navigation Menu (Breadcrumb) for external site
   var uriString = location.href;
   if (uriString.indexOf("pi012.hcm92.com:8000/psp/ps_") >= 0) {
      $jq("#ptdropdownmenu").hide();
   }
    
});


Updated on Nov 15, 2015 - End:


Note: In my example, since I don't have an external site, I am just using my regular site with an underscore (for those cases where I use a new window option). Replace the highlighted section with something that uniquely differentiates your external site (e.g.: candidate gateway) from the regular site.

- Include custom javascript in the Branding Header

I included the custom javascript in the Branding Header instead of the Branding System Options. This is because, if I include the javascript in the Branding System Options, it is firing before the DOM is ready. To get around the problem, I included the javascript at the end of the Branding Header which will make sure that the javascript fires only after the DOM element (which we want to manipulate) is ready.










- Test Changes

ptdropdownmenu displaying when URL contains sitename (ps) without underscore



ptdropdownmenu hidden when URL contains sitename (ps_) with underscore


Note: There might be several other options that are available to meet this requirement. So please evaluate and test if this solution works for you before implementing it in your production environment.

Oracle SQL: REGEX_REPLACE Function

$
0
0
Recently, I participated in a forum discussion (Higher Education User Group) where someone asked if there is a way (and if so how) to strip out HTML elements from a long character field. This is mainly for scenarios where a long character field is used to store rich text enabled data (which contains HTML elements). And while querying the data from this field either using PS Query or SQL the requirement is to only retrieve the "plain text".

I found that we could use a delivered Oracle SQL function called REGEX_REPLACE to pattern match and replace contents of a string.

Here are some examples of how to use this function:

If we want to mainly get rid of HTML elements then we can use the following pattern:

select REGEXP_REPLACE(DESCRLONG, '<[^>]+>|\&(nbsp;)|\&(nbsp)|(amp;)', '',1,0, 'i'), DESCRLONG from PSMSGCATDEFN where descrlong like '%<%>%';

If we additionally want to get rid of contents inside script/style elements then we can use the following pattern:

select REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE(DESCRLONG, '<script[^>]*>.*</script>', '',1,0,'in'), '<style[^>]*>.*</style>', '',1,0,'in'),'<[^>]+>|\&(nbsp;)|\&(nbsp)|(amp;)', '',1,0,'i'), DESCRLONG from spsoft.PSMSGCATDEFN where descrlong like '%<%>%';

Note:
- You will need to improvise the regex pattern for those cases which are not trapped in the above sample SQLs.
- This function REGEX_REPLACE only works on Oracle databases.
- I have to admit that I am not a RegEx expert and received help from some very talented colleagues who helped me with the second (more complex) SQL.

PeopleTools 8.54+ - Branding - Part 5B - Fluid Branding (Continued)

$
0
0
Before I start this post, I must apologize for the delay. This post has been on my "to do" list for a very long time but unfortunately other priorities had pushed it back. I finally managed to find time to go over some of the additional ("more advanced") topics that I wanted to cover on Fluid Branding continuing on my previous post Part 5A (using HCM 9.2 PUM Image 12 - PeopleTools 8.54.08).

It is common knowledge by now that there are several new configurable branding capabilities coming our way in PeopleTools 8.55 - particularly for Fluid. I learnt from various presentations at Oracle OpenWorld 2015 that moving forward - starting from PeopleTools 8.55 - there will be only one Branding (or in other words navigation experience) and it would be Fluid based. With that said, I still feel that this post would be useful/relevant for several folks who are currently on PeopleTools 8.54 or planning to upgrade to PeopleTools 8.54. Given that PeopleTools 8.55 has an expected GA perhaps by end of this year or early next year, it would still be a while before everyone gets in on the uptake!

Before I dive deeper, I want to share couple of topics (utilities) which will help us with some of the more advanced branding requirements.

Global JavaScript Injection Bootstrap for Fluid UI:

In my previous branding posts, we saw how we could inject custom style sheet overrides for Fluid UI using the online configuration options available in PeopleTools 8.54 (Assemble Themes - Global Override Style Sheet - follow the link for more details). This online configuration provides a mechanism to easily override delivered styles without any customizations.

But one of the major let downs with Fluid in 8.54 (at least from my perspective) is the fact that there is no way to inject javascript globally using a configuration (similar to style sheets). If we recall from my previous posts, we used the Branding System Options to inject Google Analytics javascript globally across the application for classic components (follow the link for more details). Once again, this online configuration ensures that the listed javascripts are injected in all components without any need for customizations. This helps us to avoid some of the hacks we used in the past for such injection e.g.: customizing the delivered javascript objects (PT_COMMON, PT_PAGESCRIPT, etc.). But unfortunately, the javascripts listed under 'Branding System Options' are not getting injected into the Fluid UI components.

Another disappointment for me (with regards to Fluid in PeopleTools 8.54) was that the jQuery and jQuery UI javascripts that were delivered for classic (injected globally as part of the Branding Header Definition - refer screenshot below) are NOT part of any of the Fluid UI pages/components. This is exasperated by the fact that we cannot really inject our custom javascript objects globally into Fluid!


The ability to inject javascript objects is very important for performing some of the more advanced branding tasks (which should be reasonably clear from the my preceding introduction and examples). With that in mind, I wanted to create my own framework (or bootstrap if you will) to inject custom javascript objects into Fluid UI pages. I am sure there are several ways to "skin the cat" but here are the principles or drivers for my approach:

- Should be least intrusive from a customization point of view. That is to customize the least amount of objects.
- Should be highly configurable. That is to build a bootstrap configuration that allows us the flexibility to dynamically add/remove javascripts objects online (on the fly) without repeatedly customizing.

Note: I ended up adding one line of custom code to a delivered PeopleCode object. Other than that, this framework is entirely configurable online (using the Branding Objects page).

Step 1: Create a custom javascript object

Navigation: Main Menu > PeopleTools > Portal > Branding > Branding Objects (JavaScript Tab)

Note: This javascript object needs to be added online so that it provides a configuration to inject additional javascript objects.

Let us create CSK_FL_BOOTSTRAP_JS as shown in the screenshot below. I will explain the placeholder javascript later as we start injecting other javascripts (using this javascript as a configuration).


Placeholder JavaScript Code - Updated on 20160403:

Updated on 20160403: I found a better way to dynamically retrieve the site name using the delivered getSiteName function (part of PT_COMMON javascript object) which seems to be a lot more efficient than my previous approach.

// This section was commented on 20160403
// Conditional logic for site name which might vary based on current DB instance;
// var dbname = String('%dbname').toUpperCase();
// if (dbname == "HCM92012")
// {
//   var site = "ps";  
// }
// Repeat preceding logic for other instances (DEV, TEST, QA & PROD);
// This section was commented on 20160403

// This line was added on 20160403
// Use delivered getSiteName function for dynamically retrieving the site name for different environments.
var site = getSiteName();

 
// -- NOT REQUIRED (20160403) -- Repeat preceding logic for other instances (DEV, TEST, QA & PROD);
// E.g.:
// if (dbname == "HCMDEV")
// {
//    var site = "psdev";  
// }

// Inject javascript(s);


Step 2: Add custom code to PT_HEADERPAGE.Activate (Page Activate PeopleCode)

PT_HEADERPAGE is a header page that is part of all Fluid UI components and is mainly used for navigation purposes. We will be adding a line of code to inject our bootstrap javascript using peoplecode.


Custom PeopleCode:

/* CSK Custom Javascript Bootstrap for Fluid - Start */
AddJavaScript(HTML.CSK_FL_BOOTSTRAP_JS);
/* CSK Custom Javascript Bootstrap for Fluid - End */


Step 3: Inject Javascript

Now that we have our custom javascript object (CSK_FL_BOOTSTRAP_JS) injected into all Fluid UI components, we can use that as a configuration to further inject other javascript objects.


Custom JavaScript (CSK_FL_BOOTSTRAP_JS):

// This section was commented on 20160403
// Conditional logic for site name which might vary based on current DB instance;
// var dbname = String('%dbname').toUpperCase();
// if (dbname == "HCM92012")
// {
//   var site = "ps";  
// }
// -- NOT REQUIRED (20160403) -- Repeat preceding logic for other instances (DEV, TEST, QA & PROD);
// This section was commented on 20160403

// This line was added on 20160403
// Use delivered getSiteName function for dynamically retrieving the site name for different environments.
var site = getSiteName();


// Inject javascript(s);


// jQuery - PT_JQUERY_1_6_2_JS;
document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_PTBR.ISCRIPT1.FieldFormula.IScript_GET_JS?ID=PT_JQUERY_1_6_2_JS' type='text/javascript'%3E%3C/script%3E"));

// CSK Fluid Image Replacement JS;
document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_PTBR.ISCRIPT1.FieldFormula.IScript_GET_JS?ID=CSK_FL_IR_JS' type='text/javascript'%3E%3C/script%3E"));
 

  • The reason I am using the delivered IScript (IScript_Get_JS) in conjunction with document.write is because I am not able to use %JavaScript meta-HTML functions in javascript objects (in the same fashion as we do in HTML objects). Perhaps a future enhancement if anyone from Oracle is listening? :)
  • The delivered IScript provides a way to resolve the javascript (at runtime) to the URL suitable for referencing the .js file on the web server (cache directory).
  • I am using the custom variable site as a mechanism to make this javascript production ready and database refresh proof. This would allow the javascript to dynamically determine the sitename using variable substitution instead of hardcoding.

In the above example, you can see that I used the javascript object, CSK_FL_BOOTSTRAP_JS, as an online configuration to inject additional javascript objects with the following line of code.

document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_PTBR.ISCRIPT1.FieldFormula.IScript_GET_JS?ID=PT_JQUERY_1_6_2_JS' type='text/javascript'%3E%3C/script%3E"));


IScript for Image Object Source URL Resolution:

If we look into the WEBLIB_PTBR.ISCRIPT1.FieldFormula, we will find several useful IScripts similar to IScript_GET_JS that we used in the preceding section.

Since using meta-HTML such as %Image and %JavaScript does not seem to work in JavaScript objects, I tried to see if there was an IScript which might possibly return the URL suitable for referencing an image object on the web server (loaded on the cache directory). I did not find any delivered IScripts that did something like that so I wrote my own version.

WEBLIB_FL_CSK.ISCRIPT1.FieldFormula - IScript_Set_Image_URL_Variable


PeopleCode for Reference:

Function IScript_Set_Image_URL_Variable
 
   Local string&var = %Request.GetParameter("var");
   Local string&img = %Request.GetParameter("img");
  
   Local string&html = GetHTMLText(HTML.CSK_IMAGE_URL_JS, &var, &img);
  
   %Response.Write(&html);
  
End-Function;


HTML Object - CSK_IMAGE_URL_JS


Let us see this in action. Let us create our custom javascript object.

Navigation: Main Menu > PeopleTools > Portal > Branding > Branding Objects (JavaScript Tab)



JavaScript for Reference:

// Get Image URL for CSK_LOGO;
document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_FL_CSK.ISCRIPT1.FieldFormula.IScript_Set_Image_URL_Variable?var=cskLogo&img=CSK_LOGO_SVG' type='text/javascript'%3E%3C/script%3E"));


// Print variable using jQuery once the document is ready;
var $jq = jQuery.noConflict();


$jq(document).ready(function(){
  alert(cskLogo);
});


What does this JavaScript do?
- Calls IScript (IScript_Set_Image_URL_Variable) and passes two variables (var - variable name to store image URL; img - image object name).
- Prints variable using jQuery once the document is ready for testing purposes.

Note: I previously injected the delivered jQuery javascript PT_JQUERY_1_6_2_JS object which is how I am able to use jQuery in the above javascript.

Let us now inject this javascript into Fluid UI using the Fluid Bootstrap javascript created in the previous section.


Now if we try to access any Fluid content then we should get the alert message that displays the variable cskLogo with the relative image URL substitution.


We can also access the IScript directly on the browser to see what it does behind the scenes.


In the next post, I intend to cover some advanced Fluid branding concepts such as image replacement techniques without customizations (using the utilities detailed in this post) and more. Stay tuned!

Note: You could enhance the utilities detailed in this post by writing your own custom meta-HTML which is a topic described in great detail by Jim Marion in his book,  PeopleSoft PeopleTools: Tips and Techniques - Chapter 9 - Page 350.

Implementing no CAPTCHA reCAPTCHA in PeopleSoft

$
0
0
This post is based on a great discussion concerning security on the OTN forums.

The requirement was to solve the problem of bots/hacker websites hijacking users to their malicious locations (masquerading the legitimate PeopleSoft site), scraping the credentials from the users and then posting the data into the PeopleSoft signin page in a typical phishing attack scenario.

If you read through the discussion, you will notice some very valid questions, concerns and suggestions provided by Greg Kelly from Oracle and others around how to ensure that such phishing emails and attacks can be prevented.

Outside of that discussion, traditionally CAPTCHA has been used in several websites to prevent bot attacks. Now Google's reCAPTCHA project is being used more commonly since its inception in 2009. The latest version (no CAPTCHA reCAPTCHA) has significant user experience improvements. Additionally, the reCAPTCHA API version 2.0 is now a RESTful API which makes server side validation a lot easier. Another great incentive to use Google's no CAPTCHA reCAPTCHA is the fact that it is FREE!

Before going down the path of implementing reCAPTCHA, please consider accessibility and user experience implications and test accordingly. Click here for an article that talks about accessibility features of reCAPTCHA.

Here are the steps to implement Google reCAPTCHA API version 2.0 in PeopleSoft.

Note: I am currently using a HCM 9.2 PUM Image 12 - PeopleTools 8.54.08.
Reference Document: Developer's Guide

Step 1: Sign up for an API key pair

Please click here to sign up on the Goolge reCAPTCHA website. Once you sign up for an API key pair to your site, you will be provided with two keys - secret key and site key.

Step 2: Client side integration

In this case, let us assume that we want to add reCAPTCHA to the PeopleSoft signin page. So the signin page will be our client side content where we would add the reCAPTCHA code.

Here are the instructions from the Google reCAPTCHA documentation:


Let us add the above code snippet to the PeopleSoft signin page (signin.html).

Note: We can locate the signin.html file in the following directory on the web server.
<PIA_HOME>/webserv/<DOMAIN>/applications/peoplesoft/PORTAL.war/WEB-INF/psftdocs/<site_name>/

Add the following script inclusion code just before </HEAD> as shown:
<!-- CSK reCAPTCHA - Start -->
<script src='https://www.google.com/recaptcha/api.js'></script>
<!-- CSK reCAPTCHA - End -->


 Add the following div (reCAPTCHA) in an appropriate location on the content page. I chose to add it right before the submit button which could be referenced by <input name="Submit" type="submit" title="<%=137%>" class="ps-button" value="<%=137%>">.

<!-- CSK reCAPTCHA - Start -->
    <div class="g-recaptcha" data-sitekey="<ENTER_YOUR_SITE_KEY_HERE>"align="center"></div>
    <br/>
<!-- CSK reCAPTCHA - End -->


Note: If you are on PeopleTools 8.54 then you might also want to perform the same customizations to signin_fmode.html file as well. This is due to a known issue that will be fixed in PeopleTools 8.55. Refer: E-FLUID - Fluid HomePage Sign Off Link Calls fmode=1 in URL, Skips Custom signout.html Page (Doc ID 2001761.1).

Please bounce and clear the cache on your web server domains. Let us now see the reCAPTCHA plugin in action on the client side.






We are not done yet! Once verified, the reCAPTCHA integration would additionally add a string with the name "g-recaptcha-response" to the payload when the user submits (form post). This string would be a key that is generated specifically for our site. The string needs to be validated on the server side which we will explore in the next section.

Step 3: Server side integration/validation

This is the step where we verify the string provided by reCAPTCHA for validity by making a REST API call. Instructions from Google reCAPTCHA documentation.


For more details: Refer API documentation.

In this case, since we are trying to validate the reCAPTCHA response string provided by the PeopleSoft signin page, the best place to add the validation logic would be in the SignOn PeopleCode.

Let us now add a new row/entry in the sequence of Signon PeopleCode events as shown in the following screenshot. I am referencing a custom function name which I will explain shortly.


Record: CSK_RECAPTCHA
Field Name: FUNCLIB
Event Name: FieldFormula
Function Name: CSK_RECAPTCHA_CHECK

Note: After making any changes to Signon PeopleCode we must bounce the app servers for them to take effect.

Now let us see how to write some custom code to validate the reCAPTCHA response string. For reference, I pasted the entire peoplecode at the very end of this post.

Click on image to zoom in!


Note: In this case, I am using Apache Commons HttpClient Java Libraries to make the REST API call. Please refer to my previous blog posts that have more details on this topic (Part I and Part II).

Details on custom function validate_reCAPTCHA_JSON is provided below. For the purposes of JSON parsing, I am using a server side scripting technique described by Jim Marion in his blog post

Click on image to zoom in!


Message Catalog Entry that contains the JSON Parsing Script:


Script for reference:

var result = (function() {

     var json = JSON.parse(json_string);

     if (json.success) {
          return "true";
     } else {
          return "false";
     }

}());


This completes our server side integration/validation. Now we are relatively free of bot attacks! :)

Note: The same feature can be applied to any content page within the PeopleSoft application as well. If not easier, the effort should be the same as what we just went through in this post.

PeopleCode Functions for reference:

Function validate_reCAPTCHA_JSON(&json As string) Returns boolean;
  
   Local string &success;
  
   /* Instantiate ScriptEngine Manager and Engine objects */
   Local JavaObject &manager = CreateJavaObject("javax.script.ScriptEngineManager");
   Local JavaObject &engine = &manager.getEngineByName("JavaScript");
  
   /* Pass JSON string */
   &engine.put("json_string", &json);
   /* Get JSON Parse JavaScript from Message Catalog */
   Local string &jsFunction = MsgGetExplainText(26000, 1, "NONE");
  
   If &jsFunction <> "NONE" Then
      &engine.eval(&jsFunction);
      &success = &engine.get("result").toString();
   End-If;
  
   If Upper(&success) = "TRUE" Then
      Return True;
   Else
      Return False;
   End-If;
  
End-Function;

Function CSK_RECAPTCHA_CHECK()
  
   /* Get reCaptcha parameter from the Request */
   Local string &reCAPTCHA = %Request.GetParameter("g-recaptcha-response");
  
   If &reCAPTCHA = "" Then
      /* Fail Authentication */
      SetAuthenticationResult( False, %SignonUserId, "", False);
   Else
      /* Do further validation if required. Refer: https://developers.google.com/recaptcha/docs/verify */
      /* Post user's reCAPTCHA response and server's private key to API: https://www.google.com/recaptcha/api/siteverify */
      try
        
         /* Using Apache HttpClient for REST - Post Method */
         Local JavaObject &jHttp, &jMethod, &filePart, &partArray, &mPartReqEntity;
        
         /* Initialize HttpClient and set parameters */
         &jHttp = CreateJavaObject("org.apache.commons.httpclient.HttpClient");
         &jHttp.getHttpConnectionManager().getParams().setConnectionTimeout(20000);
        
         /* Initialize PostMethod */
         /* !!!!!! Avoid hardcoding !!!!!!!! Replace below URL with a URL definition that is configurable. */
         Local string &sURL = "https://www.google.com/recaptcha/api/siteverify";
         &jMethod = CreateJavaObject("org.apache.commons.httpclient.methods.PostMethod", &sURL);
         &jMethod.setFollowRedirects( False);
        
         /* Add Multi-Part Message - Start */
         /* Create String Part - secret */
         &secretPart = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.StringPart", "secret", "<ENTER_YOUR_SECRET_KEY_HERE>");
         /* Create String Part - response */
         &responsePart = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.StringPart", "response", &reCAPTCHA);
         /* Add Parts to Part Array */
         &partArray = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.Part[]", &secretPart, &responsePart);
         /* Create Multi-Part Request Entity */
         &mPartReqEntity = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity", &partArray, &jMethod.getParams());
         /* Add Multi-Part Request Entity to the Post Method */
         &jMethod.setRequestEntity(&mPartReqEntity);
         /* Add Multi-Part Message - End */
        
         /* Invoke PostMethod */
         Local integer &return = &jHttp.executeMethod(&jMethod);
         Local string &responseBody = &jMethod.getResponseBodyAsString();
        
         If (validate_reCAPTCHA_JSON(&responseBody)) Then
            /* reCaptcha success: allow user */
            SetAuthenticationResult( True, %SignonUserId, "", False);
         Else
            /* reCaptcha failure: deny */
            SetAuthenticationResult( False, %SignonUserId, "", False);
         End-If;
        
      catch Exception &ex
         /* Unknown Exception */
         SetAuthenticationResult( False, %SignonUserId, "", False);
      end-try;
   End-If;
End-Function;

 

PeopleTools 8.54+ - Branding - Part 5C - Fluid Branding (Continued)

$
0
0
This is a continuation of my previous posts on PeopleTools Fluid Branding: Part 5A and Part 5B.

Using jQuery to override Fluid Branding Images and Icons:

Those who read my previous post (Part 5A) would realize that in order to override the delivered images and icons on the Fluid Branding we ended up customizing some of the Fluid pages and subpages. We did that because all those images and icons were referenced directly on the page field properties of the Fluid header/footer.

The question is whether we can use CSS, javascript or a combination of both to override these images and icons? The answer is yes but I would continue to ask the question if the juice is worth the squeeze? Do we really need all this additional client side code/overrides just to avoid a handful of customizations to page field properties? I will let you make that determination depending on your circumstances and environment.

In this section I will try to provide an alternative option using jQuery to avoid making customizations for image/icon overrides. You could also achieve the same using pure CSS, javascript or both but I find the jQuery library quite useful for such DOM manipulation.

As an example for the purpose of this section, I reverted the change I made previously to override the Fluid home logo image. Now the page field property is as delivered and we can see the Oracle logo on the Fluid homepage when we login.

App Designer > File > Open > Page > Select: PTNUI_LP_HEADER



In my previous post (Part 5B), I detailed how I created a online configuration framework to inject javascripts into Fluid UI. I used this framework to inject jQuery (PT_JQUERY_1_6_2_JS) and my custom javascript object (CSK_FL_IR_JS) for image replacement.


Now let us take a look at the javascript object CSK_FL_IR_JS.


In this javascript, I called an IScript that would resolve the suitable URL on the web server (cache directory) for the custom image object CSK_LOGO_SVG and store it in a javascript variable called 'cskLogo' (refer Part 5B for more details). Then I used jQuery to set/override the 'src' attribute for the image element with id 'PTNUI_LP_HEADER_PTNUI_LOGO'.

JavaScript for reference:

// Get Image URL for CSK_LOGO;
document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_FL_CSK.ISCRIPT1.FieldFormula.IScript_Set_Image_URL_Variable?var=cskLogo&img=CSK_LOGO_SVG' type='text/javascript'%3E%3C/script%3E"));

var $jq = jQuery.noConflict();
$jq(document).ready(function(){

  $jq('#PTNUI_LP_HEADER_PTNUI_LOGO img').attr('src', cskLogo);

});


Now we can test the changes and see how we could simply override the source attribute of an image using jQuery to avoid customizations to page field properties.


Creating an environment specific header for Non-Production databases:

This section is intended to help us avoid what I like to call "testing in production"! I am sure we have all worked in IT long enough to realize that accidents happen. I have seen many cases where we end up making changes in the production environment without realizing we are in production (causing all sorts of issues). This typically happens when we have end users and/or testers working on multiple environments across multiple browser windows. Traditionally, most organizations (with PeopleSoft applications) tend to add some visual cues (such as writing the database name on the header) to indicate/differentiate the fact that the user is currently logged in to a test environment.

In Classic UI, we had plenty of real estate in the branding header to add the database name. In Fluid UI, since we might not have enough wiggle room in the delivered header we will need to be a bit more creative. My approach to this requirement for Fluid is to add an additional custom header (that can be hidden - in cases were we want to take screenshots for job aids, etc.). While it does take up a small portion of the real estate, this was the least intrusive method that I could think of (without affecting existing functionality around the Fluid branding header).

Step 1: Create custom javascript object


This custom javascript object uses the jQuery library to add (using 'prepend' method) a custom div to the beginning of the delivered header element with id='PT_HEADER'.


Custom div structure:
div (id = cskdbnamecontainer)
- Text with database name (id = cskdbname)
- 'Hide' link to remove the header if required (id = cskdbnamehide)

Additionally, the javascript object (CSK_FL_DBNAME) also contains code to remove the custom div (cskdbnamecontainer) when we click on the 'Hide' link.

Javascript for reference:

// Display Database Name using jQuery once the document is ready;

var $jq1 = jQuery.noConflict();

$jq1(document).ready(function(){

   // Add div to display DB Name;
   $jq1( "#PT_HEADER" ).prepend( "<div id='cskdbnamecontainer' align='center'><span id='cskdbname'>Test Environment: %dbname</span><a href='#' id='cskdbnamehide'>Hide</a></div>" );

   // Add jQuery to hide the DB Name when the 'Hide' link is clicked;
   $jq1("#cskdbnamehide").click(function(){
         $jq1("#cskdbnamecontainer").hide();
   });

});


Step 2: Inject custom styles

In part 5A, we saw how we could inject custom styles into Fluid UI. Now let us add some additional custom styles to CSK_FLUID_CSS style sheet object so that it gets injected at runtime.


Custom styles for reference:

/* Fluid - Display DBName for non-Prod environments */
#cskdbnamecontainer {
   height: 26px;  
   background-color: rgb(204,204,204);
}
#cskdbname {
   color: rgba(229,47,0,1);
   line-height: 26px;
   font-weight: bold;
   padding-right: 10px;
}


Step 3: Inject custom javascript CSK_FL_DBNAME into Fluid UI

Let us inject this javascript for all non production databases (we don't want to display this in production).


Javascript injection snippet for reference:

// CSK Add Custom Environment Header;
if ("%dbname" !== "PROD_DBNAME") {

  document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_PTBR.ISCRIPT1.FieldFormula.IScript_GET_JS?ID=CSK_FL_DBNAME' type='text/javascript'%3E%3C/script%3E"));

}


Now we are ready to test this change.




If we click on the 'Hide' link on the custom header, then the entire div gets removed as shown below.



Adding Custom Links to Fluid Branding:

In my previous posts (Part 3 and Part 4B), we saw how we could add custom links to the Classic Branding Header. In this section, I will detail how we can add custom links to the Fluid Branding. Fluid Header as such has very limited real estate (unlike Classic), so we need to find the appropriate location to add the custom links without adversely affecting any of the delivered functionality. The best way to add custom links (with minimal impact) would be as additional list items on the "Action Menu" aka the "Hamburger" icon.



Let us say, we want to add a custom link to an external website which should be available on all Fluid Pages (including the Landing Page).

How do we add a custom link to the Fluid "Action Menu"? First, we need to figure out how the Action Menu is getting generated. If we open PT_HEADER_ACTION page in Application Designer then we can see that all delivered links are list on this page. We can also see that each delivered link is wrapped in a group box and contains specific styling. The links on the PT_HEADER_ACTION page are additionally controlled via JavaScript, CSS media queries and/or PeopleCode to display/hide links according to the device form factor. In our case, we want our custom link to always appear on all pages regardless of device form factor.


Notice there is a small area right at the top of the page which contains a "Custom Action" group box? It appears that Oracle has already anticipated the need for custom Action Menu links and provided a placeholder group box. Let us see how we can add our custom link(s) into this group box.

Step 1: Create Custom Subpage

Instead of directly adding our custom links to the PT_HEADER_ACTION page, let us create a custom subpage so that it acts as a container for all the custom links on the Fluid Branding.

The custom subpage (CSK_HEADER_ACTION) contains just two fields (one groupbox for styling and one hyperlink which is the custom link).



Page Field Properties for Group Box "CSK Home":

Add 'Default Style Name' as ps_menuitem.


Page Field Properties for Hyperlink "CSK Home":

Set the Hyperlink Destination to 'PeopleCode Command' so we can control the OnClick event using the FieldChange PeopleCode.


Always better to use a Message Catalog entry for Labels.


Step 2: Write Custom PeopleCode for the Custom Link FieldChange Event


PeopleCode for Reference:

Local string&redirectURL;

&redirectURL = GetURL(URL.CSK_FLU_HOME_ACTION_ITEM);

%Response.RedirectURL(&redirectURL);


URL Definition for Reference:


Step 3: Add Custom Subpage to PT_HEADER_ACTION


We are now ready to test these changes.




Note: The above steps detail how we can add custom links to Fluid universally across the application (for all pages). If you want to add custom links to a specific page (custom or delivered) only, then you can follow the approach used on PT_LANDINGPAGE (delivered page) to add the 'Personalize' link.


Considering Small Form Factor Logo for Fluid Branding:

If you used the approach detailed in Part 5A for overriding the Fluid Homepage Logo then you might have noticed that the logo for small form factor (SFF) devices revert back to another delivered image (PTNUI_ORACLE_LOGO_SFF).


This delivered image is generated by some runtime PageActivate PeopleCode.


We have two options to override this small form factor image.

Option 1: This applies for anyone currently using the customization approach detailed in Part 5A. We can simply customize PT_LANDINGPAGE.Activate (Page PeopleCode) to use our custom SFF image instead of the delivered as follows:


Option 2: Alternatively, if we use the jQuery image replacement technique detailed above then we can improvise the javascript to appropriately replace the logo depending on the form factor.

 Update CSK_FL_IR_JS as follows:


Updated javascript for reference:

// Get Image URL for CSK_LOGO;
document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_FL_CSK.ISCRIPT1.FieldFormula.IScript_Set_Image_URL_Variable?var=cskLogo&img=CSK_LOGO_SVG' type='text/javascript'%3E%3C/script%3E"));

// Get Image URL for CSK_LOGO (SFF);
document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_FL_CSK.ISCRIPT1.FieldFormula.IScript_Set_Image_URL_Variable?var=cskLogoSFF&img=CSK_LOGO_SFF_SVG' type='text/javascript'%3E%3C/script%3E"));

var $jq = jQuery.noConflict();
$jq(document).ready(function(){

  // Get current Image Source;
  var imageSrc = $jq('#PTNUI_LP_HEADER_PTNUI_LOGO img').attr('src');


  if (imageSrc != null) {
    if (imageSrc.indexOf("PTNUI_ORACLE_LOGO_SFF") < 0) {

      // Use Regular Image;
      $jq('#PTNUI_LP_HEADER_PTNUI_LOGO img').attr('src', cskLogo);

    } else {

      // Use Small Form Factor Image;
      $jq('#PTNUI_LP_HEADER_PTNUI_LOGO img').attr('src', cskLogoSFF);

    }
  }



});


Result:


Overriding the Favorite Icon for Fluid:

I am not sure if many of us noticed this but there is a delivered icon image (LOGO_FAVICON) on every browser tab beside the page title for all Fluid pages. This image/icon is called the Favorite Icon.



Someone has already asked Oracle on how to change this favorite icon image? According to Doc ID 2004996.1, currently there is no way to override this image other than updating the delivered image (LOGO_FAVICON) with a custom image using App Designer. Also, there might be plans to incorporate this as a configurable item in the future releases. You may choose to perform the steps detailed in the Oracle Support document.

Refer the following document on My Oracle Support for more details:
E:FLUID- How To Access Favicon On Fluid Landing Pages? (Doc ID 2004996.1)

I don't think I like the idea of replacing the delivered image LOGO_FAVICON (as suggested in Doc ID 2004996.1). There would be no way to identify that we made a customization since it is an image object.

Let us look at the option of using the jQuery image replacement technique detailed in the preceding section for overriding this delivered image LOGO_FAVICON.

Once again, I am updating my image replacement javascript object CSK_FL_IR_JS. I am finding all the occurrences of LOGO_FAVICON (delivered image) under head -> link (where href attribute contains LOGO_FAVICON) and replacing it with a custom image (CSK_LOGO_FAVICON) using jQuery.


Updated javascript (CSK_FL_IR_JS) for reference:

// Get Image URL for CSK_LOGO (FavIcon);
document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_FL_CSK.ISCRIPT1.FieldFormula.IScript_Set_Image_URL_Variable?var=cskFavIcon&img=CSK_LOGO_FAVICON' type='text/javascript'%3E%3C/script%3E"));

// Get Image URL for CSK_LOGO (Fluid);
document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_FL_CSK.ISCRIPT1.FieldFormula.IScript_Set_Image_URL_Variable?var=cskLogo&img=CSK_LOGO_SVG' type='text/javascript'%3E%3C/script%3E"));

// Get Image URL for CSK_LOGO (Fluid SFF);
document.write(unescape("%3Cscript src='/psc/" + site + "/EMPLOYEE/EMPL/s/WEBLIB_FL_CSK.ISCRIPT1.FieldFormula.IScript_Set_Image_URL_Variable?var=cskLogoSFF&img=CSK_LOGO_SFF_SVG' type='text/javascript'%3E%3C/script%3E"));

var $jq = jQuery.noConflict();
$jq(document).ready(function(){

  // Get current Image Source;
  var imageSrc = $jq('#PTNUI_LP_HEADER_PTNUI_LOGO img').attr('src');

  if (imageSrc != null) {
    if (imageSrc.indexOf("PTNUI_ORACLE_LOGO_SFF") < 0) {

      // Use Regular Image;
      $jq('#PTNUI_LP_HEADER_PTNUI_LOGO img').attr('src', cskLogo);

    } else {

      // Use Small Form Factor Image;
      $jq('#PTNUI_LP_HEADER_PTNUI_LOGO img').attr('src', cskLogoSFF);

    }
  }

  // Replace Browser Favorite Icon(s);
  $jq('head link[href*=LOGO_FAVICON]').attr('href', cskFavIcon);

});


We are ready to test these changes now. We can see from the screenshot below that all occurrences of LOGO_FAVICON (delivered image) have been replaced with CSK_LOGO_FAVICON (custom image).

What is ComponentLife variable declaration?

$
0
0
A few months ago, I came across some peoplecode which had variables declared as ComponentLife. Intrigued, I tried to look it up in PeopleBooks but could not find anything that describes this declaration. Then I raised a SR with Oracle Support seeking clarification and after many days of back and forth and pestering, I finally received some information that made a little sense. This was also documented in Doc ID 2089442.1 (My Oracle Support) later. The information provided in this document is still not self explanatory so I thought I would share a little example that demonstrates how it works and how it differs from a Component variable declaration.

From Doc ID 2089442.1:

"ComponentLife is added for NUI search,.A new type of component PC object “ComponentLife” for search page is used to create the PC application objects. They will be in component scope.

The difference between the Component and Componentlife is that Component scope is for the current row in the component, whereas ComponentLife scope is for all the records. These variable don't lose scope when you navigate from one row to another row. The scope is for the life of the component.
 

Please note that this scope is not recommended anywhere other than the Search use case." 

What I understood is that variables declared with a ComponentLife scope persist across search results. In contrast, variables declared with Component scope will only persist for the current search result.

Why would we need this? As mentioned in Doc ID 2089442.1, it appears that starting with 8.54, the NUI search uses this type of declaration a lot. Also, it seems like a very handy method to pass data across search results.

Note: This declaration only works with Fluid pages. I tried using ComponentLife in a Classic page but it does not work as expected.

I built a small Fluid page to demonstrate the way ComponentLife declaration works.

Test Fluid Page:

I built a fluid page for URL Definitions (Classic Version: Main Menu > PeopleTools > Utilities > Administration > URLs).



Test Fluid Component:

For the purposes of demonstration and saving time, I am using PT_SEARCHPAGE as a search page for my component which is not recommended by Oracle. Please refer Doc ID 2063953.1: E-FLUID: What is the PT_SEARCHPAGE Fluid Page and should it be used? before considering using this as a search page option for Fluid.






Search View:


SearchInit PeopleCode:

In the SearchInit PeopleCode, I declared and assigned a ComponentLife and a Component variable.


PageActivate PeopleCode:

In the PageActivate PeopleCode, I am just printing both the variables to see if the values persists.


Demo Video:

Check out this video >>>>ComponentLife Demo Video

Environment Details: HCM 9.2 PUM Image 12 - PeopleTools 8.54.08

Fluid - Custom Development - Small Form Factor and Viewport Considerations

$
0
0
While many of us are well underway in either implementing or supporting some of the delivered Fluid applications, it is not very common yet to hear about widespread custom Fluid development. This post might be a handy tip for those embarking on such activities currently or in the future. I also found that Javier has written a post on a similar issue.

As always, I find some really good learning opportunities in the Oracle Technology Network forums. In one such example, someone asked a question related to a custom Fluid page which does not render properly on a small form factor (SFF) device whereas delivered pages seem to be detecting the SFF and displaying correctly.

I realized that I had the exact same issue on one of my test Fluid pages. Here is the problem:

Delivered Fluid page in small form factor works as expected:


Custom Fluid page in small form factor does not display correctly:


The reason my custom fluid page was not rendering correctly is because it does not have appropriate viewport meta set in the code.

I fixed this by adding the following code in the Component PostBuild event:

Declare Function SetViewport PeopleCode PTLAYOUT.FUNCLIB FieldFormula;
SetViewport(""); /* apply the system default viewport setting */

The delivered SetViewport function either uses the viewport setting passed in as parameter or the default viewport setting for SFF/iOS.



The viewport information is added as a meta tag using the delivered AddMetaTag function.

We could also pass a custom viewport setting to the function as follows:

Declare Function SetViewport PeopleCode PTLAYOUT.FUNCLIB FieldFormula;
SetViewport("width=device-width,user-scalable=yes,initial-scale=1.0,minimum-scale=1.0"); /* apply the system default viewport setting */

Or simply use the AddMetaTag function directly as follows:

AddMetaTag("viewport", "width=device-width,user-scalable=yes,initial-scale=1.0,minimum-scale=1.0");

Result of adding viewport meta tag to my custom Fluid page:


It seems to me that using the delivered function SetViewport (with appropriate viewport parameter) might be the better way to go in general. This would take care of maintaining any default viewport values specific to certain devices.

HCM SOA Registry - Demystified

$
0
0
If you have worked on either HCM or Campus Solutions applications in PeopleSoft then you would have come across the term 'HCM SOA Registry'. Associated with the HCM SOA Registry is a step/process to 'Refresh Cache' which can either be done online or batch.

I have seen many customers (using HCM or Campus Solutions) who run this 'Refresh Cache' on a regular basis and sometimes as a post step to standard migrations. By standard migrations, I mean the weekly/fortnightly migrations which are part of production support release cycles and not necessarily the bundle/patch/upgrade migrations.

What is wrong with running this process regularly as a post step to any migration?

Well, nothing. But of late, I am finding several cases where the 'Refresh Cache' process fails with "RowsetCache::Save: Save failed for xxx/xxx=: unknown error. (2,975)" error particularly since HRMS 9.0 Bundle 26 (last HR bundle for CS).

Since this online/batch cache refresh has been causing a lot of pain, I wanted to find out when it is appropriate to refresh cache (reverse engineering and identifying the events - object changes - that would necessitate a refresh). I ended up building a SQL query to identify whether a migration of a project (say part of weekly/fortnightly production support release) would require a 'HCM SOA - Refresh Cache' just based on the objects it contains.

Before I share the details of the SQL query, I would like to share some of my notes since I did not find any information that was straight forward or easy to understand specifically on HCM Registry - Refresh Cache.

HCM SOA Registry:

HCM SOA Registry, like any other SOA Registry, provides a mechanism for service registration, discovery and binding.

SOA Registry Example:


Reference: Web 2.0 Architectures

HCM SOA Registry:


PeopleBooks Reference: Understanding the HCM Interface Registry

My Process/Flow Diagram: HCM SOA Registry

How do we access HCM SOA Registry?

Main Menu > Set Up HRMS > System Administration > HCM Registry

Service Registry:


Transformation Registry:


Where does HCM SOA Registry data get stored?

According to Doc ID 658098.1: HCM Service Framework Error When Adding, Updating, or Viewing Person Data in Campus Solutions:
"The HCM Service Registry (Set Up HRMS > System Administration > HCM Registry > Service Registry) captures the meta-data about the HCM SOA services: input and output signatures, implementation application classes, web services, component interfaces, etc. This meta-data is stored on the HC_REGISTRY portal (PeopleTools > Portal). This portal contains no other data."

How do we access this HC_REGISTRY portal where the HCM SOA Registry is stored?

- Navigate to Portal – Structure and Content: Main Menu > PeopleTools > Portal > Structure and Content.
- Replace the default portal (EMPLOYEE) with HC_REGISTRY in the URL.

For example:

https://www.test.edu/psp/ps/EMPLOYEE/HRMS/c/PORTAL_ADMIN.PORTAL_OBJ_LIST.GBL
>>>>
https://www.test.edu/psp/ps/HC_REGISTRY/HRMS/c/PORTAL_ADMIN.PORTAL_OBJ_LIST.GBL


HCM SOA Registry Hierarchy:


PeopleSoft Rowset Cache and how is it used by HCM SOA Registry?

- PeopleTools stores application data in a database cache to increase system performance.
- The RowsetCache contains a rowset, and serializes the contained rowset to binary form for speed.
- The RowsetCache class enables you to access this memory structure, created at runtime, and shared by all users.
- As with most PeopleTools objects, RowsetCache objects are cached to memory and file, but they are also cached to the data base.
- Rowset cache is stored in PSCONTDEFN and PSCONTENT.

PeopleBooks Reference:
PeopleSoft Rowset Cache
Using PeopleSoft Rowset Cache

According to Doc ID 658098.1: HCM Service Framework Error When Adding, Updating, or Viewing Person Data in Campus Solutions:
"The meta-data stored in the HC_REGISTRY portal is needed at run-time in order to execute the service. To speed up the retrieval of this meta-data at run-time, it is stored in cache, using PeopleTools Rowset Cache objects."

Layers of HCM Registry Metadata Caching:


App Server Cache*: As with most PeopleTools objects, Rowset cache also gets cached at the app server layer.

HCM Registry - Online Refresh Cache:
  • Main Menu > Setup HRMS > System Administration > HCM Registry > Service Registry > Refresh Cache
  • Refreshes HCM SOA Rowset Cache (PSCONTDEFN and PSCONTENT) with current HCM SOA metadata (HC_REGISTRY Portal).
HCM Registry - Batch Refresh Cache:
  • Main Menu > Setup HRMS > System Administration > HCM Registry > Refresh HCM SOA Portal Access.
  • Refreshes security on HC_REGISTRY portal.
    • Makes sure all folders and CREFs in HC_REGISTRY are PUBLIC.
    • DOES NOT add any roles. Adding a default role to all users is now a deprecated functionality. Refer: Doc ID 1370324.1 - FAQ on Refresh HCM SOA Portal Access - Question 1.
  • Refreshes HCM SOA Rowset Cache (PSCONTDEFN and PSCONTENT) with current HCM SOA metadata (HC_REGISTRY Portal).
SQL to identify if a migration (list of projects) requires a HCM SOA - Refresh Cache:

Based on the HCM SOA Registry Hierarchy diagram above, we can see that all metadata (HC_REGISTRY Portal) and interfaces(App Classes, SQL Views, Messages) are PeopleTools Managed Objects. So the below SQL looks at PeopleTools metadata to figure out if a list of projects (part of a release) contain any objects associated with HCM SOA Registry.

-- Test Value for &&1: 'HCM900_MP11_D','PRJ812865','PRJ889693','PRJ889694','PRJ882259'

/* HCM Registry Objects - Content References */
SELECT 'HC Registry objects (CREFs) found in release. Run SOA Refresh Cache.' AS Found,
  'HC_REGISTRY'                                                               AS OBJECT,
  OBJECTVALUE3                                                                AS PORTAL_OBJNAME
FROM PSPROJECTITEM A
WHERE A.projectname IN (&&1)
AND A.OBJECTTYPE     = 55
AND OBJECTVALUE1     = 'HC_REGISTRY'
UNION

/* Interface Objects - Application Classes (Services, Types, Exceptions) */
SELECT 'HCM metadata objects (services/types/exceptions) found in release. Run HCM SOA Refresh Cache.' AS Found,
  TO_CHAR(I.PORTAL_ATTR_VAL)                                                                           AS OBJECT,
  I.PORTAL_OBJNAME
FROM PSPRSMSYSATTRVL I
WHERE I.PORTAL_NAME   = 'HC_REGISTRY'
AND I.PORTAL_REFTYPE  = 'C'
AND I.PORTAL_OBJNAME IN
  (SELECT A.PORTAL_OBJNAME
  FROM PSPRSMSYSATTRVL A
  WHERE A.PORTAL_NAME   = 'HC_REGISTRY'
  AND A.PORTAL_REFTYPE  = 'C'
  AND A.PORTAL_ATTR_NAM = 'TYPE'
  AND TO_CHAR(A.PORTAL_ATTR_VAL) IN ('EXC', 'SRV', 'TYP')
  )
AND I.PORTAL_ATTR_VAL           like '%:%'
AND TO_CHAR(I.PORTAL_ATTR_VAL) IN
  (SELECT REPLACE (A.objectvalue1 | | ':' | | A.objectvalue2 | | ':' | | A.objectvalue3 | | ':' | | A.objectvalue4, ': ')
  FROM PSPROJECTITEM A
  WHERE A.projectname IN (&&1)
  AND objecttype       = 58
  )
UNION

/*
Interface Objects - Views */
SELECT 'HCM metadata objects (views) found in release. Run HCM SOA Refresh Cache.' AS Found,
  TO_CHAR(I.PORTAL_ATTR_VAL)                                                       AS OBJECT,
  I.PORTAL_OBJNAME
FROM PSPRSMSYSATTRVL I
WHERE I.PORTAL_NAME   = 'HC_REGISTRY'
AND I.PORTAL_REFTYPE  = 'C'
AND I.PORTAL_OBJNAME IN
  (SELECT A.PORTAL_OBJNAME
  FROM PSPRSMSYSATTRVL A
  WHERE A.PORTAL_NAME             = 'HC_REGISTRY'
  AND A.PORTAL_REFTYPE            = 'C'
  AND A.PORTAL_ATTR_NAM           = 'TYPE'
  AND TO_CHAR(A.PORTAL_ATTR_VAL) IN ('IVW')
  )
AND PORTAL_ATTR_NAM             = 'IMPLEMENTATION'
AND TO_CHAR(I.PORTAL_ATTR_VAL) IN
  (SELECT REPLACE (A.objectvalue1 | | ':' | | A.objectvalue2 | | ':' | | A.objectvalue3 | | ':' | | A.objectvalue4, ': ')
  FROM PSPROJECTITEM A
  WHERE A.projectname IN (&&1)
  AND objecttype       = 0
  )
UNION

/*
Interface Objects - HCM Transformation Maps */
SELECT 'HCM metadata objects (messages) found in release. Run HCM SOA Refresh Cache.' AS Found,
  TO_CHAR(I.PORTAL_ATTR_VAL)                                                          AS OBJECT,
  I.PORTAL_OBJNAME
FROM PSPRSMSYSATTRVL I
WHERE I.PORTAL_NAME   = 'HC_REGISTRY'
AND I.PORTAL_REFTYPE  = 'C'
AND I.PORTAL_OBJNAME IN
  (SELECT A.PORTAL_OBJNAME
  FROM PSPRSMSYSATTRVL A
  WHERE A.PORTAL_NAME             = 'HC_REGISTRY'
  AND A.PORTAL_REFTYPE            = 'C'
  AND A.PORTAL_ATTR_NAM           = 'TYPE'
  AND TO_CHAR(A.PORTAL_ATTR_VAL) IN ('TRF')
  )
AND PORTAL_ATTR_NAM            IN ('MSGNAME', 'TO_MSGNAME')
AND TO_CHAR(I.PORTAL_ATTR_VAL) IN
  (SELECT OBJECTVALUE1
  FROM PSPROJECTITEM A
  WHERE A.projectname IN (&&1)
  AND A.OBJECTTYPE     = 37
  );


If the query returns results then we need to run HCM SOA - Refresh Cache. If not, there is no need.

Note: This post is only focusing on the need (if any) for running the HCM SOA - Refresh Cache as a post step to migrations. This does not mean that there would not be other circumstances (outside of migrations) where the Refresh Cache might be necessary.

PeopleTools 8.55.x - Branding - Part I - What has changed?

$
0
0
PeopleTools 8.55 release packs a punch when it comes to new features. There are also some notable improvements to Branding in PeopleTools 8.55 building on the Branding framework that was previously delivered as part of PeopleTools 8.54.

In this post, I will cover some of my key findings at a high level and follow up with an additional article on some 'how-to' guides for common Branding tasks.

Note: This post assumes that the branding is applied to a stand-alone PeopleSoft application without the use of PeopleSoft Interaction Hub. There is a new Branding Activity Guide in PeopleSoft Interaction Hub Image 2 which provides a guided step-by-step process for customers to perform simple or advanced branding tasks and to publish the Branding Theme to other PeopleSoft applications in the cluster. Please refer to this Oracle blog post which highlights the latest Interaction Hub features and provides additional resources.

Unified Header:

This certainly deserves a mention because there may be some misconception that starting from 8.55 users are forced to use Fluid. The point to clarify and understand is that the only thing changing is the Branding header and the navigation mechanism. In 8.55, we now have the same header (hence the term unified) for both Classic and Fluid. With that, there is a shift in user navigation as well. That is, we would need to use the NavBar, Fluid Homepages, Dashboards, etc. to navigate around the application instead of using the traditional drop-down menu/breadcrumb navigation for Classic.

Matthew Haavisto from Oracle has detailed this in his blog entry with some references and how-to steps for those who might still want to use the Classic navigation.

Note: I updated the title of this section from 'Unified Header and Navigation' to just 'Unified Header'. I realize that 'Unified Navigation' is not a term to be used loosely as it may have a different meaning depending on whether we are using PeopleSoft Interaction Hub or not. Please refer to another blog post (again authored by Matthew Haavisto) which level sets these concepts.

Global Javascript Injection:

I previously wrote about the issue with custom javascript injection in Fluid pages. The same challenge still persists in 8.55. This means that any custom javascripts added to the Branding System Options does not work on the Fluid pages but it does on the Classic pages.

E.g.:

NavBar > Navigator > PeopleTools > Portal > Branding > Branding System Options


The test javascript CSK_TEST_JS contains a simple alert message.

NavBar > Navigator > PeopleTools > Portal > Branding > Branding Objects


Results in Classic: The javascript gets injected and the alert message is displayed.


Results in Fluid: The javascript does not get injected and the alert message is not displayed.


Workaround: We can still use the same workaround that I previously described here.

Global Style Sheet Injection:

The same issue exists for global style sheet injection using the Branding System Objects. But there is a delivered alternative to include custom styles to Fluid which I detailed in my previous post.

Theme Macro Sets for overriding Branding Elements:

I am saving the best for the last! This is definitely a great addition to the framework and I believe that it can only get better with future releases. In 8.55, we can now override some of the common Fluid Branding elements such as images, icons and styles with just configuration (macro sets). I previously detailed the complexity of overriding Fluid Branding elements in 8.54 (Part 5A and Part 5C).

PeopleBooks Reference: Defining Macro Sets and Macros

I will show you a teaser on how we can use the Theme Macro Sets to override the unified header (classic/fluid) branding logo image.

Before that we must start of with some housekeeping tasks to assemble a custom theme with custom homepage header, classic - theme style sheet and fluid - global override style sheet definitions. This would enable us to not only override the logo image but also to override subsequent Branding elements.

Step 1: Create Custom - Classic - Theme Style Sheet Definition

Note: We only need to perform this step if we intend to override some of the delivered styles for Classicwhile using Theme Macro Sets.

Clone delivered style sheet: PT_BRAND_CLASSIC_TEMPLTE_FLUID

Copy the entire contents on the freeform tab of the delivered style sheet (PT_BRAND_CLASSIC_TEMPLTE_FLUID) using App Designer.


Paste it as the contents of a custom style sheet object - CSK_BRAND_CLASSIC_TEMPLTE_FLUID.

NavBar > Navigator > PeopleTools > Portal > Branding > Branding Objects


Step 2: Create Custom - Fluid - Global Override Style Sheet Definition

Note: We only need to perform this step if we intend to override some of the delivered styles for Fluidwhile using Theme Macro Sets.

Clone delivered style sheet: PT_BRAND_FLUID_TEMPLATE

Copy the entire contents on the freeform tab of the delivered style sheet (PT_BRAND_FLUID_TEMPLATE) using App Designer.


Paste it as the contents of a custom style sheet object - CSK_BRAND_FLUID_TEMPLATE.

NavBar > Navigator > PeopleTools > Portal > Branding > Branding Objects


Step 3: Create Custom - Homepage Header:

NavBar > Navigator > PeopleTools > Portal > Branding > Define Header and Footers

Search for header definition DEFAULT_HEADER_FLUID and 'Save As' CSK_HEADER_FLUID (custom header).



Step 4: Create Custom - Theme Macro Set:

NavBar > Navigator > PeopleTools > Portal > Branding > Theme Macro Set

Copy the delivered Macro Set (PT_DEFAULT_MACROSET_855) and save as CSK_DEFAULT_MACROSET_855.


Enter custom Macro Set name (CSK_DEFAULT_MACROSET_855) and Save.



Step 5: Assemble Custom Theme

NavBar > Navigator > PeopleTools > Portal > Branding > Assemble Themes

Search for theme definition DEFAULT_THEME_FLUID and 'Save As' CSK_THEME_FLUID (custom theme).


Update the custom theme CSK_THEME_FLUID with the custom definitions created in the preceding steps.

Note: If you did not clone PT_BRAND_CLASSIC_TEMPLTE_FLUID and PT_BRAND_FLUID_TEMPLATE in steps 1 and 2 respectively, then you can just use the delivered styles for Classic - Theme Style Sheet and Fluid Components - Global Override Style Sheet.


Note: The following settings are mandatory for using Theme Macro Set. I did not find these mentioned anywhere in the documentation.
  1. Homepage Header: Must be derived (cloned) from DEFAULT_HEADER_FLUID.
  2. Classic - Theme Style Sheet: Must be derived (cloned) from PT_BRAND_CLASSIC_TEMPLTE_FLUID.
  3. Fluid - Global Override Style Sheet: Must be derived (cloned) from PT_BRAND_FLUID_TEMPLATE or PT_BRAND_FLUID_NOIMG_TEMPLATE.
These are the reasons why we completed steps 1-3. I believe the above requirements for Theme Macro Set are to be released shortly as part of a more detailed Branding guidelines document.

Step 6: Update Branding System Options

Update Branding System Options to reference the custom theme CSK_THEME_FLUID (created in the previous step).


We have completed all the housekeeping tasks to assemble a custom theme in the Branding framework. Now, we can start using the Theme Macro Sets to override Branding elements.

Step 7: Override Logo (or other available Branding elements) using Theme Macro Sets

NavBar > Navigator > PeopleTools > Portal > Branding > Theme Macro Set

Click on the custom Theme Macro Set to override the available Branding elements (177 elements - images, icons and styles - are available as delivered).



Since we want to override the logo, let us find the Branding elements (macro names) that represent the logo and override the macro content to use a custom image.




Note: I used a custom logo which is a SVG image with a height of 32 pixels. You may need to adjust other styles if your image height varies. I tried to match the height of the delivered image for the sake of this proof of concept.

NavBar > Navigator > PeopleTools > Portal > Branding > Branding Objects


Results in Fluid:


Results in Classic:


Now we can see the results of using a macro to override the logo image. But if you look at the screenshots closely, the logo is a little displaced. Let us fix that by adjusting the style (top padding).

Macro Name: PT_LOGO_TOP_PADDING
- Adjust top padding from 0.25em to 0.00em


Results in Fluid:


Results in Classic:

While the difference is subtle, you might notice that the Fluid logo appears to be positioned as expected (padding-top: 0.00em;) but the Classic logo is still displaced.

When I looked into it further, I figured that the classic homepage logo styling is getting generated a little differently and does not honor the macro override (PT_LOGO_TOP_PADDING) we just updated.


Since we already did all the housekeeping work, it is very easy to override this style using the custom Classic - Theme Style Sheet (CSK_BRAND_CLASSIC_TEMPL_FLUID).

NavBar > Navigator > PeopleTools > Portal > Branding > Branding Objects

Edit CSK_BRAND_CLASSIC_TEMPL_FLUID and set top to 4pxfor .homePageHdr #pthdr2logofluid:before selector.


Results:


Hope this gives you an understanding of what is new with Branding in PeopleTools 8.55. In the next post, I will provide guidelines on how to perform some more detailed branding tasks. Stay tuned!

Notes:
  1. Details of the environment used for this post: HCM 9.2 - PUM Image 16 - PeopleTools 8.55.01.
  2. If you find any inconsistent results while going through any of the steps detailed in this post (especially while assembling the theme) then please make sure you bounce your web and app servers and purge the cache.
Viewing all 132 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>