musora-content-services 2.8.2 → 2.8.3

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 (160) 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/node.js.yml +0 -0
  5. package/.prettierignore +0 -0
  6. package/.prettierrc +0 -0
  7. package/.yarnrc.yml +1 -0
  8. package/CHANGELOG.md +2 -0
  9. package/README.md +0 -0
  10. package/babel.config.cjs +0 -0
  11. package/docs/Content-Organization.html +0 -0
  12. package/docs/ContentOrganization.html +2 -2
  13. package/docs/Gamification.html +2 -2
  14. package/docs/UserManagement.html +0 -0
  15. package/docs/UserManagementSystem.html +2 -2
  16. package/docs/api_types.js.html +2 -2
  17. package/docs/config.js.html +2 -2
  18. package/docs/content-org_content-org.js.html +2 -2
  19. package/docs/content-org_playlists-types.js.html +2 -2
  20. package/docs/content-org_playlists.js.html +14 -2
  21. package/docs/content.js.html +2 -2
  22. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  23. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  24. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  25. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  26. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  27. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  28. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  29. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  30. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  31. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
  32. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  33. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  34. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  35. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  36. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
  37. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  38. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  39. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  40. package/docs/gamification_awards.js.html +2 -2
  41. package/docs/gamification_gamification.js.html +2 -2
  42. package/docs/gamification_types.js.html +2 -2
  43. package/docs/global.html +2 -2
  44. package/docs/global.html#User +0 -0
  45. package/docs/index.html +2 -2
  46. package/docs/module-Awards.html +2 -2
  47. package/docs/module-Config.html +2 -2
  48. package/docs/module-Content-Services-V2.html +2 -2
  49. package/docs/module-Content-Services.html +763 -0
  50. package/docs/module-Interests.html +2 -2
  51. package/docs/module-Notifications.html +1183 -0
  52. package/docs/module-Permissions.html +2 -2
  53. package/docs/module-Playlists.html +322 -12
  54. package/docs/module-Railcontent-Services.html +2 -2
  55. package/docs/module-Sanity-Services.html +2 -2
  56. package/docs/module-Session-Management.html +0 -0
  57. package/docs/module-Sessions.html +2 -2
  58. package/docs/module-User-Activity.html +0 -0
  59. package/docs/module-User-Management.html +0 -0
  60. package/docs/module-User-Permissions.html +0 -0
  61. package/docs/module-UserActivity.html +4410 -0
  62. package/docs/module-UserManagement.html +2 -2
  63. package/docs/module-UserNotifications.html +1183 -0
  64. package/docs/module-UserProfile.html +2 -2
  65. package/docs/railcontent.js.html +2 -2
  66. package/docs/sanity.js.html +2 -2
  67. package/docs/scripts/collapse.js +0 -0
  68. package/docs/scripts/commonNav.js +0 -0
  69. package/docs/scripts/linenumber.js +0 -0
  70. package/docs/scripts/nav.js +0 -0
  71. package/docs/scripts/polyfill.js +0 -0
  72. package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
  73. package/docs/scripts/prettify/lang-css.js +0 -0
  74. package/docs/scripts/prettify/prettify.js +0 -0
  75. package/docs/scripts/search.js +0 -0
  76. package/docs/styles/jsdoc.css +0 -0
  77. package/docs/styles/prettify.css +0 -0
  78. package/docs/types.js.html +0 -0
  79. package/docs/userActivity.js.html +197 -46
  80. package/docs/user_interests.js.html +2 -2
  81. package/docs/user_management.js.html +2 -2
  82. package/docs/user_notifications.js.html +189 -0
  83. package/docs/user_permissions.js.html +2 -2
  84. package/docs/user_profile.js.html +2 -2
  85. package/docs/user_sessions.js.html +2 -2
  86. package/docs/user_types.js.html +2 -2
  87. package/docs/user_user-management-system.js.html +2 -2
  88. package/docs/user_user-management.js.html +0 -0
  89. package/jest.config.js +0 -0
  90. package/jsdoc.json +0 -0
  91. package/package.json +1 -1
  92. package/src/contentMetaData.js +0 -0
  93. package/src/filterBuilder.js +0 -0
  94. package/src/index.d.ts +13 -0
  95. package/src/index.js +13 -0
  96. package/src/infrastructure/http/HttpClient.ts +0 -0
  97. package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
  98. package/src/infrastructure/http/index.ts +0 -0
  99. package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
  100. package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
  101. package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
  102. package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
  103. package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
  104. package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
  105. package/src/lib/httpHelper.js +0 -0
  106. package/src/lib/lastUpdated.js +0 -0
  107. package/src/services/api/types.js +0 -0
  108. package/src/services/config.js +0 -0
  109. package/src/services/content-org/content-org.js +0 -0
  110. package/src/services/content-org/playlists-types.js +11 -0
  111. package/src/services/content-org/playlists.js +2 -1
  112. package/src/services/content.js +0 -0
  113. package/src/services/contentAggregator.js +0 -0
  114. package/src/services/contentLikes.js +0 -0
  115. package/src/services/contentProgress.js +0 -0
  116. package/src/services/dataContext.js +0 -0
  117. package/src/services/dateUtils.js +0 -0
  118. package/src/services/forum.js +0 -0
  119. package/src/services/gamification/awards.js +0 -0
  120. package/src/services/gamification/gamification.js +0 -0
  121. package/src/services/gamification/types.js +0 -0
  122. package/src/services/imageSRCBuilder.js +0 -0
  123. package/src/services/imageSRCVerify.js +0 -0
  124. package/src/services/railcontent.js +0 -0
  125. package/src/services/recommendations.js +0 -0
  126. package/src/services/sanity.js +13 -1
  127. package/src/services/types.js +0 -0
  128. package/src/services/user/interests.js +0 -0
  129. package/src/services/user/management.js +0 -0
  130. package/src/services/user/notifications.js +120 -0
  131. package/src/services/user/permissions.js +0 -0
  132. package/src/services/user/profile.js +0 -0
  133. package/src/services/user/sessions.js +0 -0
  134. package/src/services/user/types.js +0 -0
  135. package/src/services/user/user-management-system.js +0 -0
  136. package/src/services/userActivity.js +2 -1
  137. package/test/HttpClient.test.js +0 -0
  138. package/test/content.test.js +0 -0
  139. package/test/contentLikes.test.js +0 -0
  140. package/test/contentProgress.test.js +0 -0
  141. package/test/dataContext.test.js +0 -0
  142. package/test/forum.test.js +0 -0
  143. package/test/imageSRCBuilder.test.js +0 -0
  144. package/test/imageSRCVerify.test.js +0 -0
  145. package/test/initializeTests.js +0 -0
  146. package/test/lib/lastUpdated.test.js +0 -0
  147. package/test/live/contentProgressLive.test.js +0 -0
  148. package/test/live/railcontentLive.test.js +0 -0
  149. package/test/localStorageMock.js +0 -0
  150. package/test/log.js +0 -0
  151. package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
  152. package/test/mockData/mockData_progress_content.json +0 -0
  153. package/test/mockData/mockData_sanity_progress_content.json +0 -0
  154. package/test/mockData/mockData_user_practices.json +0 -0
  155. package/test/progressRows.test.js +0 -0
  156. package/test/sanityQueryService.test.js +0 -0
  157. package/test/streakMessage.test.js +0 -0
  158. package/test/user/permissions.test.js +0 -0
  159. package/test/userActivity.test.js +0 -0
  160. package/tools/generate-index.cjs +0 -0
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Awards.html">Awards</a><ul class='methods'><li data-type='method'><a href="module-Awards.html#.fetchAwardsForUser">fetchAwardsForUser</a></li></ul></li><li><a href="module-Config.html">Config</a><ul class='methods'><li data-type='method'><a href="module-Config.html#.initializeService">initializeService</a></li></ul></li><li><a href="module-Content-Services-V2.html">Content-Services-V2</a><ul class='methods'><li data-type='method'><a href="module-Content-Services-V2.html#.getContentRows">getContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getNewAndUpcoming">getNewAndUpcoming</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecent">getRecent</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecommendedForYou">getRecommendedForYou</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getScheduleContentRows">getScheduleContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getTabResults">getTabResults</a></li></ul></li><li><a href="module-Interests.html">Interests</a><ul class='methods'><li data-type='method'><a href="module-Interests.html#.fetchInterests">fetchInterests</a></li><li data-type='method'><a href="module-Interests.html#.fetchUninterests">fetchUninterests</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsInterested">markContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsNotInterested">markContentAsNotInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsInterested">removeContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsNotInterested">removeContentAsNotInterested</a></li></ul></li><li><a href="module-Permissions.html">Permissions</a><ul class='methods'><li data-type='method'><a href="module-Permissions.html#.fetchUserPermissions">fetchUserPermissions</a></li><li data-type='method'><a href="module-Permissions.html#.reset">reset</a></li></ul></li><li><a href="module-Playlists.html">Playlists</a><ul class='methods'><li data-type='method'><a href="module-Playlists.html#.addItemToPlaylist">addItemToPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.createPlaylist">createPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.duplicatePlaylist">duplicatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylist">fetchPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylistItems">fetchPlaylistItems</a></li><li data-type='method'><a href="module-Playlists.html#.fetchUserPlaylists">fetchUserPlaylists</a></li><li data-type='method'><a href="module-Playlists.html#.togglePlaylistPrivate">togglePlaylistPrivate</a></li><li data-type='method'><a href="module-Playlists.html#.updatePlaylist">updatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~likePlaylist">likePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~reportPlaylist">reportPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~togglePlaylistPrivate">togglePlaylistPrivate</a></li><li data-type='method'><a href="module-Playlists.html#~unlikePlaylist">unlikePlaylist</a></li></ul></li><li><a href="module-Railcontent-Services.html">Railcontent-Services</a><ul class='methods'><li data-type='method'><a href="module-Railcontent-Services.html#.assignModeratorToComment">assignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.closeComment">closeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.createComment">createComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deleteComment">deleteComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.editComment">editComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchAllCompletedStates">fetchAllCompletedStates</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCarouselCardData">fetchCarouselCardData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeIndexMetadata">fetchChallengeIndexMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeLessonData">fetchChallengeLessonData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeMetadata">fetchChallengeMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeUserActiveChallenges">fetchChallengeUserActiveChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCommentRelies">fetchCommentRelies</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchComments">fetchComments</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedChallenges">fetchCompletedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedContent">fetchCompletedContent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedState">fetchCompletedState</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentInProgress">fetchContentInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentPageUserData">fetchContentPageUserData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchNextContentDataForParent">fetchNextContentDataForParent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchOwnedChallenges">fetchOwnedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchRecentUserActivities">fetchRecentUserActivities</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchSongsInProgress">fetchSongsInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchTopComment">fetchTopComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserAward">fetchUserAward</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserBadges">fetchUserBadges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserChallengeProgress">fetchUserChallengeProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserPracticeNotes">fetchUserPracticeNotes</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.likeComment">likeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.openComment">openComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesCommunityNotification">postChallengesCommunityNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnroll">postChallengesEnroll</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnrollmentNotification">postChallengesEnrollmentNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesHideCompletedBanner">postChallengesHideCompletedBanner</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesLeave">postChallengesLeave</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSetStartDate">postChallengesSetStartDate</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSoloNotification">postChallengesSoloNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesUnlock">postChallengesUnlock</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.replyToComment">replyToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.reportComment">reportComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.setStudentViewForUser">setStudentViewForUser</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unassignModeratorToComment">unassignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unlikeComment">unlikeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#~fetchLastInteractedChild">fetchLastInteractedChild</a></li></ul></li><li><a href="module-Sanity-Services.html">Sanity-Services</a><ul class='methods'><li data-type='method'><a href="module-Sanity-Services.html#.fetchAll">fetchAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllFilterOptions">fetchAllFilterOptions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllPacks">fetchAllPacks</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtistLessons">fetchArtistLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtists">fetchArtists</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentId">fetchByRailContentId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentIds">fetchByRailContentIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByReference">fetchByReference</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCoachLessons">fetchCoachLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchComingSoon">fetchComingSoon</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCommentModContentData">fetchCommentModContentData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchFoundation">fetchFoundation</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchGenreLessons">fetchGenreLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLeaving">fetchLeaving</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonContent">fetchLessonContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonsFeaturingThisContent">fetchLessonsFeaturingThisContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMetadata">fetchMetadata</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethod">fetchMethod</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildren">fetchMethodChildren</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildrenIds">fetchMethodChildrenIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodPreviousNextLesson">fetchMethodPreviousNextLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNewReleases">fetchNewReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNextPreviousLesson">fetchNextPreviousLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchOtherSongVersions">fetchOtherSongVersions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackAll">fetchPackAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackData">fetchPackData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchParentForDownload">fetchParentForDownload</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedLessons">fetchRelatedLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedRecommendedContent">fetchRelatedRecommendedContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedSongs">fetchRelatedSongs</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchReturning">fetchReturning</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSanity">fetchSanity</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchScheduledReleases">fetchScheduledReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchShowsData">fetchShowsData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongArtistCount">fetchSongArtistCount</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongById">fetchSongById</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchUpcomingEvents">fetchUpcomingEvents</a></li><li data-type='method'><a href="module-Sanity-Services.html#.jumpToContinueContent">jumpToContinueContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#~fetchRelatedByLicense">fetchRelatedByLicense</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getNextAndPreviousQuarterDates">getNextAndPreviousQuarterDates</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getQueryFromPage">getQueryFromPage</a></li><li data-type='method'><a href="module-Sanity-Services.html#~handleCustomFetchAll">handleCustomFetchAll</a></li></ul></li><li><a href="module-Sessions.html">Sessions</a><ul class='methods'><li data-type='method'><a href="module-Sessions.html#.login">login</a></li><li data-type='method'><a href="module-Sessions.html#.logout">logout</a></li></ul></li><li><a href="module-User-Activity.html">User-Activity</a><ul class='methods'><li data-type='method'><a href="module-User-Activity.html#.calculateLongestStreaks">calculateLongestStreaks</a></li><li data-type='method'><a href="module-User-Activity.html#.createPracticeNotes">createPracticeNotes</a></li><li data-type='method'><a href="module-User-Activity.html#.deletePracticeSession">deletePracticeSession</a></li><li data-type='method'><a href="module-User-Activity.html#.deleteUserActivity">deleteUserActivity</a></li><li data-type='method'><a href="module-User-Activity.html#.getPracticeNotes">getPracticeNotes</a></li><li data-type='method'><a href="module-User-Activity.html#.getPracticeSessions">getPracticeSessions</a></li><li data-type='method'><a href="module-User-Activity.html#.getProgressRows">getProgressRows</a></li><li data-type='method'><a href="module-User-Activity.html#.getRecentActivity">getRecentActivity</a></li><li data-type='method'><a href="module-User-Activity.html#.getUserMonthlyStats">getUserMonthlyStats</a></li><li data-type='method'><a href="module-User-Activity.html#.getUserWeeklyStats">getUserWeeklyStats</a></li><li data-type='method'><a href="module-User-Activity.html#.pinProgressRow">pinProgressRow</a></li><li data-type='method'><a href="module-User-Activity.html#.recordUserActivity">recordUserActivity</a></li><li data-type='method'><a href="module-User-Activity.html#.recordUserPractice">recordUserPractice</a></li><li data-type='method'><a href="module-User-Activity.html#.removeUserPractice">removeUserPractice</a></li><li data-type='method'><a href="module-User-Activity.html#.restorePracticeSession">restorePracticeSession</a></li><li data-type='method'><a href="module-User-Activity.html#.restoreUserPractice">restoreUserPractice</a></li><li data-type='method'><a href="module-User-Activity.html#.unpinProgressRow">unpinProgressRow</a></li><li data-type='method'><a href="module-User-Activity.html#.updatePracticeNotes">updatePracticeNotes</a></li><li data-type='method'><a href="module-User-Activity.html#.updateUserPractice">updateUserPractice</a></li></ul></li><li><a href="module-UserManagement.html">UserManagement</a><ul class='methods'><li data-type='method'><a href="module-UserManagement.html#.blockUser">blockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.deletePicture">deletePicture</a></li><li data-type='method'><a href="module-UserManagement.html#.unblockUser">unblockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPicture">uploadPicture</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPictureFromS3">uploadPictureFromS3</a></li></ul></li><li><a href="module-UserProfile.html">UserProfile</a><ul class='methods'><li data-type='method'><a href="module-UserProfile.html#.otherStats">otherStats</a></li></ul></li></ul><h3>Namespaces</h3><ul><li><a href="ContentOrganization.html">ContentOrganization</a></li><li><a href="Gamification.html">Gamification</a></li><li><a href="UserManagementSystem.html">UserManagementSystem</a></li></ul><h3><a href="global.html">Global</a></h3>
32
+ <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Awards.html">Awards</a><ul class='methods'><li data-type='method'><a href="module-Awards.html#.fetchAwardsForUser">fetchAwardsForUser</a></li></ul></li><li><a href="module-Config.html">Config</a><ul class='methods'><li data-type='method'><a href="module-Config.html#.initializeService">initializeService</a></li></ul></li><li><a href="module-Content-Services-V2.html">Content-Services-V2</a><ul class='methods'><li data-type='method'><a href="module-Content-Services-V2.html#.getContentRows">getContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getNewAndUpcoming">getNewAndUpcoming</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecent">getRecent</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecommendedForYou">getRecommendedForYou</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getScheduleContentRows">getScheduleContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getTabResults">getTabResults</a></li></ul></li><li><a href="module-Interests.html">Interests</a><ul class='methods'><li data-type='method'><a href="module-Interests.html#.fetchInterests">fetchInterests</a></li><li data-type='method'><a href="module-Interests.html#.fetchUninterests">fetchUninterests</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsInterested">markContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsNotInterested">markContentAsNotInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsInterested">removeContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsNotInterested">removeContentAsNotInterested</a></li></ul></li><li><a href="module-Permissions.html">Permissions</a><ul class='methods'><li data-type='method'><a href="module-Permissions.html#.fetchUserPermissions">fetchUserPermissions</a></li><li data-type='method'><a href="module-Permissions.html#.reset">reset</a></li></ul></li><li><a href="module-Playlists.html">Playlists</a><ul class='methods'><li data-type='method'><a href="module-Playlists.html#.addItemToPlaylist">addItemToPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.createPlaylist">createPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.deletePlaylist">deletePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.duplicatePlaylist">duplicatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylist">fetchPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylistItems">fetchPlaylistItems</a></li><li data-type='method'><a href="module-Playlists.html#.fetchUserPlaylists">fetchUserPlaylists</a></li><li data-type='method'><a href="module-Playlists.html#.togglePlaylistPrivate">togglePlaylistPrivate</a></li><li data-type='method'><a href="module-Playlists.html#.undeletePlaylist">undeletePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.updatePlaylist">updatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~likePlaylist">likePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~reportPlaylist">reportPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~togglePlaylistPrivate">togglePlaylistPrivate</a></li><li data-type='method'><a href="module-Playlists.html#~unlikePlaylist">unlikePlaylist</a></li></ul></li><li><a href="module-Railcontent-Services.html">Railcontent-Services</a><ul class='methods'><li data-type='method'><a href="module-Railcontent-Services.html#.assignModeratorToComment">assignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.closeComment">closeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.createComment">createComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deleteComment">deleteComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.editComment">editComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchAllCompletedStates">fetchAllCompletedStates</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCarouselCardData">fetchCarouselCardData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeIndexMetadata">fetchChallengeIndexMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeLessonData">fetchChallengeLessonData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeMetadata">fetchChallengeMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeUserActiveChallenges">fetchChallengeUserActiveChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCommentRelies">fetchCommentRelies</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchComments">fetchComments</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedChallenges">fetchCompletedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedContent">fetchCompletedContent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedState">fetchCompletedState</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentInProgress">fetchContentInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentPageUserData">fetchContentPageUserData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchNextContentDataForParent">fetchNextContentDataForParent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchOwnedChallenges">fetchOwnedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchRecentUserActivities">fetchRecentUserActivities</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchSongsInProgress">fetchSongsInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchTopComment">fetchTopComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserAward">fetchUserAward</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserBadges">fetchUserBadges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserChallengeProgress">fetchUserChallengeProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserPracticeNotes">fetchUserPracticeNotes</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.likeComment">likeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.openComment">openComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesCommunityNotification">postChallengesCommunityNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnroll">postChallengesEnroll</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnrollmentNotification">postChallengesEnrollmentNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesHideCompletedBanner">postChallengesHideCompletedBanner</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesLeave">postChallengesLeave</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSetStartDate">postChallengesSetStartDate</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSoloNotification">postChallengesSoloNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesUnlock">postChallengesUnlock</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.replyToComment">replyToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.reportComment">reportComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.setStudentViewForUser">setStudentViewForUser</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unassignModeratorToComment">unassignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unlikeComment">unlikeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#~fetchLastInteractedChild">fetchLastInteractedChild</a></li></ul></li><li><a href="module-Sanity-Services.html">Sanity-Services</a><ul class='methods'><li data-type='method'><a href="module-Sanity-Services.html#.fetchAll">fetchAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllFilterOptions">fetchAllFilterOptions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllPacks">fetchAllPacks</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtistLessons">fetchArtistLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtists">fetchArtists</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentId">fetchByRailContentId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentIds">fetchByRailContentIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByReference">fetchByReference</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCoachLessons">fetchCoachLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchComingSoon">fetchComingSoon</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCommentModContentData">fetchCommentModContentData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchFoundation">fetchFoundation</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchGenreLessons">fetchGenreLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLeaving">fetchLeaving</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonContent">fetchLessonContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonsFeaturingThisContent">fetchLessonsFeaturingThisContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMetadata">fetchMetadata</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethod">fetchMethod</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildren">fetchMethodChildren</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildrenIds">fetchMethodChildrenIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodPreviousNextLesson">fetchMethodPreviousNextLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNewReleases">fetchNewReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNextPreviousLesson">fetchNextPreviousLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchOtherSongVersions">fetchOtherSongVersions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackAll">fetchPackAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackData">fetchPackData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchParentForDownload">fetchParentForDownload</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedLessons">fetchRelatedLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedRecommendedContent">fetchRelatedRecommendedContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedSongs">fetchRelatedSongs</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchReturning">fetchReturning</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSanity">fetchSanity</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchScheduledReleases">fetchScheduledReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchShowsData">fetchShowsData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongArtistCount">fetchSongArtistCount</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongById">fetchSongById</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchUpcomingEvents">fetchUpcomingEvents</a></li><li data-type='method'><a href="module-Sanity-Services.html#.jumpToContinueContent">jumpToContinueContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#~fetchRelatedByLicense">fetchRelatedByLicense</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getNextAndPreviousQuarterDates">getNextAndPreviousQuarterDates</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getQueryFromPage">getQueryFromPage</a></li><li data-type='method'><a href="module-Sanity-Services.html#~handleCustomFetchAll">handleCustomFetchAll</a></li></ul></li><li><a href="module-Sessions.html">Sessions</a><ul class='methods'><li data-type='method'><a href="module-Sessions.html#.login">login</a></li><li data-type='method'><a href="module-Sessions.html#.logout">logout</a></li></ul></li><li><a href="module-UserActivity.html">UserActivity</a><ul class='methods'><li data-type='method'><a href="module-UserActivity.html#.calculateLongestStreaks">calculateLongestStreaks</a></li><li data-type='method'><a href="module-UserActivity.html#.createPracticeNotes">createPracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.deletePracticeSession">deletePracticeSession</a></li><li data-type='method'><a href="module-UserActivity.html#.deleteUserActivity">deleteUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.getPracticeNotes">getPracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.getPracticeSessions">getPracticeSessions</a></li><li data-type='method'><a href="module-UserActivity.html#.getProgressRows">getProgressRows</a></li><li data-type='method'><a href="module-UserActivity.html#.getRecentActivity">getRecentActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.getUserMonthlyStats">getUserMonthlyStats</a></li><li data-type='method'><a href="module-UserActivity.html#.getUserWeeklyStats">getUserWeeklyStats</a></li><li data-type='method'><a href="module-UserActivity.html#.pinProgressRow">pinProgressRow</a></li><li data-type='method'><a href="module-UserActivity.html#.recordUserActivity">recordUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.recordUserPractice">recordUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.removeUserPractice">removeUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.restorePracticeSession">restorePracticeSession</a></li><li data-type='method'><a href="module-UserActivity.html#.restoreUserPractice">restoreUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.unpinProgressRow">unpinProgressRow</a></li><li data-type='method'><a href="module-UserActivity.html#.updatePracticeNotes">updatePracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.updateUserPractice">updateUserPractice</a></li></ul></li><li><a href="module-UserManagement.html">UserManagement</a><ul class='methods'><li data-type='method'><a href="module-UserManagement.html#.blockUser">blockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.deletePicture">deletePicture</a></li><li data-type='method'><a href="module-UserManagement.html#.unblockUser">unblockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPicture">uploadPicture</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPictureFromS3">uploadPictureFromS3</a></li></ul></li><li><a href="module-UserNotifications.html">UserNotifications</a><ul class='methods'><li data-type='method'><a href="module-UserNotifications.html#.deleteNotification">deleteNotification</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchNotifications">fetchNotifications</a></li><li data-type='method'><a href="module-UserNotifications.html#.markAllNotificationsAsRead">markAllNotificationsAsRead</a></li><li data-type='method'><a href="module-UserNotifications.html#.markNotificationAsRead">markNotificationAsRead</a></li><li data-type='method'><a href="module-UserNotifications.html#.markNotificationAsUnread">markNotificationAsUnread</a></li></ul></li><li><a href="module-UserProfile.html">UserProfile</a><ul class='methods'><li data-type='method'><a href="module-UserProfile.html#.otherStats">otherStats</a></li></ul></li></ul><h3>Namespaces</h3><ul><li><a href="ContentOrganization.html">ContentOrganization</a></li><li><a href="Gamification.html">Gamification</a></li><li><a href="UserManagementSystem.html">UserManagementSystem</a></li></ul><h3><a href="global.html">Global</a></h3>
33
33
 
34
34
  </nav>
35
35
 
@@ -46,7 +46,7 @@
46
46
  <section>
47
47
  <article>
48
48
  <pre class="prettyprint source linenums"><code>/**
49
- * @module User-Activity
49
+ * @module UserActivity
50
50
  */
51
51
 
52
52
  import {
@@ -55,14 +55,14 @@ import {
55
55
  fetchUserPracticeMeta,
56
56
  fetchUserPracticeNotes,
57
57
  fetchHandler,
58
- fetchRecentUserActivities,
58
+ fetchRecentUserActivities, fetchChallengeLessonData
59
59
  } from './railcontent'
60
60
  import { DataContext, UserActivityVersionKey } from './dataContext.js'
61
61
  import { fetchByRailContentIds, fetchShows } from './sanity'
62
- import {fetchUserPlaylists} from "./content-org/playlists";
63
- import { convertToTimeZone, getMonday, getWeekNumber, isSameDate, isNextDay } from './dateUtils.js'
62
+ import {fetchPlaylist, fetchUserPlaylists} from "./content-org/playlists";
63
+ import {convertToTimeZone, getMonday, getWeekNumber, isSameDate, isNextDay, getTimeRemainingUntilLocal} from './dateUtils.js'
64
64
  import { globalConfig } from './config'
65
- import {collectionLessonTypes, lessonTypesMapping, progressTypesMapping} from "../contentTypeConfig";
65
+ import {collectionLessonTypes, lessonTypesMapping, progressTypesMapping, showsLessonTypes, songs} from "../contentTypeConfig";
66
66
  import {getAllStartedOrCompleted, getProgressStateByIds} from "./contentProgress";
67
67
  import {TabResponseType} from "../contentMetaData";
68
68
 
@@ -877,7 +877,7 @@ async function formatPracticeMeta(practices) {
877
877
  title: practice.content_id ? content.title : practice.title,
878
878
  category_id: practice.category_id,
879
879
  instrument_id: practice.instrument_id,
880
- content_type: getFormattedType(content.type || ''),
880
+ content_type: getFormattedType(content.type || '', content.brand),
881
881
  content_id: practice.content_id || null,
882
882
  content_brand: content.brand || null,
883
883
  created_at: convertToTimeZone(utcDate, userTimeZone),
@@ -958,6 +958,7 @@ export async function getProgressRows({ brand = null, limit = 8 } = {}) {
958
958
  const playlistEngagedOnContents = eligiblePlaylistItems.map(item => item.last_engaged_on);
959
959
  const playlistsContents = await fetchByRailContentIds(playlistEngagedOnContents, 'progress-tracker');
960
960
  const excludedParents = new Set();
961
+ const existingShows = new Set();
961
962
  for (const item of playlistsContents) {
962
963
  const contentId = item.id ?? item.railcontent_id;
963
964
  excludedParents.add(contentId)
@@ -1007,20 +1008,44 @@ export async function getProgressRows({ brand = null, limit = 8 } = {}) {
1007
1008
  }
1008
1009
  // Handle standalone parents
1009
1010
  if (!progressMap.has(id)) {
1010
- progressMap.set(id, {
1011
- id,
1012
- raw: content,
1013
- state: progress.status,
1014
- percent: progress.progress,
1015
- progressTimestamp: progress.last_update * 1000
1016
- });
1011
+ if(!existingShows.has(content.type)){
1012
+ progressMap.set(id, {
1013
+ id,
1014
+ raw: content,
1015
+ state: progress.status,
1016
+ percent: progress.progress,
1017
+ progressTimestamp: progress.last_update * 1000
1018
+ });
1019
+ }
1020
+ if(showsLessonTypes.includes(content.type)) {
1021
+ existingShows.add(content.type)
1022
+ }
1017
1023
  }
1018
1024
  }
1019
- const progressList = Array.from(progressMap.values());
1025
+ const pinnedItem = await extractPinnedItem({
1026
+ brand,
1027
+ progressMap,
1028
+ playlistItems: eligiblePlaylistItems,
1029
+ })
1030
+ const progressList = Array.from(progressMap.values())
1031
+ if (pinnedItem) {
1032
+ pinnedItem.pinned = true
1033
+ }
1034
+
1035
+ const pinnedId = pinnedItem?.id
1036
+ const filteredProgressList = pinnedId
1037
+ ? progressList.filter(item => item.id !== pinnedId)
1038
+ : progressList;
1039
+ const filteredPlaylists = pinnedId
1040
+ ? eligiblePlaylistItems.filter(item => item.id !== pinnedId)
1041
+ : eligiblePlaylistItems;
1042
+ const combinedBase = [...filteredProgressList, ...filteredPlaylists]
1043
+ const combined = pinnedItem ? [pinnedItem, ...combinedBase] : combinedBase
1044
+
1045
+ const finalCombined = mergeAndSortItems(combined, limit)
1020
1046
 
1021
- const combined = mergeAndSortItems([...progressList, ...eligiblePlaylistItems], limit);
1022
1047
  const results = await Promise.all(
1023
- combined.slice(0, limit).map(item =>
1048
+ finalCombined.slice(0, limit).map(item =>
1024
1049
  item.type === 'playlist'
1025
1050
  ? processPlaylistItem(item)
1026
1051
  : processContentItem(item)
@@ -1035,24 +1060,27 @@ export async function getProgressRows({ brand = null, limit = 8 } = {}) {
1035
1060
 
1036
1061
  async function processContentItem(item) {
1037
1062
  let data = item.raw;
1038
- const contentType = getFormattedType(data.type);
1063
+ const contentType = getFormattedType(data.type, data.brand);
1039
1064
  const status = item.state;
1040
1065
 
1041
1066
  let ctaText = 'Continue';
1042
1067
  if (contentType === 'transcription' || contentType === 'play-along' || contentType === 'jam-track') ctaText = 'Replay Song';
1043
1068
  if (contentType === 'lesson') ctaText = status === 'completed' ? 'Revisit Lesson' : 'Continue';
1044
- if ((contentType === 'pack' || contentType === 'song tutorial' || collectionLessonTypes.includes(contentType)) &amp;&amp; status === 'completed') {
1069
+ if ((contentType === 'guided course' || contentType === 'song tutorial' || collectionLessonTypes.includes(contentType)) &amp;&amp; status === 'completed') ctaText = 'Revisit Lessons' ;
1070
+ if (contentType === 'pack' &amp;&amp; status === 'completed') {
1045
1071
  ctaText = 'View Lessons';
1046
1072
  }
1047
1073
 
1048
1074
  if (data.lesson_count > 0) {
1075
+ const lessonIds = extractLessonIds(item);
1076
+ const progressOnItems = await getProgressStateByIds(lessonIds);
1077
+ let completedCount = Object.values(progressOnItems).filter(value => value === 'completed').length;
1078
+ data.completed_children = completedCount;
1079
+
1049
1080
  if (item.childIndex) {
1050
1081
  let nextId = item.childIndex
1051
- const lessonIds = extractLessonIds(item);
1052
- const progressOnItems = await getProgressStateByIds(lessonIds);
1053
- const completedCount = Object.values(progressOnItems).filter(value => value === 'completed').length;
1054
- const nextByProgress = findIncompleteLesson(progressOnItems, item.childIndex, item.raw.type);
1055
- nextId = nextByProgress ? nextByProgress : nextId;
1082
+ const nextByProgress = findIncompleteLesson(progressOnItems, item.childIndex, item.raw.type)
1083
+ nextId = nextByProgress ? nextByProgress : nextId
1056
1084
 
1057
1085
  const nestedLessons = data.lessons
1058
1086
  .filter(item => Array.isArray(item.lessons))
@@ -1068,36 +1096,57 @@ async function processContentItem(item) {
1068
1096
  }))
1069
1097
  );
1070
1098
 
1071
- const lessons = (nestedLessons.length === 0) ? data.lessons : nestedLessons;
1072
- const nextLesson = lessons.find(lesson => lesson.id === nextId);
1073
- data.first_incomplete_child = nextLesson?.parent ?? nextLesson;
1074
- data.second_incomplete_child = (nextLesson?.parent) ? nextLesson : null;
1075
- data.completed_children = completedCount;
1099
+ const lessons = (nestedLessons.length === 0) ? data.lessons : nestedLessons
1100
+ const nextLesson = lessons.find(lesson => lesson.id === nextId)
1101
+ data.first_incomplete_child = nextLesson?.parent ?? nextLesson
1102
+ data.second_incomplete_child = (nextLesson?.parent) ? nextLesson : null
1103
+ if(data.type === 'challenge' &amp;&amp; nextByProgress !== undefined ){
1104
+ const challenge = await fetchChallengeLessonData(nextByProgress)
1105
+ if(challenge.lesson.is_locked) {
1106
+ const timeRemaining = getTimeRemainingUntilLocal(challenge.lesson.unlock_date, {withTotalSeconds:true})
1107
+ data.is_locked = true
1108
+ data.time_remaining_seconds = timeRemaining.totalSeconds
1109
+ ctaText = 'Next lesson in ' + timeRemaining.formatted
1110
+ }
1111
+ }
1076
1112
  }
1077
1113
  }
1078
1114
 
1079
- if(contentType == 'show' &amp;&amp; status == 'completed'){
1115
+ if(contentType == 'show'){
1080
1116
  const shows = await fetchShows(data.brand, data.type)
1081
1117
  const showIds = shows.map(item => item.id);
1082
1118
  const progressOnItems = await getProgressStateByIds(showIds);
1083
- const nextByProgress = findIncompleteLesson(progressOnItems, data.id, data.type);
1084
- data = shows.find(lesson => lesson.id === nextByProgress);
1119
+ const completedCount = Object.values(progressOnItems).filter(value => value === 'completed').length;
1120
+ if(status == 'completed') {
1121
+ const nextByProgress = findIncompleteLesson(progressOnItems, data.id, data.type);
1122
+ data = shows.find(lesson => lesson.id === nextByProgress);
1123
+ }
1124
+ data.completed_children = completedCount;
1125
+ data.child_count = shows.length;
1126
+ item.percent = Math.round((completedCount / shows.length) * 100);
1127
+ if(completedCount == shows.length) {
1128
+ ctaText = 'Revisit Lessons';
1129
+ }
1085
1130
  }
1086
1131
 
1087
1132
  return {
1088
1133
  id: item.id,
1089
1134
  progressType: 'content',
1090
1135
  header: contentType,
1136
+ pinned: item.pinned ?? false,
1091
1137
  body: {
1092
1138
  progressPercent: item.percent,
1093
1139
  thumbnail: data.thumbnail,
1094
1140
  title: data.title,
1141
+ badge: data.badge ?? null,
1142
+ isLocked: data.is_locked ?? false,
1095
1143
  subtitle: !data.child_count || data.lesson_count === 1
1096
- ? `${data.difficulty_string} • ${data.artist_name}`
1144
+ ? (contentType === 'lesson') ? `${item.percent}% Complete`: `${data.difficulty_string} • ${data.artist_name}`
1097
1145
  : `${data.completed_children} of ${data.lesson_count ?? data.child_count} Lessons Complete`
1098
1146
  },
1099
1147
  cta: {
1100
1148
  text: ctaText,
1149
+ timeRemainingToUnlockSeconds: data.time_remaining_seconds ?? null,
1101
1150
  action: {
1102
1151
  type: data.type,
1103
1152
  brand: data.brand,
@@ -1148,10 +1197,12 @@ async function processPlaylistItem(item) {
1148
1197
  id: playlist.id,
1149
1198
  progressType: 'playlist',
1150
1199
  header: 'playlist',
1200
+ pinned: item.pinned ?? false,
1151
1201
  body: {
1152
1202
  first_items_thumbnail_url: playlist.first_items_thumbnail_url,
1153
1203
  title: playlist.name,
1154
- subtitle: `${playlist.duration_formated} • ${playlist.total_items} items • ${playlist.likes} likes • ${playlist.user.display_name}`
1204
+ subtitle: `${playlist.duration_formated} • ${playlist.total_items} items • ${playlist.likes} likes • ${playlist.user.display_name}`,
1205
+ total_items: playlist.total_items,
1155
1206
  },
1156
1207
  progressTimestamp: item.progressTimestamp,
1157
1208
  cta: {
@@ -1166,12 +1217,13 @@ async function processPlaylistItem(item) {
1166
1217
  }
1167
1218
  }
1168
1219
 
1169
- const getFormattedType = type => {
1220
+ const getFormattedType = (type, brand) => {
1170
1221
  for (const [key, values] of Object.entries(progressTypesMapping)) {
1171
1222
  if (values.includes(type)) {
1172
- return key;
1223
+ return key === 'songs' ? songs[brand] : key;
1173
1224
  }
1174
1225
  }
1226
+
1175
1227
  return null;
1176
1228
  };
1177
1229
 
@@ -1179,11 +1231,10 @@ function extractLessonIds(data) {
1179
1231
  const ids = [];
1180
1232
  function traverse(lessons) {
1181
1233
  for (const item of lessons) {
1182
- if (item.id) {
1183
- ids.push(item.id);
1184
- }
1185
1234
  if (item.lessons) {
1186
1235
  traverse(item.lessons); // Recursively handle nested lessons
1236
+ }else if (item.id) {
1237
+ ids.push(item.id);
1187
1238
  }
1188
1239
  }
1189
1240
  }
@@ -1212,9 +1263,24 @@ async function getEligiblePlaylistItems(playlists) {
1212
1263
  }
1213
1264
 
1214
1265
  function mergeAndSortItems(items, limit) {
1215
- return items
1266
+ const seen = new Set();
1267
+ const deduped = [];
1268
+
1269
+ for (const item of items) {
1270
+ const key = `${item.id}-${item.type || item.raw?.type}`;
1271
+ if (!seen.has(key)) {
1272
+ seen.add(key);
1273
+ deduped.push(item);
1274
+ }
1275
+ }
1276
+
1277
+ return deduped
1216
1278
  .filter(item => typeof item.progressTimestamp === 'number' &amp;&amp; item.progressTimestamp > 0)
1217
- .sort((a, b) => b.progressTimestamp - a.progressTimestamp)
1279
+ .sort((a, b) => {
1280
+ if (a.pinned &amp;&amp; !b.pinned) return -1;
1281
+ if (!a.pinned &amp;&amp; b.pinned) return 1;
1282
+ return b.progressTimestamp - a.progressTimestamp;
1283
+ })
1218
1284
  .slice(0, limit + 5);
1219
1285
  }
1220
1286
 
@@ -1222,7 +1288,7 @@ function findIncompleteLesson(progressOnItems, currentContentId, contentType) {
1222
1288
  const ids = Object.keys(progressOnItems).map(Number);
1223
1289
  if (contentType === 'challenge') {
1224
1290
  // Return first incomplete lesson
1225
- return ids.find(id => progressOnItems[id] !== 'completed') || null;
1291
+ return ids.find(id => progressOnItems[id] !== 'completed') || ids.at(0);
1226
1292
  }
1227
1293
 
1228
1294
  // For other types, find next incomplete after current
@@ -1254,7 +1320,15 @@ function findIncompleteLesson(progressOnItems, currentContentId, contentType) {
1254
1320
  */
1255
1321
  export async function pinProgressRow(brand, id, progressType) {
1256
1322
  const url = `/api/user-management-system/v1/progress/pin?brand=${brand}&amp;id=${id}&amp;progressType=${progressType}`;
1257
- return await fetchHandler(url, 'PUT', null)
1323
+ const response = await fetchHandler(url, 'PUT', null)
1324
+ if (response &amp;&amp; !response.error) {
1325
+ await updatePinnedProgressRow(brand, {
1326
+ id,
1327
+ progressType,
1328
+ pinnedAt: new Date().toISOString(),
1329
+ });
1330
+ }
1331
+ return response;
1258
1332
  }
1259
1333
  /**
1260
1334
  * Unpins the current pinned progress row for a user, scoped by brand.
@@ -1268,10 +1342,87 @@ export async function pinProgressRow(brand, id, progressType) {
1268
1342
  * .catch(error => console.error(error));
1269
1343
  */
1270
1344
  export async function unpinProgressRow(brand) {
1271
- const url = `/api/user-management-system/v1/progress/unpin?brand=${brand}`;
1272
- return await fetchHandler(url, 'PUT', null)
1345
+ const url = `/api/user-management-system/v1/progress/unpin?brand=${brand}`
1346
+ const response = await fetchHandler(url, 'PUT', null)
1347
+ if (response &amp;&amp; !response.error) {
1348
+ await updatePinnedProgressRow(brand, null)
1349
+ }
1350
+ return response
1273
1351
  }
1274
1352
 
1353
+ async function updatePinnedProgressRow(brand, pinnedData) {
1354
+ const userRaw = await globalConfig.localStorage.getItem('user');
1355
+ const user = userRaw ? JSON.parse(userRaw) : {};
1356
+ user.brand_pinned_progress = user.brand_pinned_progress || {}
1357
+ user.brand_pinned_progress[brand] = pinnedData
1358
+ await globalConfig.localStorage.setItem('user', JSON.stringify(user))
1359
+ }
1360
+
1361
+ async function extractPinnedItem({brand, progressMap, playlistItems}) {
1362
+ const userRaw = await globalConfig.localStorage.getItem('user');
1363
+ const user = userRaw ? JSON.parse(userRaw) : {};
1364
+ user.brand_pinned_progress = user.brand_pinned_progress || {}
1365
+
1366
+ const pinned = user.brand_pinned_progress[brand]
1367
+ if (!pinned) return null
1368
+
1369
+ const {id, progressType, pinnedAt} = pinned
1370
+
1371
+ if (progressType === 'content') {
1372
+ const pinnedId = parseInt(id)
1373
+ if (progressMap.has(pinnedId)) {
1374
+ const item = progressMap.get(pinnedId)
1375
+ progressMap.delete(pinnedId)
1376
+ return item
1377
+ } else {
1378
+ const content = await fetchByRailContentIds([`${pinnedId}`], 'progress-tracker')
1379
+ const firstLessonId = getFirstLeafLessonId(content[0])
1380
+ return {
1381
+ id: pinnedId,
1382
+ state: 'started',
1383
+ percent: 0,
1384
+ raw: content[0],
1385
+ progressTimestamp: new Date(pinnedAt).getTime(),
1386
+ childIndex: firstLessonId
1387
+ }
1388
+ }
1389
+ }
1390
+ if (progressType === 'playlist') {
1391
+ const pinnedPlaylist = playlistItems.find(p => p.raw.id === id)
1392
+ if (pinnedPlaylist) {
1393
+ return pinnedPlaylist
1394
+ }else{
1395
+ const playlist = await fetchPlaylist(id)
1396
+ return {
1397
+ id: id,
1398
+ raw: playlist,
1399
+ progressTimestamp: new Date(pinnedAt).getTime(),
1400
+ type: 'playlist',
1401
+ last_engaged_on: playlist.items[0],
1402
+ }
1403
+ }
1404
+ }
1405
+
1406
+ return null
1407
+ }
1408
+
1409
+ function getFirstLeafLessonId(data) {
1410
+ function findFirstLeaf(lessons) {
1411
+ for (const item of lessons) {
1412
+ if (!item.lessons || item.lessons.length === 0) {
1413
+ return item.id || null
1414
+ }
1415
+ const found = findFirstLeaf(item.lessons)
1416
+ if (found) return found
1417
+ }
1418
+ return null
1419
+ }
1420
+
1421
+ return data.lessons ? findFirstLeaf(data.lessons) : null
1422
+ }
1423
+
1424
+
1425
+
1275
1426
  </code></pre>
1276
1427
  </article>
1277
1428
  </section>
@@ -1286,7 +1437,7 @@ export async function unpinProgressRow(brand) {
1286
1437
  <br class="clear">
1287
1438
 
1288
1439
  <footer>
1289
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Mon May 26 2025 16:03:08 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1440
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Tue Jun 03 2025 12:20:10 GMT+0300 (Eastern European Summer Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1290
1441
  </footer>
1291
1442
 
1292
1443
  <script>prettyPrint();</script>