hof 21.0.0-instrumentation-beta.0 → 21.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. package/.github/workflows/automate-publish.yml +1 -1
  2. package/.github/workflows/automate-tag.yml +4 -4
  3. package/.nyc_output/39365c14-40b7-4634-b733-940b72a11984.json +1 -0
  4. package/.nyc_output/processinfo/39365c14-40b7-4634-b733-940b72a11984.json +1 -0
  5. package/.nyc_output/processinfo/index.json +1 -1
  6. package/CHANGELOG.md +21 -0
  7. package/README.md +340 -256
  8. package/build/tasks/sass/index.js +3 -1
  9. package/build/tasks/watch/index.js +1 -1
  10. package/codeReviewChecklist.md +22 -0
  11. package/components/combine-and-loop-fields/Readme.md +42 -0
  12. package/components/combine-and-loop-fields/index.js +156 -0
  13. package/components/date/index.js +3 -1
  14. package/components/date/templates/date.html +15 -12
  15. package/components/homeoffice-countries/index.js +22 -0
  16. package/components/index.js +2 -0
  17. package/components/notify/notify.js +2 -2
  18. package/components/summary/index.js +3 -2
  19. package/config/builder-defaults.js +3 -1
  20. package/config/component-defaults.js +13 -0
  21. package/config/hof-defaults.js +8 -0
  22. package/controller/controller.js +57 -1
  23. package/controller/formatting/formatters.js +12 -0
  24. package/controller/validation/index.js +2 -1
  25. package/controller/validation/validators.js +4 -0
  26. package/frontend/govuk-template/build/config.js +2 -2
  27. package/frontend/govuk-template/build/govuk_template.html +102 -0
  28. package/frontend/govuk-template/build/index.js +2 -2
  29. package/frontend/govuk-template/govuk_template_generated.html +102 -0
  30. package/frontend/govuk-template/index.js +4 -4
  31. package/frontend/template-mixins/mixins/template-mixins.js +40 -11
  32. package/frontend/template-mixins/partials/forms/checkbox-group.html +47 -0
  33. package/frontend/template-mixins/partials/forms/checkbox.html +9 -4
  34. package/frontend/template-mixins/partials/forms/input-submit.html +1 -1
  35. package/frontend/template-mixins/partials/forms/input-text-date.html +37 -0
  36. package/frontend/template-mixins/partials/forms/input-text-group.html +15 -10
  37. package/frontend/template-mixins/partials/forms/option-group.html +42 -26
  38. package/frontend/template-mixins/partials/forms/select.html +10 -5
  39. package/frontend/template-mixins/partials/forms/textarea-group.html +37 -23
  40. package/frontend/template-mixins/partials/mixins/panel.html +3 -4
  41. package/frontend/template-partials/views/accessibility.html +4 -4
  42. package/frontend/template-partials/views/cookies.html +1 -1
  43. package/frontend/template-partials/views/layout.html +24 -17
  44. package/frontend/template-partials/views/partials/back.html +1 -1
  45. package/frontend/template-partials/views/partials/bullet-list.html +1 -1
  46. package/frontend/template-partials/views/partials/confirmation-alert.html +4 -3
  47. package/frontend/template-partials/views/partials/continue.html +1 -1
  48. package/frontend/template-partials/views/partials/cookie-banner.html +27 -24
  49. package/frontend/template-partials/views/partials/cookie-settings-radio.html +6 -6
  50. package/frontend/template-partials/views/partials/external-link.html +1 -1
  51. package/frontend/template-partials/views/partials/form.html +2 -1
  52. package/frontend/template-partials/views/partials/gatag.html +0 -1
  53. package/frontend/template-partials/views/partials/head.html +23 -0
  54. package/frontend/template-partials/views/partials/maincontent-left.html +4 -4
  55. package/frontend/template-partials/views/partials/navigation.html +7 -6
  56. package/frontend/template-partials/views/partials/session-cookies-table.html +6 -6
  57. package/frontend/template-partials/views/partials/summary-table-row.html +2 -2
  58. package/frontend/template-partials/views/partials/table.html +7 -7
  59. package/frontend/template-partials/views/partials/validation-list.html +2 -2
  60. package/frontend/template-partials/views/partials/validation-summary.html +14 -13
  61. package/frontend/template-partials/views/partials/warn.html +7 -0
  62. package/frontend/template-partials/views/session-timeout.html +3 -2
  63. package/frontend/themes/gov-uk/client-js/cookieSettings.js +1 -1
  64. package/frontend/themes/gov-uk/client-js/govuk-cookies.js +121 -0
  65. package/frontend/themes/gov-uk/client-js/index.js +6 -1
  66. package/frontend/themes/gov-uk/client-js/skip-to-main.js +19 -0
  67. package/frontend/themes/gov-uk/styles/_cookie-banner.scss +51 -1
  68. package/frontend/themes/gov-uk/styles/govuk.scss +4 -0
  69. package/frontend/themes/gov-uk/styles/modules/_validation.scss +5 -5
  70. package/frontend/toolkit/assets/javascript/character-count.js +4 -4
  71. package/frontend/toolkit/assets/javascript/progressive-reveal.js +3 -1
  72. package/frontend/toolkit/assets/javascript/validation.js +5 -1
  73. package/frontend/toolkit/assets/stylesheets/modules/_validation.scss +3 -3
  74. package/index.js +15 -2
  75. package/lib/ga-tag.js +33 -7
  76. package/lib/settings.js +18 -2
  77. package/middleware/cookies.js +2 -0
  78. package/middleware/errors.js +2 -3
  79. package/middleware/not-found.js +0 -3
  80. package/middleware/rate-limiter.js +1 -0
  81. package/model/apis/axios-settings.js +21 -0
  82. package/model/apis/html-to-pdf-converter.js +10 -8
  83. package/model/index.js +102 -87
  84. package/package.json +18 -17
  85. package/pull_request.md +16 -0
  86. package/sandbox/README.md +3 -3
  87. package/sandbox/apps/sandbox/fields.js +33 -11
  88. package/sandbox/apps/sandbox/index.js +4 -0
  89. package/sandbox/apps/sandbox/sections/summary-data-sections.js +3 -0
  90. package/sandbox/apps/sandbox/translations/en/default.json +220 -0
  91. package/sandbox/apps/sandbox/translations/src/en/fields.json +11 -4
  92. package/sandbox/apps/sandbox/translations/src/en/journey.json +4 -1
  93. package/sandbox/apps/sandbox/translations/src/en/pages.json +7 -25
  94. package/sandbox/apps/sandbox/translations/src/en/validation.json +5 -1
  95. package/sandbox/assets/js/index.js +1 -1
  96. package/sandbox/assets/scss/app.scss +16 -16
  97. package/sandbox/package.json +7 -2
  98. package/sandbox/public/css/app.css +9632 -0
  99. package/sandbox/public/images/icons/icon-caret-left.png +0 -0
  100. package/sandbox/public/images/icons/icon-complete.png +0 -0
  101. package/sandbox/public/images/icons/icon-cross-remove-sign.png +0 -0
  102. package/sandbox/public/js/bundle.js +46721 -0
  103. package/sandbox/server.js +2 -1
  104. package/sandbox/yarn.lock +249 -2
  105. package/wizard/index.js +0 -13
  106. package/wizard/middleware/check-progress.js +36 -1
  107. package/.nyc_output/4d5a4574-78fc-4fcb-9412-3658f6ce33ff.json +0 -1
  108. package/.nyc_output/processinfo/4d5a4574-78fc-4fcb-9412-3658f6ce33ff.json +0 -1
  109. package/frontend/govuk-template/govuk_template.html +0 -109
  110. package/frontend/themes/gov-uk/views/partials/form.html +0 -9
  111. package/frontend/themes/gov-uk/views/partials/forms/option-group.html +0 -28
  112. package/frontend/themes/gov-uk/views/partials/mixins/panel.html +0 -3
  113. package/frontend/themes/gov-uk/views/partials/validation-summary.html +0 -24
  114. package/middleware/monitor.js +0 -20
  115. package/sandbox/apps/sandbox/views/confirmation.html +0 -15
@@ -35,7 +35,7 @@ function showCookieBannerSubmitted() {
35
35
  document.getElementById('cookie-banner-info').style.display = 'none';
36
36
  document.getElementById('cookie-banner-actions').style.display = 'none';
37
37
  var cookieBannerSubmitted = document.getElementById('cookie-banner-submitted');
38
- cookieBannerSubmitted.style.display = 'flex';
38
+ cookieBannerSubmitted.style.display = 'block';
39
39
  cookieBannerSubmitted.focus();
40
40
  }
41
41
 
@@ -0,0 +1,121 @@
1
+ /* eslint-disable no-undef, no-param-reassign, no-unused-vars */
2
+ (function () {
3
+ 'use strict';
4
+ const root = this;
5
+ if(typeof root.GOVUK === 'undefined') { root.GOVUK = {}; }
6
+
7
+ /*
8
+ Cookie methods
9
+ ==============
10
+
11
+ Usage:
12
+
13
+ Setting a cookie:
14
+ GOVUK.cookie('hobnob', 'tasty', { days: 30 });
15
+
16
+ Reading a cookie:
17
+ GOVUK.cookie('hobnob');
18
+
19
+ Deleting a cookie:
20
+ GOVUK.cookie('hobnob', null);
21
+ */
22
+ GOVUK.cookie = function (name, value, options) {
23
+ if(typeof value !== 'undefined') {
24
+ if(value === false || value === null) {
25
+ return GOVUK.setCookie(name, '', { days: -1 });
26
+ }
27
+ return GOVUK.setCookie(name, value, options);
28
+ }
29
+ return GOVUK.getCookie(name);
30
+ };
31
+ GOVUK.setCookie = function (name, value, options) {
32
+ if(typeof options === 'undefined') {
33
+ options = {};
34
+ }
35
+ let cookieString = name + '=' + value + '; path=/';
36
+ if (options.days) {
37
+ const date = new Date();
38
+ date.setTime(date.getTime() + (options.days * 24 * 60 * 60 * 1000));
39
+ cookieString = cookieString + '; expires=' + date.toGMTString();
40
+ }
41
+ if (document.location.protocol === 'https:') {
42
+ cookieString = cookieString + '; Secure';
43
+ }
44
+ document.cookie = cookieString;
45
+ };
46
+ GOVUK.getCookie = function (name) {
47
+ const nameEQ = name + '=';
48
+ const cookies = document.cookie.split(';');
49
+ for(let i = 0, len = cookies.length; i < len; i++) {
50
+ let cookie = cookies[i];
51
+ while (cookie.charAt(0) === ' ') {
52
+ cookie = cookie.substring(1, cookie.length);
53
+ }
54
+ if (cookie.indexOf(nameEQ) === 0) {
55
+ return decodeURIComponent(cookie.substring(nameEQ.length));
56
+ }
57
+ }
58
+ return null;
59
+ };
60
+ }).call(this);
61
+ (function () {
62
+ 'use strict';
63
+ const root = this;
64
+ if (typeof root.GOVUK === 'undefined') { root.GOVUK = {}; }
65
+
66
+ GOVUK.addCookieMessage = function () {
67
+ const message = document.getElementById('global-cookie-message');
68
+
69
+ const hasCookieMessage = (message && GOVUK.cookie('seen_cookie_message') === null);
70
+
71
+ if (hasCookieMessage) {
72
+ message.style.display = 'block';
73
+ GOVUK.cookie('seen_cookie_message', 'yes', { days: 28 });
74
+
75
+ document.addEventListener('DOMContentLoaded', function (event) {
76
+ if (GOVUK.analytics && typeof GOVUK.analytics.trackEvent === 'function') {
77
+ GOVUK.analytics.trackEvent('cookieBanner', 'Cookie banner shown', {
78
+ value: 1,
79
+ nonInteraction: true
80
+ });
81
+ }
82
+ });
83
+ }
84
+ };
85
+ }).call(this)
86
+ ;
87
+ (function () {
88
+ 'use strict';
89
+
90
+ // add cookie message
91
+ if (window.GOVUK && GOVUK.addCookieMessage) {
92
+ GOVUK.addCookieMessage();
93
+ }
94
+
95
+ // header navigation toggle
96
+ if (document.querySelectorAll && document.addEventListener) {
97
+ const els = document.querySelectorAll('.js-header-toggle');
98
+ let i; let _i;
99
+ for(i = 0, _i = els.length; i < _i; i++) {
100
+ els[i].addEventListener('click', function (e) {
101
+ e.preventDefault();
102
+ const target = document.getElementById(this.getAttribute('href').substr(1));
103
+ const targetClass = target.getAttribute('class') || '';
104
+ const sourceClass = this.getAttribute('class') || '';
105
+
106
+ if(targetClass.indexOf('js-visible') !== -1) {
107
+ target.setAttribute('class', targetClass.replace(/(^|\s)js-visible(\s|$)/, ''));
108
+ } else {
109
+ target.setAttribute('class', targetClass + ' js-visible');
110
+ }
111
+ if(sourceClass.indexOf('js-visible') !== -1) {
112
+ this.setAttribute('class', sourceClass.replace(/(^|\s)js-visible(\s|$)/, ''));
113
+ } else {
114
+ this.setAttribute('class', sourceClass + ' js-visible');
115
+ }
116
+ this.setAttribute('aria-expanded', this.getAttribute('aria-expanded') !== 'true');
117
+ target.setAttribute('aria-hidden', target.getAttribute('aria-hidden') === 'false');
118
+ });
119
+ }
120
+ }
121
+ }).call(this);
@@ -1,4 +1,4 @@
1
- /* eslint-disable no-var */
1
+ /* eslint-disable no-var, vars-on-top, no-unused-vars */
2
2
  'use strict';
3
3
 
4
4
  var toolkit = require('../../../toolkit');
@@ -8,6 +8,11 @@ var formFocus = toolkit.formFocus;
8
8
  var characterCount = toolkit.characterCount;
9
9
  var validation = toolkit.validation;
10
10
 
11
+ var GOVUK = require('govuk-frontend');
12
+ GOVUK.initAll();
13
+ window.GOVUK = GOVUK;
14
+ var skipToMain = require('./skip-to-main');
15
+ var cookie = require('./govuk-cookies');
11
16
  var cookieSettings = require('./cookieSettings');
12
17
 
13
18
  toolkit.detailsSummary();
@@ -0,0 +1,19 @@
1
+ const skipToMain = function () {
2
+ const skipToMainLink = document.getElementById('skip-to-main');
3
+ const firstControlId = skipToMainLink.hash.split('#')[1] ? skipToMainLink.hash.split('#')[1] : 'main-content';
4
+ if(firstControlId === 'main-content') {
5
+ skipToMainLink.setAttribute('href', '#main-content');
6
+ }
7
+ if(firstControlId) {
8
+ // eslint-disable-next-line no-unused-vars
9
+ skipToMainLink.onclick = function (e) {
10
+ // here timeout added just to make this functionality asynchronous
11
+ // to focus on form as well as non form contents
12
+ setTimeout(() => {
13
+ const firstControl = document.getElementById(firstControlId);
14
+ firstControl.focus();
15
+ }, 10);
16
+ };
17
+ }
18
+ };
19
+ skipToMain();
@@ -10,7 +10,6 @@
10
10
  }
11
11
 
12
12
  #cookie-banner {
13
- max-width: 960px;
14
13
  margin: 0 15px;
15
14
  p {
16
15
  margin: 0;
@@ -62,3 +61,54 @@
62
61
  height: fit-content;
63
62
  }
64
63
  }
64
+
65
+ // the following are additional hof specific govuk cookie banner styling
66
+ .govuk-banner--success {
67
+ border-color: #00703c;
68
+ color: #00703c;
69
+ }
70
+
71
+ .govuk-banner {
72
+ border: 5px solid #1d70b8;
73
+ font-size: 0;
74
+ margin-bottom: 30px;
75
+ padding: 10px;
76
+ }
77
+
78
+ .govuk-banner__icon{
79
+ display: inline-block;
80
+ }
81
+
82
+ .govuk-banner__message {
83
+ font-family: "GDS Transport", Arial, sans-serif;
84
+ -webkit-font-smoothing: antialiased;
85
+ font-weight: 400;
86
+ font-size: 1rem;
87
+ line-height: 1.25;
88
+ color: #0b0c0c;
89
+ display: block;
90
+ overflow: hidden;
91
+ display: inline-block;
92
+ margin-left: 10px;
93
+ }
94
+
95
+ .govuk-banner__assistive {
96
+ position: absolute !important;
97
+ width: 1px !important;
98
+ height: 1px !important;
99
+ margin: 0 !important;
100
+ padding: 0 !important;
101
+ overflow: hidden !important;
102
+ clip: rect(0 0 0 0) !important;
103
+ clip-path: inset(50%) !important;
104
+ border: 0 !important;
105
+ white-space: nowrap !important;
106
+ }
107
+
108
+ .cookie-table-holder > table > tbody > tr > td:first-child{
109
+ font-weight:bold;
110
+ }
111
+
112
+ .js-enabled #global-cookie-message {
113
+ display: none;
114
+ }
@@ -12,6 +12,10 @@ $path: "/public/images/" !default;
12
12
  // https://github.com/alphagov/govuk_elements/blob/master/packages/govuk-elements-sass/public/sass/_elements.scss
13
13
  @import "govuk-elements-sass/public/sass/elements";
14
14
 
15
+ // Govuk frontend
16
+ // https://github.com/alphagov/govuk-frontend-docs
17
+ @import "govuk-frontend";
18
+
15
19
  // Custom
16
20
  @import "base";
17
21
  @import "layout";
@@ -22,10 +22,10 @@
22
22
  }
23
23
  }
24
24
 
25
- .validation-error {
25
+ .govuk-form-group--error {
26
26
  box-sizing: border-box;
27
27
  padding-left: $gutter-half - $validation-bdr-size;
28
- border-left: $validation-bdr-size-lg solid $error-colour;
28
+ //border-left: $validation-bdr-size-lg solid $error-colour;
29
29
 
30
30
  &:focus {
31
31
  outline: $focus-outline;
@@ -36,16 +36,16 @@
36
36
  }
37
37
  }
38
38
 
39
- .error-message {
39
+ .govuk-error-message {
40
40
  display: block;
41
41
  @include media(tablet) {
42
42
  margin-bottom: 0.5em;
43
43
  }
44
44
  @include bold-19;
45
- color: $error-colour;
45
+ //color: $error-colour;
46
46
  }
47
47
 
48
48
  .invalid-input,
49
- .validation-error .date-input {
49
+ .govuk-form-group--error .date-input {
50
50
  border: $validation-bdr-size solid $error-colour;
51
51
  }
@@ -30,12 +30,12 @@ CharacterCount.prototype.updateCount = function () {
30
30
  this.$maxlengthHint.innerHTML = 'You have ' + number + characterNoun + remainderSuffix;
31
31
 
32
32
  if (currentLength >= this.maxLength + 1) {
33
- helpers.removeClass(this.$maxlengthHint, 'form-hint');
34
- helpers.addClass(this.$maxlengthHint, 'error-message');
33
+ helpers.removeClass(this.$maxlengthHint, 'govuk-hint');
34
+ helpers.addClass(this.$maxlengthHint, 'govuk-error-message');
35
35
  helpers.addClass(this.$textarea, 'textarea-error');
36
36
  } else {
37
- helpers.addClass(this.$maxlengthHint, 'form-hint');
38
- helpers.removeClass(this.$maxlengthHint, 'error-message');
37
+ helpers.addClass(this.$maxlengthHint, 'govuk-hint');
38
+ helpers.removeClass(this.$maxlengthHint, 'govuk-error-message');
39
39
  helpers.removeClass(this.$textarea, 'textarea-error');
40
40
  }
41
41
  };
@@ -7,12 +7,14 @@ var groupBy = require('lodash').groupBy;
7
7
  var helpers = require('./helpers');
8
8
  var inputs; var groups;
9
9
  var toggleAttr = 'data-toggle';
10
- var hiddenClass = 'js-hidden';
10
+ var checkboxHiddenClass = 'govuk-checkboxes__conditional--hidden';
11
+ var radioHiddenClass = 'govuk-radios__conditional--hidden';
11
12
 
12
13
  function inputClicked(e, target) {
13
14
  target = target || helpers.target(e);
14
15
  var shown;
15
16
  each(groups[target.name], function (input) {
17
+ var hiddenClass = (input.type.match(/checkbox/)) ? checkboxHiddenClass : radioHiddenClass;
16
18
  var id = input.getAttribute('aria-controls');
17
19
  var toggle = document.getElementById(id);
18
20
  if (toggle) {
@@ -53,7 +53,11 @@ function setup(summary) {
53
53
  }
54
54
 
55
55
  function validation() {
56
- var summaries = helpers.getElementsByClass(document.getElementById('content'), 'div', 'validation-summary');
56
+ var summaries = [];
57
+
58
+ if (document.getElementById('content')) {
59
+ summaries = helpers.getElementsByClass(document.getElementById('content'), 'div', 'validation-summary');
60
+ }
57
61
 
58
62
  if (summaries.length) {
59
63
  summary = summaries[0];
@@ -22,7 +22,7 @@
22
22
  }
23
23
  }
24
24
 
25
- .validation-error {
25
+ .govuk-form-group--error {
26
26
  box-sizing: border-box;
27
27
  padding-left: $gutter-half - $validation-bdr-size;
28
28
  border-left: $validation-bdr-size-lg solid $error-colour;
@@ -36,7 +36,7 @@
36
36
  }
37
37
  }
38
38
 
39
- .error-message {
39
+ .govuk-error-message {
40
40
  display: block;
41
41
  @include media(tablet) {
42
42
  margin-bottom: 0.5em;
@@ -46,6 +46,6 @@
46
46
  }
47
47
 
48
48
  .invalid-input,
49
- .validation-error .date-input {
49
+ .govuk-form-group--error .date-input {
50
50
  border: $validation-bdr-size solid $error-colour;
51
51
  }
package/index.js CHANGED
@@ -78,8 +78,16 @@ const getContentSecurityPolicy = (config, res) => {
78
78
  styleSrc: ['www.googletagmanager.com', 'fonts.googleapis.com', 'tagmanager.google.com'],
79
79
  fontSrc: ['fonts.gstatic.com '],
80
80
  scriptSrc: ['www.google-analytics.com', 'ssl.google-analytics.com'],
81
- imgSrc: ['www.google-analytics.com', 'ssl.gstatic.com'],
82
- connectSrc: ['https://www.google-analytics.com', 'https://region1.google-analytics.com']
81
+ imgSrc: [
82
+ 'www.google-analytics.com',
83
+ 'ssl.gstatic.com',
84
+ 'www.google.co.uk/ads/ga-audiences'
85
+ ],
86
+ connectSrc: [
87
+ 'https://www.google-analytics.com',
88
+ 'https://region1.google-analytics.com',
89
+ 'https://region1.analytics.google.com'
90
+ ]
83
91
  };
84
92
 
85
93
  if (config.gaTagId) {
@@ -120,6 +128,8 @@ const getContentSecurityPolicy = (config, res) => {
120
128
  * @param options.getTerms {boolean} Optional boolean - whether to mount the /terms endpoint
121
129
  * @param options.getCookies {boolean} Optional boolean - whether to mount the /cookies endpoint
122
130
  * @param options.noCache {boolean} Optional boolean - whether to disable caching
131
+ * @param options.getAccessibilityStatement {boolean} Optional boolean - whether to mount the
132
+ * /accessibility-statement endpoint
123
133
  *
124
134
  * @returns {object} A new HOF application using the configuration supplied in options
125
135
  */
@@ -209,6 +219,9 @@ function bootstrap(options) {
209
219
  app.use(hofMiddleware.rateLimiter(config, 'requests'));
210
220
  }
211
221
 
222
+ // Set up routing so <YOUR-SITE-URL>/assets are served from /node_modules/govuk-frontend/govuk/assets
223
+ app.use('/assets', express.static(path.join(__dirname, '/node_modules/govuk-frontend/govuk/assets')));
224
+
212
225
  if (config.getAccessibility === true) {
213
226
  deprecate(
214
227
  '`getAccessibility` option is deprecated and may be removed in future versions.',
package/lib/ga-tag.js CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  const _ = require('lodash');
4
4
 
5
+ const convertToGTMPage = text => {
6
+ // Remove leading and trailing slashes
7
+ let str = text.replace(/^\/|\/$/g, '');
8
+ // Replace hyphens with spaces and capitalize each word
9
+ str = str.replace(/-+/g, ' ').replace(/(^|\s)\S/g, function (match) {
10
+ return match.toUpperCase();
11
+ });
12
+ return str;
13
+ };
14
+
5
15
  const pageView = (path, pageMap) => pageMap.get(path) || path;
6
16
 
7
17
  const createUris = routes => {
@@ -42,19 +52,35 @@ const setupPageMap = routes => {
42
52
  module.exports = (app, config) => {
43
53
  const gaTagId = config.gaTagId;
44
54
  const ga4TagId = config.ga4TagId;
55
+ const gtm = config.gtm;
45
56
  const gaCrossDomainTrackingTagId = config.gaCrossDomainTrackingTagId;
46
57
  const routes = config.routes;
47
58
 
48
- if (gaTagId) {
59
+ if (gaTagId || ga4TagId || gtm.tagId) {
49
60
  const pageMap = setupPageMap(routes);
50
61
 
51
62
  app.use((req, res, next) => {
52
- res.locals.gaAllowDebug = config.env === 'development';
53
- res.locals.gaTagId = gaTagId;
54
- res.locals.ga4TagId = ga4TagId;
55
- res.locals.gaCrossDomainTrackingTagId = gaCrossDomainTrackingTagId;
56
- res.locals['ga-id'] = gaTagId;
57
- res.locals['ga-page'] = pageView(req.path, pageMap);
63
+ const page = pageView(req.path, pageMap);
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);
58
84
  next();
59
85
  });
60
86
  }
package/lib/settings.js CHANGED
@@ -7,7 +7,22 @@ const hoganExpressStrict = require('hogan-express-strict');
7
7
  const expressPartialTemplates = require('express-partial-templates');
8
8
  const bodyParser = require('body-parser');
9
9
 
10
- module.exports = (app, config) => {
10
+ const dirExists = dir => {
11
+ try {
12
+ if (fs.existsSync(dir)) {
13
+ return true;
14
+ }
15
+ return false;
16
+ } catch(err) {
17
+ throw new Error(`${err}: Cannot check if the directory path exists`);
18
+ }
19
+ };
20
+
21
+ const filterEmptyViews = views => {
22
+ return views.filter(view => dirExists(view));
23
+ };
24
+
25
+ module.exports = async (app, config) => {
11
26
  const viewEngine = config.viewEngine || 'html';
12
27
 
13
28
  app.use((req, res, next) => {
@@ -17,7 +32,8 @@ module.exports = (app, config) => {
17
32
 
18
33
  app.use(config.theme());
19
34
 
20
- const viewPaths = [].concat(config.theme.views);
35
+ const filteredViews = filterEmptyViews(config.theme.views);
36
+ const viewPaths = [].concat(filteredViews);
21
37
  app.set('view engine', viewEngine);
22
38
  app.enable('view cache');
23
39
 
@@ -22,6 +22,8 @@ module.exports = options => {
22
22
  const reqIsCookieCheckRedirect = req.query[paramName] !== undefined;
23
23
 
24
24
  if (reqIncludesCookies || isHealthcheckUrl(req.path, healthcheckUrls)) {
25
+ const prefs = 'cookie_preferences' in req.cookies ? JSON.parse(req.cookies.cookie_preferences) : {};
26
+ res.locals.cookiesAccepted = Boolean(prefs.usage);
25
27
  next();
26
28
  } else if (req.cookies === undefined || (!Object.keys(req.cookies).length && reqIsCookieCheckRedirect)) {
27
29
  const err = new Error('Cookies required');
@@ -2,7 +2,6 @@
2
2
  'use strict';
3
3
 
4
4
  const rateLimitsConfig = require('../config/rate-limits');
5
- const monitor = require('./monitor');
6
5
 
7
6
  const errorTitle = code => `${code}_ERROR`;
8
7
  const errorMsg = code => `There is a ${code}_ERROR`;
@@ -13,6 +12,8 @@ const getContent = (err, translate) => {
13
12
  if (err.code === 'SESSION_TIMEOUT') {
14
13
  err.status = 401;
15
14
  err.template = 'session-timeout';
15
+ err.title = (translate && translate('errors.session.title'));
16
+ err.message = (translate && translate('errors.session.message'));
16
17
  content.title = (translate && translate('errors.session.title'));
17
18
  content.message = (translate && translate('errors.session.message'));
18
19
  }
@@ -90,8 +91,6 @@ module.exports = options => {
90
91
  baseUrl: returnBaseUrl(req.path)
91
92
  };
92
93
 
93
- monitor(req, res, err.status);
94
-
95
94
  if (logger && logger.error) {
96
95
  logger.error(err.message || err.error, err);
97
96
  }
@@ -1,5 +1,4 @@
1
1
  'use strict';
2
- const monitor = require('./monitor');
3
2
 
4
3
  const getTranslations = translate => {
5
4
  const translations = {
@@ -27,8 +26,6 @@ module.exports = options => {
27
26
  logger.warn(`Cannot find: ${req.url}`);
28
27
  }
29
28
 
30
- monitor(req, res, '404');
31
-
32
29
  res.status(404).render('404', {
33
30
  title: translations.title,
34
31
  description: translations.description,
@@ -4,6 +4,7 @@ const redis = require('redis');
4
4
  const config = require('./../config/hof-defaults');
5
5
 
6
6
  module.exports = (options, rateLimitType) => {
7
+ // eslint-disable-next-line no-console
7
8
  const logger = options.logger || { log: (func, msg) => console[func](msg) };
8
9
  const rateLimits = options.rateLimits[rateLimitType];
9
10
  const timestampName = `${rateLimitType}TimeStamp`;
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+ const { format } = require('url'); // Destructure 'format' from 'url' module
3
+
4
+ module.exports = (settings = {}, body = null) => {
5
+ if (typeof settings !== 'object' || settings === null) {
6
+ throw new TypeError('settings must be a non-null object');
7
+ }
8
+
9
+ const {
10
+ uri,
11
+ url,
12
+ body: settingsBody,
13
+ data: settingsData,
14
+ ...restSettings
15
+ } = settings;
16
+
17
+ return Object.assign({}, restSettings, {
18
+ url: uri || url || format(settings),
19
+ data: settingsBody || body || settingsData
20
+ });
21
+ };
@@ -9,6 +9,7 @@ module.exports = class PDFModel extends Model {
9
9
  const settings = super.requestConfig(options);
10
10
  settings.encoding = null;
11
11
  settings.rejectUnauthorized = false;
12
+ settings.responseType = 'arraybuffer';
12
13
  return settings;
13
14
  }
14
15
 
@@ -17,17 +18,18 @@ module.exports = class PDFModel extends Model {
17
18
  }
18
19
 
19
20
  handleResponse(response, callback) {
20
- if (isPdf(Buffer.from(response.body))) {
21
- return this.parseResponse(response.statusCode, response.body, callback);
21
+ if (isPdf(Buffer.from(response.data))) {
22
+ return this.parseResponse(response.status, response.data, callback);
22
23
  }
23
24
  const err = new Error();
24
- if (parseInt(response.statusCode, 10) === 400) {
25
- err.title = response.body.code;
26
- err.message = response.body.message;
25
+
26
+ if (parseInt(response.status, 10) === 400) {
27
+ err.title = response.status;
28
+ err.message = response.statusText;
27
29
  } else {
28
- err.body = response.body;
30
+ err.body = response.data;
29
31
  }
30
- err.status = response.statusCode;
31
- return callback(err, null, response.statusCode);
32
+ err.status = response.status;
33
+ return callback(err, null, response.status);
32
34
  }
33
35
  };