hof 21.0.20-axios-beta → 22.0.0-timeout-warning-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.nyc_output/39365c14-40b7-4634-b733-940b72a11984.json +1 -0
  2. package/.nyc_output/processinfo/39365c14-40b7-4634-b733-940b72a11984.json +1 -0
  3. package/.nyc_output/processinfo/index.json +1 -1
  4. package/CHANGELOG.md +16 -0
  5. package/codeReviewChecklist.md +22 -0
  6. package/config/hof-defaults.js +11 -2
  7. package/frontend/govuk-template/build/govuk_template.html +3 -4
  8. package/frontend/govuk-template/govuk_template_generated.html +3 -4
  9. package/frontend/template-mixins/mixins/template-mixins.js +1 -0
  10. package/frontend/template-mixins/partials/forms/checkbox.html +5 -0
  11. package/frontend/template-mixins/partials/forms/input-text-group.html +1 -1
  12. package/frontend/template-mixins/partials/forms/select.html +6 -6
  13. package/frontend/template-mixins/partials/forms/textarea-group.html +1 -1
  14. package/frontend/template-partials/views/partials/head.html +8 -10
  15. package/frontend/template-partials/views/partials/page.html +1 -0
  16. package/frontend/template-partials/views/partials/session-timeout-warning.html +17 -0
  17. package/frontend/themes/gov-uk/client-js/index.js +2 -0
  18. package/frontend/themes/gov-uk/client-js/session-timeout-dialog.js +333 -0
  19. package/frontend/themes/gov-uk/styles/_session-timeout-dialog.scss +209 -0
  20. package/frontend/themes/gov-uk/styles/govuk.scss +1 -0
  21. package/index.js +8 -4
  22. package/lib/ga-tag.js +22 -13
  23. package/model/index.js +28 -29
  24. package/package.json +6 -7
  25. package/pull_request.md +16 -0
  26. package/sandbox/apps/sandbox/index.js +1 -0
  27. package/sandbox/package.json +1 -1
  28. package/sandbox/public/css/app.css +251 -6
  29. package/sandbox/public/js/bundle.js +36441 -25219
  30. package/sandbox/yarn.lock +14 -9
  31. package/.nyc_output/9651d42a-59d8-48e6-949c-655d9fa6db21.json +0 -1
  32. package/.nyc_output/processinfo/9651d42a-59d8-48e6-949c-655d9fa6db21.json +0 -1
  33. package/model/apis/axios-settings.js +0 -9
@@ -0,0 +1,333 @@
1
+ /* eslint max-len: 0 */
2
+ 'use strict';
3
+
4
+ const $ = require('jquery');
5
+
6
+ // Modal dialog prototype
7
+ window.GOVUK.sessionDialog = {
8
+ el: document.getElementById('js-modal-dialog'),
9
+ $el: $('#js-modal-dialog'),
10
+ $lastFocusedEl: null,
11
+ $closeButton: $('.modal-dialog .js-dialog-close'),
12
+ dialogIsOpenClass: 'dialog-is-open',
13
+ timers: [],
14
+ warningTextPrefix: 'To protect your information, this page will time out in ',
15
+ warningTextSuffix: '.',
16
+ warningText: $('.dialog-text').text(),
17
+ warningTextExtra: '',
18
+
19
+ // Timer specific markup. If these are not present, timeout and redirection are disabled
20
+ $timer: $('#js-modal-dialog .timer'),
21
+ $accessibleTimer: $('#js-modal-dialog .at-timer'),
22
+
23
+ secondsSessionTimeout: parseInt($('#js-modal-dialog').data('session-timeout'), 10 || 1800),
24
+ secondsTimeoutWarning: parseInt($('#js-modal-dialog').data('session-timeout-warning'), 10 || 300),
25
+ timeoutRedirectUrl: $('#js-modal-dialog').data('url-redirect'),
26
+ timeSessionRefreshed: new Date(),
27
+
28
+ bindUIElements: function () {
29
+ window.GOVUK.sessionDialog.$closeButton.on('click', function (e) {
30
+ e.preventDefault();
31
+ window.GOVUK.sessionDialog.closeDialog();
32
+ });
33
+
34
+ // Close modal when ESC pressed
35
+ $(document).keydown(function (e) {
36
+ if (window.GOVUK.sessionDialog.isDialogOpen() && e.keyCode === 27) {
37
+ window.GOVUK.sessionDialog.closeDialog();
38
+ }
39
+ });
40
+ },
41
+
42
+ isDialogOpen: function () {
43
+ return window.GOVUK.sessionDialog.el.open;
44
+ },
45
+
46
+ isConfigured: function () {
47
+ return window.GOVUK.sessionDialog.$timer.length > 0 &&
48
+ window.GOVUK.sessionDialog.$accessibleTimer.length > 0 &&
49
+ window.GOVUK.sessionDialog.secondsSessionTimeout &&
50
+ window.GOVUK.sessionDialog.secondsTimeoutWarning &&
51
+ window.GOVUK.sessionDialog.timeoutRedirectUrl;
52
+ },
53
+
54
+ openDialog: function () {
55
+ if (!window.GOVUK.sessionDialog.isDialogOpen()) {
56
+ $('html, body').addClass(window.GOVUK.sessionDialog.dialogIsOpenClass);
57
+ window.GOVUK.sessionDialog.saveLastFocusedEl();
58
+ window.GOVUK.sessionDialog.makePageContentInert();
59
+ window.GOVUK.sessionDialog.el.showModal();
60
+ }
61
+ },
62
+
63
+ closeDialog: function () {
64
+ if (window.GOVUK.sessionDialog.isDialogOpen()) {
65
+ $('html, body').removeClass(window.GOVUK.sessionDialog.dialogIsOpenClass);
66
+ window.GOVUK.sessionDialog.el.close();
67
+ window.GOVUK.sessionDialog.setFocusOnLastFocusedEl();
68
+ window.GOVUK.sessionDialog.removeInertFromPageContent();
69
+ window.GOVUK.sessionDialog.refreshSession();
70
+ }
71
+ },
72
+
73
+ saveLastFocusedEl: function () {
74
+ window.GOVUK.sessionDialog.$lastFocusedEl = document.activeElement;
75
+ if (!window.GOVUK.sessionDialog.$lastFocusedEl || window.GOVUK.sessionDialog.$lastFocusedEl === document.body) {
76
+ window.GOVUK.sessionDialog.$lastFocusedEl = null;
77
+ } else if (document.querySelector) {
78
+ window.GOVUK.sessionDialog.$lastFocusedEl = document.querySelector(':focus');
79
+ }
80
+ },
81
+
82
+ // Set focus back on last focused el when modal closed
83
+ setFocusOnLastFocusedEl: function () {
84
+ if (window.GOVUK.sessionDialog.$lastFocusedEl) {
85
+ window.setTimeout(function () {
86
+ window.GOVUK.sessionDialog.$lastFocusedEl.focus();
87
+ }, 0);
88
+ }
89
+ },
90
+
91
+ // Set page content to inert to indicate to screenreaders it's inactive
92
+ // NB: This will look for #content for toggling inert state
93
+ makePageContentInert: function () {
94
+ if (document.querySelector('#content')) {
95
+ document.querySelector('#content').inert = true;
96
+ document.querySelector('#content').setAttribute('aria-hidden', 'true');
97
+ }
98
+ },
99
+
100
+ // Make page content active when modal is not open
101
+ // NB: This will look for #content for toggling inert state
102
+ removeInertFromPageContent: function () {
103
+ if (document.querySelector('#content')) {
104
+ document.querySelector('#content').inert = false;
105
+ document.querySelector('#content').setAttribute('aria-hidden', 'false');
106
+ }
107
+ },
108
+
109
+ numberToWords: function (n) {
110
+ const string = n.toString();
111
+ let start;
112
+ let end;
113
+ let chunk;
114
+ let ints;
115
+ let i;
116
+ let word;
117
+ let words = 'and';
118
+
119
+ if (parseInt(string, 10) === 0) {
120
+ return 'zero';
121
+ }
122
+
123
+ /* Array of units as words */
124
+ const units = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'];
125
+
126
+ /* Array of tens as words */
127
+ const tens = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'];
128
+
129
+ /* Array of scales as words */
130
+ const scales = ['', 'thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion', 'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quatttuor-decillion', 'quindecillion', 'sexdecillion', 'septen-decillion', 'octodecillion', 'novemdecillion', 'vigintillion', 'centillion'];
131
+
132
+ /* Split user arguemnt into 3 digit chunks from right to left */
133
+ start = string.length;
134
+ const chunks = [];
135
+ while (start > 0) {
136
+ end = start;
137
+ chunks.push(string.slice((start = Math.max(0, start - 3)), end));
138
+ }
139
+
140
+ /* Check if function has enough scale words to be able to stringify the user argument */
141
+ const chunksLen = chunks.length;
142
+ if (chunksLen > scales.length) {
143
+ return '';
144
+ }
145
+
146
+ /* Stringify each integer in each chunk */
147
+ words = [];
148
+ for (i = 0; i < chunksLen; i++) {
149
+ chunk = parseInt(chunks[i], 10);
150
+
151
+ if (chunk) {
152
+ /* Split chunk into array of individual integers */
153
+ ints = chunks[i].split('').reverse().map(parseFloat);
154
+
155
+ /* If tens integer is 1, i.e. 10, then add 10 to units integer */
156
+ if (ints[1] === 1) {
157
+ ints[0] += 10;
158
+ }
159
+
160
+ /* Add scale word if chunk is not zero and array item exists */
161
+ if ((word === scales[i])) {
162
+ words.push(word);
163
+ }
164
+
165
+ /* Add unit word if array item exists */
166
+ if ((word === units[ints[0]])) {
167
+ words.push(word);
168
+ }
169
+
170
+ /* Add tens word if array item exists */
171
+ if ((word === tens[ints[1]])) {
172
+ words.push(word);
173
+ }
174
+
175
+ /* Add hundreds word if array item exists */
176
+ if ((word === units[ints[2]])) {
177
+ words.push(word + ' hundred');
178
+ }
179
+ }
180
+ }
181
+ return words.reverse().join(' ');
182
+ },
183
+
184
+ // Attempt to convert numerics into text as OS VoiceOver
185
+ // occasionally stalled when encountering numbers
186
+ timeToWords: function (t, unit) {
187
+ let words;
188
+ if (t > 0) {
189
+ try {
190
+ words = window.GOVUK.sessionDialog.numberToWords(t);
191
+ } catch (e) {
192
+ words = t;
193
+ }
194
+ words = words + ' ' + window.GOVUK.sessionDialog.pluralise(t, unit);
195
+ } else {
196
+ words = '';
197
+ }
198
+ return words;
199
+ },
200
+
201
+ pluralise: function (n, unit) {
202
+ return n === 1 ? unit : unit + 's';
203
+ },
204
+
205
+ numericSpan: function (n, unit) {
206
+ return '<span class="tabular-numbers">' + n + '</span> ' + window.GOVUK.sessionDialog.pluralise(n, unit);
207
+ },
208
+
209
+ countdownText: function (minutes, seconds) {
210
+ const minutesText = window.GOVUK.sessionDialog.numericSpan(minutes, 'minute');
211
+ const secondsText = window.GOVUK.sessionDialog.numericSpan(seconds, 'second');
212
+ return minutes > 0 ? minutesText : secondsText;
213
+ },
214
+
215
+ countdownAtText: function (minutes, seconds) {
216
+ const minutesText = window.GOVUK.sessionDialog.timeToWords(minutes, 'minute');
217
+ const secondsText = window.GOVUK.sessionDialog.timeToWords(seconds, 'second');
218
+ return minutes > 0 ? minutesText : secondsText;
219
+ },
220
+
221
+ startCountdown: function () {
222
+ const $timer = window.GOVUK.sessionDialog.$timer;
223
+ const $accessibleTimer = window.GOVUK.sessionDialog.$accessibleTimer;
224
+ let timerRunOnce = false;
225
+ const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
226
+
227
+ const seconds = window.GOVUK.sessionDialog.secondsUntilSessionTimeout();
228
+ const minutes = seconds / 60;
229
+
230
+ $timer.text(minutes + ' minute' + (minutes > 1 ? 's' : ''));
231
+
232
+ (function countdown() {
233
+ const secondsUntilSessionTimeout = window.GOVUK.sessionDialog.secondsUntilSessionTimeout();
234
+ const timerExpired = secondsUntilSessionTimeout <= window.GOVUK.sessionDialog.secondsFinalWarning;
235
+
236
+ if (!timerExpired) {
237
+ const minutesLeft = parseInt(secondsUntilSessionTimeout / 60, 10);
238
+ const secondsLeft = parseInt(secondsUntilSessionTimeout % 60, 10);
239
+ const atMinutesText = window.GOVUK.sessionDialog.timeToWords(minutesLeft, 'minute');
240
+ const atSecondsText = window.GOVUK.sessionDialog.timeToWords(secondsLeft, 'second');
241
+
242
+ // Below string will get read out by screen readers every time
243
+ // the timeout refreshes.
244
+ // Add additional information in extraText which will get announced to AT the
245
+ // first time the time out opens
246
+ const countdownText = window.GOVUK.sessionDialog.countdownText(minutesLeft, secondsLeft);
247
+ const text = window.GOVUK.sessionDialog.warningTextPrefix + '<strong>' + countdownText + '</strong>' + window.GOVUK.sessionDialog.warningTextSuffix;
248
+ const countdownAtText = window.GOVUK.sessionDialog.countdownAtText(atMinutesText, atSecondsText);
249
+ const atText = window.GOVUK.sessionDialog.warningTextPrefix + countdownAtText + window.GOVUK.sessionDialog.warningTextSuffix + 'bgbhj ' + window.GOVUK.sessionDialog.warningText;
250
+ const extraText = '\n' + window.GOVUK.sessionDialog.warningTextExtra;
251
+
252
+ $timer.html(text + ' ' + extraText);
253
+
254
+ // Update screen reader friendly content every 20 secs
255
+ if (secondsLeft % 20 === 0) {
256
+ // Read out the extra content only once.
257
+ // Don't read out on iOS VoiceOver which stalls on the longer text
258
+ if (!timerRunOnce && !iOS) {
259
+ $accessibleTimer.text(atText + extraText);
260
+ timerRunOnce = true;
261
+ } else {
262
+ $accessibleTimer.text(atText);
263
+ }
264
+ }
265
+
266
+ window.GOVUK.sessionDialog.addTimer(countdown, 20);
267
+ }
268
+ })();
269
+ },
270
+
271
+ // Clears all timers
272
+ clearTimers: function () {
273
+ for (let i = 0; i < window.GOVUK.sessionDialog.timers.length; i++) {
274
+ clearInterval(window.GOVUK.sessionDialog.timers[i]);
275
+ }
276
+ },
277
+
278
+ refreshSession: function () {
279
+ $.get('');
280
+ window.GOVUK.sessionDialog.timeSessionRefreshed = new Date();
281
+ window.GOVUK.sessionDialog.controller();
282
+ },
283
+
284
+ redirect: function () {
285
+ window.location = window.GOVUK.sessionDialog.timeoutRedirectUrl;
286
+ },
287
+
288
+ // JS doesn't allow resetting timers globally so timers need
289
+ // to be retained for resetting.
290
+ addTimer: function (f, seconds) {
291
+ window.GOVUK.sessionDialog.timers.push(setInterval(f, seconds * 1000));
292
+ },
293
+
294
+ secondsSinceRefresh: function () {
295
+ return Math.round(Math.abs((window.GOVUK.sessionDialog.timeSessionRefreshed - new Date()) / 1000));
296
+ },
297
+
298
+ secondsUntilSessionTimeout: function () {
299
+ return window.GOVUK.sessionDialog.secondsSessionTimeout - window.GOVUK.sessionDialog.secondsSinceRefresh();
300
+ },
301
+
302
+ secondsUntilTimeoutWarning: function () {
303
+ return window.GOVUK.sessionDialog.secondsUntilSessionTimeout() - window.GOVUK.sessionDialog.secondsTimeoutWarning;
304
+ },
305
+
306
+ // countdown controller logic
307
+ controller: function () {
308
+ window.GOVUK.sessionDialog.clearTimers();
309
+
310
+ const secondsUntilSessionTimeout = window.GOVUK.sessionDialog.secondsUntilSessionTimeout();
311
+
312
+ if (secondsUntilSessionTimeout <= 0) {
313
+ // timed out - redirect
314
+ window.GOVUK.sessionDialog.redirect();
315
+ } else if (secondsUntilSessionTimeout <= window.GOVUK.sessionDialog.secondsTimeoutWarning) {
316
+ // timeout warning - show countdown and schedule redirect
317
+ window.GOVUK.sessionDialog.openDialog();
318
+ window.GOVUK.sessionDialog.startCountdown();
319
+ window.GOVUK.sessionDialog.addTimer(window.GOVUK.sessionDialog.controller, window.GOVUK.sessionDialog.secondsUntilSessionTimeout());
320
+ } else {
321
+ // wait for warning
322
+ window.GOVUK.sessionDialog.addTimer(window.GOVUK.sessionDialog.controller, window.GOVUK.sessionDialog.secondsUntilTimeoutWarning());
323
+ }
324
+ },
325
+
326
+ init: function (options) {
327
+ $.extend(window.GOVUK.sessionDialog, options);
328
+ if (window.GOVUK.sessionDialog.el && window.GOVUK.sessionDialog.isConfigured()) {
329
+ window.GOVUK.sessionDialog.bindUIElements();
330
+ window.GOVUK.sessionDialog.controller();
331
+ }
332
+ }
333
+ };
@@ -0,0 +1,209 @@
1
+ .modal-dialog {
2
+ display: none;
3
+ }
4
+
5
+ .modal-dialog--no-js-persistent {
6
+ display: inline-block;
7
+ }
8
+
9
+ .js-enabled {
10
+ .modal-dialog--no-js-persistent {
11
+ display: none;
12
+
13
+ &[open], .dialog-button {
14
+ display: inline-block;
15
+ }
16
+ }
17
+
18
+ .modal-dialog[open] {
19
+ display: inline-block;
20
+ }
21
+ }
22
+
23
+ .modal-dialog[open] {
24
+ overflow-x: hidden;
25
+ overflow-y: auto;
26
+ max-height: 90vh;
27
+ padding: 0;
28
+ margin-bottom: 0;
29
+ margin-top: 0;
30
+ position: fixed;
31
+ top: 50% !important;
32
+ -webkit-transform: translate(0, -50%);
33
+ -ms-transform: translate(0, -50%);
34
+ transform: translate(0, -50%);
35
+ }
36
+
37
+ @media (min-width: 641px) {
38
+ .modal-dialog[open] {
39
+ padding: 0;
40
+ }
41
+ }
42
+
43
+ .modal-dialog__inner {
44
+ padding: 20px;
45
+ }
46
+
47
+ @media (min-width: 641px) {
48
+ .modal-dialog__inner {
49
+ padding: 30px;
50
+ }
51
+ }
52
+
53
+ .modal-dialog__inner__text {
54
+ font-family: "nta", Arial, sans-serif;
55
+ font-weight: 400;
56
+ text-transform: none;
57
+ font-size: 16px;
58
+ line-height: 1.25;
59
+ padding-top: 2px;
60
+ padding-bottom: 8px;
61
+ margin-bottom: 20px;
62
+ }
63
+
64
+ @media (min-width: 641px) {
65
+ .modal-dialog__inner__text {
66
+ font-size: 19px;
67
+ line-height: 1.31579;
68
+ }
69
+ }
70
+
71
+ @media (min-width: 641px) {
72
+ .modal-dialog__inner__text {
73
+ padding-top: 0;
74
+ padding-bottom: 5px;
75
+ }
76
+ }
77
+
78
+ .modal-dialog__inner__button {
79
+ font-size: 19px;
80
+ margin-top: 10px;
81
+ }
82
+
83
+ .modal-dialog__inner__link {
84
+ font-family: "nta", Arial, sans-serif;
85
+ font-weight: 400;
86
+ text-transform: none;
87
+ font-size: 16px;
88
+ line-height: 1.25;
89
+ padding-top: 2px;
90
+ padding-bottom: 8px;
91
+ background: none;
92
+ border: none;
93
+ vertical-align: middle;
94
+ margin-top: 20px;
95
+
96
+ &:hover {
97
+ cursor: pointer;
98
+ }
99
+ }
100
+
101
+ @media (min-width: 641px) {
102
+ .modal-dialog__inner__link {
103
+ font-size: 19px;
104
+ line-height: 1.31579;
105
+ }
106
+ }
107
+
108
+ @media (min-width: 641px) {
109
+ .modal-dialog__inner__link {
110
+ padding-top: 0;
111
+ padding-bottom: 5px;
112
+ }
113
+ }
114
+
115
+ @media (max-width: 640px) {
116
+ .modal-dialog__inner__link {
117
+ text-align: center;
118
+ display: block;
119
+ margin-top: 25px;
120
+ }
121
+ }
122
+
123
+ @media (min-width: 641px) {
124
+ .modal-dialog__inner__link {
125
+ position: absolute;
126
+ top: 50%;
127
+ transform: translateY(-50%);
128
+ padding: 0;
129
+ margin: 0 0 0 30px;
130
+ }
131
+ }
132
+
133
+ .modal-dialog__inner__block {
134
+ position: relative;
135
+ }
136
+
137
+ .modal-dialog #dialog-title {
138
+ margin-top: 0;
139
+ }
140
+
141
+ .dialog-is-open {
142
+ overflow: hidden;
143
+ }
144
+
145
+ dialog {
146
+ left: 0;
147
+ right: 0;
148
+ width: -moz-fit-content;
149
+ width: -webkit-fit-content;
150
+ width: fit-content;
151
+ height: -moz-fit-content;
152
+ height: -webkit-fit-content;
153
+ height: fit-content;
154
+ margin: auto;
155
+ border: solid;
156
+ padding: 1em;
157
+ background: white;
158
+ color: black;
159
+ display: none;
160
+ border: 5px solid black;
161
+
162
+ + .backdrop {
163
+ position: fixed;
164
+ top: 0;
165
+ right: 0;
166
+ bottom: 0;
167
+ left: 0;
168
+ background: rgba(0, 0, 0, 0.8);
169
+ }
170
+
171
+ &[open] {
172
+ display: block;
173
+ box-sizing: border-box;
174
+ margin: 0 auto;
175
+ padding: 15px;
176
+ width: 90%;
177
+
178
+ + .backdrop, &::backdrop {
179
+ background: rgba(0, 0, 0, 0.8);
180
+ }
181
+ }
182
+ }
183
+
184
+ @media (min-width: 641px) {
185
+ dialog[open] {
186
+ padding: 30px;
187
+ margin: 30px auto;
188
+ max-width: 500px;
189
+ }
190
+ }
191
+
192
+ .tabular-numbers {
193
+ font-family: "ntatabularnumbers", "nta", Arial, sans-serif;
194
+ }
195
+
196
+ .dialog-sign-out-link {
197
+ @include govuk-font($size: 24);
198
+ display: inline-block;
199
+ margin: 5px;
200
+
201
+ @include govuk-media-query($from: tablet) {
202
+ @include govuk-font($size: 19);
203
+
204
+ position: relative;
205
+ top: 2px;
206
+ padding: 0.526315em 0.789473em 0.263157em;
207
+ line-height: 1.5;
208
+ }
209
+ }
@@ -26,6 +26,7 @@ $path: "/public/images/" !default;
26
26
  @import "cookie-settings";
27
27
  @import "check_your_answers";
28
28
  @import "pdf";
29
+ @import "session-timeout-dialog";
29
30
 
30
31
  // Modules
31
32
  @import "modules/validation";
package/index.js CHANGED
@@ -84,6 +84,7 @@ const getContentSecurityPolicy = (config, res) => {
84
84
  'www.google.co.uk/ads/ga-audiences'
85
85
  ],
86
86
  connectSrc: [
87
+ "'self'",
87
88
  'https://www.google-analytics.com',
88
89
  'https://region1.google-analytics.com',
89
90
  'https://region1.analytics.google.com'
@@ -147,6 +148,9 @@ function bootstrap(options) {
147
148
  res.locals.appName = config.appName;
148
149
  res.locals.htmlLang = config.htmlLang;
149
150
  res.locals.cookieName = config.session.name;
151
+ // session timeout warning configs
152
+ res.locals.sessionTimeOut = config.session.ttl;
153
+ res.locals.sessionTimeOutWarning = config.sessionTimeOutWarning;
150
154
  next();
151
155
  });
152
156
 
@@ -189,10 +193,10 @@ function bootstrap(options) {
189
193
  app.use(morgan('sessionId=:id ' + morgan.combined, {
190
194
  stream: config.logger.stream,
191
195
  skip: (req, res) => config.loglevel !== 'debug' &&
192
- (
193
- res.statusCode >= 300 || !_.get(req, 'session.id') ||
194
- config.ignoreMiddlewareLogs.some(v => req.originalUrl.includes(v))
195
- )
196
+ (
197
+ res.statusCode >= 300 || !_.get(req, 'session.id') ||
198
+ config.ignoreMiddlewareLogs.some(v => req.originalUrl.includes(v))
199
+ )
196
200
  }));
197
201
 
198
202
  serveStatic(app, config);
package/lib/ga-tag.js CHANGED
@@ -52,26 +52,35 @@ const setupPageMap = routes => {
52
52
  module.exports = (app, config) => {
53
53
  const gaTagId = config.gaTagId;
54
54
  const ga4TagId = config.ga4TagId;
55
- const gtmTagId = config.gtmTagId;
56
- const environmentType = config.environmentType ? config.environmentType : 'dev';
55
+ const gtm = config.gtm;
57
56
  const gaCrossDomainTrackingTagId = config.gaCrossDomainTrackingTagId;
58
57
  const routes = config.routes;
59
58
 
60
- if (gaTagId || ga4TagId) {
59
+ if (gaTagId || ga4TagId || gtm.tagId) {
61
60
  const pageMap = setupPageMap(routes);
62
61
 
63
62
  app.use((req, res, next) => {
64
63
  const page = pageView(req.path, pageMap);
65
- res.locals.gaAllowDebug = config.env === 'development';
66
- res.locals.isETA = config.appName === 'ETA';
67
- res.locals.gaTagId = gaTagId;
68
- res.locals.ga4TagId = ga4TagId;
69
- res.locals.gtmTagId = gtmTagId;
70
- res.locals.environmentType = environmentType;
71
- res.locals.gaCrossDomainTrackingTagId = gaCrossDomainTrackingTagId;
72
- res.locals['ga-id'] = gaTagId;
73
- res.locals['ga-page'] = page;
74
- res.locals['gtm-page'] = convertToGTMPage(page);
64
+
65
+ // Preparing common res.locals properties
66
+ const properties = {
67
+ gaAllowDebug: config.env === 'development',
68
+ gaTagId: gaTagId,
69
+ ga4TagId: ga4TagId,
70
+ gaCrossDomainTrackingTagId: gaCrossDomainTrackingTagId,
71
+ 'ga-id': gaTagId,
72
+ 'ga-page': page
73
+ };
74
+
75
+ // Adding extra properties if a GTM TAG is available
76
+ if (gtm.tagId) {
77
+ gtm.config.pageName = gtm.composePageName(page, convertToGTMPage);
78
+ Object.assign(properties, {
79
+ gtmConfig: JSON.stringify(gtm.config),
80
+ gtmTagId: gtm.tagId
81
+ });
82
+ }
83
+ res.locals = Object.assign(res.locals, properties);
75
84
  next();
76
85
  });
77
86
  }