musora-content-services 2.28.6 → 2.30.0
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 +38 -0
- package/link_mcs.sh +0 -0
- package/package.json +1 -1
- package/src/contentTypeConfig.js +69 -50
- package/src/services/config.js +0 -6
- package/src/services/content-org/playlists-types.js +10 -0
- package/src/services/content-org/playlists.js +14 -14
- package/src/services/content.js +8 -9
- package/src/services/contentAggregator.js +45 -7
- package/src/services/contentProgress.js +67 -0
- package/src/services/gamification/awards.js +52 -33
- package/src/services/gamification/types.js +5 -23
- package/src/services/railcontent.js +25 -36
- package/src/services/recommendations.js +20 -18
- package/src/services/sanity.js +27 -57
- package/src/services/types.js +0 -8
- package/src/services/userActivity.js +340 -419
- package/test/initializeTests.js +0 -4
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { globalConfig } from './config.js'
|
|
5
5
|
import { fetchJSONHandler } from '../lib/httpHelper.js'
|
|
6
|
-
import { convertToTimeZone } from './dateUtils.js';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Exported functions that are excluded from index generation.
|
|
@@ -285,7 +284,7 @@ async function postDataHandler(url, data) {
|
|
|
285
284
|
}
|
|
286
285
|
|
|
287
286
|
async function patchDataHandler_depreciated(url, data) {
|
|
288
|
-
throw Error(
|
|
287
|
+
throw Error('PATCH verb throws a CORS error on the FEW. Use PATCH instead')
|
|
289
288
|
}
|
|
290
289
|
|
|
291
290
|
async function putDataHandler(url, data) {
|
|
@@ -296,8 +295,8 @@ async function deleteDataHandler(url, data) {
|
|
|
296
295
|
return fetchHandler(url, 'delete')
|
|
297
296
|
}
|
|
298
297
|
|
|
299
|
-
export async function fetchLikeCount(contendId){
|
|
300
|
-
const url
|
|
298
|
+
export async function fetchLikeCount(contendId) {
|
|
299
|
+
const url = `/api/content/v1/content/like_count/${contendId}`
|
|
301
300
|
return await fetchDataHandler(url)
|
|
302
301
|
}
|
|
303
302
|
|
|
@@ -584,40 +583,36 @@ export async function fetchComment(commentId) {
|
|
|
584
583
|
}
|
|
585
584
|
|
|
586
585
|
export async function fetchUserPractices(currentVersion = 0, { userId } = {}) {
|
|
587
|
-
const params = new URLSearchParams()
|
|
588
|
-
if (userId) params.append('user_id', userId)
|
|
589
|
-
const query = params.toString() ? `?${params.toString()}` : ''
|
|
590
|
-
const url = `/api/user/practices/v1/practices${query}
|
|
591
|
-
const response = await fetchDataHandler(url, currentVersion)
|
|
592
|
-
const { data, version } = response
|
|
593
|
-
const userPractices = data
|
|
594
|
-
if(!userPractices
|
|
595
|
-
return { data: { practices: {} }, version }
|
|
586
|
+
const params = new URLSearchParams()
|
|
587
|
+
if (userId) params.append('user_id', userId)
|
|
588
|
+
const query = params.toString() ? `?${params.toString()}` : ''
|
|
589
|
+
const url = `/api/user/practices/v1/practices${query}`
|
|
590
|
+
const response = await fetchDataHandler(url, currentVersion)
|
|
591
|
+
const { data, version } = response
|
|
592
|
+
const userPractices = data
|
|
593
|
+
if (!userPractices) {
|
|
594
|
+
return { data: { practices: {} }, version }
|
|
596
595
|
}
|
|
597
596
|
|
|
598
|
-
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
599
|
-
|
|
600
597
|
const formattedPractices = userPractices.reduce((acc, practice) => {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
if (!acc[userTimeZoneDay]) {
|
|
604
|
-
acc[userTimeZoneDay] = [];
|
|
598
|
+
if (!acc[practice.day]) {
|
|
599
|
+
acc[practice.day] = []
|
|
605
600
|
}
|
|
606
601
|
|
|
607
|
-
acc[
|
|
602
|
+
acc[practice.day].push({
|
|
608
603
|
id: practice.id,
|
|
609
604
|
duration_seconds: practice.duration_seconds,
|
|
610
|
-
})
|
|
605
|
+
})
|
|
611
606
|
|
|
612
|
-
return acc
|
|
613
|
-
}, {})
|
|
607
|
+
return acc
|
|
608
|
+
}, {})
|
|
614
609
|
|
|
615
610
|
return {
|
|
616
611
|
data: {
|
|
617
612
|
practices: formattedPractices,
|
|
618
613
|
},
|
|
619
614
|
version,
|
|
620
|
-
}
|
|
615
|
+
}
|
|
621
616
|
}
|
|
622
617
|
|
|
623
618
|
export async function logUserPractice(practiceDetails) {
|
|
@@ -628,11 +623,11 @@ export async function fetchUserPracticeMeta(practiceIds, userId = null) {
|
|
|
628
623
|
if (practiceIds.length == 0) {
|
|
629
624
|
return []
|
|
630
625
|
}
|
|
631
|
-
const params = new URLSearchParams()
|
|
632
|
-
practiceIds.forEach(id => params.append('practice_ids[]', id))
|
|
626
|
+
const params = new URLSearchParams()
|
|
627
|
+
practiceIds.forEach((id) => params.append('practice_ids[]', id))
|
|
633
628
|
|
|
634
629
|
if (userId !== null) {
|
|
635
|
-
params.append('user_id', userId)
|
|
630
|
+
params.append('user_id', userId)
|
|
636
631
|
}
|
|
637
632
|
const url = `/api/user/practices/v1/practices?${params.toString()}`
|
|
638
633
|
return await fetchHandler(url, 'GET', null)
|
|
@@ -653,7 +648,6 @@ export async function fetchUserPracticeNotes(date) {
|
|
|
653
648
|
return await fetchHandler(url, 'GET', null)
|
|
654
649
|
}
|
|
655
650
|
|
|
656
|
-
|
|
657
651
|
/**
|
|
658
652
|
* Get the id and slug of last interacted child. Only valid for certain content types
|
|
659
653
|
*
|
|
@@ -674,8 +668,8 @@ export async function fetchUserPracticeNotes(date) {
|
|
|
674
668
|
* }
|
|
675
669
|
*/
|
|
676
670
|
export async function fetchLastInteractedChild(content_ids) {
|
|
677
|
-
const params = new URLSearchParams()
|
|
678
|
-
content_ids.forEach(id => params.append('content_ids[]', id))
|
|
671
|
+
const params = new URLSearchParams()
|
|
672
|
+
content_ids.forEach((id) => params.append('content_ids[]', id))
|
|
679
673
|
const url = `/api/content/v1/user/last_interacted_child?${params.toString()}`
|
|
680
674
|
return await fetchHandler(url, 'GET', null)
|
|
681
675
|
}
|
|
@@ -708,18 +702,13 @@ export async function fetchLastInteractedChild(content_ids) {
|
|
|
708
702
|
* .then(activities => console.log(activities))
|
|
709
703
|
* .catch(error => console.error(error));
|
|
710
704
|
*/
|
|
711
|
-
export async function fetchRecentUserActivities({
|
|
712
|
-
page = 1,
|
|
713
|
-
limit = 5,
|
|
714
|
-
tabName = null
|
|
715
|
-
} = {}) {
|
|
705
|
+
export async function fetchRecentUserActivities({ page = 1, limit = 5, tabName = null } = {}) {
|
|
716
706
|
let pageAndLimit = `?page=${page}&limit=${limit}`
|
|
717
707
|
let tabParam = tabName ? `&tabName=${tabName}` : ''
|
|
718
708
|
const url = `/api/user-management-system/v1/activities/all${pageAndLimit}${tabParam}`
|
|
719
709
|
return await fetchHandler(url, 'GET', null)
|
|
720
710
|
}
|
|
721
711
|
|
|
722
|
-
|
|
723
712
|
function fetchAbsolute(url, params) {
|
|
724
713
|
if (globalConfig.sessionConfig.authToken) {
|
|
725
714
|
params.headers['Authorization'] = `Bearer ${globalConfig.sessionConfig.authToken}`
|
|
@@ -12,6 +12,8 @@ import { HttpClient } from '../infrastructure/http/HttpClient'
|
|
|
12
12
|
*/
|
|
13
13
|
const excludeFromGeneratedIndex = []
|
|
14
14
|
|
|
15
|
+
const baseURL = 'https://recommender.musora.com'
|
|
16
|
+
|
|
15
17
|
/**
|
|
16
18
|
* Fetches similar content to the provided content id
|
|
17
19
|
*
|
|
@@ -36,10 +38,7 @@ export async function fetchSimilarItems(content_id, brand, count = 10) {
|
|
|
36
38
|
}
|
|
37
39
|
const url = `/similar_items/`
|
|
38
40
|
try {
|
|
39
|
-
const httpClient = new HttpClient(
|
|
40
|
-
globalConfig.recommendationsConfig.baseUrl,
|
|
41
|
-
globalConfig.recommendationsConfig.token
|
|
42
|
-
)
|
|
41
|
+
const httpClient = new HttpClient(baseURL)
|
|
43
42
|
const response = await httpClient.post(url, data)
|
|
44
43
|
// we requested count + 1 then filtered out the extra potential value, so we need slice to the correct size if necessary
|
|
45
44
|
return response['similar_items'].filter((item) => item !== content_id).slice(0, count)
|
|
@@ -75,23 +74,29 @@ export async function rankCategories(brand, categories) {
|
|
|
75
74
|
}
|
|
76
75
|
const url = `/rank_each_list/`
|
|
77
76
|
try {
|
|
78
|
-
const httpClient = new HttpClient(
|
|
79
|
-
globalConfig.recommendationsConfig.baseUrl,
|
|
80
|
-
globalConfig.recommendationsConfig.token
|
|
81
|
-
)
|
|
77
|
+
const httpClient = new HttpClient(baseURL)
|
|
82
78
|
const response = await httpClient.post(url, data)
|
|
83
79
|
let rankedCategories = []
|
|
84
80
|
|
|
85
81
|
for (const rankedPlaylist of response['ranked_playlists']) {
|
|
86
82
|
rankedCategories.push({
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
slug: rankedPlaylist.playlist_id,
|
|
84
|
+
items: rankedPlaylist.ranked_items,
|
|
89
85
|
})
|
|
90
86
|
}
|
|
91
87
|
return rankedCategories
|
|
92
88
|
} catch (error) {
|
|
93
|
-
console.error('
|
|
94
|
-
|
|
89
|
+
console.error('RankCategories fetch error:', error)
|
|
90
|
+
const defaultSorting = []
|
|
91
|
+
for (const slug in categories) {
|
|
92
|
+
defaultSorting.push(
|
|
93
|
+
{
|
|
94
|
+
slug: slug,
|
|
95
|
+
items: categories[slug],
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
return defaultSorting
|
|
95
100
|
}
|
|
96
101
|
}
|
|
97
102
|
|
|
@@ -117,15 +122,12 @@ export async function rankItems(brand, content_ids) {
|
|
|
117
122
|
}
|
|
118
123
|
const url = `/rank_items/`
|
|
119
124
|
try {
|
|
120
|
-
const httpClient = new HttpClient(
|
|
121
|
-
globalConfig.recommendationsConfig.baseUrl,
|
|
122
|
-
globalConfig.recommendationsConfig.token
|
|
123
|
-
)
|
|
125
|
+
const httpClient = new HttpClient(baseURL)
|
|
124
126
|
const response = await httpClient.post(url, data)
|
|
125
127
|
return response['ranked_content_ids']
|
|
126
128
|
} catch (error) {
|
|
127
|
-
console.error('
|
|
128
|
-
return
|
|
129
|
+
console.error('rankItems fetch error:', error)
|
|
130
|
+
return content_ids
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
133
|
|
package/src/services/sanity.js
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
showsTypes,
|
|
17
17
|
getNewReleasesTypes,
|
|
18
18
|
coachLessonsTypes,
|
|
19
|
+
getFieldsForContentTypeWithFilteredChildren,
|
|
19
20
|
getChildFieldsForContentType,
|
|
20
21
|
SONG_TYPES,
|
|
21
22
|
} from '../contentTypeConfig.js'
|
|
@@ -75,7 +76,7 @@ export async function fetchSongById(documentId) {
|
|
|
75
76
|
*/
|
|
76
77
|
export async function fetchLeaving(brand, { pageNumber = 1, contentPerPage = 20 } = {}) {
|
|
77
78
|
const today = new Date()
|
|
78
|
-
const isoDateOnly = today
|
|
79
|
+
const isoDateOnly = getDateOnly(today)
|
|
79
80
|
const filterString = `brand == '${brand}' && quarter_removed > '${isoDateOnly}'`
|
|
80
81
|
const startEndOrder = getQueryFromPage(pageNumber, contentPerPage)
|
|
81
82
|
const sortOrder = {
|
|
@@ -102,7 +103,7 @@ export async function fetchLeaving(brand, { pageNumber = 1, contentPerPage = 20
|
|
|
102
103
|
*/
|
|
103
104
|
export async function fetchReturning(brand, { pageNumber = 1, contentPerPage = 20 } = {}) {
|
|
104
105
|
const today = new Date()
|
|
105
|
-
const isoDateOnly = today
|
|
106
|
+
const isoDateOnly = getDateOnly(today)
|
|
106
107
|
const filterString = `brand == '${brand}' && quarter_published >= '${isoDateOnly}'`
|
|
107
108
|
const startEndOrder = getQueryFromPage(pageNumber, contentPerPage)
|
|
108
109
|
const sortOrder = {
|
|
@@ -159,41 +160,6 @@ function getQueryFromPage(pageNumber, contentPerPage) {
|
|
|
159
160
|
return result
|
|
160
161
|
}
|
|
161
162
|
|
|
162
|
-
/**
|
|
163
|
-
* returns array of next and previous quarter dates as strings
|
|
164
|
-
*
|
|
165
|
-
* @returns {string[]}
|
|
166
|
-
*/
|
|
167
|
-
function getNextAndPreviousQuarterDates() {
|
|
168
|
-
const january = 1
|
|
169
|
-
const april = 4
|
|
170
|
-
const july = 7
|
|
171
|
-
const october = 10
|
|
172
|
-
const month = new Date().getMonth()
|
|
173
|
-
let year = new Date().getFullYear()
|
|
174
|
-
let nextQuarter = ''
|
|
175
|
-
let prevQuarter = ''
|
|
176
|
-
if (month < april) {
|
|
177
|
-
nextQuarter = `${year}-0${april}-01`
|
|
178
|
-
prevQuarter = `${year}-0${january}-01`
|
|
179
|
-
} else if (month < july) {
|
|
180
|
-
nextQuarter = `${year}-0${july}-01`
|
|
181
|
-
prevQuarter = `${year}-0${april}-01`
|
|
182
|
-
} else if (month < october) {
|
|
183
|
-
nextQuarter = `${year}-${october}-01`
|
|
184
|
-
prevQuarter = `${year}-0${july}-01`
|
|
185
|
-
} else {
|
|
186
|
-
prevQuarter = `${year}-${october}-01`
|
|
187
|
-
year++
|
|
188
|
-
nextQuarter = `${year}-0${january}-01`
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
let result = []
|
|
192
|
-
result['next'] = nextQuarter
|
|
193
|
-
result['previous'] = prevQuarter
|
|
194
|
-
return result
|
|
195
|
-
}
|
|
196
|
-
|
|
197
163
|
/**
|
|
198
164
|
* Fetch all artists with lessons available for a specific brand.
|
|
199
165
|
*
|
|
@@ -350,8 +316,8 @@ export async function fetchNewReleases(
|
|
|
350
316
|
const start = (page - 1) * limit
|
|
351
317
|
const end = start + limit
|
|
352
318
|
const sortOrder = getSortOrder(sort, brand)
|
|
353
|
-
const
|
|
354
|
-
const filter = `_type in ${typesString} && brand == '${brand}' && status == 'published' && show_in_new_feed == true &&
|
|
319
|
+
const now = getDateOnly()
|
|
320
|
+
const filter = `_type in ${typesString} && brand == '${brand}' && (status == 'published' && show_in_new_feed == true && published_on <= '${now}')`
|
|
355
321
|
const fields = `
|
|
356
322
|
"id": railcontent_id,
|
|
357
323
|
title,
|
|
@@ -367,12 +333,7 @@ export async function fetchNewReleases(
|
|
|
367
333
|
web_url_path,
|
|
368
334
|
"permission_id": permission[]->railcontent_id,
|
|
369
335
|
`
|
|
370
|
-
const
|
|
371
|
-
const query = await buildQuery(filter, filterParams, fields, {
|
|
372
|
-
sortOrder: sortOrder,
|
|
373
|
-
start,
|
|
374
|
-
end: end,
|
|
375
|
-
})
|
|
336
|
+
const query = buildRawQuery(filter, fields, {sortOrder: sortOrder, start, end: end})
|
|
376
337
|
return fetchSanity(query, true)
|
|
377
338
|
}
|
|
378
339
|
|
|
@@ -477,12 +438,12 @@ export async function fetchScheduledReleases(brand, { page = 1, limit = 10 }) {
|
|
|
477
438
|
* .catch(error => console.error(error));
|
|
478
439
|
*/
|
|
479
440
|
export async function fetchByRailContentId(id, contentType) {
|
|
480
|
-
const fields =
|
|
481
|
-
const
|
|
441
|
+
const fields = await getFieldsForContentTypeWithFilteredChildren(contentType)
|
|
442
|
+
const lessonFields = getChildFieldsForContentType(contentType)
|
|
482
443
|
const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
|
|
483
444
|
const entityFieldsString = ` ${fields}
|
|
484
445
|
'child_count': coalesce(count(child[${childrenFilter}]->), 0) ,
|
|
485
|
-
"lessons": child[${childrenFilter}]->{${
|
|
446
|
+
"lessons": child[${childrenFilter}]->{${lessonFields}},
|
|
486
447
|
'length_in_seconds': coalesce(
|
|
487
448
|
math::sum(
|
|
488
449
|
select(
|
|
@@ -519,17 +480,19 @@ export async function fetchByRailContentIds(ids, contentType = undefined, brand
|
|
|
519
480
|
if (!ids?.length) {
|
|
520
481
|
return []
|
|
521
482
|
}
|
|
483
|
+
ids = [...new Set(ids.filter(item => item !== null && item !== undefined))];
|
|
522
484
|
const idsString = ids.join(',')
|
|
523
485
|
const brandFilter = brand ? ` && brand == "${brand}"` : ''
|
|
524
|
-
const
|
|
486
|
+
const lessonCountFilter = await new FilterBuilder(`_id in ^.child[]._ref`, {pullFutureContent: true}).buildFilter()
|
|
487
|
+
const fields = await getFieldsForContentTypeWithFilteredChildren(contentType, true)
|
|
525
488
|
const query = `*[
|
|
526
489
|
railcontent_id in [${idsString}]${brandFilter}
|
|
527
490
|
]{
|
|
528
|
-
${
|
|
491
|
+
${fields}
|
|
492
|
+
'lesson_count': coalesce(count(*[${lessonCountFilter}]), 0),
|
|
529
493
|
live_event_start_time,
|
|
530
494
|
live_event_end_time,
|
|
531
495
|
}`
|
|
532
|
-
|
|
533
496
|
const customPostProcess = (results) => {
|
|
534
497
|
const now = getSanityDate(new Date(), false);
|
|
535
498
|
const liveProcess = (result) => {
|
|
@@ -555,7 +518,7 @@ export async function fetchByRailContentIds(ids, contentType = undefined, brand
|
|
|
555
518
|
}
|
|
556
519
|
|
|
557
520
|
// Sort results to match the order of the input IDs
|
|
558
|
-
const sortedResults = results
|
|
521
|
+
const sortedResults = results?.sort(sortFuction) ?? null
|
|
559
522
|
|
|
560
523
|
return sortedResults
|
|
561
524
|
}
|
|
@@ -565,6 +528,7 @@ export async function fetchContentRows(brand, pageName, contentRowSlug)
|
|
|
565
528
|
if (pageName === 'lessons') pageName = 'lesson'
|
|
566
529
|
if (pageName === 'songs') pageName = 'song'
|
|
567
530
|
const rowString = contentRowSlug ? ` && slug.current == "${contentRowSlug.toLowerCase()}"` : ''
|
|
531
|
+
const lessonCountFilter = await new FilterBuilder(`_id in ^.child[]._ref`, {pullFutureContent: true}).buildFilter()
|
|
568
532
|
const childFilter = await new FilterBuilder('', {isChildrenFilter: true}).buildFilter()
|
|
569
533
|
const query = `*[_type == 'recommended-content-row' && brand == '${brand}' && type == '${pageName}'${rowString}]{
|
|
570
534
|
brand,
|
|
@@ -573,6 +537,7 @@ export async function fetchContentRows(brand, pageName, contentRowSlug)
|
|
|
573
537
|
'content': content[${childFilter}]->{
|
|
574
538
|
'children': child[${childFilter}]->{ 'id': railcontent_id, 'children': child[${childFilter}]->{'id': railcontent_id}, },
|
|
575
539
|
${getFieldsForContentType('tab-data')}
|
|
540
|
+
'lesson_count': coalesce(count(*[${lessonCountFilter}]), 0),
|
|
576
541
|
},
|
|
577
542
|
}`
|
|
578
543
|
return fetchSanity(query, true)
|
|
@@ -1172,19 +1137,17 @@ export async function fetchLessonContent(railContentId) {
|
|
|
1172
1137
|
const query = await buildQuery(`railcontent_id == ${railContentId}`, filterParams, fields, {
|
|
1173
1138
|
isSingle: true,
|
|
1174
1139
|
})
|
|
1175
|
-
console.log('query', query)
|
|
1176
1140
|
const chapterProcess = (result) => {
|
|
1177
1141
|
const now = getSanityDate(new Date(), false)
|
|
1178
1142
|
if (result.live_event_start_time && result.live_event_end_time) {
|
|
1179
1143
|
result.isLive = result.live_event_start_time <= now && result.live_event_end_time >= now
|
|
1180
1144
|
}
|
|
1181
1145
|
const chapters = result.chapters ?? []
|
|
1182
|
-
if (chapters.length
|
|
1146
|
+
if (chapters.length === 0) return result
|
|
1183
1147
|
result.chapters = chapters.map((chapter, index) => ({
|
|
1184
1148
|
...chapter,
|
|
1185
1149
|
chapter_thumbnail_url: `https://musora-web-platform.s3.amazonaws.com/chapters/${result.brand}/Chapter${index + 1}.jpg`,
|
|
1186
1150
|
}))
|
|
1187
|
-
console.log('result', result)
|
|
1188
1151
|
return result
|
|
1189
1152
|
}
|
|
1190
1153
|
|
|
@@ -1474,7 +1437,7 @@ export async function fetchLiveEvent(brand, forcedContentId = null) {
|
|
|
1474
1437
|
*/
|
|
1475
1438
|
export async function fetchPackData(id) {
|
|
1476
1439
|
const query = `*[railcontent_id == ${id}]{
|
|
1477
|
-
${
|
|
1440
|
+
${await getFieldsForContentTypeWithFilteredChildren('pack')}
|
|
1478
1441
|
} [0...1]`
|
|
1479
1442
|
return fetchSanity(query, false)
|
|
1480
1443
|
}
|
|
@@ -2013,6 +1976,10 @@ function getSanityDate(date, roundToHourForCaching = true) {
|
|
|
2013
1976
|
return date.toISOString()
|
|
2014
1977
|
}
|
|
2015
1978
|
|
|
1979
|
+
function getDateOnly(date = new Date()) {
|
|
1980
|
+
return date.toISOString().split('T')[0]
|
|
1981
|
+
}
|
|
1982
|
+
|
|
2016
1983
|
const merge = (a, b, predicate = (a, b) => a === b) => {
|
|
2017
1984
|
const c = [...a] // copy to avoid side effects
|
|
2018
1985
|
// add all items from B to copy C if they're not already present
|
|
@@ -2230,11 +2197,12 @@ export async function fetchTabData(
|
|
|
2230
2197
|
|
|
2231
2198
|
filter = `brand == "${brand}" ${includedFieldsFilter} ${progressFilter}`
|
|
2232
2199
|
const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
|
|
2200
|
+
const lessonCountFilter = await new FilterBuilder(`_id in ^.child[]._ref`).buildFilter()
|
|
2233
2201
|
entityFieldsString =
|
|
2234
2202
|
` ${fieldsString}
|
|
2235
2203
|
'children': child[${childrenFilter}]->{'id': railcontent_id},
|
|
2236
2204
|
'isLive': live_event_start_time <= "${now}" && live_event_end_time >= "${now}",
|
|
2237
|
-
'lesson_count': coalesce(count(
|
|
2205
|
+
'lesson_count': coalesce(count(*[${lessonCountFilter}]), 0),
|
|
2238
2206
|
'length_in_seconds': coalesce(
|
|
2239
2207
|
math::sum(
|
|
2240
2208
|
select(
|
|
@@ -2305,6 +2273,7 @@ export async function fetchScheduledAndNewReleases(
|
|
|
2305
2273
|
"id": railcontent_id,
|
|
2306
2274
|
title,
|
|
2307
2275
|
"image": thumbnail.asset->url,
|
|
2276
|
+
"thumbnail": thumbnail.asset->url,
|
|
2308
2277
|
${artistOrInstructorName()},
|
|
2309
2278
|
"artists": instructor[]->name,
|
|
2310
2279
|
difficulty,
|
|
@@ -2327,6 +2296,7 @@ export async function fetchShows(brand, type, sort = 'sort') {
|
|
|
2327
2296
|
|
|
2328
2297
|
const query = await buildQuery(filter, filterParams, getFieldsForContentType(type), {
|
|
2329
2298
|
sortOrder: sortOrder,
|
|
2299
|
+
end: 100, // Adrian: added for homepage progress rows, this should be handled gracefully
|
|
2330
2300
|
})
|
|
2331
2301
|
return fetchSanity(query, true)
|
|
2332
2302
|
}
|
package/src/services/types.js
CHANGED
|
@@ -29,20 +29,12 @@
|
|
|
29
29
|
* @property {string} authToken - The bearer authorization token.
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
|
-
/**
|
|
33
|
-
* @typedef {object} RecommendationsConfig - Configuration for recommendation services.
|
|
34
|
-
*
|
|
35
|
-
* @property {string} token - The token for authenticating recommendation requests.
|
|
36
|
-
* @property {string} baseUrl - The url for the recommendation server.
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
32
|
/**
|
|
40
33
|
* @typedef {object} Config
|
|
41
34
|
*
|
|
42
35
|
* @property {SanityConfig} sanityConfig
|
|
43
36
|
* @property {RailcontentConfig} railcontentConfig - DEPRECATED use sessionConfig and baseUrl instead.
|
|
44
37
|
* @property {SessionConfig} sessionConfig
|
|
45
|
-
* @property {RecommendationsConfig} recommendationsConfig
|
|
46
38
|
* @property {string} baseUrl - The url for the environment.
|
|
47
39
|
* @property {Object} localStorage - Cache to use for localStorage
|
|
48
40
|
* @property {boolean} isMA - Variable that tells if the library is used by MA or FEW
|