govuk_publishing_components 35.2.0 → 35.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 972ee046b894a4166b8098b0fd68443fe83c9dd3ca990dc53df66943719bc3f8
4
- data.tar.gz: fe06a9efe47489b88fe35088fe043cbf404683516ba709d9ec8192412749e2e6
3
+ metadata.gz: 0f87c9fa99d845d53392c5a02a8c4330f7a9557b94290a55cc18b5f169862215
4
+ data.tar.gz: ee6d97596ccbc7cfc9704f95dd3b1940e6b60254fc3fe7f6c51d5d6c16d1ead4
5
5
  SHA512:
6
- metadata.gz: 788a0616987260f023d3c4b982e9ae7ca1150bdf996ed6001c7d999eb22116725b4a5ebaef2069ab23882fb4d1acbdb7c47d7f0686c1ef4bd171773de27da178
7
- data.tar.gz: ee4d860cc7fcaa7e7f374edd761d4f513455b319efea4b1e115667ae8cef89c0fef815c46c00b9b0330eb511ce6d5822dea79877174dddc3e1c67cb9feac3182
6
+ metadata.gz: 635eaae4b3ce872688184197dd240be9751f6d9286680f324a876cea3d00a9bfa0b6037b5817fbf58a66d319510dcbca747ff5c7bc69e5d76a7c33cb345963cb
7
+ data.tar.gz: 595feac64b2542ef4ff5cb669e7e12462cea78d250cb0d44f01312de9297379d0e2c9f4d8bff0ab75a59a3b523fd6d801df93518f4c407c600b87695c17c1ea8
@@ -2,4 +2,5 @@
2
2
  //= require_tree .
3
3
  //= require ../govuk_publishing_components/dependencies
4
4
  //= require ../govuk_publishing_components/components/accordion
5
+ //= require ../govuk_publishing_components/components/intervention
5
6
  //= require ../govuk_publishing_components/components/tabs
@@ -230,7 +230,7 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
230
230
  // Only index links that are not search results
231
231
  if (!link.getAttribute('data-ga4-ecommerce-path')) {
232
232
  totalLinks++
233
- link.setAttribute('data-ga4-index', '{"index_link": "' + totalLinks + '"}')
233
+ link.setAttribute('data-ga4-index', '{"index_link": ' + totalLinks + '}')
234
234
  }
235
235
  }
236
236
 
@@ -273,6 +273,31 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
273
273
  index_link: parseInt(index[2])
274
274
  }
275
275
  }
276
+ },
277
+
278
+ addAttributesToElements: function (selector, dataAttributes) {
279
+ var targetElements = document.querySelectorAll(selector)
280
+
281
+ for (var i = 0; i < targetElements.length; i++) {
282
+ var element = targetElements[i]
283
+
284
+ for (var j = 0; j < dataAttributes.length; j++) {
285
+ var key = dataAttributes[j].key
286
+ var value = dataAttributes[j].value
287
+
288
+ // value must check for undefined only as it would return false on an empty string, the number 0, etc.
289
+ if (key && value !== undefined) {
290
+ var existingAttributeValue = element.getAttribute(key)
291
+
292
+ if (key === 'data-module' && existingAttributeValue) {
293
+ // Combines values to prevent replacing any existing data-module values.
294
+ element.setAttribute(key, existingAttributeValue + ' ' + value)
295
+ } else {
296
+ element.setAttribute(key, value)
297
+ }
298
+ }
299
+ }
300
+ }
276
301
  }
277
302
  },
278
303
 
@@ -108,20 +108,22 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
108
108
  }
109
109
 
110
110
  Ga4LinkTracker.prototype.setIndex = function (indexData, target) {
111
- var index
111
+ var index = window.GOVUK.analyticsGa4.core.trackFunctions.createIndexObject(indexData)
112
112
 
113
113
  if (target.getAttribute('data-ga4-index')) {
114
114
  try {
115
- index = JSON.parse(target.getAttribute('data-ga4-index'))
115
+ var indexLink = JSON.parse(target.getAttribute('data-ga4-index'))
116
+
117
+ // Check whether the index object already exists on a parent element, as is the case with tracking accordion links.
118
+ // If true, combine data-ga4-index with the index object. Otherwise, just return indexLink
119
+ index = index ? window.GOVUK.extendObject(index, indexLink) : indexLink
116
120
  } catch (e) {
117
121
  console.error('Unable to parse index as JSON: ' + e.message, window.location)
118
122
  return
119
123
  }
120
- } else {
121
- index = indexData || undefined
122
124
  }
123
125
 
124
- return window.GOVUK.analyticsGa4.core.trackFunctions.createIndexObject(index)
126
+ return index
125
127
  }
126
128
 
127
129
  Modules.Ga4LinkTracker = Ga4LinkTracker
@@ -8,6 +8,11 @@ var initFunction = function () {
8
8
  window.GOVUK.analyticsGa4.vars.internalDomains = []
9
9
  window.GOVUK.analyticsGa4.vars.internalDomains.push(window.GOVUK.analyticsGa4.core.trackFunctions.getHostname())
10
10
  window.GOVUK.analyticsGa4.core.trackFunctions.appendDomainsWithoutWWW(window.GOVUK.analyticsGa4.vars.internalDomains)
11
+ var attachmentLinkData = [
12
+ { key: 'data-module', value: 'ga4-link-tracker' },
13
+ { key: 'data-ga4-track-links-only', value: '' },
14
+ { key: 'data-ga4-link', value: JSON.stringify({ event_name: 'navigation', type: 'html attachment' }) }]
15
+ window.GOVUK.analyticsGa4.core.trackFunctions.addAttributesToElements('[data-ga4-attachment-link]', attachmentLinkData)
11
16
  window.GOVUK.analyticsGa4.core.load()
12
17
 
13
18
  var analyticsModules = window.GOVUK.analyticsGa4.analyticsModules
@@ -0,0 +1,69 @@
1
+ window.GOVUK = window.GOVUK || {}
2
+ window.GOVUK.Modules = window.GOVUK.Modules || {};
3
+
4
+ (function (Modules) {
5
+ function Intervention ($module) {
6
+ this.$module = $module
7
+ this.$closeLink = this.$module.querySelector('.js-dismiss-link')
8
+ this.$campaignName = this.$module.getAttribute('data-intervention-name')
9
+ this.$campaignCookie = window.GOVUK.cookie('intervention_campaign') || ''
10
+ }
11
+
12
+ Intervention.prototype.init = function () {
13
+ this.$cookieHasCampaign = this.cookieHasCampaign()
14
+
15
+ if (this.$closeLink) {
16
+ this.$module.close = this.handleClose.bind(this)
17
+ this.$closeLink.addEventListener('click', this.$module.close)
18
+ }
19
+
20
+ if (this.$cookieHasCampaign) {
21
+ this.hideBanner()
22
+ }
23
+ }
24
+
25
+ Intervention.prototype.handleClose = function (event) {
26
+ event.preventDefault()
27
+
28
+ if (this.$cookieHasCampaign) {
29
+ this.setCookies()
30
+ }
31
+ this.hideBanner()
32
+ }
33
+
34
+ Intervention.prototype.cookieHasCampaign = function () {
35
+ if (this.$campaignCookie) {
36
+ return this.cookieValues().includes(this.$campaignName)
37
+ }
38
+ return false
39
+ }
40
+
41
+ Intervention.prototype.cookieValues = function () {
42
+ if (this.$campaignCookie !== null && this.$campaignCookie.length > 0) {
43
+ return this.$campaignCookie.split(',')
44
+ }
45
+ }
46
+
47
+ Intervention.prototype.appendCookieValues = function () {
48
+ return this.$campaignCookie + ',' + this.$campaignName
49
+ }
50
+
51
+ Intervention.prototype.setCookies = function () {
52
+ if (this.$campaignCookie) {
53
+ window.GOVUK.setCookie('intervention_campaign', this.appendCookieValues(), { days: 30 })
54
+ } else {
55
+ window.GOVUK.setCookie('intervention_campaign', this.$campaignName, { days: 30 })
56
+ }
57
+ }
58
+
59
+ Intervention.prototype.hideBanner = function () {
60
+ if (!this.$cookieHasCampaign) {
61
+ this.setCookies()
62
+ }
63
+
64
+ this.$module.hidden = true
65
+ this.$module.style.display = 'none'
66
+ }
67
+
68
+ Modules.Intervention = Intervention
69
+ })(window.GOVUK.Modules)
@@ -17,6 +17,7 @@
17
17
  cookie_preferences_set: 'essential',
18
18
  cookies_preferences_set: 'essential',
19
19
  '_email-alert-frontend_session': 'essential',
20
+ intervention_campaign: 'essential',
20
21
  licensing_session: 'essential',
21
22
  govuk_contact_referrer: 'essential',
22
23
  multivariatetest_cohort_coronavirus_extremely_vulnerable_rate_limit: 'essential',
@@ -37,6 +37,7 @@
37
37
  index = i + 1
38
38
 
39
39
  item[:data_attributes] ||= nil
40
+ ga4_link_data_attributes ||= nil
40
41
 
41
42
  if ga4_tracking
42
43
  item[:data_attributes] ||= {}
@@ -49,6 +50,23 @@
49
50
  index_section_count: items.length,
50
51
  },
51
52
  }.to_json
53
+
54
+ # These attributes have been created separately from the item[:data_attributes]
55
+ # object in order to keep them from colliding with GA4 event tracking and UA
56
+ # tracking attributes
57
+ ga4_link_data_attributes = {}
58
+ ga4_link_data_attributes[:module] = "ga4-link-tracker"
59
+ ga4_link_data_attributes[:ga4_tracks_links_only] = ""
60
+ ga4_link_data_attributes[:ga4_set_indexes] = ""
61
+ ga4_link_data_attributes[:ga4_link] = {
62
+ event_name: "navigation",
63
+ type: "accordion",
64
+ section: item[:heading][:text],
65
+ index: {
66
+ index_section: index,
67
+ index_section_count: (items.length),
68
+ }
69
+ }.to_json
52
70
  end
53
71
 
54
72
  section_classes = %w(govuk-accordion__section)
@@ -74,7 +92,13 @@
74
92
  %>
75
93
  <%= tag.div(item[:summary][:text], id: "#{id}-summary-#{index}", class: summary_classes) if item[:summary].present? %>
76
94
  <% end %>
77
- <%= tag.div(item[:content][:html], id: "#{id}-content-#{index}", class: "govuk-accordion__section-content", 'aria-labelledby': "#{id}-heading-#{index}") %>
95
+ <%= tag.div(
96
+ item[:content][:html],
97
+ id: "#{id}-content-#{index}",
98
+ class: "govuk-accordion__section-content",
99
+ 'aria-labelledby': "#{id}-heading-#{index}",
100
+ data: ga4_link_data_attributes
101
+ ) %>
78
102
  <% end %>
79
103
  <% end %>
80
104
  <% end %>
@@ -1,6 +1,7 @@
1
1
  <%
2
2
  add_gem_component_stylesheet("intervention")
3
3
 
4
+ name ||= ""
4
5
  dismiss_text ||= false
5
6
  suggestion_link_text ||= false
6
7
  suggestion_link_url ||= false
@@ -10,16 +11,23 @@
10
11
 
11
12
  data_attributes ||= {}
12
13
  suggestion_data_attributes ||= {}
13
- dismiss_data_attributes ||= {}
14
+ data_attributes[:module] = "intervention"
15
+ data_attributes["intervention-name"] = name
14
16
 
15
17
  aria_attributes ||= {}
16
18
  aria_attributes[:label] = 'Intervention'
17
19
 
18
- local_assigns[:query_string] ||= request.query_string
19
- local_assigns[:suggestion_link_text] = suggestion_link_text
20
- local_assigns[:suggestion_link_url] = suggestion_link_url
20
+ options = {
21
+ name: name,
22
+ dismiss_text: dismiss_text,
23
+ params: request.params,
24
+ query_string: request.query_string,
25
+ suggestion_text: suggestion_text,
26
+ suggestion_link_text: suggestion_link_text,
27
+ suggestion_link_url: suggestion_link_url,
28
+ }
21
29
 
22
- intervention_helper = GovukPublishingComponents::Presenters::InterventionHelper.new(local_assigns)
30
+ intervention_helper = GovukPublishingComponents::Presenters::InterventionHelper.new(options)
23
31
  dismiss_href = intervention_helper.dismiss_link
24
32
 
25
33
  suggestion_tag_options = {
@@ -44,7 +52,7 @@
44
52
  }
45
53
  section_options.merge!({ hidden: true }) if hide
46
54
  %>
47
- <% if suggestion_text || (suggestion_link_text && suggestion_link_url) %>
55
+ <% if intervention_helper.show? %>
48
56
  <%= tag.section **section_options do %>
49
57
  <p class="govuk-body">
50
58
  <%= tag.span suggestion_text, class: "gem-c-intervention__textwrapper" if suggestion_text %>
@@ -55,7 +63,7 @@
55
63
 
56
64
  <% if dismiss_text %>
57
65
  <p class="govuk-body">
58
- <%= tag.a class: "govuk-link", href: dismiss_href, data: dismiss_data_attributes do %>
66
+ <%= tag.a class: "govuk-link js-dismiss-link", href: dismiss_href do %>
59
67
  <svg class="gem-c-intervention__dismiss-icon"
60
68
  width="19" height="19" viewBox="0 0 19 19"
61
69
  aria-hidden="true"
@@ -22,7 +22,7 @@
22
22
  %>
23
23
  <% if steps %>
24
24
  <div
25
- data-module="gemstepnav<% if ga4_tracking %> ga4-event-tracker ga4-link-tracker<% end %>"
25
+ data-module="gemstepnav<% if ga4_tracking %> ga4-event-tracker<% end %>"
26
26
  <%= "data-ga4-expandable" if ga4_tracking %>
27
27
  class="gem-c-step-nav js-hidden <% if small %>govuk-!-display-none-print<% end %> <% unless small %>gem-c-step-nav--large<% end %>"
28
28
  <%= "data-remember" if remember_last_step %>
@@ -73,7 +73,27 @@
73
73
  <% end %>
74
74
  </div>
75
75
 
76
- <div class="gem-c-step-nav__panel js-panel" id="step-panel-<%= id %>-<%= step_index + 1 %>">
76
+ <%
77
+ ga4_link_data = {}
78
+
79
+ if ga4_tracking
80
+ ga4_link_data = {
81
+ "module": "ga4-link-tracker",
82
+ "ga4-track-links-only": "",
83
+ "ga4-set-indexes": "",
84
+ "ga4-link": {
85
+ "event_name": "navigation",
86
+ "type": "step by step",
87
+ "index": {
88
+ "index_section": step_index + 1
89
+ },
90
+ "section": step[:title]
91
+ }.to_json
92
+ }
93
+ end
94
+ %>
95
+
96
+ <%= tag.div(class: "gem-c-step-nav__panel js-panel", id: "step-panel-#{id}-#{step_index + 1}", data: ga4_link_data) do %>
77
97
  <%
78
98
  in_substep = false
79
99
  options[:step_nav_content_id] = step_nav_content_id
@@ -91,7 +111,7 @@
91
111
  end
92
112
  %>
93
113
  <% end %>
94
- </div>
114
+ <% end %>
95
115
 
96
116
  </li>
97
117
  <% end %>
@@ -6,7 +6,10 @@ body: |
6
6
  that would be useful to them. This component would be used to add this personalised content and would
7
7
  indicate to the user that this is not normally part of the page, but has been added for them specifically.
8
8
 
9
- The dismiss link points to the current URL with the "hide-intervention" query string parameter set to "true". The backend should check for this string in order to render the same page without the intervention.
9
+ The dismiss link works without Javascript by pointing to the current URL with the "hide-intervention"
10
+ query string parameter set to "true". It's progressively enhanced and sets a cookie to remember that
11
+ the user has dismissed the banner before. The cookie requires a "name" parameter, the value of which
12
+ is stored in the cookie to distinguish which campaign banner the user has dismissed.
10
13
 
11
14
  accessibility_criteria: |
12
15
  The intervention component must:
@@ -30,20 +33,20 @@ examples:
30
33
  suggestion_link_url: /travel-abroad
31
34
 
32
35
  with_dismiss_link:
36
+ description: |
37
+ Name is required in order to set a cookie. The name value should be distinct to the campaign for the banner,
38
+ so that other banners using this component are not hidden by accident.
33
39
  data:
34
40
  suggestion_text: You should renew your permit every 6 months.
35
41
  dismiss_text: Hide this suggestion
36
-
37
- with_suggestion_link_only:
38
- data:
39
- suggestion_link_text: You can now apply for a permit online.
40
- suggestion_link_url: /permit
42
+ name: campaign-name
41
43
 
42
44
  with_hide:
43
45
  description: |
44
46
  This example is for when we want to hide by default and display to the user based on some logic,
45
47
  either in the backend or with Javascript.
46
48
  data:
49
+ suggestion_text: You should renew your permit every 6 months.
47
50
  suggestion_link_text: You may be invited to fill in a questionnaire
48
51
  suggestion_link_url: /questionnaire
49
52
  hide: true
@@ -55,6 +58,7 @@ examples:
55
58
  Link text should tell the user that the link opens in a new tab.
56
59
  Note: "(opens in a new tab)" is added to link text if the phrase isn't included.
57
60
  data:
61
+ suggestion_text: You should renew your permit every 6 months.
58
62
  suggestion_link_text: You can now apply for a permit online
59
63
  suggestion_link_url: www.google.com/permit
60
64
  new_tab: true
@@ -76,6 +80,7 @@ examples:
76
80
  track-dimension-index: 29
77
81
  track-label: clicked suggestion
78
82
  dismiss_text: Hide this suggestion
83
+ name: another-campaign-name
79
84
  dismiss_data_attributes:
80
85
  track-category: interventionBanner
81
86
  track-action: interventionDismissed
@@ -1,11 +1,15 @@
1
1
  module GovukPublishingComponents
2
2
  module Presenters
3
3
  class InterventionHelper
4
- def initialize(local_assigns)
4
+ def initialize(options = {})
5
+ @name = options[:name]
6
+ @dismiss_text = options[:dismiss_text]
5
7
  @accessible_text_suffix = I18n.t("components.intervention.accessible_link_text_suffix")
6
- @query_string = local_assigns[:query_string]
7
- @suggestion_link_text = local_assigns[:suggestion_link_text]
8
- @suggestion_link_url = local_assigns[:suggestion_link_url]
8
+ @params = options[:params]
9
+ @query_string = options[:query_string]
10
+ @suggestion_text = options[:suggestion_text]
11
+ @suggestion_link_text = options[:suggestion_link_text]
12
+ @suggestion_link_url = options[:suggestion_link_url]
9
13
  end
10
14
 
11
15
  def accessible_text
@@ -29,9 +33,16 @@ module GovukPublishingComponents
29
33
  rel
30
34
  end
31
35
 
36
+ def show?
37
+ return false if params["hide-intervention"] == "true"
38
+ return false if @dismiss_text && @name.blank?
39
+
40
+ @suggestion_text || (@suggestion_link_text && @suggestion_link_url)
41
+ end
42
+
32
43
  private
33
44
 
34
- attr_reader :accessible_text_suffix, :query_string, :suggestion_link_text, :suggestion_link_url
45
+ attr_reader :accessible_text_suffix, :query_string, :params, :suggestion_text, :suggestion_link_text, :suggestion_link_url
35
46
  end
36
47
  end
37
48
  end
@@ -46,7 +46,6 @@ module GovukPublishingComponents
46
46
  :li,
47
47
  class: "gem-c-step-nav__list-item js-list-item #{link_active(contents[:active])}",
48
48
  ) do
49
- @options[:ga4_index_total] = element[:contents].length if @options[:ga4_tracking]
50
49
  create_list_item_content(contents)
51
50
  end,
52
51
  )
@@ -65,26 +64,11 @@ module GovukPublishingComponents
65
64
  concat create_context(link[:context])
66
65
  end
67
66
 
68
- ga4_link_data ||= nil
69
- if @options[:ga4_tracking]
70
- ga4_link_data = {
71
- "event_name": "navigation",
72
- "type": "step by step",
73
- "index": {
74
- "index_section": (@options[:step_index] + 1).to_s,
75
- "index_link": @link_index.to_s,
76
- },
77
- "index_total": @options[:ga4_index_total].to_s,
78
- "section": @options[:step_title],
79
- }.to_json
80
- end
81
-
82
67
  link_to(
83
68
  href,
84
69
  rel: ("external" if href.start_with?("http")),
85
70
  data: {
86
71
  position: "#{@options[:step_index] + 1}.#{@link_index}",
87
- ga4_link: ga4_link_data,
88
72
  },
89
73
  class: "gem-c-step-nav__link js-link",
90
74
  ) do
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = "35.2.0".freeze
2
+ VERSION = "35.3.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_publishing_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 35.2.0
4
+ version: 35.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-31 00:00:00.000000000 Z
11
+ date: 2023-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: govuk_app_config
@@ -484,6 +484,7 @@ files:
484
484
  - app/assets/javascripts/govuk_publishing_components/components/feedback.js
485
485
  - app/assets/javascripts/govuk_publishing_components/components/govspeak.js
486
486
  - app/assets/javascripts/govuk_publishing_components/components/image-card.js
487
+ - app/assets/javascripts/govuk_publishing_components/components/intervention.js
487
488
  - app/assets/javascripts/govuk_publishing_components/components/layout-header.js
488
489
  - app/assets/javascripts/govuk_publishing_components/components/layout-super-navigation-header.js
489
490
  - app/assets/javascripts/govuk_publishing_components/components/metadata.js
@@ -1415,7 +1416,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1415
1416
  - !ruby/object:Gem::Version
1416
1417
  version: '0'
1417
1418
  requirements: []
1418
- rubygems_version: 3.4.10
1419
+ rubygems_version: 3.4.12
1419
1420
  signing_key:
1420
1421
  specification_version: 4
1421
1422
  summary: A gem to document components in GOV.UK frontend applications