musora-content-services 1.0.105 → 1.0.108
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/.github/workflows/node.js.yml +0 -0
- package/CHANGELOG.md +6 -0
- package/README.md +0 -0
- package/babel.config.js +0 -0
- package/docs/config.js.html +2 -2
- package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/index.html +2 -2
- package/docs/module-Config.html +2 -2
- package/docs/module-Railcontent-Services.html +2 -2
- package/docs/module-Sanity-Services.html +393 -42
- package/docs/railcontent.js.html +2 -2
- package/docs/sanity.js.html +307 -86
- package/docs/scripts/collapse.js +0 -0
- package/docs/scripts/commonNav.js +0 -0
- package/docs/scripts/linenumber.js +0 -0
- package/docs/scripts/nav.js +0 -0
- package/docs/scripts/polyfill.js +0 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
- package/docs/scripts/prettify/lang-css.js +0 -0
- package/docs/scripts/prettify/prettify.js +0 -0
- package/docs/scripts/search.js +0 -0
- package/docs/styles/jsdoc.css +0 -0
- package/docs/styles/prettify.css +0 -0
- package/jest.config.js +0 -0
- package/jsdoc.json +0 -0
- package/package.json +1 -1
- package/src/contentTypeConfig.js +1331 -12
- package/src/filterBuilder.js +122 -0
- package/src/index.d.ts +0 -0
- package/src/index.js +0 -0
- package/src/services/config.js +0 -0
- package/src/services/railcontent.js +0 -0
- package/src/services/sanity.js +267 -87
- package/src/services/userContext.js +0 -0
- package/test/localStorageMock.js +0 -0
- package/test/log.js +0 -0
- package/test/sanityQueryService.test.js +222 -17
- package/test/userContext.test.js +0 -0
package/src/services/sanity.js
CHANGED
|
@@ -12,10 +12,13 @@ import {
|
|
|
12
12
|
filtersToGroq,
|
|
13
13
|
getUpcomingEventsTypes,
|
|
14
14
|
getNewReleasesTypes,
|
|
15
|
+
showsTypes,
|
|
16
|
+
contentMetadata
|
|
15
17
|
} from "../contentTypeConfig";
|
|
16
18
|
import {globalConfig} from "./config";
|
|
17
19
|
|
|
18
20
|
import { fetchAllCompletedStates, fetchCurrentSongComplete } from './railcontent.js';
|
|
21
|
+
import {arrayToStringRepresentation, FilterBuilder} from "../filterBuilder";
|
|
19
22
|
|
|
20
23
|
/**
|
|
21
24
|
* Fetch a song by its document ID from Sanity.
|
|
@@ -29,12 +32,15 @@ import { fetchAllCompletedStates, fetchCurrentSongComplete } from './railcontent
|
|
|
29
32
|
* .catch(error => console.error(error));
|
|
30
33
|
*/
|
|
31
34
|
export async function fetchSongById(documentId) {
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
const fields = getFieldsForContentType('song');
|
|
36
|
+
const filterParams = {};
|
|
37
|
+
const query = buildQuery(
|
|
38
|
+
`_type == "song" && railcontent_id == ${documentId}`,
|
|
39
|
+
filterParams,
|
|
40
|
+
fields,
|
|
41
|
+
{
|
|
42
|
+
isSingle: true,
|
|
43
|
+
});
|
|
38
44
|
return fetchSanity(query, false);
|
|
39
45
|
}
|
|
40
46
|
|
|
@@ -50,10 +56,11 @@ export async function fetchSongById(documentId) {
|
|
|
50
56
|
* .catch(error => console.error(error));
|
|
51
57
|
*/
|
|
52
58
|
export async function fetchArtists(brand) {
|
|
59
|
+
const filter = new FilterBuilder(`_type == "song" && brand == "${brand}" && references(^._id)`).buildFilter();
|
|
53
60
|
const query = `
|
|
54
61
|
*[_type == "artist"]{
|
|
55
62
|
name,
|
|
56
|
-
"lessonsCount": count(*[
|
|
63
|
+
"lessonsCount": count(*[${filter}])
|
|
57
64
|
}[lessonsCount > 0]`;
|
|
58
65
|
return fetchSanity(query, true);
|
|
59
66
|
}
|
|
@@ -252,25 +259,34 @@ export async function fetchWorkouts(brand) {
|
|
|
252
259
|
* @param {string} brand - The brand for which to fetch new releases.
|
|
253
260
|
* @returns {Promise<Object|null>} - The fetched new releases data or null if not found.
|
|
254
261
|
*/
|
|
255
|
-
export async function fetchNewReleases(brand, { page = 1, limit =
|
|
262
|
+
export async function fetchNewReleases(brand, { page = 1, limit = 20, sort="-published_on" } = {}) {
|
|
256
263
|
const newTypes = getNewReleasesTypes(brand);
|
|
257
|
-
const typesString =
|
|
264
|
+
const typesString = arrayToStringRepresentation(newTypes);
|
|
258
265
|
const start = (page - 1) * limit;
|
|
259
266
|
const end = start + limit;
|
|
260
267
|
const sortOrder = getSortOrder(sort);
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
268
|
+
const filter = `_type in ${typesString} && brand == '${brand}'`;
|
|
269
|
+
const fields = `
|
|
270
|
+
"id": railcontent_id,
|
|
271
|
+
title,
|
|
272
|
+
"image": thumbnail.asset->url,
|
|
273
|
+
"artist_name": instructor[0]->name,
|
|
274
|
+
"artists": instructor[]->name,
|
|
275
|
+
difficulty,
|
|
276
|
+
difficulty_string,
|
|
277
|
+
length_in_seconds,
|
|
278
|
+
published_on,
|
|
279
|
+
"type": _type,
|
|
280
|
+
web_url_path,`;
|
|
281
|
+
const filterParams = {};
|
|
282
|
+
const query = buildQuery(
|
|
283
|
+
filter,
|
|
284
|
+
filterParams,
|
|
285
|
+
fields,
|
|
286
|
+
{
|
|
287
|
+
sortOrder: sortOrder,
|
|
288
|
+
end: end,
|
|
289
|
+
});
|
|
274
290
|
return fetchSanity(query, true);
|
|
275
291
|
}
|
|
276
292
|
|
|
@@ -291,11 +307,11 @@ export async function fetchNewReleases(brand, { page = 1, limit = 10, sort="-pub
|
|
|
291
307
|
*/
|
|
292
308
|
export async function fetchUpcomingEvents(brand, { page = 1, limit = 10 } = {}) {
|
|
293
309
|
const liveTypes = getUpcomingEventsTypes(brand);
|
|
294
|
-
const typesString =
|
|
310
|
+
const typesString = arrayToStringRepresentation(liveTypes);
|
|
295
311
|
const now = getSanityDate(new Date());
|
|
296
312
|
const start = (page - 1) * limit;
|
|
297
313
|
const end = start + limit;
|
|
298
|
-
const
|
|
314
|
+
const fields = `
|
|
299
315
|
"id": railcontent_id,
|
|
300
316
|
title,
|
|
301
317
|
"image": thumbnail.asset->url,
|
|
@@ -306,8 +322,16 @@ export async function fetchUpcomingEvents(brand, { page = 1, limit = 10 } = {})
|
|
|
306
322
|
length_in_seconds,
|
|
307
323
|
published_on,
|
|
308
324
|
"type": _type,
|
|
309
|
-
web_url_path
|
|
310
|
-
|
|
325
|
+
web_url_path,`;
|
|
326
|
+
const query = buildRawQuery(
|
|
327
|
+
`_type in ${typesString} && brand == '${brand}' && published_on > '${now}' && status == 'scheduled'`,
|
|
328
|
+
fields,
|
|
329
|
+
{
|
|
330
|
+
sortOrder: 'published_on asc',
|
|
331
|
+
start: start,
|
|
332
|
+
end: end,
|
|
333
|
+
},
|
|
334
|
+
);
|
|
311
335
|
return fetchSanity(query, true);
|
|
312
336
|
}
|
|
313
337
|
|
|
@@ -354,6 +378,7 @@ export async function fetchScheduledReleases(brand, { page = 1, limit = 10 }) {
|
|
|
354
378
|
* Fetch content by a specific Railcontent ID.
|
|
355
379
|
*
|
|
356
380
|
* @param {string} id - The Railcontent ID of the content to fetch.
|
|
381
|
+
* @param {string} contentType - The document type of content to fetch
|
|
357
382
|
* @returns {Promise<Object|null>} - A promise that resolves to the content object or null if not found.
|
|
358
383
|
*
|
|
359
384
|
* @example
|
|
@@ -362,10 +387,16 @@ export async function fetchScheduledReleases(brand, { page = 1, limit = 10 }) {
|
|
|
362
387
|
* .catch(error => console.error(error));
|
|
363
388
|
*/
|
|
364
389
|
export async function fetchByRailContentId(id, contentType) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
390
|
+
|
|
391
|
+
const query = buildRawQuery(
|
|
392
|
+
`railcontent_id == ${id} && _type == '${contentType}'`,
|
|
393
|
+
getFieldsForContentType(contentType),
|
|
394
|
+
{
|
|
395
|
+
isSingle: true,
|
|
396
|
+
},
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
return fetchSanity(query, false);
|
|
369
400
|
}
|
|
370
401
|
|
|
371
402
|
/**
|
|
@@ -382,6 +413,7 @@ export async function fetchByRailContentId(id, contentType) {
|
|
|
382
413
|
*/
|
|
383
414
|
export async function fetchByRailContentIds(ids, contentType = undefined) {
|
|
384
415
|
const idsString = ids.join(',');
|
|
416
|
+
|
|
385
417
|
const query = `*[railcontent_id in [${idsString}]]{
|
|
386
418
|
${getFieldsForContentType(contentType)}
|
|
387
419
|
}`
|
|
@@ -437,6 +469,9 @@ export async function fetchAll(brand, type, {
|
|
|
437
469
|
const start = (page - 1) * limit;
|
|
438
470
|
const end = start + limit;
|
|
439
471
|
|
|
472
|
+
// Construct the type filter
|
|
473
|
+
const typeFilter = type ? `&& _type == '${type}'` : "";
|
|
474
|
+
|
|
440
475
|
// Construct the search filter
|
|
441
476
|
const searchFilter = searchTerm
|
|
442
477
|
? groupBy !== "" ?
|
|
@@ -465,8 +500,8 @@ export async function fetchAll(brand, type, {
|
|
|
465
500
|
let webUrlPath = 'artists';
|
|
466
501
|
query = `
|
|
467
502
|
{
|
|
468
|
-
"total": count(*[_type == '${groupBy}' && count(*[
|
|
469
|
-
"entity": *[_type == '${groupBy}' && count(*[
|
|
503
|
+
"total": count(*[_type == '${groupBy}' && count(*[brand == '${brand}' && ^._id == ${groupBy}._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]),
|
|
504
|
+
"entity": *[_type == '${groupBy}' && count(*[brand == '${brand}' && ^._id == ${groupBy}._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]
|
|
470
505
|
{
|
|
471
506
|
'id': _id,
|
|
472
507
|
'type': _type,
|
|
@@ -477,7 +512,7 @@ export async function fetchAll(brand, type, {
|
|
|
477
512
|
'lessons': *[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{
|
|
478
513
|
${fieldsString},
|
|
479
514
|
${groupBy}
|
|
480
|
-
}[0...
|
|
515
|
+
}[0...20]
|
|
481
516
|
}
|
|
482
517
|
|order(${sortOrder})
|
|
483
518
|
[${start}...${end}]
|
|
@@ -486,19 +521,19 @@ export async function fetchAll(brand, type, {
|
|
|
486
521
|
let webUrlPath = (groupBy == 'genre')?'/genres':'';
|
|
487
522
|
query = `
|
|
488
523
|
{
|
|
489
|
-
"total": count(*[_type == '${groupBy}' && count(*[
|
|
490
|
-
"entity": *[_type == '${groupBy}' && count(*[
|
|
524
|
+
"total": count(*[_type == '${groupBy}' && count(*[brand == '${brand}' && ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]),
|
|
525
|
+
"entity": *[_type == '${groupBy}' && count(*[brand == '${brand}' && ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]
|
|
491
526
|
{
|
|
492
527
|
'id': _id,
|
|
493
528
|
'type': _type,
|
|
494
529
|
name,
|
|
495
530
|
'head_shot_picture_url': thumbnail_url.asset->url,
|
|
496
531
|
'web_url_path': select(defined(web_url_path)=> web_url_path +'?included_fieds[]=type,${type}',!defined(web_url_path)=> '/${brand}${webUrlPath}/'+name+'/${webUrlPathType}'),
|
|
497
|
-
'all_lessons_count': count(*[
|
|
498
|
-
'lessons': *[
|
|
532
|
+
'all_lessons_count': count(*[brand == '${brand}' && ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id),
|
|
533
|
+
'lessons': *[brand == '${brand}' && ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{
|
|
499
534
|
${fieldsString},
|
|
500
535
|
${groupBy}
|
|
501
|
-
}[0...
|
|
536
|
+
}[0...20]
|
|
502
537
|
}
|
|
503
538
|
|order(${sortOrder})
|
|
504
539
|
[${start}...${end}]
|
|
@@ -506,10 +541,10 @@ export async function fetchAll(brand, type, {
|
|
|
506
541
|
} else {
|
|
507
542
|
query = `
|
|
508
543
|
{
|
|
509
|
-
"entity": *[
|
|
544
|
+
"entity": *[brand == "${brand}" ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}] | order(${sortOrder}) [${start}...${end}] {
|
|
510
545
|
${fieldsString},
|
|
511
546
|
},
|
|
512
|
-
"total": count(*[
|
|
547
|
+
"total": count(*[brand == "${brand}" ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}])
|
|
513
548
|
}
|
|
514
549
|
`;
|
|
515
550
|
}
|
|
@@ -617,8 +652,8 @@ export async function fetchChildren(railcontentId, contentType) {
|
|
|
617
652
|
${getFieldsForContentType(contentType)}
|
|
618
653
|
},
|
|
619
654
|
}[0..1]`;
|
|
620
|
-
let parent = await fetchSanity(query,
|
|
621
|
-
return parent[
|
|
655
|
+
let parent = await fetchSanity(query, false);
|
|
656
|
+
return parent['children'] ?? [];
|
|
622
657
|
}
|
|
623
658
|
|
|
624
659
|
/**
|
|
@@ -634,8 +669,8 @@ export async function fetchParentByRailContentId(railcontentId) {
|
|
|
634
669
|
})
|
|
635
670
|
])
|
|
636
671
|
}[0...1]`;
|
|
637
|
-
let child = await fetchSanity(query,
|
|
638
|
-
return child[
|
|
672
|
+
let child = await fetchSanity(query, false);
|
|
673
|
+
return child['parents'][0] ?? [];
|
|
639
674
|
}
|
|
640
675
|
|
|
641
676
|
/**
|
|
@@ -656,9 +691,16 @@ export async function fetchMethods(brand) {
|
|
|
656
691
|
* @returns {Promise<Object|null>} - The fetched foundation data or null if not found.
|
|
657
692
|
*/
|
|
658
693
|
export async function fetchFoundation(slug) {
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
694
|
+
const filterParams = {};
|
|
695
|
+
const query = buildQuery(
|
|
696
|
+
`_type == 'foundation' && slug.current == "${slug}"`,
|
|
697
|
+
filterParams,
|
|
698
|
+
getFieldsForContentType('foundation'),
|
|
699
|
+
{
|
|
700
|
+
sortOrder: 'published_on asc',
|
|
701
|
+
isSingle: true,
|
|
702
|
+
}
|
|
703
|
+
);
|
|
662
704
|
return fetchSanity(query, false);
|
|
663
705
|
}
|
|
664
706
|
|
|
@@ -761,7 +803,6 @@ export async function fetchMethodPreviousNextLesson(railcontentId, methodId) {
|
|
|
761
803
|
* @returns {Promise<Array<Object>|null>} - The fetched children data or null if not found.
|
|
762
804
|
*/
|
|
763
805
|
export async function fetchMethodChildrenIds(railcontentId) {
|
|
764
|
-
//TODO: Implement getByParentId include sum XP
|
|
765
806
|
const query = `*[_type == 'learning-path' && railcontent_id == ${railcontentId}]{
|
|
766
807
|
'children': child[]-> {
|
|
767
808
|
'id': railcontent_id,
|
|
@@ -774,7 +815,7 @@ export async function fetchMethodChildrenIds(railcontentId) {
|
|
|
774
815
|
}
|
|
775
816
|
}`;
|
|
776
817
|
let allChildren = await fetchSanity(query, false);
|
|
777
|
-
return getChildrenToDepth(allChildren, 4)
|
|
818
|
+
return getChildrenToDepth(allChildren, 4);
|
|
778
819
|
}
|
|
779
820
|
|
|
780
821
|
function getChildrenToDepth(parent, depth = 1)
|
|
@@ -823,8 +864,8 @@ export async function fetchNextPreviousLesson(railcontentId) {
|
|
|
823
864
|
* .catch(error => console.error(error));
|
|
824
865
|
*/
|
|
825
866
|
export async function fetchLessonContent(railContentId) {
|
|
826
|
-
|
|
827
|
-
|
|
867
|
+
const filterParams = {};
|
|
868
|
+
const fields = `title,
|
|
828
869
|
published_on,
|
|
829
870
|
"type":_type,
|
|
830
871
|
"resources": resource,
|
|
@@ -860,8 +901,19 @@ export async function fetchLessonContent(railContentId) {
|
|
|
860
901
|
},
|
|
861
902
|
${assignmentsField}
|
|
862
903
|
video,
|
|
863
|
-
length_in_seconds
|
|
864
|
-
|
|
904
|
+
length_in_seconds,
|
|
905
|
+
mp3_no_drums_no_click_url,
|
|
906
|
+
mp3_no_drums_yes_click_url,
|
|
907
|
+
mp3_yes_drums_no_click_url,
|
|
908
|
+
mp3_yes_drums_yes_click_url,`;
|
|
909
|
+
const query = buildQuery(
|
|
910
|
+
`railcontent_id == ${railContentId}`,
|
|
911
|
+
filterParams,
|
|
912
|
+
fields,
|
|
913
|
+
{
|
|
914
|
+
isSingle: true,
|
|
915
|
+
}
|
|
916
|
+
);
|
|
865
917
|
return fetchSanity(query, false);
|
|
866
918
|
}
|
|
867
919
|
|
|
@@ -920,10 +972,16 @@ export async function fetchRelatedMethodLessons(railContentId, brand) {
|
|
|
920
972
|
*/
|
|
921
973
|
export async function fetchAllPacks(brand, sort = "-published_on", searchTerm = "") {
|
|
922
974
|
const sortOrder = getSortOrder(sort);
|
|
923
|
-
|
|
924
|
-
const
|
|
925
|
-
|
|
926
|
-
|
|
975
|
+
const filter = `_type == 'pack' && brand == '${brand}' && title match "${searchTerm}*"`
|
|
976
|
+
const filterParams = {};
|
|
977
|
+
const query = buildQuery(
|
|
978
|
+
filter,
|
|
979
|
+
filterParams,
|
|
980
|
+
getFieldsForContentType('pack'),
|
|
981
|
+
{
|
|
982
|
+
sortOrder: sortOrder,
|
|
983
|
+
}
|
|
984
|
+
);
|
|
927
985
|
return fetchSanity(query, true);
|
|
928
986
|
}
|
|
929
987
|
|
|
@@ -933,11 +991,7 @@ export async function fetchAllPacks(brand, sort = "-published_on", searchTerm =
|
|
|
933
991
|
* @returns {Promise<Array<Object>|null>} - The fetched pack content data or null if not found.
|
|
934
992
|
*/
|
|
935
993
|
export async function fetchPackAll(railcontentId) {
|
|
936
|
-
|
|
937
|
-
const query = `*[railcontent_id == ${railcontentId}]{
|
|
938
|
-
${getFieldsForContentType('pack')}
|
|
939
|
-
} | order(published_on asc)[0...1]`
|
|
940
|
-
return fetchSanity(query, false);
|
|
994
|
+
return fetchByRailContentId(railcontentId, 'pack');
|
|
941
995
|
}
|
|
942
996
|
|
|
943
997
|
export async function fetchLiveEvent(brand) {
|
|
@@ -1013,7 +1067,7 @@ export async function fetchPackChildren(railcontentId) {
|
|
|
1013
1067
|
export async function fetchChallengeOverview(id) {
|
|
1014
1068
|
// WIP
|
|
1015
1069
|
const query = `*[railcontent_id == ${id}]{
|
|
1016
|
-
${getFieldsForContentType("challenge"
|
|
1070
|
+
${getFieldsForContentType("challenge")}
|
|
1017
1071
|
"lessons": child[]->{
|
|
1018
1072
|
"id": railcontent_id,
|
|
1019
1073
|
title,
|
|
@@ -1024,7 +1078,7 @@ export async function fetchChallengeOverview(id) {
|
|
|
1024
1078
|
difficulty,
|
|
1025
1079
|
"type": _type,
|
|
1026
1080
|
}
|
|
1027
|
-
}`;
|
|
1081
|
+
} [0...1]`;
|
|
1028
1082
|
return fetchSanity(query, false);
|
|
1029
1083
|
}
|
|
1030
1084
|
|
|
@@ -1044,18 +1098,21 @@ export async function fetchCoachLessons(brand, id, {
|
|
|
1044
1098
|
page = 1,
|
|
1045
1099
|
limit = 20,
|
|
1046
1100
|
} = {}) {
|
|
1047
|
-
const fieldsString =
|
|
1101
|
+
const fieldsString = getFieldsForContentType();
|
|
1048
1102
|
const start = (page - 1) * limit;
|
|
1049
1103
|
const end = start + limit;
|
|
1050
|
-
const searchFilter = searchTerm ? `&& title match "${searchTerm}*"`: ''
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1104
|
+
const searchFilter = searchTerm ? `&& title match "${searchTerm}*"`: ''
|
|
1105
|
+
const filter = `brand == '${brand}' ${searchFilter} && references(*[_type=='instructor' && railcontent_id == ${id}]._id)`;
|
|
1106
|
+
sortOrder = getSortOrder(sortOrder);
|
|
1107
|
+
const query = buildEntityAndTotalQuery(
|
|
1108
|
+
filter,
|
|
1109
|
+
fieldsString,
|
|
1110
|
+
{
|
|
1111
|
+
sortOrder: sortOrder,
|
|
1112
|
+
start: start,
|
|
1113
|
+
end: end,
|
|
1114
|
+
},
|
|
1115
|
+
);
|
|
1059
1116
|
return fetchSanity(query, true);
|
|
1060
1117
|
}
|
|
1061
1118
|
|
|
@@ -1070,10 +1127,7 @@ export async function fetchCoachLessons(brand, id, {
|
|
|
1070
1127
|
* .catch(error => console.error(error));
|
|
1071
1128
|
*/
|
|
1072
1129
|
export async function fetchCourseOverview(id) {
|
|
1073
|
-
|
|
1074
|
-
${getFieldsForContentType("course", true)}
|
|
1075
|
-
}`
|
|
1076
|
-
return fetchSanity(query, false);
|
|
1130
|
+
return fetchByRailContentId(id, 'course');
|
|
1077
1131
|
}
|
|
1078
1132
|
|
|
1079
1133
|
/**
|
|
@@ -1094,21 +1148,23 @@ export async function fetchByReference(brand, {
|
|
|
1094
1148
|
limit = 20,
|
|
1095
1149
|
includedFields = [],
|
|
1096
1150
|
} = {}) {
|
|
1097
|
-
const fieldsString =
|
|
1151
|
+
const fieldsString = getFieldsForContentType();
|
|
1098
1152
|
const start = (page - 1) * limit;
|
|
1099
1153
|
const end = start + limit;
|
|
1100
1154
|
const searchFilter = searchTerm ? `&& title match "${searchTerm}*"`: '';
|
|
1101
1155
|
const includedFieldsFilter = includedFields.length > 0
|
|
1102
1156
|
? includedFields.join(' && ')
|
|
1103
1157
|
: "";
|
|
1104
|
-
|
|
1105
|
-
const query =
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1158
|
+
const filter = `brand == '${brand}' ${searchFilter} && references(*[${includedFieldsFilter}]._id)`;
|
|
1159
|
+
const query = buildEntityAndTotalQuery(
|
|
1160
|
+
filter,
|
|
1161
|
+
fieldsString,
|
|
1162
|
+
{
|
|
1163
|
+
sortOrder: getSortOrder(sortOrder),
|
|
1164
|
+
start: start,
|
|
1165
|
+
end: end,
|
|
1166
|
+
},
|
|
1167
|
+
);
|
|
1112
1168
|
return fetchSanity(query, true);
|
|
1113
1169
|
}
|
|
1114
1170
|
|
|
@@ -1273,6 +1329,48 @@ export async function fetchCatalogMetadata(contentType)
|
|
|
1273
1329
|
return fetchSanity(query, false);
|
|
1274
1330
|
}
|
|
1275
1331
|
|
|
1332
|
+
/**
|
|
1333
|
+
* Fetch shows data for a brand.
|
|
1334
|
+
*
|
|
1335
|
+
* @param brand - The brand for which to fetch shows.
|
|
1336
|
+
* @returns {Promise<[]>}
|
|
1337
|
+
*
|
|
1338
|
+
* @example
|
|
1339
|
+
*
|
|
1340
|
+
* fetchShowsData('drumeo')
|
|
1341
|
+
* .then(data => console.log(data))
|
|
1342
|
+
* .catch(error => console.error(error));
|
|
1343
|
+
*/
|
|
1344
|
+
export async function fetchShowsData(brand) {
|
|
1345
|
+
let shows = showsTypes[brand] ?? [];
|
|
1346
|
+
const showsInfo = [];
|
|
1347
|
+
|
|
1348
|
+
shows.forEach(type => {
|
|
1349
|
+
const processedData = processMetadata(brand, type);
|
|
1350
|
+
if (processedData) showsInfo.push(processedData)
|
|
1351
|
+
});
|
|
1352
|
+
|
|
1353
|
+
return showsInfo;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
/**
|
|
1357
|
+
* Fetch metadata from the contentTypeConfig.js based on brand and type.
|
|
1358
|
+
*
|
|
1359
|
+
* @param {string} brand - The brand for which to fetch metadata.
|
|
1360
|
+
* @param {string} type - The type for which to fetch metadata.
|
|
1361
|
+
* @returns {Promise<{name, description, type: *, thumbnailUrl}>}
|
|
1362
|
+
*
|
|
1363
|
+
* @example
|
|
1364
|
+
*
|
|
1365
|
+
* fetchMetadata('drumeo','song')
|
|
1366
|
+
* .then(data => console.log(data))
|
|
1367
|
+
* .catch(error => console.error(error));
|
|
1368
|
+
*/
|
|
1369
|
+
export async function fetchMetadata(brand, type) {
|
|
1370
|
+
const processedData = processMetadata(brand, type, true);
|
|
1371
|
+
return processedData ? processedData : {};
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1276
1374
|
|
|
1277
1375
|
//Helper Functions
|
|
1278
1376
|
function arrayJoinWithQuotes(array, delimiter = ',') {
|
|
@@ -1312,3 +1410,85 @@ function checkSanityConfig(config) {
|
|
|
1312
1410
|
}
|
|
1313
1411
|
|
|
1314
1412
|
|
|
1413
|
+
function buildRawQuery(
|
|
1414
|
+
filter = '',
|
|
1415
|
+
fields = '...',
|
|
1416
|
+
{
|
|
1417
|
+
sortOrder = 'published_on desc',
|
|
1418
|
+
start = 0,
|
|
1419
|
+
end = 10,
|
|
1420
|
+
isSingle = false,
|
|
1421
|
+
}
|
|
1422
|
+
) {
|
|
1423
|
+
const sortString = sortOrder ? `order(${sortOrder})` : '';
|
|
1424
|
+
const countString = isSingle ? '[0...1]' : `[${start}...${end}]`;
|
|
1425
|
+
const query = `*[${filter}]{
|
|
1426
|
+
${fields}
|
|
1427
|
+
} | ${sortString}${countString}`
|
|
1428
|
+
return query;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
function buildQuery(
|
|
1433
|
+
baseFilter = '',
|
|
1434
|
+
filterParams = {},
|
|
1435
|
+
fields = '...',
|
|
1436
|
+
{
|
|
1437
|
+
sortOrder = 'published_on desc',
|
|
1438
|
+
start = 0,
|
|
1439
|
+
end = 10,
|
|
1440
|
+
isSingle = false,
|
|
1441
|
+
},
|
|
1442
|
+
) {
|
|
1443
|
+
const filter = new FilterBuilder(baseFilter, filterParams).buildFilter();
|
|
1444
|
+
return buildRawQuery(filter, fields, {sortOrder, start, end, isSingle});
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
function buildEntityAndTotalQuery(
|
|
1448
|
+
filter = '',
|
|
1449
|
+
fields = '...',
|
|
1450
|
+
{
|
|
1451
|
+
sortOrder = 'published_on desc',
|
|
1452
|
+
start = 0,
|
|
1453
|
+
end = 10,
|
|
1454
|
+
isSingle = false,
|
|
1455
|
+
},
|
|
1456
|
+
) {
|
|
1457
|
+
const sortString = sortOrder ? `order(${sortOrder})` : '';
|
|
1458
|
+
const countString = isSingle ? '[0...1]' : `[${start}...${end}]`;
|
|
1459
|
+
const query = `{
|
|
1460
|
+
"entity": *[${filter}] | ${sortString}${countString}
|
|
1461
|
+
{
|
|
1462
|
+
${fields}
|
|
1463
|
+
},
|
|
1464
|
+
"total": count(*[${filter}])
|
|
1465
|
+
}`;
|
|
1466
|
+
return query;
|
|
1467
|
+
}
|
|
1468
|
+
function processMetadata(brand, type, withFilters = false) {
|
|
1469
|
+
const metadataElement = contentMetadata[brand]?.[type];
|
|
1470
|
+
if (!metadataElement) {
|
|
1471
|
+
return null;
|
|
1472
|
+
}
|
|
1473
|
+
const processedData = {
|
|
1474
|
+
type,
|
|
1475
|
+
thumbnailUrl: metadataElement.thumbnailUrl || null,
|
|
1476
|
+
name: metadataElement.name || null,
|
|
1477
|
+
description: metadataElement.description || null
|
|
1478
|
+
};
|
|
1479
|
+
|
|
1480
|
+
if (withFilters) {
|
|
1481
|
+
Object.keys(metadataElement).forEach(key => {
|
|
1482
|
+
if ( !['thumbnailUrl', 'name', 'description'].includes(key) ) {
|
|
1483
|
+
processedData[key] = metadataElement[key];
|
|
1484
|
+
}
|
|
1485
|
+
});
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
return processedData;
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
|
|
1492
|
+
|
|
1493
|
+
|
|
1494
|
+
|
|
File without changes
|
package/test/localStorageMock.js
CHANGED
|
File without changes
|
package/test/log.js
CHANGED
|
File without changes
|