diff --git a/grails-app/assets/javascripts/base-bs4.js b/grails-app/assets/javascripts/base-bs4.js
index 2dbb01f1c..8cfe63de4 100644
--- a/grails-app/assets/javascripts/base-bs4.js
+++ b/grails-app/assets/javascripts/base-bs4.js
@@ -2,3 +2,65 @@
//= require jquery/jquery.js
//= require js-cookie/js.cookie.js
//= require bootstrap/js/bootstrap.bundle.js
+/**
+ * This function sets up a timeout warning banner that will be displayed when the session has expired
+ * or network has been lost.
+ * It is called in the nrm_bs4.gsp template file.
+ */
+function setupTimeoutWarning(options) {
+ var $logoutWarningBanner = $('#' + options.logoutWarningBannerId);
+ var $networkWarningBanner = $('#' + options.networkWarningBannerId);
+ var $logoutButton = $('#' + options.logoutButtonId);
+ var $loginButton = $('#' + options.loginButtonId);
+
+ // Set up a timer that will periodically poll the server to keep the session alive
+ var intervalSeconds = 5//; * 60;
+
+ function fireKeepAlive() {
+ $.ajax(options.keepSessionAliveUrl).fail(function (xhr) {
+ if (xhr.status == 0) {
+ // Network outage?
+ $networkWarningBanner.show();
+ } else if (xhr.status == 401) {
+ $networkWarningBanner.hide();
+ // Session timed out.
+ $logoutWarningBanner.show();
+ }
+ }).done(function (xhr) {
+ $networkWarningBanner.hide();
+ $logoutWarningBanner.hide();
+ });
+ }
+
+ setInterval(fireKeepAlive, intervalSeconds * 1000);
+
+ if (!window.localStorage) {
+ return;
+ }
+ var LOGOUT_PRESSED_KEY = 'logout';
+ var LOGIN_PRESSED_KEY = 'login';
+
+ $logoutButton.click(function () {
+ window.localStorage.setItem(LOGOUT_PRESSED_KEY, new Date().getTime());
+ });
+ $loginButton.click(function () {
+ window.localStorage.setItem(LOGIN_PRESSED_KEY, new Date().getTime());
+ });
+ $logoutWarningBanner.find('a').click(function () {
+ $logoutWarningBanner.hide();
+ });
+ window.addEventListener('storage', function (e) {
+ if (e.key == LOGOUT_PRESSED_KEY) {
+ $logoutWarningBanner.show();
+ }
+ if (e.key == LOGIN_PRESSED_KEY) {
+ $logoutWarningBanner.hide();
+ }
+ });
+ window.addEventListener('online', function() {
+ $networkWarningBanner.hide();
+ });
+ window.addEventListener('offline', function() {
+ $networkWarningBanner.show();
+ });
+}
diff --git a/grails-app/assets/javascripts/fieldcapture-application.js b/grails-app/assets/javascripts/fieldcapture-application.js
index 00420732a..dc55151fb 100644
--- a/grails-app/assets/javascripts/fieldcapture-application.js
+++ b/grails-app/assets/javascripts/fieldcapture-application.js
@@ -934,20 +934,6 @@ function replaceContentSection(contentSelector, url) {
});
}
-$(function() {
- $('#logout-btn').click(function() {
- if (window.localStorage) {
- window.localStorage.setItem('logout', new Date().getTime());
- }
- });
- $('#logout-warning a').click(function(){ $('#logout-warning').hide(); });
- window.addEventListener('storage', function(e) {
- if (e.key == 'logout') {
- $('#logout-warning').show();
- }
- });
-});
-
function stageNumberFromStage(stage) {
var stageRegexp = /.+ (\d+)/;
var match = stageRegexp.exec(stage);
diff --git a/grails-app/assets/stylesheets/nrm/css/screen.css b/grails-app/assets/stylesheets/nrm/css/screen.css
index 39433699d..01ab32945 100644
--- a/grails-app/assets/stylesheets/nrm/css/screen.css
+++ b/grails-app/assets/stylesheets/nrm/css/screen.css
@@ -2444,6 +2444,21 @@ div#announcement p {
margin: 0;
}
+div#logout-warning, div#network-warning {
+ padding: 15px;
+ font-size: 20px;
+ font-weight: bold;
+ text-align: center;
+ color: white;
+ background-color: red;
+ border-bottom: 0px solid red;
+}
+#logout-warning a:visited, #network-warning a:visited {
+ color:white;
+}
+
+
+
.container-fluid form.search.merit {
display: block;
float: left;
diff --git a/grails-app/views/layouts/nrm_bs4.gsp b/grails-app/views/layouts/nrm_bs4.gsp
index 918efc47a..ce1648103 100644
--- a/grails-app/views/layouts/nrm_bs4.gsp
+++ b/grails-app/views/layouts/nrm_bs4.gsp
@@ -51,17 +51,18 @@
+
+
+
+
+
-