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

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/39337dba-f075-4b5c-ad46-31665a16d443.json +1 -0
  2. package/.nyc_output/processinfo/39337dba-f075-4b5c-ad46-31665a16d443.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 +345 -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 +37430 -26196
  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,345 @@
1
+ const $ = require('jquery');
2
+
3
+ // Modal dialog prototype
4
+ window.GOVUK.sessionDialog = {
5
+ el: document.getElementById('js-modal-dialog'),
6
+ $el: $('#js-modal-dialog'),
7
+ $lastFocusedEl: null,
8
+ $closeButton: $('.modal-dialog .js-dialog-close'),
9
+ dialogIsOpenClass: 'dialog-is-open',
10
+ timers: [],
11
+ warningTextPrefix: 'To protect your information, this page will time out in ',
12
+ warningTextSuffix: '.',
13
+ warningText: $('.dialog-text').text(),
14
+ warningTextExtra: '',
15
+
16
+ // Timer specific markup. If these are not present, timeout and redirection are disabled
17
+ $timer: $('#js-modal-dialog .timer'),
18
+ $accessibleTimer: $('#js-modal-dialog .at-timer'),
19
+
20
+ secondsSessionTimeout: parseInt($('#js-modal-dialog').data('session-timeout') || 1800),
21
+ secondsTimeoutWarning: parseInt($('#js-modal-dialog').data('session-timeout-warning') || 300),
22
+ timeoutRedirectUrl: $('#js-modal-dialog').data('url-redirect'),
23
+ timeSessionRefreshed: new Date(),
24
+
25
+ bindUIElements: function () {
26
+ window.GOVUK.sessionDialog.$closeButton.on('click', function (e) {
27
+ e.preventDefault();
28
+ window.GOVUK.sessionDialog.closeDialog();
29
+ })
30
+
31
+ // Close modal when ESC pressed
32
+ $(document).keydown(function (e) {
33
+ if (window.GOVUK.sessionDialog.isDialogOpen() && e.keyCode === 27) {
34
+ window.GOVUK.sessionDialog.closeDialog();
35
+ }
36
+ })
37
+ },
38
+
39
+ isDialogOpen: function () {
40
+ return window.GOVUK.sessionDialog.el['open'];
41
+ },
42
+
43
+ isConfigured: function () {
44
+ return window.GOVUK.sessionDialog.$timer.length > 0 &&
45
+ window.GOVUK.sessionDialog.$accessibleTimer.length > 0 &&
46
+ window.GOVUK.sessionDialog.secondsSessionTimeout &&
47
+ window.GOVUK.sessionDialog.secondsTimeoutWarning &&
48
+ window.GOVUK.sessionDialog.timeoutRedirectUrl;
49
+ },
50
+
51
+ openDialog: function () {
52
+ if (!window.GOVUK.sessionDialog.isDialogOpen()) {
53
+ $('html, body').addClass(window.GOVUK.sessionDialog.dialogIsOpenClass);
54
+ window.GOVUK.sessionDialog.saveLastFocusedEl();
55
+ window.GOVUK.sessionDialog.makePageContentInert();
56
+ window.GOVUK.sessionDialog.el.showModal();
57
+ }
58
+ },
59
+
60
+ closeDialog: function () {
61
+ if (window.GOVUK.sessionDialog.isDialogOpen()) {
62
+ $('html, body').removeClass(window.GOVUK.sessionDialog.dialogIsOpenClass);
63
+ window.GOVUK.sessionDialog.el.close();
64
+ window.GOVUK.sessionDialog.setFocusOnLastFocusedEl();
65
+ window.GOVUK.sessionDialog.removeInertFromPageContent();
66
+ window.GOVUK.sessionDialog.refreshSession();
67
+ }
68
+ },
69
+
70
+ saveLastFocusedEl: function () {
71
+ window.GOVUK.sessionDialog.$lastFocusedEl = document.activeElement;
72
+ if (!window.GOVUK.sessionDialog.$lastFocusedEl || window.GOVUK.sessionDialog.$lastFocusedEl === document.body) {
73
+ window.GOVUK.sessionDialog.$lastFocusedEl = null;
74
+ } else if (document.querySelector) {
75
+ window.GOVUK.sessionDialog.$lastFocusedEl = document.querySelector(':focus');
76
+ }
77
+ },
78
+
79
+ // Set focus back on last focused el when modal closed
80
+ setFocusOnLastFocusedEl: function () {
81
+ if (window.GOVUK.sessionDialog.$lastFocusedEl) {
82
+ window.setTimeout(function () {
83
+ window.GOVUK.sessionDialog.$lastFocusedEl.focus();
84
+ }, 0)
85
+ }
86
+ },
87
+
88
+ // Set page content to inert to indicate to screenreaders it's inactive
89
+ // NB: This will look for #content for toggling inert state
90
+ makePageContentInert: function () {
91
+ if (document.querySelector('#content')) {
92
+ document.querySelector('#content').inert = true;
93
+ document.querySelector('#content').setAttribute('aria-hidden', 'true');
94
+ }
95
+ },
96
+
97
+ // Make page content active when modal is not open
98
+ // NB: This will look for #content for toggling inert state
99
+ removeInertFromPageContent: function () {
100
+ if (document.querySelector('#content')) {
101
+ document.querySelector('#content').inert = false;
102
+ document.querySelector('#content').setAttribute('aria-hidden', 'false');
103
+ }
104
+ },
105
+
106
+ numberToWords: function (n) {
107
+ let string = n.toString()
108
+ let units
109
+ let tens
110
+ let scales
111
+ let start
112
+ let end
113
+ let chunks
114
+ let chunksLen
115
+ let chunk
116
+ let ints
117
+ let i
118
+ let word
119
+ let words = 'and'
120
+
121
+ if (parseInt(string) === 0) {
122
+ return 'zero';
123
+ }
124
+
125
+ /* Array of units as words */
126
+ units = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'];
127
+
128
+ /* Array of tens as words */
129
+ tens = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'];
130
+
131
+ /* Array of scales as words */
132
+ 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'];
133
+
134
+ /* Split user arguemnt into 3 digit chunks from right to left */
135
+ start = string.length;
136
+ chunks = [];
137
+ while (start > 0) {
138
+ end = start;
139
+ chunks.push(string.slice((start = Math.max(0, start - 3)), end));
140
+ }
141
+
142
+ /* Check if function has enough scale words to be able to stringify the user argument */
143
+ chunksLen = chunks.length
144
+ if (chunksLen > scales.length) {
145
+ return '';
146
+ }
147
+
148
+ /* Stringify each integer in each chunk */
149
+ words = []
150
+ for (i = 0; i < chunksLen; i++) {
151
+ chunk = parseInt(chunks[i]);
152
+
153
+ if (chunk) {
154
+ /* Split chunk into array of individual integers */
155
+ ints = chunks[i].split('').reverse().map(parseFloat);
156
+
157
+ /* If tens integer is 1, i.e. 10, then add 10 to units integer */
158
+ if (ints[1] === 1) {
159
+ ints[0] += 10;
160
+ }
161
+
162
+ /* Add scale word if chunk is not zero and array item exists */
163
+ if ((word = scales[i])) {
164
+ words.push(word);
165
+ }
166
+
167
+ /* Add unit word if array item exists */
168
+ if ((word = units[ints[0]])) {
169
+ words.push(word);
170
+ }
171
+
172
+ /* Add tens word if array item exists */
173
+ if ((word = tens[ints[1]])) {
174
+ words.push(word);
175
+ }
176
+
177
+ /* Add hundreds word if array item exists */
178
+ if ((word = units[ints[2]])) {
179
+ words.push(word + ' hundred');
180
+ }
181
+ }
182
+ }
183
+ return words.reverse().join(' ');
184
+ },
185
+
186
+ // Attempt to convert numerics into text as OS VoiceOver
187
+ // occasionally stalled when encountering numbers
188
+ timeToWords: function (t, unit) {
189
+ let words;
190
+ if (t > 0) {
191
+ try {
192
+ words = window.GOVUK.sessionDialog.numberToWords(t);
193
+ } catch (e) {
194
+ words = t;
195
+ }
196
+ words = words + ' ' + window.GOVUK.sessionDialog.pluralise(t, unit);
197
+ } else {
198
+ words = '';
199
+ }
200
+ return words;
201
+ },
202
+
203
+ pluralise: function (n, unit) {
204
+ return n == 1 ? unit : unit + 's';
205
+ },
206
+
207
+ numericSpan: function (n, unit) {
208
+ return '<span class="tabular-numbers">' + n + '</span> ' + window.GOVUK.sessionDialog.pluralise(n, unit);
209
+ },
210
+
211
+ countdownText: function (minutes, seconds) {
212
+ const minutesText = window.GOVUK.sessionDialog.numericSpan(minutes, 'minute');
213
+ const secondsText = window.GOVUK.sessionDialog.numericSpan(seconds, 'second');
214
+ return minutes > 0 ? minutesText : secondsText;
215
+ },
216
+
217
+ countdownAtText: function (minutes, seconds) {
218
+ const minutesText = window.GOVUK.sessionDialog.timeToWords(minutes, 'minute');
219
+ const secondsText = window.GOVUK.sessionDialog.timeToWords(seconds, 'second');
220
+ return minutes > 0 ? minutesText : secondsText;
221
+ },
222
+
223
+ startCountdown: function () {
224
+ const $timer = window.GOVUK.sessionDialog.$timer;
225
+ const $accessibleTimer = window.GOVUK.sessionDialog.$accessibleTimer;
226
+ let timerRunOnce = false;
227
+ const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
228
+
229
+ const seconds = window.GOVUK.sessionDialog.secondsUntilSessionTimeout();
230
+ const minutes = seconds / 60;
231
+
232
+ $timer.text(minutes + ' minute' + (minutes > 1 ? 's' : ''));
233
+
234
+ (function countdown() {
235
+ const secondsUntilSessionTimeout = window.GOVUK.sessionDialog.secondsUntilSessionTimeout();
236
+ const timerExpired = secondsUntilSessionTimeout <= window.GOVUK.sessionDialog.secondsFinalWarning;
237
+
238
+ if (!timerExpired) {
239
+
240
+ const minutesLeft = parseInt(secondsUntilSessionTimeout / 60, 10);
241
+ const secondsLeft = parseInt(secondsUntilSessionTimeout % 60, 10);
242
+
243
+
244
+ const atMinutesText = window.GOVUK.sessionDialog.timeToWords(minutesLeft, 'minute');
245
+ const atSecondsText = window.GOVUK.sessionDialog.timeToWords(secondsLeft, 'second');
246
+
247
+ // Below string will get read out by screen readers every time
248
+ // the timeout refreshes.
249
+ // Add additional information in extraText which will get announced to AT the
250
+ // first time the time out opens
251
+ const countdownText = window.GOVUK.sessionDialog.countdownText(minutesLeft, secondsLeft);
252
+ const text = window.GOVUK.sessionDialog.warningTextPrefix + '<strong>' + countdownText + '</strong>' + window.GOVUK.sessionDialog.warningTextSuffix;
253
+ const countdownAtText = window.GOVUK.sessionDialog.countdownAtText(atMinutesText, atSecondsText);
254
+ const atText = window.GOVUK.sessionDialog.warningTextPrefix + countdownAtText + window.GOVUK.sessionDialog.warningTextSuffix + 'bgbhj ' + window.GOVUK.sessionDialog.warningText;
255
+ const extraText = '\n' + window.GOVUK.sessionDialog.warningTextExtra;
256
+
257
+ $timer.html(text + ' ' + extraText);
258
+
259
+ // Update screen reader friendly content every 20 secs
260
+ if (secondsLeft % 20 === 0) {
261
+
262
+ // Read out the extra content only once.
263
+ // Don't read out on iOS VoiceOver which stalls on the longer text
264
+ if (!timerRunOnce && !iOS) {
265
+ $accessibleTimer.text(atText + extraText);
266
+ timerRunOnce = true;
267
+ } else {
268
+ $accessibleTimer.text(atText);
269
+ }
270
+ }
271
+
272
+ window.GOVUK.sessionDialog.addTimer(countdown,20);
273
+ }
274
+ })()
275
+ },
276
+
277
+ // Clears all timers
278
+ clearTimers: function () {
279
+ for (let i = 0; i < window.GOVUK.sessionDialog.timers.length; i++) {
280
+ clearInterval(window.GOVUK.sessionDialog.timers[i]);
281
+ }
282
+ },
283
+
284
+ refreshSession: function () {
285
+ $.get("");
286
+ window.GOVUK.sessionDialog.timeSessionRefreshed = new Date();
287
+ window.GOVUK.sessionDialog.controller();
288
+ },
289
+
290
+ redirect: function () {
291
+ window.location = window.GOVUK.sessionDialog.timeoutRedirectUrl;
292
+ },
293
+
294
+ // JS doesn't allow resetting timers globally so timers need
295
+ // to be retained for resetting.
296
+ addTimer: function (f, seconds) {
297
+ window.GOVUK.sessionDialog.timers.push(setInterval(f, seconds * 1000));
298
+ },
299
+
300
+ secondsSinceRefresh: function () {
301
+ return Math.round(Math.abs((window.GOVUK.sessionDialog.timeSessionRefreshed - new Date()) / 1000));
302
+ },
303
+
304
+ secondsUntilSessionTimeout: function () {
305
+ return window.GOVUK.sessionDialog.secondsSessionTimeout - window.GOVUK.sessionDialog.secondsSinceRefresh();
306
+ },
307
+
308
+ secondsUntilTimeoutWarning: function () {
309
+ return window.GOVUK.sessionDialog.secondsUntilSessionTimeout() - window.GOVUK.sessionDialog.secondsTimeoutWarning;
310
+ },
311
+
312
+ // countdown controller logic
313
+ controller: function () {
314
+ window.GOVUK.sessionDialog.clearTimers();
315
+
316
+ const secondsUntilSessionTimeout = window.GOVUK.sessionDialog.secondsUntilSessionTimeout();
317
+
318
+ //timed out - redirect
319
+ if (secondsUntilSessionTimeout <= 0) {
320
+ window.GOVUK.sessionDialog.redirect();
321
+ }
322
+
323
+ //timeout warning - show countdown and schedule redirect
324
+ else if (secondsUntilSessionTimeout <= window.GOVUK.sessionDialog.secondsTimeoutWarning) {
325
+ window.GOVUK.sessionDialog.openDialog();
326
+ window.GOVUK.sessionDialog.startCountdown();
327
+ window.GOVUK.sessionDialog.addTimer(window.GOVUK.sessionDialog.controller,window.GOVUK.sessionDialog.secondsUntilSessionTimeout());
328
+ }
329
+
330
+ //wait for warning
331
+ else {
332
+ window.GOVUK.sessionDialog.addTimer(window.GOVUK.sessionDialog.controller, window.GOVUK.sessionDialog.secondsUntilTimeoutWarning());
333
+ }
334
+ },
335
+
336
+ init: function (options) {
337
+ $.extend(window.GOVUK.sessionDialog, options);
338
+ if (window.GOVUK.sessionDialog.el && window.GOVUK.sessionDialog.isConfigured()) {
339
+ window.GOVUK.sessionDialog.bindUIElements();
340
+ window.GOVUK.sessionDialog.controller();
341
+ }
342
+ }
343
+ }
344
+
345
+ window.GOVUK = GOVUK;
@@ -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
  }