gatsby-core-theme 44.30.1 → 44.30.3
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 +14 -0
- package/package.json +1 -1
- package/src/components/atoms/notifications/notification-items/bonuses/bonuses.test.js +8 -5
- package/src/components/atoms/notifications/notification-items/bonuses/index.js +62 -15
- package/src/components/atoms/notifications/notification-items/cards-v2/index.js +22 -13
- package/src/components/atoms/notifications/notification-items/spotlight/index.js +25 -13
- package/src/components/atoms/notifications/notifications.module.scss +31 -1
- package/src/helpers/date-time.js +8 -0
- package/src/helpers/date-time.test.js +8 -1
- package/src/images/icons/check-circle.js +1 -1
- package/src/resolver/modules.mjs +42 -2
- package/src/resolver/modules.test.js +40 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [44.30.3](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.30.2...v44.30.3) (2026-06-25)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* add variable for height of bonus code button ([f147e4d](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/f147e4d70100a3fc9cd55e1e497cfdff7dd1f629))
|
|
7
|
+
|
|
8
|
+
## [44.30.2](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.30.1...v44.30.2) (2026-06-24)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* fixes for notification panel ([80c7649](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/80c7649bb5650317b017c336b3b9653fa52a1042))
|
|
14
|
+
|
|
1
15
|
## [44.30.1](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.30.0...v44.30.1) (2026-06-22)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
2
|
+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
3
3
|
import '@testing-library/jest-dom/extend-expect';
|
|
4
4
|
import { getListToplistItem } from '~tests/factories/modules/toplist.factory';
|
|
5
5
|
import BonusesItems from '.';
|
|
@@ -25,7 +25,7 @@ const buildToplist = (overrides = {}) => ({
|
|
|
25
25
|
describe('BonusesItems', () => {
|
|
26
26
|
beforeEach(() => {
|
|
27
27
|
Object.assign(navigator, {
|
|
28
|
-
clipboard: { writeText: jest.fn() },
|
|
28
|
+
clipboard: { writeText: jest.fn().mockResolvedValue(undefined) },
|
|
29
29
|
});
|
|
30
30
|
});
|
|
31
31
|
|
|
@@ -34,7 +34,7 @@ describe('BonusesItems', () => {
|
|
|
34
34
|
expect(screen.getByText('No new items')).toBeVisible();
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
test('renders bonus item with promo code and copies on click', () => {
|
|
37
|
+
test('renders bonus item with promo code and copies on click', async () => {
|
|
38
38
|
const toplist = buildToplist();
|
|
39
39
|
const { container } = render(<BonusesItems toplist={toplist} showUnread />);
|
|
40
40
|
|
|
@@ -44,7 +44,10 @@ describe('BonusesItems', () => {
|
|
|
44
44
|
expect(screen.getByText('BONUS123')).toBeVisible();
|
|
45
45
|
|
|
46
46
|
fireEvent.click(screen.getByText('BONUS123'));
|
|
47
|
-
|
|
47
|
+
await waitFor(() => {
|
|
48
|
+
expect(navigator.clipboard.writeText).toHaveBeenCalledWith('BONUS123');
|
|
49
|
+
expect(screen.getByText('CODE COPIED')).toBeVisible();
|
|
50
|
+
});
|
|
48
51
|
});
|
|
49
52
|
|
|
50
53
|
test('renders bonus item without promo code row', () => {
|
|
@@ -60,4 +63,4 @@ describe('BonusesItems', () => {
|
|
|
60
63
|
expect(container.querySelector('.bonusCodeRow')).toBeFalsy();
|
|
61
64
|
expect(screen.getByText('name1 Review')).toBeVisible();
|
|
62
65
|
});
|
|
63
|
-
});
|
|
66
|
+
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useState } from "react";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import { FaArrowRight } from "@react-icons/all-files/fa/FaArrowRight";
|
|
4
4
|
import CopyIcon from "~images/icons/copyIcon";
|
|
5
|
+
import CheckCircleIcon from "~images/icons/check-circle";
|
|
5
6
|
import LazyImage from "~hooks/lazy-image";
|
|
6
7
|
import PrettyLink from "~atoms/pretty-link";
|
|
7
8
|
import ReviewLink from "~atoms/review-link";
|
|
@@ -14,7 +15,7 @@ import {
|
|
|
14
15
|
imagePrettyUrl,
|
|
15
16
|
} from "~helpers/getters";
|
|
16
17
|
import { getAltText } from "~helpers/image";
|
|
17
|
-
import { getTimeAgo } from "~helpers/date-time";
|
|
18
|
+
import { getTimeAgo, parseSortableDate } from "~helpers/date-time";
|
|
18
19
|
import { TrackingKeys } from "~constants/tracking-api";
|
|
19
20
|
import VerifiedBadgeIcon from "~images/icons/verifiedBadgeIcon";
|
|
20
21
|
import useTranslate from "~hooks/useTranslate/useTranslate";
|
|
@@ -29,6 +30,7 @@ const BonusItem = ({
|
|
|
29
30
|
updatedLabel,
|
|
30
31
|
hideBadges
|
|
31
32
|
}) => {
|
|
33
|
+
const [copySuccess, setCopySuccess] = useState(false);
|
|
32
34
|
const bonus = getBonusData(item, tracker);
|
|
33
35
|
const oneliner = [bonus?.mainLine, bonus?.secondLine]
|
|
34
36
|
.filter(Boolean)
|
|
@@ -37,14 +39,21 @@ const BonusItem = ({
|
|
|
37
39
|
const reviewPath = item.review_link
|
|
38
40
|
? `/${item.review_link}`
|
|
39
41
|
: item.path || null;
|
|
40
|
-
const timeData = getTimeAgo(item.updated_at)
|
|
42
|
+
const timeData = item.updated_at ? getTimeAgo(item.updated_at) : null;
|
|
41
43
|
const timeKeyLabel = useTranslate(
|
|
42
|
-
timeData
|
|
43
|
-
timeData
|
|
44
|
+
timeData?.key,
|
|
45
|
+
timeData?.key?.replace(/_/g, " ")
|
|
44
46
|
);
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
const foundedYear = item?.founded?.substring(0, 4);
|
|
48
|
+
let timeAgo = "";
|
|
49
|
+
|
|
50
|
+
if (timeData?.value) {
|
|
51
|
+
timeAgo = `${updatedLabel} ${timeData.value} ${timeKeyLabel}`;
|
|
52
|
+
} else if (foundedYear) {
|
|
53
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
54
|
+
timeAgo = `${useTranslate("founded", "Founded")} ${foundedYear}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
48
57
|
const hasTnc = Boolean(getOperatorTnc(item, tracker));
|
|
49
58
|
|
|
50
59
|
const verifiedMonth = new Intl.DateTimeFormat("en-US", {
|
|
@@ -55,6 +64,20 @@ const BonusItem = ({
|
|
|
55
64
|
"notification_verified_in",
|
|
56
65
|
"Verified in [month]"
|
|
57
66
|
).replace("[month]", verifiedMonth);
|
|
67
|
+
const codeCopiedLabel = useTranslate("code_copied", "CODE COPIED");
|
|
68
|
+
const isBet365 = item.short_name === "bet365";
|
|
69
|
+
|
|
70
|
+
const copyToClipBoard = async (e, copyMe) => {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
e.stopPropagation();
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
await navigator.clipboard.writeText(copyMe);
|
|
76
|
+
setCopySuccess(true);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
setCopySuccess(false);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
58
81
|
|
|
59
82
|
return (
|
|
60
83
|
<li className={styles.bonusItem}>
|
|
@@ -72,7 +95,7 @@ const BonusItem = ({
|
|
|
72
95
|
width={52}
|
|
73
96
|
height={52}
|
|
74
97
|
alt={getAltText(item.logo, item.name)}
|
|
75
|
-
src={imagePrettyUrl(item.logo?.filename
|
|
98
|
+
src={imagePrettyUrl(item.logo?.filename)}
|
|
76
99
|
/>
|
|
77
100
|
</PrettyLink>
|
|
78
101
|
|
|
@@ -83,11 +106,30 @@ const BonusItem = ({
|
|
|
83
106
|
<span className={styles.bonusCodeLabel}>{bonusCodeLabel}</span>
|
|
84
107
|
<button
|
|
85
108
|
type="button"
|
|
86
|
-
className={styles.bonusCode}
|
|
87
|
-
onClick={() =>
|
|
109
|
+
className={`${styles.bonusCode} ${copySuccess ? styles.bonusCodeCopied : ""}`}
|
|
110
|
+
onClick={(e) =>
|
|
111
|
+
promoCode && !isBet365 ? copyToClipBoard(e, promoCode) : undefined
|
|
112
|
+
}
|
|
113
|
+
disabled={isBet365}
|
|
88
114
|
>
|
|
89
|
-
|
|
90
|
-
|
|
115
|
+
{!copySuccess ? (
|
|
116
|
+
<>
|
|
117
|
+
<span>{promoCode}</span>
|
|
118
|
+
{!isBet365 && <CopyIcon width={20} height={20} />}
|
|
119
|
+
</>
|
|
120
|
+
) : (
|
|
121
|
+
<>
|
|
122
|
+
<span>{codeCopiedLabel}</span>
|
|
123
|
+
<span className={styles.bonusCodeCheckIcon}>
|
|
124
|
+
<CheckCircleIcon
|
|
125
|
+
width={20}
|
|
126
|
+
height={20}
|
|
127
|
+
bgColor="var(--notification-bonus-code-border, #20cd77)"
|
|
128
|
+
color="#fff"
|
|
129
|
+
/>
|
|
130
|
+
</span>
|
|
131
|
+
</>
|
|
132
|
+
)}
|
|
91
133
|
</button>
|
|
92
134
|
</div>
|
|
93
135
|
)}
|
|
@@ -138,6 +180,7 @@ BonusItem.propTypes = {
|
|
|
138
180
|
updated_at: PropTypes.string,
|
|
139
181
|
short_name: PropTypes.string,
|
|
140
182
|
name: PropTypes.string,
|
|
183
|
+
founded: PropTypes.string,
|
|
141
184
|
logo: PropTypes.shape({
|
|
142
185
|
filename: PropTypes.string,
|
|
143
186
|
}),
|
|
@@ -151,7 +194,11 @@ BonusItem.propTypes = {
|
|
|
151
194
|
};
|
|
152
195
|
|
|
153
196
|
const BonusesItems = ({ toplist, showUnread, hideBadges }) => {
|
|
154
|
-
const items = toplist?.items || []
|
|
197
|
+
const items = [...(toplist?.items || [])].sort(
|
|
198
|
+
(a, b) =>
|
|
199
|
+
parseSortableDate(b.updated_at || b.founded) -
|
|
200
|
+
parseSortableDate(a.updated_at || a.founded)
|
|
201
|
+
);
|
|
155
202
|
const tracker =
|
|
156
203
|
toplist?.toplist_bonus || toplist?.one_liner || toplist?.tracker || "main";
|
|
157
204
|
const noBonuses = useTranslate("noNewUpdates", "No new items");
|
|
@@ -189,4 +236,4 @@ BonusesItems.propTypes = {
|
|
|
189
236
|
hideBadges: PropTypes.bool
|
|
190
237
|
};
|
|
191
238
|
|
|
192
|
-
export default BonusesItems;
|
|
239
|
+
export default BonusesItems;
|
|
@@ -13,9 +13,17 @@ import {
|
|
|
13
13
|
import { getAltText, getImageFilename } from "~helpers/image";
|
|
14
14
|
import ArticleIcon from "../../../../../images/icons/articleIcon";
|
|
15
15
|
import useTranslate from "~hooks/useTranslate/useTranslate";
|
|
16
|
-
import { getTimeAgo } from "~helpers/date-time";
|
|
16
|
+
import { getTimeAgo, parseSortableDate } from "~helpers/date-time";
|
|
17
17
|
import styles from "./notification-items.module.scss";
|
|
18
18
|
|
|
19
|
+
const getTrendingSortDate = (item) =>
|
|
20
|
+
parseSortableDate(
|
|
21
|
+
item?.manual_updated_date ||
|
|
22
|
+
item?.updated_at ||
|
|
23
|
+
item?.manual_published_date ||
|
|
24
|
+
item?.created_at
|
|
25
|
+
);
|
|
26
|
+
|
|
19
27
|
const CategoryTag = ({ category }) => {
|
|
20
28
|
const label = useTranslate(
|
|
21
29
|
`category_${category.short_name}`,
|
|
@@ -28,9 +36,10 @@ const CategoryTag = ({ category }) => {
|
|
|
28
36
|
};
|
|
29
37
|
|
|
30
38
|
const CardsItems = ({ module, showUnread = false }) => {
|
|
31
|
-
const
|
|
39
|
+
const items = [...(module?.items || [])].sort(
|
|
40
|
+
(a, b) => getTrendingSortDate(b) - getTrendingSortDate(a)
|
|
41
|
+
);
|
|
32
42
|
const noNewUpdates = useTranslate("noNewUpdates", "No new items");
|
|
33
|
-
const updatedLabel = useTranslate("updated", "Updated");
|
|
34
43
|
|
|
35
44
|
const renderItem = (item) => {
|
|
36
45
|
const isArticleOrPage = ["article", "page"].includes(item?.relation_type);
|
|
@@ -46,20 +55,20 @@ const CardsItems = ({ module, showUnread = false }) => {
|
|
|
46
55
|
const categories = item?.categories || [];
|
|
47
56
|
const description =
|
|
48
57
|
subtitle || item?.short_description || item?.description || "";
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
const dateModified = item?.manual_updated_date || item?.updated_at;
|
|
59
|
+
const datePublished = item?.manual_published_date || item?.created_at;
|
|
60
|
+
const dateString = dateModified || datePublished;
|
|
61
|
+
const usePublishedLabel = !dateModified && Boolean(datePublished);
|
|
62
|
+
const timeData = dateString ? getTimeAgo(dateString) : null;
|
|
63
|
+
const timeAgo = timeData?.value
|
|
64
|
+
? `${useTranslate(
|
|
65
|
+
usePublishedLabel ? "published" : "updated",
|
|
66
|
+
usePublishedLabel ? "Published" : "Updated"
|
|
67
|
+
)} ${timeData.value} ${useTranslate(
|
|
58
68
|
timeData.key,
|
|
59
69
|
timeData.key?.replace(/_/g, " ")
|
|
60
70
|
)}`
|
|
61
71
|
: "";
|
|
62
|
-
|
|
63
72
|
const thumbnail = img ? (
|
|
64
73
|
<LazyImage
|
|
65
74
|
width={40}
|
|
@@ -9,13 +9,22 @@ import LazyImage from "~hooks/lazy-image";
|
|
|
9
9
|
import keygen from "~helpers/keygen";
|
|
10
10
|
import Link from "~hooks/link";
|
|
11
11
|
import useTranslate from "~hooks/useTranslate/useTranslate";
|
|
12
|
-
import { getTimeAgo } from "~helpers/date-time";
|
|
12
|
+
import { getTimeAgo, parseSortableDate } from "~helpers/date-time";
|
|
13
13
|
import styles from "../cards-v2/notification-items.module.scss";
|
|
14
14
|
|
|
15
|
+
const getTrendingSortDate = (item) =>
|
|
16
|
+
parseSortableDate(
|
|
17
|
+
item?.manual_updated_date ||
|
|
18
|
+
item?.updated_at ||
|
|
19
|
+
item?.manual_published_date ||
|
|
20
|
+
item?.created_at
|
|
21
|
+
);
|
|
22
|
+
|
|
15
23
|
const SpotlightItems = ({ module, showUnread = false }) => {
|
|
16
|
-
const
|
|
24
|
+
const items = [...(module?.items || [])].sort(
|
|
25
|
+
(a, b) => getTrendingSortDate(b) - getTrendingSortDate(a)
|
|
26
|
+
);
|
|
17
27
|
const noNewUpdates = useTranslate("noNewUpdates", "No new items");
|
|
18
|
-
const updatedLabel = useTranslate("updated", "Updated");
|
|
19
28
|
|
|
20
29
|
const renderItem = (item) => {
|
|
21
30
|
const img = item?.image;
|
|
@@ -25,21 +34,24 @@ const SpotlightItems = ({ module, showUnread = false }) => {
|
|
|
25
34
|
const ribbon = item?.subtitle?.split(",")[0]?.replace("[null]", "")?.trim();
|
|
26
35
|
const metaText = item?.subtitle?.split(",").slice(1).join(",").trim();
|
|
27
36
|
const description = item?.short_description || item?.text || "";
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
const dateModified = item?.manual_updated_date || item?.updated_at;
|
|
38
|
+
const datePublished = item?.manual_published_date || item?.created_at;
|
|
39
|
+
const dateString = dateModified || datePublished;
|
|
40
|
+
const usePublishedLabel = !dateModified && Boolean(datePublished);
|
|
41
|
+
const timeData = dateString ? getTimeAgo(dateString) : null;
|
|
33
42
|
const timeKeyLabel = useTranslate(
|
|
34
|
-
timeData
|
|
35
|
-
timeData
|
|
43
|
+
timeData?.key,
|
|
44
|
+
timeData?.key?.replace(/_/g, " ")
|
|
36
45
|
);
|
|
37
46
|
let timeAgo = "";
|
|
38
47
|
|
|
39
|
-
if (timeData
|
|
40
|
-
timeAgo = `${
|
|
48
|
+
if (timeData?.value) {
|
|
49
|
+
timeAgo = `${useTranslate(
|
|
50
|
+
usePublishedLabel ? "published" : "updated",
|
|
51
|
+
usePublishedLabel ? "Published" : "Updated"
|
|
52
|
+
)} ${timeData.value} ${timeKeyLabel}`;
|
|
41
53
|
} else if (metaText) {
|
|
42
|
-
timeAgo = `${
|
|
54
|
+
timeAgo = `${useTranslate("updated", "Updated")} ${metaText}`;
|
|
43
55
|
}
|
|
44
56
|
|
|
45
57
|
return (
|
|
@@ -116,6 +116,7 @@
|
|
|
116
116
|
gap: 0.8rem;
|
|
117
117
|
padding: 0 0 0.8rem;
|
|
118
118
|
border-bottom: 1px solid var(--notification-item-border, #e3e6ef);
|
|
119
|
+
cursor: default;
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
.unreadDot {
|
|
@@ -135,6 +136,7 @@
|
|
|
135
136
|
gap: 0.8rem;
|
|
136
137
|
width: 100%;
|
|
137
138
|
min-height: 5.2rem;
|
|
139
|
+
cursor: default;
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
.logo {
|
|
@@ -145,6 +147,7 @@
|
|
|
145
147
|
height: 5.2rem;
|
|
146
148
|
border: 1px solid var(--notification-logo-border, #dedede);
|
|
147
149
|
border-radius: var(--notification-logo-border-radius, 0.8rem);
|
|
150
|
+
cursor: default;
|
|
148
151
|
|
|
149
152
|
img {
|
|
150
153
|
display: block;
|
|
@@ -154,6 +157,7 @@
|
|
|
154
157
|
}
|
|
155
158
|
}
|
|
156
159
|
|
|
160
|
+
|
|
157
161
|
.bonusText {
|
|
158
162
|
@include flex-direction(column);
|
|
159
163
|
@include flex-align(flex-start, center);
|
|
@@ -162,6 +166,7 @@
|
|
|
162
166
|
min-width: 0;
|
|
163
167
|
gap: 0.4rem;
|
|
164
168
|
padding-right: 2.4rem;
|
|
169
|
+
cursor: default;
|
|
165
170
|
}
|
|
166
171
|
|
|
167
172
|
.oneliner {
|
|
@@ -170,6 +175,7 @@
|
|
|
170
175
|
font-weight: 700;
|
|
171
176
|
line-height: 2.2rem;
|
|
172
177
|
color: var(--notification-oneliner-color, #1b1b1c);
|
|
178
|
+
cursor: default;
|
|
173
179
|
}
|
|
174
180
|
|
|
175
181
|
.bonusCodeRow {
|
|
@@ -190,7 +196,7 @@
|
|
|
190
196
|
@include flex-align(center, center);
|
|
191
197
|
|
|
192
198
|
gap: 0.6rem;
|
|
193
|
-
height: 2.4rem;
|
|
199
|
+
height: var(--notification-bonus-code-height, 2.4rem);
|
|
194
200
|
padding: 0 0.8rem;
|
|
195
201
|
border: 1px var(--notification-bonus-code-border-style, dashed)
|
|
196
202
|
var(--notification-bonus-code-border, #20cd77);
|
|
@@ -211,15 +217,36 @@
|
|
|
211
217
|
|
|
212
218
|
svg {
|
|
213
219
|
flex-shrink: 0;
|
|
220
|
+
pointer-events: none;
|
|
214
221
|
color: var(--notification-bonus-code-icon, #262629);
|
|
215
222
|
}
|
|
216
223
|
}
|
|
217
224
|
|
|
225
|
+
.bonusCodeCopied {
|
|
226
|
+
border-color: var(--notification-bonus-code-border, #20cd77);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.bonusCodeCheckIcon {
|
|
230
|
+
@include flex-align(center, center);
|
|
231
|
+
|
|
232
|
+
flex-shrink: 0;
|
|
233
|
+
width: 2rem;
|
|
234
|
+
height: 2rem;
|
|
235
|
+
pointer-events: none;
|
|
236
|
+
|
|
237
|
+
svg {
|
|
238
|
+
display: block;
|
|
239
|
+
width: 2rem;
|
|
240
|
+
height: 2rem;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
218
244
|
.meta {
|
|
219
245
|
@include flex-align(center, flex-start);
|
|
220
246
|
|
|
221
247
|
width: 100%;
|
|
222
248
|
min-height: 1.8rem;
|
|
249
|
+
cursor: default;
|
|
223
250
|
}
|
|
224
251
|
|
|
225
252
|
.reviewLink {
|
|
@@ -230,6 +257,7 @@
|
|
|
230
257
|
line-height: 1.8rem;
|
|
231
258
|
color: var(--notification-link-color, #165af8);
|
|
232
259
|
text-decoration: underline;
|
|
260
|
+
cursor: pointer;
|
|
233
261
|
}
|
|
234
262
|
|
|
235
263
|
.updated {
|
|
@@ -241,6 +269,7 @@
|
|
|
241
269
|
color: var(--notification-meta-color, #515156);
|
|
242
270
|
text-align: right;
|
|
243
271
|
white-space: nowrap;
|
|
272
|
+
cursor: default;
|
|
244
273
|
}
|
|
245
274
|
|
|
246
275
|
.cta {
|
|
@@ -254,6 +283,7 @@
|
|
|
254
283
|
background: var(--notification-cta-bg, #6e33e5);
|
|
255
284
|
color: var(--notification-cta-color, #fff);
|
|
256
285
|
text-decoration: none;
|
|
286
|
+
cursor: default;
|
|
257
287
|
|
|
258
288
|
&:hover {
|
|
259
289
|
background: var(--notification-cta-hover-bg, #5a28c7);
|
package/src/helpers/date-time.js
CHANGED
|
@@ -52,3 +52,11 @@ export const getTimeAgo = (dateString) => {
|
|
|
52
52
|
}
|
|
53
53
|
return { value: diffMinutes, key: diffMinutes === 1 ? "minute_ago" : "minutes_ago" };
|
|
54
54
|
};
|
|
55
|
+
|
|
56
|
+
export const parseSortableDate = (dateString) => {
|
|
57
|
+
if (!dateString) return 0;
|
|
58
|
+
|
|
59
|
+
const time = Date.parse(String(dateString).replace(" ", "T"));
|
|
60
|
+
|
|
61
|
+
return Number.isNaN(time) ? 0 : time;
|
|
62
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { formatDate, getTimeAgo } from './date-time';
|
|
1
|
+
import { formatDate, getTimeAgo, parseSortableDate } from './date-time';
|
|
2
2
|
|
|
3
3
|
describe('Date-Time Helper', () => {
|
|
4
4
|
test('formatDate()', () => {
|
|
@@ -22,4 +22,11 @@ describe('Date-Time Helper', () => {
|
|
|
22
22
|
expect(getTimeAgo(daysAgo)).toMatchObject({ key: 'days_ago', value: 10 });
|
|
23
23
|
expect(getTimeAgo(monthsAgo)).toMatchObject({ key: 'months_ago', value: 2 });
|
|
24
24
|
});
|
|
25
|
+
|
|
26
|
+
test('parseSortableDate()', () => {
|
|
27
|
+
expect(parseSortableDate(null)).toBe(0);
|
|
28
|
+
expect(parseSortableDate('2025-06-01 10:00:00')).toBeGreaterThan(
|
|
29
|
+
parseSortableDate('2024-01-01 10:00:00')
|
|
30
|
+
);
|
|
31
|
+
});
|
|
25
32
|
});
|
|
@@ -6,7 +6,7 @@ export default function CheckCircleIcon({ width = 24, height = 24, color = '#272
|
|
|
6
6
|
<svg
|
|
7
7
|
width={width}
|
|
8
8
|
height={height}
|
|
9
|
-
viewBox=
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
10
|
fill="none"
|
|
11
11
|
aria-labelledby="checkCircleIcon"
|
|
12
12
|
xmlns="http://www.w3.org/2000/svg"
|
package/src/resolver/modules.mjs
CHANGED
|
@@ -520,6 +520,35 @@ export function shouldSavePrefilled(module = {}, siteName) {
|
|
|
520
520
|
);
|
|
521
521
|
}
|
|
522
522
|
|
|
523
|
+
function normalizePathForMatch(path) {
|
|
524
|
+
if (!path || typeof path !== "string") return "";
|
|
525
|
+
return path.replace(/^\/+|\/+$/g, "");
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
function getSpotlightLinkedPage(link, pagesMappedById = {}) {
|
|
529
|
+
if (!link || link.type !== "page") return null;
|
|
530
|
+
|
|
531
|
+
if (link.page_id && pagesMappedById[link.page_id]) {
|
|
532
|
+
return pagesMappedById[link.page_id];
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const linkValue = link.value;
|
|
536
|
+
if (!linkValue) return null;
|
|
537
|
+
|
|
538
|
+
if (pagesMappedById[linkValue]) {
|
|
539
|
+
return pagesMappedById[linkValue];
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
const linkPath = normalizePathForMatch(linkValue);
|
|
543
|
+
if (!linkPath) return null;
|
|
544
|
+
|
|
545
|
+
return (
|
|
546
|
+
Object.values(pagesMappedById).find(
|
|
547
|
+
(page) => normalizePathForMatch(page?.path) === linkPath
|
|
548
|
+
) || null
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
|
|
523
552
|
export function processSpotlightModule(module = {}, content, relations, ribbons, previewPageID, translations, relationData, operators, games,
|
|
524
553
|
pagesMappedById = {}
|
|
525
554
|
) {
|
|
@@ -543,11 +572,22 @@ export function processSpotlightModule(module = {}, content, relations, ribbons,
|
|
|
543
572
|
games
|
|
544
573
|
);
|
|
545
574
|
|
|
546
|
-
const
|
|
547
|
-
const linkedPage = pageId ? pagesMappedById[pageId] : null;
|
|
575
|
+
const linkedPage = getSpotlightLinkedPage(item?.link, pagesMappedById);
|
|
548
576
|
if (linkedPage?.short_description) {
|
|
549
577
|
item.short_description = linkedPage.short_description;
|
|
550
578
|
}
|
|
579
|
+
if (linkedPage?.updated_at) {
|
|
580
|
+
item.updated_at = linkedPage.updated_at;
|
|
581
|
+
}
|
|
582
|
+
if (linkedPage?.manual_updated_date) {
|
|
583
|
+
item.manual_updated_date = linkedPage.manual_updated_date;
|
|
584
|
+
}
|
|
585
|
+
if (linkedPage?.created_at) {
|
|
586
|
+
item.created_at = linkedPage.created_at;
|
|
587
|
+
}
|
|
588
|
+
if (linkedPage?.manual_published_date) {
|
|
589
|
+
item.manual_published_date = linkedPage.manual_published_date;
|
|
590
|
+
}
|
|
551
591
|
});
|
|
552
592
|
}
|
|
553
593
|
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
shouldSavePrefilled,
|
|
12
12
|
processContentModule,
|
|
13
13
|
processAnchor,
|
|
14
|
+
processSpotlightModule,
|
|
14
15
|
} from "./modules.mjs";
|
|
15
16
|
import { objectsHolder } from "~tests/factories/modules/modules.factory";
|
|
16
17
|
import getPageDataList from "~tests/factories/pages/list.factory";
|
|
@@ -391,4 +392,43 @@ expect(module.value.ribbons[0]).toBe("testRibbon");
|
|
|
391
392
|
|
|
392
393
|
expect(prefilledModule.items).toHaveLength(3);
|
|
393
394
|
});
|
|
395
|
+
|
|
396
|
+
test("Spotlights resolve linked page by path when page_id is missing", () => {
|
|
397
|
+
const linkedPage = {
|
|
398
|
+
...getPageData(),
|
|
399
|
+
id: 123,
|
|
400
|
+
path: "casino-bonus/irishlucks-exclusive-bonuses-vault",
|
|
401
|
+
updated_at: "2024-06-10 12:00:00",
|
|
402
|
+
short_description: "Linked page description",
|
|
403
|
+
};
|
|
404
|
+
const module = {
|
|
405
|
+
mode: "image_text",
|
|
406
|
+
items: [
|
|
407
|
+
{
|
|
408
|
+
label: "Bonus Club",
|
|
409
|
+
text: "<p>Join now!</p>",
|
|
410
|
+
link: {
|
|
411
|
+
type: "page",
|
|
412
|
+
value: "/casino-bonus/irishlucks-exclusive-bonuses-vault",
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
processSpotlightModule(
|
|
419
|
+
module,
|
|
420
|
+
{},
|
|
421
|
+
{},
|
|
422
|
+
{},
|
|
423
|
+
null,
|
|
424
|
+
{},
|
|
425
|
+
{},
|
|
426
|
+
{},
|
|
427
|
+
{},
|
|
428
|
+
{ 123: linkedPage }
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
expect(module.items[0].short_description).toBe("Linked page description");
|
|
432
|
+
expect(module.items[0].updated_at).toBe("2024-06-10 12:00:00");
|
|
433
|
+
});
|
|
394
434
|
});
|