Sunday, January 29, 2017

Fluid UI - New Window Feature - Workaround

Graham Smith created an idea on My Oracle Support Community to carry forward the "New Window" feature in Fluid pages especially for users on the desktop (or non-small form factor devices).

We can understand that Fluid user interface is designed with a mobile first and more importantly small form factor (SFF) first approach. This is one of the reasons why we don't get the Toolbar Actions (Save, Return to List, Next in list, Previous in list, etc.) by default on Fluid pages. But Graham has rightly pointed out that Fluid is not just an UI for mobile devices, we also need to account for users on desktops who are accustomed to opening new windows using the "New Window" feature.

This idea is trending and has already received several votes in a short period. I am hoping this would be incorporated as an enhancement in the future PeopleTools releases. I encourage everyone to continue voting. The more the merrier!
https://community.oracle.com/ideas/16701
 
Workaround while we wait?

Note: The workaround suggested in this post involves a minor customization. As with any customization, we will need to determine - based on our environment and circumstances - if the cost of maintaining this customization (until such time as we receive a solution from Oracle) outweighs the benefits!

Let us say that we decided to go down the path of introducing the "New Window" feature in Fluid, where would we put it? I am not convinced that bringing it back in literal terms and placing it exactly where it was located in Classic pages would be a good fit for Fluid (even if we are only talking medium, large and extra large form factors). If we notice, the traditional "Help" feature that links to context sensitive PeopleBooks, is now located in the Action Menu on the Fluid Header.

New Window and Help links in Classic:


Help link in Fluid:


It seems logical to similarly add the "New Window" functionality to the Action Menu in the Fluid Branding Header! That way, we will not be interfering with the content area of the page.

In my previous posts on Branding, I described how we can globally (across the application) add a link to the Action Menu in the Fluid Branding Header. I demonstrated the concept using an external link as an example.
Refer: Adding Custom Links to Fluid Branding

We can follow the same steps to add the 'New Window' link as well. In my case, I already created the custom subpage (CSK_HEADER_ACTION). I simply added a groupbox and a hyperlink (derived work field) to the subpage (similar to the external link example).



I added the following PeopleCode on the FieldChange event to open a New Window.


Results:



Suppress New Window feature on Small Form Factor (SFF) Devices (Optional):

If we would like to suppress the New Window feature for SFF devices, then we can simply configure this using the page field properties as shown in the following screenshots.



PeopleCode for Reference:

&fullURI = %Request.FullURI;

&pos1 = Find("/psc/", &fullURI);
&part1 = Substring(&fullURI, 1, &pos1 + 4);
&part2 = Substring(&fullURI, &pos1 + 5, Len(&fullURI));

&pos2 = Find("/", &part2);
&part3 = Substring(&part2, 1, &pos2 - 1);
&part4 = Substring(&part2, &pos2, Len(&part2));

&pos3 = Find("_", &part3);
If &pos3 = 0 Then
   &site = &part3;
Else
   &site = Substring(&part3, 1, &pos3 - 1);
End-If;

&newWinURL = &part1 | &site | "_newwin" | &part4;
ViewContentURL(&newWinURL);


Related Posts - Productivity Enhancements:
Fluid UI - CTRL+J - On Mobile Devices

Friday, January 27, 2017

Using PSSpreadsheet Class in App Engine

Jim Marion brought the PSSpreadsheet class to our notice during Oracle OpenWorld conference last year. If you want a copy of his slide deck, you can find it in the below link (may not work for long, so grab it before they take it down):
https://oracle.rainfocus.com/scripts/catalog/oow16.jsp?search=marion&search.event=oracleopenworld

There is a great delivered example under the following navigation:
Reporting Tools > PS/nVision > Spread Sheet API Sample Page

This page provides a working example of how to use the PSSpreadsheet class to render a spreadsheet to the end user via an IScript (WEBLIB_SSAPI.ISCRIPT1.FieldFormula).

Peoplebooks:
Understanding The PSSpreadsheet Class

Someone asked if we could use the same PeopleCode API to create spreadsheets using an App Engine and post the file to the Report Manager? Here is an example of how we can do just that.

Sample App Engine PeopleCode:


Results:

The file should show up in Process Monitor as follows:



Notes:
- Currently, if we use the Open method of the PSSpreadsheet class to create the spreadsheet, it creates the file in the PS_HOME directory by default. There appears to be no way to pass in a parameter such as %FilePath_Relative to create the file in the process instance directory which would in turn help with posting the file to the Report Manager (Perhaps a good enhancement?). To workaround that, I wrote some code to dynamically derive the process instance directory and pass that as the first parameter (filename) for the Open method.
- The second parameter for the Open method is a boolean. We can enable Rowset processing by setting it to True. This does not seem to be documented in PeopleBooks but we can figure it out based on code in the IScript example (WEBLIB_SSAPI.ISCRIPT1.FieldFormula).

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

Consider voting for idea to enhance PSSpreadsheet class Open method:
https://community.oracle.com/ideas/16749

PeopleCode for Reference:

/* Get Process Instance Directory */
SQLExec("SELECT PRCSOUTPUTDIR FROM PS_CDM_LIST WHERE PRCSINSTANCE = :1", SV_AE_TEST_AET.PROCESS_INSTANCE, &path);

/* Get Directory Separator */
&dirSep = "/";
If Substring(GetEnv("PS_SERVDIR"), 1, 1) <> "/" Then
   &dirSep = "\";
End-If;;

/* Set Output File Name */
&outFileName = "HelloWorld.xlsx";

/* Create Spreadsheet using PSSpreadsheet class */
Local object &ss;
&ss = CreateObject("PSSpreadsheet");
&ss.Open(&path | &dirSep | &outFileName, True);

/* Load data using Rowset */
Local Rowset &rs = CreateRowset(Record.PSMSGCATDEFN);
&rs.Fill("where MESSAGE_SET_NBR = :1", 4);
&ss.SetRowSetData(&rs);

/* Save */
&ss.save();