musora-content-services 2.26.1 → 2.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/.coderabbit.yaml +0 -0
  2. package/.editorconfig +0 -0
  3. package/.github/pull_request_template.md +0 -0
  4. package/.github/workflows/conventional-commits.yaml +0 -0
  5. package/.github/workflows/docs.js.yml +0 -0
  6. package/.github/workflows/node.js.yml +0 -0
  7. package/.prettierignore +0 -0
  8. package/.prettierrc +0 -0
  9. package/.yarnrc.yml +1 -0
  10. package/CHANGELOG.md +16 -0
  11. package/README.md +0 -0
  12. package/babel.config.cjs +0 -0
  13. package/docs/Content-Organization.html +0 -0
  14. package/docs/ContentOrganization.html +0 -0
  15. package/docs/Gamification.html +0 -0
  16. package/docs/UserManagement.html +0 -0
  17. package/docs/UserManagementSystem.html +0 -0
  18. package/docs/api_types.js.html +0 -0
  19. package/docs/config.js.html +0 -0
  20. package/docs/content-org_content-org.js.html +0 -0
  21. package/docs/content-org_playlists-types.js.html +0 -0
  22. package/docs/content-org_playlists.js.html +0 -0
  23. package/docs/content.js.html +0 -0
  24. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  25. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  26. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  27. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  28. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  29. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  30. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  31. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  32. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  33. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
  34. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  35. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  36. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  37. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  38. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
  39. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  40. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  41. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  42. package/docs/gamification_awards.js.html +0 -0
  43. package/docs/gamification_gamification.js.html +0 -0
  44. package/docs/gamification_types.js.html +0 -0
  45. package/docs/global.html +0 -0
  46. package/docs/global.html#User +0 -0
  47. package/docs/index.html +0 -0
  48. package/docs/module-Awards.html +0 -0
  49. package/docs/module-Config.html +0 -0
  50. package/docs/module-Content-Services-V2.html +0 -0
  51. package/docs/module-Interests.html +0 -0
  52. package/docs/module-Notifications.html +0 -0
  53. package/docs/module-Permissions.html +0 -0
  54. package/docs/module-Playlists.html +0 -0
  55. package/docs/module-Railcontent-Services.html +0 -0
  56. package/docs/module-Sanity-Services.html +0 -0
  57. package/docs/module-Session-Management.html +0 -0
  58. package/docs/module-Sessions.html +0 -0
  59. package/docs/module-User-Activity.html +0 -0
  60. package/docs/module-User-Management.html +0 -0
  61. package/docs/module-User-Permissions.html +0 -0
  62. package/docs/module-UserActivity.html +0 -0
  63. package/docs/module-UserChat.html +0 -0
  64. package/docs/module-UserManagement.html +0 -0
  65. package/docs/module-UserNotifications.html +0 -0
  66. package/docs/module-UserProfile.html +0 -0
  67. package/docs/railcontent.js.html +0 -0
  68. package/docs/sanity.js.html +0 -0
  69. package/docs/scripts/collapse.js +0 -0
  70. package/docs/scripts/commonNav.js +0 -0
  71. package/docs/scripts/linenumber.js +0 -0
  72. package/docs/scripts/nav.js +0 -0
  73. package/docs/scripts/polyfill.js +0 -0
  74. package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
  75. package/docs/scripts/prettify/lang-css.js +0 -0
  76. package/docs/scripts/prettify/prettify.js +0 -0
  77. package/docs/scripts/search.js +0 -0
  78. package/docs/styles/jsdoc.css +0 -0
  79. package/docs/styles/prettify.css +0 -0
  80. package/docs/types.js.html +0 -0
  81. package/docs/userActivity.js.html +0 -0
  82. package/docs/user_chat.js.html +0 -0
  83. package/docs/user_interests.js.html +0 -0
  84. package/docs/user_management.js.html +0 -0
  85. package/docs/user_notifications.js.html +0 -0
  86. package/docs/user_permissions.js.html +0 -0
  87. package/docs/user_profile.js.html +0 -0
  88. package/docs/user_sessions.js.html +0 -0
  89. package/docs/user_types.js.html +0 -0
  90. package/docs/user_user-management-system.js.html +0 -0
  91. package/docs/user_user-management.js.html +0 -0
  92. package/jest.config.js +0 -0
  93. package/jsdoc.json +0 -0
  94. package/package.json +1 -1
  95. package/src/contentMetaData.js +0 -0
  96. package/src/filterBuilder.js +0 -0
  97. package/src/index.d.ts +4 -2
  98. package/src/index.js +4 -2
  99. package/src/infrastructure/http/HttpClient.ts +0 -0
  100. package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
  101. package/src/infrastructure/http/index.ts +0 -0
  102. package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
  103. package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
  104. package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
  105. package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
  106. package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
  107. package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
  108. package/src/lib/httpHelper.js +0 -0
  109. package/src/lib/lastUpdated.js +0 -0
  110. package/src/services/api/types.js +0 -0
  111. package/src/services/config.js +0 -0
  112. package/src/services/content-org/content-org.js +0 -0
  113. package/src/services/content-org/guided-courses.ts +0 -0
  114. package/src/services/content-org/playlists-types.js +0 -0
  115. package/src/services/content-org/playlists.js +0 -0
  116. package/src/services/content.js +0 -0
  117. package/src/services/contentAggregator.js +0 -0
  118. package/src/services/contentLikes.js +0 -0
  119. package/src/services/contentProgress.js +0 -0
  120. package/src/services/dataContext.js +0 -0
  121. package/src/services/dateUtils.js +0 -0
  122. package/src/services/forum.js +0 -0
  123. package/src/services/gamification/awards.js +0 -0
  124. package/src/services/gamification/gamification.js +0 -0
  125. package/src/services/gamification/types.js +0 -0
  126. package/src/services/imageSRCBuilder.js +0 -0
  127. package/src/services/railcontent.js +0 -0
  128. package/src/services/recommendations.js +0 -0
  129. package/src/services/sanity.js +20 -1
  130. package/src/services/types.js +0 -0
  131. package/src/services/user/account.ts +0 -0
  132. package/src/services/user/chat.js +0 -0
  133. package/src/services/user/interests.js +0 -0
  134. package/src/services/user/management.js +0 -0
  135. package/src/services/user/notifications.js +39 -26
  136. package/src/services/user/permissions.js +0 -0
  137. package/src/services/user/profile.js +0 -0
  138. package/src/services/user/sessions.js +0 -0
  139. package/src/services/user/types.js +0 -0
  140. package/src/services/user/user-management-system.js +0 -0
  141. package/src/services/userActivity.js +8 -6
  142. package/test/HttpClient.test.js +0 -0
  143. package/test/content.test.js +0 -0
  144. package/test/contentLikes.test.js +0 -0
  145. package/test/contentProgress.test.js +0 -0
  146. package/test/dataContext.test.js +0 -0
  147. package/test/forum.test.js +0 -0
  148. package/test/imageSRCBuilder.test.js +0 -0
  149. package/test/imageSRCVerify.test.js +0 -0
  150. package/test/initializeTests.js +0 -0
  151. package/test/lib/lastUpdated.test.js +0 -0
  152. package/test/live/contentProgressLive.test.js +0 -0
  153. package/test/live/railcontentLive.test.js +0 -0
  154. package/test/localStorageMock.js +0 -0
  155. package/test/log.js +0 -0
  156. package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
  157. package/test/mockData/mockData_progress_content.json +0 -0
  158. package/test/mockData/mockData_sanity_progress_content.json +0 -0
  159. package/test/mockData/mockData_user_practices.json +0 -0
  160. package/test/notifications.test.js +0 -0
  161. package/test/progressRows.test.js +0 -0
  162. package/test/sanityQueryService.test.js +0 -0
  163. package/test/streakMessage.test.js +0 -0
  164. package/test/user/permissions.test.js +0 -0
  165. package/test/userActivity.test.js +0 -0
  166. package/tools/generate-index.cjs +0 -0
package/.coderabbit.yaml CHANGED
File without changes
package/.editorconfig CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
package/.prettierignore CHANGED
File without changes
package/.prettierrc CHANGED
File without changes
package/.yarnrc.yml ADDED
@@ -0,0 +1 @@
1
+ nodeLinker: node-modules
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [2.27.0](https://github.com/railroadmedia/musora-content-services/compare/v2.24.0...v2.27.0) (2025-07-17)
6
+
7
+
8
+ ### Features
9
+
10
+ * **BEH-38:** add context data to tab results ([#344](https://github.com/railroadmedia/musora-content-services/issues/344)) ([02fe932](https://github.com/railroadmedia/musora-content-services/commit/02fe9321dfa56e74d7c73cb7a80e54f5818d1427))
11
+ * **MU2-805:** Set a pauseLiveEventPollingUntil field when user mark all notificatio… ([#351](https://github.com/railroadmedia/musora-content-services/issues/351)) ([bfe1010](https://github.com/railroadmedia/musora-content-services/commit/bfe10107c522ea725436e4a6338a869e852c08d5))
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * Add live event fallback to unread notifications count ([61afc83](https://github.com/railroadmedia/musora-content-services/commit/61afc835a7f009ec5e12947b2bf2131b7ed7049a))
17
+ * T3PS-21: Live Stream content cards in the Progress Row and Recent Lessons ([3736c48](https://github.com/railroadmedia/musora-content-services/commit/3736c4898d9db27869de079660474e6dd0233da4))
18
+ * T3PS-259: Incorrect stats for past months ([b38ee32](https://github.com/railroadmedia/musora-content-services/commit/b38ee320488196115ff4ef97d4ea4ea661d1eb43))
19
+ * user data endpoint ([#356](https://github.com/railroadmedia/musora-content-services/issues/356)) ([2a00bb8](https://github.com/railroadmedia/musora-content-services/commit/2a00bb859faa72ec22930919f4a636275b219772))
20
+
5
21
  ### [2.26.1](https://github.com/railroadmedia/musora-content-services/compare/v2.26.0...v2.26.1) (2025-07-16)
6
22
 
7
23
  ## [2.26.0](https://github.com/railroadmedia/musora-content-services/compare/v2.25.1...v2.26.0) (2025-07-16)
package/README.md CHANGED
File without changes
package/babel.config.cjs CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/docs/global.html CHANGED
File without changes
File without changes
package/docs/index.html CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/jest.config.js CHANGED
File without changes
package/jsdoc.json CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.26.1",
3
+ "version": "2.27.0",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
File without changes
File without changes
package/src/index.d.ts CHANGED
@@ -261,13 +261,14 @@ import {
261
261
 
262
262
  import {
263
263
  deleteNotification,
264
+ fetchLiveEventPollingState,
264
265
  fetchNotificationSettings,
265
266
  fetchNotifications,
266
267
  fetchUnreadCount,
267
268
  markAllNotificationsAsRead,
268
269
  markNotificationAsRead,
269
270
  markNotificationAsUnread,
270
- pauseLiveEventPollingUntil,
271
+ pauseLiveEventPolling,
271
272
  startLiveEventPolling,
272
273
  updateNotificationSetting
273
274
  } from './services/user/notifications.js';
@@ -382,6 +383,7 @@ declare module 'musora-content-services' {
382
383
  fetchLessonsFeaturingThisContent,
383
384
  fetchLikeCount,
384
385
  fetchLiveEvent,
386
+ fetchLiveEventPollingState,
385
387
  fetchMetadata,
386
388
  fetchMethod,
387
389
  fetchMethodChildren,
@@ -488,7 +490,7 @@ declare module 'musora-content-services' {
488
490
  markNotificationAsUnread,
489
491
  openComment,
490
492
  otherStats,
491
- pauseLiveEventPollingUntil,
493
+ pauseLiveEventPolling,
492
494
  pinGuidedCourse,
493
495
  pinProgressRow,
494
496
  pinnedGuidedCourses,
package/src/index.js CHANGED
@@ -261,13 +261,14 @@ import {
261
261
 
262
262
  import {
263
263
  deleteNotification,
264
+ fetchLiveEventPollingState,
264
265
  fetchNotificationSettings,
265
266
  fetchNotifications,
266
267
  fetchUnreadCount,
267
268
  markAllNotificationsAsRead,
268
269
  markNotificationAsRead,
269
270
  markNotificationAsUnread,
270
- pauseLiveEventPollingUntil,
271
+ pauseLiveEventPolling,
271
272
  startLiveEventPolling,
272
273
  updateNotificationSetting
273
274
  } from './services/user/notifications.js';
@@ -381,6 +382,7 @@ export {
381
382
  fetchLessonsFeaturingThisContent,
382
383
  fetchLikeCount,
383
384
  fetchLiveEvent,
385
+ fetchLiveEventPollingState,
384
386
  fetchMetadata,
385
387
  fetchMethod,
386
388
  fetchMethodChildren,
@@ -487,7 +489,7 @@ export {
487
489
  markNotificationAsUnread,
488
490
  openComment,
489
491
  otherStats,
490
- pauseLiveEventPollingUntil,
492
+ pauseLiveEventPolling,
491
493
  pinGuidedCourse,
492
494
  pinProgressRow,
493
495
  pinnedGuidedCourses,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -520,13 +520,30 @@ export async function fetchByRailContentIds(ids, contentType = undefined, brand
520
520
  }
521
521
  const idsString = ids.join(',')
522
522
  const brandFilter = brand ? ` && brand == "${brand}"` : ''
523
+ const now = getSanityDate(new Date())
523
524
  const query = `*[
524
525
  railcontent_id in [${idsString}]${brandFilter}
525
526
  ]{
526
527
  ${getFieldsForContentType(contentType)}
528
+ live_event_start_time,
529
+ live_event_end_time,
527
530
  }`
528
531
 
529
- const results = await fetchSanity(query, true)
532
+ const customPostProcess = (results) => {
533
+ const now = getSanityDate(new Date(), false);
534
+ const liveProcess = (result) => {
535
+ if (result.live_event_start_time && result.live_event_end_time) {
536
+ result.isLive =
537
+ result.live_event_start_time <= now &&
538
+ result.live_event_end_time >= now;
539
+ } else {
540
+ result.isLive = false;
541
+ }
542
+ return result;
543
+ };
544
+ return results.map(liveProcess);
545
+ }
546
+ const results = await fetchSanity(query, true, { customPostProcess: customPostProcess })
530
547
 
531
548
  const sortFuction = function compare(a, b) {
532
549
  const indexA = ids.indexOf(a['id'])
@@ -2385,6 +2402,7 @@ export async function fetchTabData(
2385
2402
  }
2386
2403
 
2387
2404
  const fieldsString = getFieldsForContentType('tab-data');
2405
+ const now = getSanityDate(new Date())
2388
2406
 
2389
2407
  // Determine the group by clause
2390
2408
  let query = ''
@@ -2396,6 +2414,7 @@ export async function fetchTabData(
2396
2414
  entityFieldsString =
2397
2415
  ` ${fieldsString}
2398
2416
  'children': child[${childrenFilter}]->{'id': railcontent_id},
2417
+ 'isLive': live_event_start_time <= "${now}" && live_event_end_time >= "${now}",
2399
2418
  'lesson_count': coalesce(count(child[${childrenFilter}]->), 0),
2400
2419
  'length_in_seconds': coalesce(
2401
2420
  math::sum(
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -60,21 +60,15 @@ export async function markNotificationAsRead(notificationId) {
60
60
  }
61
61
 
62
62
  /**
63
- * Marks all notifications as read for a specific brand.
63
+ * Marks all notifications as read for the current user.
64
64
  *
65
- * @returns {Promise<any>} - A promise that resolves when all notifications are marked as read.
65
+ * This also pauses live event polling if there is an active event, to prevent immediate re-polling.
66
66
  *
67
- * @example
68
- * markAllNotificationsAsRead('drumeo')
69
- * .then(response => console.log(response))
70
- * .catch(error => console.error(error));
67
+ * @param {string} [brand='drumeo'] - The brand context for live event handling before marking notifications.
68
+ * @returns {Promise<Object>} - A promise resolving to the API response from the notifications read endpoint.
71
69
  */
72
70
  export async function markAllNotificationsAsRead(brand = 'drumeo') {
73
- const liveEvent = await fetchLiveEvent(brand)
74
- if(liveEvent){
75
- await pauseLiveEventPollingUntil(liveEvent.live_event_end_time)
76
- }
77
-
71
+ await pauseLiveEventPolling(brand)
78
72
  const url = `${baseUrl}/v1/read`
79
73
  return fetchHandler(url, 'put')
80
74
  }
@@ -128,20 +122,33 @@ export async function deleteNotification(notificationId) {
128
122
  /**
129
123
  * Fetches the count of unread notifications for the current user in a given brand context.
130
124
  *
125
+ * This function first checks for standard unread notifications. If none are found,
126
+ * it checks if live event polling is active. If so, it will query for any ongoing live events.
127
+ * If a live event is active, it counts as an unread item.
128
+ *
131
129
  * @param {Object} [options={}] - Options for fetching unread count.
132
- * @param {string} options.brand - The brand to filter unread notifications by (required).
133
- * @returns {Promise<Object>} - A promise that resolves to an object with the unread count.
130
+ * @param {string} options.brand - The brand to filter unread notifications by. Defaults to 'drumeo'.
131
+ * @returns {Promise<Object>} - A promise that resolves to an object with a `data` property indicating the unread count (0 or 1).
134
132
  *
135
- * @throws {Error} If the brand is not provided.
133
+ * @throws {Error} If the brand is not provided or if network requests fail.
136
134
  *
137
135
  * @example
138
136
  * fetchUnreadCount({ brand: 'drumeo' })
139
- * .then(data => console.log(data.unread_count))
137
+ * .then(data => console.log(data.data)) // 0 or 1
140
138
  * .catch(error => console.error(error));
141
139
  */
142
- export async function fetchUnreadCount({ brand = null} = {}) {
140
+ export async function fetchUnreadCount({ brand = 'drumeo'} = {}) {
143
141
  const url = `${baseUrl}/v1/unread-count`
144
- return fetchHandler(url, 'get')
142
+ const notifUnread = await fetchHandler(url, 'get')
143
+ if (notifUnread.data > 0) {
144
+ return notifUnread// Return early if unread notifications exist
145
+ }
146
+ const liveEventPollingState = await fetchLiveEventPollingState()
147
+ if(liveEventPollingState.data?.read_state === true){
148
+ const liveEvent = await fetchLiveEvent(brand)
149
+ return { data: liveEvent ? 1 : 0}
150
+ }
151
+ return notifUnread
145
152
  }
146
153
 
147
154
  /**
@@ -231,20 +238,26 @@ export async function updateNotificationSetting({ brand, settingName, email, pus
231
238
  }
232
239
 
233
240
  /**
234
- * Pauses live event polling until the specified time.
235
- * @param {string|null} [until=null] - ISO timestamp string or null to unpause
236
- * @returns {Promise<Object>} - Promise resolving to the API response
241
+ * Pauses live event polling for the current user based on the live event end time.
242
+ *
243
+ * If a live event is active, polling will be paused until its end time. If no live event is found,
244
+ * polling is not paused.
245
+ *
246
+ * @param {string} [brand='drumeo'] - The brand context to fetch live event data for.
247
+ * @returns {Promise<Object>} - A promise resolving to the API response from the pause polling endpoint.
237
248
  */
238
- export async function pauseLiveEventPollingUntil(until = null) {
239
- const url = `/api/user-management-system/v1/users/pause-polling${until ? `?until=${until}` : ''}`
240
- return fetchHandler(url, 'PUT', null)
249
+ export async function pauseLiveEventPolling(brand = 'drumeo') {
250
+ const liveEvent = await fetchLiveEvent(brand)
251
+ const until = liveEvent?.live_event_end_time || null
252
+ const url = `/api/user-management-system/v1/users/pause-polling${until ? `?until=${until}` : ''}`
253
+ return fetchHandler(url, 'PUT', null)
241
254
  }
242
255
 
243
256
  /**
244
257
  * Start live event polling.
245
258
  * @returns {Promise<Object>} - Promise resolving to the API response
246
259
  */
247
- export async function startLiveEventPolling() {
260
+ export async function startLiveEventPolling(brand = 'drumeo') {
248
261
  const url = `/api/user-management-system/v1/users/start-polling`
249
262
  return fetchHandler(url, 'PUT', null)
250
263
  }
@@ -254,10 +267,10 @@ export async function startLiveEventPolling() {
254
267
  + @returns {Promise<Object>} - Promise resolving to the polling state
255
268
  */
256
269
 
257
- export async function fetchLiveEventPollingState() {
270
+ export async function fetchLiveEventPollingState() {
258
271
  const url = `/api/user-management-system/v1/users/polling`
259
272
  return fetchHandler(url, 'GET', null)
260
- }
273
+ }
261
274
 
262
275
 
263
276
 
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -174,11 +174,11 @@ export async function getUserMonthlyStats(params = {}) {
174
174
  }
175
175
 
176
176
  let endOfMonth = new Date(year, month + 1, 0)
177
- while (endOfMonth.getDay() !== 0) {
178
- endOfMonth.setDate(endOfMonth.getDate() + 1)
177
+ let endOfGrid = new Date(year, month + 1, 0)
178
+ while (endOfGrid.getDay() !== 0) {
179
+ endOfGrid.setDate(endOfGrid.getDate() + 1)
179
180
  }
180
-
181
- let daysInMonth = Math.ceil((endOfMonth - startOfGrid) / (1000 * 60 * 60 * 24)) + 1
181
+ let daysInMonth = Math.ceil((endOfGrid - startOfGrid) / (1000 * 60 * 60 * 24)) + 1
182
182
 
183
183
  let dailyStats = []
184
184
  let practiceDuration = 0
@@ -1073,6 +1073,7 @@ async function processContentItem(item) {
1073
1073
  let data = item.raw;
1074
1074
  const contentType = getFormattedType(data.type, data.brand);
1075
1075
  const status = item.state;
1076
+ const isLive = data.isLive ?? false
1076
1077
  let ctaText = 'Continue';
1077
1078
  if (contentType === 'transcription' || contentType === 'play-along' || contentType === 'jam-track') ctaText = 'Replay Song';
1078
1079
  if (contentType === 'lesson') ctaText = status === 'completed' ? 'Revisit Lesson' : 'Continue';
@@ -1159,13 +1160,14 @@ async function processContentItem(item) {
1159
1160
  header: contentType,
1160
1161
  pinned: item.pinned ?? false,
1161
1162
  body: {
1162
- progressPercent: item.percent,
1163
+ progressPercent: isLive ? undefined: item.percent,
1163
1164
  thumbnail: data.thumbnail,
1164
1165
  title: data.title,
1166
+ isLive: isLive,
1165
1167
  badge: data.badge ?? null,
1166
1168
  isLocked: data.is_locked ?? false,
1167
1169
  subtitle: !data.child_count || data.lesson_count === 1
1168
- ? (contentType === 'lesson') ? `${item.percent}% Complete`: `${data.difficulty_string} • ${data.artist_name}`
1170
+ ? (contentType === 'lesson' && isLive === false) ? `${item.percent}% Complete`: `${data.difficulty_string} • ${data.artist_name}`
1169
1171
  : `${data.completed_children} of ${data.lesson_count ?? data.child_count} Lessons Complete`
1170
1172
  },
1171
1173
  cta: {
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/test/log.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes