govuk_publishing_components 29.14.0 → 29.15.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/gtm-click-tracking.js +24 -13
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/gtm-page-views.js +9 -12
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/gtm-schemas.js +32 -0
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
  6. data/app/assets/javascripts/govuk_publishing_components/components/accordion.js +17 -22
  7. data/app/assets/javascripts/govuk_publishing_components/components/table.js +52 -0
  8. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_charts.scss +13 -2
  9. data/app/models/govuk_publishing_components/audit_applications.rb +31 -9
  10. data/app/models/govuk_publishing_components/audit_comparer.rb +15 -9
  11. data/app/views/govuk_publishing_components/audit/_components.html.erb +20 -2
  12. data/app/views/govuk_publishing_components/components/_table.html.erb +61 -30
  13. data/app/views/govuk_publishing_components/components/docs/back_link.yml +1 -1
  14. data/app/views/govuk_publishing_components/components/docs/big_number.yml +2 -2
  15. data/app/views/govuk_publishing_components/components/docs/breadcrumbs.yml +2 -2
  16. data/app/views/govuk_publishing_components/components/docs/button.yml +41 -40
  17. data/app/views/govuk_publishing_components/components/docs/cards.yml +2 -0
  18. data/app/views/govuk_publishing_components/components/docs/checkboxes.yml +216 -216
  19. data/app/views/govuk_publishing_components/components/docs/cookie_banner.yml +2 -1
  20. data/app/views/govuk_publishing_components/components/docs/copy_to_clipboard.yml +2 -2
  21. data/app/views/govuk_publishing_components/components/docs/details.yml +5 -1
  22. data/app/views/govuk_publishing_components/components/docs/document_list.yml +1 -2
  23. data/app/views/govuk_publishing_components/components/docs/error_alert.yml +4 -0
  24. data/app/views/govuk_publishing_components/components/docs/error_summary.yml +4 -6
  25. data/app/views/govuk_publishing_components/components/docs/govspeak.yml +6 -7
  26. data/app/views/govuk_publishing_components/components/docs/image_card.yml +3 -2
  27. data/app/views/govuk_publishing_components/components/docs/intervention.yml +25 -25
  28. data/app/views/govuk_publishing_components/components/docs/organisation_logo.yml +1 -2
  29. data/app/views/govuk_publishing_components/components/docs/print_link.yml +5 -1
  30. data/app/views/govuk_publishing_components/components/docs/select.yml +101 -98
  31. data/app/views/govuk_publishing_components/components/docs/table.yml +36 -1
  32. data/app/views/govuk_publishing_components/components/docs/tabs.yml +4 -0
  33. data/config/locales/ar.yml +4 -0
  34. data/config/locales/az.yml +4 -0
  35. data/config/locales/be.yml +4 -0
  36. data/config/locales/bg.yml +4 -0
  37. data/config/locales/bn.yml +4 -0
  38. data/config/locales/cs.yml +4 -0
  39. data/config/locales/cy.yml +4 -0
  40. data/config/locales/da.yml +4 -0
  41. data/config/locales/de.yml +4 -0
  42. data/config/locales/dr.yml +4 -0
  43. data/config/locales/el.yml +4 -0
  44. data/config/locales/en.yml +4 -0
  45. data/config/locales/es-419.yml +4 -0
  46. data/config/locales/es.yml +4 -0
  47. data/config/locales/et.yml +4 -0
  48. data/config/locales/fa.yml +4 -0
  49. data/config/locales/fi.yml +4 -0
  50. data/config/locales/fr.yml +4 -0
  51. data/config/locales/gd.yml +4 -0
  52. data/config/locales/gu.yml +4 -0
  53. data/config/locales/he.yml +4 -0
  54. data/config/locales/hi.yml +4 -0
  55. data/config/locales/hr.yml +4 -0
  56. data/config/locales/hu.yml +4 -0
  57. data/config/locales/hy.yml +4 -0
  58. data/config/locales/id.yml +4 -0
  59. data/config/locales/is.yml +4 -0
  60. data/config/locales/it.yml +4 -0
  61. data/config/locales/ja.yml +4 -0
  62. data/config/locales/ka.yml +4 -0
  63. data/config/locales/kk.yml +4 -0
  64. data/config/locales/ko.yml +4 -0
  65. data/config/locales/lt.yml +4 -0
  66. data/config/locales/lv.yml +4 -0
  67. data/config/locales/ms.yml +4 -0
  68. data/config/locales/mt.yml +4 -0
  69. data/config/locales/nl.yml +4 -0
  70. data/config/locales/no.yml +4 -0
  71. data/config/locales/pa-pk.yml +4 -0
  72. data/config/locales/pa.yml +4 -0
  73. data/config/locales/pl.yml +4 -0
  74. data/config/locales/ps.yml +4 -0
  75. data/config/locales/pt.yml +4 -0
  76. data/config/locales/ro.yml +4 -0
  77. data/config/locales/ru.yml +4 -0
  78. data/config/locales/si.yml +4 -0
  79. data/config/locales/sk.yml +4 -0
  80. data/config/locales/sl.yml +4 -0
  81. data/config/locales/so.yml +4 -0
  82. data/config/locales/sq.yml +4 -0
  83. data/config/locales/sr.yml +4 -0
  84. data/config/locales/sv.yml +4 -0
  85. data/config/locales/sw.yml +4 -0
  86. data/config/locales/ta.yml +4 -0
  87. data/config/locales/th.yml +4 -0
  88. data/config/locales/tk.yml +4 -0
  89. data/config/locales/tr.yml +4 -0
  90. data/config/locales/uk.yml +4 -0
  91. data/config/locales/ur.yml +4 -0
  92. data/config/locales/uz.yml +4 -0
  93. data/config/locales/vi.yml +4 -0
  94. data/config/locales/zh-hk.yml +4 -0
  95. data/config/locales/zh-tw.yml +4 -0
  96. data/config/locales/zh.yml +4 -0
  97. data/lib/govuk_publishing_components/app_helpers/table_helper.rb +4 -2
  98. data/lib/govuk_publishing_components/version.rb +1 -1
  99. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea69ac62517f1d199c528b86f901ea00cf09b7d09b9c4b7c6550af866ad67cea
4
- data.tar.gz: f92c94a1bad3f1516e4cdc4e415202c72e027b42990ed3e1c9c5eacebe389d14
3
+ metadata.gz: dc8afcd723e5dd4096349ddfbce6a967b852d9525f46bb3a1b078c11ab0b5b41
4
+ data.tar.gz: b2c550b431ad6892bdee23afa7f2e83315e52725007d16149f20ce9a0ef29e7a
5
5
  SHA512:
6
- metadata.gz: e4a5fa8f083422f90461f0473ebe979d1240a5b0a0f4a0a56f19a24936eb33c70f18216b4e29bb43140f945c9985e5da738299563b0ceab1a40932c2cb85b138
7
- data.tar.gz: 3ab97ddb79f5ed2a1494c9fa63868573b4bc18d8ba067343d4acc035b5602f90ab6a47b089a36b8590f77b5d45e9cc70084001b355cc458dbe2326346ec63073
6
+ metadata.gz: 0bd443616d7ab532ec0f2fe36549782986c3cb5bdbab636bdeec40ff595b7873b006d432f75c16f33311dda1c78b7e4533a4376ad52f19a8d1bf07b882dc03cd
7
+ data.tar.gz: 3f64655cddd38bf346a6ab3dd8c69917a70b3de614ad0d4f73b16b28f777b3c7901b466fe8479d0c7abc8205f0b123469f35c3f97f44ab3fdb6456cde97883f1
@@ -7,7 +7,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
7
7
 
8
8
  function GtmClickTracking (module) {
9
9
  this.module = module
10
- this.trackingTrigger = 'data-gtm-event-name' // elements with this attribute get tracked
10
+ this.trackingTrigger = 'data-ga4' // elements with this attribute get tracked
11
11
  }
12
12
 
13
13
  GtmClickTracking.prototype.init = function () {
@@ -18,12 +18,24 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
18
18
  if (window.dataLayer) {
19
19
  var target = this.findTrackingAttributes(event.target)
20
20
  if (target) {
21
- var data = {
22
- event: 'analytics',
23
- event_name: target.getAttribute('data-gtm-event-name'),
24
- // get entire URL apart from domain
25
- link_url: window.location.href.substring(window.location.origin.length),
26
- ui: JSON.parse(target.getAttribute('data-gtm-attributes')) || {}
21
+ var schema = new window.GOVUK.analyticsGA4.Schemas().eventSchema()
22
+
23
+ try {
24
+ var data = target.getAttribute(this.trackingTrigger)
25
+ data = JSON.parse(data)
26
+ } catch (e) {
27
+ // if there's a problem with the config, don't start the tracker
28
+ console.error('GA4 configuration error: ' + e.message, window.location)
29
+ return
30
+ }
31
+
32
+ schema.event = 'event_data'
33
+ // get attributes from the data attribute to send to GA
34
+ // only allow it if it already exists in the schema
35
+ for (var property in data) {
36
+ if (schema.event_data[property]) {
37
+ schema.event_data[property] = data[property]
38
+ }
27
39
  }
28
40
 
29
41
  // Ensure it only tracks aria-expanded in an accordion element, instead of in any child of the clicked element
@@ -39,15 +51,14 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
39
51
  var detailsElement = target.closest('details')
40
52
 
41
53
  if (ariaExpanded) {
42
- data.ui.text = data.ui.text || target.innerText
43
- data.ui.action = (ariaExpanded === 'false') ? 'opened' : 'closed'
54
+ schema.event_data.text = data.text || target.innerText
55
+ schema.event_data.action = (ariaExpanded === 'false') ? 'opened' : 'closed'
44
56
  } else if (detailsElement) {
45
- data.ui.text = data.ui.text || detailsElement.textContent
57
+ schema.event_data.text = data.text || detailsElement.textContent
46
58
  var openAttribute = detailsElement.getAttribute('open')
47
- data.ui.action = (openAttribute == null) ? 'opened' : 'closed'
59
+ schema.event_data.action = (openAttribute == null) ? 'opened' : 'closed'
48
60
  }
49
-
50
- window.dataLayer.push(data)
61
+ window.dataLayer.push(schema)
51
62
  }
52
63
  }
53
64
  }
@@ -9,29 +9,26 @@
9
9
  sendPageView: function () {
10
10
  if (window.dataLayer) {
11
11
  var data = {
12
- event: 'config_ready',
12
+ event: 'page_view',
13
13
  page: {
14
14
  location: this.getLocation(),
15
15
  referrer: this.getReferrer(),
16
16
  title: this.getTitle(),
17
- status_code: this.getStatusCode()
18
- },
19
- publishing: {
17
+ status_code: this.getStatusCode(),
18
+
20
19
  document_type: this.getMetaContent('format'),
21
20
  publishing_app: this.getMetaContent('publishing-app'),
22
21
  rendering_app: this.getMetaContent('rendering-app'),
23
22
  schema_name: this.getMetaContent('schema-name'),
24
- content_id: this.getMetaContent('content-id')
25
- },
26
- taxonomy: {
23
+ content_id: this.getMetaContent('content-id'),
24
+
27
25
  section: this.getMetaContent('section'),
28
26
  taxon_slug: this.getMetaContent('taxon-slug'),
29
27
  taxon_id: this.getMetaContent('taxon-id'),
30
28
  themes: this.getMetaContent('themes'),
31
29
  taxon_slugs: this.getMetaContent('taxon-slugs'),
32
- taxon_ids: this.getMetaContent('taxon-ids')
33
- },
34
- content: {
30
+ taxon_ids: this.getMetaContent('taxon-ids'),
31
+
35
32
  language: this.getLanguage(),
36
33
  history: this.getHistory(),
37
34
  withdrawn: this.getWithDrawn(),
@@ -65,9 +62,9 @@
65
62
  // https://github.com/alphagov/static/blob/main/app/views/root/_error_page.html.erb#L32
66
63
  getStatusCode: function () {
67
64
  if (window.httpStatusCode) {
68
- return window.httpStatusCode
65
+ return window.httpStatusCode.toString()
69
66
  } else {
70
- return 200
67
+ return '200'
71
68
  }
72
69
  },
73
70
 
@@ -0,0 +1,32 @@
1
+ ;(function (global) {
2
+ 'use strict'
3
+
4
+ var GOVUK = global.GOVUK || {}
5
+
6
+ var Schemas = function () {
7
+ this.null = 'n/a'
8
+ }
9
+
10
+ Schemas.prototype.eventSchema = function () {
11
+ return {
12
+ event: this.null,
13
+
14
+ event_data: {
15
+ event_name: this.null,
16
+ type: this.null,
17
+ url: this.null,
18
+ text: this.null,
19
+ index: this.null,
20
+ index_total: this.null,
21
+ section: this.null,
22
+ action: this.null,
23
+ external: this.null
24
+ }
25
+ }
26
+ }
27
+
28
+ GOVUK.analyticsGA4 = GOVUK.analyticsGA4 || {}
29
+ GOVUK.analyticsGA4.Schemas = Schemas
30
+
31
+ global.GOVUK = GOVUK
32
+ })(window)
@@ -1,4 +1,5 @@
1
1
  // The following modules are imported in a specific order
2
+ //= require ./analytics-ga4/gtm-schemas
2
3
  //= require ./analytics-ga4/pii-remover
3
4
  //= require ./analytics-ga4/gtm-page-views
4
5
  //= require ./analytics-ga4/gtm-click-tracking
@@ -10,27 +10,22 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
10
10
  function GemAccordion ($module) {
11
11
  this.$module = $module
12
12
  this.sectionClass = 'govuk-accordion__section'
13
- this.sectionClassExpanded = 'govuk-accordion__section--expanded'
14
- this.sectionHeaderClass = 'govuk-accordion__section-header'
15
- this.sectionInnerContent = 'govuk-accordion__section-content'
16
- this.showAllControls = 'govuk-accordion__show-all'
17
- this.sectionButton = 'govuk-accordion__section-button'
18
- this.headingText = 'govuk-accordion__section-heading-text'
19
-
20
- // Translated component content and language attribute pulled from data attributes
13
+ this.sectionExpandedClass = 'govuk-accordion__section--expanded'
14
+ this.sectionInnerContentClass = 'govuk-accordion__section-content'
15
+
16
+ this.sectionHeader = '.govuk-accordion__section-header'
17
+ this.showAllControls = '.govuk-accordion__show-all'
18
+ this.sectionButton = '.govuk-accordion__section-button'
19
+ this.headingText = '.govuk-accordion__section-heading-text'
20
+
21
+ // language attribute pulled from data attributes
21
22
  this.$module.actions = {}
22
23
  this.$module.actions.locale = this.$module.getAttribute('data-locale')
23
- this.$module.actions.showText = this.$module.getAttribute('data-show-text')
24
- this.$module.actions.hideText = this.$module.getAttribute('data-hide-text')
25
- this.$module.actions.showAllText = this.$module.getAttribute('data-show-all-text')
26
- this.$module.actions.hideAllText = this.$module.getAttribute('data-hide-all-text')
27
- this.$module.actions.thisSectionVisuallyHidden = this.$module.getAttribute('data-this-section-visually-hidden')
28
24
  }
29
25
 
30
26
  GemAccordion.prototype.init = function () {
31
27
  // Indicate that JavaScript has worked
32
- this.$module.classList.add('gem-c-accordion--active')
33
- this.$module.querySelector('.' + this.showAllControls).classList.add('gem-c-accordion__show-all')
28
+ this.$module.querySelector(this.showAllControls).classList.add('gem-c-accordion__show-all')
34
29
 
35
30
  // Feature flag for anchor tag navigation used on manuals
36
31
  if (this.$module.getAttribute('data-anchor-navigation') === 'true') {
@@ -50,7 +45,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
50
45
  var showAllAttributes = this.$module.getAttribute('data-show-all-attributes')
51
46
  if (showAllAttributes) {
52
47
  try {
53
- var showAll = this.$module.querySelector('.' + this.showAllControls)
48
+ var showAll = this.$module.querySelector(this.showAllControls)
54
49
  var values = JSON.parse(showAllAttributes)
55
50
  var keys = Object.keys(values)
56
51
  for (var i = 0; i < keys.length; i++) {
@@ -74,7 +69,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
74
69
  // Add event listeners for links to open accordion sections when navigated to using said anchor links on the page
75
70
  // Adding an event listener to all anchor link a tags in an accordion is risky but we circumvent this risk partially by only being a layer of accordion behaviour instead of any sort of change to link behaviour
76
71
  GemAccordion.prototype.addEventListenersForAnchors = function () {
77
- var links = this.$module.querySelectorAll('.' + this.sectionInnerContent + ' a[href*="#"]')
72
+ var links = this.$module.querySelectorAll(this.sectionInnerContentClass + ' a[href*="#"]')
78
73
 
79
74
  nodeListForEach(links, function (link) {
80
75
  if (link.pathname === window.location.pathname) {
@@ -87,7 +82,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
87
82
  GemAccordion.prototype.openForAnchor = function (hash) {
88
83
  var target = document.getElementById(hash)
89
84
  var $section = this.getContainingSection(target)
90
- var $header = $section.querySelector('.' + this.sectionHeaderClass)
85
+ var $header = $section.querySelector(this.sectionHeader)
91
86
  var $expanded = this.getContainingSection($section)
92
87
  var $parent = $header.parentElement
93
88
 
@@ -95,7 +90,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
95
90
  // Should the target anchor link be within the same page, open section - navigate normally
96
91
  // Should the target anchor link be within a different, closed section, open this section
97
92
  // Should the target anchor link be within a different page and different, closed section open this section
98
- if ($expanded && (!$parent.classList.contains(this.sectionClassExpanded))) {
93
+ if ($expanded && (!$parent.classList.contains(this.sectionExpandedClass))) {
99
94
  $header.click()
100
95
  }
101
96
  }
@@ -119,7 +114,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
119
114
 
120
115
  // To track the Accordion's "Show all sections" / "Hide all sections" button click events and pass them to the GA event tracking
121
116
  GemAccordion.prototype.addAccordionOpenAllTracking = function () {
122
- this.$module.querySelector('.' + this.showAllControls).addEventListener('click', function (event) {
117
+ this.$module.querySelector(this.showAllControls).addEventListener('click', function (event) {
123
118
  var expanded = event.target.getAttribute('aria-expanded') === 'true'
124
119
  var label = expanded ? 'Show all sections' : 'Hide all sections'
125
120
  var action = expanded ? 'accordionOpened' : 'accordionClosed'
@@ -141,7 +136,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
141
136
  }
142
137
 
143
138
  GemAccordion.prototype.addEventListenerSections = function () {
144
- var sections = this.$module.querySelectorAll('.' + this.sectionButton)
139
+ var sections = this.$module.querySelectorAll(this.sectionButton)
145
140
  nodeListForEach(sections, function (section) {
146
141
  section.addEventListener('click', this.addAccordionSectionTracking.bind(this, section))
147
142
  }.bind(this))
@@ -150,7 +145,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
150
145
  // If the Accordion's sections are opened on click, then pass them to the GA event tracking
151
146
  GemAccordion.prototype.addAccordionSectionTracking = function (section) {
152
147
  var expanded = section.getAttribute('aria-expanded') === 'false'
153
- var label = section.querySelector('.' + this.headingText).textContent
148
+ var label = section.querySelector(this.headingText).textContent
154
149
  var action = expanded ? 'accordionOpened' : 'accordionClosed'
155
150
  var options = { transport: 'beacon', label: label }
156
151
 
@@ -0,0 +1,52 @@
1
+ window.GOVUK = window.GOVUK || {}
2
+ window.GOVUK.Modules = window.GOVUK.Modules || {};
3
+
4
+ (function (Modules) {
5
+ function Table ($module) {
6
+ this.$module = $module
7
+ this.searchInput = $module.querySelector('input[name="filter"]')
8
+ this.tableRows = $module.querySelectorAll('.js-govuk-table__row')
9
+ this.filter = $module.querySelector('.js-gem-c-table__filter')
10
+ this.filterCount = this.filter.querySelector('.js-filter-count')
11
+ this.message = $module.querySelector('.js-gem-c-table__message')
12
+ this.hiddenClass = 'govuk-!-display-none'
13
+ this.filterCountText = this.filterCount.getAttribute('data-count-text')
14
+ this.tableRowsContent = []
15
+
16
+ for (var i = 0; i < this.tableRows.length; i++) {
17
+ this.tableRowsContent.push(this.tableRows[i].textContent.toUpperCase())
18
+ }
19
+ }
20
+
21
+ Table.prototype.init = function () {
22
+ this.$module.updateRows = this.updateRows.bind(this)
23
+ this.filter.classList.remove(this.hiddenClass)
24
+ this.searchInput.addEventListener('input', this.$module.updateRows)
25
+ }
26
+
27
+ // Reads value of input and filters content
28
+ Table.prototype.updateRows = function () {
29
+ var value = this.searchInput.value
30
+ var hiddenRows = 0
31
+ var length = this.tableRows.length
32
+
33
+ for (var i = 0; i < length; i++) {
34
+ if (this.tableRowsContent[i].includes(value.toUpperCase())) {
35
+ this.tableRows[i].classList.remove(this.hiddenClass)
36
+ } else {
37
+ this.tableRows[i].classList.add(this.hiddenClass)
38
+ hiddenRows++
39
+ }
40
+ }
41
+
42
+ this.filterCount.textContent = (length - hiddenRows) + ' ' + this.filterCountText
43
+
44
+ if (length === hiddenRows) {
45
+ this.message.classList.remove(this.hiddenClass)
46
+ } else {
47
+ this.message.classList.add(this.hiddenClass)
48
+ }
49
+ }
50
+
51
+ Modules.Table = Table
52
+ })(window.GOVUK.Modules)
@@ -25,12 +25,23 @@
25
25
  $caption-side: top; // Caption alignment. Top or bottom.
26
26
  $key-width: 160px; // Only used by IE. Other browsers get smallest width that fits content
27
27
 
28
+ // The following accessible colour palette has been developed to meet the colour contrast requirements for adjacent colours (as set out in WCAG 2.1)
29
+ // For charts, the palette should be used instead of the GOV.UK colour palette - https://design-system.service.gov.uk/styles/colour/
30
+ // https://gss.civilservice.gov.uk/policy-store/data-visualisation-colours-in-charts/#section-5
31
+
32
+ $gss-colour-dark-blue: #12436d;
33
+ $gss-colour-turquoise: #28a197;
34
+ $gss-colour-dark-pink: #801650;
35
+ $gss-colour-orange: #f46a25;
36
+ $gss-colour-dark-grey: #3d3d3d;
37
+ $gss-colour-plum: #a285d1;
38
+
28
39
  // CHART COLOUR SCHEME
29
40
 
30
41
  $chart-border: govuk-colour("white"); // Chart border colour
31
42
  $key-border: govuk-colour("white"); // Key border colour
32
- $bar-colours: govuk-colour("blue"), govuk-colour("turquoise"), govuk-colour("green"), govuk-colour("light-green"), govuk-colour("yellow"), govuk-colour("orange"), govuk-colour("red"), govuk-colour("bright-purple", $legacy: "bright-red");
33
- $bar-text-colours: govuk-colour("white"), govuk-colour("black"), govuk-colour("white"), govuk-colour("black"), govuk-colour("black"), govuk-colour("black"), govuk-colour("white"), govuk-colour("white");
43
+ $bar-colours: $gss-colour-dark-blue, $gss-colour-turquoise, $gss-colour-dark-pink, $gss-colour-orange, $gss-colour-dark-grey, $gss-colour-plum;
44
+ $bar-text-colours: govuk-colour("white"), govuk-colour("white"), govuk-colour("white"), govuk-colour("black"), govuk-colour("white"), govuk-colour("black");
34
45
  $bar-cell-colour: govuk-colour("black");
35
46
  $bar-outdented-colour: govuk-colour("black");
36
47
 
@@ -6,6 +6,7 @@ module GovukPublishingComponents
6
6
  @path = path
7
7
  application_found = application_exists(path)
8
8
  components_found = []
9
+ @component_locations = {}
9
10
  @gem_style_references = []
10
11
  @jquery_references = []
11
12
 
@@ -25,15 +26,15 @@ module GovukPublishingComponents
25
26
  @find_all_javascripts = /\/\/ *= require govuk_publishing_components\/all_components/
26
27
  find_javascripts = /(?<=require govuk_publishing_components\/components\/)[a-zA-Z_-]+/
27
28
 
28
- components_in_templates = find_components(templates, find_components, "templates") || []
29
- components_in_stylesheets = find_components(stylesheets, find_stylesheets, "stylesheets") || []
30
- components_in_print_stylesheets = find_components(stylesheets, find_print_stylesheets, "print_stylesheets") || []
31
- components_in_javascripts = find_components(javascripts, find_javascripts, "javascripts") || []
29
+ components_in_templates = find_components(templates, find_components, "templates", true) || []
30
+ components_in_stylesheets = find_components(stylesheets, find_stylesheets, "stylesheets", false) || []
31
+ components_in_print_stylesheets = find_components(stylesheets, find_print_stylesheets, "print_stylesheets", false) || []
32
+ components_in_javascripts = find_components(javascripts, find_javascripts, "javascripts", false) || []
32
33
 
33
34
  ruby_paths = %w[/app/helpers/ /app/presenters/ /lib/]
34
35
  components_in_ruby = []
35
36
  ruby_paths.each do |ruby_path|
36
- components_in_ruby << find_components(Dir["#{path}#{ruby_path}**/*.{rb,erb}"], find_components, "ruby") || []
37
+ components_in_ruby << find_components(Dir["#{path}#{ruby_path}**/*.{rb,erb}"], find_components, "ruby", true) || []
37
38
  end
38
39
  components_in_ruby = components_in_ruby.flatten.uniq
39
40
 
@@ -67,17 +68,32 @@ module GovukPublishingComponents
67
68
  components_found: components_found,
68
69
  gem_style_references: @gem_style_references.flatten.uniq.sort,
69
70
  jquery_references: @jquery_references.flatten.uniq.sort,
71
+ component_locations: @component_locations,
70
72
  }
71
73
  end
72
74
 
73
75
  private
74
76
 
75
- def find_components(files, find, type)
77
+ def find_components(files, find, type, keep_locations)
76
78
  components_found = []
77
79
 
78
80
  files.each do |file|
79
81
  src = File.read(file)
80
- components_found << find_match(find, src, type)
82
+
83
+ if keep_locations
84
+ components = find_match(find, src, type)
85
+ if components.any?
86
+ components_found << components
87
+ components.each do |component|
88
+ component_sym = component.to_sym
89
+ @component_locations[component_sym] = [] unless @component_locations[component_sym]
90
+ @component_locations[component_sym] << clean_file_path(file)
91
+ @component_locations[component_sym].sort!
92
+ end
93
+ end
94
+ else
95
+ components_found << find_match(find, src, type)
96
+ end
81
97
 
82
98
  if type == "javascripts"
83
99
  jquery_references = find_code_references(file, src, /\$\(/)
@@ -93,12 +109,16 @@ module GovukPublishingComponents
93
109
  components_found.flatten.uniq.sort
94
110
  end
95
111
 
112
+ # looks for components in the given src of a file
113
+ # returns an array of component names or an empty array
96
114
  def find_match(find, src, type)
97
115
  return %w[all] if src.match(@find_all_stylesheets) && type == "stylesheets"
98
116
  return %w[all] if src.match(@find_all_print_stylesheets) && type == "print_stylesheets"
99
117
  return %w[all] if src.match(@find_all_javascripts) && type == "javascripts"
100
118
 
101
119
  matches = src.scan(find)
120
+ return [] unless matches.any?
121
+
102
122
  all_matches = []
103
123
  matches.each do |match|
104
124
  all_matches << clean_file_name(match.tr('[])\'"', ""))
@@ -108,9 +128,11 @@ module GovukPublishingComponents
108
128
  end
109
129
 
110
130
  def find_code_references(file, src, regex)
111
- clean_file_path = /(?<=#{Regexp.escape(@path.to_s)}\/)[\/a-zA-Z_-]+.[a-zA-Z.]+/
131
+ return clean_file_path(file) if regex.match?(src)
132
+ end
112
133
 
113
- return file[clean_file_path] if regex.match?(src)
134
+ def clean_file_path(file)
135
+ file[/(?<=#{Regexp.escape(@path.to_s)}\/)[\/a-zA-Z_-]+.[a-zA-Z.]+/]
114
136
  end
115
137
 
116
138
  def clean_file_name(name)
@@ -106,6 +106,7 @@ module GovukPublishingComponents
106
106
  warning_count: warnings.length,
107
107
  gem_style_references: result[:gem_style_references],
108
108
  jquery_references: result[:jquery_references],
109
+ component_locations: result[:component_locations],
109
110
  }
110
111
  else
111
112
  data << {
@@ -244,28 +245,33 @@ module GovukPublishingComponents
244
245
  (haystack - needle).flatten.sort
245
246
  end
246
247
 
248
+ # returns details of component inclusion by applications
247
249
  def get_components_by_application
248
250
  results = []
249
251
  found_something = false
250
252
 
251
253
  @gem_data[:component_listing].each do |component|
252
- found_in_applications = []
254
+ component_name = component[:name]
255
+ locations = []
253
256
 
254
257
  @applications_data.each do |application|
255
- next unless application[:application_found]
258
+ next unless application[:application_found] && application[:component_locations][component_name.to_sym]
256
259
 
257
- name = application[:name]
260
+ application_name = application[:name]
258
261
  found_something = true
259
262
 
260
- application[:summary].each do |item|
261
- found_in_applications << name if item[:value].include?(component[:name])
262
- end
263
+ locations << {
264
+ name: application_name,
265
+ locations: application[:component_locations][component_name.to_sym],
266
+ }
263
267
  end
264
268
 
269
+ locations = locations.flatten
270
+
265
271
  results << {
266
- component: component[:name],
267
- count: found_in_applications.uniq.length,
268
- list: found_in_applications.uniq.join(", "),
272
+ component: component_name,
273
+ count: locations.length,
274
+ locations: locations,
269
275
  }
270
276
  end
271
277
 
@@ -63,10 +63,28 @@
63
63
  <% @components[:components_by_application].each do |component| %>
64
64
  <div class="govuk-summary-list__row">
65
65
  <dt class="govuk-summary-list__key">
66
- <%= component[:component] %> (<%= component[:count] %>)
66
+ <%= component[:component] %> (<%= pluralize(component[:count], 'use') %>)
67
67
  </dt>
68
68
  <dd class="govuk-summary-list__value">
69
- <%= component[:list] %>
69
+ <% component[:locations].each do |application| %>
70
+ <% github_link = 'https://github.com/alphagov/' + application[:name] + '/blob/main/' %>
71
+ <details class="govuk-details govuk-!-margin-bottom-2" data-module="govuk-details">
72
+ <summary class="govuk-details__summary">
73
+ <span class="govuk-details__summary-text">
74
+ <%= application[:name] %> (<%= application[:locations].length %>)
75
+ </span>
76
+ </summary>
77
+ <div class="govuk-details__text">
78
+ <ul class="govuk-list govuk-list--bullet">
79
+ <% application[:locations].each do |location| %>
80
+ <li>
81
+ <a href="<%= github_link %><%= location %>" class="govuk-link"><%= location %></a>
82
+ </li>
83
+ <% end %>
84
+ </ul>
85
+ </div>
86
+ </details>
87
+ <% end %>
70
88
  </dd>
71
89
  </div>
72
90
  <% end %>
@@ -2,46 +2,77 @@
2
2
  caption ||= nil
3
3
  head ||= []
4
4
  rows ||= []
5
- first_cell_is_header ||=false
5
+ first_cell_is_header ||= false
6
6
  caption_classes ||= nil
7
- sortable ||=false
7
+ sortable ||= false
8
+ filterable ||= false
9
+ label ||= t("components.table.filter_label")
10
+
11
+ table_id = "table-id-#{SecureRandom.hex(4)}"
12
+ filter_count_id = "filter-count-id-#{SecureRandom.hex(4)}"
8
13
  %>
9
14
 
10
- <%= GovukPublishingComponents::AppHelpers::TableHelper.helper(self, caption, {
11
- sortable: sortable,
12
- caption_classes: caption_classes
13
- }) do |t| %>
14
-
15
- <% if head.any? %>
16
- <%= t.head do %>
17
- <% head.each_with_index do |item, cellindex| %>
18
- <%= t.header item[:text], {
19
- format: item[:format],
20
- href: item[:href],
21
- data_attributes: item[:data_attributes],
22
- sort_direction: item[:sort_direction]
23
- } %>
15
+ <% @table = capture do %>
16
+ <%= GovukPublishingComponents::AppHelpers::TableHelper.helper(self, caption, {
17
+ sortable: sortable,
18
+ filterable: filterable,
19
+ caption_classes: caption_classes,
20
+ table_id: table_id
21
+ }) do |t| %>
22
+
23
+ <% if head.any? %>
24
+ <%= t.head do %>
25
+ <% head.each_with_index do |item, cellindex| %>
26
+ <%= t.header item[:text], {
27
+ format: item[:format],
28
+ href: item[:href],
29
+ data_attributes: item[:data_attributes],
30
+ sort_direction: item[:sort_direction]
31
+ } %>
32
+ <% end %>
24
33
  <% end %>
25
34
  <% end %>
26
- <% end %>
27
35
 
28
- <%= t.body do %>
29
- <% rows.each_with_index do |row, rowindex| %>
30
- <%= t.row do %>
31
- <% row.each_with_index do |cell, cellindex| %>
32
- <% if cellindex == 0 && first_cell_is_header %>
33
- <%= t.header cell[:text], {
34
- scope: "row",
35
- format: cell[:format]
36
- } %>
37
- <% else %>
38
- <%= t.cell cell[:text], {
39
- format: cell[:format]
40
- } %>
36
+ <%= t.body do %>
37
+ <% rows.each_with_index do |row, rowindex| %>
38
+ <%= t.row do %>
39
+ <% row.each_with_index do |cell, cellindex| %>
40
+ <% if cellindex == 0 && first_cell_is_header %>
41
+ <%= t.header cell[:text], {
42
+ scope: "row",
43
+ format: cell[:format]
44
+ } %>
45
+ <% else %>
46
+ <%= t.cell cell[:text], {
47
+ format: cell[:format]
48
+ } %>
49
+ <% end %>
41
50
  <% end %>
42
51
  <% end %>
43
52
  <% end %>
44
53
  <% end %>
45
54
  <% end %>
55
+ <% end %>
56
+
57
+ <% if filterable %>
58
+ <div data-module="table">
59
+ <div class="js-gem-c-table__filter govuk-!-display-none">
60
+ <%= render "govuk_publishing_components/components/input", {
61
+ label: {
62
+ text: label
63
+ },
64
+ name: "filter",
65
+ controls: table_id,
66
+ aria_described_by: filter_count_id,
67
+ } %>
68
+
69
+ <p id="<%= filter_count_id %>" aria-live="polite" class="js-filter-count govuk-visually-hidden" data-count-text="<%= t("components.table.filter_count") %>"></p>
70
+ </div>
71
+
72
+ <%= @table %>
46
73
 
74
+ <p class="govuk-body govuk-!-display-none js-gem-c-table__message"><%= t("components.table.filter_message") %></p>
75
+ </div>
76
+ <% else %>
77
+ <%= @table %>
47
78
  <% end %>
@@ -18,4 +18,4 @@ examples:
18
18
  data:
19
19
  href: '#'
20
20
  data_attributes:
21
- tracking: GT-1234
21
+ an_attribute: the value
@@ -36,8 +36,8 @@ examples:
36
36
  with_data_attributes:
37
37
  description: |
38
38
  If a `href` attribute is present, `data_attributes` will apply to the `span` containing the number value (see below).
39
-
40
- This will also not automatically apply a `gem-track-click` module attribute if the data attributes pertain to click tracking. Remember to apply this outside the component call in a surrounding element, if using.
39
+
40
+ Note that the component does not include built in tracking. If this is required consider using the [track click script](https://github.com/alphagov/govuk_publishing_components/blob/main/docs/analytics/track-click.md).
41
41
  data:
42
42
  number: 23
43
43
  label: Ministerial departments