musora-content-services 1.0.78 → 1.0.81

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
@@ -2,6 +2,12 @@
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
+ ### [1.0.81](https://github.com/railroadmedia/musora-content-services/compare/v1.0.80...v1.0.81) (2024-09-05)
6
+
7
+ ### [1.0.80](https://github.com/railroadmedia/musora-content-services/compare/v1.0.79...v1.0.80) (2024-09-05)
8
+
9
+ ### [1.0.79](https://github.com/railroadmedia/musora-content-services/compare/v1.0.77...v1.0.79) (2024-09-05)
10
+
5
11
  ### [1.0.77](https://github.com/railroadmedia/musora-content-services/compare/v1.0.76...v1.0.77) (2024-09-04)
6
12
 
7
13
  ### [1.0.76](https://github.com/railroadmedia/musora-content-services/compare/v1.0.75...v1.0.76) (2024-08-30)
package/link_mcs.sh CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "1.0.78",
3
+ "version": "1.0.81",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/publish.sh CHANGED
File without changes
@@ -134,13 +134,14 @@ let contentTypeConfig = {
134
134
  'low_soundslice_slug'
135
135
  ]
136
136
  },
137
- 'pack-bundle': {
137
+ 'pack-children': {
138
138
  'fields': [
139
139
  'child_count',
140
140
  `"children": child[]->{
141
141
  "description": ${descriptionField},
142
142
  ${getFieldsForContentType()}
143
143
  }`,
144
+ '"resources": resource',
144
145
  '"image": logo_image_url.asset->url',
145
146
  '"thumbnail": thumbnail.asset->url',
146
147
  '"light_logo": light_mode_logo_url.asset->url',
@@ -149,6 +150,33 @@ let contentTypeConfig = {
149
150
  'total_xp',
150
151
  ]
151
152
  },
153
+ 'foundation': {
154
+ 'fields': [
155
+ `"description": ${descriptionField}`,
156
+ `"instructors":instructor[]->name`,
157
+ `"units": child[]->{
158
+ "id": railcontent_id,
159
+ published_on,
160
+ child_count,
161
+ difficulty,
162
+ difficulty_string,
163
+ "thumbnail_url": thumbnail.asset->url,
164
+ "instructor": instructor[]->{name},
165
+ title,
166
+ "type": _type,
167
+ "description": ${descriptionField},
168
+ "url": web_url_path,
169
+ xp,
170
+ }`
171
+ ]
172
+ },
173
+ 'instructor': {
174
+ 'fields': [
175
+ 'name',
176
+ '"coach_card_image": coach_card_image.asset->url',
177
+ 'focus'
178
+ ]
179
+ },
152
180
  // content with just the added 'instructors' Field
153
181
  'student-focus': contentWithInstructorsField,
154
182
  'quick-tips': contentWithInstructorsField,
package/src/index.d.ts CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  fetchByRailContentIds,
15
15
  fetchAll,
16
16
  fetchAllFilterOptions,
17
+ fetchFoundation,
17
18
  fetchMethods,
18
19
  fetchMethod,
19
20
  fetchMethodChildren,
@@ -51,6 +52,7 @@ declare module 'musora-content-services' {
51
52
  fetchByRailContentIds,
52
53
  fetchAll,
53
54
  fetchAllFilterOptions,
55
+ fetchFoundation,
54
56
  fetchMethods,
55
57
  fetchMethod,
56
58
  fetchMethodNextLesson,
package/src/index.js CHANGED
@@ -16,6 +16,7 @@ import {
16
16
  fetchAll,
17
17
  fetchAllFilterOptions,
18
18
  fetchMethodNextLesson,
19
+ fetchFoundation,
19
20
  fetchMethod,
20
21
  fetchMethods,
21
22
  fetchMethodChildren,
@@ -38,6 +39,7 @@ import {
38
39
  fetchAllCompletedStates,
39
40
  fetchContentInProgress,
40
41
  fetchVimeoData,
42
+ fetchContentPageUserData,
41
43
  } from './services/railcontent.js';
42
44
 
43
45
 
@@ -57,6 +59,7 @@ export {
57
59
  fetchByRailContentIds,
58
60
  fetchAll,
59
61
  fetchAllFilterOptions,
62
+ fetchFoundation,
60
63
  fetchMethods,
61
64
  fetchMethod,
62
65
  fetchMethodChildren,
@@ -77,4 +80,5 @@ export {
77
80
  fetchLiveEvent,
78
81
  fetchChallengeOverview,
79
82
  fetchVimeoData,
83
+ fetchContentPageUserData,
80
84
  }
@@ -366,6 +366,7 @@ export async function fetchByRailContentIds(ids, contentType = undefined) {
366
366
  * @param {string} [params.sort="-published_on"] - The field to sort the content by.
367
367
  * @param {Array<string>} [params.includedFields=[]] - The fields to include in the query.
368
368
  * @param {string} [params.groupBy=""] - The field to group the results by (e.g., 'artist', 'genre').
369
+ * @param {Array<string>} [params.progressIds=undefined] - An array of railcontent IDs to filter the results by. Used for filtering by progress.
369
370
  * @returns {Promise<Object|null>} - The fetched content data or null if not found.
370
371
  *
371
372
  * @example
@@ -386,7 +387,8 @@ export async function fetchAll(brand, type, {
386
387
  searchTerm = "",
387
388
  sort = "-published_on",
388
389
  includedFields = [],
389
- groupBy = ""
390
+ groupBy = "",
391
+ progressIds = undefined
390
392
  } = {}) {
391
393
  let config = contentTypeConfig[type] ?? {};
392
394
  let additionalFields = config?.fields ?? [];
@@ -406,6 +408,10 @@ export async function fetchAll(brand, type, {
406
408
  ? filtersToGroq(includedFields)
407
409
  : "";
408
410
 
411
+ // limits the results to supplied progressIds for started & completed filters
412
+ const progressFilter = progressIds !== undefined ?
413
+ `&& railcontent_id in [${progressIds.join(',')}]` : "";
414
+
409
415
  // Determine the sort order
410
416
  const sortOrder = getSortOrder(sort);
411
417
 
@@ -417,15 +423,15 @@ export async function fetchAll(brand, type, {
417
423
  if (groupBy !== "" && isGroupByOneToOne) {
418
424
  query = `
419
425
  {
420
- "total": count(*[_type == '${groupBy}' && count(*[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter}]._id) > 0]),
421
- "entity": *[_type == '${groupBy}' && count(*[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter}]._id) > 0]
426
+ "total": count(*[_type == '${groupBy}' && count(*[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]),
427
+ "entity": *[_type == '${groupBy}' && count(*[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]
422
428
  {
423
429
  'id': _id,
424
430
  'type': _type,
425
431
  name,
426
432
  'head_shot_picture_url': thumbnail_url.asset->url,
427
- 'all_lessons_count': count(*[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter}]._id),
428
- 'lessons': *[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter}]{
433
+ 'all_lessons_count': count(*[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id),
434
+ 'lessons': *[_type == '${type}' && brand == '${brand}' && ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{
429
435
  ${fieldsString},
430
436
  ${groupBy}
431
437
  }[0...10]
@@ -436,15 +442,15 @@ export async function fetchAll(brand, type, {
436
442
  } else if (groupBy !== "") {
437
443
  query = `
438
444
  {
439
- "total": count(*[_type == '${groupBy}' && count(*[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter}]._id) > 0]),
440
- "entity": *[_type == '${groupBy}' && count(*[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter}]._id) > 0]
445
+ "total": count(*[_type == '${groupBy}' && count(*[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]),
446
+ "entity": *[_type == '${groupBy}' && count(*[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]
441
447
  {
442
448
  'id': _id,
443
449
  'type': _type,
444
450
  name,
445
451
  'head_shot_picture_url': thumbnail_url.asset->url,
446
- 'all_lessons_count': count(*[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter}]._id),
447
- 'lessons': *[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter}]{
452
+ 'all_lessons_count': count(*[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id),
453
+ 'lessons': *[_type == '${type}' && brand == '${brand}' && ^._id in ${groupBy}[]._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{
448
454
  ${fieldsString},
449
455
  ${groupBy}
450
456
  }[0...10]
@@ -455,10 +461,10 @@ export async function fetchAll(brand, type, {
455
461
  } else {
456
462
  query = `
457
463
  {
458
- "entity": *[_type == '${type}' && brand == "${brand}" ${searchFilter} ${includedFieldsFilter}] | order(${sortOrder}) [${start}...${end}] {
464
+ "entity": *[_type == '${type}' && brand == "${brand}" ${searchFilter} ${includedFieldsFilter} ${progressFilter}] | order(${sortOrder}) [${start}...${end}] {
459
465
  ${fieldsString}
460
466
  },
461
- "total": count(*[_type == '${type}' && brand == "${brand}" ${searchFilter} ${includedFieldsFilter}])
467
+ "total": count(*[_type == '${type}' && brand == "${brand}" ${searchFilter} ${includedFieldsFilter} ${progressFilter}])
462
468
  }
463
469
  `;
464
470
  }
@@ -500,7 +506,7 @@ export function getSortOrder(sort= '-published_on', groupBy)
500
506
  * @param {string} [artist] - Optional artist name to filter the results. If provided, the query will check if the artist's name matches.
501
507
  * @param {string} contentType - The content type to fetch (e.g., 'song', 'lesson').
502
508
  * @param {string} [term] - Optional search term to match against various fields such as title, album, artist name, and genre.
503
- *
509
+ * @param {Array<string>} [progressIds=undefined] - An array of railcontent IDs to filter the results by. Used for filtering by progress.
504
510
  * @returns {Promise<Object|null>} - A promise that resolves to an object containing the total results and filter options, or null if the query fails.
505
511
  *
506
512
  * @example
@@ -515,11 +521,15 @@ export async function fetchAllFilterOptions(
515
521
  style,
516
522
  artist,
517
523
  contentType,
518
- term
524
+ term,
525
+ progressIds = undefined
519
526
  ) {
520
527
  const includedFieldsFilter = filters?.length > 0 ? filtersToGroq(filters) : undefined;
521
528
 
522
- const commonFilter = `_type == '${contentType}' && brand == "${brand}"${style ? ` && '${style}' in genre[]->name` : ''}${artist ? ` && artist->name == '${artist}'` : ''} ${includedFieldsFilter ? includedFieldsFilter : ''}`;
529
+ const progressFilter = progressIds !== undefined ?
530
+ `&& railcontent_id in [${progressIds.join(',')}]` : "";
531
+
532
+ const commonFilter = `_type == '${contentType}' && brand == "${brand}"${style ? ` && '${style}' in genre[]->name` : ''}${artist ? ` && artist->name == '${artist}'` : ''} ${progressFilter} ${includedFieldsFilter ? includedFieldsFilter : ''}`;
523
533
  const query = `
524
534
  {
525
535
  "meta": {
@@ -594,6 +604,18 @@ export async function fetchMethods(brand) {
594
604
  return fetchSanity(query, true);
595
605
  }
596
606
 
607
+ /**
608
+ * Fetch the Foundations 2019.
609
+ * @param {string} slug - The slug of the method.
610
+ * @returns {Promise<Object|null>} - The fetched foundation data or null if not found.
611
+ */
612
+ export async function fetchFoundation(slug) {
613
+ const query = `*[_type == 'foundation' && slug.current == "${slug}"] {
614
+ ${ getFieldsForContentType('foundation') }
615
+ } | order(published_on asc)`
616
+ return fetchSanity(query, false);
617
+ }
618
+
597
619
  /**
598
620
  * Fetch the Method (learning-paths) for a specific brand.
599
621
  * @param {string} brand - The brand for which to fetch methods.
@@ -27,6 +27,7 @@ const {
27
27
  fetchChildren,
28
28
  fetchMethod,
29
29
  fetchMethods,
30
+ fetchFoundation,
30
31
  } = require('../src/services/sanity.js');
31
32
 
32
33
  describe('Sanity Queries', function () {
@@ -203,4 +204,38 @@ describe('Sanity Queries', function () {
203
204
  expect(response.length).toBeGreaterThan(0);
204
205
  expect(response[0].type).toBe('learning-path');
205
206
  });
207
+
208
+ test('fetchAll-WithProgress', async () => {
209
+ const ids = [410213, 305649];
210
+ let response = await fetchAll('drumeo', 'song', {
211
+ sort: 'slug',
212
+ progressIds: ids,
213
+ });
214
+ expect(response.entity.length).toBe(2);
215
+ expect(response.entity[0].id = 305649);
216
+ expect(response.entity[1].id = 410213);
217
+ // change the type and we expect no results
218
+ response = await fetchAll('drumeo', 'quick-tip', {
219
+ sort: 'slug',
220
+ progressIds: ids,
221
+ });
222
+ expect(response.entity.length).toBe(0);
223
+ });
224
+
225
+ test('fetchAllFilterOptions-WithProgress', async () => {
226
+ const ids = [410213, 305649];
227
+ let response = await fetchAllFilterOptions('drumeo', '', '', '', 'song', '', ids);
228
+ expect(response.meta.totalResults).toBe(2);
229
+ // change the brand and we expect no results
230
+ response = await fetchAllFilterOptions('singeo', '', '', '', 'song', '', ids);
231
+ expect(response.meta.totalResults).toBe(0);
232
+
233
+ });
234
+
235
+ test('fetchFoundation', async () => {
236
+ const response = await fetchFoundation('foundations-2019');
237
+ //console.log(response);
238
+ expect(response.units.length).toBeGreaterThan(0);
239
+ expect(response.type).toBe('foundation');
240
+ });
206
241
  });