Skip to main content

This content has been archived and is no longer being updated. Links may not function; however, this content may be relevant to outdated versions of the product.

Support Article

CPM Portal: pxSession Timer not working properly.

SA-22254

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">&nbsp;</span></TD>
                      <TD nowrap>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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"> &nbsp;</TD>
                            <td NOWRAP="NOWRAP">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
                            <TD NOWRAP="NOWRAP" class="dialogHeaderLabel">&nbsp;</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">&nbsp;</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">&nbsp;</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'">&nbsp
                  Ok&nbsp;</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

Was this useful?

0% found this useful

Have a question? Get answers now.

Visit the Collaboration Center to ask questions, engage in discussions, share ideas, and help others.

Did you find this content helpful?

We'd prefer it if you saw us at our best.

Pega Community has detected you are using a browser which may prevent you from experiencing the site as intended. To improve your experience, please update your browser.

Close Deprecation Notice