gatsby-core-theme 1.3.0 → 1.4.2

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 (80) hide show
  1. package/.storybook/main.js +2 -3
  2. package/.storybook/preview.js +1 -4
  3. package/CHANGELOG.md +94 -0
  4. package/gatsby-node.esm.js +59 -19
  5. package/jest.config.js +1 -0
  6. package/package.json +1 -1
  7. package/src/components/app.js +12 -7
  8. package/src/components/atoms/archive/items/index.js +1 -1
  9. package/src/components/atoms/author/index.js +3 -2
  10. package/src/components/atoms/author-box/author-box.test.js +1 -5
  11. package/src/components/atoms/author-box/index.js +42 -13
  12. package/src/components/atoms/breadcrumbs/index.js +8 -4
  13. package/src/components/atoms/button/button.test.js +7 -0
  14. package/src/components/atoms/button/index.js +10 -3
  15. package/src/components/atoms/carousel/arrow/index.js +3 -2
  16. package/src/components/atoms/carousel/pagination-item/index.js +3 -2
  17. package/src/components/atoms/collapse/index.js +3 -1
  18. package/src/components/atoms/custom-select/index.js +2 -1
  19. package/src/components/atoms/logo/index.js +2 -2
  20. package/src/components/atoms/menu/items/index.js +6 -0
  21. package/src/components/atoms/menu/items/item/index.js +5 -4
  22. package/src/components/atoms/menu/menu-icon/index.js +4 -4
  23. package/src/components/atoms/module-title/index.js +2 -1
  24. package/src/components/atoms/not-found/index.js +14 -0
  25. package/src/components/atoms/not-found/not-found.module.scss +16 -0
  26. package/src/components/atoms/open-graph/index.js +5 -5
  27. package/src/components/atoms/operator-cta/index.js +15 -5
  28. package/src/components/atoms/operator-cta/{operator-cta.test.disabled.js → operator-cta.test.js} +12 -1
  29. package/src/components/atoms/operator-info-block/index.js +8 -1
  30. package/src/components/atoms/search/autocomplete/operator.js +1 -1
  31. package/src/components/atoms/spotlights/index.js +15 -4
  32. package/src/components/molecules/carousel/default-slide/index.js +4 -0
  33. package/src/components/molecules/counter/index.js +2 -2
  34. package/src/components/molecules/footer/index.js +6 -2
  35. package/src/components/molecules/header/header.test.js +0 -1
  36. package/src/components/molecules/link-list/index.js +9 -1
  37. package/src/components/molecules/main/index.js +3 -1
  38. package/src/components/molecules/menu/index.js +5 -1
  39. package/src/components/molecules/operator-banner/index.js +17 -7
  40. package/src/components/molecules/operator-banner/operator-banner.test.js +1 -1
  41. package/src/components/molecules/pagination/index.js +16 -5
  42. package/src/components/molecules/pagination/pagination.test.js +3 -3
  43. package/src/components/molecules/pagination/with-midpoints.js +41 -17
  44. package/src/components/molecules/pagination/with-midpoints.test.js +7 -8
  45. package/src/components/molecules/search/index.js +14 -3
  46. package/src/components/molecules/slider/index.js +27 -3
  47. package/src/components/molecules/toplist/default-row/index.js +27 -4
  48. package/src/components/organisms/accordion/accordion.test.js +3 -3
  49. package/src/components/organisms/accordion/index.js +1 -1
  50. package/src/components/organisms/anchor/index.js +2 -1
  51. package/src/components/organisms/archive/archive.test.js +8 -1
  52. package/src/components/organisms/archive/index.js +12 -12
  53. package/src/components/organisms/cards/cards.stories.js +1 -0
  54. package/src/components/organisms/cards/index.js +1 -1
  55. package/src/components/organisms/carousel/index.js +16 -17
  56. package/src/components/organisms/cookie-consent/cookie-consent.stories.js +6 -1
  57. package/src/components/organisms/cookie-consent/index.js +2 -0
  58. package/src/components/organisms/form/index.js +1 -0
  59. package/src/components/organisms/navigation/index.js +4 -4
  60. package/src/components/organisms/search/index.js +1 -1
  61. package/src/components/organisms/toplist/index.js +15 -19
  62. package/src/components/organisms/toplist/list/index.js +22 -29
  63. package/src/components/pages/body/index.js +9 -5
  64. package/src/components/pages/search/index.js +36 -1
  65. package/src/components/pages/tracker/index.js +8 -4
  66. package/src/constants/pick-keys.js +2 -0
  67. package/src/context/TranslationsProvider.js +9 -0
  68. package/src/helpers/processor/index.js +20 -3
  69. package/src/helpers/processor/processor.test.js +14 -0
  70. package/src/hooks/lazy-image/lazy-image.stories.js +1 -0
  71. package/src/hooks/link/index.js +2 -0
  72. package/src/hooks/link/link.test.js +9 -0
  73. package/src/hooks/modal/modal-content.js +7 -3
  74. package/src/hooks/modal/modal.test.js +3 -2
  75. package/src/hooks/tabs/index.js +4 -1
  76. package/src/hooks/tabs/tab/tab-list.js +4 -1
  77. package/src/hooks/tabs/tab/tab.js +11 -2
  78. package/src/pages/sitemap/index.js +77 -0
  79. package/src/pages/sitemap/sitemap.module.scss +21 -0
  80. package/tests/factories/relations/operator.factory.js +33 -0
@@ -32,7 +32,10 @@ const Pagination = ({
32
32
  if (i <= totalPages) {
33
33
  pages.push(
34
34
  <li key={keygen()}>
35
- <Link className={i === currentPage ? styles.active : ''} to={getPagePath(i)}>
35
+ <Link
36
+ className={`${i === currentPage ? styles.active : ''} pagination-gtm`}
37
+ to={getPagePath(i)}
38
+ >
36
39
  {i}
37
40
  </Link>
38
41
  </li>
@@ -47,13 +50,17 @@ const Pagination = ({
47
50
  {/* previous button */}
48
51
  {currentPage !== 1 && (
49
52
  <li>
50
- <Link to={getPagePath(currentPage - 1)}>{previousText}</Link>
53
+ <Link to={getPagePath(currentPage - 1)} className="pagination-gtm">
54
+ {previousText}
55
+ </Link>
51
56
  </li>
52
57
  )}
53
58
  {/* first page link */}
54
59
  {currentPage >= numOfItemsEachSide && (
55
60
  <li>
56
- <Link to={getPagePath(1)}>1</Link>
61
+ <Link to={getPagePath(1)} className="pagination-gtm">
62
+ 1
63
+ </Link>
57
64
  {currentPage !== numOfItemsEachSide && <span>...</span>}
58
65
  </li>
59
66
  )}
@@ -63,13 +70,17 @@ const Pagination = ({
63
70
  {totalPages - currentPage >= numOfItemsEachSide - 1 && (
64
71
  <li>
65
72
  {totalPages - currentPage !== numOfItemsEachSide - 1 && <span>...</span>}
66
- <Link to={getPagePath(totalPages)}>{totalPages}</Link>
73
+ <Link to={getPagePath(totalPages)} className="pagination-gtm">
74
+ {totalPages}
75
+ </Link>
67
76
  </li>
68
77
  )}
69
78
  {/* next button */}
70
79
  {currentPage < totalPages && (
71
80
  <li>
72
- <Link to={getPagePath(currentPage + 1)}>{nextText}</Link>
81
+ <Link to={getPagePath(currentPage + 1)} className="pagination-gtm">
82
+ {nextText}
83
+ </Link>
73
84
  </li>
74
85
  )}
75
86
  </ul>
@@ -14,8 +14,8 @@ describe('Pagination Component', () => {
14
14
  });
15
15
 
16
16
  test('current page class name', () => {
17
- expect(screen.getByText('3').getAttribute('class')).toEqual('active');
18
- expect(screen.getByText('5').getAttribute('class')).toEqual('');
17
+ expect(screen.getByText('3').getAttribute('class')).toEqual('active pagination-gtm');
18
+ expect(screen.getByText('5').getAttribute('class')).toEqual(' pagination-gtm');
19
19
  });
20
20
 
21
21
  test('number of items', () => {
@@ -36,7 +36,7 @@ describe('Pagination Component', () => {
36
36
  // so the last item is item index 9 = ( 9 + 2 ) - 2
37
37
  // and it should link to the total page number ( 26 )
38
38
  expect(container.querySelectorAll('li')[9].innerHTML).toEqual(
39
- '<span>...</span><a href="/another_type/page/26">26</a>'
39
+ '<span>...</span><a class="pagination-gtm" href="/another_type/page/26">26</a>'
40
40
  );
41
41
  });
42
42
  });
@@ -1,8 +1,9 @@
1
- import React from 'react';
1
+ import React, { useContext } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { MdLastPage, MdFirstPage, MdChevronRight, MdChevronLeft } from 'react-icons/md';
4
4
  import { translate } from '~helpers/getters';
5
5
  import Link from '~hooks/link';
6
+ import { Context } from '~context/TranslationsProvider';
6
7
  import styles from './pagination-with-midpoints.module.scss';
7
8
 
8
9
  const PaginationWithMidPoints = ({
@@ -13,8 +14,8 @@ const PaginationWithMidPoints = ({
13
14
  nextComp = <MdChevronRight />,
14
15
  firstComp = <MdFirstPage />,
15
16
  lastComp = <MdLastPage />,
16
- translations,
17
17
  }) => {
18
+ const { translations } = useContext(Context) || {};
18
19
  const current = Number(currentPage);
19
20
  const total = Number(totalPages);
20
21
  function getPagePath(index) {
@@ -30,7 +31,10 @@ const PaginationWithMidPoints = ({
30
31
  {/* got to first page */}
31
32
  <li className={styles.showInAll}>
32
33
  {current > 1 ? (
33
- <Link to={getPagePath(1)} className={`${styles.button} ${styles.isActive}`}>
34
+ <Link
35
+ to={getPagePath(1)}
36
+ className={`${styles.button} ${styles.isActive} pagination-gtm`}
37
+ >
34
38
  {firstComp}
35
39
  </Link>
36
40
  ) : (
@@ -40,7 +44,10 @@ const PaginationWithMidPoints = ({
40
44
  {/* previous button */}
41
45
  <li className={styles.showInAll}>
42
46
  {current > 1 ? (
43
- <Link to={getPagePath(current - 1)} className={`${styles.button} ${styles.isActive}`}>
47
+ <Link
48
+ to={getPagePath(current - 1)}
49
+ className={`${styles.button} ${styles.isActive} pagination-gtm`}
50
+ >
44
51
  {previousComp}
45
52
  </Link>
46
53
  ) : (
@@ -52,59 +59,76 @@ const PaginationWithMidPoints = ({
52
59
  {/* first page link */}
53
60
  {current !== 1 && (
54
61
  <li>
55
- <Link to={getPagePath(1)}>1</Link>
62
+ <Link to={getPagePath(1)} className="pagination-gtm">
63
+ 1
64
+ </Link>
56
65
  {current > 4 && <span>...</span>}
57
66
  </li>
58
67
  )}
59
68
  {/* first mid page link */}
60
69
  {current > 3 && (
61
70
  <li>
62
- <Link to={getPagePath(firstMidPage)}>{firstMidPage}</Link>
71
+ <Link to={getPagePath(firstMidPage)} className="pagination-gtm">
72
+ {firstMidPage}
73
+ </Link>
63
74
  {firstMidPage < current - 2 && <span>...</span>}
64
75
  </li>
65
76
  )}
66
77
  {/* current page -1 link */}
67
78
  {current > 2 && (
68
79
  <li>
69
- <Link to={getPagePath(current - 1)}>{current - 1}</Link>
80
+ <Link to={getPagePath(current - 1)} className="pagination-gtm">
81
+ {current - 1}
82
+ </Link>
70
83
  </li>
71
84
  )}
72
85
  {/* current page link */}
73
86
  <li className={styles.showInAll}>
74
- <Link to={getPagePath(current)} className={styles.active}>
87
+ <Link to={getPagePath(current)} className={`${styles.active} pagination-gtm`}>
75
88
  {current}
76
89
  </Link>
77
90
  </li>
78
91
  {/* current page +1 link */}
79
92
  {current < total - 1 && (
80
93
  <li>
81
- <Link to={getPagePath(current + 1)}>{current + 1}</Link>
94
+ <Link to={getPagePath(current + 1)} className="pagination-gtm">
95
+ {current + 1}
96
+ </Link>
82
97
  </li>
83
98
  )}
84
99
  {/* last mid page link */}
85
100
  {current < total - 3 && (
86
101
  <li>
87
102
  {lastMidPage > current + 2 && <span>...</span>}
88
- <Link to={getPagePath(lastMidPage)}>{lastMidPage}</Link>
103
+ <Link to={getPagePath(lastMidPage)} className="pagination-gtm">
104
+ {lastMidPage}
105
+ </Link>
89
106
  </li>
90
107
  )}
91
108
  {/* last page link */}
92
109
  {current !== total && (
93
110
  <li>
94
111
  {current < total - 2 && <span>...</span>}
95
- <Link to={getPagePath(total)}>{total}</Link>
112
+ <Link to={getPagePath(total)} className="pagination-gtm">
113
+ {total}
114
+ </Link>
96
115
  </li>
97
116
  )}
98
117
  <li className={styles.showInMobile}>
99
118
  <span>{translate(translations, 'of', 'of')}</span>
100
- <Link to={getPagePath(total)}>{total}</Link>
119
+ <Link to={getPagePath(total)} className="pagination-gtm">
120
+ {total}
121
+ </Link>
101
122
  </li>
102
123
  </div>
103
124
 
104
125
  {/* next button */}
105
126
  <li className={styles.showInAll}>
106
127
  {current < total ? (
107
- <Link to={getPagePath(current + 1)} className={`${styles.button} ${styles.isActive}`}>
128
+ <Link
129
+ to={getPagePath(current + 1)}
130
+ className={`${styles.button} ${styles.isActive} pagination-gtm`}
131
+ >
108
132
  {nextComp}
109
133
  </Link>
110
134
  ) : (
@@ -114,7 +138,10 @@ const PaginationWithMidPoints = ({
114
138
  {/* got to last page */}
115
139
  <li className={styles.showInAll}>
116
140
  {current !== total ? (
117
- <Link to={getPagePath(total)} className={`${styles.button} ${styles.isActive}`}>
141
+ <Link
142
+ to={getPagePath(total)}
143
+ className={`${styles.button} ${styles.isActive} pagination-gtm`}
144
+ >
118
145
  {lastComp}
119
146
  </Link>
120
147
  ) : (
@@ -133,9 +160,6 @@ PaginationWithMidPoints.propTypes = {
133
160
  previousComp: PropTypes.oneOfType([PropTypes.element, PropTypes.any]),
134
161
  firstComp: PropTypes.oneOfType([PropTypes.element, PropTypes.any]),
135
162
  lastComp: PropTypes.oneOfType([PropTypes.element, PropTypes.any]),
136
- translations: PropTypes.shape({
137
- of: PropTypes.string,
138
- }),
139
163
  };
140
164
 
141
165
  export default PaginationWithMidPoints;
@@ -1,12 +1,11 @@
1
1
  import React from 'react';
2
- import { render, screen, cleanup } from '@testing-library/react';
2
+ import { render, cleanup } from '@testing-library/react';
3
3
  import '@testing-library/jest-dom/extend-expect';
4
-
5
4
  import PaginationWithMidPoints from './with-midpoints';
6
5
 
7
6
  describe('Pagination Component', () => {
8
7
  test('render with props', () => {
9
- const { container, getByText , getAllByText } = render(
8
+ const { container, getByText, getAllByText } = render(
10
9
  <PaginationWithMidPoints currentPage={10} pagePath="example" totalPages={60} />
11
10
  );
12
11
  expect(container).toBeTruthy();
@@ -24,32 +23,32 @@ describe('Pagination Component', () => {
24
23
  const { getByText } = render(
25
24
  <PaginationWithMidPoints currentPage={15} pagePath="example" totalPages={35} />
26
25
  );
27
- expect(getByText('15').getAttribute('class')).toEqual('active');
26
+ expect(getByText('15').getAttribute('class')).toEqual('active pagination-gtm');
28
27
  });
29
28
 
30
29
  test('render with different midpoints', () => {
31
- const { container, getByText,getAllByText } = render(
30
+ const { container, getByText, getAllByText } = render(
32
31
  <PaginationWithMidPoints currentPage={40} pagePath="example" totalPages={60} />
33
32
  );
34
33
  expect(container).toBeTruthy();
35
34
  expect(getByText('1').getAttribute('href')).toEqual('/example');
36
35
  expect(getByText('20').getAttribute('href')).toEqual('/example/page/20');
37
36
  expect(getByText('39').getAttribute('href')).toEqual('/example/page/39');
38
- expect(getByText('40').getAttribute('class')).toEqual('active');
37
+ expect(getByText('40').getAttribute('class')).toEqual('active pagination-gtm');
39
38
  expect(getByText('41').getAttribute('href')).toEqual('/example/page/41');
40
39
  expect(getByText('50').getAttribute('href')).toEqual('/example/page/50');
41
40
  expect(getAllByText('60')[0].getAttribute('href')).toEqual('/example/page/60');
42
41
  });
43
42
 
44
43
  test('render with different midpoints', () => {
45
- const { container, getByText,getAllByText } = render(
44
+ const { container, getByText, getAllByText } = render(
46
45
  <PaginationWithMidPoints currentPage={30} pagePath="example" totalPages={60} />
47
46
  );
48
47
  expect(container).toBeTruthy();
49
48
  expect(getByText('1').getAttribute('href')).toEqual('/example');
50
49
  expect(getByText('15').getAttribute('href')).toEqual('/example/page/15');
51
50
  expect(getByText('29').getAttribute('href')).toEqual('/example/page/29');
52
- expect(getByText('30').getAttribute('class')).toEqual('active');
51
+ expect(getByText('30').getAttribute('class')).toEqual('active pagination-gtm');
53
52
  expect(getByText('31').getAttribute('href')).toEqual('/example/page/31');
54
53
  expect(getByText('45').getAttribute('href')).toEqual('/example/page/45');
55
54
  expect(getAllByText('60')[0].getAttribute('href')).toEqual('/example/page/60');
@@ -29,6 +29,7 @@ const Search = ({
29
29
  pageSearchOptions = null,
30
30
  inputPlaceholder = '',
31
31
  children,
32
+ page,
32
33
  }) => {
33
34
  const { setShowSearch } = useContext(NavigationContext);
34
35
  const pageSearchOptionsCopy = pageSearchOptions;
@@ -241,7 +242,7 @@ const Search = ({
241
242
  // Use a default or given close button
242
243
  if (formSearchOptionsCopy !== null && formSearchOptionsCopy.searchButtonComponent === undefined) {
243
244
  formSearchOptionsCopy.searchButtonComponent = (
244
- <button aria-label="Search" type="submit">
245
+ <button aria-label="Search" type="submit" className="search-gtm btn-cta">
245
246
  {searchIcon === null ? <FaSearch /> : <img alt="search" src={searchIcon} />}
246
247
  </button>
247
248
  );
@@ -289,7 +290,7 @@ const Search = ({
289
290
  maxLength="60"
290
291
  />
291
292
  <div className={styles.searchButton}>
292
- <button aria-label="Search" type="submit">
293
+ <button aria-label="Search" type="submit" className="search-gtm btn-cta">
293
294
  {searchIcon === null ? <FaSearch /> : <img alt="search" src={searchIcon} />}
294
295
  </button>
295
296
  </div>
@@ -310,6 +311,7 @@ const Search = ({
310
311
  {...pageSearchOptionsCopy.tabsOptions}
311
312
  activeTabClass="searchActive"
312
313
  headerClass="searchHeader"
314
+ gtmClass="search-tabs-menu-gtm"
313
315
  >
314
316
  {items}
315
317
  </Tabs>
@@ -332,6 +334,7 @@ const Search = ({
332
334
  items,
333
335
  model_type: type,
334
336
  title: titleObj ? titleObj.title : '',
337
+ pagination_type: 'load_more',
335
338
  ...pageSearchOptionsCopy.archiveOptions.includeOptions,
336
339
  };
337
340
  }
@@ -353,7 +356,12 @@ const Search = ({
353
356
  module_title_tag: 'h2',
354
357
  }}
355
358
  />
356
- <Archive module={items} loadMore={loadMore} />
359
+ <Archive
360
+ module={items}
361
+ loadMore={loadMore}
362
+ page={page}
363
+ gtmClass="archive-gtm"
364
+ />
357
365
  </>
358
366
  )}
359
367
  </div>
@@ -413,6 +421,9 @@ Search.propTypes = {
413
421
  }),
414
422
  children: PropTypes.elementType,
415
423
  styles: PropTypes.shape({}),
424
+ page: PropTypes.shape({
425
+ translations: PropTypes.shape({}),
426
+ }),
416
427
  };
417
428
 
418
429
  export default Search;
@@ -1,3 +1,5 @@
1
+ /* eslint-disable no-unused-expressions */
2
+ /* eslint-disable react-hooks/exhaustive-deps */
1
3
  import React, { useState, useRef, useEffect } from 'react';
2
4
  import PropTypes, { element } from 'prop-types';
3
5
 
@@ -15,11 +17,12 @@ import Arrow from '~atoms/carousel/arrow';
15
17
  import Pagination from '~atoms/carousel/pagination-item';
16
18
 
17
19
  function Slider({
20
+ gtmClass = '',
18
21
  useArrows = true,
19
22
  usePagination = true,
20
23
  arrows = {
21
- prev: <Arrow direction="left" />,
22
- next: <Arrow direction="right" />,
24
+ prev: <Arrow direction="left" gtmClass={gtmClass} />,
25
+ next: <Arrow direction="right" gtmClass={gtmClass} />,
23
26
  },
24
27
  settings = {
25
28
  swipeEndThreshold: 0.25,
@@ -108,6 +111,23 @@ function Slider({
108
111
  sliderConditionsRef
109
112
  );
110
113
 
114
+ let throttlePause;
115
+ const onWheel = (e) => {
116
+ e.preventDefault();
117
+ if (useArrows || usePagination) {
118
+ throttlePause ? null : (throttlePause = true);
119
+ setTimeout(() => {
120
+ e.deltaY > 0 ? arrowHandler('next') : arrowHandler('prev');
121
+ throttlePause = false;
122
+ }, 300);
123
+ } else {
124
+ sliderContainerRef.current.scrollTo({
125
+ top: 0,
126
+ left: sliderContainerRef.current.scrollLeft + e.deltaY,
127
+ });
128
+ }
129
+ };
130
+
111
131
  useEffect(() => {
112
132
  // Keep slider node reference for multiple carousels in an instance
113
133
  const sliderContentNode = sliderContentRef.current;
@@ -145,6 +165,7 @@ function Slider({
145
165
  sliderContentNode.addEventListener('touchstart', mousedown);
146
166
  sliderContentNode.addEventListener('touchmove', mouseMoveDebounce);
147
167
  sliderContentNode.addEventListener('touchend', mouseUpDebounce);
168
+ sliderContainerRef.current.addEventListener('wheel', onWheel);
148
169
 
149
170
  return () => {
150
171
  sliderContentNode.removeEventListener('click', click);
@@ -154,6 +175,7 @@ function Slider({
154
175
  sliderContentNode.removeEventListener('touchstart', mousedown);
155
176
  sliderContentNode.removeEventListener('touchmove', mouseMoveDebounce);
156
177
  sliderContentNode.removeEventListener('touchend', mouseUpDebounce);
178
+ sliderContainerRef.current.removeEventListener('wheel', onWheel);
157
179
  };
158
180
  });
159
181
 
@@ -175,7 +197,7 @@ function Slider({
175
197
  <div
176
198
  tabIndex="0"
177
199
  role="button"
178
- className={styles.sliderContent}
200
+ className={`${styles.sliderContent}`}
179
201
  style={style}
180
202
  ref={sliderContentRef}
181
203
  >
@@ -204,6 +226,7 @@ function Slider({
204
226
  paginationHandler={paginationHandler}
205
227
  slideIndex={state.slideIndex}
206
228
  totalSlides={state.length}
229
+ gtmClass={gtmClass}
207
230
  />
208
231
  )}
209
232
  </div>
@@ -225,6 +248,7 @@ Slider.propTypes = {
225
248
  }),
226
249
  className: PropTypes.string,
227
250
  children: PropTypes.arrayOf(element).isRequired,
251
+ gtmClass: PropTypes.string,
228
252
  };
229
253
 
230
254
  export default Slider;
@@ -16,19 +16,42 @@ const Row = ({ item, oneliner = 'main', layout = 'list' }) => {
16
16
 
17
17
  return (
18
18
  <div className={`${styles.row} ${styles[layout]}`}>
19
- <a href={prettyLink} title={item.name} target="_blank" rel="noreferrer">
19
+ <a
20
+ href={prettyLink}
21
+ className="casinos-top-list-gtm name-cta"
22
+ title={item.name}
23
+ target="_blank"
24
+ rel="noreferrer"
25
+ >
20
26
  {item.name}
21
27
  </a>
22
- <a href={prettyLink} title={item.name} target="_blank" rel="noreferrer">
28
+ <a
29
+ href={prettyLink}
30
+ title={item.name}
31
+ className="casinos-top-list-gtm logo-cta"
32
+ target="_blank"
33
+ rel="noreferrer"
34
+ >
23
35
  <LazyImage alt={item.name} src={imagePrettyUrl(item.logo_url, 100)} />
24
36
  </a>
25
37
  <Bonus item={item} tracker={oneliner} />
26
38
  <SellingPoints icon={<MdCheck />} sellingPoints={item.selling_points} />
27
39
  <div>
28
- <Button to={`/${item.review_link}`} primaryColor={false} btnText="Omtale" />
40
+ <Button
41
+ to={`/${item.review_link}`}
42
+ primaryColor={false}
43
+ gtmClass="casinos-top-list-gtm btn-cta"
44
+ btnText="Omtale"
45
+ />
29
46
  </div>
30
47
  <div>
31
- <Button to={prettyLink} btnText="Spill nå!" primaryColor isInternalLink={false} />
48
+ <Button
49
+ to={prettyLink}
50
+ btnText="Spill nå!"
51
+ gtmClass="casinos-top-list-gtm btn-cta"
52
+ primaryColor
53
+ isInternalLink={false}
54
+ />
32
55
  </div>
33
56
  </div>
34
57
  );
@@ -48,8 +48,8 @@ describe('Accordions Component', () => {
48
48
  fireEvent.click(thirdtItemBtn);
49
49
  const items = container.querySelectorAll('button.title');
50
50
  expect(items[2].getAttribute('class')).toContain('invertArrow');
51
- expect(items[1].getAttribute('class')).toEqual('title');
52
- expect(items[0].getAttribute('class')).toEqual('title');
51
+ expect(items[1].getAttribute('class')).toEqual('title accordion-gtm btn-cta');
52
+ expect(items[0].getAttribute('class')).toEqual('title accordion-gtm btn-cta');
53
53
  });
54
54
 
55
55
  test('do not close others when open one', () => {
@@ -61,7 +61,7 @@ describe('Accordions Component', () => {
61
61
  fireEvent.click(thirdtItemBtn);
62
62
  const items = container.querySelectorAll('button.title');
63
63
  expect(items[2].getAttribute('class')).toContain('invertArrow');
64
- expect(items[1].getAttribute('class')).toEqual('title');
64
+ expect(items[1].getAttribute('class')).toEqual('title accordion-gtm btn-cta');
65
65
  expect(items[0].getAttribute('class')).toContain('invertArrow');
66
66
  });
67
67
  });
@@ -62,7 +62,7 @@ const Accordion = ({ module, openAll = false, openItem, closeOthers = false }) =
62
62
  <div key={keygen()} className={styles.accordionItem}>
63
63
  <button
64
64
  onClick={() => toggle(index)}
65
- className={styles.title}
65
+ className={`${styles.title} accordion-gtm btn-cta`}
66
66
  type="button"
67
67
  ref={(el) => (btnRefs.current[index] = el)}
68
68
  >
@@ -28,10 +28,11 @@ function Anchor({ module: { items }, headerOffset = 80, sliderGap = 0 }) {
28
28
  usePagination={false}
29
29
  settings={{ numberOfSlides: 0, sliderGap }}
30
30
  className={styles.sliderWrapper}
31
+ gtmClass="anchor-carousel-gtm"
31
32
  >
32
33
  {items.map((anchor) => (
33
34
  <a
34
- className={styles.link}
35
+ className={`${styles.link} anchor-carousel-gtm anchor-menu-gtm`}
35
36
  key={keygen()}
36
37
  onClick={handleClick}
37
38
  href={`#${anchor.label && anchorLink(anchor?.label?.toLowerCase().trim())}`}
@@ -26,7 +26,14 @@ describe('archive component', () => {
26
26
  const archiveModule = getArchiveModule(4, 2);
27
27
 
28
28
  const { container, getByText } = render(
29
- <Archive module={archiveModule} page={{ page: { translations: {} } }} />
29
+ <Archive
30
+ module={archiveModule}
31
+ page={{ page: { translations: {} } }}
32
+ loadMore={{
33
+ limit: 3,
34
+ increment: 6,
35
+ }}
36
+ />
30
37
  );
31
38
  expect(container.querySelectorAll('button')).toHaveLength(1);
32
39
  expect(getByText('Load More')).toBeTruthy();
@@ -1,4 +1,3 @@
1
- /* eslint-disable react/forbid-prop-types */
2
1
  /* eslint-disable no-nested-ternary */
3
2
  import React, { useState, useEffect } from 'react';
4
3
  import PropTypes from 'prop-types';
@@ -9,23 +8,23 @@ import Button from '~atoms/button';
9
8
  import { translate } from '~helpers/getters';
10
9
  import styles from './archive.module.scss';
11
10
 
12
- const Archive = ({ module, PaginationComponent, page }) => {
11
+ const Archive = ({ module, PaginationComponent, page, loadMore, gtmClass = '' }) => {
13
12
  const [moduleItems, setModuleItems] = useState([...module.items]);
14
13
  const updatedModule = { ...module };
15
- const loadMore = module.pagination_type === 'load_more';
14
+ const hasLoadMore = module.pagination_type === 'load_more';
16
15
 
17
16
  useEffect(() => {
18
17
  if (module.pagination_type === 'load_more') {
19
- const items = module.items.filter((item, index) => index < parseInt(module.num_of_items));
18
+ const items = module.items.filter((item, index) => index < parseInt(loadMore.limit));
20
19
  setModuleItems(items);
21
20
  }
22
- }, [module, module.items]);
21
+ }, [module, module.items, loadMore]);
23
22
 
24
23
  const loadMoreHandler = () => {
25
24
  let items = [...module.items];
26
25
  if (items.length > moduleItems.length) {
27
26
  items = items.filter(
28
- (item, index) => index < moduleItems.length + parseInt(module.num_of_items)
27
+ (item, index) => index < moduleItems.length + parseInt(loadMore.increment)
29
28
  );
30
29
  setModuleItems(items);
31
30
  }
@@ -34,15 +33,16 @@ const Archive = ({ module, PaginationComponent, page }) => {
34
33
  updatedModule.items = moduleItems;
35
34
  return (
36
35
  <>
37
- <Items module={updatedModule} page={page} />
38
- {loadMore ? (
36
+ <Items module={updatedModule} page={page} gtmClass={gtmClass} />
37
+ {hasLoadMore ? (
39
38
  module.items.length > updatedModule.items.length && (
40
39
  <div className={styles.loadMoreWrapper}>
41
40
  <Button
42
- btnText={translate(page.translations, 'load_more', 'Load More')}
41
+ btnText={translate(page?.translations, 'load_more', 'Load More')}
43
42
  onClick={loadMoreHandler}
44
43
  isButton
45
44
  primaryColor
45
+ gtmClass="archive-gtm btn-cta"
46
46
  />
47
47
  </div>
48
48
  )
@@ -51,7 +51,6 @@ const Archive = ({ module, PaginationComponent, page }) => {
51
51
  pagePath={module.rootPath}
52
52
  currentPage={module.currentPage}
53
53
  totalPages={module.numOfPages}
54
- translations={page.translations}
55
54
  />
56
55
  ) : (
57
56
  <Pagination
@@ -72,7 +71,7 @@ Archive.propTypes = {
72
71
  numOfPages: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
73
72
  items: PropTypes.arrayOf(PropTypes.object),
74
73
  pagination_type: PropTypes.string,
75
- num_of_items: PropTypes.string,
74
+ num_of_items: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
76
75
  }).isRequired,
77
76
  loadMore: PropTypes.shape({
78
77
  label: PropTypes.string,
@@ -83,8 +82,9 @@ Archive.propTypes = {
83
82
  }),
84
83
  PaginationComponent: PropTypes.oneOfType([PropTypes.element, PropTypes.node, PropTypes.any]),
85
84
  page: PropTypes.shape({
86
- translations: PropTypes.object,
85
+ translations: PropTypes.shape({}),
87
86
  }),
87
+ gtmClass: PropTypes.string,
88
88
  };
89
89
 
90
90
  export default Archive;
@@ -1,3 +1,4 @@
1
+ /* eslint-disable import/no-extraneous-dependencies */
1
2
  import React from 'react';
2
3
  import {
3
4
  Title,
@@ -46,7 +46,7 @@ const Cards = ({ module, CustomCardComponent, page, desktopColumns = 4 }) => (
46
46
  {module.items &&
47
47
  module.items.map((item, index) => (
48
48
  <div key={keygen()}>
49
- {CustomCardComponent !== undefined ? (
49
+ {CustomCardComponent ? (
50
50
  <CustomCardComponent
51
51
  featured={module.style === 'featured'}
52
52
  item={item}