[PATCH] [Wok] User session alert UI

From: peterpennings <peterpnns@gmail.com> This patch get a request header parameter to trigger a counter which shows up a alert to the user when the session is getting to expire peterpennings (1): User session timeout alert (UI) ui/css/src/wok.scss | 27 ++++ ui/css/wok.css | 30 ++++ ui/js/src/wok.api.js | 23 +++ ui/js/src/wok.session.js | 67 +++++++++ ui/pages/i18n.json.tmpl | 2 + ui/pages/wok-ui.html.tmpl | 15 +- 5 files changed, 443 insertions(+), 20 deletions(-) create mode 100644 ui/js/src/wok.session.js -- 2.5.0

From: peterpennings <peterpnns@gmail.com> Signed-off-by: peterpennings <peterpnns@gmail.com> --- ui/css/src/wok.scss | 27 +++++++++++++++++++ ui/css/wok.css | 30 +++++++++++++++++++++ ui/js/src/wok.api.js | 23 ++++++++++++++++ ui/js/src/wok.session.js | 67 +++++++++++++++++++++++++++++++++++++++++++++++ ui/pages/i18n.json.tmpl | 2 ++ ui/pages/wok-ui.html.tmpl | 13 +++++++++ 6 files changed, 162 insertions(+) create mode 100644 ui/js/src/wok.session.js diff --git a/ui/css/src/wok.scss b/ui/css/src/wok.scss index 454c3d8..830fa57 100755 --- a/ui/css/src/wok.scss +++ b/ui/css/src/wok.scss @@ -166,6 +166,33 @@ html.in-progress [disabled], margin: 10px; } +// session expiring +.session-expiring { + z-index: 9999999; + position: fixed; + bottom: 19px; + right: 19px; + .close { + margin-right: 8px; + margin-top: 4px; + } + .well { + background: #eee; + width: 280px; + padding: 0; + margin: 0; + p { + padding: 9px 9px 0 9px; + } + .form-group { + border-top: 1px solid #ccc; + margin: 0; + padding:9px; + text-align: right; + } + } +} + // Login @import "modules/login"; // Topbar and navigation diff --git a/ui/css/wok.css b/ui/css/wok.css index 5d8905f..7411ffd 100644 --- a/ui/css/wok.css +++ b/ui/css/wok.css @@ -157,6 +157,36 @@ html.in-progress .disabled { margin: 10px; } +.session-expiring { + z-index: 9999999; + position: fixed; + bottom: 19px; + right: 19px; +} + +.session-expiring .close { + margin-right: 8px; + margin-top: 4px; +} + +.session-expiring .well { + background: #eee; + width: 280px; + padding: 0; + margin: 0; +} + +.session-expiring .well p { + padding: 9px 9px 0 9px; +} + +.session-expiring .well .form-group { + border-top: 1px solid #ccc; + margin: 0; + padding: 9px; + text-align: right; +} + .login .content .container { width: 100% !important; padding-left: 0 !important; diff --git a/ui/js/src/wok.api.js b/ui/js/src/wok.api.js index 5238594..e2829ab 100644 --- a/ui/js/src/wok.api.js +++ b/ui/js/src/wok.api.js @@ -41,6 +41,18 @@ var wok = { settings['originalError'] = settings['error']; settings['error'] = null; settings['wok'] = true; + settings['complete'] = function(req) { + wok.session.remainingSessionTime = req.getResponseHeader('Session-Expires-On'); + wok.session.remainingSessionTime = (parseInt(wok.session.remainingSessionTime, 10) * 1000); + if (!wok.session.flagInTimer) { + wok.session.refreshExpiringCounter(); + wok.session.expiringCounter(); + } else if(wok.session.remainingSessionTime > wok.session.remaingTimeToShowAlert) { + wok.session.hideExpiringAlert(); + wok.session.refreshExpiringCounter(); + wok.session.flagInTimer = false; + } + }; return $.ajax(settings); }, @@ -122,4 +134,15 @@ var wok = { error : err }); }, + + getTasks: function(suc, err) { + wok.requestJSON({ + url : 'tasks', + type : 'GET', + contentType : "application/json", + dataType : 'json', + success : suc, + error : err + }); + } }; diff --git a/ui/js/src/wok.session.js b/ui/js/src/wok.session.js new file mode 100644 index 0000000..18456d2 --- /dev/null +++ b/ui/js/src/wok.session.js @@ -0,0 +1,67 @@ +/* + * Project Wok + * + * Copyright IBM Corp, 2015-2016 + * + * Code derived from Project Kimchi + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +wok.session = { + + remaingTimeToShowAlert: 30000, + remainingSessionTime: null, + flagInTimer: false, + expiringTimeout: null, + oneSecondExternalCounter: null, + oneSecondInternalCounter: null, + + expiringCounter: function(){ + var counter = wok.session.remainingSessionTime - wok.session.remaingTimeToShowAlert; + wok.session.expiringTimeout = setTimeout(function(){ + wok.session.flagInTimer = true; + $("#session-expiring-alert").show(); + $("#session-expiring-alert p").html("<script>var message = i18n['WOKSESS0001M'].replace('%1', 30);" + + "$('#session-expiring-alert p').html(message);" + + "var n = 30;" + + "wok.session.oneSecondExternalCounter = setTimeout(countDown,1000);" + + "function countDown(){n--; if(n > 0){wok.session.oneSecondInternalCounter = setTimeout(countDown,1000);}" + + "message = i18n['WOKSESS0001M'].replace('%1', n);" + + "$('#session-expiring-alert p').html(message);}</script>" + ); + }, counter); + }, + + refreshExpiringCounter: function() { + clearTimeout(wok.session.oneSecondExternalCounter); + clearTimeout(wok.session.oneSecondInternalCounter); + clearTimeout(wok.session.expiringTimeout); + wok.session.expiringTimeout = null; + wok.session.oneSecondExternalCounter = null; + wok.session.oneSecondInternalCounter = null; + }, + + renewSession: function(){ + wok.getTasks(function(){}, function(){}); + wok.session.flagInTimer = false; + clearTimeout(wok.session.oneSecondExternalCounter); + clearTimeout(wok.session.oneSecondInternalCounter); + wok.session.oneSecondExternalCounter = null; + wok.session.oneSecondInternalCounter = null; + $("#session-expiring-alert").hide(); + }, + + hideExpiringAlert: function(){ + $("#session-expiring-alert").hide(); + } +}; \ No newline at end of file diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl index de0eb70..5628479 100644 --- a/ui/pages/i18n.json.tmpl +++ b/ui/pages/i18n.json.tmpl @@ -53,6 +53,8 @@ "WOKSETT0013M": "$_("Timezone")", "WOKSETT0014M": "$_("IP Address")", + "WOKSESS0001M": "$_("Your session will be expired on: %1 s. Do you want to renew it?")", + "WOKFMT2001M": "$_("Ki")", "WOKFMT2002M": "$_("Mi")", "WOKFMT2003M": "$_("Gi")", diff --git a/ui/pages/wok-ui.html.tmpl b/ui/pages/wok-ui.html.tmpl index c56af3e..8a4abb5 100644 --- a/ui/pages/wok-ui.html.tmpl +++ b/ui/pages/wok-ui.html.tmpl @@ -183,6 +183,19 @@ <div class="modal fade host-modal" id="aboutModal" tabindex="-1" role="dialog" labelledby="aboutModalLabel" aria-hidden="true"> </div> + + <div class="fade in session-expiring" id="session-expiring-alert" hidden> + <button type="button" class="close">×</button> + <div class="well"> + <p>$_("Your session will expire on: 30s. Do you want to renew it?")</p> + <div class="form-group"> + <button class="btn btn-primary btn-xs" id="renew-session-button" onclick="wok.session.renewSession();">Renew</button> + <button class="btn btn-primary btn-xs" id="dismiss-session-button" onclick="wok.session.hideExpiringAlert();">Dismiss</button> + </div> + </div> + </div> + + <script id="about-tmpl" type="wok/template"> <div class="modal-dialog" role="document"> <div class="modal-content" > -- 2.5.0

Tested-by: Socorro Stoppler <socorro@linux.vnet.ibm.com> On 07/25/2016 12:04 PM, peterpnns@gmail.com wrote:
From: peterpennings <peterpnns@gmail.com>
Signed-off-by: peterpennings <peterpnns@gmail.com> --- ui/css/src/wok.scss | 27 +++++++++++++++++++ ui/css/wok.css | 30 +++++++++++++++++++++ ui/js/src/wok.api.js | 23 ++++++++++++++++ ui/js/src/wok.session.js | 67 +++++++++++++++++++++++++++++++++++++++++++++++ ui/pages/i18n.json.tmpl | 2 ++ ui/pages/wok-ui.html.tmpl | 13 +++++++++ 6 files changed, 162 insertions(+) create mode 100644 ui/js/src/wok.session.js
diff --git a/ui/css/src/wok.scss b/ui/css/src/wok.scss index 454c3d8..830fa57 100755 --- a/ui/css/src/wok.scss +++ b/ui/css/src/wok.scss @@ -166,6 +166,33 @@ html.in-progress [disabled], margin: 10px; }
+// session expiring +.session-expiring { + z-index: 9999999; + position: fixed; + bottom: 19px; + right: 19px; + .close { + margin-right: 8px; + margin-top: 4px; + } + .well { + background: #eee; + width: 280px; + padding: 0; + margin: 0; + p { + padding: 9px 9px 0 9px; + } + .form-group { + border-top: 1px solid #ccc; + margin: 0; + padding:9px; + text-align: right; + } + } +} + // Login @import "modules/login"; // Topbar and navigation diff --git a/ui/css/wok.css b/ui/css/wok.css index 5d8905f..7411ffd 100644 --- a/ui/css/wok.css +++ b/ui/css/wok.css @@ -157,6 +157,36 @@ html.in-progress .disabled { margin: 10px; }
+.session-expiring { + z-index: 9999999; + position: fixed; + bottom: 19px; + right: 19px; +} + +.session-expiring .close { + margin-right: 8px; + margin-top: 4px; +} + +.session-expiring .well { + background: #eee; + width: 280px; + padding: 0; + margin: 0; +} + +.session-expiring .well p { + padding: 9px 9px 0 9px; +} + +.session-expiring .well .form-group { + border-top: 1px solid #ccc; + margin: 0; + padding: 9px; + text-align: right; +} + .login .content .container { width: 100% !important; padding-left: 0 !important; diff --git a/ui/js/src/wok.api.js b/ui/js/src/wok.api.js index 5238594..e2829ab 100644 --- a/ui/js/src/wok.api.js +++ b/ui/js/src/wok.api.js @@ -41,6 +41,18 @@ var wok = { settings['originalError'] = settings['error']; settings['error'] = null; settings['wok'] = true; + settings['complete'] = function(req) { + wok.session.remainingSessionTime = req.getResponseHeader('Session-Expires-On'); + wok.session.remainingSessionTime = (parseInt(wok.session.remainingSessionTime, 10) * 1000); + if (!wok.session.flagInTimer) { + wok.session.refreshExpiringCounter(); + wok.session.expiringCounter(); + } else if(wok.session.remainingSessionTime > wok.session.remaingTimeToShowAlert) { + wok.session.hideExpiringAlert(); + wok.session.refreshExpiringCounter(); + wok.session.flagInTimer = false; + } + }; return $.ajax(settings); },
@@ -122,4 +134,15 @@ var wok = { error : err }); }, + + getTasks: function(suc, err) { + wok.requestJSON({ + url : 'tasks', + type : 'GET', + contentType : "application/json", + dataType : 'json', + success : suc, + error : err + }); + } }; diff --git a/ui/js/src/wok.session.js b/ui/js/src/wok.session.js new file mode 100644 index 0000000..18456d2 --- /dev/null +++ b/ui/js/src/wok.session.js @@ -0,0 +1,67 @@ +/* + * Project Wok + * + * Copyright IBM Corp, 2015-2016 + * + * Code derived from Project Kimchi + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +wok.session = { + + remaingTimeToShowAlert: 30000, + remainingSessionTime: null, + flagInTimer: false, + expiringTimeout: null, + oneSecondExternalCounter: null, + oneSecondInternalCounter: null, + + expiringCounter: function(){ + var counter = wok.session.remainingSessionTime - wok.session.remaingTimeToShowAlert; + wok.session.expiringTimeout = setTimeout(function(){ + wok.session.flagInTimer = true; + $("#session-expiring-alert").show(); + $("#session-expiring-alert p").html("<script>var message = i18n['WOKSESS0001M'].replace('%1', 30);" + + "$('#session-expiring-alert p').html(message);" + + "var n = 30;" + + "wok.session.oneSecondExternalCounter = setTimeout(countDown,1000);" + + "function countDown(){n--; if(n > 0){wok.session.oneSecondInternalCounter = setTimeout(countDown,1000);}" + + "message = i18n['WOKSESS0001M'].replace('%1', n);" + + "$('#session-expiring-alert p').html(message);}</script>" + ); + }, counter); + }, + + refreshExpiringCounter: function() { + clearTimeout(wok.session.oneSecondExternalCounter); + clearTimeout(wok.session.oneSecondInternalCounter); + clearTimeout(wok.session.expiringTimeout); + wok.session.expiringTimeout = null; + wok.session.oneSecondExternalCounter = null; + wok.session.oneSecondInternalCounter = null; + }, + + renewSession: function(){ + wok.getTasks(function(){}, function(){}); + wok.session.flagInTimer = false; + clearTimeout(wok.session.oneSecondExternalCounter); + clearTimeout(wok.session.oneSecondInternalCounter); + wok.session.oneSecondExternalCounter = null; + wok.session.oneSecondInternalCounter = null; + $("#session-expiring-alert").hide(); + }, + + hideExpiringAlert: function(){ + $("#session-expiring-alert").hide(); + } +}; \ No newline at end of file diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl index de0eb70..5628479 100644 --- a/ui/pages/i18n.json.tmpl +++ b/ui/pages/i18n.json.tmpl @@ -53,6 +53,8 @@ "WOKSETT0013M": "$_("Timezone")", "WOKSETT0014M": "$_("IP Address")",
+ "WOKSESS0001M": "$_("Your session will be expired on: %1 s. Do you want to renew it?")", + "WOKFMT2001M": "$_("Ki")", "WOKFMT2002M": "$_("Mi")", "WOKFMT2003M": "$_("Gi")", diff --git a/ui/pages/wok-ui.html.tmpl b/ui/pages/wok-ui.html.tmpl index c56af3e..8a4abb5 100644 --- a/ui/pages/wok-ui.html.tmpl +++ b/ui/pages/wok-ui.html.tmpl @@ -183,6 +183,19 @@ <div class="modal fade host-modal" id="aboutModal" tabindex="-1" role="dialog" labelledby="aboutModalLabel" aria-hidden="true"> </div>
+ + <div class="fade in session-expiring" id="session-expiring-alert" hidden> + <button type="button" class="close">×</button> + <div class="well"> + <p>$_("Your session will expire on: 30s. Do you want to renew it?")</p> + <div class="form-group"> + <button class="btn btn-primary btn-xs" id="renew-session-button" onclick="wok.session.renewSession();">Renew</button> + <button class="btn btn-primary btn-xs" id="dismiss-session-button" onclick="wok.session.hideExpiringAlert();">Dismiss</button> + </div> + </div> + </div> + + <script id="about-tmpl" type="wok/template"> <div class="modal-dialog" role="document"> <div class="modal-content" >
participants (3)
-
Aline Manera
-
peterpnns@gmail.com
-
Socorro Stoppler