Friday, March 29, 2019

Fluid UI - Working with Grids - Part 3 - Where are the Previous and Next buttons?

Someone asked the question if we can use the 'Next' and 'Previous' grid buttons in Fluid similar to Classic?

In Classic, we use the 'Previous' and 'Next' buttons which are available on the Grid Navigation Bar to move past the number of rows defined in the grid 'occurs count'.


When I revisited my previous post on Fluid Grids (Part 2), I realized that I set the Grid Properties - 'Occurs Count' to 5 rows and as a result I could only see 5 rows even though there are 13 rows overall. As you can see in the demo video below, when I search/find a value that is not in the first 5 rows, I can still find them. Only issue is that I cannot freely navigate across the 13 rows.



So, how do we navigate across the various rows in the Fluid grid if we are limited by the 'Occurs Count' as shown in the above example? One way is to use, 'Unlimited Occurs Count' but that is cheating!


Lazy Scrolling

Fortunately for grids, we can enable "lazy scrolling" which will pull in the additional rows dynamically as we scroll down. This method of lazy scrolling (if you will) is aimed at improving the performance of fluid application pages.

PeopleBooks | Enabling Lazy Scrolling for Scrollable Grids


Demo of Lazy Scrolling


Environment Details

FSCM 9.2 PUM 30
PeopleTools 8.57.02

Friday, March 22, 2019

Enable/Disable Classic Plus without Customizations

Classic Plus was introduced in PeopleTools 8.56 as a means to unify the look and feel of Classic and Fluid PeopleSoft pages from a styling point of view. If you want a quick overview of how this works, you can go to youtube and watch this fantastic video created by PeopleSoft guru, Graham Smith.

https://www.youtube.com/watch?v=Cg7JmqEkPjk

As you can see in this video, PeopleTools team as well as the Apps teams are delivering (with every new release) many components that are Classic Plus enabled. But not all Classic components are Classic Plus enabled for various reasons. In cases where Classic Plus is not enabled on a desired component, or alternatively where Classic Plus is enabled as delivered but we may want to disable it on a certain component, we will need to enable it manually via a Component property (Classic Plus Theme Selection).

In such cases where we need to manually enable/disable Classic Plus, we incur some technical debt in the form of a minor customization to the components involved which needs to be maintained in the future.

Note: Merely enabling this property may not be sufficient to Enable Classic Plus in some advanced cases. Review the following  PeopleBook for more details.

Reworking Components for Classic Plus Display

Assuming, we are not dealing with any page refactoring complexities, then we can simply enable/disable Classic Plus using a PeopleCode function!

ConfigureClassicPlusComponent

According to Doc ID 2440035.1, this is a new function in PeopleTools 8.57, although I can see that is exists in PeopleTools 8.56 as well.

Oracle's PeopleSoft PeopleTools 8.57 New Features Overview (Doc ID 2440035.1)


Based on what I am seeing in some delivered code, it appears to be available in PeopleTools 8.56.06 and higher.


Anyway, why is this exciting? Because we can simply use this function in conjunction with Event Mapping and enable/disable Classic Plus without incurring any customizations.

Event Mapping App Classes

Enable Classic Plus

Disable Classic Plus

Event Mapping - Related Content Services

PeopleTools > Portal > Related Content Service > Define Related Content Service

Enable Classic Plus Service


Disable Classic Plus Service


Enable/Disable Classic Plus using Event Mapping Configuration

Let us say, we want to enable Classic Plus on a Classic component that is not using Classic Plus as delivered. We can simply create an event mapping configuration to associate the component with the 'Enable Classic Plus Service'.

As an example, let us use PT_THM_MACROSET component which is not using Classic Plus as delivered (Navigation: PeopleTools > Portal > Branding > Theme Macro Set). As we can see in the demo below, the 'Classic Plus Theme Selection' component property is not set for PT_THM_MACROSET by default. By associating the custom event mapping code which is part of our 'Enable Classic Plus Service' (SV_ENABLE_CLASSIC_PLUS), we can enable Classic Plus on this component without any customization. We can see that behind the scenes (by calling the ConfigureClassicPlusComponent function via Event Mapping PeopleCode), the 'Classic Plus Theme Selection' component property is updated without any effect on the last updated userid/datetime which means that this change will not be marked as a customization.


Similarly, let us say, we want to disable Classic Plus on a Classic component that is already using Classic Plus as delivered. We can simply create an event mapping configuration to associate the component with the 'Disable Classic Plus Service'.

As an example, let us use PEOPLECODE_TRACE component which is using Classic Plus as delivered (Navigation: PeopleTools > Utilities > Debug > PeopleCode Trace). As we can see in the demo below, the 'Classic Plus Theme Selection' component property is already set for PEOPLECODE_TRACE by default. By associating the custom event mapping code which is part of our 'Disable Classic Plus Service' (SV_DISABLE_CLASSIC_PLUS), we can disable Classic Plus on this component without any customization. Again, we can see that behind the scenes (by calling the ConfigureClassicPlusComponent function via Event Mapping PeopleCode), the 'Classic Plus Theme Selection' component property is updated without any effect on the last updated userid/datetime which means that this change will not be marked as a customization.


Environment Details

FSCM 9.2 PUM Image 30
PeopleTools 8.57.02

Concluding Thoughts

This post is not to suggest that this approach is best practice. While enabling/disabling Classic Plus, you will need to determine what works best for your lifecycle management procedures. It is as simple as that. What works for one customer might not work for another.

Personally, the prospect of automating the enable/disable Classic Plus customization through PeopleCode is very exciting. It is the main reason why I wrote this post. Additionally, combining that with Event Mapping provides an alternative 'customization free' approach in certain cases.

Further, we can see that this function/peoplecode logic is similarly used in the delivered 'Set Classic Plus' App Engine (EOCP_SETCP) which can be found in PeopleTools 8.56.06 and higher under the following navigation.

Enterprise Components > Common Utilities > Classic Plus Setup

PeopleBooks - Classic Plus Setup Page

If this setup page already exists in the application under Enterprise Components, why not simply use that instead? Yes, we should! But this setup page is only available in certain apps like FSCM and HCM. It is not yet available in Campus Solutions.

Thursday, March 21, 2019

PSSpreadsheet Class Part 2 | Documentation Update, Date Format (converting to epoch) and more

This is a continuation of 'Using PSSpreadsheet Class in App Engine' where I demonstrated how we can use this new API to generate Excel spreadsheets using PeopleCode. While there were and still are a lot of gaps in the documentation of this API, it provides an easier method to create spreadsheets from PeopleCode.

Documentation Update

Previously, in the notes section, I explained the significance of the second parameter (rowset processing) in the Open method which was not documented in PeopleBooks at that point in time. This has been updated.

PSSpreadSheet - Open Method PeopleBook

This is also documented in the following My Oracle Support - Doc Id which clarifies the RangeApplyStyle method as well.
E-PC: There Is Missing Documentation In PeopleBooks For PeopleCode PSSpreadsheet Class - Methods Open And RangeApplyStyle (Doc ID 2357922.1)

Other useful documents on My Oracle Support are listed below.
E-PC: PSSpreadsheet SetColumnWidth Method Is Not Working (Doc ID 2354586.1)
E-NV: What is RangeApplyStyle() in PSSpreadsheet API ? (Doc ID 2288870.1)
E-PC: PeopleCode API PSSpreadSheet SetActiveSheetName method is not working (Doc ID 2511065.1)
E-PC/NV - Method RangeApplyStyle Of Class PSSpreadsheet Is Not Available On PT8.55 And PT8.56 (Doc ID 2516382.1)
Bug 29384267 : ERRORRETURN-> 255 - FILE IS ALREADY IN OPEN STATE! WITH PSSPREADSHEET

Needless to say, that while some of the reported issues are fixed/clarified, there are still improvements to be made which I hope will follow suit in subsequent releases/patches of PeopleTools.

Date Format for SetCellDate

After reviewing a comment thread on my previous post, I was curious to find out more about the SetCellDate method.

Comment thread
PSSpreadsheet - SetCellDate PeopleBook


If we see the example provided in PeopleBooks, a value (string) of 120223323 produces a cell (date format) with the following value.
1/2/1970  9:23:43 AM


So what is this mystery number/value 120223323 that magically converts to a date of 1/2/1970  9:23:43 AM? After many days of spinning my wheels, I finally found (thanks to Oracle Support) that this is actually the date in epoch format (date/time in milliseconds since epoch). Wow! Why? 😂

One reason I can think of is that behind the scenes PSSpreadSheet API is implemented in Java (Apache POI) and therefore may require this format to pass into appropriate java methods? My guess is as good as yours. In any case, there is potential for this to be improved where this date calculation/conversion can be masked from the API user (perhaps with an internal conversion) for the date parameter in the SetCellDate method.

Anyway, now how do we calculate the date in epoch timestamp format if we ever want to use this method successfully under the current circumstances? There are some online converters which we can use to get ourselves familiarized with the calculation.

https://www.epochconverter.com/
https://www.freeformatter.com/epoch-timestamp-to-date-converter.html

Note: Keep in mind that the SetCellDate method expects the epoch timestamp to be in milliseconds (some converts provide the timestamp value in seconds which might throw us off when used in PeopleCode).

That said, how do we do this calculation/conversion in PeopleCode? I have not found a delivered function and/or API that helps with this calculation/conversion. So, I resorted to using javascript and executing it on the server side using a very handy technique demonstrated by Jim Marion on his blog here.

JavaScript to convert date to epoch timestamp format (milliseconds)

Here is a simple JavaScript that converts a human readable date to epoch timestamp format. You can follow this link to test the code directly in jsFiddle.

https://jsfiddle.net/SasankVemana/bgLk8sez/



Sample PeopleCode Snippet with SetCellDate example

JavaScript in Message Catalog (29999, 1)

Message Catalog (29000, 1) for reference


GitHub Project Update

In my previous post, I shared a sample App Engine program that will simply generate Excel spreadsheet using data from a rowset. It was brought to my attention that if a column contains a date/datetime field, then the spreadsheet is not generated as expected. This is definitely a limiting factor when it comes to using the rowset processing option in the PSSpreadSheet class.

I created another GitHub project which generates a spreadsheet via an App Engine which uses non-rowset processing option. If you are looking for examples, the App Designer project can be downloaded and used evaluation purposes.

GitHub Project: https://github.com/SasankVemana/PSSpreadsheet-in-App-Engine-2

This sample App Engine will produce a spreadsheet as follows.

Tuesday, March 19, 2019

JavaScript Injection Framework - Updates, Bugs and Fixes

The reason I am writing this blog post is to make readers aware of the latest version of the JavaScript Injection Framework and known bugs/fixes associated with the older versions.

If you read some of my previous posts on Branding and other UI enhancements, you may have come across several attempts made by me to find a means to globally (system wide) inject JavaScript/CSS. Unfortunately, there is no way to do this via delivered configuration/code so I ended up writing custom javascript code.

Over the years, I have made iterative improvements to this code and created a framework of sorts with a minimally invasive customization.

Early (Beta) version
https://pe0ples0ft.blogspot.com/2015/11/peopletools-854-branding-part-5b-fluid.html#FluJSInjectionBootstrap

Updated version (using RequireJS)
https://pe0ples0ft.blogspot.com/p/javascript-injection-framework.html

As I was making further changes, I moved this framework to GitHub in an effort to better manage the code/versioning.

GitHub Project
https://github.com/SasankVemana/PeopleTools-JavaScript-Injection-Framework

Recently, the following Doc ID was brought to my attention via a twitter post.

Oracle Support Document 2294106.1
E-PIA: Run to HTML,Excel and XML links in Query Manager and Query Viewer spinning for ever while running a report having prompt criteria

Twitter Thread
https://twitter.com/ArcherHuck/status/1085635936053051394
After reviewing Doc ID 2294106.1, I realized that this issue is most likely caused by a customer who implemented this JavaScript Injection Framework. The issue reported in the Doc ID, is very similar to an existing issue identified with an older version of the framework.

Reported Issue: https://pe0ples0ft.blogspot.com/p/javascript-injection-framework.html#c6317103235239955618

The solution provided by Oracle in the Doc ID is to completely remove the custom framework which is understandable since this is not Oracle code. But this issue can be overcome by using the latest version of the JavaScript Injection Framework. In the latest version of the bootstrap javascript as shown below, the regex pattern is updated to account for an extended list of PeopleSoft URL types.


Additionally, the latest version of the framework that is available on GitHub also addresses and fixes some race conditions (which I ran into under certain circumstances) associated with RequireJS and other custom scripts.

Here are some resources that are very useful to understand common timing issues related to javascript functions and callbacks.

https://blog.kevinchisholm.com/functions-javascript/javascript-callback-functions-the-absolute-basics/
https://www.sitepoint.com/understanding-requirejs-for-effective-javascript-module-loading/