musora-content-services 2.104.4 → 2.104.7

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 (212) hide show
  1. package/.claude/settings.local.json +3 -10
  2. package/.coderabbit.yaml +0 -0
  3. package/.editorconfig +0 -0
  4. package/.github/pull_request_template.md +0 -0
  5. package/.github/workflows/conventional-commits.yaml +0 -0
  6. package/.github/workflows/docs.js.yml +0 -0
  7. package/.github/workflows/node.js.yml +0 -0
  8. package/.prettierignore +0 -0
  9. package/.prettierrc +0 -0
  10. package/CHANGELOG.md +17 -0
  11. package/CLAUDE.md +0 -0
  12. package/README.md +0 -0
  13. package/babel.config.cjs +0 -0
  14. package/jest.config.js +0 -0
  15. package/jsdoc.json +0 -0
  16. package/package.json +1 -1
  17. package/src/constants/award-assets.js +0 -0
  18. package/src/contentMetaData.js +0 -0
  19. package/src/filterBuilder.js +0 -0
  20. package/src/infrastructure/http/HttpClient.ts +0 -0
  21. package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
  22. package/src/infrastructure/http/index.ts +0 -0
  23. package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
  24. package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
  25. package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
  26. package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
  27. package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
  28. package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
  29. package/src/lib/ads/monoid.ts +0 -0
  30. package/src/lib/ads/semigroup.ts +0 -0
  31. package/src/lib/brands.ts +0 -0
  32. package/src/lib/httpHelper.js +0 -0
  33. package/src/lib/lastUpdated.js +0 -0
  34. package/src/lib/sanity/filter.ts +13 -0
  35. package/src/lib/sanity/query.ts +0 -0
  36. package/src/services/api/types.js +0 -0
  37. package/src/services/api/types.ts +0 -0
  38. package/src/services/awards/award-callbacks.js +0 -0
  39. package/src/services/awards/internal/.indexignore +0 -0
  40. package/src/services/awards/internal/award-definitions.js +0 -0
  41. package/src/services/awards/internal/award-events.js +0 -0
  42. package/src/services/awards/internal/certificate-builder.js +0 -0
  43. package/src/services/awards/internal/completion-data-generator.js +0 -0
  44. package/src/services/awards/internal/content-progress-observer.js +0 -0
  45. package/src/services/awards/internal/image-utils.js +0 -0
  46. package/src/services/awards/internal/message-generator.js +0 -0
  47. package/src/services/awards/internal/types.js +0 -0
  48. package/src/services/awards/types.d.ts +0 -0
  49. package/src/services/awards/types.js +0 -0
  50. package/src/services/config.js +0 -0
  51. package/src/services/content/artist.ts +17 -25
  52. package/src/services/content/content.ts +0 -0
  53. package/src/services/content/genre.ts +17 -25
  54. package/src/services/content/instructor.ts +15 -23
  55. package/src/services/content-org/content-org.js +0 -0
  56. package/src/services/content-org/guided-courses.ts +0 -0
  57. package/src/services/content-org/learning-paths.ts +87 -37
  58. package/src/services/content-org/playlists-types.js +0 -0
  59. package/src/services/contentAggregator.js +0 -0
  60. package/src/services/contentLikes.js +0 -0
  61. package/src/services/contentProgress.js +0 -0
  62. package/src/services/dataContext.js +0 -0
  63. package/src/services/dateUtils.js +0 -0
  64. package/src/services/eventsAPI.js +0 -0
  65. package/src/services/forums/categories.ts +0 -0
  66. package/src/services/forums/forums.ts +0 -0
  67. package/src/services/forums/posts.ts +0 -0
  68. package/src/services/forums/threads.ts +0 -0
  69. package/src/services/forums/types.ts +0 -0
  70. package/src/services/gamification/awards.ts +0 -0
  71. package/src/services/gamification/gamification.js +0 -0
  72. package/src/services/imageSRCBuilder.js +0 -0
  73. package/src/services/imageSRCVerify.js +0 -0
  74. package/src/services/liveTesting.ts +0 -0
  75. package/src/services/permissions/PermissionsAdapter.ts +0 -0
  76. package/src/services/permissions/PermissionsAdapterFactory.ts +0 -0
  77. package/src/services/permissions/PermissionsV1Adapter.ts +0 -0
  78. package/src/services/permissions/PermissionsV2Adapter.ts +0 -0
  79. package/src/services/permissions/README.md +0 -0
  80. package/src/services/permissions/index.ts +0 -0
  81. package/src/services/progress-events.js +0 -0
  82. package/src/services/progress-row/method-card.js +38 -24
  83. package/src/services/recommendations.js +0 -0
  84. package/src/services/reporting/README.md +0 -0
  85. package/src/services/reporting/types.ts +0 -0
  86. package/src/services/sanity.js +8 -4
  87. package/src/services/sentry/.indexignore +0 -0
  88. package/src/services/sentry/index.ts +0 -0
  89. package/src/services/sync/.indexignore +0 -0
  90. package/src/services/sync/adapters/factory.ts +0 -0
  91. package/src/services/sync/adapters/lokijs.ts +0 -0
  92. package/src/services/sync/adapters/sqlite.ts +0 -0
  93. package/src/services/sync/concurrency-safety.ts +0 -0
  94. package/src/services/sync/context/index.ts +0 -0
  95. package/src/services/sync/context/providers/base.ts +0 -0
  96. package/src/services/sync/context/providers/connectivity.ts +0 -0
  97. package/src/services/sync/context/providers/durability.ts +0 -0
  98. package/src/services/sync/context/providers/index.ts +0 -0
  99. package/src/services/sync/context/providers/session.ts +0 -0
  100. package/src/services/sync/context/providers/tabs.ts +0 -0
  101. package/src/services/sync/context/providers/visibility.ts +0 -0
  102. package/src/services/sync/database/factory.ts +0 -0
  103. package/src/services/sync/errors/boundary.ts +0 -0
  104. package/src/services/sync/errors/index.ts +0 -0
  105. package/src/services/sync/fetch.ts +0 -0
  106. package/src/services/sync/index.ts +0 -0
  107. package/src/services/sync/manager.ts +0 -0
  108. package/src/services/sync/models/Base.ts +0 -0
  109. package/src/services/sync/models/ContentLike.ts +0 -0
  110. package/src/services/sync/models/ContentProgress.ts +0 -0
  111. package/src/services/sync/models/Practice.ts +0 -0
  112. package/src/services/sync/models/PracticeDayNote.ts +0 -0
  113. package/src/services/sync/models/UserAwardProgress.ts +0 -0
  114. package/src/services/sync/models/index.ts +0 -0
  115. package/src/services/sync/repositories/base.ts +0 -0
  116. package/src/services/sync/repositories/content-likes.ts +0 -0
  117. package/src/services/sync/repositories/content-progress.ts +0 -0
  118. package/src/services/sync/repositories/index.ts +0 -0
  119. package/src/services/sync/repositories/practice-day-notes.ts +0 -0
  120. package/src/services/sync/repositories/practices.ts +0 -0
  121. package/src/services/sync/repository-proxy.ts +0 -0
  122. package/src/services/sync/resolver.ts +0 -0
  123. package/src/services/sync/retry.ts +0 -0
  124. package/src/services/sync/run-scope.ts +0 -0
  125. package/src/services/sync/schema/index.ts +0 -0
  126. package/src/services/sync/serializers/index.ts +0 -0
  127. package/src/services/sync/serializers/model.ts +0 -0
  128. package/src/services/sync/serializers/raw.ts +0 -0
  129. package/src/services/sync/store/index.ts +0 -0
  130. package/src/services/sync/store/push-coalescer.ts +0 -0
  131. package/src/services/sync/store-configs.ts +0 -0
  132. package/src/services/sync/strategies/base.ts +0 -0
  133. package/src/services/sync/strategies/index.ts +0 -0
  134. package/src/services/sync/strategies/initial.ts +0 -0
  135. package/src/services/sync/strategies/polling.ts +0 -0
  136. package/src/services/sync/telemetry/index.ts +0 -0
  137. package/src/services/sync/telemetry/sampling.ts +0 -0
  138. package/src/services/sync/utils/event-emitter.ts +0 -0
  139. package/src/services/sync/utils/index.ts +0 -0
  140. package/src/services/sync/utils/throttle.ts +0 -0
  141. package/src/services/sync/utils/timers.ts +0 -0
  142. package/src/services/types.js +0 -0
  143. package/src/services/user/account.ts +0 -0
  144. package/src/services/user/chat.js +0 -0
  145. package/src/services/user/interests.js +0 -0
  146. package/src/services/user/management.js +0 -0
  147. package/src/services/user/memberships.ts +0 -0
  148. package/src/services/user/notifications.js +0 -0
  149. package/src/services/user/onboarding.ts +0 -0
  150. package/src/services/user/payments.ts +0 -0
  151. package/src/services/user/permissions.js +0 -0
  152. package/src/services/user/profile.js +0 -0
  153. package/src/services/user/sessions.js +0 -0
  154. package/src/services/user/types.d.ts +0 -0
  155. package/src/services/user/types.js +0 -0
  156. package/src/services/user/user-management-system.js +0 -0
  157. package/src/services/userActivity.js +0 -0
  158. package/test/HttpClient.test.js +0 -0
  159. package/test/awards/award-alacarte-observer.test.js +0 -0
  160. package/test/awards/award-auto-refresh.test.js +0 -0
  161. package/test/awards/award-calculations.test.js +0 -0
  162. package/test/awards/award-certificate-display.test.js +0 -0
  163. package/test/awards/award-collection-edge-cases.test.js +0 -0
  164. package/test/awards/award-collection-filtering.test.js +0 -0
  165. package/test/awards/award-exclusion-handling.test.js +0 -0
  166. package/test/awards/award-multi-lesson.test.js +0 -0
  167. package/test/awards/award-observer-integration.test.js +0 -0
  168. package/test/awards/award-query-messages.test.js +0 -0
  169. package/test/awards/award-user-collection.test.js +0 -0
  170. package/test/awards/duplicate-prevention.test.js +0 -0
  171. package/test/awards/helpers/completion-mock.js +0 -0
  172. package/test/awards/helpers/index.js +0 -0
  173. package/test/awards/helpers/mock-setup.js +0 -0
  174. package/test/awards/helpers/progress-emitter.js +0 -0
  175. package/test/awards/message-generator.test.js +0 -0
  176. package/test/content.test.js +0 -0
  177. package/test/contentLikes.test.js +0 -0
  178. package/test/contentProgress.test.js +0 -0
  179. package/test/dataContext.test.js +0 -0
  180. package/test/forum.test.js +0 -0
  181. package/test/imageSRCBuilder.test.js +0 -0
  182. package/test/imageSRCVerify.test.js +0 -0
  183. package/test/initializeTests.js +0 -0
  184. package/test/learningPaths.test.js +0 -0
  185. package/test/lib/__snapshots__/filter.test.ts.snap +0 -0
  186. package/test/lib/filter.test.ts +0 -0
  187. package/test/lib/lastUpdated.test.js +0 -0
  188. package/test/lib/query.test.ts +0 -0
  189. package/test/live/contentProgressLive.test.js +0 -0
  190. package/test/live/railcontentLive.test.js +0 -0
  191. package/test/localStorageMock.js +0 -0
  192. package/test/log.js +0 -0
  193. package/test/mockData/award-definitions.js +0 -0
  194. package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
  195. package/test/mockData/mockData_progress_content.json +0 -0
  196. package/test/mockData/mockData_sanity_progress_content.json +0 -0
  197. package/test/mockData/mockData_user_practices.json +0 -0
  198. package/test/notifications.test.js +0 -0
  199. package/test/progressRows.test.js +0 -0
  200. package/test/sanityQueryService.test.js +0 -0
  201. package/test/streakMessage.test.js +0 -0
  202. package/test/sync/adapter.ts +0 -0
  203. package/test/sync/initialize-sync-manager.js +0 -0
  204. package/test/sync/models/award-database-integration.test.js +0 -0
  205. package/test/user/permissions.test.js +0 -0
  206. package/test/userActivity.test.js +0 -0
  207. package/tools/generate-index.cjs +0 -0
  208. package/.yarnrc.yml +0 -1
  209. package/check_content.js +0 -30
  210. package/check_content.mjs +0 -32
  211. package/test/reporting.test.js +0 -132
  212. package/test_owned_navigate.js +0 -74
@@ -72,7 +72,7 @@ export async function getDailySession(brand: string, userDate: Date) {
72
72
  export async function updateDailySession(
73
73
  brand: string,
74
74
  userDate: Date,
75
- keepFirstLearningPath: boolean
75
+ keepFirstLearningPath: boolean = false
76
76
  ) {
77
77
  const stringDate = userDate.toISOString().split('T')[0]
78
78
  const url: string = `${LEARNING_PATHS_PATH}/daily-session/create`
@@ -194,6 +194,23 @@ export function mapContentToParent(lessons, parentContentType, parentContentId)
194
194
  })
195
195
  }
196
196
 
197
+ interface fetchLearningPathLessonsResponse {
198
+ id: number
199
+ thumbnail?: string
200
+ title: string
201
+ children: any[]
202
+ is_active_learning_path: boolean
203
+ active_learning_path_id?: number
204
+ active_learning_path_created_at?: string
205
+ upcoming_lessons?: any[]
206
+ completed_lessons?: any[]
207
+ learning_path_dailies?: any[]
208
+ next_learning_path_dailies?: any[]
209
+ next_learning_path_id?: number
210
+ previous_learning_path_dailies?: any[]
211
+ previous_learning_path_id?: number
212
+ }
213
+
197
214
  /** Fetches and organizes learning path lessons.
198
215
  *
199
216
  * @param {number} learningPathId - The learning path ID.
@@ -203,13 +220,17 @@ export function mapContentToParent(lessons, parentContentType, parentContentId)
203
220
  * @returns {number} result.id - The learning path ID.
204
221
  * @returns {string} result.thumbnail - Optional thumbnail URL for the learning path.
205
222
  * @returns {string} result.title - The title of the learning path.
206
- * @returns {boolean} result.is_active_learning_path - Whether the learning path is currently active.
207
223
  * @returns {Array} result.children - Array of all lessons.
208
- * @returns {Array} result.upcoming_lessons - Array of upcoming/additional lessons.
209
- * @returns {Array} result.todays_lessons - Array of today's lessons (max 3).
210
- * @returns {Array} result.next_learning_path_lessons - Array of next lessons to be taken.
211
- * @returns {Array} result.completed_lessons - Array of completed lessons.
212
- * @returns {Array} result.previous_learning_path_todays - Array of completed lessons.
224
+ * @returns {boolean} result.is_active_learning_path - Whether the learning path is currently active.
225
+ * @returns {number} result.active_learning_path_id - The active learning path ID from daily session.
226
+ * @returns {string} result.active_learning_path_created_at - The datetime the learning path was set as active.
227
+ * @returns {Array} result.upcoming_lessons - Array of upcoming lessons.
228
+ * @returns {Array} result.learning_path_dailies - Array of today's dailies in this learning path.
229
+ * @returns {Array} result.next_learning_path_dailies - Array of today's dailies in the next learning path.
230
+ * @returns {number} result.next_learning_path_id - the next learning path (after the active path).
231
+ * @returns {Array} result.completed_lessons - Array of completed lessons in this learning path.
232
+ * @returns {Array} result.previous_learning_path_dailies - Array of today's dailies in the previous learning path.
233
+ * @returns {number} result.previous_learning_path_id - the previous learning path (before the active path)
213
234
  */
214
235
  export async function fetchLearningPathLessons(
215
236
  learningPathId: number,
@@ -217,9 +238,9 @@ export async function fetchLearningPathLessons(
217
238
  userDate: Date
218
239
  ) {
219
240
  const learningPath = await getEnrichedLearningPath(learningPathId)
220
- let dailySession = await getDailySession(brand, userDate); // what if the call just fails, and a DS does exist?
241
+ let dailySession = await getDailySession(brand, userDate) as DailySessionResponse // what if the call just fails, and a DS does exist?
221
242
  if (!dailySession) {
222
- dailySession = await updateDailySession(brand, userDate, false)
243
+ dailySession = await updateDailySession(brand, userDate, false) as DailySessionResponse
223
244
  }
224
245
 
225
246
  const isActiveLearningPath = (dailySession?.active_learning_path_id || 0) == learningPathId
@@ -227,48 +248,64 @@ export async function fetchLearningPathLessons(
227
248
  return {
228
249
  ...learningPath,
229
250
  is_active_learning_path: isActiveLearningPath,
230
- }
251
+ } as fetchLearningPathLessonsResponse
231
252
  }
232
- // this assumes that the first entry is active_path, based on user flows
233
- const todayContentIds = dailySession.daily_session[0]?.content_ids || []
234
- const todayLearningPathId = dailySession.daily_session[0]?.learning_path_id
235
253
 
236
- const nextContentIds = dailySession.daily_session[1]?.content_ids || []
237
- const nextLearningPathId = dailySession.daily_session[1]?.learning_path_id
254
+ let todayContentIds = []
255
+ let todayLearningPathId = null
256
+ let nextContentIds = []
257
+ let nextLearningPathId = null
258
+ let previousContentIds = []
259
+ let previousLearningPathId = null
260
+
261
+
262
+
263
+ for (const session of dailySession.daily_session) {
264
+ if (session.learning_path_id === learningPathId) {
265
+ todayContentIds = session.content_ids || []
266
+ todayLearningPathId = session.learning_path_id
267
+ } else {
268
+ if (!todayLearningPathId) {
269
+ previousContentIds = session.content_ids || []
270
+ previousLearningPathId = session.learning_path_id
271
+ } else if (!nextLearningPathId) {
272
+ nextContentIds = session.content_ids || []
273
+ nextLearningPathId = session.learning_path_id
274
+ }
275
+ }
276
+ }
238
277
 
239
278
  const completedLessons = []
240
279
  let thisLPDailies = []
241
280
  let nextLPDailies = []
242
- let previousLearningPathTodays = []
281
+ let previousLPDailies = []
243
282
  const upcomingLessons = []
244
283
 
284
+ //previous/next never within LP
245
285
  learningPath.children.forEach((lesson: any) => {
246
286
  if (todayContentIds.includes(lesson.id)) {
247
287
  thisLPDailies.push(lesson)
248
- } else if (lesson.progressStatus === 'completed') {
288
+ } else if (lesson.progressStatus === STATE.COMPLETED) {
249
289
  completedLessons.push(lesson)
250
290
  } else {
251
291
  upcomingLessons.push(lesson)
252
292
  }
253
293
  })
254
294
 
255
- if (thisLPDailies.length == 0) {
256
- // Daily sessions first lessons are not part of the active learning path, but next lessons are
257
- // load todays lessons from previous learning path
258
- previousLearningPathTodays = await getLearningPathLessonsByIds(
259
- todayContentIds,
260
- todayLearningPathId
295
+ if (previousContentIds.length !== 0) {
296
+ previousLPDailies = await getLearningPathLessonsByIds(
297
+ previousContentIds,
298
+ previousLearningPathId
261
299
  )
262
- } else if ( // show next LP dailies if they exist
263
- nextContentIds.length > 0
264
- ) {
265
- // Daily sessions first lessons are the active learning path and the next lessons are not
266
- // load next lessons from next learning path
267
- const lessons = await getLearningPathLessonsByIds(nextContentIds, nextLearningPathId)
268
- nextLPDailies = lessons.map(lesson => ({
300
+ }
301
+ if (nextContentIds.length !== 0) {
302
+ nextLPDailies = await getLearningPathLessonsByIds(
303
+ nextContentIds,
304
+ nextLearningPathId
305
+ ).then(lessons => lessons.map(lesson => ({
269
306
  ...lesson,
270
- in_next_learning_path: STATE.COMPLETED === learningPath.progressStatus
271
- }))
307
+ in_next_learning_path: learningPath.progressStatus === STATE.COMPLETED
308
+ })))
272
309
  }
273
310
 
274
311
  return {
@@ -277,11 +314,12 @@ export async function fetchLearningPathLessons(
277
314
  active_learning_path_id: dailySession?.active_learning_path_id,
278
315
  active_learning_path_created_at: dailySession?.active_learning_path_created_at,
279
316
  upcoming_lessons: upcomingLessons,
280
- todays_lessons: thisLPDailies,
281
- next_learning_path_lessons: nextLPDailies,
282
- next_learning_path_id: nextLearningPathId,
283
317
  completed_lessons: completedLessons,
284
- previous_learning_path_todays: previousLearningPathTodays,
318
+ learning_path_dailies: thisLPDailies,
319
+ next_learning_path_dailies: nextLPDailies,
320
+ next_learning_path_id: nextLearningPathId,
321
+ previous_learning_path_dailies: previousLPDailies,
322
+ previous_learning_path_id: previousLearningPathId,
285
323
  }
286
324
  }
287
325
 
@@ -341,12 +379,14 @@ interface completeLearningPathIntroVideo {
341
379
  intro_video_response: SyncWriteDTO<ContentProgress, any> | null
342
380
  learning_path_reset_response: SyncWriteDTO<ContentProgress, any> | null
343
381
  lesson_import_response: SyncWriteDTO<ContentProgress, any> | null
382
+ update_dailies_response: DailySessionResponse | null
344
383
  }
345
384
  /**
346
385
  * Handles completion of learning path intro video and other related actions.
347
386
  * @param introVideoId - The learning path intro video content ID.
348
387
  * @param learningPathId - The content_id of the learning path that this learning path intro video belongs to.
349
388
  * @param lessonsToImport - content ids for all lessons with progress found during intro video progress check. empty if user chose not to keep learning path progress.
389
+ * @param brand
350
390
  * @returns {Promise<Array>} response - The response object.
351
391
  * @returns {Promise<Object|null>} response.intro_video_response - The intro video completion response or null if already completed.
352
392
  * @returns {Promise<void>} response.learning_path_reset_response - The reset learning path response.
@@ -355,7 +395,8 @@ interface completeLearningPathIntroVideo {
355
395
  export async function completeLearningPathIntroVideo(
356
396
  introVideoId: number,
357
397
  learningPathId: number,
358
- lessonsToImport: number[] | null
398
+ lessonsToImport: number[] | null,
399
+ brand: string | null
359
400
  ) {
360
401
  let response = {} as completeLearningPathIntroVideo
361
402
 
@@ -368,6 +409,15 @@ export async function completeLearningPathIntroVideo(
368
409
 
369
410
  } else {
370
411
  response.lesson_import_response = await contentStatusCompletedMany(lessonsToImport, collection)
412
+
413
+ const activePath = await getActivePath(brand)
414
+ if (activePath.active_learning_path_id === learningPathId) {
415
+ response.update_dailies_response = await updateDailySession(
416
+ brand,
417
+ getToday(),
418
+ true
419
+ )
420
+ }
371
421
  }
372
422
 
373
423
  return response
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
@@ -6,7 +6,7 @@ import { getActivePath, fetchLearningPathLessons } from '../content-org/learning
6
6
  import { getToday } from '../dateUtils.js'
7
7
  import { fetchMethodV2IntroVideo } from '../sanity'
8
8
  import { getProgressState } from '../contentProgress'
9
- import { COLLECTION_TYPE } from '../sync/models/ContentProgress'
9
+ import {COLLECTION_TYPE, STATE} from '../sync/models/ContentProgress'
10
10
 
11
11
  export async function getMethodCard(brand) {
12
12
  const introVideo = await fetchMethodV2IntroVideo(brand)
@@ -19,7 +19,7 @@ export async function getMethodCard(brand) {
19
19
 
20
20
  const activeLearningPath = await getActivePath(brand)
21
21
 
22
- if (introVideoProgressState !== 'completed' || !activeLearningPath) {
22
+ if (introVideoProgressState !== STATE.COMPLETED || !activeLearningPath) {
23
23
  //startLearningPath('drumeo', 422533)
24
24
  const timestamp = Math.floor(Date.now() / 1000)
25
25
  const instructorText =
@@ -43,43 +43,57 @@ export async function getMethodCard(brand) {
43
43
  progressTimestamp: timestamp,
44
44
  }
45
45
  } else {
46
- //TODO: Optimize loading of dailySessions/Path, should not need multiple requests
47
46
  const learningPath = await fetchLearningPathLessons(
48
47
  activeLearningPath.active_learning_path_id,
49
48
  brand,
50
49
  getToday()
51
50
  )
52
51
 
53
- const allCompleted = learningPath?.todays_lessons.every(
54
- (lesson) => lesson.progressStatus === 'completed'
55
- )
56
-
57
- const anyCompleted = learningPath?.todays_lessons.some(
58
- (lesson) => lesson.progressStatus === 'completed'
59
- )
60
-
61
- const noneCompleted = learningPath?.todays_lessons.every(
62
- (lesson) => lesson.progressStatus !== 'completed'
63
- )
52
+ if (!learningPath) {
53
+ return null
54
+ }
64
55
 
65
- const nextIncompleteLesson = learningPath?.todays_lessons.find(
66
- (lesson) => lesson.progressStatus !== 'completed'
67
- )
56
+ // need to calculate based on all dailies
57
+ const allDailies = [
58
+ ...learningPath.previous_learning_path_dailies,
59
+ ...learningPath.learning_path_dailies,
60
+ ...learningPath.next_learning_path_dailies
61
+ ]
62
+
63
+ let allDailiesCompleted = true;
64
+ let anyDailiesCompleted = false;
65
+ let noDailiesCompleted = true;
66
+ let nextIncompleteDaily = null;
67
+
68
+ for (const lesson of allDailies) {
69
+ if (lesson.progressStatus === STATE.COMPLETED) {
70
+ anyDailiesCompleted = true;
71
+ noDailiesCompleted = false;
72
+ } else {
73
+ allDailiesCompleted = false;
74
+ if (!nextIncompleteDaily) {
75
+ nextIncompleteDaily = lesson;
76
+ }
77
+ }
78
+ if (!allDailiesCompleted && anyDailiesCompleted && nextIncompleteDaily) {
79
+ break;
80
+ }
81
+ }
68
82
 
69
83
  // get the first incomplete lesson from upcoming and next learning path lessons
70
84
  const nextLesson = [
71
85
  ...learningPath?.upcoming_lessons,
72
- ...learningPath?.next_learning_path_lessons,
73
- ]?.find((lesson) => lesson.progressStatus !== 'completed')
86
+ ...learningPath?.next_learning_path_dailies,
87
+ ]?.find((lesson) => lesson.progressStatus !== STATE.COMPLETED)
74
88
 
75
89
  let ctaText, action
76
- if (noneCompleted) {
90
+ if (noDailiesCompleted) {
77
91
  ctaText = 'Start Session'
78
- action = getMethodActionCTA(nextIncompleteLesson)
79
- } else if (anyCompleted && !allCompleted) {
92
+ action = getMethodActionCTA(nextIncompleteDaily)
93
+ } else if (anyDailiesCompleted && !allDailiesCompleted) {
80
94
  ctaText = 'Continue Session'
81
- action = getMethodActionCTA(nextIncompleteLesson)
82
- } else if (allCompleted) {
95
+ action = getMethodActionCTA(nextIncompleteDaily)
96
+ } else if (allDailiesCompleted) {
83
97
  ctaText = nextLesson ? 'Start Next Lesson' : 'Browse Lessons'
84
98
  action = nextLesson
85
99
  ? getMethodActionCTA(nextLesson)
File without changes
File without changes
File without changes
@@ -1306,7 +1306,7 @@ export async function fetchByReference(
1306
1306
  * @returns {Promise<int|null>}
1307
1307
  */
1308
1308
  export async function fetchTopLevelParentId(railcontentId) {
1309
- const parentFilter = "railcontent_id in [...(^.parent_content_data[].id)]"
1309
+ const parentFilter = 'railcontent_id in [...(^.parent_content_data[].id)]'
1310
1310
  const statusFilter = "&& status in ['scheduled', 'published', 'archived', 'unlisted']"
1311
1311
 
1312
1312
  const query = `*[railcontent_id == ${railcontentId}]{
@@ -1379,7 +1379,7 @@ export async function fetchHierarchy(railcontentId) {
1379
1379
  }
1380
1380
 
1381
1381
  function populateHierarchyLookups(currentLevel, data, parentId) {
1382
- const railcontentIdField = currentLevel.railcontent_id ? "railcontent_id" : "id";
1382
+ const railcontentIdField = currentLevel.railcontent_id ? 'railcontent_id' : 'id'
1383
1383
 
1384
1384
  let contentId = currentLevel[railcontentIdField]
1385
1385
  let children = currentLevel['children']
@@ -1534,6 +1534,10 @@ function contentResultsDecorator(results, fieldName, callback) {
1534
1534
  results.related_lessons.forEach((result) => {
1535
1535
  result[fieldName] = callback(result)
1536
1536
  })
1537
+ } else if (results.data && Array.isArray(results.data)) {
1538
+ results.data.forEach((result) => {
1539
+ result[fieldName] = callback(result)
1540
+ })
1537
1541
  } else {
1538
1542
  results[fieldName] = callback(results)
1539
1543
  }
@@ -2017,7 +2021,7 @@ export async function fetchMethodV2Structure(brand) {
2017
2021
  * @returns {Promise<*|null>}
2018
2022
  */
2019
2023
  export async function fetchMethodV2StructureFromId(contentId) {
2020
- const _type = "method-v2";
2024
+ const _type = 'method-v2'
2021
2025
  const query = `*[_type == '${_type}' && brand == *[railcontent_id == ${contentId}][0].brand][0...1]{
2022
2026
  'sanity_id': _id,
2023
2027
  brand,
@@ -2028,7 +2032,7 @@ export async function fetchMethodV2StructureFromId(contentId) {
2028
2032
  'children': child[]->railcontent_id
2029
2033
  }
2030
2034
  }`
2031
- return await fetchSanity(query, false);
2035
+ return await fetchSanity(query, false)
2032
2036
  }
2033
2037
 
2034
2038
  /**
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
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