Skip to content
Snippets Groups Projects
Commit 5bea2ad5 authored by Mark M. Florida's avatar Mark M. Florida
Browse files

Ground-up rewrite of session timeout script; style tweaks to some admin ui elements.

parent 1db4ff50
Branches
No related tags found
No related merge requests found
......@@ -210,8 +210,6 @@
<script src="${SITE_ROOT}/scripts/xnat/spawner.js"></script>
<script src="${SITE_ROOT}/scripts/timeLeft.js"></script>
${headBottom}
</head>
......@@ -238,10 +236,10 @@ ${bodyTop}
<b>|</b>
<a id="logout_user" href="${SITE_ROOT}/app/action/LogoutUser">Logout</a>
</span>
<%--<script type="text/javascript">--%>
<%--$('#timeLeftRenew').click(XNAT.app.timeout.handleOk);--%>
<%--Cookies.set('guest', 'false', {path: '/'});--%>
<%--</script>--%>
<script type="text/javascript">
Cookies.set('guest', 'false', {path: '/'});
</script>
<script src="${SITE_ROOT}/scripts/xnat/app/timeout.js"></script>
</c:if>
......@@ -301,8 +299,8 @@ ${bodyTop}
</ul>
</li>
<pg:restricted msg="<!-- non-admin -->">
<c:if test="${isAdmin == true}">
<!-- Sequence: 40 -->
<li class="more"><a href="#adminbox">Administer</a>
<ul>
......@@ -317,8 +315,8 @@ ${bodyTop}
<li><a href="${SITE_ROOT}/app/template/XDATScreen_admin_options.vm">More...</a></li>
</ul>
</li>
</c:if>
</pg:restricted>
<!-- Title: Tools -->
<!-- Sequence: 50 -->
......@@ -652,13 +650,29 @@ ${bodyTop}
<script src="${SITE_ROOT}/scripts/xnat/app/customPage.js"></script>
<div id="view-page">
<!-- BODY START -->
<jsp:doBody/>
<!-- BODY END -->
</div>
<!-- end xnat-templates/screens/Page.vm -->
......@@ -706,9 +720,9 @@ ${bodyTop}
</script>
<%--<script src="${SITE_ROOT}/scripts/footer.js"></script>--%>
<div id="xmodal-loading" style="position:fixed;left:-9999px;top:-9999px;">
<img src="${SITE_ROOT}/scripts/xmodal-v1/loading_bar.gif" alt="loading">
</div>
<%--<div id="xmodal-loading" style="position:fixed;left:-9999px;top:-9999px;">--%>
<%--<img src="${SITE_ROOT}/scripts/xmodal/loading_bar.gif" alt="loading">--%>
<%--</div>--%>
${bodyBottom}
......
......@@ -98,6 +98,8 @@ body.xnat .panel-default { border: 1px solid #c8c8c8; }
border-bottom: 1px solid #c8c8c8;
}
.panel .panel-element textarea { width: 80%; font-family: Courier, monospace; font-weight: normal; }
/* ELEMENT GROUP ITEMS */
.panel .panel-element-group .group-item .element-label { width: auto; }
......@@ -113,6 +115,7 @@ body.xnat .panel-default { border: 1px solid #c8c8c8; }
/* FORM CONTROLS */
body.xnat textarea.form-control { font-family: Courier, monospace; font-weight: normal; }
/* ==========================================================
UI WIDGETS
========================================================== */
......
......@@ -241,7 +241,12 @@ if (typeof jQuery == 'undefined') {
var $top_modal = $(xmodal.dialog.top).last();
if (keyCode === 27) { // key 27 = 'esc'
if ($top_modal.hasClass('esc')) {
xmodal.close($top_modal);
if ($top_modal.find('.buttons .cancel').length) {
$top_modal.find('.buttons .cancel').not('.disabled').trigger('click');
}
else {
xmodal.close($top_modal);
}
//$top_modal.find('.title .close').trigger('click');
}
}
......
/*!
* Session timeout warning dialog
*/
var XNAT = getObject(XNAT);
(function(factory){
if (typeof define === 'function' && define.amd) {
define(factory);
}
else if (typeof exports === 'object') {
module.exports = factory();
}
else {
return factory();
}
}(function(){
var timeout, undefined;
var $timeLeftDisplay = $('#timeLeft');
XNAT.app = getObject(XNAT.app || {});
XNAT.app.timeout = timeout =
getObject(XNAT.app.timeout || {});
// timeout polling interval
timeout.interval = 1000;
// when do we show the dialog?
timeout.showTime = 60;
timeout.cancelled = false;
function timeoutCookie(name){
var undefined;
function CookieFn(){
this.cookieExists = false;
this.name = name !== undefined ? name : this.name;
this.value = '';
this.opts = { path: '/' };
}
var fn = CookieFn.prototype;
// reset values after each call
fn.reset = function(){
this.cookieExists = false;
this.name = name !== undefined ? name : this.name;
this.value = '';
this.opts = { path: '/' };
return this;
};
fn.exists = function(name){
this.name = name;
this.cookieExists = !!Cookies.get(this.name);
return this.cookieExists;
};
fn.set = function(name, value){
if (value === undefined) {
value = name;
name = undefined;
}
this.name = name !== undefined ? name : this.name;
this.value = value !== undefined ? value : this.value;
Cookies.set(this.name, this.value, this.opts);
//this.reset(); // reset to prevent passing of values to chained methods
return this;
};
// 'value' is a default value to set if the cookie doesn't exist
fn.get = function(){
this.value = Cookies.get()[this.name];
return this;
};
fn.is = function(value) {
return this.get().value.toString() === value.toString();
};
fn.cookie = function(name) {
this.name = name;
this.exists();
return this;
};
return new CookieFn();
}
var cookie = {};
// store cookie value from server as a js var
cookie.SESSION_EXPIRATION_TIME = timeoutCookie('SESSION_EXPIRATION_TIME').get();
// is the dialog displayed?
cookie.SESSION_DIALOG_OPEN = timeoutCookie('SESSION_DIALOG_OPEN').set('false');
// has it been cancelled?
cookie.SESSION_DIALOG_CANCELLED = timeoutCookie('SESSION_DIALOG_CANCELLED').set('false');
// has the session timed out?
cookie.SESSION_TIMED_OUT = timeoutCookie('SESSION_TIMED_OUT').get();
// the time, in ms, that the session will end
cookie.SESSION_TIMEOUT_TIME = timeoutCookie('SESSION_TIMEOUT_TIME');
// has the user been redirected after timout?
cookie.SESSION_LOGOUT_REDIRECT = timeoutCookie('SESSION_LOGOUT_REDIRECT').get();
// the time, in ms, that the session started
cookie.SESSION_LAST_LOGIN = timeoutCookie('SESSION_LAST_LOGIN');
// what was the last page visited?
cookie.SESSION_LAST_PAGE = timeoutCookie('SESSION_LAST_PAGE').set(window.location.href);
timeout.expTime = '';
// parse the timeout values
timeout.getValues = function(){
var expTime = cookie.SESSION_EXPIRATION_TIME.get().value;
if (timeout.expTime && timeout.expTime === expTime) return;
timeout.expTime = expTime; // save it for next time
expTime = expTime.replace(/"/g, '').split(',');
timeout.startTime = (expTime[0].trim()*1 + 12000);
timeout.duration = expTime[1].trim()*1;
timeout.endTime = timeout.startTime + timeout.duration;
return {
startTime: timeout.startTime,
duration: timeout.duration,
endTime: timeout.endTime
}
};
// set SESSION_TIMEOUT_TIME cookie
cookie.SESSION_TIMEOUT_TIME.set(timeout.endTime);
function parseTimestamp(time) {
time = time || timeout.endTime;
var timeLeft = time - Date.now();
var secondsLeft = Math.floor(timeLeft / 1000);
var minutesLeft = Math.floor(secondsLeft / 60);
var secondsPart = secondsLeft % 60;
var hoursPart = Math.floor(minutesLeft / 60);
var minutesPart = minutesLeft % 60;
return {
time: time,
timeLeft: timeLeft,
secondsLeft: secondsLeft,
seconds: secondsPart,
minutes: minutesPart,
hours: hoursPart
};
}
// these things need to wait for the DOM to load
$(function(){
// create the dialog but don't render until DOM load
// and don't show it until needed
function timeoutDialog(){
var z = 99999;
var dialog = xmodal.open({
id: 'session-timeout-warning',
classes: 'keep static',
width: 300,
height: 200,
title: false,
content: 'Your ' + XNAT.app.siteId + ' session will expire in: <br><br>' +
'<b class="mono timeout-hours"></b> hours ' +
'<b class="mono timeout-minutes"></b> minutes ' +
'<b class="mono timeout-seconds"></b> seconds.' +
'</br></br>Click "Renew" to reset session timer.',
okLabel: 'Renew',
okClose: false,
okAction: function(){
timeout.handleOk();
dialog.hide();
},
cancelClose: false, // don't destroy the dialog
cancelAction: function(){
timeout.handleCancel();
dialog.hide();
}
});
dialog.$mask.hide().css('z-index', z-1);
dialog.$modal.hide().css('z-index', z);
dialog.hours = dialog.$modal.find('b.timeout-hours');
dialog.minutes = dialog.$modal.find('b.timeout-minutes');
dialog.seconds = dialog.$modal.find('b.timeout-seconds');
dialog.show = function(){
// DON'T SHOW IF ALREADY SHOWING
// set this as a js var so it's window-independend
if (timeout.dialogIsOpen) return;
// ONLY SHOW THE DIALOG IF NOT CANCELLED
if (cookie.SESSION_DIALOG_CANCELLED.is('false')) {
dialog.$mask.show();
dialog.$modal.show();
cookie.SESSION_DIALOG_OPEN.set('true');
timeout.dialogIsOpen = true;
$('applet').css('visibility', 'hidden');
}
};
dialog.hide = function(){
if (timeout.dialogIsOpen) {
dialog.$modal.hide();
dialog.$mask.hide();
cookie.SESSION_DIALOG_OPEN.set('false');
$('applet').css('visibility', 'visible');
}
timeout.dialogIsOpen = false;
};
return dialog;
}
timeout.dialog = timeoutDialog();
function redirectToLogin() {
timeout.redirecting = true;
xmodal.loading.open('#redirecting');
timeout.dialog.hide();
cookie.SESSION_TIMEOUT_TIME.set(Date.now());
cookie.SESSION_DIALOG_OPEN.set('false');
cookie.SESSION_DIALOG_CANCELLED.set('false');
cookie.SESSION_TIMED_OUT.set('true');
cookie.SESSION_LOGOUT_REDIRECT.set('true');
timeoutCookie('WARNING_BAR').set('OPEN');
timeoutCookie('guest').set('true');
// need to wait a little longer before reloading
setTimeout(function(){
window.location.reload();
}, 2000);
}
function renewSession(){
timeout.dialog.hide();
cookie.SESSION_EXPIRATION_TIME.get();
timeout.getValues();
cookie.SESSION_DIALOG_OPEN.set('false');
cookie.SESSION_DIALOG_CANCELLED.set('false');
cookie.SESSION_TIMED_OUT.set('false');
cookie.SESSION_TIMEOUT_TIME.set(timeout.endTime);
cookie.SESSION_LOGOUT_REDIRECT.set('false');
timeout.cancelled = false;
}
timeout.touch = function(opts){
return XNAT.xhr.get(extend(true, {
url: XNAT.url.restUrl('/xapi/siteConfig/buildInfo')
}, opts || {} ));
};
timeout.handleOk = function(){
var touch = timeout.touch();
touch.done(function(data){
cookie.SESSION_DIALOG_CANCELLED.set('true');
// an object is returned if session is still valid
timeout.sessionExpired = !isPlainObject(data);
if (timeout.sessionExpired) {
redirectToLogin();
}
else {
renewSession();
}
});
};
// fire this once when the script loads
timeout.handleOk();
timeout.handleCancel = function(){
timeout.dialog.hide();
timeout.cancelled = true;
cookie.SESSION_DIALOG_CANCELLED.set('true');
cookie.SESSION_DIALOG_OPEN.set('false');
};
// check every second to see if our timeout time has been reached
timeout.check = function(){
timeout.getValues();
// redirect if TIMED_OUT cookie is true
if (!timeout.redirecting && cookie.SESSION_TIMED_OUT.is('true')) {
redirectToLogin();
return false;
}
// redirect if time has run out
if (timeout.endTime <= Date.now()) {
cookie.SESSION_TIMED_OUT.set('true');
return false;
}
// close dialog if closed from another window
if (cookie.SESSION_DIALOG_OPEN.is('false')) {
timeout.dialog.hide();
}
// if endTime minus showTime is less than now
if (timeout.endTime - (timeout.showTime*1000) <= Date.now()) {
//don't do anything if the dialog has already been cancelled
if (cookie.SESSION_DIALOG_CANCELLED.is('true')) {
//timeout.handleCancel();
return false;
}
cookie.SESSION_DIALOG_CANCELLED.set('false');
timeout.dialog.show();
return false;
}
return true;
};
timeout.sessionCountdown = function() {
var timeLeft = parseTimestamp();
var hours = timeLeft.hours;
var mins = zeroPad(timeLeft.minutes);
var secs = zeroPad(timeLeft.seconds);
$timeLeftDisplay.text(hours + ":" + mins + ":" + secs);
if (cookie.SESSION_TIMED_OUT.is('true')) {
$timeLeftDisplay.text("Session Expired");
hours = mins = secs = '--';
}
// Update the text in the dialog too so it's always in synch
timeout.dialog.hours.text(hours);
timeout.dialog.minutes.text(mins);
timeout.dialog.seconds.text(secs);
};
timeout.running = false;
timeout.init = function(){
if (!timeout.running) {
timeout.running = true;
setInterval(
function(){
timeout.check();
timeout.sessionCountdown();
},
timeout.interval
);
}
};
// only run the timer if *not* a guest user (if an authenticated user)
if ((!!Cookies.get('guest')) && (Cookies.get('guest') === 'false')) {
timeout.init();
}
// attach event handler to elements with 'renew-session' class
$('body').on('click', '#timeLeftRenew, .renew-session', function(){
timeout.handleOk();
});
});
// this script has loaded
timeout.loaded = true;
return XNAT.app.timeout = timeout;
}));
......@@ -708,9 +708,11 @@ var XNAT = getObject(XNAT || {});
opts.value ||
opts.text ||
opts.html || '';
opts.element.html = doLookup(opts.element.html);
opts.element.rows = 6;
var textarea = spawn('textarea', opts.element);
return XNAT.ui.template.panelDisplay(opts, textarea).spawned;
};
......
......@@ -266,8 +266,6 @@ var XNAT = getObject(XNAT);
element.checked = /true|checked/i.test((opts.checked || element.value).toString());
element.checked = /true|checked/i.test((opts.checked || element.value).toString());
// add a hidden input to capture the checkbox/radio value
hiddenInput = spawn('input', {
type: 'hidden',
......
......@@ -47,7 +47,7 @@
</div>
</div><!-- /user_bar -->
<script src="$content.getURI("scripts/timeLeft.js")"></script>
<script src="$content.getURI("scripts/xnat/app/timeout.js")"></script>
#if ($sessionCount > 1 || $sessionIpCount > 1 )
##If you want fewer warnings, you can eliminate $sessionCount > 1 so it will not display a warning for multiple sessions on the same IP, or increase it to $sessionCount > X where X is the maximum number of sessions you can have on the same IP before you get a warning.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment