musora-content-services 2.8.2 → 2.8.4

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 (48) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/docs/ContentOrganization.html +2 -2
  3. package/docs/Gamification.html +2 -2
  4. package/docs/UserManagementSystem.html +2 -2
  5. package/docs/api_types.js.html +2 -2
  6. package/docs/config.js.html +2 -2
  7. package/docs/content-org_content-org.js.html +2 -2
  8. package/docs/content-org_playlists-types.js.html +2 -2
  9. package/docs/content-org_playlists.js.html +14 -2
  10. package/docs/content.js.html +2 -2
  11. package/docs/gamification_awards.js.html +2 -2
  12. package/docs/gamification_gamification.js.html +2 -2
  13. package/docs/gamification_types.js.html +2 -2
  14. package/docs/global.html +2 -2
  15. package/docs/index.html +2 -2
  16. package/docs/module-Awards.html +2 -2
  17. package/docs/module-Config.html +2 -2
  18. package/docs/module-Content-Services-V2.html +2 -2
  19. package/docs/module-Interests.html +2 -2
  20. package/docs/module-Notifications.html +1183 -0
  21. package/docs/module-Permissions.html +2 -2
  22. package/docs/module-Playlists.html +322 -12
  23. package/docs/module-Railcontent-Services.html +2 -2
  24. package/docs/module-Sanity-Services.html +2 -2
  25. package/docs/module-Sessions.html +2 -2
  26. package/docs/module-UserActivity.html +4410 -0
  27. package/docs/module-UserManagement.html +2 -2
  28. package/docs/module-UserNotifications.html +1183 -0
  29. package/docs/module-UserProfile.html +2 -2
  30. package/docs/railcontent.js.html +2 -2
  31. package/docs/sanity.js.html +2 -2
  32. package/docs/userActivity.js.html +197 -46
  33. package/docs/user_interests.js.html +2 -2
  34. package/docs/user_management.js.html +2 -2
  35. package/docs/user_notifications.js.html +189 -0
  36. package/docs/user_permissions.js.html +2 -2
  37. package/docs/user_profile.js.html +2 -2
  38. package/docs/user_sessions.js.html +2 -2
  39. package/docs/user_types.js.html +2 -2
  40. package/docs/user_user-management-system.js.html +2 -2
  41. package/package.json +1 -1
  42. package/src/index.d.ts +13 -0
  43. package/src/index.js +13 -0
  44. package/src/services/content-org/playlists-types.js +13 -0
  45. package/src/services/content-org/playlists.js +2 -1
  46. package/src/services/sanity.js +13 -1
  47. package/src/services/user/notifications.js +120 -0
  48. package/src/services/userActivity.js +2 -1
@@ -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>