musora-content-services 2.20.0 → 2.21.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.
Files changed (166) hide show
  1. package/.coderabbit.yaml +0 -0
  2. package/.editorconfig +0 -0
  3. package/.github/pull_request_template.md +0 -0
  4. package/.github/workflows/conventional-commits.yaml +0 -0
  5. package/.github/workflows/docs.js.yml +0 -0
  6. package/.github/workflows/node.js.yml +0 -0
  7. package/.prettierignore +0 -0
  8. package/.prettierrc +0 -0
  9. package/.yarnrc.yml +1 -0
  10. package/CHANGELOG.md +15 -0
  11. package/README.md +0 -0
  12. package/babel.config.cjs +0 -0
  13. package/docs/Content-Organization.html +0 -0
  14. package/docs/ContentOrganization.html +0 -0
  15. package/docs/Gamification.html +0 -0
  16. package/docs/UserManagement.html +0 -0
  17. package/docs/UserManagementSystem.html +0 -0
  18. package/docs/api_types.js.html +0 -0
  19. package/docs/config.js.html +0 -0
  20. package/docs/content-org_content-org.js.html +0 -0
  21. package/docs/content-org_playlists-types.js.html +0 -0
  22. package/docs/content-org_playlists.js.html +0 -0
  23. package/docs/content.js.html +0 -0
  24. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  25. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  26. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  27. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  28. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  29. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  30. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  31. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  32. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  33. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
  34. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  35. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  36. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  37. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  38. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
  39. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  40. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  41. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  42. package/docs/gamification_awards.js.html +0 -0
  43. package/docs/gamification_gamification.js.html +0 -0
  44. package/docs/gamification_types.js.html +0 -0
  45. package/docs/global.html +0 -0
  46. package/docs/global.html#User +0 -0
  47. package/docs/index.html +0 -0
  48. package/docs/module-Awards.html +0 -0
  49. package/docs/module-Config.html +0 -0
  50. package/docs/module-Content-Services-V2.html +0 -0
  51. package/docs/module-Interests.html +0 -0
  52. package/docs/module-Notifications.html +0 -0
  53. package/docs/module-Permissions.html +0 -0
  54. package/docs/module-Playlists.html +0 -0
  55. package/docs/module-Railcontent-Services.html +0 -0
  56. package/docs/module-Sanity-Services.html +0 -0
  57. package/docs/module-Session-Management.html +0 -0
  58. package/docs/module-Sessions.html +0 -0
  59. package/docs/module-User-Activity.html +0 -0
  60. package/docs/module-User-Management.html +0 -0
  61. package/docs/module-User-Permissions.html +0 -0
  62. package/docs/module-UserActivity.html +0 -0
  63. package/docs/module-UserChat.html +0 -0
  64. package/docs/module-UserManagement.html +0 -0
  65. package/docs/module-UserNotifications.html +0 -0
  66. package/docs/module-UserProfile.html +0 -0
  67. package/docs/railcontent.js.html +0 -0
  68. package/docs/sanity.js.html +0 -0
  69. package/docs/scripts/collapse.js +0 -0
  70. package/docs/scripts/commonNav.js +0 -0
  71. package/docs/scripts/linenumber.js +0 -0
  72. package/docs/scripts/nav.js +0 -0
  73. package/docs/scripts/polyfill.js +0 -0
  74. package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
  75. package/docs/scripts/prettify/lang-css.js +0 -0
  76. package/docs/scripts/prettify/prettify.js +0 -0
  77. package/docs/scripts/search.js +0 -0
  78. package/docs/styles/jsdoc.css +0 -0
  79. package/docs/styles/prettify.css +0 -0
  80. package/docs/types.js.html +0 -0
  81. package/docs/userActivity.js.html +0 -0
  82. package/docs/user_chat.js.html +0 -0
  83. package/docs/user_interests.js.html +0 -0
  84. package/docs/user_management.js.html +0 -0
  85. package/docs/user_notifications.js.html +0 -0
  86. package/docs/user_permissions.js.html +0 -0
  87. package/docs/user_profile.js.html +0 -0
  88. package/docs/user_sessions.js.html +0 -0
  89. package/docs/user_types.js.html +0 -0
  90. package/docs/user_user-management-system.js.html +0 -0
  91. package/docs/user_user-management.js.html +0 -0
  92. package/jest.config.js +0 -0
  93. package/jsdoc.json +0 -0
  94. package/link_mcs.sh +0 -0
  95. package/package.json +1 -1
  96. package/src/contentMetaData.js +0 -0
  97. package/src/contentTypeConfig.js +3 -3
  98. package/src/filterBuilder.js +0 -0
  99. package/src/index.d.ts +2 -0
  100. package/src/index.js +2 -0
  101. package/src/infrastructure/http/HttpClient.ts +0 -0
  102. package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
  103. package/src/infrastructure/http/index.ts +0 -0
  104. package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
  105. package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
  106. package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
  107. package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
  108. package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
  109. package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
  110. package/src/lib/httpHelper.js +0 -0
  111. package/src/lib/lastUpdated.js +0 -0
  112. package/src/services/api/types.js +0 -0
  113. package/src/services/config.js +0 -0
  114. package/src/services/content-org/content-org.js +0 -0
  115. package/src/services/content-org/playlists-types.js +0 -0
  116. package/src/services/content-org/playlists.js +0 -0
  117. package/src/services/content.js +42 -25
  118. package/src/services/contentAggregator.js +18 -3
  119. package/src/services/contentLikes.js +0 -0
  120. package/src/services/contentProgress.js +7 -1
  121. package/src/services/dataContext.js +0 -0
  122. package/src/services/dateUtils.js +0 -0
  123. package/src/services/forum.js +0 -0
  124. package/src/services/gamification/awards.js +0 -0
  125. package/src/services/gamification/gamification.js +0 -0
  126. package/src/services/gamification/types.js +0 -0
  127. package/src/services/imageSRCBuilder.js +0 -0
  128. package/src/services/railcontent.js +0 -0
  129. package/src/services/recommendations.js +8 -5
  130. package/src/services/sanity.js +15 -0
  131. package/src/services/types.js +0 -0
  132. package/src/services/user/account.ts +0 -0
  133. package/src/services/user/chat.js +0 -0
  134. package/src/services/user/interests.js +0 -0
  135. package/src/services/user/management.js +0 -0
  136. package/src/services/user/notifications.js +0 -0
  137. package/src/services/user/permissions.js +0 -0
  138. package/src/services/user/profile.js +0 -0
  139. package/src/services/user/sessions.js +0 -0
  140. package/src/services/user/types.js +0 -0
  141. package/src/services/user/user-management-system.js +0 -0
  142. package/test/HttpClient.test.js +0 -0
  143. package/test/content.test.js +0 -0
  144. package/test/contentLikes.test.js +0 -0
  145. package/test/contentProgress.test.js +0 -0
  146. package/test/dataContext.test.js +0 -0
  147. package/test/forum.test.js +0 -0
  148. package/test/imageSRCBuilder.test.js +0 -0
  149. package/test/imageSRCVerify.test.js +0 -0
  150. package/test/initializeTests.js +0 -0
  151. package/test/lib/lastUpdated.test.js +0 -0
  152. package/test/live/contentProgressLive.test.js +0 -0
  153. package/test/live/railcontentLive.test.js +0 -0
  154. package/test/localStorageMock.js +0 -0
  155. package/test/log.js +0 -0
  156. package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
  157. package/test/mockData/mockData_progress_content.json +0 -0
  158. package/test/mockData/mockData_sanity_progress_content.json +0 -0
  159. package/test/mockData/mockData_user_practices.json +0 -0
  160. package/test/notifications.test.js +0 -0
  161. package/test/progressRows.test.js +0 -0
  162. package/test/sanityQueryService.test.js +0 -0
  163. package/test/streakMessage.test.js +0 -0
  164. package/test/user/permissions.test.js +0 -0
  165. package/test/userActivity.test.js +0 -0
  166. package/tools/generate-index.cjs +0 -0
package/.coderabbit.yaml CHANGED
File without changes
package/.editorconfig CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
package/.prettierignore CHANGED
File without changes
package/.prettierrc CHANGED
File without changes
package/.yarnrc.yml ADDED
@@ -0,0 +1 @@
1
+ nodeLinker: node-modules
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
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.21.1](https://github.com/railroadmedia/musora-content-services/compare/v2.21.0...v2.21.1) (2025-07-14)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * track correct amount of video watch time ([07d31c8](https://github.com/railroadmedia/musora-content-services/commit/07d31c802164b0625b5e72ce78e618fc5d12ecaf))
11
+ * track correct amount of video watch time ([41a0d0b](https://github.com/railroadmedia/musora-content-services/commit/41a0d0b82d73183c52db7b510d00bbf7838554d0))
12
+
13
+ ## [2.21.0](https://github.com/railroadmedia/musora-content-services/compare/v2.20.0...v2.21.0) (2025-07-12)
14
+
15
+
16
+ ### Features
17
+
18
+ * **BEH-572:** ai recommender row categories ([#337](https://github.com/railroadmedia/musora-content-services/issues/337)) ([d1984d2](https://github.com/railroadmedia/musora-content-services/commit/d1984d28371fa2d4f22d8ddb50fdcfd952399b46))
19
+
5
20
  ## [2.20.0](https://github.com/railroadmedia/musora-content-services/compare/v2.19.2...v2.20.0) (2025-07-11)
6
21
 
7
22
 
package/README.md CHANGED
File without changes
package/babel.config.cjs CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/docs/global.html CHANGED
File without changes
File without changes
package/docs/index.html CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/jest.config.js CHANGED
File without changes
package/jsdoc.json CHANGED
File without changes
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": "2.20.0",
3
+ "version": "2.21.1",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
File without changes
@@ -24,7 +24,6 @@ export const DEFAULT_FIELDS = [
24
24
  "'url': web_url_path",
25
25
  'published_on',
26
26
  "'type': _type",
27
- 'progress_percent',
28
27
  "'length_in_seconds' : coalesce(length_in_seconds, soundslice[0].soundslice_length_in_second)",
29
28
  'brand',
30
29
  "'genre': genre[]->name",
@@ -139,7 +138,7 @@ export const singleLessonTypes = ['quick-tips', 'rudiment', 'coach-lessons'];
139
138
  export const practiceAlongsLessonTypes = ['workout', 'boot-camp','challenges'];
140
139
  export const performancesLessonTypes = ['performance','solo','drum-fest-international-2022'];
141
140
  export const documentariesLessonTypes = ['tama','sonor','history-of-electronic-drums','paiste-cymbals'];
142
- export const liveArchivesLessonTypes = ['podcast', 'coach-stream', 'question-and-answer', 'live-streams'];
141
+ export const liveArchivesLessonTypes = ['podcast', 'coach-stream', 'question-and-answer', 'live-streams', 'live'];
143
142
  export const studentArchivesLessonTypes = ['student-review', 'student-focus','student-collaboration'];
144
143
  export const tutorialsLessonTypes = ['song-tutorial'];
145
144
  export const transcriptionsLessonTypes = ['song'];
@@ -209,7 +208,8 @@ export const filterTypes = {
209
208
  export const recentTypes = {
210
209
  lessons: [...individualLessonsTypes],
211
210
  songs: [...tutorialsLessonTypes, ...transcriptionsLessonTypes, ...playAlongLessonTypes],
212
- home: [...individualLessonsTypes, ...tutorialsLessonTypes, ...transcriptionsLessonTypes, ...playAlongLessonTypes]
211
+ home: [...individualLessonsTypes, ...tutorialsLessonTypes, ...transcriptionsLessonTypes, ...playAlongLessonTypes,
212
+ 'guided-course', 'learning-path', 'live']
213
213
  }
214
214
 
215
215
  export let contentTypeConfig = {
File without changes
package/src/index.d.ts CHANGED
@@ -189,6 +189,7 @@ import {
189
189
  fetchCoachLessons,
190
190
  fetchComingSoon,
191
191
  fetchCommentModContentData,
192
+ fetchContentRows,
192
193
  fetchFoundation,
193
194
  fetchGenreLessons,
194
195
  fetchHierarchy,
@@ -364,6 +365,7 @@ declare module 'musora-content-services' {
364
365
  fetchContentInProgress,
365
366
  fetchContentPageUserData,
366
367
  fetchContentProgress,
368
+ fetchContentRows,
367
369
  fetchEnrollmentPageMetadata,
368
370
  fetchFoundation,
369
371
  fetchGenreLessons,
package/src/index.js CHANGED
@@ -189,6 +189,7 @@ import {
189
189
  fetchCoachLessons,
190
190
  fetchComingSoon,
191
191
  fetchCommentModContentData,
192
+ fetchContentRows,
192
193
  fetchFoundation,
193
194
  fetchGenreLessons,
194
195
  fetchHierarchy,
@@ -363,6 +364,7 @@ export {
363
364
  fetchContentInProgress,
364
365
  fetchContentPageUserData,
365
366
  fetchContentProgress,
367
+ fetchContentRows,
366
368
  fetchEnrollmentPageMetadata,
367
369
  fetchFoundation,
368
370
  fetchGenreLessons,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -11,11 +11,12 @@ import {
11
11
  fetchUpcomingEvents,
12
12
  fetchScheduledReleases,
13
13
  fetchReturning,
14
- fetchLeaving, fetchScheduledAndNewReleases
14
+ fetchLeaving, fetchScheduledAndNewReleases, fetchContentRows
15
15
  } from './sanity.js'
16
16
  import {TabResponseType, Tabs, capitalizeFirstLetter} from '../contentMetaData.js'
17
17
  import {fetchHandler} from "./railcontent";
18
- import {recommendations} from "./recommendations";
18
+ import {recommendations, rankCategories} from "./recommendations";
19
+ import {addContextToContent} from "./contentAggregator.js";
19
20
 
20
21
 
21
22
  export async function getLessonContentRows (brand='drumeo', pageName = 'lessons') {
@@ -149,11 +150,11 @@ export async function getRecent(brand, pageName, tabName = 'all', {
149
150
  }
150
151
 
151
152
  /**
152
- * Fetches content rows for a given brand and page with optional filtering by content row id.
153
+ * Fetches content rows for a given brand and page with optional filtering by content row slug.
153
154
  *
154
155
  * @param {string} brand - The brand for which to fetch content rows.
155
156
  * @param {string} pageName - The page name (e.g., 'lessons', 'songs', 'challenges').
156
- * @param {string} [contentRowId] - The specific content row ID to fetch.
157
+ * @param {string|null} contentRowSlug - The specific content row ID to fetch.
157
158
  * @param {Object} params - Parameters for pagination.
158
159
  * @param {number} [params.page=1] - The page number for pagination.
159
160
  * @param {number} [params.limit=10] - The maximum number of content items per row.
@@ -168,32 +169,48 @@ export async function getRecent(brand, pageName, tabName = 'all', {
168
169
  * .then(content => console.log(content))
169
170
  * .catch(error => console.error(error));
170
171
  */
171
- export async function getContentRows(brand, pageName, contentRowId , {
172
+ export async function getContentRows(brand, pageName, contentRowSlug = null, {
172
173
  page = 1,
173
- limit = 10,
174
+ limit = 10
174
175
  } = {}) {
175
- const contentRow = contentRowId ? `&content_row_id=${contentRowId}` : ''
176
- const url = `/api/content/v1/rows?brand=${brand}&page_name=${pageName}${contentRow}&page=${page}&limit=${limit}`;
177
- const contentRows = await fetchHandler(url, 'get', null) || [];
178
- const results = await Promise.all(
179
- contentRows.map(async (row) => {
180
- if (row.content.length === 0){
181
- return { id: row.id, title: row.title, items: [] }
182
- }
183
- const data = await fetchByRailContentIds(row.content)
184
- return { id: row.id, title: row.title, items: data }
185
- })
186
- )
176
+ const sanityData = await addContextToContent(fetchContentRows, brand, pageName, contentRowSlug, {
177
+ dataField: 'content',
178
+ iterateDataFieldOnEachArrayElement: true,
179
+ addProgressStatus: true,
180
+ addProgressPercentage: true,
181
+ addNextLesson: true
182
+ })
183
+ if (!sanityData) {
184
+ return []
185
+ }
186
+ let contentMap = {}
187
+ let recData = {}
188
+ let slugNameMap = {}
189
+ for (const category of sanityData) {
190
+ recData[category.slug] = category.content.map(item => item.railcontent_id)
191
+ for (const content of category.content) {
192
+ contentMap[content.railcontent_id] = content
193
+ }
194
+ slugNameMap[category.slug] = category.name
195
+ }
196
+ const start = (page - 1) * limit
197
+ const end = start + limit
198
+ const sortedData = await rankCategories(brand, recData)
199
+ let finalData = []
200
+ for (const category of sortedData) {
201
+ finalData.push( {
202
+ id: category.slug,
203
+ title: slugNameMap[category.slug],
204
+ items: category.items.slice(start, end).map(id => contentMap[id])})
205
+ }
187
206
 
188
- if (contentRowId) {
189
- return {
207
+ return contentRowSlug ?
208
+ {
190
209
  type: TabResponseType.CATALOG,
191
- data: results[0].items,
210
+ data: finalData[0].items,
192
211
  meta: {}
193
- };
194
- }
195
-
196
- return results
212
+ }
213
+ : finalData
197
214
  }
198
215
 
199
216
  /**
@@ -16,6 +16,7 @@ export async function addContextToContent(dataPromise, ...dataArgs)
16
16
 
17
17
  const {
18
18
  dataField = null,
19
+ iterateDataFieldOnEachArrayElement = false,
19
20
  addProgressPercentage = false,
20
21
  addIsLiked = false,
21
22
  addLikeCount = false,
@@ -34,8 +35,14 @@ export async function addContextToContent(dataPromise, ...dataArgs)
34
35
  let items = []
35
36
  let dataMap = []
36
37
 
37
- if (dataField && data?.[dataField]) {
38
- items = data[dataField];
38
+ if (dataField && (data?.[dataField] || iterateDataFieldOnEachArrayElement)) {
39
+ if (iterateDataFieldOnEachArrayElement && Array.isArray(data)) {
40
+ for(const parent of data) {
41
+ ids = [...ids, ...parent[dataField].map(item => item?.id).filter(Boolean)]
42
+ }
43
+ } else {
44
+ ids = data[dataField].map(item => item?.id).filter(Boolean);
45
+ }
39
46
  } else if (Array.isArray(data)) {
40
47
  items = data;
41
48
  } else if (data?.id) {
@@ -85,9 +92,17 @@ export async function addContextToContent(dataPromise, ...dataArgs)
85
92
  }
86
93
 
87
94
  if (dataField) {
88
- data[dataField] = Array.isArray(data[dataField])
95
+ if (iterateDataFieldOnEachArrayElement) {
96
+ for(let parent of data) {
97
+ parent[dataField] = Array.isArray(parent[dataField])
98
+ ? await Promise.all(parent[dataField].map(addContext))
99
+ : await addContext(parent[dataField])
100
+ }
101
+ } else {
102
+ data[dataField] = Array.isArray(data[dataField])
89
103
  ? await Promise.all(data[dataField].map(addContext))
90
104
  : await addContext(data[dataField])
105
+ }
91
106
  return data
92
107
  } else {
93
108
  return Array.isArray(data)
File without changes
@@ -18,6 +18,8 @@ const DATA_KEY_LAST_UPDATED_TIME = 'u'
18
18
 
19
19
  export let dataContext = new DataContext(ContentProgressVersionKey, fetchContentProgress)
20
20
 
21
+ let sessionData = []
22
+
21
23
  export async function getProgressPercentage(contentId) {
22
24
  return getById(contentId, DATA_KEY_PROGRESS, 0)
23
25
  }
@@ -383,10 +385,14 @@ export async function recordWatchSession(
383
385
  }
384
386
 
385
387
  try {
386
- await recordUserPractice({ content_id: contentId, duration_seconds: Math.ceil(secondsPlayed) })
388
+ //TODO: Good enough for Alpha, Refine in reliability improvements
389
+ sessionData[sessionId] = sessionData[sessionId] || {}
390
+ const secondsSinceLastUpdate = Math.ceil(secondsPlayed - (sessionData[sessionId][contentId] ?? 0))
391
+ await recordUserPractice({ content_id: contentId, duration_seconds: secondsSinceLastUpdate })
387
392
  } catch (error) {
388
393
  console.error('Failed to record user practice:', error)
389
394
  }
395
+ sessionData[sessionId][contentId] = secondsPlayed
390
396
 
391
397
  await dataContext.update(
392
398
  async function (localContext) {
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -80,11 +80,14 @@ export async function rankCategories(brand, categories) {
80
80
  globalConfig.recommendationsConfig.token
81
81
  )
82
82
  const response = await httpClient.post(url, data)
83
- let rankedCategories = {}
84
- response['ranked_playlists'].forEach(
85
- (category) =>
86
- (rankedCategories[category['playlist_id']] = categories[category['playlist_id']])
87
- )
83
+ let rankedCategories = []
84
+
85
+ for (const rankedPlaylist of response['ranked_playlists']) {
86
+ rankedCategories.push({
87
+ 'slug': rankedPlaylist.playlist_id,
88
+ 'items': rankedPlaylist.ranked_items
89
+ })
90
+ }
88
91
  return rankedCategories
89
92
  } catch (error) {
90
93
  console.error('Fetch error:', error)
@@ -540,6 +540,21 @@ export async function fetchByRailContentIds(ids, contentType = undefined, brand
540
540
  return sortedResults
541
541
  }
542
542
 
543
+ export async function fetchContentRows(brand, pageName, contentRowSlug)
544
+ {
545
+ if (pageName === 'lessons') pageName = 'lesson'
546
+ if (pageName === 'songs') pageName = 'song'
547
+ const rowString = contentRowSlug ? ` && slug.current == "${contentRowSlug.toLowerCase()}"` : ''
548
+ return fetchSanity(`*[_type == 'recommended-content-row' && brand == '${brand}' && type == '${pageName}'${rowString}]{
549
+ brand,
550
+ name,
551
+ 'slug': slug.current,
552
+ 'content': content[]->{ ${getFieldsForContentType()} }
553
+ }`, true)
554
+ }
555
+
556
+
557
+
543
558
  /**
544
559
  * Fetch all content for a specific brand and type with pagination, search, and grouping options.
545
560
  * @param {string} brand - The brand for which to fetch content.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/test/log.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes