gatsby-core-theme 44.15.0 → 44.15.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 +36 -0
- package/gatsby-node.mjs +44 -6
- package/package.json +1 -1
- package/src/components/organisms/navigation/index.js +4 -2
- package/src/constants/generators.mjs +2 -1
- package/src/constants/pick-keys.mjs +4 -1
- package/src/helpers/generators.mjs +23 -7
- package/src/helpers/tracker.mjs +20 -3
- package/src/helpers/tracker.test.js +161 -0
- package/src/hooks/modal/modal-content.js +19 -34
- package/src/resolver/index.mjs +15 -7
- package/src/resolver/modules.mjs +43 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
## [44.15.2](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.15.1...v44.15.2) (2026-02-26)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* add jackpot on pick keys for games ([ad29abd](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/ad29abdb66c06d33d4ea0c2dc8a2d1dcc24c592e))
|
|
7
|
+
* block crawling for develop environment ([ca986f6](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/ca986f649be3f90dac3b4bdc181415e5aa05bf56))
|
|
8
|
+
* clean data for pages that contain archive module ([3a2aaf0](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/3a2aaf005042d1a1c1649fa286b86fc1fc5a6a86))
|
|
9
|
+
* update isMeutimao constant ([b888337](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/b888337b2530e90e5a12eb1e8feccf26115c4164))
|
|
10
|
+
* update logic on gatsby node to have all the operators ([39f07ed](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/39f07edacac4c57b813d689b144a17ebba9a5c64))
|
|
11
|
+
* update module introduction to accept short codes ([acdf3df](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/acdf3dfa9325c63a230a92a9f9037b8d1adde68f))
|
|
12
|
+
* update modules function ([5851809](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/58518099f23e1774da43de91c38e8f384b47d562))
|
|
13
|
+
* update name ([a36746a](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/a36746a5f06d49217bef0bf3900ac461ded8d640))
|
|
14
|
+
* update regex and naming ([f0f08b5](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/f0f08b5e80b94865d2fdfb717212cc1f596c55a1))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
* Merge branch 'en-221-update-logic-modules' into 'master' ([b888646](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/b88864634144e41667d8da50bf9d3bc964114e07))
|
|
18
|
+
* Merge branch 'en-330-jackpot-data' into 'master' ([dff9e12](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/dff9e12a7242c7ef1768109ba55ab81f7f62903a))
|
|
19
|
+
* Merge branch 'EN-371' into 'master' ([537296e](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/537296e0ff9db0aa02d3c75575e45d6056d86474))
|
|
20
|
+
* Merge branch 'EN-359' into 'master' ([0f6f3e3](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/0f6f3e307e1f5c007b73be2b4eb8f8aedfa3f6a7))
|
|
21
|
+
* Merge branch 'en-221-update-logic' into 'master' ([7641052](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/7641052265fbf88550073ff0b4300c60e03592ee))
|
|
22
|
+
* Merge branch 'en-372-short-codes-module-intro' into 'master' ([bac2830](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/bac283079b3bf2e99d8e49e373bbb5e706ec7860))
|
|
23
|
+
|
|
24
|
+
## [44.15.1](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.15.0...v44.15.1) (2026-02-19)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Bug Fixes
|
|
28
|
+
|
|
29
|
+
* add validation for api ([75a44d6](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/75a44d6aacc3a4d7702773d040edcc23b271d298))
|
|
30
|
+
* imporve test ([a2ef17b](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/a2ef17b491f4130a08769fd2f5982d2825743234))
|
|
31
|
+
* remove unnacessary use effects block, remove unnacessary function from dependency array ([fbda456](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/fbda456a83e61d044a722ba031f61f7f532df763))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
* Merge branch 'EN/fix-scroll-behaviour' into 'master' ([1065b8e](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/1065b8e457790256826258d4b520b4340fa14600))
|
|
35
|
+
* Merge branch 'em-367-api-handle' into 'master' ([e6289c8](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/e6289c858230ebc9c5efea9f9c67189d7d396723))
|
|
36
|
+
|
|
1
37
|
# [44.15.0](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.14.0...v44.15.0) (2026-02-11)
|
|
2
38
|
|
|
3
39
|
|
package/gatsby-node.mjs
CHANGED
|
@@ -76,6 +76,21 @@ export const createPages = async (
|
|
|
76
76
|
preconnectLinks = themeOptions.preconnectLinks || [];
|
|
77
77
|
console.log(chalk.magenta("info") + chalk.whiteBright(" starting processor"));
|
|
78
78
|
|
|
79
|
+
const includeAllOperators = process.env.ENABLE_SHORT_CODES_OPERATOR;
|
|
80
|
+
const operatorsByShortName = includeAllOperators
|
|
81
|
+
? Object.values(operatorData || {}).reduce((acc, operator) => {
|
|
82
|
+
if (operator?.short_name) {
|
|
83
|
+
acc[operator.short_name.toLowerCase()] = {
|
|
84
|
+
min_deposit: operator.min_deposit,
|
|
85
|
+
max_deposit: operator.max_deposit,
|
|
86
|
+
min_withdrawal: operator.min_withdrawal,
|
|
87
|
+
max_withdrawal: operator.max_withdrawal,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return acc;
|
|
91
|
+
}, {})
|
|
92
|
+
: {};
|
|
93
|
+
|
|
79
94
|
// add data to modules
|
|
80
95
|
const processed = processor.run(
|
|
81
96
|
{
|
|
@@ -87,6 +102,7 @@ export const createPages = async (
|
|
|
87
102
|
toplists: toplistData,
|
|
88
103
|
content: contentData,
|
|
89
104
|
ribbons: ribbonsData,
|
|
105
|
+
...(includeAllOperators && { operators: operatorsByShortName }),
|
|
90
106
|
relations: {
|
|
91
107
|
operator: operatorData,
|
|
92
108
|
payment_method: paymentData,
|
|
@@ -102,7 +118,7 @@ export const createPages = async (
|
|
|
102
118
|
},
|
|
103
119
|
themeOptions,
|
|
104
120
|
fs,
|
|
105
|
-
translationsData
|
|
121
|
+
translationsData,
|
|
106
122
|
);
|
|
107
123
|
pages = processed.pages;
|
|
108
124
|
|
|
@@ -112,12 +128,14 @@ export const createPages = async (
|
|
|
112
128
|
htmlSitemapPages = processSitemapPages(pages, processed.site_markets);
|
|
113
129
|
|
|
114
130
|
// create robots.txt file
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
131
|
+
// block all crawlers to prevent indexing for non-production environments
|
|
132
|
+
const isProduction = process.env.GATSBY_ACTIVE_ENV === "production";
|
|
133
|
+
const robotsTxtContent = isProduction
|
|
134
|
+
? (siteGeneralData.robots_txt || "")
|
|
135
|
+
: "User-agent: *\nDisallow: /\n";
|
|
118
136
|
const streamRobotsTxt = fs.createWriteStream("./static/robots.txt");
|
|
119
137
|
console.log(
|
|
120
|
-
chalk.magenta("info") + chalk.whiteBright(
|
|
138
|
+
chalk.magenta("info") + chalk.whiteBright(` creating robots.txt file (${isProduction ? "production" : "blocking"})`)
|
|
121
139
|
);
|
|
122
140
|
streamRobotsTxt.write(robotsTxtContent);
|
|
123
141
|
streamRobotsTxt.end();
|
|
@@ -140,7 +158,7 @@ export const createPages = async (
|
|
|
140
158
|
|
|
141
159
|
siteSchema = schemaData[page["market_id"]];
|
|
142
160
|
authors = siteSettingsData.authors;
|
|
143
|
-
|
|
161
|
+
|
|
144
162
|
|
|
145
163
|
page.siteInfo = siteGeneralData;
|
|
146
164
|
page.siteSchema = siteSchema;
|
|
@@ -158,6 +176,26 @@ export const createPages = async (
|
|
|
158
176
|
__dirname
|
|
159
177
|
);
|
|
160
178
|
|
|
179
|
+
const template = templatesData[page.template_id];
|
|
180
|
+
const autogenerated = template && template.autogenerated_content;
|
|
181
|
+
|
|
182
|
+
archivePages.forEach((archivePage) => {
|
|
183
|
+
archivePage.context = clean({
|
|
184
|
+
...archivePage.context,
|
|
185
|
+
marketSections: removeUnwantedSections(
|
|
186
|
+
marketSection,
|
|
187
|
+
page.type,
|
|
188
|
+
ribbonsData
|
|
189
|
+
),
|
|
190
|
+
authors,
|
|
191
|
+
autogenerated,
|
|
192
|
+
siteSchema,
|
|
193
|
+
comments: commentsData?.[page?.id],
|
|
194
|
+
lang: page.language,
|
|
195
|
+
...themeOptions,
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
161
199
|
pagesToCreate.push(...archivePages);
|
|
162
200
|
return;
|
|
163
201
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable import/no-named-as-default */
|
|
2
|
-
import React, { useRef, useContext } from "react";
|
|
2
|
+
import React, { useRef, useContext, useEffect } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { Context } from "~context/MainProvider.js";
|
|
5
5
|
import Search from "~organisms/search";
|
|
@@ -59,7 +59,9 @@ const Navigation = ({
|
|
|
59
59
|
<img alt={useTranslate('nav_site_logo', logoAlt)} src={logo} width={logoWidth} height={logoHeight} />
|
|
60
60
|
);
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (stopScrollOnOpen) toggleScroll("", true);
|
|
64
|
+
}, [stopScrollOnOpen]);
|
|
63
65
|
|
|
64
66
|
const activeMarket =
|
|
65
67
|
pageContext?.allMarkets && pageContext?.allMarkets[pageContext.page.market];
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { months } from "./common.mjs";
|
|
2
2
|
|
|
3
3
|
const generatorsPlaceholderRegex =
|
|
4
|
-
/\[MONTH\]|\[YEAR\]|\[currentyear\]|\[sitename\]|\[currentmonth\]|\[title\]|\[currentdate\]|\[operator_name]|\[author_name]|\[link\]/gi;
|
|
4
|
+
/\[[a-z0-9_]+\.(min_deposit|max_deposit|min_withdrawal|max_withdrawal)\]|\[MONTH\]|\[YEAR\]|\[currentyear\]|\[sitename\]|\[currentmonth\]|\[title\]|\[currentdate\]|\[operator_name\]|\[author_name\]|\[link\]/gi;
|
|
5
|
+
|
|
5
6
|
|
|
6
7
|
const generatorsPlaceholderReplaceObject = (
|
|
7
8
|
data,
|
|
@@ -116,6 +116,7 @@ export const pickRelationKeys = {
|
|
|
116
116
|
"withdrawal_method",
|
|
117
117
|
"support_email",
|
|
118
118
|
"min_deposit",
|
|
119
|
+
"max_deposit",
|
|
119
120
|
"max_withdrawal",
|
|
120
121
|
"min_withdrawal",
|
|
121
122
|
"license_objects",
|
|
@@ -179,7 +180,9 @@ export const pickRelationKeys = {
|
|
|
179
180
|
"extra_fields",
|
|
180
181
|
"game_categories",
|
|
181
182
|
'maximum_bet',
|
|
182
|
-
"game_themes"
|
|
183
|
+
"game_themes",
|
|
184
|
+
'jackpot'
|
|
185
|
+
|
|
183
186
|
],
|
|
184
187
|
software_provider: [
|
|
185
188
|
"logo_filename_object",
|
|
@@ -39,24 +39,40 @@ export function generateTrackerLink(operator, trackerType, provider = false) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export function generatePlaceholderString(
|
|
42
|
+
export function generatePlaceholderString(
|
|
43
|
+
string = "",
|
|
44
|
+
translations,
|
|
45
|
+
data,
|
|
46
|
+
operators,
|
|
47
|
+
) {
|
|
48
|
+
|
|
49
|
+
|
|
43
50
|
const date = new Date();
|
|
44
51
|
const day = String(date.getDate()).padStart(2, "0");
|
|
45
52
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
46
53
|
const year = date.getFullYear();
|
|
47
54
|
const regex = generatorsConstant.generatorsPlaceholderRegex;
|
|
48
55
|
|
|
49
|
-
return string.replace(
|
|
50
|
-
|
|
51
|
-
(
|
|
56
|
+
return string.replace(regex, (match) => {
|
|
57
|
+
const key = match.toLowerCase();
|
|
58
|
+
if (key.includes(".")) {
|
|
59
|
+
const [operatorKey, field] = key
|
|
60
|
+
.slice(1, -1)
|
|
61
|
+
.split(".");
|
|
62
|
+
const value = operators?.[operatorKey]?.[field];
|
|
63
|
+
return value ?? "";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return (
|
|
52
67
|
generatorsConstant.generatorsPlaceholderReplaceObject(
|
|
53
68
|
data,
|
|
54
69
|
translations,
|
|
55
70
|
month,
|
|
56
71
|
day,
|
|
57
|
-
year
|
|
58
|
-
)[
|
|
59
|
-
|
|
72
|
+
year,
|
|
73
|
+
)[key] ?? ""
|
|
74
|
+
);
|
|
75
|
+
});
|
|
60
76
|
}
|
|
61
77
|
|
|
62
78
|
export function generateArray(obj) {
|
package/src/helpers/tracker.mjs
CHANGED
|
@@ -169,9 +169,26 @@ export async function getAffiliateLink(operator, path, page, headers, url) {
|
|
|
169
169
|
headers: headers ? filterCfKeys(Object.fromEntries(headers)) : {},
|
|
170
170
|
});
|
|
171
171
|
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
// Check if response is ok and content-type is JSON
|
|
173
|
+
if (!res.ok) {
|
|
174
|
+
console.error(`Tracking API error: ${res.status} ${res.statusText}`);
|
|
175
|
+
return { props: { success: false } };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const contentType = res.headers.get("content-type");
|
|
179
|
+
if (!contentType || !contentType.includes("application/json")) {
|
|
180
|
+
console.error(`Tracking API returned non-JSON content-type: ${contentType}`);
|
|
181
|
+
return { props: { success: false } };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Try to parse JSON safely
|
|
185
|
+
try {
|
|
186
|
+
const data = await res.json();
|
|
187
|
+
return { props: data };
|
|
188
|
+
} catch (jsonError) {
|
|
189
|
+
console.error("Failed to parse tracking API response as JSON:", jsonError);
|
|
190
|
+
return { props: { success: false } };
|
|
191
|
+
}
|
|
175
192
|
} catch (error) {
|
|
176
193
|
console.error("Error fetching affiliate link:", error);
|
|
177
194
|
return { props: { success: false } };
|
|
@@ -96,9 +96,14 @@ describe("Tracker Helper", () => {
|
|
|
96
96
|
|
|
97
97
|
global.fetch = jest.fn(() =>
|
|
98
98
|
Promise.resolve({
|
|
99
|
+
ok: true,
|
|
100
|
+
headers: {
|
|
101
|
+
get: (key) => (key === "content-type" ? "application/json" : null),
|
|
102
|
+
},
|
|
99
103
|
json: () => Promise.resolve({ success: true }),
|
|
100
104
|
})
|
|
101
105
|
);
|
|
106
|
+
|
|
102
107
|
beforeEach(() => {
|
|
103
108
|
fetch.mockClear();
|
|
104
109
|
});
|
|
@@ -153,6 +158,162 @@ describe("Tracker Helper", () => {
|
|
|
153
158
|
);
|
|
154
159
|
});
|
|
155
160
|
|
|
161
|
+
test("getAffiliateLink handles successful response", async () => {
|
|
162
|
+
fetch.mockImplementationOnce(() =>
|
|
163
|
+
Promise.resolve({
|
|
164
|
+
ok: true,
|
|
165
|
+
headers: {
|
|
166
|
+
get: (key) => (key === "content-type" ? "application/json" : null),
|
|
167
|
+
},
|
|
168
|
+
json: () => Promise.resolve({ success: true, result: { link: "https://example.com" } }),
|
|
169
|
+
})
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
const result = await Tracker.getAffiliateLink(
|
|
173
|
+
operator,
|
|
174
|
+
"/no/visit/rizk",
|
|
175
|
+
{ template: "default" },
|
|
176
|
+
null
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
expect(result).toEqual({ props: { success: true, result: { link: "https://example.com" } } });
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test("getAffiliateLink handles failed HTTP response", async () => {
|
|
183
|
+
const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
|
|
184
|
+
|
|
185
|
+
fetch.mockImplementationOnce(() =>
|
|
186
|
+
Promise.resolve({
|
|
187
|
+
ok: false,
|
|
188
|
+
status: 500,
|
|
189
|
+
statusText: "Internal Server Error",
|
|
190
|
+
headers: {
|
|
191
|
+
get: () => null,
|
|
192
|
+
},
|
|
193
|
+
})
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
const result = await Tracker.getAffiliateLink(
|
|
197
|
+
operator,
|
|
198
|
+
"/no/visit/rizk",
|
|
199
|
+
{ template: "default" },
|
|
200
|
+
null
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
expect(result).toEqual({ props: { success: false } });
|
|
204
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
205
|
+
"Tracking API error: 500 Internal Server Error"
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
consoleErrorSpy.mockRestore();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("getAffiliateLink handles non-JSON content-type (HTML error page)", async () => {
|
|
212
|
+
const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
|
|
213
|
+
|
|
214
|
+
fetch.mockImplementationOnce(() =>
|
|
215
|
+
Promise.resolve({
|
|
216
|
+
ok: true,
|
|
217
|
+
headers: {
|
|
218
|
+
get: (key) => (key === "content-type" ? "text/html" : null),
|
|
219
|
+
},
|
|
220
|
+
})
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
const result = await Tracker.getAffiliateLink(
|
|
224
|
+
operator,
|
|
225
|
+
"/no/visit/rizk",
|
|
226
|
+
{ template: "default" },
|
|
227
|
+
null
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
expect(result).toEqual({ props: { success: false } });
|
|
231
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
232
|
+
"Tracking API returned non-JSON content-type: text/html"
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
consoleErrorSpy.mockRestore();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test("getAffiliateLink handles missing content-type", async () => {
|
|
239
|
+
const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
|
|
240
|
+
|
|
241
|
+
fetch.mockImplementationOnce(() =>
|
|
242
|
+
Promise.resolve({
|
|
243
|
+
ok: true,
|
|
244
|
+
headers: {
|
|
245
|
+
get: () => null,
|
|
246
|
+
},
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
const result = await Tracker.getAffiliateLink(
|
|
251
|
+
operator,
|
|
252
|
+
"/no/visit/rizk",
|
|
253
|
+
{ template: "default" },
|
|
254
|
+
null
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
expect(result).toEqual({ props: { success: false } });
|
|
258
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
259
|
+
"Tracking API returned non-JSON content-type: null"
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
consoleErrorSpy.mockRestore();
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
test("getAffiliateLink handles JSON parsing error", async () => {
|
|
266
|
+
const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
|
|
267
|
+
|
|
268
|
+
fetch.mockImplementationOnce(() =>
|
|
269
|
+
Promise.resolve({
|
|
270
|
+
ok: true,
|
|
271
|
+
headers: {
|
|
272
|
+
get: (key) => (key === "content-type" ? "application/json" : null),
|
|
273
|
+
},
|
|
274
|
+
json: () => Promise.reject(new Error("Unexpected token < in JSON at position 0")),
|
|
275
|
+
})
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
const result = await Tracker.getAffiliateLink(
|
|
279
|
+
operator,
|
|
280
|
+
"/no/visit/rizk",
|
|
281
|
+
{ template: "default" },
|
|
282
|
+
null
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
expect(result).toEqual({ props: { success: false } });
|
|
286
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
287
|
+
"Failed to parse tracking API response as JSON:",
|
|
288
|
+
expect.any(Error)
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
consoleErrorSpy.mockRestore();
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
test("getAffiliateLink handles network error", async () => {
|
|
295
|
+
const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
|
|
296
|
+
|
|
297
|
+
fetch.mockImplementationOnce(() =>
|
|
298
|
+
Promise.reject(new Error("Network error"))
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
const result = await Tracker.getAffiliateLink(
|
|
302
|
+
operator,
|
|
303
|
+
"/no/visit/rizk",
|
|
304
|
+
{ template: "default" },
|
|
305
|
+
null
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
expect(result).toEqual({ props: { success: false } });
|
|
309
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
310
|
+
"Error fetching affiliate link:",
|
|
311
|
+
expect.any(Error)
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
consoleErrorSpy.mockRestore();
|
|
315
|
+
});
|
|
316
|
+
|
|
156
317
|
test("getTrackingAPIParams tests", async () => {
|
|
157
318
|
const params = Tracker.getTrackingAPIParams(
|
|
158
319
|
"temlateValue",
|
|
@@ -6,62 +6,47 @@ import PropTypes from "prop-types";
|
|
|
6
6
|
import { ModalContext } from "./modalContext";
|
|
7
7
|
import styles from "./modal.module.scss";
|
|
8
8
|
import useTranslate from "~hooks/useTranslate/useTranslate";
|
|
9
|
+
import { toggleScroll } from "~helpers/scroll";
|
|
9
10
|
|
|
10
11
|
const ModalContent = ({ closeIcon, customCss, children }) => {
|
|
11
12
|
const { showModal, setShowModal } = useContext(ModalContext);
|
|
12
13
|
const modal = useRef(null);
|
|
13
14
|
|
|
14
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
15
|
-
const close = () => {
|
|
16
|
-
document.body.style.overflow = "auto";
|
|
17
|
-
setShowModal(false);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
15
|
useEffect(() => {
|
|
21
|
-
if (showModal)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
modal.current.classList.remove(styles.activeModal);
|
|
25
|
-
}
|
|
26
|
-
}, [showModal]);
|
|
16
|
+
if (!showModal) return;
|
|
17
|
+
|
|
18
|
+
toggleScroll("modal");
|
|
27
19
|
|
|
28
|
-
// Close on esc
|
|
29
|
-
useEffect(() => {
|
|
30
20
|
const handleEsc = (event) => {
|
|
31
21
|
if (event.keyCode === 27) {
|
|
32
|
-
|
|
22
|
+
setShowModal(false);
|
|
33
23
|
}
|
|
34
24
|
};
|
|
35
|
-
if (typeof window !== "undefined")
|
|
36
|
-
window.addEventListener("keydown", handleEsc);
|
|
37
|
-
return () => {
|
|
38
|
-
if (typeof window !== "undefined")
|
|
39
|
-
window.removeEventListener("keydown", handleEsc);
|
|
40
|
-
};
|
|
41
|
-
}, [close]);
|
|
42
25
|
|
|
43
|
-
// Close on outside click
|
|
44
|
-
useEffect(() => {
|
|
45
26
|
const handleOutsideClick = (event) => {
|
|
46
27
|
if (
|
|
47
28
|
modal.current &&
|
|
48
29
|
!modal.current.contains(event.target) &&
|
|
49
|
-
!modal.current.previousElementSibling
|
|
30
|
+
!modal.current.previousElementSibling?.contains(event.target)
|
|
50
31
|
) {
|
|
51
|
-
|
|
32
|
+
setShowModal(false);
|
|
52
33
|
}
|
|
53
34
|
};
|
|
54
|
-
|
|
55
|
-
|
|
35
|
+
|
|
36
|
+
window.addEventListener("keydown", handleEsc);
|
|
37
|
+
window.addEventListener("mousedown", handleOutsideClick);
|
|
38
|
+
|
|
56
39
|
return () => {
|
|
57
|
-
|
|
58
|
-
|
|
40
|
+
window.removeEventListener("keydown", handleEsc);
|
|
41
|
+
window.removeEventListener("mousedown", handleOutsideClick);
|
|
42
|
+
toggleScroll("modal");
|
|
59
43
|
};
|
|
60
|
-
}, [
|
|
44
|
+
}, [showModal, setShowModal]);
|
|
45
|
+
|
|
61
46
|
const closeIconAriaLabel = useTranslate("ariaLabel-closeIcon", "Close Icon");
|
|
62
47
|
return (
|
|
63
|
-
<div className={styles.modalInner || ""} ref={modal}>
|
|
64
|
-
<div className={styles.modalOverlay || ""} onClick={
|
|
48
|
+
<div className={`${styles.modalInner || ""} ${showModal ? styles.activeModal || "" : ""}`} ref={modal}>
|
|
49
|
+
<div className={styles.modalOverlay || ""} onClick={() => setShowModal(false)} />
|
|
65
50
|
<div
|
|
66
51
|
className={`${styles.modalContent || ""} ${
|
|
67
52
|
customCss ? customCss || "" : ""
|
|
@@ -72,7 +57,7 @@ const ModalContent = ({ closeIcon, customCss, children }) => {
|
|
|
72
57
|
className={`${styles.closeIcon || ""} modal-gtm btn-cta`}
|
|
73
58
|
aria-label={closeIconAriaLabel}
|
|
74
59
|
type="button"
|
|
75
|
-
onClick={
|
|
60
|
+
onClick={() => setShowModal(false)}
|
|
76
61
|
>
|
|
77
62
|
{closeIcon}
|
|
78
63
|
</button>
|
package/src/resolver/index.mjs
CHANGED
|
@@ -150,7 +150,8 @@ export function processSections(
|
|
|
150
150
|
data,
|
|
151
151
|
toplists,
|
|
152
152
|
content,
|
|
153
|
-
previewPageID
|
|
153
|
+
previewPageID,
|
|
154
|
+
operators = {}
|
|
154
155
|
) {
|
|
155
156
|
// pageId we will use it just on operator review pages
|
|
156
157
|
const pageId = page ? page.id : null;
|
|
@@ -225,7 +226,8 @@ export function processSections(
|
|
|
225
226
|
toplists,
|
|
226
227
|
content,
|
|
227
228
|
prefilledMarketModules,
|
|
228
|
-
previewPageID
|
|
229
|
+
previewPageID,
|
|
230
|
+
operators
|
|
229
231
|
);
|
|
230
232
|
sections[sectionKey].modules[key] = module;
|
|
231
233
|
if (module?.filters) {
|
|
@@ -334,13 +336,15 @@ export function processExtraFields(
|
|
|
334
336
|
});
|
|
335
337
|
}
|
|
336
338
|
|
|
337
|
-
function updatePlaceholders(page, data, translationsData) {
|
|
339
|
+
function updatePlaceholders(page, data, translationsData, operators = {}) {
|
|
340
|
+
|
|
338
341
|
page.title =
|
|
339
342
|
page.title &&
|
|
340
343
|
generatePlaceholderString(page.title, translationsData, {
|
|
341
344
|
siteName: data.site_name,
|
|
342
345
|
pageTitle: page.title,
|
|
343
346
|
market: page.market,
|
|
347
|
+
operators
|
|
344
348
|
});
|
|
345
349
|
|
|
346
350
|
page.meta_title =
|
|
@@ -357,6 +361,7 @@ function updatePlaceholders(page, data, translationsData) {
|
|
|
357
361
|
siteName: data.site_name,
|
|
358
362
|
pageTitle: page.title,
|
|
359
363
|
market: page.market,
|
|
364
|
+
operators
|
|
360
365
|
});
|
|
361
366
|
}
|
|
362
367
|
|
|
@@ -425,7 +430,7 @@ export default {
|
|
|
425
430
|
relations,
|
|
426
431
|
data.content
|
|
427
432
|
);
|
|
428
|
-
updatePlaceholders(page, generalData, translations);
|
|
433
|
+
updatePlaceholders(page, generalData, translations, data.operators);
|
|
429
434
|
|
|
430
435
|
// Set Affiliate relations
|
|
431
436
|
processRelations(
|
|
@@ -477,7 +482,8 @@ export default {
|
|
|
477
482
|
siteName: generalData.site_name,
|
|
478
483
|
pageTitle: page.title,
|
|
479
484
|
market: page.market,
|
|
480
|
-
}
|
|
485
|
+
},
|
|
486
|
+
data.operators
|
|
481
487
|
);
|
|
482
488
|
}
|
|
483
489
|
|
|
@@ -651,7 +657,8 @@ export default {
|
|
|
651
657
|
null,
|
|
652
658
|
data.toplists,
|
|
653
659
|
data.content,
|
|
654
|
-
previewPageID
|
|
660
|
+
previewPageID,
|
|
661
|
+
data.operators || {}
|
|
655
662
|
);
|
|
656
663
|
}
|
|
657
664
|
|
|
@@ -676,7 +683,8 @@ export default {
|
|
|
676
683
|
data,
|
|
677
684
|
data.toplists,
|
|
678
685
|
data.content,
|
|
679
|
-
previewPageID
|
|
686
|
+
previewPageID,
|
|
687
|
+
data.operators || {}
|
|
680
688
|
),
|
|
681
689
|
});
|
|
682
690
|
}
|
package/src/resolver/modules.mjs
CHANGED
|
@@ -515,7 +515,8 @@ export function processContentModule(
|
|
|
515
515
|
translations,
|
|
516
516
|
relationData,
|
|
517
517
|
content,
|
|
518
|
-
previewPageID
|
|
518
|
+
previewPageID,
|
|
519
|
+
operators,
|
|
519
520
|
) {
|
|
520
521
|
module.value = previewPageID
|
|
521
522
|
? module.value
|
|
@@ -524,7 +525,8 @@ export function processContentModule(
|
|
|
524
525
|
module.value = generatePlaceholderString(
|
|
525
526
|
module.value,
|
|
526
527
|
translations,
|
|
527
|
-
relationData
|
|
528
|
+
relationData,
|
|
529
|
+
operators
|
|
528
530
|
);
|
|
529
531
|
|
|
530
532
|
module.value = trailingSlash(module.value);
|
|
@@ -536,7 +538,17 @@ export function processContentModule(
|
|
|
536
538
|
module.show_more_content = generatePlaceholderString(
|
|
537
539
|
module.show_more_content,
|
|
538
540
|
translations,
|
|
539
|
-
relationData
|
|
541
|
+
relationData,
|
|
542
|
+
operators
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if (module.module_introduction && Object.keys(operators).length) {
|
|
547
|
+
module.module_introduction = generatePlaceholderString(
|
|
548
|
+
module.module_introduction,
|
|
549
|
+
translations,
|
|
550
|
+
relationData,
|
|
551
|
+
operators,
|
|
540
552
|
);
|
|
541
553
|
}
|
|
542
554
|
}
|
|
@@ -552,14 +564,14 @@ export function shouldSavePrefilled(module = {}, siteName) {
|
|
|
552
564
|
);
|
|
553
565
|
}
|
|
554
566
|
|
|
555
|
-
export function processSpotlightModule(module = {}, content, previewPageID) {
|
|
567
|
+
export function processSpotlightModule(module = {}, content, previewPageID, translations, relationData, operators) {
|
|
556
568
|
module.items.forEach((item) => {
|
|
557
569
|
item.content = trailingSlash(
|
|
558
570
|
previewPageID ? item.content : (content && content[item.content]) || ""
|
|
559
571
|
);
|
|
560
|
-
item.text = trailingSlash(
|
|
561
|
-
previewPageID ? item.text : (content && content[item.text]) || ""
|
|
562
|
-
);
|
|
572
|
+
item.text = generatePlaceholderString(trailingSlash(
|
|
573
|
+
previewPageID ? item.text : (content && content[item.text]) || "",
|
|
574
|
+
), translations, relationData, operators);
|
|
563
575
|
});
|
|
564
576
|
|
|
565
577
|
return module;
|
|
@@ -572,30 +584,32 @@ export function processCarouselModule(module = {}, content) {
|
|
|
572
584
|
return module;
|
|
573
585
|
}
|
|
574
586
|
|
|
575
|
-
export function processFaq(module = {}, content, relationData, previewPageID) {
|
|
587
|
+
export function processFaq(module = {}, content, relationData, previewPageID, operators) {
|
|
576
588
|
// eslint-disable-next-line no-unused-expressions
|
|
577
589
|
module.items &&
|
|
578
590
|
// eslint-disable-next-line array-callback-return
|
|
579
591
|
module.items.map((item) => {
|
|
580
592
|
item.question = trailingSlash(
|
|
581
593
|
previewPageID
|
|
582
|
-
? generatePlaceholderString(item.question, null, relationData)
|
|
594
|
+
? generatePlaceholderString(item.question, null, relationData, operators)
|
|
583
595
|
: (content
|
|
584
596
|
? generatePlaceholderString(
|
|
585
597
|
content[item.question],
|
|
586
598
|
null,
|
|
587
|
-
relationData
|
|
599
|
+
relationData,
|
|
600
|
+
operators,
|
|
588
601
|
)
|
|
589
602
|
: "") || ""
|
|
590
603
|
);
|
|
591
604
|
item.answer = trailingSlash(
|
|
592
605
|
previewPageID
|
|
593
|
-
? generatePlaceholderString(item.answer, null, relationData)
|
|
606
|
+
? generatePlaceholderString(item.answer, null, relationData, operators)
|
|
594
607
|
: (content &&
|
|
595
608
|
generatePlaceholderString(
|
|
596
609
|
content[item.answer],
|
|
597
610
|
null,
|
|
598
|
-
relationData
|
|
611
|
+
relationData,
|
|
612
|
+
operators
|
|
599
613
|
)) ||
|
|
600
614
|
""
|
|
601
615
|
);
|
|
@@ -632,19 +646,29 @@ export function processModule(
|
|
|
632
646
|
toplists,
|
|
633
647
|
content,
|
|
634
648
|
prefilledMarketModules,
|
|
635
|
-
previewPageID
|
|
649
|
+
previewPageID,
|
|
650
|
+
operators
|
|
636
651
|
) {
|
|
637
652
|
module.module_title =
|
|
638
653
|
module.module_title &&
|
|
639
|
-
generatePlaceholderString(module.module_title, translations, relationData);
|
|
654
|
+
generatePlaceholderString(module.module_title, translations, relationData, operators);
|
|
640
655
|
module.title =
|
|
641
656
|
module.title &&
|
|
642
|
-
generatePlaceholderString(module.title, translations, relationData);
|
|
657
|
+
generatePlaceholderString(module.title, translations, relationData, operators);
|
|
643
658
|
|
|
644
659
|
module.anchor_slug =
|
|
645
660
|
module.anchor_slug &&
|
|
646
661
|
generatePlaceholderString(module.anchor_slug, translations, relationData);
|
|
647
662
|
|
|
663
|
+
module.module_introduction =
|
|
664
|
+
module.module_introduction &&
|
|
665
|
+
generatePlaceholderString(
|
|
666
|
+
module.module_introduction,
|
|
667
|
+
translations,
|
|
668
|
+
relationData,
|
|
669
|
+
operators,
|
|
670
|
+
);
|
|
671
|
+
|
|
648
672
|
// See more link
|
|
649
673
|
if (
|
|
650
674
|
module.see_more_link?.value &&
|
|
@@ -671,7 +695,8 @@ export function processModule(
|
|
|
671
695
|
translations,
|
|
672
696
|
relationData,
|
|
673
697
|
content,
|
|
674
|
-
previewPageID
|
|
698
|
+
previewPageID,
|
|
699
|
+
operators,
|
|
675
700
|
);
|
|
676
701
|
} else if (module.name === "bonus") {
|
|
677
702
|
processBonus(module, relations, data);
|
|
@@ -686,11 +711,11 @@ export function processModule(
|
|
|
686
711
|
translations
|
|
687
712
|
);
|
|
688
713
|
} else if (module.name === "faq") {
|
|
689
|
-
processFaq(module, content, relationData, previewPageID);
|
|
714
|
+
processFaq(module, content, relationData, previewPageID, operators);
|
|
690
715
|
} else if (module.name === "anchor") {
|
|
691
716
|
processAnchor(module, relationData, translations);
|
|
692
717
|
} else if (module.name === "spotlights") {
|
|
693
|
-
processSpotlightModule(module, content, previewPageID);
|
|
718
|
+
processSpotlightModule(module, content, previewPageID, translations, relationData, operators);
|
|
694
719
|
} else if (module.name === "menu" && menus && menus[module.menu_id]) {
|
|
695
720
|
module = Object.assign(module, menus[module.menu_id]);
|
|
696
721
|
} else if (module.name === "statistics_counter") {
|