gatsby-core-theme 1.6.21 → 2.0.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.
- package/CHANGELOG.md +85 -0
- package/gatsby-node.esm.js +14 -3
- package/package.json +2 -2
- package/src/components/app.js +4 -0
- package/src/components/atoms/iframe/index.js +15 -9
- package/src/components/atoms/selling-points/index.js +1 -2
- package/src/components/atoms/selling-points/selling-points.module.scss +12 -5
- package/src/components/atoms/selling-points/selling-points.test.js +1 -1
- package/src/components/molecules/content/index.js +10 -1
- package/src/components/molecules/footer/footer.test.js +22 -22
- package/src/components/molecules/footer/index.js +3 -1
- package/src/components/molecules/header/index.js +7 -2
- package/src/components/molecules/link-list/index.js +9 -12
- package/src/components/molecules/operator-banner/operator-banner.test.js +0 -1
- package/src/components/molecules/search/index.js +5 -3
- package/src/components/molecules/slider/index.js +6 -2
- package/src/components/molecules/slider/slider.test.js +30 -23
- package/src/components/molecules/star-rating/index.js +10 -22
- package/src/components/molecules/star-rating/star-rating.module.scss +13 -1
- package/src/components/molecules/star-rating/star-rating.test.js +5 -4
- package/src/components/molecules/tnc/index.js +2 -3
- package/src/components/molecules/tnc/tnc.test.js +0 -1
- package/src/components/molecules/toplist/default-row/index.js +22 -20
- package/src/components/pages/search/index.js +3 -2
- package/src/helpers/device-detect.js +5 -6
- package/src/helpers/events.js +91 -0
- package/src/helpers/generators.js +11 -3
- package/src/helpers/generators.test.js +34 -12
- package/src/helpers/processor/sports.js +0 -2
- package/src/helpers/rating.js +2 -0
- package/src/helpers/schedule.js +0 -36
- package/src/hooks/lazy-image/index.js +30 -44
- package/src/hooks/tabs/index.js +4 -2
- package/src/hooks/tabs/tabs.test.js +32 -15
- package/src/styles/utils/_mixins.scss +42 -0
- package/src/styles/utils/variables/_main.scss +8 -0
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { FaStar, FaStarHalfAlt, FaRegStar } from 'react-icons/fa';
|
|
3
2
|
import PropTypes from 'prop-types';
|
|
4
3
|
import LazyLoad from 'react-lazyload';
|
|
5
|
-
|
|
6
4
|
import styles from './star-rating.module.scss';
|
|
7
5
|
import keygen from '~helpers/keygen';
|
|
8
6
|
import { getRating } from '~helpers/rating';
|
|
9
7
|
|
|
10
|
-
const StarRating = ({
|
|
11
|
-
numOfStars,
|
|
12
|
-
iconEmpty = <FaRegStar />,
|
|
13
|
-
iconHalf = <FaStarHalfAlt />,
|
|
14
|
-
iconFull = <FaStar />,
|
|
15
|
-
rating,
|
|
16
|
-
halfStars = true,
|
|
17
|
-
}) => {
|
|
8
|
+
const StarRating = ({ numOfStars, rating, halfStars = true }) => {
|
|
18
9
|
const renderFarm = () => {
|
|
19
10
|
const output = [];
|
|
20
11
|
const rate = getRating(rating);
|
|
@@ -22,20 +13,20 @@ const StarRating = ({
|
|
|
22
13
|
for (let i = 1; i < numOfStars + 1; i += 1) {
|
|
23
14
|
if (i <= rate) {
|
|
24
15
|
output.push(
|
|
25
|
-
<span className={
|
|
26
|
-
{
|
|
16
|
+
<span className={styles.fullStar} key={keygen()}>
|
|
17
|
+
{' '}
|
|
27
18
|
</span>
|
|
28
19
|
);
|
|
29
20
|
} else if (halfStars && i - 0.5 === rate) {
|
|
30
21
|
output.push(
|
|
31
|
-
<span className={
|
|
32
|
-
{
|
|
22
|
+
<span className={styles.halfStar} key={keygen()}>
|
|
23
|
+
{' '}
|
|
33
24
|
</span>
|
|
34
25
|
);
|
|
35
26
|
} else {
|
|
36
27
|
output.push(
|
|
37
|
-
<span className={
|
|
38
|
-
{
|
|
28
|
+
<span className={styles.emptyStar} key={keygen()}>
|
|
29
|
+
{' '}
|
|
39
30
|
</span>
|
|
40
31
|
);
|
|
41
32
|
}
|
|
@@ -43,17 +34,14 @@ const StarRating = ({
|
|
|
43
34
|
return output;
|
|
44
35
|
};
|
|
45
36
|
return (
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
</
|
|
37
|
+
<div className={styles.starRatingContainer}>
|
|
38
|
+
<LazyLoad>{renderFarm()}</LazyLoad>
|
|
39
|
+
</div>
|
|
49
40
|
);
|
|
50
41
|
};
|
|
51
42
|
|
|
52
43
|
StarRating.propTypes = {
|
|
53
44
|
numOfStars: PropTypes.oneOf([5, 10]).isRequired,
|
|
54
|
-
iconEmpty: PropTypes.element,
|
|
55
|
-
iconHalf: PropTypes.element,
|
|
56
|
-
iconFull: PropTypes.element,
|
|
57
45
|
rating: PropTypes.oneOfType([PropTypes.array, PropTypes.number, PropTypes.string]).isRequired,
|
|
58
46
|
halfStars: PropTypes.bool,
|
|
59
47
|
};
|
|
@@ -7,4 +7,16 @@
|
|
|
7
7
|
fill: var(--star-rating-color);
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
.fullStar{
|
|
12
|
+
@include star(var(--full-star-fill-color), var(--full-star-border-color))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.halfStar{
|
|
16
|
+
@include half-star(var(--half-star-border-color), var(--halfFull-star-fill-color), var(--halfEmpty-star-fill-color))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.emptyStar{
|
|
20
|
+
@include star(var(--empty-star-border-color), var(--empty-star-fill-color))
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, cleanup } from '@testing-library/react';
|
|
2
|
+
import { render, cleanup, waitFor } from '@testing-library/react';
|
|
3
3
|
import '@testing-library/jest-dom/extend-expect';
|
|
4
4
|
|
|
5
5
|
import StarRating from '.';
|
|
6
6
|
|
|
7
7
|
describe('StarRating Component', () => {
|
|
8
|
-
test('render container with lazyload', () => {
|
|
8
|
+
test('render container with lazyload', async () => {
|
|
9
9
|
const { container } = render(<StarRating numOfStars={10} rating={6.5} />);
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
await waitFor(() => {
|
|
11
|
+
expect(container.querySelectorAll('.lazyload-placeholder')).toHaveLength(1);
|
|
12
|
+
});
|
|
12
13
|
});
|
|
13
14
|
});
|
|
14
15
|
afterEach(() => {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import LazyLoad from 'react-lazyload';
|
|
4
3
|
|
|
5
4
|
import Collapse from '~atoms/collapse';
|
|
6
5
|
|
|
@@ -13,7 +12,7 @@ const Tnc = ({
|
|
|
13
12
|
initOpen = false,
|
|
14
13
|
operator,
|
|
15
14
|
}) => (
|
|
16
|
-
|
|
15
|
+
<>
|
|
17
16
|
{hasCollapse ? (
|
|
18
17
|
<Collapse
|
|
19
18
|
onlyMobile={onlyMobile}
|
|
@@ -26,7 +25,7 @@ const Tnc = ({
|
|
|
26
25
|
) : (
|
|
27
26
|
contentText
|
|
28
27
|
)}
|
|
29
|
-
|
|
28
|
+
</>
|
|
30
29
|
);
|
|
31
30
|
|
|
32
31
|
Tnc.propTypes = {
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { MdCheck } from 'react-icons/md';
|
|
4
|
-
|
|
5
|
-
import Button from '~atoms/button';
|
|
6
4
|
import Bonus from '~atoms/bonus';
|
|
5
|
+
import { Context } from '~context/TranslationsProvider';
|
|
7
6
|
import SellingPoints from '~atoms/selling-points';
|
|
8
|
-
|
|
9
|
-
import
|
|
7
|
+
import StarRating from '~molecules/star-rating';
|
|
8
|
+
import Link from '~hooks/link';
|
|
9
|
+
import OperatorCta from '~atoms/operator-cta';
|
|
10
|
+
import { prettyTracker, imagePrettyUrl, translate } from '~helpers/getters';
|
|
10
11
|
import LazyImage from '~hooks/lazy-image';
|
|
11
12
|
|
|
12
13
|
import styles from './default-row.module.scss';
|
|
13
14
|
|
|
14
|
-
const Row = ({ item, oneliner = 'main', layout = 'list' }) => {
|
|
15
|
+
const Row = ({ item, oneliner = 'main', layout = 'list', tracker = 'main' }) => {
|
|
15
16
|
const prettyLink = prettyTracker(item);
|
|
17
|
+
const itemRating = item.rating;
|
|
18
|
+
const { translations } = useContext(Context) || {};
|
|
16
19
|
|
|
17
20
|
return (
|
|
18
21
|
<div className={`${styles.row} ${styles[layout]}`}>
|
|
@@ -33,26 +36,23 @@ const Row = ({ item, oneliner = 'main', layout = 'list' }) => {
|
|
|
33
36
|
rel="noreferrer"
|
|
34
37
|
aria-label={`${item.name} Link`}
|
|
35
38
|
>
|
|
36
|
-
<LazyImage
|
|
39
|
+
<LazyImage
|
|
40
|
+
alt={item.name}
|
|
41
|
+
src={imagePrettyUrl(item.logo_url, 100)}
|
|
42
|
+
width={150}
|
|
43
|
+
height={40}
|
|
44
|
+
/>
|
|
37
45
|
</a>
|
|
38
46
|
<Bonus item={item} tracker={oneliner} />
|
|
47
|
+
<StarRating numOfStars={5} rating={itemRating} />
|
|
39
48
|
<SellingPoints icon={<MdCheck />} sellingPoints={item.selling_points} />
|
|
40
49
|
<div>
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
gtmClass="casinos-top-list-gtm btn-cta"
|
|
45
|
-
btnText="Omtale"
|
|
46
|
-
/>
|
|
50
|
+
<Link className={`${styles.reviewLink} toplist-variant-one-gtm`} to={item.review_link}>
|
|
51
|
+
{`${translate(translations, 'read_review', 'Review')}`}
|
|
52
|
+
</Link>
|
|
47
53
|
</div>
|
|
48
54
|
<div>
|
|
49
|
-
<
|
|
50
|
-
to={prettyLink}
|
|
51
|
-
btnText="Spill nå!"
|
|
52
|
-
gtmClass="casinos-top-list-gtm btn-cta"
|
|
53
|
-
primaryColor
|
|
54
|
-
isInternalLink={false}
|
|
55
|
-
/>
|
|
55
|
+
<OperatorCta operator={item} tracker={tracker} gtmClass="toplist-operator-cta-gtm" />
|
|
56
56
|
</div>
|
|
57
57
|
</div>
|
|
58
58
|
);
|
|
@@ -61,11 +61,13 @@ const Row = ({ item, oneliner = 'main', layout = 'list' }) => {
|
|
|
61
61
|
Row.propTypes = {
|
|
62
62
|
oneliner: PropTypes.string,
|
|
63
63
|
layout: PropTypes.string,
|
|
64
|
+
tracker: PropTypes.string,
|
|
64
65
|
item: PropTypes.shape({
|
|
65
66
|
name: PropTypes.string,
|
|
66
67
|
logo_url: PropTypes.string,
|
|
67
68
|
selling_points: PropTypes.arrayOf(PropTypes.string),
|
|
68
69
|
review_link: PropTypes.string,
|
|
70
|
+
rating: PropTypes.string,
|
|
69
71
|
one_liners: PropTypes.shape({
|
|
70
72
|
main: PropTypes.shape({
|
|
71
73
|
one_liner: PropTypes.string,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/* eslint-disable arrow-body-style */
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
|
-
|
|
5
|
-
import Search from '~molecules/search';
|
|
4
|
+
import loadable from '@loadable/component';
|
|
6
5
|
import Card from '~atoms/cards/default-card';
|
|
7
6
|
import { translate } from '~helpers/getters';
|
|
8
7
|
|
|
9
8
|
const SearchContent = ({ page }) => {
|
|
9
|
+
const Search = loadable(() => import('~molecules/search'));
|
|
10
|
+
|
|
10
11
|
return (
|
|
11
12
|
<Search
|
|
12
13
|
pageSearchOptions={{
|
|
@@ -14,12 +14,11 @@ export function isMobileDevice() {
|
|
|
14
14
|
const isIos = () => Boolean(userAgent.match(/iPhone|iPad|iPod/i));
|
|
15
15
|
const isOpera = () => Boolean(userAgent.match(/Opera Mini/i));
|
|
16
16
|
const isWindows = () => Boolean(userAgent.match(/IEMobile/i));
|
|
17
|
-
const isIos13 = () =>
|
|
18
|
-
Boolean(
|
|
19
|
-
platform === 'MacIntel' &&
|
|
20
|
-
maxTouchPoints &&
|
|
21
|
-
maxTouchPoints === 5
|
|
22
|
-
);
|
|
17
|
+
const isIos13 = () => Boolean(platform === 'MacIntel' && maxTouchPoints && maxTouchPoints === 5);
|
|
23
18
|
|
|
24
19
|
return Boolean(isAndroid() || isIos() || isOpera() || isWindows() || isIos13());
|
|
25
20
|
}
|
|
21
|
+
|
|
22
|
+
export function isNativeImageLazyLoadingSupported() {
|
|
23
|
+
return typeof HTMLImageElement !== 'undefined' && 'loading' in HTMLImageElement.prototype;
|
|
24
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
/* eslint-disable import/prefer-default-export */
|
|
3
|
+
import { zeroPadding } from './schedule';
|
|
4
|
+
|
|
5
|
+
function isValidDate(d) {
|
|
6
|
+
return d instanceof Date && !Number.isNaN(d);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function convertTimeZone(event) {
|
|
10
|
+
if (!event || !event.date || !event.date.time) {
|
|
11
|
+
return event;
|
|
12
|
+
}
|
|
13
|
+
const timeArr = event.date.time.split(':');
|
|
14
|
+
|
|
15
|
+
// ecmascript has month ranges between 0 - 11, that's why we do -1 to month_number
|
|
16
|
+
const currentTimeZoneDate = new Date(
|
|
17
|
+
Date.UTC(
|
|
18
|
+
event.date.year_number,
|
|
19
|
+
zeroPadding(event.date.month_number - 1, 2),
|
|
20
|
+
zeroPadding(event.date.day_number, 2),
|
|
21
|
+
timeArr[0],
|
|
22
|
+
timeArr[1]
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (!isValidDate(currentTimeZoneDate)) return event;
|
|
27
|
+
|
|
28
|
+
const time = `${zeroPadding(currentTimeZoneDate.getHours(), 2)}:${zeroPadding(
|
|
29
|
+
currentTimeZoneDate.getMinutes(),
|
|
30
|
+
2
|
|
31
|
+
)}`;
|
|
32
|
+
|
|
33
|
+
// in case the utc is 23:00, but user's timezone can get 00:00 so update the date object.
|
|
34
|
+
const day_number = zeroPadding(currentTimeZoneDate.getDate(), 2);
|
|
35
|
+
const month_number = zeroPadding(currentTimeZoneDate.getMonth() + 1, 2);
|
|
36
|
+
const date = `${day_number}-${month_number}-${zeroPadding(currentTimeZoneDate.getFullYear(), 2)}`;
|
|
37
|
+
|
|
38
|
+
const dateAttrs = {
|
|
39
|
+
date: {
|
|
40
|
+
...event.date,
|
|
41
|
+
time,
|
|
42
|
+
month_number,
|
|
43
|
+
day_number,
|
|
44
|
+
date,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return { ...event, ...dateAttrs };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function updateAllTimezones(relation) {
|
|
52
|
+
const relationSchedule = relation?.schedule;
|
|
53
|
+
const relationFeaturedEvents = relation?.featured_events;
|
|
54
|
+
const relationShowcasedEvents = relation?.showcased_events;
|
|
55
|
+
|
|
56
|
+
// formated timezone schedule
|
|
57
|
+
const schedule = relationSchedule
|
|
58
|
+
? Object.keys(relationSchedule).reduce((acc, dateKey) => {
|
|
59
|
+
const { tournaments } = relationSchedule[dateKey] || {};
|
|
60
|
+
|
|
61
|
+
const formattedTournaments = Object.keys(tournaments).reduce(
|
|
62
|
+
(tournamentAcc, currentTournamentKey) => {
|
|
63
|
+
const league = tournaments[currentTournamentKey];
|
|
64
|
+
const formattedEvents = league.events.map((event) => convertTimeZone(event));
|
|
65
|
+
tournamentAcc[currentTournamentKey] = { ...league, events: formattedEvents };
|
|
66
|
+
return tournamentAcc;
|
|
67
|
+
},
|
|
68
|
+
{}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
acc[dateKey] = { ...relation.schedule[dateKey], tournaments: formattedTournaments };
|
|
72
|
+
return acc;
|
|
73
|
+
}, {})
|
|
74
|
+
: {};
|
|
75
|
+
|
|
76
|
+
// formated timezone featured events
|
|
77
|
+
const featured_events = relationFeaturedEvents?.map((event) => convertTimeZone(event)) || [];
|
|
78
|
+
|
|
79
|
+
// formated timezone showcased events
|
|
80
|
+
const showcased_events = relationShowcasedEvents?.map((event) => convertTimeZone(event)) || [];
|
|
81
|
+
|
|
82
|
+
// format timezone for relation.event
|
|
83
|
+
const event = convertTimeZone(relation?.event);
|
|
84
|
+
|
|
85
|
+
const updatedObject = { ...relation, schedule, featured_events, showcased_events };
|
|
86
|
+
if (event) {
|
|
87
|
+
updatedObject.event = event;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return updatedObject;
|
|
91
|
+
}
|
|
@@ -21,17 +21,25 @@ export function generateTrackerLink(operator, trackerType) {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export function
|
|
24
|
+
export function generateMetaString(metaString, translations, props) {
|
|
25
25
|
const date = new Date();
|
|
26
|
+
const day = date.getDate();
|
|
26
27
|
const month = months[date.getMonth()];
|
|
27
28
|
const year = date.getFullYear();
|
|
29
|
+
const regex =
|
|
30
|
+
/\[MONTH\]|\[YEAR\]|\[currentyear\]|\[sitename\]|\[currentmonth\]|\[title\]|\[currentdate\]/gi;
|
|
28
31
|
|
|
29
|
-
return
|
|
30
|
-
|
|
32
|
+
return metaString.replace(
|
|
33
|
+
regex,
|
|
31
34
|
(match) =>
|
|
32
35
|
({
|
|
33
36
|
'[MONTH]': (translations && translations[month]) || month,
|
|
34
37
|
'[YEAR]': year,
|
|
38
|
+
'[currentdate]': `${(translations && translations[month]) || month} ${day}, ${year}`,
|
|
39
|
+
'[currentmonth]': (translations && translations[month]) || month,
|
|
40
|
+
'[currentyear]': year,
|
|
41
|
+
'[sitename]': (props && props.siteName) || '',
|
|
42
|
+
'[title]': (props && props.siteTitle) || '',
|
|
35
43
|
}[match])
|
|
36
44
|
);
|
|
37
45
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { generateTrackerLink,
|
|
1
|
+
import { generateTrackerLink, generateMetaString } from './generators';
|
|
2
2
|
import { months } from '~constants/common';
|
|
3
3
|
|
|
4
4
|
describe('Generate Tracker Link Helper', () => {
|
|
@@ -17,24 +17,46 @@ describe('Generate Tracker Link Helper', () => {
|
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
describe('Generate Meta Title Helper', () => {
|
|
20
|
-
test('
|
|
21
|
-
const
|
|
20
|
+
test('generateMetaString uppercase', () => {
|
|
21
|
+
const metaString = generateMetaString('meta title [MONTH] [YEAR]');
|
|
22
22
|
const date = new Date();
|
|
23
|
-
|
|
24
|
-
expect(
|
|
25
|
-
expect(
|
|
26
|
-
expect(
|
|
23
|
+
|
|
24
|
+
expect(metaString).not.toContain('[MONTH]');
|
|
25
|
+
expect(metaString).not.toContain('[YEAR]');
|
|
26
|
+
expect(metaString).toContain(date.getFullYear());
|
|
27
|
+
expect(metaString).toContain(months[date.getMonth()]);
|
|
28
|
+
});
|
|
29
|
+
test('generateMetaString lowercase', () => {
|
|
30
|
+
const metaString = generateMetaString(
|
|
31
|
+
'meta title [currentdate] [currentmonth] [currentyear] [sitename] [title]',
|
|
32
|
+
null,
|
|
33
|
+
{
|
|
34
|
+
siteName: 'Site Name',
|
|
35
|
+
siteTitle: 'Site Title',
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
const date = new Date();
|
|
39
|
+
|
|
40
|
+
expect(metaString).not.toContain('[currentdate]');
|
|
41
|
+
expect(metaString).not.toContain('[currentmonth]');
|
|
42
|
+
expect(metaString).not.toContain('[currentyear]');
|
|
43
|
+
expect(metaString).not.toContain('[sitename]');
|
|
44
|
+
expect(metaString).not.toContain('[title]');
|
|
45
|
+
expect(metaString).toContain(date.getDate());
|
|
46
|
+
expect(metaString).toContain(months[date.getMonth()]);
|
|
47
|
+
expect(metaString).toContain(date.getFullYear());
|
|
48
|
+
expect(metaString).toContain('Site Name');
|
|
49
|
+
expect(metaString).toContain('Site Title');
|
|
27
50
|
});
|
|
28
|
-
test('
|
|
51
|
+
test('generateMetaString translated', () => {
|
|
29
52
|
const translateMonths = months.reduce(
|
|
30
53
|
(translated, month) => ({ ...translated, [month]: `translate${month.substring(0, 1)}` }),
|
|
31
54
|
{}
|
|
32
55
|
);
|
|
33
|
-
const
|
|
56
|
+
const metaString = generateMetaString('meta title [MONTH]', translateMonths);
|
|
34
57
|
const date = new Date();
|
|
35
58
|
|
|
36
|
-
expect(
|
|
37
|
-
expect(
|
|
38
|
-
expect(metaTitle).toContain(translateMonths[months[date.getMonth()]]);
|
|
59
|
+
expect(metaString).not.toContain('[MONTH]');
|
|
60
|
+
expect(metaString).toContain(translateMonths[months[date.getMonth()]]);
|
|
39
61
|
});
|
|
40
62
|
});
|
|
@@ -6,11 +6,9 @@ import {
|
|
|
6
6
|
filterEvents,
|
|
7
7
|
findTournaments,
|
|
8
8
|
getSortedEvents,
|
|
9
|
-
formatEvents,
|
|
10
9
|
} from '../schedule';
|
|
11
10
|
|
|
12
11
|
export function prepareSportsData(sportsData) {
|
|
13
|
-
sportsData.events = formatEvents(sportsData.events);
|
|
14
12
|
Object.keys(sportsData.tournaments).forEach((key) => {
|
|
15
13
|
if (sportsData.tournaments[key].events) {
|
|
16
14
|
sportsData.tournaments[key].events = filterEvents(
|
package/src/helpers/rating.js
CHANGED
package/src/helpers/schedule.js
CHANGED
|
@@ -120,39 +120,3 @@ export function filterEvents(tournamentEvents, events) {
|
|
|
120
120
|
|
|
121
121
|
return futureEvents;
|
|
122
122
|
}
|
|
123
|
-
|
|
124
|
-
export function changeEventHour(event, hour = 1) {
|
|
125
|
-
if (!event || !event.date || !event.date.time) {
|
|
126
|
-
return event;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const timeArr = event.date.time.split(':');
|
|
130
|
-
timeArr[0] = Number(timeArr[0]) - hour;
|
|
131
|
-
event.date.time = timeArr.join(':');
|
|
132
|
-
|
|
133
|
-
return event;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export function formatEvents(events) {
|
|
137
|
-
const eventsArr = Object.values(events);
|
|
138
|
-
const siteName = process.env.GATSBY_SITE_NAME;
|
|
139
|
-
let prefix = '0';
|
|
140
|
-
|
|
141
|
-
switch (siteName) {
|
|
142
|
-
case 'sefodbold.dk':
|
|
143
|
-
case 'sesport.dk':
|
|
144
|
-
case 'watchfooty.co.uk':
|
|
145
|
-
case 'bekijksport.nl':
|
|
146
|
-
case 'livestreamsvoetbal.nl':
|
|
147
|
-
prefix = 1;
|
|
148
|
-
break;
|
|
149
|
-
default:
|
|
150
|
-
prefix = 0;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return eventsArr.reduce((acc, current) => {
|
|
154
|
-
const event = changeEventHour(current, prefix);
|
|
155
|
-
acc[event.id] = event;
|
|
156
|
-
return acc;
|
|
157
|
-
}, {});
|
|
158
|
-
}
|
|
@@ -1,39 +1,29 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
3
|
-
// import LazyLoad from 'react-lazyload';
|
|
4
3
|
import PropTypes from 'prop-types';
|
|
4
|
+
import loadable from '@loadable/component';
|
|
5
|
+
import { isNativeImageLazyLoadingSupported } from '~helpers/device-detect';
|
|
5
6
|
|
|
6
|
-
// When to use this component:
|
|
7
|
-
// 1. If you have 1 image to lazyload
|
|
8
|
-
// 2. If you have images for different breakpoints and want the browser to decide when to serve the images based on the device, bandwidth, etc.
|
|
9
7
|
export default function LazyImage({
|
|
10
8
|
height,
|
|
11
9
|
width,
|
|
12
|
-
// offset = 200,
|
|
13
10
|
style = {},
|
|
14
11
|
className,
|
|
15
12
|
src = '#',
|
|
16
|
-
// srcSet = '',
|
|
17
13
|
alt = '',
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// once = false,
|
|
14
|
+
defaultImg,
|
|
15
|
+
loading = 'lazy',
|
|
21
16
|
}) {
|
|
22
|
-
|
|
17
|
+
const [errorImage, setErrorImage] = useState(false);
|
|
23
18
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
if ((defaultImg && !src) || errorImage === true) {
|
|
20
|
+
return defaultImg;
|
|
21
|
+
}
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
width={`${width}px`}
|
|
33
|
-
offset={offset}
|
|
34
|
-
debounce={0}
|
|
35
|
-
once={once}
|
|
36
|
-
>
|
|
23
|
+
if (!isNativeImageLazyLoadingSupported()) {
|
|
24
|
+
const LazyLoad = loadable(() => import(`react-lazyload`));
|
|
25
|
+
return (
|
|
26
|
+
<LazyLoad height={`${height}px`} width={`${width}px`} debounce={0}>
|
|
37
27
|
<img
|
|
38
28
|
src={src}
|
|
39
29
|
className={className}
|
|
@@ -41,36 +31,32 @@ export default function LazyImage({
|
|
|
41
31
|
width={width}
|
|
42
32
|
alt={alt}
|
|
43
33
|
style={style}
|
|
44
|
-
srcSet={srcSet}
|
|
45
|
-
sizes={sizes}
|
|
46
|
-
onError={() => setErrorImage(true)}
|
|
47
34
|
/>
|
|
48
|
-
</LazyLoad>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
{
|
|
60
|
-
|
|
35
|
+
</LazyLoad>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<img
|
|
41
|
+
src={src}
|
|
42
|
+
loading={loading}
|
|
43
|
+
className={className}
|
|
44
|
+
height={height}
|
|
45
|
+
width={width}
|
|
46
|
+
alt={alt}
|
|
47
|
+
style={style}
|
|
48
|
+
onError={() => setErrorImage(true)}
|
|
49
|
+
/>
|
|
61
50
|
);
|
|
62
51
|
}
|
|
63
52
|
|
|
64
53
|
LazyImage.propTypes = {
|
|
65
54
|
width: PropTypes.number,
|
|
66
55
|
height: PropTypes.number,
|
|
67
|
-
// offset: PropTypes.number,
|
|
68
56
|
style: PropTypes.shape({}),
|
|
69
57
|
className: PropTypes.string,
|
|
70
58
|
src: PropTypes.string,
|
|
71
59
|
alt: PropTypes.string,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
// defaultImg: PropTypes.element,
|
|
75
|
-
// once: PropTypes.bool,
|
|
60
|
+
defaultImg: PropTypes.element,
|
|
61
|
+
loading: PropTypes.string,
|
|
76
62
|
};
|
package/src/hooks/tabs/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { forceCheck } from 'react-lazyload';
|
|
4
|
-
import
|
|
4
|
+
import loadable from '@loadable/component';
|
|
5
5
|
import styles from './tabs.module.scss';
|
|
6
6
|
|
|
7
7
|
const Tabs = ({
|
|
@@ -19,6 +19,8 @@ const Tabs = ({
|
|
|
19
19
|
showAll ? showAllTabId : `${children[0].props.label}_0`
|
|
20
20
|
);
|
|
21
21
|
|
|
22
|
+
const TabList = showTabs ? loadable(() => import('./tab/tab-list')) : null;
|
|
23
|
+
|
|
22
24
|
const tabHeaderClass = `${styles.tabsHeader} ${!HeaderComp && styles.tabsOnly} ${
|
|
23
25
|
styles[headerClass]
|
|
24
26
|
} ${tabsAlign === 'right' && styles.invertOrder}`;
|
|
@@ -31,7 +33,7 @@ const Tabs = ({
|
|
|
31
33
|
return (
|
|
32
34
|
<>
|
|
33
35
|
<div className={tabHeaderClass}>
|
|
34
|
-
{
|
|
36
|
+
{TabList && (
|
|
35
37
|
<TabList
|
|
36
38
|
onClick={onClickTabItem}
|
|
37
39
|
items={children}
|