musora-content-services 1.0.102 → 1.0.105
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 +6 -0
- package/README.md +34 -7
- package/docs/config.js.html +2 -2
- package/docs/index.html +47 -9
- package/docs/module-Config.html +2 -2
- package/docs/module-Railcontent-Services.html +2 -2
- package/docs/module-Sanity-Services.html +373 -40
- package/docs/railcontent.js.html +64 -14
- package/docs/sanity.js.html +98 -31
- package/package.json +1 -1
- package/src/contentTypeConfig.js +32 -11
- package/src/index.js +4 -0
- package/src/services/railcontent.js +12 -12
- package/src/services/sanity.js +28 -7
- package/test/log.js +5 -0
- package/test/sanityQueryService.test.js +39 -21
|
@@ -150,15 +150,15 @@ export async function fetchSongsInProgress(brand) {
|
|
|
150
150
|
* .then(songs => console.log(songs))
|
|
151
151
|
* .catch(error => console.error(error));
|
|
152
152
|
*/
|
|
153
|
-
export async function fetchContentInProgress(type="all", brand, {
|
|
154
|
-
page = 1,
|
|
155
|
-
limit = 10,
|
|
156
|
-
} = {}) {
|
|
153
|
+
export async function fetchContentInProgress(type="all", brand, { page, limit } = {}) {
|
|
157
154
|
let url;
|
|
155
|
+
const limitString = limit ? `&limit=${limit}` : '';
|
|
156
|
+
const pageString = page ? `&page=${page}` : '';
|
|
157
|
+
|
|
158
158
|
if(type === "all") {
|
|
159
|
-
url = `/content/in_progress/${globalConfig.railcontentConfig.userId}?brand=${brand}
|
|
159
|
+
url = `/content/in_progress/${globalConfig.railcontentConfig.userId}?brand=${brand}${limitString}${pageString}`;
|
|
160
160
|
} else {
|
|
161
|
-
url = `/content/in_progress/${globalConfig.railcontentConfig.userId}?content_type=${type}&brand=${brand}
|
|
161
|
+
url = `/content/in_progress/${globalConfig.railcontentConfig.userId}?content_type=${type}&brand=${brand}${limitString}${pageString}`;
|
|
162
162
|
}
|
|
163
163
|
const headers = {
|
|
164
164
|
'Content-Type': 'application/json',
|
|
@@ -192,15 +192,15 @@ export async function fetchContentInProgress(type="all", brand, {
|
|
|
192
192
|
* .then(songs => console.log(songs))
|
|
193
193
|
* .catch(error => console.error(error));
|
|
194
194
|
*/
|
|
195
|
-
export async function fetchCompletedContent(type="all", brand, {
|
|
196
|
-
page = 1,
|
|
197
|
-
limit = 10,
|
|
198
|
-
} = {}) {
|
|
195
|
+
export async function fetchCompletedContent(type="all", brand, { page, limit } = {}) {
|
|
199
196
|
let url;
|
|
197
|
+
const limitString = limit ? `&limit=${limit}` : '';
|
|
198
|
+
const pageString = page ? `&page=${page}` : '';
|
|
199
|
+
|
|
200
200
|
if(type === "all") {
|
|
201
|
-
url = `/content/completed/${globalConfig.railcontentConfig.userId}?brand=${brand}
|
|
201
|
+
url = `/content/completed/${globalConfig.railcontentConfig.userId}?brand=${brand}${limitString}${pageString}`;
|
|
202
202
|
} else {
|
|
203
|
-
url = `/content/completed/${globalConfig.railcontentConfig.userId}?content_type=${type}&brand=${brand}
|
|
203
|
+
url = `/content/completed/${globalConfig.railcontentConfig.userId}?content_type=${type}&brand=${brand}${limitString}${pageString}`;
|
|
204
204
|
}
|
|
205
205
|
const headers = {
|
|
206
206
|
'Content-Type': 'application/json',
|
package/src/services/sanity.js
CHANGED
|
@@ -90,6 +90,7 @@ export async function fetchRelatedSongs(brand, songId) {
|
|
|
90
90
|
"url": web_url_path,
|
|
91
91
|
"published_on": published_on,
|
|
92
92
|
status,
|
|
93
|
+
"image": thumbnail.asset->url,
|
|
93
94
|
"fields": [
|
|
94
95
|
{
|
|
95
96
|
"key": "title",
|
|
@@ -108,10 +109,6 @@ export async function fetchRelatedSongs(brand, songId) {
|
|
|
108
109
|
"value": soundslice[0].soundslice_length_in_second
|
|
109
110
|
}
|
|
110
111
|
],
|
|
111
|
-
"data": [{
|
|
112
|
-
"key": "thumbnail_url",
|
|
113
|
-
"value": thumbnail.asset->url
|
|
114
|
-
}]
|
|
115
112
|
}[0...10]),
|
|
116
113
|
...(*[_type == "song" && brand == "${brand}" && railcontent_id != ${songId} && references(^.genre[]->_id)]{
|
|
117
114
|
"type": _type,
|
|
@@ -229,6 +226,27 @@ export async function fetchSongCount(brand) {
|
|
|
229
226
|
return fetchSanity(query, true);
|
|
230
227
|
}
|
|
231
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Fetch the latest workouts for a specific brand, including completion status and progress.
|
|
231
|
+
* This function retrieves up to five of the latest workout content for a given brand, sorted in descending order by their publication date.
|
|
232
|
+
* It also includes completion status and progress percentage for each workout by fetching additional data about user progress.
|
|
233
|
+
*
|
|
234
|
+
* @param {string} brand - The brand for which to fetch workouts (e.g., 'drumeo', 'pianote').
|
|
235
|
+
* @returns {Promise<Array<Object>|null>} - A promise that resolves to an array of workout data objects with additional properties for completion status and progress percentage, or null if no workouts are found.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* fetchWorkouts('drumeo')
|
|
239
|
+
* .then(workouts => console.log(workouts))
|
|
240
|
+
* .catch(error => console.error(error));
|
|
241
|
+
*/
|
|
242
|
+
export async function fetchWorkouts(brand) {
|
|
243
|
+
const fields = getFieldsForContentType('workout');
|
|
244
|
+
const query = `*[_type == 'workout' && brand == '${brand}'] [0...5] {
|
|
245
|
+
${fields.toString()}
|
|
246
|
+
} | order(published_on desc)[0...5]`
|
|
247
|
+
return fetchSanity(query, true);
|
|
248
|
+
}
|
|
249
|
+
|
|
232
250
|
/**
|
|
233
251
|
* Fetch the latest new releases for a specific brand.
|
|
234
252
|
* @param {string} brand - The brand for which to fetch new releases.
|
|
@@ -415,6 +433,7 @@ export async function fetchAll(brand, type, {
|
|
|
415
433
|
let config = contentTypeConfig[type] ?? {};
|
|
416
434
|
let additionalFields = config?.fields ?? [];
|
|
417
435
|
let isGroupByOneToOne = (groupBy ? config?.relationships?.[groupBy]?.isOneToOne : false) ?? false;
|
|
436
|
+
let webUrlPathType = config?.slug ?? type;
|
|
418
437
|
const start = (page - 1) * limit;
|
|
419
438
|
const end = start + limit;
|
|
420
439
|
|
|
@@ -443,6 +462,7 @@ export async function fetchAll(brand, type, {
|
|
|
443
462
|
// Determine the group by clause
|
|
444
463
|
let query = "";
|
|
445
464
|
if (groupBy !== "" && isGroupByOneToOne) {
|
|
465
|
+
let webUrlPath = 'artists';
|
|
446
466
|
query = `
|
|
447
467
|
{
|
|
448
468
|
"total": count(*[_type == '${groupBy}' && count(*[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]),
|
|
@@ -452,7 +472,7 @@ export async function fetchAll(brand, type, {
|
|
|
452
472
|
'type': _type,
|
|
453
473
|
name,
|
|
454
474
|
'head_shot_picture_url': thumbnail_url.asset->url,
|
|
455
|
-
web_url_path,
|
|
475
|
+
'web_url_path': '/${brand}/${webUrlPath}/'+name+'?included_fieds[]=type,${type}',
|
|
456
476
|
'all_lessons_count': count(*[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id),
|
|
457
477
|
'lessons': *[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{
|
|
458
478
|
${fieldsString},
|
|
@@ -463,6 +483,7 @@ export async function fetchAll(brand, type, {
|
|
|
463
483
|
[${start}...${end}]
|
|
464
484
|
}`;
|
|
465
485
|
} else if (groupBy !== "") {
|
|
486
|
+
let webUrlPath = (groupBy == 'genre')?'/genres':'';
|
|
466
487
|
query = `
|
|
467
488
|
{
|
|
468
489
|
"total": count(*[_type == '${groupBy}' && count(*[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]),
|
|
@@ -472,7 +493,7 @@ export async function fetchAll(brand, type, {
|
|
|
472
493
|
'type': _type,
|
|
473
494
|
name,
|
|
474
495
|
'head_shot_picture_url': thumbnail_url.asset->url,
|
|
475
|
-
web_url_path,
|
|
496
|
+
'web_url_path': select(defined(web_url_path)=> web_url_path +'?included_fieds[]=type,${type}',!defined(web_url_path)=> '/${brand}${webUrlPath}/'+name+'/${webUrlPathType}'),
|
|
476
497
|
'all_lessons_count': count(*[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id),
|
|
477
498
|
'lessons': *[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{
|
|
478
499
|
${fieldsString},
|
|
@@ -658,6 +679,7 @@ export async function fetchMethod(brand, slug) {
|
|
|
658
679
|
status,
|
|
659
680
|
title,
|
|
660
681
|
video,
|
|
682
|
+
length_in_seconds,
|
|
661
683
|
"type": _type,
|
|
662
684
|
"levels": child[]->
|
|
663
685
|
{
|
|
@@ -712,7 +734,6 @@ export async function fetchMethodNextLesson(railcontentId, methodId) {
|
|
|
712
734
|
return childIndex ? await fetchByRailContentId(childIndex) : null;
|
|
713
735
|
}
|
|
714
736
|
|
|
715
|
-
|
|
716
737
|
/**
|
|
717
738
|
* Fetch the next lesson for a specific method by Railcontent ID.
|
|
718
739
|
* @param {string} railcontentId - The Railcontent ID of the current lesson.
|
package/test/log.js
ADDED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {initializeService} from '../src/services/config.js';
|
|
2
|
+
import {log} from './log.js';
|
|
2
3
|
|
|
3
4
|
const {
|
|
4
5
|
fetchSongById,
|
|
@@ -37,14 +38,14 @@ const {
|
|
|
37
38
|
|
|
38
39
|
describe('Sanity Queries', function () {
|
|
39
40
|
beforeEach(() => {
|
|
40
|
-
const config = {
|
|
41
|
+
const config = {
|
|
41
42
|
sanityConfig: {
|
|
42
43
|
token: process.env.SANITY_API_TOKEN,
|
|
43
44
|
projectId: process.env.SANITY_PROJECT_ID,
|
|
44
45
|
dataset: process.env.SANITY_DATASET,
|
|
45
|
-
useCachedAPI: process.env.SANITY_USE_CACHED_API || true,
|
|
46
|
+
useCachedAPI: process.env.SANITY_USE_CACHED_API === 'true' || true,
|
|
46
47
|
version: '2021-06-07',
|
|
47
|
-
debug: process.env.DEBUG || false
|
|
48
|
+
debug: process.env.DEBUG === 'true' || false
|
|
48
49
|
}
|
|
49
50
|
};
|
|
50
51
|
initializeService(config);
|
|
@@ -66,7 +67,7 @@ describe('Sanity Queries', function () {
|
|
|
66
67
|
|
|
67
68
|
test('fetchSongArtistCount', async () => {
|
|
68
69
|
const response = await fetchSongArtistCount('drumeo');
|
|
69
|
-
|
|
70
|
+
log(response);
|
|
70
71
|
expect(response).toBeGreaterThan(1000);
|
|
71
72
|
});
|
|
72
73
|
|
|
@@ -95,7 +96,7 @@ describe('Sanity Queries', function () {
|
|
|
95
96
|
|
|
96
97
|
test('fetchAllSongs', async () => {
|
|
97
98
|
const response = await fetchAllSongs('drumeo', {});
|
|
98
|
-
|
|
99
|
+
log(response);
|
|
99
100
|
expect(response.entity[0].soundslice).toBeDefined();
|
|
100
101
|
expect(response.entity[0].artist_name).toBeDefined();
|
|
101
102
|
expect(response.entity[0].instrumentless).toBeDefined();
|
|
@@ -111,20 +112,20 @@ describe('Sanity Queries', function () {
|
|
|
111
112
|
|
|
112
113
|
test('fetchAllWorkouts', async () => {
|
|
113
114
|
const response = await fetchAll('drumeo', 'workout',{});
|
|
114
|
-
|
|
115
|
+
log(response);
|
|
115
116
|
expect(response.entity[0].id).toBeDefined();
|
|
116
117
|
});
|
|
117
118
|
|
|
118
119
|
test('fetchAllInstructorField', async () => {
|
|
119
120
|
const response = await fetchAll('drumeo', 'quick-tips',{searchTerm: 'Domino Santantonio'});
|
|
120
|
-
|
|
121
|
+
log(response);
|
|
121
122
|
expect(response.entity[0].id).toBeDefined();
|
|
122
123
|
expect(response.entity[0].instructors).toBeTruthy();
|
|
123
124
|
});
|
|
124
125
|
|
|
125
126
|
test('fetchAllSortField', async () => {
|
|
126
127
|
const response = await fetchAll('drumeo', 'rhythmic-adventures-of-captain-carson',{});
|
|
127
|
-
|
|
128
|
+
log(response);
|
|
128
129
|
expect(response.entity[0].id).toBeDefined();
|
|
129
130
|
expect(response.entity[0].sort).toBeDefined();
|
|
130
131
|
});
|
|
@@ -132,7 +133,7 @@ describe('Sanity Queries', function () {
|
|
|
132
133
|
|
|
133
134
|
test('fetchAllChallenges', async () => {
|
|
134
135
|
const response = await fetchAll('drumeo', 'challenge',{});
|
|
135
|
-
|
|
136
|
+
log(response);
|
|
136
137
|
expect(response.entity[0].registration_url).toBeDefined();
|
|
137
138
|
expect(response.entity[0].enrollment_start_time).toBeDefined();
|
|
138
139
|
expect(response.entity[0].enrollment_end_time).toBeDefined();
|
|
@@ -146,12 +147,12 @@ describe('Sanity Queries', function () {
|
|
|
146
147
|
|
|
147
148
|
test('fetchAll-CustomFields', async () => {
|
|
148
149
|
let response = await fetchAll('drumeo', 'challenge',{customFields:['garbage']});
|
|
149
|
-
|
|
150
|
+
log(response);
|
|
150
151
|
expect(response.entity[0].garbage).toBeDefined();
|
|
151
152
|
expect(response.entity[0].id).toBeDefined();
|
|
152
153
|
|
|
153
154
|
response = await fetchAll('drumeo', 'challenge',{useDefaultFields: false, customFields:['garbage']});
|
|
154
|
-
|
|
155
|
+
log(response);
|
|
155
156
|
expect(response.entity[0].garbage).toBeDefined();
|
|
156
157
|
expect.not.objectContaining(response.entity[0].id);
|
|
157
158
|
});
|
|
@@ -177,8 +178,8 @@ describe('Sanity Queries', function () {
|
|
|
177
178
|
const id = 191338; ////https://web-staging-one.musora.com/admin/studio/publishing/structure/play-along;play-along_191338
|
|
178
179
|
const expectedChildID = 191492;
|
|
179
180
|
const response = await fetchChildren(id);
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
log('num children', response.length);
|
|
182
|
+
log(response);
|
|
182
183
|
|
|
183
184
|
expect(response.length > 0).toBeTruthy();
|
|
184
185
|
const foundExpectedChild = response.some((child) => {
|
|
@@ -209,15 +210,14 @@ describe('Sanity Queries', function () {
|
|
|
209
210
|
});
|
|
210
211
|
|
|
211
212
|
test('fetchMethod', async () => {
|
|
212
|
-
const response = await fetchMethod('drumeo', 'drumeo-method');
|
|
213
|
-
//console.log(response);
|
|
213
|
+
const response = await fetchMethod('drumeo', 'drumeo-method');log(response);
|
|
214
214
|
expect(response).toBeDefined();
|
|
215
215
|
expect(response.levels.length).toBeGreaterThan(0);
|
|
216
216
|
});
|
|
217
217
|
|
|
218
218
|
test('fetchMethods', async () => {
|
|
219
219
|
const response = await fetchMethods('drumeo');
|
|
220
|
-
|
|
220
|
+
log(response);
|
|
221
221
|
expect(response.length).toBeGreaterThan(0);
|
|
222
222
|
expect(response[0].type).toBe('learning-path');
|
|
223
223
|
});
|
|
@@ -250,15 +250,14 @@ describe('Sanity Queries', function () {
|
|
|
250
250
|
});
|
|
251
251
|
|
|
252
252
|
test('fetchFoundation', async () => {
|
|
253
|
-
const response = await fetchFoundation('foundations-2019');
|
|
254
|
-
// console.log(response);
|
|
253
|
+
const response = await fetchFoundation('foundations-2019');log(response);
|
|
255
254
|
expect(response.units.length).toBeGreaterThan(0);
|
|
256
255
|
expect(response.type).toBe('foundation');
|
|
257
256
|
});
|
|
258
257
|
|
|
259
258
|
test('fetchPackAll', async () => {
|
|
260
259
|
const response = await fetchPackAll(212899); //https://web-staging-one.musora.com/admin/studio/publishing/structure/pack;pack_212899%2Cinspect%3Don
|
|
261
|
-
|
|
260
|
+
log(response);
|
|
262
261
|
expect(response.slug).toBe('creative-control');
|
|
263
262
|
});
|
|
264
263
|
|
|
@@ -266,8 +265,9 @@ describe('Sanity Queries', function () {
|
|
|
266
265
|
let response = await fetchAllPacks('drumeo');
|
|
267
266
|
response = await fetchAllPacks('drumeo', 'slug');
|
|
268
267
|
const titles = response.map((doc) => doc.title);
|
|
269
|
-
|
|
270
|
-
|
|
268
|
+
|
|
269
|
+
const sortedTitles = [...titles].sort((a, b) => a === b ? 0 : a > b ? 1 : -1);
|
|
270
|
+
|
|
271
271
|
expect(titles).toStrictEqual(sortedTitles);
|
|
272
272
|
response = await fetchAllPacks('drumeo', 'slug', 'Creative Control');
|
|
273
273
|
expect(response[0].id).toBe(212899);
|
|
@@ -292,4 +292,22 @@ describe('Sanity Queries', function () {
|
|
|
292
292
|
const response = await fetchScheduledReleases('drumeo', {});
|
|
293
293
|
expect(response.length).toBeGreaterThan(0);
|
|
294
294
|
});
|
|
295
|
+
|
|
296
|
+
test('fetchAll-GroupBy-Genre', async () => {
|
|
297
|
+
let response = await fetchAll('drumeo', 'solo',{groupBy: 'genre'});
|
|
298
|
+
log(response);
|
|
299
|
+
expect(response.entity[0].web_url_path).toContain('/drumeo/genres/');
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
test('fetchAll-GroupBy-Artists', async () => {
|
|
303
|
+
let response = await fetchAll('drumeo', 'song',{groupBy: 'artist'});
|
|
304
|
+
log(response);
|
|
305
|
+
expect(response.entity[0].web_url_path).toContain('/drumeo/artists/');
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
test('fetchAll-GroupBy-Instructors', async () => {
|
|
309
|
+
let response = await fetchAll('drumeo', 'course',{groupBy: 'instructor'});
|
|
310
|
+
log(response);
|
|
311
|
+
expect(response.entity[0].web_url_path).toContain('/drumeo/coaches/');
|
|
312
|
+
});
|
|
295
313
|
});
|