govuk_publishing_components 57.1.0 → 57.2.0

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/govuk_publishing_components/intervention/hmrc.svg +5 -0
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +4 -0
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-event-tracker.js +22 -0
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-form-tracker.js +72 -12
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +2 -2
  7. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/pii-remover.js +10 -0
  8. data/app/assets/javascripts/govuk_publishing_components/components/add-another.js +57 -7
  9. data/app/assets/javascripts/govuk_publishing_components/components/reorderable-list.js +24 -4
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_intervention.scss +17 -0
  11. data/app/controllers/govuk_publishing_components/audit_controller.rb +0 -1
  12. data/app/views/govuk_publishing_components/components/_add_another.html.erb +2 -0
  13. data/app/views/govuk_publishing_components/components/_intervention.html.erb +7 -2
  14. data/app/views/govuk_publishing_components/components/_reorderable_list.html.erb +24 -2
  15. data/app/views/govuk_publishing_components/components/docs/add_another.yml +25 -0
  16. data/app/views/govuk_publishing_components/components/docs/intervention.yml +10 -0
  17. data/app/views/govuk_publishing_components/components/docs/reorderable_list.yml +16 -0
  18. data/config/locales/ar.yml +12 -3
  19. data/config/locales/az.yml +12 -3
  20. data/config/locales/be.yml +12 -3
  21. data/config/locales/bg.yml +12 -3
  22. data/config/locales/bn.yml +12 -3
  23. data/config/locales/cs.yml +12 -3
  24. data/config/locales/cy.yml +14 -5
  25. data/config/locales/da.yml +12 -3
  26. data/config/locales/de.yml +12 -3
  27. data/config/locales/dr.yml +12 -3
  28. data/config/locales/el.yml +12 -3
  29. data/config/locales/en.yml +16 -7
  30. data/config/locales/es-419.yml +12 -3
  31. data/config/locales/es.yml +12 -3
  32. data/config/locales/et.yml +12 -3
  33. data/config/locales/fa.yml +12 -3
  34. data/config/locales/fi.yml +12 -3
  35. data/config/locales/fr.yml +12 -3
  36. data/config/locales/gd.yml +12 -3
  37. data/config/locales/gu.yml +12 -3
  38. data/config/locales/he.yml +12 -3
  39. data/config/locales/hi.yml +12 -3
  40. data/config/locales/hr.yml +12 -3
  41. data/config/locales/hu.yml +12 -3
  42. data/config/locales/hy.yml +12 -3
  43. data/config/locales/id.yml +12 -3
  44. data/config/locales/is.yml +12 -3
  45. data/config/locales/it.yml +12 -3
  46. data/config/locales/ja.yml +12 -3
  47. data/config/locales/ka.yml +12 -3
  48. data/config/locales/kk.yml +12 -3
  49. data/config/locales/ko.yml +12 -3
  50. data/config/locales/lt.yml +12 -3
  51. data/config/locales/lv.yml +12 -3
  52. data/config/locales/ms.yml +12 -3
  53. data/config/locales/mt.yml +12 -3
  54. data/config/locales/ne.yml +12 -6
  55. data/config/locales/nl.yml +12 -3
  56. data/config/locales/no.yml +12 -3
  57. data/config/locales/pa-pk.yml +12 -3
  58. data/config/locales/pa.yml +12 -3
  59. data/config/locales/pl.yml +12 -3
  60. data/config/locales/ps.yml +12 -3
  61. data/config/locales/pt.yml +12 -3
  62. data/config/locales/ro.yml +12 -3
  63. data/config/locales/ru.yml +12 -3
  64. data/config/locales/si.yml +12 -3
  65. data/config/locales/sk.yml +12 -3
  66. data/config/locales/sl.yml +12 -3
  67. data/config/locales/so.yml +12 -3
  68. data/config/locales/sq.yml +12 -3
  69. data/config/locales/sr.yml +12 -3
  70. data/config/locales/sv.yml +12 -3
  71. data/config/locales/sw.yml +12 -3
  72. data/config/locales/ta.yml +12 -3
  73. data/config/locales/th.yml +12 -3
  74. data/config/locales/tk.yml +12 -3
  75. data/config/locales/tr.yml +12 -3
  76. data/config/locales/uk.yml +12 -3
  77. data/config/locales/ur.yml +12 -3
  78. data/config/locales/uz.yml +12 -3
  79. data/config/locales/vi.yml +12 -3
  80. data/config/locales/zh-hk.yml +12 -3
  81. data/config/locales/zh-tw.yml +12 -3
  82. data/config/locales/zh.yml +12 -3
  83. data/lib/govuk_publishing_components/presenters/devolved_nations_helper.rb +14 -13
  84. data/lib/govuk_publishing_components/version.rb +1 -1
  85. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8767b5e700d2cf0da57d46943ed8ed4e645f510fb872ecc422293270abf339b
4
- data.tar.gz: 375137a4c58f557ae925e83cb03bd59e80da2198f87c846c26ed608741e141fe
3
+ metadata.gz: fc35380bef3675b6001b4827358013c9c54218a696fbe7170625d5c0c9f33bdd
4
+ data.tar.gz: 77f96614f15a6e7978e3265bf3f3275e25826f7cd3a629cc90bbb55cb2675c30
5
5
  SHA512:
6
- metadata.gz: 4d6b71754931f043138955f7762a252c0763cf5e59f01fa168589268586e92f83d2e50ec7908d249815ab0132467af7cbd4b6132ecbf8c67b62ba2012eb36cab
7
- data.tar.gz: 93b9a850cef309bfb5f37ceef3e7716f958186c26bad463681a3f6419a9eb570209e75fe7c0361186aa1bf940868887e2719a0ed840fd1bf23a251c42c856009
6
+ metadata.gz: 765da3cf1fb7d292acb42f840bc373166360790f30cb869334629750042fe0e7869ff310115e21019757f8bce65f5b3ad6e2ecaca1ac5f06d39f93592370d4ac
7
+ data.tar.gz: fe864e55147fd9faf3986d951c5af9b91d96c218563b2a1a080fb742c14ed0aca1dddc3ec01e281259a32e628cc0745644c54ab7ed558c87e62066c44818d582
@@ -0,0 +1,5 @@
1
+ <svg width="480" height="480" viewBox="0 0 480 480" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="480" height="480" fill="#008670"/>
3
+ <circle cx="240" cy="240" r="175" stroke="white" stroke-width="22"/>
4
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M271.481 179.736C268.533 172.742 271.935 164.633 279.115 161.806C286.145 158.978 294.308 162.326 297.256 169.32C300.204 176.314 296.803 184.274 289.773 187.176C282.592 190.078 274.429 186.73 271.557 179.736H271.481ZM234.746 211.356C227.566 214.258 224.24 222.367 227.112 229.286C230.06 236.28 238.148 239.628 245.328 236.726C252.358 233.899 255.759 225.864 252.811 218.87C249.864 211.877 241.7 208.454 234.671 211.356H234.746ZM327.113 209.05C334.142 206.222 337.544 198.187 334.596 191.194C331.648 184.2 323.484 180.778 316.455 183.679C309.274 186.581 305.949 194.69 308.821 201.61C311.769 208.603 319.856 211.951 327.037 208.975L327.113 209.05ZM333.613 237.842C336.561 244.836 344.649 248.184 351.829 245.208C358.859 242.381 362.26 234.346 359.312 227.352C356.364 220.358 348.201 216.936 341.172 219.838C333.991 222.739 330.665 230.849 333.537 237.768L333.613 237.842ZM232.63 144.619C233.159 145.289 233.764 145.884 234.444 146.405L224.315 176.462V176.611C223.862 178.099 223.56 179.736 223.56 181.373C223.56 189.482 229.682 196.253 237.619 197.369H237.997C238.677 197.443 239.357 197.518 240.037 197.518C240.718 197.518 241.398 197.518 242.078 197.369H242.456C250.393 196.178 256.515 189.482 256.515 181.373C256.515 179.736 256.288 178.099 255.759 176.611V176.462L245.631 146.405C246.311 145.884 246.916 145.289 247.445 144.619C247.974 143.95 265.056 153.696 265.056 153.696V128.102L247.445 133.608C246.991 132.938 246.387 132.343 245.706 131.822C245.026 131.302 252.811 109.8 252.811 109.8H227.415L234.52 131.748C233.915 132.269 233.31 132.864 232.781 133.534C232.252 134.203 215.17 128.102 215.17 128.102V153.696L232.781 144.545L232.63 144.619ZM190.075 187.176C197.256 190.078 205.419 186.73 208.291 179.736C211.239 172.742 207.838 164.633 200.657 161.806C193.628 158.978 185.464 162.326 182.516 169.32C179.569 176.314 182.97 184.274 189.999 187.176H190.075ZM152.735 209.124C159.916 212.026 168.079 208.678 170.952 201.758C173.9 194.765 170.498 186.655 163.317 183.828C156.288 181.001 148.125 184.349 145.177 191.342C142.229 198.336 145.63 206.297 152.66 209.198L152.735 209.124ZM128.019 245.357C135.199 248.258 143.363 244.91 146.235 237.991C149.183 230.998 145.782 222.888 138.601 220.061C131.571 217.234 123.408 220.582 120.46 227.575C117.512 234.569 120.914 242.53 127.943 245.431L128.019 245.357ZM342.079 260.832C343.968 270.281 344.271 274.67 342.154 280.771C339.055 277.795 336.107 272.215 333.764 263.808L324.618 293.866C330.212 290.071 334.52 287.616 339.433 287.542C330.741 306.067 319.781 310.829 312.751 309.49C304.134 307.927 300.128 300.338 301.489 293.94C303.454 284.863 312.978 282.482 317.362 293.047C325.828 276.01 311.466 270.727 302.245 275.786C316.455 261.799 318.042 249.449 306.629 234.42C290.68 246.473 290.453 258.377 297.634 275.117C288.337 264.626 273.749 270.281 279.04 287.244C285.767 276.977 294.686 283.45 293.25 293.196C292.041 301.678 280.703 308.522 266.493 307.332C246.16 305.546 244.951 291.708 244.421 280.325C249.41 279.432 258.405 283.97 266.115 294.61L268.911 262.766C260.597 271.322 252.963 272.959 244.573 273.182C247.369 264.552 260.294 250.49 260.294 250.49H219.856C219.856 250.49 232.706 264.626 235.578 273.182C227.188 272.885 219.554 271.322 211.239 262.766L214.036 294.61C221.746 284.045 230.665 279.432 235.729 280.325C235.2 291.782 233.991 305.546 213.658 307.332C199.448 308.522 188.11 301.678 186.9 293.196C185.464 283.45 194.383 276.977 201.111 287.244C206.326 270.281 191.813 264.626 182.516 275.117C189.697 258.377 189.546 246.473 173.522 234.42C162.033 249.449 163.695 261.799 177.906 275.786C168.684 270.727 154.247 276.084 162.788 293.047C167.248 282.482 176.696 284.863 178.661 293.94C180.022 300.338 176.016 307.927 167.399 309.49C160.37 310.754 149.41 305.993 140.717 287.542C145.63 287.69 149.939 290.071 155.532 293.866L146.386 263.808C144.043 272.215 141.095 277.795 137.996 280.771C135.88 274.67 136.182 270.281 137.996 260.832L119.1 267.454C129.153 280.92 138.903 299.892 146.84 333C175.033 329.057 206.628 326.825 239.962 326.825C273.295 326.825 304.966 329.057 333.16 333C341.172 299.892 350.922 280.92 360.9 267.454L342.003 260.832H342.079Z" fill="white"/>
5
+ </svg>
@@ -211,6 +211,10 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
211
211
  return string.substring(string.length - stringToFind.length, string.length) === stringToFind
212
212
  },
213
213
 
214
+ toSnakeCase: function (str) {
215
+ return str.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase()
216
+ },
217
+
214
218
  populateLinkDomain: function (href) {
215
219
  // We always want mailto links to have an undefined link_domain
216
220
  if (this.isMailToLink(href)) {
@@ -28,6 +28,26 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
28
28
  }
29
29
  }
30
30
 
31
+ Ga4EventTracker.prototype.getTargetDatasetSchema = function (element) {
32
+ var targetDataset
33
+
34
+ try {
35
+ targetDataset = element.dataset
36
+ } catch (error) {
37
+ console.error(error)
38
+ }
39
+
40
+ var eventData = {}
41
+
42
+ Object.keys(targetDataset).forEach(function (key) {
43
+ var schemaKey = window.GOVUK.analyticsGa4.core.trackFunctions.toSnakeCase(key)
44
+
45
+ eventData[schemaKey] = targetDataset[key]
46
+ })
47
+
48
+ return eventData
49
+ }
50
+
31
51
  Ga4EventTracker.prototype.trackClick = function (event) {
32
52
  if (event.tracked) return
33
53
  var target = window.GOVUK.analyticsGa4.core.trackFunctions.findTrackingAttributes(event.target, this.trackingTrigger)
@@ -41,6 +61,8 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
41
61
  return
42
62
  }
43
63
 
64
+ data = Object.assign(data, this.getTargetDatasetSchema(target))
65
+
44
66
  var text = data.text || event.target.textContent
45
67
  data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(text)
46
68
 
@@ -8,6 +8,8 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
8
8
  this.module = module
9
9
  this.trackingTrigger = 'data-ga4-form' // elements with this attribute get tracked
10
10
  this.includeTextInputValues = this.module.hasAttribute('data-ga4-form-include-text')
11
+ this.recordJson = this.module.hasAttribute('data-ga4-form-record-json')
12
+ this.useTextCount = this.module.hasAttribute('data-ga4-form-use-text-count')
11
13
  this.redacted = false
12
14
  this.useFallbackValue = this.module.hasAttribute('data-ga4-form-no-answer-undefined') ? undefined : 'No answer given'
13
15
  }
@@ -84,19 +86,58 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
84
86
  var inputNodename = elem.nodeName
85
87
  var inputTypes = ['text', 'search', 'email', 'number']
86
88
 
87
- if (inputType === 'checkbox' && elem.checked) {
89
+ input.section = labelText
90
+
91
+ var isTextField = inputTypes.indexOf(inputType) !== -1 || inputNodename === 'TEXTAREA'
92
+ var conditionalField = elem.closest('.govuk-checkboxes__conditional')
93
+ var conditionalCheckbox = conditionalField && conditionalField.querySelector('[aria-controls="' + conditionalField.id + '"]')
94
+ var conditionalCheckboxChecked = conditionalCheckbox && conditionalCheckbox.checked
95
+
96
+ if (conditionalField && conditionalCheckboxChecked) {
97
+ var conditionalCheckboxLabel = conditionalField.querySelector('[for="' + conditionalCheckbox.id + '"]')
98
+
99
+ if (conditionalCheckboxLabel) {
100
+ input.parentSection = conditionalCheckboxLabel.innerText
101
+ }
102
+ }
103
+
104
+ if (conditionalCheckbox && !conditionalCheckboxChecked) {
105
+ // don't include conditional field if condition not checked
106
+ inputs.splice(i, 1)
107
+ } else if (conditionalField && elem.hasAttribute('aria-controls')) {
108
+ // don't include conditional field control in text
109
+ inputs.splice(i, 1)
110
+ } else if (elem.checked) {
88
111
  input.answer = labelText
112
+
113
+ var fieldset = elem.closest('fieldset')
114
+
115
+ if (fieldset) {
116
+ var legend = fieldset.querySelector('legend')
117
+
118
+ if (legend) {
119
+ input.section = legend.innerText
120
+ }
121
+ }
89
122
  } else if (inputNodename === 'SELECT' && elem.options[elem.selectedIndex] && elem.options[elem.selectedIndex].value) {
90
123
  input.answer = elem.options[elem.selectedIndex].text
91
- } else if (inputTypes.indexOf(inputType) !== -1 && elem.value) {
124
+ } else if (isTextField && elem.value) {
92
125
  if (this.includeTextInputValues || elem.hasAttribute('data-ga4-form-include-input')) {
93
- var PIIRemover = new window.GOVUK.analyticsGa4.PIIRemover()
94
- input.answer = PIIRemover.stripPIIWithOverride(elem.value, true, true)
126
+ if (this.useTextCount) {
127
+ input.answer = elem.value.length
128
+ } else {
129
+ var PIIRemover = new window.GOVUK.analyticsGa4.PIIRemover()
130
+ input.answer = PIIRemover.stripPIIWithOverride(elem.value, true, true)
131
+ }
95
132
  } else {
96
- this.redacted = true
133
+ // if recording JSON and text input not allowed
134
+ // set the specific answer to '[REDACTED]'
135
+ if (this.recordJson) {
136
+ input.answer = '[REDACTED]'
137
+ } else {
138
+ this.redacted = true
139
+ }
97
140
  }
98
- } else if (inputType === 'radio' && elem.checked) {
99
- input.answer = labelText
100
141
  } else {
101
142
  // remove the input from those gathered as it has no value
102
143
  inputs.splice(i, 1)
@@ -106,19 +147,38 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
106
147
  }
107
148
 
108
149
  Ga4FormTracker.prototype.combineGivenAnswers = function (data) {
109
- var answers = []
150
+ var answers = this.recordJson ? {} : []
151
+
110
152
  for (var i = 0; i < data.length; i++) {
111
153
  var answer = data[i].answer
154
+
112
155
  if (answer) {
113
- answers.push(answer)
156
+ if (this.recordJson) {
157
+ var fieldSection = data[i].section
158
+ var parentFieldSection = data[i].parentSection
159
+
160
+ if (fieldSection) {
161
+ if (parentFieldSection) {
162
+ answers[parentFieldSection] = answers[parentFieldSection] || {}
163
+ answers[parentFieldSection][fieldSection] = answer
164
+ } else {
165
+ answers[fieldSection] = answer
166
+ }
167
+ }
168
+ } else {
169
+ answers.push(answer)
170
+ }
114
171
  }
115
172
  }
116
- if (this.redacted) {
173
+ // default behaviour for redacted text is to omit
174
+ // answer and append '[REDACTED]' to final joined text
175
+ // if JSON being recorded then prevent this as answer
176
+ // will be already redacted
177
+ if (this.redacted && !this.recordJson) {
117
178
  answers.push('[REDACTED]')
118
179
  }
119
180
 
120
- answers = answers.join(',')
121
- return answers
181
+ return this.recordJson ? JSON.stringify(answers) : answers.join(',')
122
182
  }
123
183
 
124
184
  Modules.Ga4FormTracker = Ga4FormTracker
@@ -9,7 +9,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
9
9
  init: function (config) {
10
10
  if (window.dataLayer) {
11
11
  config = config || {}
12
- this.internalDownloadPaths = config.internalDownloadPaths || ['/government/uploads/', '/media/']
12
+ this.internalDownloadPaths = config.internalDownloadPaths || ['/government/uploads/', '/media/', '/csv-preview/']
13
13
  this.dedicatedDownloadDomains = config.dedicatedDownloadDomains || ['assets.publishing.service.gov.uk']
14
14
  window.GOVUK.analyticsGa4.core.trackFunctions.appendDomainsWithoutWWW(this.dedicatedDownloadDomains)
15
15
  this.handleClick = this.handleClick.bind(this)
@@ -151,7 +151,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
151
151
  Regex is used over JS string methods as this should work with anchor links, query string parameters and files that may have 'preview' in their name.
152
152
  */
153
153
  var previewRegex = /\.\w+\/preview/i
154
- return previewRegex.test(href)
154
+ return previewRegex.test(href) || href.startsWith('https://www.gov.uk/csv-preview/')
155
155
  },
156
156
 
157
157
  hrefPointsToDownloadPath: function (href) {
@@ -36,6 +36,11 @@
36
36
  // e.g. 'AB123456A', 'AB 12 34 56 A', 'ab 123456 a', 'ab 12 34 56 a', 'AB+12+34+56+A'
37
37
  var NATIONAL_INSURANCE_NUMBER = /[A-CEGHJ-OPR-TW-Z]{2}(\s+|\++)?(\d{2}(\s+|\++)?){3}[A-D]/gi
38
38
 
39
+ var UK_MOBILE_NUMBER = /07\d{9}/g
40
+ var UK_MOBILE_NUMBER_INTERNATIONAL = /\+447\d{9}/g
41
+ var UK_LANDLINE_NUMBER = /0[1246]\d{8,9}/g
42
+ var UK_LANDLINE_NUMBER_INTERNATIONAL = /\+44[1246]\d{8,9}/g
43
+
39
44
  function shouldStripDates () {
40
45
  var metas = document.querySelectorAll('meta[name="govuk:ga4-strip-dates"]')
41
46
  return metas.length > 0
@@ -109,6 +114,11 @@
109
114
  stripped = stripped.replace(VISA_PATTERN_GWF, '[gwf number]')
110
115
  stripped = stripped.replace(VISA_PATTERN_GB, '[gb eori number]')
111
116
  stripped = stripped.replace(NATIONAL_INSURANCE_NUMBER, '[ni number]')
117
+ stripped = stripped.replace(UK_LANDLINE_NUMBER, '[phone number]')
118
+ stripped = stripped.replace(UK_LANDLINE_NUMBER_INTERNATIONAL, '[phone number]')
119
+ stripped = stripped.replace(UK_MOBILE_NUMBER, '[phone number]')
120
+ stripped = stripped.replace(UK_MOBILE_NUMBER_INTERNATIONAL, '[phone number]')
121
+
112
122
  stripped = this.stripQueryStringParameters(stripped)
113
123
 
114
124
  if (this.stripDatePII === true) {
@@ -4,15 +4,21 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
4
4
  (function (Modules) {
5
5
  function AddAnother (module) {
6
6
  this.module = module
7
+ this.disableGa4 = this.module.dataset.disableGa4
7
8
  this.emptyFieldset = undefined
8
9
  this.addAnotherButton = undefined
9
10
  }
10
11
 
11
- function createButton (textContent, additionalClass = '') {
12
+ function createButton (textContent, additionalClass = '', dataAttributes = {}) {
12
13
  var button = document.createElement('button')
13
14
  button.className = 'gem-c-button govuk-button ' + additionalClass
14
15
  button.type = 'button'
15
16
  button.textContent = textContent
17
+
18
+ Object.keys(dataAttributes).forEach(dataAttribute => {
19
+ button.dataset[dataAttribute] = dataAttributes[dataAttribute]
20
+ })
21
+
16
22
  return button
17
23
  }
18
24
 
@@ -23,21 +29,50 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
23
29
  this.updateFieldsetsAndButtons()
24
30
  }
25
31
 
32
+ AddAnother.prototype.createEventData = function (data) {
33
+ var eventData = Object.assign({
34
+ event_name: 'select_content',
35
+ type: 'add another'
36
+ }, data)
37
+
38
+ var sectionElement = this.module.closest('[data-ga4-section]')
39
+
40
+ if (sectionElement) {
41
+ eventData.section = sectionElement.dataset.ga4Section
42
+ }
43
+
44
+ return JSON.stringify(eventData)
45
+ }
46
+
26
47
  AddAnother.prototype.createAddAnotherButton = function () {
48
+ var dataAttributes = {}
49
+
50
+ if (!this.disableGa4) {
51
+ dataAttributes.ga4Event = this.createEventData({ action: 'added' })
52
+ }
53
+
27
54
  this.addAnotherButton =
28
55
  createButton(
29
56
  this.module.dataset.addButtonText,
30
- 'js-add-another__add-button govuk-button--secondary'
57
+ 'js-add-another__add-button govuk-button--secondary',
58
+ dataAttributes
31
59
  )
32
60
  this.addAnotherButton.addEventListener('click', this.addNewFieldset.bind(this))
33
61
  this.module.appendChild(this.addAnotherButton)
34
62
  }
35
63
 
36
64
  AddAnother.prototype.createRemoveButton = function (fieldset, removeFunction) {
65
+ var dataAttributes = {}
66
+
67
+ if (!this.disableGa4) {
68
+ dataAttributes.ga4Event = this.createEventData({ action: 'deleted' })
69
+ }
70
+
37
71
  var removeButton =
38
72
  createButton(
39
73
  'Delete',
40
- 'js-add-another__remove-button gem-c-add-another__remove-button govuk-button--warning'
74
+ 'js-add-another__remove-button gem-c-add-another__remove-button govuk-button--warning',
75
+ dataAttributes
41
76
  )
42
77
  removeButton.addEventListener('click', function (event) {
43
78
  removeFunction(event)
@@ -62,10 +97,18 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
62
97
  }
63
98
 
64
99
  AddAnother.prototype.updateFieldsetsAndButtons = function () {
65
- this.module.querySelectorAll('.js-add-another__fieldset:not([hidden]) > fieldset > legend')
66
- .forEach(function (legend, index) {
67
- legend.textContent = this.module.dataset.fieldsetLegend + ' ' + (index + 1)
68
- }.bind(this))
100
+ var visibleFields = this.module.querySelectorAll('.js-add-another__fieldset:not([hidden]) > fieldset')
101
+
102
+ visibleFields.forEach(function (field, index) {
103
+ field.querySelector('legend').textContent = this.module.dataset.fieldsetLegend + ' ' + (index + 1)
104
+
105
+ var trackedRemoveButton = field.parentNode.querySelector('.js-add-another__remove-button[data-ga4-event]')
106
+
107
+ if (trackedRemoveButton) {
108
+ trackedRemoveButton.dataset.indexSection = index
109
+ trackedRemoveButton.dataset.indexSectionCount = visibleFields.length + 1
110
+ }
111
+ }.bind(this))
69
112
 
70
113
  if (this.module.dataset.emptyFields === 'false') {
71
114
  this.module.querySelector('.js-add-another__remove-button').classList.toggle(
@@ -73,6 +116,13 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
73
116
  this.module.querySelectorAll('.js-add-another__fieldset:not([hidden])').length === 1
74
117
  )
75
118
  }
119
+
120
+ var trackedAddAnotherButton = this.module.querySelector('.js-add-another__add-button[data-ga4-event]')
121
+
122
+ if (trackedAddAnotherButton) {
123
+ trackedAddAnotherButton.dataset.indexSection = visibleFields.length
124
+ trackedAddAnotherButton.dataset.indexSectionCount = visibleFields.length + 1
125
+ }
76
126
  }
77
127
 
78
128
  AddAnother.prototype.addNewFieldset = function (event) {
@@ -16,6 +16,21 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
16
16
  onSort: function () {
17
17
  this.updateOrderIndexes()
18
18
  this.triggerEvent(this.$module, 'reorder-drag')
19
+ }.bind(this),
20
+
21
+ onEnd: function (event) {
22
+ if (event.oldIndex !== event.newIndex) {
23
+ var item = event.item
24
+ var eventData = item.querySelector('[data-ga4-event]')
25
+
26
+ if (eventData) {
27
+ item.dataset.ga4Event = eventData.dataset.ga4Event
28
+ item.dataset.action = 'drag and drop'
29
+ item.dataset.text = event.newIndex > event.oldIndex ? 'Up' : 'Down'
30
+ this.triggerEvent(item, 'click')
31
+ delete item.dataset.ga4Event
32
+ }
33
+ }
19
34
  }.bind(this)
20
35
  })
21
36
 
@@ -84,10 +99,15 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
84
99
  }
85
100
 
86
101
  ReorderableList.prototype.updateOrderIndexes = function () {
87
- var $orderInputs = this.$module.querySelectorAll('.gem-c-reorderable-list__actions input')
88
- for (var i = 0; i < $orderInputs.length; i++) {
89
- $orderInputs[i].setAttribute('value', i + 1)
90
- }
102
+ var $actions = this.$module.querySelectorAll('.gem-c-reorderable-list__actions')
103
+
104
+ $actions.forEach(function ($action, index) {
105
+ $action.querySelector('input').value = index + 1
106
+
107
+ $action.querySelectorAll('button[data-ga4-event]').forEach(function ($trackButton) {
108
+ $trackButton.dataset.indexSection = index
109
+ })
110
+ })
91
111
  }
92
112
 
93
113
  ReorderableList.prototype.triggerEvent = function (element, eventName) {
@@ -12,6 +12,23 @@
12
12
  }
13
13
  }
14
14
 
15
+ .gem-c-intervention--image {
16
+ border-left: 0;
17
+ display: flex;
18
+ }
19
+
20
+ .gem-c-intervention__image-container {
21
+ min-width: 50px;
22
+ height: 50px;
23
+ margin-right: govuk-spacing(4);
24
+ background-size: 50px;
25
+ }
26
+
27
+ .gem-c-intervention__image-container--hmrc {
28
+ background-image: url("govuk_publishing_components/intervention/hmrc.svg");
29
+ border-radius: 10px;
30
+ }
31
+
15
32
  .gem-c-intervention__textwrapper {
16
33
  display: block;
17
34
  }
@@ -5,7 +5,6 @@ module GovukPublishingComponents
5
5
  account-api
6
6
  collections
7
7
  collections-publisher
8
- contacts-admin
9
8
  content-data-admin
10
9
  content-publisher
11
10
  content-tagger
@@ -5,6 +5,7 @@
5
5
  fieldset_legend ||= ""
6
6
  add_button_text ||= "Add another"
7
7
  empty_fields ||= false
8
+ disable_ga4 ||= nil
8
9
 
9
10
  component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
10
11
  component_helper.add_class("gem-c-add-another")
@@ -13,6 +14,7 @@
13
14
  add_button_text:,
14
15
  fieldset_legend:,
15
16
  empty_fields:,
17
+ disable_ga4:,
16
18
  })
17
19
  %>
18
20
 
@@ -8,6 +8,7 @@
8
8
  suggestion_text ||= nil
9
9
  hide ||= false
10
10
  new_tab ||= false
11
+ image ||= nil
11
12
 
12
13
  suggestion_data_attributes = {}
13
14
  dismiss_data_attributes = {}
@@ -51,6 +52,7 @@
51
52
 
52
53
  component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
53
54
  component_helper.add_class("gem-c-intervention")
55
+ component_helper.add_class("gem-c-intervention--image") if image
54
56
  component_helper.add_role("region")
55
57
  component_helper.add_aria_attribute({ label: "Intervention"})
56
58
  component_helper.add_data_attribute({ module: "intervention", intervention_name: name })
@@ -60,12 +62,15 @@
60
62
  %>
61
63
  <% if intervention_helper.show? %>
62
64
  <%= tag.section(**component_helper.all_attributes) do %>
63
- <p class="govuk-body">
65
+ <% valid_image = %w[hmrc].include? image %>
66
+ <%= tag.span(class: "gem-c-intervention__image-container gem-c-intervention__image-container--#{image}") if valid_image %>
67
+
68
+ <%= tag.p(class: "govuk-body") do %>
64
69
  <%= tag.span suggestion_text, class: "gem-c-intervention__textwrapper" if suggestion_text %>
65
70
  <% if suggestion_link_text && suggestion_link_url %>
66
71
  <%= tag.a suggestion_link_text, **suggestion_tag_options %>
67
72
  <% end %>
68
- </p>
73
+ <% end %>
69
74
 
70
75
  <% if dismiss_text %>
71
76
  <%= tag.p class: "govuk-body govuk-!-display-none-print", data: dismiss_data_attributes do %>
@@ -3,14 +3,30 @@
3
3
 
4
4
  items ||= []
5
5
  input_name ||= "ordering"
6
+ disable_ga4 ||= false
7
+ ga4_attributes ||= {
8
+ event_name: 'select_content',
9
+ type: 'reorderable list',
10
+ }
6
11
 
7
12
  component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
8
13
  component_helper.add_class("gem-c-reorderable-list")
9
14
  component_helper.add_data_attribute({ module: "reorderable-list" })
15
+ component_helper.add_data_attribute({ module: "ga4-event-tracker" }) unless disable_ga4
10
16
  %>
11
17
 
12
18
  <%= tag.ol(**component_helper.all_attributes) do %>
13
19
  <% items.each_with_index do |item, index| %>
20
+
21
+ <%
22
+ ga4_event = nil
23
+
24
+ unless disable_ga4
25
+ ga4_event = ga4_attributes
26
+ ga4_event.merge!({ section: item[:title], index_section: index, index_section_count: items.length }) unless disable_ga4
27
+ end
28
+ %>
29
+
14
30
  <%= tag.li class: "gem-c-reorderable-list__item" do %>
15
31
  <%= tag.div class: "gem-c-reorderable-list__wrapper" do %>
16
32
  <%= tag.div class: "gem-c-reorderable-list__content" do %>
@@ -33,14 +49,20 @@
33
49
  type: "button",
34
50
  aria_label: "Move \"#{item[:title]}\" up",
35
51
  classes: "js-reorderable-list-up",
36
- secondary_solid: true
52
+ secondary_solid: true,
53
+ data_attributes: {
54
+ ga4_event: ga4_event && ga4_event.merge({ action: 'Up' }).as_json
55
+ }
37
56
  } %>
38
57
  <%= render "govuk_publishing_components/components/button", {
39
58
  text: "Down",
40
59
  type: "button",
41
60
  aria_label: "Move \"#{item[:title]}\" down",
42
61
  classes: "js-reorderable-list-down",
43
- secondary_solid: true
62
+ secondary_solid: true,
63
+ data_attributes: {
64
+ ga4_event: ga4_event && ga4_event.merge({ action: 'Down' }).as_json
65
+ }
44
66
  } %>
45
67
  <% end %>
46
68
  <% end %>
@@ -46,6 +46,31 @@ examples:
46
46
  <label for="person_1_name" class="gem-c-label govuk-label">Full name</label>
47
47
  <input class="gem-c-input govuk-input" id="person_1_name" name="person[1]name">
48
48
  </div>
49
+ without_ga4_tracking:
50
+ description: |
51
+ Disables GA4 tracking on the add another component. Tracking is enabled by default. This adds a data module and data-attributes with JSONs to the add another component buttons. See the [ga4-event-tracker documentation](https://github.com/alphagov/govuk_publishing_components/blob/main/docs/analytics-ga4/ga4-event-tracker.md) for more information.
52
+ data:
53
+ fieldset_legend: "Item"
54
+ add_button_text: "Add another item"
55
+ disable_ga4: true
56
+ items:
57
+ - fields: >
58
+ <div class="govuk-form-group">
59
+ <label for="item_0_name" class="gem-c-label govuk-label">Full name</label>
60
+ <input class="gem-c-input govuk-input" id="item_0_name" name="item[0]name">
61
+ </div>
62
+ destroy_checkbox: >
63
+ <div class="govuk-checkboxes" data-module="govuk-checkboxes">
64
+ <div class="govuk-checkboxes__item">
65
+ <input type="checkbox" name="item[0][_destroy]" id="item_0__destroy" class="govuk-checkboxes__input">
66
+ <label for="item_0__destroy" class="govuk-label govuk-checkboxes__label">Delete</label>
67
+ </div>
68
+ </div>
69
+ empty:
70
+ <div class="govuk-form-group">
71
+ <label for="item_1_name" class="gem-c-label govuk-label">Full name</label>
72
+ <input class="gem-c-input govuk-input" id="item_1_name" name="item[1]name">
73
+ </div>
49
74
  start_empty:
50
75
  description: By default no form fields are displayed when the component loads if no content is specified
51
76
  data:
@@ -74,3 +74,13 @@ examples:
74
74
  suggestion_link_url: /travel-abroad
75
75
  dismiss_text: Hide this suggestion
76
76
  name: another-campaign-name
77
+
78
+ with_image:
79
+ description: |
80
+ An image can be displayed as shown. Currently, this only supports `image: "hmrc"`.
81
+ data:
82
+ image: "hmrc"
83
+ suggestion_text: This is a promotion for an interesting product
84
+ suggestion_link_text: Get the interesting product
85
+ suggestion_link_url: www.gov.uk
86
+ new_tab: true
@@ -74,6 +74,22 @@ examples:
74
74
  title: "Table 2.1: Budget 2018 policy decisions"
75
75
  - id: "5ebd75d7-6c37-4b93-b444-1b7c49757fb9"
76
76
  title: "Table 2.2: Measures announced at Autumn Budget 2017 or earlier that will take effect from November 2018 or later (£ million)"
77
+ without_ga4_tracking:
78
+ description: |
79
+ Disables GA4 tracking on the reorderable list. Tracking is enabled by default. This adds a data module and data-attributes with JSONs to the reorderable list. See the [ga4-event-tracker documentation](https://github.com/alphagov/govuk_publishing_components/blob/main/docs/analytics-ga4/ga4-event-tracker.md) for more information.
80
+ data:
81
+ disable_ga4: true
82
+ items:
83
+ - id: "ce99dd60-67dc-11eb-ae93-0242ac130002"
84
+ title: "Budget 2018"
85
+ - id: "d321cb86-67dc-11eb-ae93-0242ac130002"
86
+ title: "Budget 2018 (web)"
87
+ - id: "63a6d29e-6b6d-4157-9067-84c1a390e352"
88
+ title: "Impact on households: distributional analysis to accompany Budget 2018"
89
+ - id: "0a4d377d-68f4-472f-b2e3-ef71dc750f85"
90
+ title: "Table 2.1: Budget 2018 policy decisions"
91
+ - id: "5ebd75d7-6c37-4b93-b444-1b7c49757fb9"
92
+ title: "Table 2.2: Measures announced at Autumn Budget 2017 or earlier that will take effect from November 2018 or later (£ million)"
77
93
  with_custom_input_name:
78
94
  data:
79
95
  input_name: "attachments[ordering]"
@@ -63,18 +63,27 @@ ar:
63
63
  devolved_nations:
64
64
  applies_to:
65
65
  aria_label:
66
- connectors:
67
- last_word:
68
- two_words:
69
66
  england:
67
+ end:
68
+ middle:
69
+ start:
70
70
  northern_ireland:
71
+ end:
72
+ middle:
73
+ start:
71
74
  scotland:
75
+ end:
76
+ middle:
77
+ start:
72
78
  type:
73
79
  consultation:
74
80
  detailed_guide:
75
81
  guidance:
76
82
  publication:
77
83
  wales:
84
+ end:
85
+ middle:
86
+ start:
78
87
  feedback:
79
88
  close: إغلاق
80
89
  dont_include_personal_info: لا تقم بتضمين معلومات شخصية أو مالية مثل رقم التأمين الوطني أو تفاصيل بطاقة الائتمان الخاصة بك.
@@ -60,18 +60,27 @@ az:
60
60
  devolved_nations:
61
61
  applies_to:
62
62
  aria_label:
63
- connectors:
64
- last_word:
65
- two_words:
66
63
  england:
64
+ end:
65
+ middle:
66
+ start:
67
67
  northern_ireland:
68
+ end:
69
+ middle:
70
+ start:
68
71
  scotland:
72
+ end:
73
+ middle:
74
+ start:
69
75
  type:
70
76
  consultation:
71
77
  detailed_guide:
72
78
  guidance:
73
79
  publication:
74
80
  wales:
81
+ end:
82
+ middle:
83
+ start:
75
84
  feedback:
76
85
  close: Bağla
77
86
  dont_include_personal_info: Sosial sığorta nömrəniz və ya kredit kartınızın məlumatları kimi şəxsi və ya maliyyə məlumatları daxil etməyin.