gatsby-core-theme 44.2.20 → 44.3.1

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 CHANGED
@@ -1,3 +1,44 @@
1
+ ## [44.3.1](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.3.0...v44.3.1) (2025-06-30)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * flag module as toplist ([b0715ee](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/b0715ee5aa6ad3d2f9ed86d8f5381b7e67e2181f))
7
+ * move filters to page, flag toplist that has filters ([7f40833](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/7f408336481a5f53febc7eb8504364971d3683d0))
8
+
9
+
10
+ * Merge branch 'tm-5525-toplist-filters' into 'master' ([30427fb](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/30427fbdaa89b0abf48243ad80ed81e1af23047f))
11
+
12
+ # [44.3.0](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.2.20...v44.3.0) (2025-06-25)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * filters order ([78bae80](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/78bae801cd85a65cf30007997e7c8973d17d505a))
18
+ * notification time ([355d437](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/355d4373ae1d7636c70e3822f1be52f502143927))
19
+ * rm consoel logs ([9d02b9d](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/9d02b9d9808b904d53f4fb63ee72bb7c76bc52d6))
20
+ * rm old tests ([41d19a8](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/41d19a859a1d9a76e16aa19c374ab5e27f7f8557))
21
+ * sync with main ([dfcc323](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/dfcc323274e8578b9de12a04345ec77692c6ca6a))
22
+ * use filterOperators in processFilters ([c6745f1](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/c6745f1c331746565a769bb3a77f77811f4febce))
23
+
24
+
25
+ * Merge branch 'tm-5525-toplist-filters' into 'master' ([e5b1468](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/e5b1468a565a367351fe065d44592383ed1d31f0))
26
+ * Merge branch 'tm-5536-notifications-time' into 'master' ([48889f9](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/48889f94b175238fffac8fa91e88e5bf15f504f2))
27
+
28
+
29
+ ### Features
30
+
31
+ * build filters for enabled templates ([3d201c2](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/3d201c20fa5e1794b00a7522953d2ab195168bfb))
32
+ * build filters on top list ([908a65f](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/908a65fbb2b6fcf6869fadce2e83d96267e2c29e))
33
+ * slice toplists on filters ([6074186](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/60741862f3bc6f9d30a107921a9c1866f9b1d7ac))
34
+ * split filter operators, remove promises ([55483bb](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/55483bbe76ed03673ce6feae7ed62bce6e8dda58))
35
+
36
+
37
+ ### Tests
38
+
39
+ * buildTopListFilter ([ab811e7](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/ab811e791e631c6fffb1cd76c05cdce36ec07987))
40
+ * process filters ([d396159](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/d396159e6789b86b63d14cd743f7838e9d6dd7e3))
41
+
1
42
  ## [44.2.20](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.2.19...v44.2.20) (2025-06-24)
2
43
 
3
44
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gatsby-core-theme",
3
- "version": "44.2.20",
3
+ "version": "44.3.1",
4
4
  "description": "Gatsby Theme NPM Package",
5
5
  "author": "",
6
6
  "license": "ISC",
@@ -1,13 +1,20 @@
1
1
  /* eslint-disable react/prop-types */
2
- import React, { createContext, useState } from 'react';
2
+ import React, { createContext, useState } from "react";
3
3
 
4
4
  export const Context = createContext();
5
5
 
6
6
  export default (props) => {
7
7
  const { value, children } = props;
8
8
 
9
- const [ showTranslationKeys, setShowTranslationKeys ] = useState(false);
10
-
9
+ const [showTranslationKeys, setShowTranslationKeys] = useState(false);
10
+ const [showFilter, setShowFilter] = useState(false);
11
+ const [topListFilters, setTopListFilters] = useState();
12
+ const topListContext = {
13
+ showFilter,
14
+ setShowFilter,
15
+ topListFilters,
16
+ setTopListFilters,
17
+ };
11
18
  return (
12
19
  <Context.Provider
13
20
  value={{
@@ -15,8 +22,9 @@ export default (props) => {
15
22
  preview: value.isPreview,
16
23
  language: value.language,
17
24
  admin: value.admin,
25
+ setShowTranslationKeys,
18
26
  showTranslationKeys,
19
- setShowTranslationKeys
27
+ topListContext,
20
28
  }}
21
29
  >
22
30
  {children}
@@ -30,14 +30,14 @@ export function formatDate(date, format, separator = '/', market = 'en-GB') {
30
30
  }
31
31
 
32
32
  export const getTimeAgo = (dateString) => {
33
- const date = new Date(dateString.includes('Z') ? dateString : `${dateString.replace(" ", "T")}Z`);
34
- const now = new Date(new Date().toISOString().slice(0, 19));
33
+ const date = new Date(dateString.replace(" ", "T")); // Make it ISO-compliant
34
+ const now = new Date();
35
35
 
36
- const diffMs = now.getTime() - date.getTime();
37
- const diffMinutes = Math.floor(diffMs / (1000 * 60));
38
- const diffHours = Math.floor(diffMinutes / 60);
39
- const diffDays = Math.floor(diffHours / 24);
40
- const diffMonths = Math.floor(diffDays / 30);
36
+ const diffMs = now.getTime() - date.getTime();
37
+ const diffMinutes = Math.floor(diffMs / (1000 * 60));
38
+ const diffHours = Math.floor(diffMinutes / 60);
39
+ const diffDays = Math.floor(diffHours / 24);
40
+ const diffMonths = Math.floor(diffDays / 30);
41
41
 
42
42
  if (diffDays >= 32) {
43
43
  return { value: diffMonths, key: diffMonths === 1 ? "month_ago" : "months_ago" };
@@ -49,4 +49,4 @@ export const getTimeAgo = (dateString) => {
49
49
  return { value: diffHours, key: diffHours === 1 ? "hour_ago" : "hours_ago" };
50
50
  }
51
51
  return { value: diffMinutes, key: diffMinutes === 1 ? "minute_ago" : "minutes_ago" };
52
- };
52
+ };
@@ -10,16 +10,16 @@ describe('Date-Time Helper', () => {
10
10
 
11
11
 
12
12
  test('getTimeAgo()', () => {
13
- const nowUTC = new Date(new Date().toISOString().slice(0, 19));
13
+ const now = new Date();
14
14
 
15
- const minutesAgo = new Date(nowUTC.getTime() - 5 * 60 * 1000).toISOString().slice(0, 19); // 5 mins ago
16
- const hoursAgo = new Date(nowUTC.getTime() - 2 * 60 * 60 * 1000).toISOString().slice(0, 19); // 2 hours ago
17
- const daysAgo = new Date(nowUTC.getTime() - 10 * 24 * 60 * 60 * 1000).toISOString().slice(0, 19); // 10 days ago
18
- const monthsAgo = new Date(nowUTC.getTime() - 65 * 24 * 60 * 60 * 1000).toISOString().slice(0, 19); // ~2 months ago
15
+ const minutesAgo = new Date(now.getTime() - 5 * 60 * 1000).toISOString(); // 5 minutes ago
16
+ const hoursAgo = new Date(now.getTime() - 2 * 60 * 60 * 1000).toISOString(); // 2 hours ago
17
+ const daysAgo = new Date(now.getTime() - 10 * 24 * 60 * 60 * 1000).toISOString(); // 10 days ago
18
+ const monthsAgo = new Date(now.getTime() - 65 * 24 * 60 * 60 * 1000).toISOString(); // ~2 months ago
19
19
 
20
- expect(getTimeAgo(minutesAgo)).toMatchObject({ key: 'minutes_ago', value: 5 });
21
- expect(getTimeAgo(hoursAgo)).toMatchObject({ key: 'hours_ago', value: 2 });
22
- expect(getTimeAgo(daysAgo)).toMatchObject({ key: 'days_ago', value: 10 });
23
- expect(getTimeAgo(monthsAgo)).toMatchObject({ key: 'months_ago', value: 2 });
24
- });
20
+ expect(getTimeAgo(minutesAgo)).toMatchObject({ key: 'minutes_ago', value: 5 });
21
+ expect(getTimeAgo(hoursAgo)).toMatchObject({ key: 'hours_ago', value: 2 });
22
+ expect(getTimeAgo(daysAgo)).toMatchObject({ key: 'days_ago', value: 10 });
23
+ expect(getTimeAgo(monthsAgo)).toMatchObject({ key: 'months_ago', value: 2 });
24
+ });
25
25
  });
@@ -0,0 +1,66 @@
1
+ function buildToplistFilter(pageFilters, operator) {
2
+ const addToFilter = (category, key, operatorId) => {
3
+ if (!category[key]) category[key] = { items: [] };
4
+ category[key].items.push(operatorId);
5
+ };
6
+ const operatorId = operator.id;
7
+ const rating = Math.floor(operator.rating);
8
+
9
+ // Rating filters
10
+ if (rating >= 1 && rating <= 5) {
11
+ pageFilters.rating[rating].items.push(operatorId);
12
+
13
+ // Best online casinos (5-star ratings)
14
+ if (rating === 5) {
15
+ pageFilters.popular_filters.best_online.items.push(operatorId);
16
+ }
17
+ }
18
+
19
+ // Deposit methods
20
+ operator.deposit_methods?.forEach((method) => {
21
+ addToFilter(pageFilters.deposit_methods, method.name, operatorId);
22
+
23
+ // Crypto filter
24
+ if (method.name.toLowerCase() === "cryptocurrency") {
25
+ pageFilters.popular_filters.crypto.items.push(operatorId);
26
+ }
27
+ });
28
+
29
+ // Withdrawal methods
30
+ operator.withdrawal_method?.forEach((method) => {
31
+ addToFilter(pageFilters.withdrawal_method, method.name, operatorId);
32
+ });
33
+
34
+ // Game categories
35
+ operator.game_categories?.forEach((category) => {
36
+ addToFilter(pageFilters.game_categories, category, operatorId);
37
+ });
38
+
39
+ // Licenses
40
+ operator.license_objects?.forEach((license) => {
41
+ addToFilter(pageFilters.licenses, license.name, operatorId);
42
+ });
43
+
44
+ // Payout time
45
+ if (operator.payout_time) {
46
+ addToFilter(pageFilters.payout_time, operator.payout_time, operatorId);
47
+ }
48
+
49
+ // Payout rate
50
+ const payoutRatio = operator.extra_fields?.payoutRatio;
51
+ if (payoutRatio) {
52
+ addToFilter(pageFilters.payout_rate, payoutRatio, operatorId);
53
+ }
54
+
55
+ // Mobile optimized
56
+ if (operator.extra_fields?.mobile_optimized) {
57
+ pageFilters.popular_filters.mobile_optimized.items.push(operatorId);
58
+ }
59
+
60
+ // Best live casino
61
+ if (operator.extra_fields?.best_live_casino) {
62
+ pageFilters.popular_filters.best_live.items.push(operatorId);
63
+ }
64
+ }
65
+
66
+ export default buildToplistFilter;
@@ -0,0 +1,104 @@
1
+ import buildToplistFilter from "./build-toplist-filter.mjs";
2
+
3
+ describe("buildToplistFilter", () => {
4
+ let pageFilters;
5
+ let operator;
6
+
7
+ beforeEach(() => {
8
+ pageFilters = {
9
+ rating: {
10
+ 1: { items: [] },
11
+ 2: { items: [] },
12
+ 3: { items: [] },
13
+ 4: { items: [] },
14
+ 5: { items: [] },
15
+ },
16
+ popular_filters: {
17
+ best_online: { items: [] },
18
+ crypto: { items: [] },
19
+ mobile_optimized: { items: [] },
20
+ best_live: { items: [] },
21
+ },
22
+ deposit_methods: {},
23
+ withdrawal_method: {},
24
+ game_categories: {},
25
+ licenses: {},
26
+ payout_time: {},
27
+ payout_rate: {},
28
+ };
29
+
30
+ operator = {
31
+ id: "operator1",
32
+ rating: 5,
33
+ deposit_methods: [{ name: "Cryptocurrency" }, { name: "Credit Card" }],
34
+ withdrawal_method: [{ name: "Bank Transfer" }],
35
+ game_categories: ["Slots", "Poker"],
36
+ license_objects: [{ name: "License A" }],
37
+ payout_time: "24 hours",
38
+ extra_fields: {
39
+ payoutRatio: "95%",
40
+ mobile_optimized: true,
41
+ best_live_casino: true,
42
+ },
43
+ };
44
+ });
45
+
46
+ it("should add operator to the correct rating filter", () => {
47
+ buildToplistFilter(pageFilters, operator);
48
+ expect(pageFilters.rating[5].items).toContain("operator1");
49
+ expect(pageFilters.popular_filters.best_online.items).toContain(
50
+ "operator1"
51
+ );
52
+ });
53
+
54
+ it("should add operator to the deposit methods and crypto filter", () => {
55
+ buildToplistFilter(pageFilters, operator);
56
+ expect(pageFilters.deposit_methods.Cryptocurrency.items).toContain(
57
+ "operator1"
58
+ );
59
+ expect(pageFilters.deposit_methods["Credit Card"].items).toContain(
60
+ "operator1"
61
+ );
62
+ expect(pageFilters.popular_filters.crypto.items).toContain("operator1");
63
+ });
64
+
65
+ it("should add operator to the withdrawal methods", () => {
66
+ buildToplistFilter(pageFilters, operator);
67
+ expect(pageFilters.withdrawal_method["Bank Transfer"].items).toContain(
68
+ "operator1"
69
+ );
70
+ });
71
+
72
+ it("should add operator to the game categories", () => {
73
+ buildToplistFilter(pageFilters, operator);
74
+ expect(pageFilters.game_categories.Slots.items).toContain("operator1");
75
+ expect(pageFilters.game_categories.Poker.items).toContain("operator1");
76
+ });
77
+
78
+ it("should add operator to the licenses", () => {
79
+ buildToplistFilter(pageFilters, operator);
80
+ expect(pageFilters.licenses["License A"].items).toContain("operator1");
81
+ });
82
+
83
+ it("should add operator to the payout time filter", () => {
84
+ buildToplistFilter(pageFilters, operator);
85
+ expect(pageFilters.payout_time["24 hours"].items).toContain("operator1");
86
+ });
87
+
88
+ it("should add operator to the payout rate filter", () => {
89
+ buildToplistFilter(pageFilters, operator);
90
+ expect(pageFilters.payout_rate["95%"].items).toContain("operator1");
91
+ });
92
+
93
+ it("should add operator to the mobile optimized filter", () => {
94
+ buildToplistFilter(pageFilters, operator);
95
+ expect(pageFilters.popular_filters.mobile_optimized.items).toContain(
96
+ "operator1"
97
+ );
98
+ });
99
+
100
+ it("should add operator to the best live casino filter", () => {
101
+ buildToplistFilter(pageFilters, operator);
102
+ expect(pageFilters.popular_filters.best_live.items).toContain("operator1");
103
+ });
104
+ });
@@ -113,21 +113,20 @@ export function transform(response) {
113
113
  Object.keys(pages[market][pageType]).forEach((pageId) => {
114
114
  const page = pages[market][pageType][pageId];
115
115
  if (
116
- mainSettings[page.relation_type] && mainSettings[page.relation_type].reading_time &&
116
+ mainSettings[page.relation_type] &&
117
+ mainSettings[page.relation_type].reading_time &&
117
118
  mainSettings[page.relation_type].reading_time[
118
119
  process.env.GATSBY_SITE_NAME
119
120
  ]
120
121
  ) {
121
122
  page.reading_time = getReadingTime(page.sections, response.content);
122
123
  }
123
-
124
124
 
125
125
  if (response.site_markets[siteMarket].path_prefix && page) {
126
126
  // set page prefix for multiple markets
127
127
  page.path = `${response.site_markets[siteMarket].path_prefix}${
128
128
  page.path !== "/" ? `/${page.path}` : ""
129
129
  }`;
130
-
131
130
  transformed[siteMarket][pageType].push(page);
132
131
  } else if (page) {
133
132
  transformed[siteMarket][pageType].push(page);
@@ -178,13 +177,19 @@ export function processSections(
178
177
  shouldSavePrefilled(module, siteName) &&
179
178
  savedModules[module.module_value_id]
180
179
  ) {
181
- const filteredModule = cloneDeep(savedModules[module.module_value_id]);
180
+ const filteredModule = cloneDeep(
181
+ savedModules[module.module_value_id]
182
+ );
182
183
 
183
184
  const relationID = pagesMappedById[pageId]?.relation_id;
184
- if (filteredModule.name === 'cards_v2' &&
185
- relationID && filteredModule.items
185
+ if (
186
+ filteredModule.name === "cards_v2" &&
187
+ relationID &&
188
+ filteredModule.items
186
189
  ) {
187
- filteredModule.items = filteredModule.items.filter((item) => !item.relation || item.relation.id !== relationID);
190
+ filteredModule.items = filteredModule.items.filter(
191
+ (item) => !item.relation || item.relation.id !== relationID
192
+ );
188
193
  }
189
194
 
190
195
  Object.assign(module, filteredModule);
@@ -195,13 +200,11 @@ export function processSections(
195
200
  module = {
196
201
  ...cloneDeep(
197
202
  prefilledMarketModules[module.module_value_id] ||
198
- prefilledMarketModules[module.value_id]
203
+ prefilledMarketModules[module.value_id]
199
204
  ),
200
205
  value_type: ModuleValue.VALUE_TYPE_PREFILLED_MODULE_MARKET,
201
206
  };
202
207
  }
203
-
204
-
205
208
  processModule(
206
209
  module,
207
210
  pages,
@@ -216,9 +219,14 @@ export function processSections(
216
219
  toplists,
217
220
  content
218
221
  );
219
-
220
222
  sections[sectionKey].modules[key] = module;
221
-
223
+ if (module?.filters) {
224
+ if (!page?.topListFilters) {
225
+ page.toplistFilters = module.filters;
226
+ module.topListFilters = true;
227
+ }
228
+ delete module.filters;
229
+ }
222
230
  if (shouldSavePrefilled(module, siteName)) {
223
231
  savedModules[module.module_value_id] = module;
224
232
  }
@@ -239,7 +247,10 @@ export function getReadingTime(sections, content) {
239
247
  sections[sectionKey].modules.forEach((module) => {
240
248
  // calculate reading time
241
249
  if (module.name === "content") {
242
- const nrOfWords = removeTags(content ? content[module.value] : module.value).split(" ").length / 250;
250
+ const nrOfWords =
251
+ removeTags(content ? content[module.value] : module.value).split(
252
+ " "
253
+ ).length / 250;
243
254
  const minPerModule = Math.floor(nrOfWords);
244
255
  const secPerModule = Math.floor((nrOfWords % 1) * 60);
245
256
 
@@ -277,7 +288,7 @@ function processSearchData(data, fs, filename) {
277
288
  if (error) {
278
289
  console.log(
279
290
  chalk.magenta("info") +
280
- chalk.whiteBright(` Error writing search json file : ${error}`)
291
+ chalk.whiteBright(` Error writing search json file : ${error}`)
281
292
  );
282
293
  }
283
294
  }
@@ -316,7 +327,6 @@ export function processExtraFields(
316
327
  }
317
328
 
318
329
  function updatePlaceholders(page, data, translationsData) {
319
-
320
330
  page.title =
321
331
  page.title &&
322
332
  generatePlaceholderString(page.title, translationsData, {
@@ -328,21 +338,21 @@ function updatePlaceholders(page, data, translationsData) {
328
338
  page.meta_title &&
329
339
  generatePlaceholderString(page.meta_title, translationsData, {
330
340
  siteName: data.site_name,
331
- pageTitle: page.title
341
+ pageTitle: page.title,
332
342
  });
333
343
 
334
344
  page.meta_description =
335
345
  page.meta_description &&
336
346
  generatePlaceholderString(page.meta_description, translationsData, {
337
347
  siteName: data.site_name,
338
- pageTitle: page.title
348
+ pageTitle: page.title,
339
349
  });
340
350
  }
341
351
 
342
352
  export default {
343
353
  run(data, themeOptions, fs, translationsData, previewPageID = null) {
344
354
  const start = new Date();
345
- const transformedPages = transform(data);
355
+ const transformedPages = transform(data);
346
356
 
347
357
  const allResponsibleGaming = data.responsible_gamings || null;
348
358
  const generalData = data.general;
@@ -365,12 +375,11 @@ export default {
365
375
 
366
376
  const searchEnabled =
367
377
  themeOptions.searchEnabled !== undefined &&
368
- themeOptions.searchEnabled !== null
378
+ themeOptions.searchEnabled !== null
369
379
  ? themeOptions.searchEnabled
370
380
  : true;
371
381
 
372
382
  menus = data.menus;
373
-
374
383
  // Menu changes when there is a path prefix configured on hercules
375
384
  Object.keys(menus).forEach((menu) => {
376
385
  if (data?.site_markets[menus[menu]?.market]?.path_prefix !== null) {
@@ -380,7 +389,6 @@ export default {
380
389
  );
381
390
  }
382
391
  });
383
-
384
392
  Object.keys(data.site_markets).forEach((market) => {
385
393
  relations = data.relations;
386
394
  pages = transformedPages[market];
@@ -393,10 +401,12 @@ export default {
393
401
 
394
402
  Object.keys(transformedPages[market]).forEach((pageType) => {
395
403
  transformedPages[market][pageType].forEach((page, index) => {
404
+ // Check if it should build fuilters for this template
396
405
  const translations = translationsData
397
406
  ? translationsData[page.language]
398
407
  : {};
399
408
  // process page extra fields
409
+ //
400
410
  page.extra_fields &&
401
411
  processExtraFields(
402
412
  page.extra_fields,
@@ -404,7 +414,6 @@ export default {
404
414
  relations,
405
415
  data.content
406
416
  );
407
-
408
417
  updatePlaceholders(page, generalData, translations);
409
418
 
410
419
  // Set Affiliate relations
@@ -528,7 +537,7 @@ export default {
528
537
  extra_fields?.operator &&
529
538
  filterRelation(
530
539
  extra_fields?.operator,
531
- searchReleationPickKeys.operator
540
+ searchReleationPickKeys?.operator
532
541
  );
533
542
 
534
543
  const minimalPage = {
@@ -549,12 +558,14 @@ export default {
549
558
  cloneDeep({
550
559
  ...minimalPage,
551
560
  ...(filteredRelation && { relation: filteredRelation }),
552
- ...(filteredAuthorRelation && { author: filteredAuthorRelation }),
553
- ...operatorExtraFileds && {
561
+ ...(filteredAuthorRelation && {
562
+ author: filteredAuthorRelation,
563
+ }),
564
+ ...(operatorExtraFileds && {
554
565
  extra_fields: {
555
- operator: operatorExtraFileds
556
- }
557
- },
566
+ operator: operatorExtraFileds,
567
+ },
568
+ }),
558
569
  })
559
570
  );
560
571
  }
@@ -575,7 +586,6 @@ export default {
575
586
  const postSectionModules =
576
587
  data.market_sections[market][res].modules || [];
577
588
  postSectionModules.forEach((item) => {
578
-
579
589
  if (!page.sections.main) {
580
590
  return;
581
591
  }
@@ -590,7 +600,6 @@ export default {
590
600
  ModuleValue.VALUE_TYPE_PREFILLED_MODULE_MARKET,
591
601
  });
592
602
  } else {
593
-
594
603
  if (
595
604
  transformedPages[market][pageType][index].relation &&
596
605
  checkForInactiveOperatorToplist(
@@ -611,7 +620,6 @@ export default {
611
620
  });
612
621
  });
613
622
 
614
-
615
623
  // fill market sections
616
624
  if (data.market_sections[market]) {
617
625
  data.market_sections[market] = processSections(
@@ -626,7 +634,7 @@ export default {
626
634
  data.content
627
635
  );
628
636
  }
629
-
637
+
630
638
  // fill page sections
631
639
  if (transformedPages[market]) {
632
640
  Object.keys(transformedPages[market]).forEach((pageType) => {
@@ -637,7 +645,6 @@ export default {
637
645
  (page.sections && !previewPageID) ||
638
646
  (previewPageID && page.id === previewPageID)
639
647
  ) {
640
-
641
648
  transformedPages[market][pageType][index] = Object.assign(page, {
642
649
  sections: processSections(
643
650
  page.sections,
@@ -15,7 +15,12 @@ import {
15
15
  import { sanitizeOperatorData } from "./operators.mjs";
16
16
  import settings from "../constants/settings.mjs";
17
17
  import ModuleValue from "../constants/module-value.mjs";
18
- import { shiftFirstOperator, getModuleTitle, trailingSlash } from "../helpers/getters.mjs";
18
+ import {
19
+ shiftFirstOperator,
20
+ getModuleTitle,
21
+ trailingSlash,
22
+ } from "../helpers/getters.mjs";
23
+ import buildToplistFilter from "./build-toplist-filter.mjs";
19
24
 
20
25
  const pagesGroupedByTemplateId = [];
21
26
  const cardItems = {};
@@ -185,7 +190,7 @@ export function processCardsV2(
185
190
  // Populate pagesList if page type and template exists
186
191
  pagesList =
187
192
  !pagesGroupedByTemplateId[`${cardType}_${market}`] ||
188
- !pagesGroupedByTemplateId[`${cardType}_${market}`][pageTemplateId]
193
+ !pagesGroupedByTemplateId[`${cardType}_${market}`][pageTemplateId]
189
194
  ? []
190
195
  : pagesGroupedByTemplateId[`${cardType}_${market}`][pageTemplateId];
191
196
  } else {
@@ -277,7 +282,6 @@ export function processCardsV2(
277
282
  }
278
283
  }
279
284
 
280
-
281
285
  if (styleName !== "comparison_table") {
282
286
  const relationID = pagesMappedById[pageId]?.relation_id;
283
287
 
@@ -288,7 +292,6 @@ export function processCardsV2(
288
292
  }
289
293
  }
290
294
 
291
-
292
295
  if (
293
296
  styleName === "comparison_table" &&
294
297
  pageId !== null &&
@@ -303,7 +306,8 @@ export function processCardsV2(
303
306
  }
304
307
 
305
308
  // modify page so it doesn't have too much data
306
- module.items = module.items.map((item) => clonePageForCards(cloneDeep(item), module.style, content)
309
+ module.items = module.items.map((item) =>
310
+ clonePageForCards(cloneDeep(item), module.style, content)
307
311
  );
308
312
  }
309
313
 
@@ -328,19 +332,33 @@ export function processTopListModule(
328
332
  data,
329
333
  toplists
330
334
  ) {
335
+ const filterEnabled = module.style === "filter";
336
+ const filters = {
337
+ popular_filters: {
338
+ best_online: { items: [] },
339
+ crypto: { items: [] },
340
+ mobile_optimized: { items: [] },
341
+ best_live: { items: [] },
342
+ },
343
+ rating: {
344
+ 1: { items: [] },
345
+ 2: { items: [] },
346
+ 3: { items: [] },
347
+ 4: { items: [] },
348
+ 5: { items: [] },
349
+ },
350
+ game_categories: {},
351
+ deposit_methods: {},
352
+ withdrawal_method: {},
353
+ payout_time: {},
354
+ payout_rate: {},
355
+ licenses: {},
356
+ };
357
+
331
358
  module.items = module.items.map((listItem) => {
332
359
  const { type } = listItem;
333
- const showLoadMore = listItem.show_load_more || 0;
334
- const itemsCount = listItem.num_items_initial_load
335
- ? Number(listItem.num_items_initial_load)
336
- : 0;
337
-
338
- if (showLoadMore === 0 && itemsCount > 0) {
339
- listItem.items = listItem.items
340
- ? listItem.items.slice(0, itemsCount)
341
- : [];
342
- }
343
-
360
+ const showLoadMore = +listItem.show_load_more;
361
+ const itemsCount = +listItem.num_items_initial_load;
344
362
  if (listItem.id && toplists && toplists[listItem.id.toString()]) {
345
363
  listItem.market = toplists[listItem.id].market?.short_code;
346
364
  listItem.items = toplists[listItem.id].items;
@@ -348,74 +366,84 @@ export function processTopListModule(
348
366
  listItem.tracker = toplists[listItem.id].tracker;
349
367
  }
350
368
 
369
+ if (!showLoadMore && itemsCount) {
370
+ listItem.items = listItem.items?.slice(0, itemsCount);
371
+ }
372
+
351
373
  listItem.items = listItem.items
352
374
  ? listItem.items.map((item) => {
353
- const operatorRelation = cloneDeep(
354
- Object.values(relations.operator).find(
355
- (operator) =>
356
- operator.operator_id === item.operator_id &&
357
- operator.market === listItem.market &&
358
- type === operator.type
359
- )
360
- );
361
-
362
- if (operatorRelation) {
363
- operatorRelation.ribbons =
364
- item.ribbon_ids && item.ribbon_ids.length === 0
365
- ? operatorRelation.ribbons
366
- : item.ribbon_ids;
367
-
368
- operatorRelation.selling_points =
369
- item.selling_points && item.selling_points.length === 0
370
- ? operatorRelation.selling_points
371
- : item.selling_points;
372
- }
373
-
374
- operatorRelation.updated_at = item.updated_at;
375
- operatorRelation.toplist_bonus = item.bonus_name;
376
-
377
- const operatorPage =
378
- pages && pages.operator && operatorRelation
379
- ? pages.operator.filter(
380
- (page) =>
381
- page.relation &&
382
- page.relation.operator_id ===
383
- operatorRelation.operator_id &&
384
- page.relation.type === operatorRelation.type
375
+ const operatorRelation = cloneDeep(
376
+ Object.values(relations.operator).find(
377
+ (operator) =>
378
+ operator.operator_id === item.operator_id &&
379
+ operator.market === listItem.market &&
380
+ type === operator.type
385
381
  )
386
- : [];
387
-
388
- const reviewLink =
389
- process.env.DMS_REVIEW_LINKS_ENABLED === 'true'
390
- ? stripDomainAndLeadingSlash(operatorRelation?.review_link) || operatorPage[0]?.path
391
- : operatorPage[0]?.path;
392
-
393
- const authorTitle = operatorPage[0] && operatorPage[0]?.author?.author_title;
394
-
395
- const clone = sanitizeOperatorData(
396
- cloneDeep(operatorRelation),
397
- operatorPage,
398
- data,
399
- toplists && toplists[listItem.id].label
400
- );
401
-
402
- const socialAuthorLinks = [
403
- 'facebook_profile',
404
- 'twitter_profile',
405
- 'instagram_profile',
406
- 'linkedin_profile',
407
- ];
408
-
409
- return Object.assign(clone, {
410
- review_link: reviewLink,
411
- author_title: authorTitle,
412
- author_same_as: operatorPage[0] && operatorPage[0]?.author && socialAuthorLinks
413
- .map((socialLink) => operatorPage[0]?.author?.[socialLink])
414
- .filter((socialLink) => socialLink),
415
- });
416
- })
382
+ );
383
+
384
+ if (operatorRelation) {
385
+ operatorRelation.ribbons =
386
+ item.ribbon_ids && item.ribbon_ids.length === 0
387
+ ? operatorRelation.ribbons
388
+ : item.ribbon_ids;
389
+
390
+ operatorRelation.selling_points =
391
+ item.selling_points && item.selling_points.length === 0
392
+ ? operatorRelation.selling_points
393
+ : item.selling_points;
394
+ }
395
+
396
+ operatorRelation.updated_at = item.updated_at;
397
+ operatorRelation.toplist_bonus = item.bonus_name;
398
+
399
+ const operatorPage =
400
+ pages && pages.operator && operatorRelation
401
+ ? pages.operator.filter(
402
+ (page) =>
403
+ page.relation &&
404
+ page.relation.operator_id ===
405
+ operatorRelation.operator_id &&
406
+ page.relation.type === operatorRelation.type
407
+ )
408
+ : [];
409
+
410
+ const reviewLink =
411
+ process.env.DMS_REVIEW_LINKS_ENABLED === "true"
412
+ ? stripDomainAndLeadingSlash(operatorRelation?.review_link) ||
413
+ operatorPage[0]?.path
414
+ : operatorPage[0]?.path;
415
+
416
+ const authorTitle =
417
+ operatorPage[0] && operatorPage[0]?.author?.author_title;
418
+
419
+ const clone = sanitizeOperatorData(
420
+ cloneDeep(operatorRelation),
421
+ operatorPage,
422
+ data,
423
+ toplists && toplists[listItem.id].label
424
+ );
425
+
426
+ const socialAuthorLinks = [
427
+ "facebook_profile",
428
+ "twitter_profile",
429
+ "instagram_profile",
430
+ "linkedin_profile",
431
+ ];
432
+ if (filterEnabled) {
433
+ buildToplistFilter(filters, clone);
434
+ }
435
+ return Object.assign(clone, {
436
+ review_link: reviewLink,
437
+ author_title: authorTitle,
438
+ author_same_as:
439
+ operatorPage[0] &&
440
+ operatorPage[0]?.author &&
441
+ socialAuthorLinks
442
+ .map((socialLink) => operatorPage[0]?.author?.[socialLink])
443
+ .filter((socialLink) => socialLink),
444
+ });
445
+ })
417
446
  : [];
418
-
419
447
  const latestItems = listItem.items
420
448
  .map((toplist) => ({
421
449
  ...toplist,
@@ -441,10 +469,10 @@ export function processTopListModule(
441
469
  // eslint-disable-next-line no-restricted-globals
442
470
  latestUpdatedDate instanceof Date && !isNaN(latestUpdatedDate)
443
471
  ? new Intl.DateTimeFormat("en-US", {
444
- year: "numeric",
445
- month: "long",
446
- day: "numeric",
447
- }).format(latestUpdatedDate)
472
+ year: "numeric",
473
+ month: "long",
474
+ day: "numeric",
475
+ }).format(latestUpdatedDate)
448
476
  : null;
449
477
 
450
478
  listItem.latest_items = formattedLatestItems;
@@ -452,6 +480,8 @@ export function processTopListModule(
452
480
 
453
481
  return listItem;
454
482
  });
483
+
484
+ if (filterEnabled) module.filters = filters;
455
485
  }
456
486
 
457
487
  export function processContentModule(
@@ -523,7 +553,7 @@ export function processFaq(module = {}, content, relationData) {
523
553
  null,
524
554
  relationData
525
555
  )) ||
526
- item.question
556
+ item.question
527
557
  );
528
558
  item.answer = trailingSlash(
529
559
  (content && content[item.answer]) || item.answer