Support Article
CPM Portal: pxSession Timer not working properly.
Summary
There are several issues with the pxSessionTimer and the LogoffTimer when using the newer CPM 7.1.3 & 7.1.4end user portals.
1) Session Time out pop-up is opening multiple times after launching new interactions.
2) The LogoffTimer modal window is not always removed properly either when clicking the "Ok" button or when the LogffTimer has run to zero.
This issues has occured with CPM 7.1.3 & 7.1.4 on PRPC 7.1.7 and PRPC 7.1.8.
Error Messages
LogoffTimer Modal window is opening multiple times.
LogoffTimer Modal window is not always removed properly.
Steps to Reproduce
1) Include pxSessionTimer section in CPMInteractionPortalHeader section with 3 minutes timeout and 1 minute warning parameter settings.
2) Save the rule and launch CPMInteraction Portal
3) Launch 2/3 Interaction and wait for the LogOffTimer to display.
Root Cause
The CPMInteractionPortalHeader gets refreshed when launching a new interaction. This causes a timer to be left active and NOT properly reset resulting in a timeout popup to be displayed even when a user is actively using the application. If just testing timeouts you will see multiple timeout LogoffTimer countdown windows being displayed.
The LogoffTimer modal window is using a variation of the flow action or grid level edit modal window. This was sporadically not shutting down properly. The only solution found was to use a JQuery modal window instead of using pega.openURLInModal.showModalDialog, code found in pzpega_openurl_in_modal.js. This uses a local implementation of _showJqueryModalDialog that is a private method in pega.openURLinModal so it can't be called directly.
Resolution
If you are using CPM 7.1.3/4 on PRPC 7.1.7/8 and want to display a LogoffTimer when users are idle for X amount use the following local change:
1) Copy pxSessionTimer to you own application RuleSet (Change rule name to "SessionTimer_<AppName>")
Add the following scripting within the existing <script></script> tags
....
/*handle refresh of CPMInteractionPortalHeader*/
if (pega.d.TimeoutWarningCountdown != null) {
console.log("clearing timer [load]: " + pega.desktop.TimeoutWarningCountdown);
clearTimeout(pega.desktop.TimeoutWarningCountdown);
}
pega.d.TimeoutWarningCountdown = null;
function desktop_restartTimeoutWarningTimer(){
if (pega.desktop.TimeoutTime && pega.desktop.TimeoutTime > 0) {
var nTimeoutWarningTime= (pega.desktop.TimeoutTime - pega.desktop.TimeoutWarningWindow) * 60000;
console.log("clearing timer: " + pega.desktop.TimeoutWarningCountdown);
clearTimeout(pega.desktop.TimeoutWarningCountdown);
pega.desktop.TimeoutWarningCountdown = null;
if (nTimeoutWarningTime >= 0) {
pega.desktop.TimeoutWarningCountdown = self.setTimeout("desktop_showTimeoutLogoffDialogNew('"+pega.desktop.TimeoutWarningWindow+"')",nTimeoutWarningTime);
console.log("created timer: " + pega.desktop.TimeoutWarningCountdown);
}
}
}
function desktop_showTimeoutLogoffDialogNew(strTime) {
var iTime = parseInt(strTime);
iTime = iTime * 60000;
var oSafeURL = new SafeURL("@baseclass.ShowLogoffTimer");
oSafeURL.put("time",iTime);
/*pega.openUrlInModal.showModalDialog*/
showJqueryModalDialog(oSafeURL,iTime, 210, 420, function(ret){
if (ret == null || ret == "ok") {
console.log("calling desktop_restartTimeoutWarningTimer from OK response from modal");
desktop_restartTimeoutWarningTimer();
} else {
pega.u.d.gDirtyOverride = false;
try {
application.logOff(true);
} catch(e) {
pega.u.d.replace('pyActivity=LogOff&pzPrimaryPageName=pyDisplayHarness', null);
}
}
});
self.setTimeout(function(){console.log("clearing timer while modal displays");clearTimeout(pega.desktop.TimeoutWarningCountdown);}, 5000);
}
/* display a modal dialog using jquery Code taken/modified from pzpega_openurl_in_modal.js */
function showJqueryModalDialog(url, arDialogArguments, height, width, callbackFunction ) {
if(arDialogArguments) window.dialogArguments = arDialogArguments;
var $frame = $('<div><iframe name="pzDisplayModalDialog" id="pzDisplayModalDialog" frameborder="0" src="' + ( typeof url == "string" ? url : url.toURL() ) + '" style="width:100%; height:100%"/></div>');
var $dialogWindow = $frame.dialog({
autoOpen: true,
modal: true,
width: width,
height: height+50,
resizable: false,
autoResize: false,
position: ['middle',20],
overlay: {
opacity: 0.8,
background: "black"
},
open: function() {
pzDisplayModalDialogWindow = $(this).children()[0].contentWindow;
if(window.gsServerReqURI) pzDisplayModalDialogWindow.gsServerReqURI = window.gsServerReqURI;
pzDisplayModalDialogWindow.dialogArguments = window.dialogArguments;
pzDisplayModalDialogWindow.returnValue = undefined;
},
close: function() {
handleCloseJqueryModal( callbackFunction, undefined , $frame, $dialogWindow);
}
}).width(width-30).height(height).css("overflow", "hidden");
$frame.children().load(function() {
var title = $(this).contents().find("title").html();
$dialogWindow.dialog('option', 'title', title);
pzDisplayModalDialogWindow = $(this)[0].contentWindow;
pzDisplayModalDialogWindow.closeModal = function() {
handleCloseJqueryModal( callbackFunction, pzDisplayModalDialogWindow.returnValue, $frame, $dialogWindow );
};
});
}
function handleCloseJqueryModal( callbackFunction, retval, frame, dialogWindow ) {
window.returnValue = retval;
dialogWindow.dialog('destroy');
frame.remove();
dialogWindow.remove();
if( callbackFunction) {
try {
callbackFunction(window.returnValue);
} catch(e) {
alert("pega.openUrlInModal.showModalDialog - error when calling callbackfunction: '" +e.message + "'");
}
}
}
...
3) LogOffTimer (PRPC 7.1.7 only)
The LogOffTimer HTML when using PRPC 7.1.7 needs to be modified to use the PRPC 7.1.8 version. Copy existing LogOffTimer and rename to LogOffTimer_<AppName>
<HTML>
<Title><pega:lookup property=".pyMessageLabel" value="Log off timeout warning" /> </Title>
<pega:include name="DesktopStyles" />
<script>
var iTime;
function init() {
window.focus();
window.returnValue = "ok";
iTime = parseInt(window.dialogArguments);
window.setTimeout("closeMe()", iTime);
setTime();
}
function closeMe() {
window.returnValue="timeout";
if(typeof window.closeModal == 'function') { window.closeModal(); } else { window.close(); }
}
function setTime() {
var numSec = iTime / 1000;
numSec--;
var min = Math.floor(numSec / 60);
var sec = numSec % 60
if (sec <= 9) {
sec = "0" + sec;
}
if (document.all){
document.all('_minutes').innerText = min;
document.all('_seconds').innerText = sec;
}
else{
document.all('_minutes').textContent= min;
document.all('_seconds').textContent= sec;
}
iTime = iTime - 1000;
window.setTimeout("setTime()",1000);
}
</script>
<body onload="init()">
<table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<!-- dialog header -->
<td valign="top" class="dialogHeaderBackground" id="topBanner" height="15%"> <table border="0" cellspacing="0" cellpadding="5">
<tr>
<td><TABLE>
<TR>
<!-- Dialog image goes here, use a style to contain the image, add to desktopbase and other style sheets -->
<TD valign="top" nowrap><span class="iconDialogSetWatch"> </span></TD>
<TD nowrap> </TD>
<TD valign="top" nowrap> <table border="0" cellpadding="2" cellspacing="0">
<TR>
<TD NOWRAP="NOWRAP" class="dialogHeaderLabel"><pega:lookup property=".pyMessageLabel" value="Log off timeout warning" /> </TD>
<TD NOWRAP="NOWRAP" cLASS="dialogHeaderData"> </TD>
<td NOWRAP="NOWRAP"> </td>
<TD NOWRAP="NOWRAP" class="dialogHeaderLabel"> </TD>
<TD NOWRAP="NOWRAP" CLASS="dialogHeaderData"></TD>
</TR>
</TABLE></TD>
</TR>
</TABLE></td>
</tr>
</table></td>
<!-- end of dialog header -->
</tr>
<tr>
<td valign="top" height="85%"><div class="dialogDataContainer" id="scrollingDIV">
<!-- body of dialog -->
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top"><table width="100%" cellpadding="0" cellspacing="0">
<TR>
<td align="center" width="76%" CLASS="dialogSubHeaderBackground"> </td>
</TR>
<TR>
<TD valign="top" align="center"> <TABLE border="0" CELLPADDING="0" CELLSPACING="2">
<TR>
<TD NOWRAP="NOWRAP" class="dialogLabelStyle" align="center"> <div><pega:lookup property=".pyMessageLabel" value="Timeout will occur in" /> </div></TD>
</TR>
<TR>
<TD NOWRAP="NOWRAP" class="dialogLabelStyle" align="center"><h2><span id="_minutes"> </span>:<span id="_seconds"> </span></h2></TD>
</TR>
<TR>
<TD NOWRAP="NOWRAP" class="dialogLabelStyle" align="center"><pega:include name="LogoutTimerMessage" /></TD>
</TR>
</TABLE></TD>
</TR>
<TR>
<TD valign="top"> </TD>
</TR>
</TABLE></td>
</tr>
</table>
</div></td>
<!-- end of body of dialog -->
</tr>
<tr>
<!-- dialog buttons -->
<td align="center" class="dialogButtonBarContainer" id="buttonBar">
<table cellpadding="0" cellspacing="0" width="100%">
<tr>
<td nowrap="nowrap" align="center">
<button title='Close this window' onclick="if(typeof window.closeModal == 'function') { window.closeModal(); } else { window.close(); }"
class="littleButton" id="button1" name="button1"> <span class="buttonLeft"></span>
<span class="buttonMiddle"> <span class="buttonText" onmouseout="this.className='buttonText'" onmouseover="this.className='buttonTextHover'">
Ok </span> </span> <span class="buttonRight"></span>
</button></td>
</tr>
</table></td>
<!-- end of dialog buttons -->
</tr>
</table>
</body>
</HTML>
3) Update @baseclass.ShowLogoffTimer to call LogoffTimer_<AppName>. (PRPC 7.1.7 only)
Copy @baseclass.ShowLogoffTimer into your own application ruleset. This is NOT a final record, leave name the same as called from Javascript added in step 1.
Udpate Step 1 "Show-HTML" to call LogOffTimer_<AppName>
Published April 25, 2016 - Updated October 8, 2020
Have a question? Get answers now.
Visit the Collaboration Center to ask questions, engage in discussions, share ideas, and help others.