musora-content-services 2.30.9 → 2.31.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 +21 -0
- package/package.json +1 -1
- package/src/contentMetaData.js +6 -0
- package/src/contentTypeConfig.js +13 -3
- package/src/index.d.ts +3 -1
- package/src/index.js +3 -1
- package/src/services/content.js +46 -23
- package/src/services/railcontent.js +19 -0
- package/src/services/sanity.js +6 -51
- package/src/services/user/notifications.js +2 -2
- package/test/contentProgress.test.js +3 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [2.31.1](https://github.com/railroadmedia/musora-content-services/compare/v2.31.0...v2.31.1) (2025-08-14)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **MU-922:** uses BE for fetching recent content items ([#411](https://github.com/railroadmedia/musora-content-services/issues/411)) ([e85fe88](https://github.com/railroadmedia/musora-content-services/commit/e85fe881d382aadbe8fc902e959cfad2cbc98576))
|
|
11
|
+
|
|
12
|
+
## [2.31.0](https://github.com/railroadmedia/musora-content-services/compare/v2.30.9...v2.31.0) (2025-08-14)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* T3PS-458: Add Jam Tracks pill on Songs Overview page ([7351760](https://github.com/railroadmedia/musora-content-services/commit/7351760f3c4a92997036c860fadb6ef2602fc505))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* MU2-914: prevent null access error in fetchUnreadCount ([1813999](https://github.com/railroadmedia/musora-content-services/commit/1813999872466f970aa20c936d702b6a4ecc7b91))
|
|
23
|
+
* prevent null access error in fetchUnreadCount ([df39ccf](https://github.com/railroadmedia/musora-content-services/commit/df39ccfaf972214d08827e5a60f91653d491504e))
|
|
24
|
+
* T3PS-732 Filter sorting by name ([a25792c](https://github.com/railroadmedia/musora-content-services/commit/a25792cfce9163b8124c3f000569fd24541a7b33))
|
|
25
|
+
|
|
5
26
|
### [2.30.9](https://github.com/railroadmedia/musora-content-services/compare/v2.30.5...v2.30.9) (2025-08-13)
|
|
6
27
|
|
|
7
28
|
|
package/package.json
CHANGED
package/src/contentMetaData.js
CHANGED
|
@@ -39,6 +39,7 @@ export class Tabs {
|
|
|
39
39
|
static Tutorials = { name: 'Tutorials', short_name: 'Tutorials', value: 'type,tutorials', cardType: 'big' }
|
|
40
40
|
static Transcriptions = { name: 'Transcriptions', short_name: 'Transcriptions', value: 'type,transcription', cardType: 'small' }
|
|
41
41
|
static PlayAlongs = { name: 'Play-Alongs', short_name: 'Play-Alongs', value:'type,play along', cardType: 'small' }
|
|
42
|
+
static JamTracks = { name: 'Jam Tracks', short_name: 'Jam Tracks', value:'type,jam-track', cardType: 'small' }
|
|
42
43
|
static RecentAll = { name: 'All', short_name: 'All' }
|
|
43
44
|
static RecentIncomplete = { name: 'Incomplete', short_name: 'Incomplete' }
|
|
44
45
|
static RecentCompleted = { name: 'Completed', short_name: 'Completed' }
|
|
@@ -220,6 +221,7 @@ const commonMetadata = {
|
|
|
220
221
|
Tabs.Tutorials,
|
|
221
222
|
Tabs.Transcriptions,
|
|
222
223
|
Tabs.PlayAlongs,
|
|
224
|
+
Tabs.JamTracks,
|
|
223
225
|
Tabs.ExploreAll
|
|
224
226
|
],
|
|
225
227
|
},
|
|
@@ -359,6 +361,7 @@ const contentMetadata = {
|
|
|
359
361
|
Tabs.Tutorials,
|
|
360
362
|
Tabs.Transcriptions,
|
|
361
363
|
Tabs.PlayAlongs,
|
|
364
|
+
Tabs.JamTracks,
|
|
362
365
|
Tabs.ExploreAll
|
|
363
366
|
],
|
|
364
367
|
},
|
|
@@ -400,6 +403,7 @@ const contentMetadata = {
|
|
|
400
403
|
Tabs.Tutorials,
|
|
401
404
|
Tabs.Transcriptions,
|
|
402
405
|
Tabs.PlayAlongs,
|
|
406
|
+
Tabs.JamTracks,
|
|
403
407
|
Tabs.ExploreAll
|
|
404
408
|
],
|
|
405
409
|
},
|
|
@@ -451,6 +455,7 @@ const contentMetadata = {
|
|
|
451
455
|
Tabs.Tutorials,
|
|
452
456
|
Tabs.Transcriptions,
|
|
453
457
|
Tabs.PlayAlongs,
|
|
458
|
+
Tabs.JamTracks,
|
|
454
459
|
Tabs.ExploreAll
|
|
455
460
|
],
|
|
456
461
|
},
|
|
@@ -491,6 +496,7 @@ const contentMetadata = {
|
|
|
491
496
|
Tabs.Tutorials,
|
|
492
497
|
Tabs.Transcriptions,
|
|
493
498
|
Tabs.PlayAlongs,
|
|
499
|
+
Tabs.JamTracks,
|
|
494
500
|
Tabs.ExploreAll
|
|
495
501
|
],
|
|
496
502
|
},
|
package/src/contentTypeConfig.js
CHANGED
|
@@ -174,6 +174,7 @@ export const studentArchivesLessonTypes = ['student-review', 'student-focus','st
|
|
|
174
174
|
export const tutorialsLessonTypes = ['song-tutorial'];
|
|
175
175
|
export const transcriptionsLessonTypes = ['song'];
|
|
176
176
|
export const playAlongLessonTypes = ['play-along'];
|
|
177
|
+
export const jamTrackLessonTypes = ['jam-track'];
|
|
177
178
|
|
|
178
179
|
export const individualLessonsTypes = [
|
|
179
180
|
...singleLessonTypes,
|
|
@@ -207,7 +208,7 @@ export const lessonTypesMapping = {
|
|
|
207
208
|
'tabs': transcriptionsLessonTypes,
|
|
208
209
|
'sheet music': transcriptionsLessonTypes,
|
|
209
210
|
'play-alongs': playAlongLessonTypes,
|
|
210
|
-
'jam tracks':
|
|
211
|
+
'jam tracks': jamTrackLessonTypes,
|
|
211
212
|
};
|
|
212
213
|
|
|
213
214
|
export const getNextLessonLessonParentTypes = ['course', 'guided-course', 'pack', 'pack-bundle', 'song-tutorial'];
|
|
@@ -222,7 +223,7 @@ export const progressTypesMapping = {
|
|
|
222
223
|
'guided course': ['guided-course'],
|
|
223
224
|
'pack': ['pack', 'semester-pack'],
|
|
224
225
|
'method': ['learning-path'],
|
|
225
|
-
'jam track':
|
|
226
|
+
'jam track': jamTrackLessonTypes,
|
|
226
227
|
'course video': ['course-part'],
|
|
227
228
|
};
|
|
228
229
|
|
|
@@ -235,7 +236,7 @@ export const songs = {
|
|
|
235
236
|
|
|
236
237
|
export const filterTypes = {
|
|
237
238
|
lessons: [...individualLessonsTypes, ...collectionLessonTypes],
|
|
238
|
-
songs: [...tutorialsLessonTypes, ...transcriptionsLessonTypes, ...playAlongLessonTypes,
|
|
239
|
+
songs: [...tutorialsLessonTypes, ...transcriptionsLessonTypes, ...playAlongLessonTypes, ...jamTrackLessonTypes],
|
|
239
240
|
}
|
|
240
241
|
|
|
241
242
|
export const recentTypes = {
|
|
@@ -670,6 +671,12 @@ export function getUpcomingEventsTypes(brand) {
|
|
|
670
671
|
}
|
|
671
672
|
}
|
|
672
673
|
|
|
674
|
+
export function getRecentTypesForPage(pageType) {
|
|
675
|
+
const types = recentTypes[pageType]
|
|
676
|
+
// defensive copy with de-duplication to avoid accidental mutation and redundant query params
|
|
677
|
+
return Array.isArray(types) ? [...new Set(types)] : []
|
|
678
|
+
}
|
|
679
|
+
|
|
673
680
|
export function artistOrInstructorName(key = 'artist_name') {
|
|
674
681
|
return `'${key}': coalesce(artist->name, instructor[0]->name)`
|
|
675
682
|
}
|
|
@@ -802,6 +809,9 @@ export function filtersToGroq(filters, selectedFilters = [], pageName = '') {
|
|
|
802
809
|
} else if(value.toLowerCase() === Tabs.PlayAlongs.name.toLowerCase()){
|
|
803
810
|
const conditions = playAlongLessonTypes.map(lessonType => `_type == '${lessonType}'`).join(' || ');
|
|
804
811
|
return ` (${conditions})`;
|
|
812
|
+
} else if(value.toLowerCase() === Tabs.JamTracks.name.toLowerCase()){
|
|
813
|
+
const conditions = jamTrackLessonTypes.map(lessonType => `_type == '${lessonType}'`).join(' || ');
|
|
814
|
+
return ` (${conditions})`;
|
|
805
815
|
} else if(value.toLowerCase() === Tabs.ExploreAll.name.toLowerCase()){
|
|
806
816
|
var allLessons = filterTypes[pageName] || [];
|
|
807
817
|
const conditions = allLessons.map(lessonType => `_type == '${lessonType}'`).join(' || ');
|
package/src/index.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
getLessonContentRows,
|
|
39
39
|
getNewAndUpcoming,
|
|
40
40
|
getRecent,
|
|
41
|
+
getRecentForTab,
|
|
41
42
|
getRecommendedForYou,
|
|
42
43
|
getScheduleContentRows,
|
|
43
44
|
getTabResults
|
|
@@ -129,6 +130,7 @@ import {
|
|
|
129
130
|
fetchLastInteractedChild,
|
|
130
131
|
fetchLikeCount,
|
|
131
132
|
fetchNextContentDataForParent,
|
|
133
|
+
fetchRecent,
|
|
132
134
|
fetchRecentUserActivities,
|
|
133
135
|
fetchSongsInProgress,
|
|
134
136
|
fetchTopComment,
|
|
@@ -197,7 +199,6 @@ import {
|
|
|
197
199
|
fetchPackData,
|
|
198
200
|
fetchParentForDownload,
|
|
199
201
|
fetchPlayAlongsCount,
|
|
200
|
-
fetchRecent,
|
|
201
202
|
fetchRelatedLessons,
|
|
202
203
|
fetchRelatedRecommendedContent,
|
|
203
204
|
fetchRelatedSongs,
|
|
@@ -442,6 +443,7 @@ declare module 'musora-content-services' {
|
|
|
442
443
|
getProgressStateByIds,
|
|
443
444
|
getRecent,
|
|
444
445
|
getRecentActivity,
|
|
446
|
+
getRecentForTab,
|
|
445
447
|
getRecommendedForYou,
|
|
446
448
|
getResumeTimeSeconds,
|
|
447
449
|
getResumeTimeSecondsByIds,
|
package/src/index.js
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
getLessonContentRows,
|
|
39
39
|
getNewAndUpcoming,
|
|
40
40
|
getRecent,
|
|
41
|
+
getRecentForTab,
|
|
41
42
|
getRecommendedForYou,
|
|
42
43
|
getScheduleContentRows,
|
|
43
44
|
getTabResults
|
|
@@ -129,6 +130,7 @@ import {
|
|
|
129
130
|
fetchLastInteractedChild,
|
|
130
131
|
fetchLikeCount,
|
|
131
132
|
fetchNextContentDataForParent,
|
|
133
|
+
fetchRecent,
|
|
132
134
|
fetchRecentUserActivities,
|
|
133
135
|
fetchSongsInProgress,
|
|
134
136
|
fetchTopComment,
|
|
@@ -197,7 +199,6 @@ import {
|
|
|
197
199
|
fetchPackData,
|
|
198
200
|
fetchParentForDownload,
|
|
199
201
|
fetchPlayAlongsCount,
|
|
200
|
-
fetchRecent,
|
|
201
202
|
fetchRelatedLessons,
|
|
202
203
|
fetchRelatedRecommendedContent,
|
|
203
204
|
fetchRelatedSongs,
|
|
@@ -441,6 +442,7 @@ export {
|
|
|
441
442
|
getProgressStateByIds,
|
|
442
443
|
getRecent,
|
|
443
444
|
getRecentActivity,
|
|
445
|
+
getRecentForTab,
|
|
444
446
|
getRecommendedForYou,
|
|
445
447
|
getResumeTimeSeconds,
|
|
446
448
|
getResumeTimeSecondsByIds,
|
package/src/services/content.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import {
|
|
6
6
|
fetchByRailContentIds,
|
|
7
7
|
fetchMetadata,
|
|
8
|
-
fetchRecent,
|
|
9
8
|
fetchTabData,
|
|
10
9
|
fetchNewReleases,
|
|
11
10
|
fetchUpcomingEvents,
|
|
@@ -13,16 +12,18 @@ import {
|
|
|
13
12
|
fetchReturning,
|
|
14
13
|
fetchLeaving, fetchScheduledAndNewReleases, fetchContentRows
|
|
15
14
|
} from './sanity.js'
|
|
15
|
+
import {getRecentTypesForPage} from '../contentTypeConfig.js'
|
|
16
16
|
import {TabResponseType, Tabs, capitalizeFirstLetter} from '../contentMetaData.js'
|
|
17
|
-
import {
|
|
17
|
+
import {fetchRecent} from "./railcontent";
|
|
18
18
|
import {recommendations, rankCategories, rankItems} from "./recommendations";
|
|
19
19
|
import {addContextToContent} from "./contentAggregator.js";
|
|
20
20
|
|
|
21
|
+
export async function getLessonContentRows(brand, pageName) {
|
|
22
|
+
const [recentContentIds, contentRows] = await Promise.all([
|
|
23
|
+
fetchRecent(brand, { types: getRecentTypesForPage(pageName) }, { limit: 10 }),
|
|
24
|
+
getContentRows(brand, pageName)
|
|
25
|
+
])
|
|
21
26
|
|
|
22
|
-
export async function getLessonContentRows (brand='drumeo', pageName = 'lessons') {
|
|
23
|
-
let recentContentIds = await fetchRecent(brand, pageName, { progress: 'recent', limit: 10 });
|
|
24
|
-
|
|
25
|
-
let contentRows = await getContentRows(brand, pageName);
|
|
26
27
|
contentRows = Array.isArray(contentRows) ? contentRows : [];
|
|
27
28
|
contentRows.unshift({
|
|
28
29
|
id: 'recent',
|
|
@@ -66,13 +67,8 @@ export async function getTabResults(brand, pageName, tabName, {
|
|
|
66
67
|
sort = 'recommended',
|
|
67
68
|
selectedFilters = []
|
|
68
69
|
} = {}) {
|
|
69
|
-
// Extract and handle 'progress' filter separately
|
|
70
|
-
const progressFilter = selectedFilters.find(f => f.startsWith('progress,')) || 'progress,all';
|
|
71
|
-
const progressValue = progressFilter.split(',')[1].toLowerCase();
|
|
72
|
-
const filteredSelectedFilters = selectedFilters.filter(f => !f.startsWith('progress,'));
|
|
73
|
-
|
|
74
70
|
// Prepare included fields
|
|
75
|
-
const mergedIncludedFields = [...
|
|
71
|
+
const mergedIncludedFields = [...selectedFilters, `tab,${tabName.toLowerCase()}`];
|
|
76
72
|
|
|
77
73
|
// Fetch data
|
|
78
74
|
let results
|
|
@@ -85,7 +81,7 @@ export async function getTabResults(brand, pageName, tabName, {
|
|
|
85
81
|
addProgressStatus: true
|
|
86
82
|
})
|
|
87
83
|
} else {
|
|
88
|
-
let temp = await fetchTabData(brand, pageName, { page, limit, sort, includedFields: mergedIncludedFields
|
|
84
|
+
let temp = await fetchTabData(brand, pageName, { page, limit, sort, includedFields: mergedIncludedFields });
|
|
89
85
|
|
|
90
86
|
const [ranking, contextResults] = await Promise.all([
|
|
91
87
|
sort === 'recommended' ? rankItems(brand, temp.entity.map(e => e.railcontent_id)) : [],
|
|
@@ -104,7 +100,6 @@ export async function getTabResults(brand, pageName, tabName, {
|
|
|
104
100
|
})
|
|
105
101
|
}
|
|
106
102
|
|
|
107
|
-
|
|
108
103
|
// Fetch metadata
|
|
109
104
|
const metaData = await fetchMetadata(brand, pageName);
|
|
110
105
|
|
|
@@ -115,8 +110,7 @@ export async function getTabResults(brand, pageName, tabName, {
|
|
|
115
110
|
const value = item.value.split(',')[1];
|
|
116
111
|
return {
|
|
117
112
|
...item,
|
|
118
|
-
selected: selectedFilters.includes(`${filter.key},${value}`)
|
|
119
|
-
(filter.key === 'progress' && value === 'all' && !selectedFilters.some(f => f.startsWith('progress,')))
|
|
113
|
+
selected: selectedFilters.includes(`${filter.key},${value}`)
|
|
120
114
|
};
|
|
121
115
|
})
|
|
122
116
|
}));
|
|
@@ -151,7 +145,7 @@ export async function getTabResults(brand, pageName, tabName, {
|
|
|
151
145
|
* @returns {Promise<Object>} - The fetched content data.
|
|
152
146
|
*
|
|
153
147
|
* @example
|
|
154
|
-
* getRecent('drumeo', '
|
|
148
|
+
* getRecent('drumeo', { status: 'completed', types: ['lessons'] }, {
|
|
155
149
|
* page: 2,
|
|
156
150
|
* limit: 15,
|
|
157
151
|
* sort: '-popularity'
|
|
@@ -159,14 +153,43 @@ export async function getTabResults(brand, pageName, tabName, {
|
|
|
159
153
|
* .then(content => console.log(content))
|
|
160
154
|
* .catch(error => console.error(error));
|
|
161
155
|
*/
|
|
162
|
-
export async function getRecent(brand,
|
|
156
|
+
export async function getRecent(brand, { status, types } = {}, {
|
|
163
157
|
page = 1,
|
|
164
|
-
limit = 10
|
|
165
|
-
sort = '-published_on',
|
|
158
|
+
limit = 10
|
|
166
159
|
} = {}) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
160
|
+
return await fetchRecent(brand, { status, types }, { page, limit });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Fetches recent content for a given brand and page with pagination.
|
|
165
|
+
*
|
|
166
|
+
* @param {string} brand - The brand for which to fetch data.
|
|
167
|
+
* @param {string} pageName - The page name (e.g., 'all', 'incomplete', 'completed').
|
|
168
|
+
* @param {string} [tabName='all'] - The tab name (defaults to 'all' for recent content).
|
|
169
|
+
* @param {Object} params - Parameters for pagination and sorting.
|
|
170
|
+
* @param {number} [params.page=1] - The page number for pagination.
|
|
171
|
+
* @param {number} [params.limit=10] - The number of items per page.
|
|
172
|
+
* @param {string} [params.sort="-published_on"] - The field to sort the data by.
|
|
173
|
+
* @returns {Promise<Object>} - The fetched content data.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* getRecent('drumeo', 'lessons', 'all', {
|
|
177
|
+
* page: 2,
|
|
178
|
+
* limit: 15,
|
|
179
|
+
* sort: '-popularity'
|
|
180
|
+
* })
|
|
181
|
+
* .then(content => console.log(content))
|
|
182
|
+
* .catch(error => console.error(error));
|
|
183
|
+
*/
|
|
184
|
+
export async function getRecentForTab(brand, pageType, tabName, { page = 1, limit = 10 } = {}) {
|
|
185
|
+
const types = getRecentTypesForPage(pageType)
|
|
186
|
+
const status = tabName === Tabs.RecentCompleted.name ? 'completed' : tabName === Tabs.RecentIncomplete.name ? 'incomplete' : null
|
|
187
|
+
|
|
188
|
+
const [recentContentIds, metaData] = await Promise.all([
|
|
189
|
+
fetchRecent(brand, { status, types }, { page, limit }),
|
|
190
|
+
fetchMetadata(brand, 'recent')
|
|
191
|
+
])
|
|
192
|
+
|
|
170
193
|
return {
|
|
171
194
|
type: TabResponseType.CATALOG,
|
|
172
195
|
data: recentContentIds,
|
|
@@ -668,6 +668,25 @@ export async function fetchUserPracticeNotes(date) {
|
|
|
668
668
|
return await fetchHandler(url, 'GET', null)
|
|
669
669
|
}
|
|
670
670
|
|
|
671
|
+
export async function fetchRecent(brand, { status, types } = {}, {
|
|
672
|
+
page = 1,
|
|
673
|
+
limit = 10
|
|
674
|
+
} = {}) {
|
|
675
|
+
const query = new URLSearchParams()
|
|
676
|
+
query.append('brand', brand)
|
|
677
|
+
if (status) query.append('status', status)
|
|
678
|
+
if (types) {
|
|
679
|
+
types.forEach((type) => query.append('types[]', type))
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
query.append('page', page)
|
|
683
|
+
query.append('limit', limit)
|
|
684
|
+
|
|
685
|
+
const url = `/api/content-org/v1/user/recent?${query.toString()}`
|
|
686
|
+
const response = await fetchHandler(url, 'GET', null)
|
|
687
|
+
return response ? response.result : []
|
|
688
|
+
}
|
|
689
|
+
|
|
671
690
|
/**
|
|
672
691
|
* Get the id and slug of last interacted child. Only valid for certain content types
|
|
673
692
|
*
|
package/src/services/sanity.js
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
getFieldsForContentTypeWithFilteredChildren,
|
|
20
20
|
getChildFieldsForContentType,
|
|
21
21
|
SONG_TYPES,
|
|
22
|
+
recentTypes
|
|
22
23
|
} from '../contentTypeConfig.js'
|
|
23
24
|
import {fetchSimilarItems, recommendations} from './recommendations.js'
|
|
24
25
|
import { processMetadata, typeWithSortOrder } from '../contentMetaData.js'
|
|
@@ -753,7 +754,7 @@ export function getSortOrder(sort = '-published_on', brand, groupBy) {
|
|
|
753
754
|
sort = isDesc ? sort.substring(1) : sort
|
|
754
755
|
switch (sort) {
|
|
755
756
|
case 'slug':
|
|
756
|
-
sortOrder = groupBy ? 'name' : 'title'
|
|
757
|
+
sortOrder = groupBy ? 'name' : '!defined(title), lower(title)'
|
|
757
758
|
break
|
|
758
759
|
case 'name':
|
|
759
760
|
sortOrder = sort
|
|
@@ -2051,10 +2052,10 @@ async function buildQuery(
|
|
|
2051
2052
|
function buildEntityAndTotalQuery(
|
|
2052
2053
|
filter = '',
|
|
2053
2054
|
fields = '...',
|
|
2054
|
-
{ sortOrder = 'published_on desc', start = 0, end = 10, isSingle = false
|
|
2055
|
+
{ sortOrder = 'published_on desc', start = 0, end = 10, isSingle = false }
|
|
2055
2056
|
) {
|
|
2056
2057
|
const sortString = sortOrder ? ` | order(${sortOrder})` : ''
|
|
2057
|
-
const countString = isSingle ? '[0...1]' :
|
|
2058
|
+
const countString = isSingle ? '[0...1]' : `[${start}...${end}]`
|
|
2058
2059
|
const query = `{
|
|
2059
2060
|
"entity": *[${filter}] ${sortString}${countString}
|
|
2060
2061
|
{
|
|
@@ -2168,9 +2169,7 @@ export async function fetchTabData(
|
|
|
2168
2169
|
page = 1,
|
|
2169
2170
|
limit = 10,
|
|
2170
2171
|
sort = '-published_on',
|
|
2171
|
-
includedFields = []
|
|
2172
|
-
progressIds = undefined,
|
|
2173
|
-
progress = 'all',
|
|
2172
|
+
includedFields = []
|
|
2174
2173
|
} = {}
|
|
2175
2174
|
) {
|
|
2176
2175
|
const start = (page - 1) * limit
|
|
@@ -2181,23 +2180,6 @@ export async function fetchTabData(
|
|
|
2181
2180
|
|
|
2182
2181
|
let sortOrder = getSortOrder(sort, brand, '')
|
|
2183
2182
|
|
|
2184
|
-
switch (progress) {
|
|
2185
|
-
case 'recent':
|
|
2186
|
-
progressIds = await getAllStartedOrCompleted({ brand, onlyIds: true });
|
|
2187
|
-
sortOrder = null;
|
|
2188
|
-
break;
|
|
2189
|
-
case 'incomplete':
|
|
2190
|
-
progressIds = await getAllStarted();
|
|
2191
|
-
sortOrder = null;
|
|
2192
|
-
break;
|
|
2193
|
-
case 'completed':
|
|
2194
|
-
progressIds = await getAllCompleted();
|
|
2195
|
-
sortOrder = null;
|
|
2196
|
-
break;
|
|
2197
|
-
}
|
|
2198
|
-
|
|
2199
|
-
// limits the results to supplied progressIds for started & completed filters
|
|
2200
|
-
const progressFilter = await getProgressFilter(progress, progressIds)
|
|
2201
2183
|
const fieldsString = getFieldsForContentType('tab-data');
|
|
2202
2184
|
const now = getSanityDate(new Date())
|
|
2203
2185
|
|
|
@@ -2206,7 +2188,7 @@ export async function fetchTabData(
|
|
|
2206
2188
|
let entityFieldsString = ''
|
|
2207
2189
|
let filter = ''
|
|
2208
2190
|
|
|
2209
|
-
filter = `brand == "${brand}" ${includedFieldsFilter}
|
|
2191
|
+
filter = `brand == "${brand}" ${includedFieldsFilter}`
|
|
2210
2192
|
const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
|
|
2211
2193
|
const lessonCountFilter = await new FilterBuilder(`_id in ^.child[]._ref`).buildFilter()
|
|
2212
2194
|
entityFieldsString =
|
|
@@ -2231,36 +2213,9 @@ export async function fetchTabData(
|
|
|
2231
2213
|
|
|
2232
2214
|
let results = await fetchSanity(query, true);
|
|
2233
2215
|
|
|
2234
|
-
if (['recent', 'incomplete', 'completed'].includes(progress) && results.entity.length > 1) {
|
|
2235
|
-
const orderMap = new Map(progressIds.map((id, index) => [id, index]))
|
|
2236
|
-
results.entity = results.entity
|
|
2237
|
-
.sort((a, b) => {
|
|
2238
|
-
const aIdx = orderMap.get(a.id) ?? Number.MAX_SAFE_INTEGER;
|
|
2239
|
-
const bIdx = orderMap.get(b.id) ?? Number.MAX_SAFE_INTEGER;
|
|
2240
|
-
return aIdx - bIdx || new Date(b.published_on) - new Date(a.published_on);
|
|
2241
|
-
})
|
|
2242
|
-
.slice(start, end);
|
|
2243
|
-
}
|
|
2244
|
-
|
|
2245
2216
|
return results;
|
|
2246
2217
|
}
|
|
2247
2218
|
|
|
2248
|
-
export async function fetchRecent(
|
|
2249
|
-
brand,
|
|
2250
|
-
pageName,
|
|
2251
|
-
{ page = 1, limit = 10, sort = '-published_on', includedFields = [], progress = 'recent' } = {}
|
|
2252
|
-
) {
|
|
2253
|
-
const mergedIncludedFields = [...includedFields, `tab,all`]
|
|
2254
|
-
const results = await fetchTabData(brand, pageName, {
|
|
2255
|
-
page,
|
|
2256
|
-
limit,
|
|
2257
|
-
sort,
|
|
2258
|
-
includedFields: mergedIncludedFields,
|
|
2259
|
-
progress: progress.toLowerCase(),
|
|
2260
|
-
})
|
|
2261
|
-
return results.entity
|
|
2262
|
-
}
|
|
2263
|
-
|
|
2264
2219
|
export async function fetchScheduledAndNewReleases(
|
|
2265
2220
|
brand,
|
|
2266
2221
|
{ page = 1, limit = 20, sort = '-published_on' } = {}
|
|
@@ -162,7 +162,7 @@ export async function restoreNotification(notificationId) {
|
|
|
162
162
|
export async function fetchUnreadCount({ brand = 'drumeo'} = {}) {
|
|
163
163
|
const url = `${baseUrl}/v1/unread-count`
|
|
164
164
|
const notifUnread = await fetchHandler(url, 'get')
|
|
165
|
-
if (notifUnread.data > 0) {
|
|
165
|
+
if (notifUnread && notifUnread.data > 0) {
|
|
166
166
|
return notifUnread// Return early if unread notifications exist
|
|
167
167
|
}
|
|
168
168
|
const liveEventPollingState = await fetchLiveEventPollingState()
|
|
@@ -170,7 +170,7 @@ export async function fetchUnreadCount({ brand = 'drumeo'} = {}) {
|
|
|
170
170
|
const liveEvent = await fetchLiveEvent(brand)
|
|
171
171
|
return { data: liveEvent ? 1 : 0}
|
|
172
172
|
}
|
|
173
|
-
return
|
|
173
|
+
return { data: 0}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
/**
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
} from '../src/services/contentProgress'
|
|
16
16
|
import { initializeTestService } from './initializeTests'
|
|
17
17
|
import {getLessonContentRows, postContentComplete} from '../src'
|
|
18
|
-
import {fetchRecent} from "../src/services/sanity";
|
|
19
18
|
import {getRecent, getTabResults} from "../src/services/content";
|
|
20
19
|
import {individualLessonsTypes, playAlongLessonTypes, transcriptionsLessonTypes, tutorialsLessonTypes} from "../src/contentTypeConfig";
|
|
21
20
|
|
|
@@ -258,21 +257,21 @@ describe('contentProgressDataContext', function () {
|
|
|
258
257
|
//
|
|
259
258
|
// });
|
|
260
259
|
test('getRecentLessons', async () => {
|
|
261
|
-
let result = await getRecent('drumeo',
|
|
260
|
+
let result = await getRecent('drumeo', {})
|
|
262
261
|
console.log(result);
|
|
263
262
|
expect(result.data[0].id).toStrictEqual(412986)
|
|
264
263
|
expect(individualLessonsTypes).toContain(result.data[0].type)
|
|
265
264
|
})
|
|
266
265
|
|
|
267
266
|
test('getRecentLessons-Incomplete', async () => {
|
|
268
|
-
let result = await getRecent('drumeo','
|
|
267
|
+
let result = await getRecent('drumeo', {status: 'incomplete'})
|
|
269
268
|
console.log(result);
|
|
270
269
|
expect(result.data[0].id).toStrictEqual(407665)
|
|
271
270
|
expect(individualLessonsTypes).toContain(result.data[0].type)
|
|
272
271
|
})
|
|
273
272
|
|
|
274
273
|
test('getRecentLessons-Completed', async () => {
|
|
275
|
-
let result = await getRecent('drumeo','
|
|
274
|
+
let result = await getRecent('drumeo', {status: 'completed'})
|
|
276
275
|
console.log(result);
|
|
277
276
|
expect(result.data[0].id).toStrictEqual(412986)
|
|
278
277
|
expect(individualLessonsTypes).toContain(result.data[0].type)
|