musora-content-services 2.36.2 → 2.36.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.
- package/CHANGELOG.md +2 -0
- package/package.json +1 -1
- package/src/index.d.ts +4 -2
- package/src/index.js +4 -2
- package/src/services/content-org/guided-courses.ts +0 -5
- package/src/services/contentAggregator.js +0 -1
- package/src/services/contentProgress.js +30 -0
- package/src/services/railcontent.js +10 -0
- package/src/services/sanity.js +0 -3
- package/src/services/userActivity.js +19 -36
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
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.36.3](https://github.com/railroadmedia/musora-content-services/compare/v2.36.2...v2.36.3) (2025-09-09)
|
|
6
|
+
|
|
5
7
|
### [2.36.2](https://github.com/railroadmedia/musora-content-services/compare/v2.36.1...v2.36.2) (2025-09-09)
|
|
6
8
|
|
|
7
9
|
### [2.36.1](https://github.com/railroadmedia/musora-content-services/compare/v2.36.0...v2.36.1) (2025-09-09)
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
fetchEnrollmentPageMetadata,
|
|
11
11
|
guidedCourses,
|
|
12
12
|
pinGuidedCourse,
|
|
13
|
-
pinnedGuidedCourses,
|
|
14
13
|
unEnrollUserInGuidedCourse,
|
|
15
14
|
unPinGuidedCourse
|
|
16
15
|
} from './services/content-org/guided-courses.ts';
|
|
@@ -59,6 +58,7 @@ import {
|
|
|
59
58
|
import {
|
|
60
59
|
contentStatusCompleted,
|
|
61
60
|
contentStatusReset,
|
|
61
|
+
contentStatusStartedForGuidedCourseEnrollment,
|
|
62
62
|
getAllCompleted,
|
|
63
63
|
getAllStarted,
|
|
64
64
|
getAllStartedOrCompleted,
|
|
@@ -149,6 +149,7 @@ import {
|
|
|
149
149
|
postContentLiked,
|
|
150
150
|
postContentReset,
|
|
151
151
|
postContentRestore,
|
|
152
|
+
postContentStartForGC,
|
|
152
153
|
postContentUnliked,
|
|
153
154
|
postPlaylistContentEngaged,
|
|
154
155
|
postRecordWatchSession,
|
|
@@ -338,6 +339,7 @@ declare module 'musora-content-services' {
|
|
|
338
339
|
confirmEmailChange,
|
|
339
340
|
contentStatusCompleted,
|
|
340
341
|
contentStatusReset,
|
|
342
|
+
contentStatusStartedForGuidedCourseEnrollment,
|
|
341
343
|
convertToTimeZone,
|
|
342
344
|
createComment,
|
|
343
345
|
createPlaylist,
|
|
@@ -508,11 +510,11 @@ declare module 'musora-content-services' {
|
|
|
508
510
|
pauseLiveEventPolling,
|
|
509
511
|
pinGuidedCourse,
|
|
510
512
|
pinProgressRow,
|
|
511
|
-
pinnedGuidedCourses,
|
|
512
513
|
postContentComplete,
|
|
513
514
|
postContentLiked,
|
|
514
515
|
postContentReset,
|
|
515
516
|
postContentRestore,
|
|
517
|
+
postContentStartForGC,
|
|
516
518
|
postContentUnliked,
|
|
517
519
|
postPlaylistContentEngaged,
|
|
518
520
|
postRecordWatchSession,
|
package/src/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
fetchEnrollmentPageMetadata,
|
|
11
11
|
guidedCourses,
|
|
12
12
|
pinGuidedCourse,
|
|
13
|
-
pinnedGuidedCourses,
|
|
14
13
|
unEnrollUserInGuidedCourse,
|
|
15
14
|
unPinGuidedCourse
|
|
16
15
|
} from './services/content-org/guided-courses.ts';
|
|
@@ -59,6 +58,7 @@ import {
|
|
|
59
58
|
import {
|
|
60
59
|
contentStatusCompleted,
|
|
61
60
|
contentStatusReset,
|
|
61
|
+
contentStatusStartedForGuidedCourseEnrollment,
|
|
62
62
|
getAllCompleted,
|
|
63
63
|
getAllStarted,
|
|
64
64
|
getAllStartedOrCompleted,
|
|
@@ -149,6 +149,7 @@ import {
|
|
|
149
149
|
postContentLiked,
|
|
150
150
|
postContentReset,
|
|
151
151
|
postContentRestore,
|
|
152
|
+
postContentStartForGC,
|
|
152
153
|
postContentUnliked,
|
|
153
154
|
postPlaylistContentEngaged,
|
|
154
155
|
postRecordWatchSession,
|
|
@@ -337,6 +338,7 @@ export {
|
|
|
337
338
|
confirmEmailChange,
|
|
338
339
|
contentStatusCompleted,
|
|
339
340
|
contentStatusReset,
|
|
341
|
+
contentStatusStartedForGuidedCourseEnrollment,
|
|
340
342
|
convertToTimeZone,
|
|
341
343
|
createComment,
|
|
342
344
|
createPlaylist,
|
|
@@ -507,11 +509,11 @@ export {
|
|
|
507
509
|
pauseLiveEventPolling,
|
|
508
510
|
pinGuidedCourse,
|
|
509
511
|
pinProgressRow,
|
|
510
|
-
pinnedGuidedCourses,
|
|
511
512
|
postContentComplete,
|
|
512
513
|
postContentLiked,
|
|
513
514
|
postContentReset,
|
|
514
515
|
postContentRestore,
|
|
516
|
+
postContentStartForGC,
|
|
515
517
|
postContentUnliked,
|
|
516
518
|
postPlaylistContentEngaged,
|
|
517
519
|
postRecordWatchSession,
|
|
@@ -39,8 +39,3 @@ export async function guidedCourses() {
|
|
|
39
39
|
const url: string = `${BASE_PATH}/v1/user/guided-courses/`
|
|
40
40
|
return await fetchHandler(url, 'GET')
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
export async function pinnedGuidedCourses(brand) {
|
|
44
|
-
const url: string = `${BASE_PATH}/v1/user/guided-courses/pinned?brand=${brand}`
|
|
45
|
-
return await fetchHandler(url, 'GET')
|
|
46
|
-
}
|
|
@@ -93,7 +93,6 @@ export async function addContextToContent(dataPromise, ...dataArgs)
|
|
|
93
93
|
addNextLesson ? getNextLesson(items) : Promise.resolve(null),
|
|
94
94
|
addNavigateTo ? getNavigateTo(items) : Promise.resolve(null),
|
|
95
95
|
])
|
|
96
|
-
if (addNextLesson) console.log('AddNextLesson is depreciated in favour of addNavigateTo')
|
|
97
96
|
|
|
98
97
|
const addContext = async (item) => ({
|
|
99
98
|
...item,
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
fetchContentProgress,
|
|
3
3
|
postContentComplete,
|
|
4
4
|
postContentReset,
|
|
5
|
+
postContentStartForGC,
|
|
5
6
|
postRecordWatchSession,
|
|
6
7
|
} from './railcontent.js'
|
|
7
8
|
import { DataContext, ContentProgressVersionKey } from './dataContext.js'
|
|
@@ -359,6 +360,19 @@ export async function contentStatusCompleted(contentId) {
|
|
|
359
360
|
}
|
|
360
361
|
)
|
|
361
362
|
}
|
|
363
|
+
export async function contentStatusStartedForGuidedCourseEnrollment(contentId) {
|
|
364
|
+
const response = await postContentStartForGC(contentId);
|
|
365
|
+
|
|
366
|
+
return await dataContext.update(
|
|
367
|
+
async function (localContext) {
|
|
368
|
+
let hierarchy = await fetchHierarchy(contentId)
|
|
369
|
+
startStatusInLocalContext(localContext, contentId, hierarchy)
|
|
370
|
+
},
|
|
371
|
+
async function () {
|
|
372
|
+
return response
|
|
373
|
+
}
|
|
374
|
+
)
|
|
375
|
+
}
|
|
362
376
|
|
|
363
377
|
function saveContentProgress(localContext, contentId, progress, currentSeconds, hierarchy) {
|
|
364
378
|
if (progress === 100) {
|
|
@@ -395,6 +409,22 @@ function completeStatusInLocalContext(localContext, contentId, hierarchy) {
|
|
|
395
409
|
bubbleProgress(hierarchy, contentId, localContext)
|
|
396
410
|
}
|
|
397
411
|
|
|
412
|
+
function startStatusInLocalContext(localContext, contentId, hierarchy) {
|
|
413
|
+
let data = localContext.data[contentId] ?? {}
|
|
414
|
+
data[DATA_KEY_PROGRESS] = 0
|
|
415
|
+
data[DATA_KEY_STATUS] = STATE_STARTED
|
|
416
|
+
data[DATA_KEY_LAST_UPDATED_TIME] = Math.round(new Date().getTime() / 1000)
|
|
417
|
+
localContext.data[contentId] = data
|
|
418
|
+
|
|
419
|
+
if (!hierarchy) return
|
|
420
|
+
let children = hierarchy.children[contentId] ?? []
|
|
421
|
+
for (let i = 0; i < children.length; i++) {
|
|
422
|
+
let childId = children[i]
|
|
423
|
+
startStatusInLocalContext(localContext, childId, hierarchy)
|
|
424
|
+
}
|
|
425
|
+
bubbleProgress(hierarchy, contentId, localContext)
|
|
426
|
+
}
|
|
427
|
+
|
|
398
428
|
function getChildrenToDepth(parentId, hierarchy, depth = 1) {
|
|
399
429
|
let childIds = hierarchy.children[parentId] ?? []
|
|
400
430
|
let allChildrenIds = childIds
|
|
@@ -388,6 +388,16 @@ export async function postContentComplete(contentId) {
|
|
|
388
388
|
return postDataHandler(url)
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
+
/**
|
|
392
|
+
* start a Guided Course content's progress for a given user
|
|
393
|
+
* @param contentId
|
|
394
|
+
* @returns {Promise<any|string|null>}
|
|
395
|
+
*/
|
|
396
|
+
export async function postContentStartForGC(contentId) {
|
|
397
|
+
let url = `/api/content/v1/user/progress/start`
|
|
398
|
+
return postDataHandler(url, { contentId })
|
|
399
|
+
}
|
|
400
|
+
|
|
391
401
|
/**
|
|
392
402
|
* resets the user's progress on a content
|
|
393
403
|
* @param contentId
|
package/src/services/sanity.js
CHANGED
|
@@ -1834,9 +1834,6 @@ export async function fetchSanity(
|
|
|
1834
1834
|
}
|
|
1835
1835
|
const result = await response.json()
|
|
1836
1836
|
if (result.result) {
|
|
1837
|
-
if (globalConfig.sanityConfig.debug) {
|
|
1838
|
-
console.log('fetchSanity Results:', result)
|
|
1839
|
-
}
|
|
1840
1837
|
let results = isList ? result.result : result.result[0]
|
|
1841
1838
|
if (!results) {
|
|
1842
1839
|
throw new Error('No results found')
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import { DataContext, UserActivityVersionKey } from './dataContext.js'
|
|
14
14
|
import { fetchByRailContentId, fetchByRailContentIds, fetchShows } from './sanity'
|
|
15
15
|
import { fetchPlaylist, fetchUserPlaylists } from './content-org/playlists'
|
|
16
|
-
import {guidedCourses
|
|
16
|
+
import {guidedCourses} from './content-org/guided-courses'
|
|
17
17
|
import {
|
|
18
18
|
getMonday,
|
|
19
19
|
getWeekNumber,
|
|
@@ -950,7 +950,6 @@ async function extractPinnedItemsAndSortAllItems(
|
|
|
950
950
|
userPinnedItem,
|
|
951
951
|
contentsMap,
|
|
952
952
|
eligiblePlaylistItems,
|
|
953
|
-
pinnedGuidedCourse,
|
|
954
953
|
limit
|
|
955
954
|
) {
|
|
956
955
|
let pinnedItem = await popPinnedItemFromContentsOrPlaylistMap(
|
|
@@ -959,22 +958,8 @@ async function extractPinnedItemsAndSortAllItems(
|
|
|
959
958
|
eligiblePlaylistItems
|
|
960
959
|
)
|
|
961
960
|
|
|
962
|
-
const guidedCourseID = pinnedGuidedCourse?.content_id
|
|
963
961
|
let combined = []
|
|
964
|
-
|
|
965
|
-
const guidedCourseContent =
|
|
966
|
-
contentsMap.get(guidedCourseID) ??
|
|
967
|
-
(await addContextToContent(fetchByRailContentId, guidedCourseID, 'guided-course', {
|
|
968
|
-
addNextLesson: true,
|
|
969
|
-
addNavigateTo: true,
|
|
970
|
-
addProgressStatus: true,
|
|
971
|
-
addProgressPercentage: true,
|
|
972
|
-
addProgressTimestamp: true,
|
|
973
|
-
}))
|
|
974
|
-
contentsMap = popContentAndRemoveChildrenFromContentsMap(guidedCourseContent, contentsMap)
|
|
975
|
-
guidedCourseContent.pinned = true
|
|
976
|
-
combined.push(guidedCourseContent)
|
|
977
|
-
}
|
|
962
|
+
|
|
978
963
|
if (pinnedItem) {
|
|
979
964
|
pinnedItem.pinned = true
|
|
980
965
|
combined.push(pinnedItem)
|
|
@@ -1052,20 +1037,15 @@ function generateContentsMap(contents, playlistsContents) {
|
|
|
1052
1037
|
export async function getProgressRows({ brand = null, limit = 8 } = {}) {
|
|
1053
1038
|
// TODO slice progress to a reasonable number, say 100
|
|
1054
1039
|
|
|
1055
|
-
const [recentPlaylists, progressContents,
|
|
1040
|
+
const [recentPlaylists, progressContents, userPinnedItem, enrolledGuidedCourses] =
|
|
1056
1041
|
await Promise.all([
|
|
1057
1042
|
fetchUserPlaylists(brand, { sort: '-last_progress', limit: limit }),
|
|
1058
1043
|
getAllStartedOrCompleted({ onlyIds: false, brand: brand }),
|
|
1059
|
-
pinnedGuidedCourses(brand),
|
|
1060
1044
|
getUserPinnedItem(brand),
|
|
1061
1045
|
guidedCourses()
|
|
1062
1046
|
])
|
|
1063
1047
|
|
|
1064
1048
|
const enrolledGuidedCoursesIds = enrolledGuidedCourses.map(course => String(course.content_id));
|
|
1065
|
-
|
|
1066
|
-
const mergedGuidedCourses = 1 //get all cuigded courses, incl no progress.
|
|
1067
|
-
let pinnedGuidedCourse = allPinnedGuidedCourse?.[0] ?? null
|
|
1068
|
-
|
|
1069
1049
|
const playlists = recentPlaylists?.data || []
|
|
1070
1050
|
const eligiblePlaylistItems = await getEligiblePlaylistItems(playlists)
|
|
1071
1051
|
const playlistEngagedOnContents = eligiblePlaylistItems.map(
|
|
@@ -1079,8 +1059,6 @@ export async function getProgressRows({ brand = null, limit = 8 } = {}) {
|
|
|
1079
1059
|
if (userPinnedItem?.progressType === 'content') {
|
|
1080
1060
|
nonPlaylistContentIds.push(userPinnedItem.id)
|
|
1081
1061
|
}
|
|
1082
|
-
console.log("nonPlaylistContentIds",nonPlaylistContentIds)
|
|
1083
|
-
|
|
1084
1062
|
|
|
1085
1063
|
const [playlistsContents, contents] = await Promise.all([
|
|
1086
1064
|
playlistEngagedOnContents ? addContextToContent(fetchByRailContentIds, playlistEngagedOnContents, 'progress-tracker', {
|
|
@@ -1103,7 +1081,6 @@ console.log("nonPlaylistContentIds",nonPlaylistContentIds)
|
|
|
1103
1081
|
userPinnedItem,
|
|
1104
1082
|
contentsMap,
|
|
1105
1083
|
eligiblePlaylistItems,
|
|
1106
|
-
pinnedGuidedCourse,
|
|
1107
1084
|
limit
|
|
1108
1085
|
)
|
|
1109
1086
|
const results = await Promise.all(
|
|
@@ -1361,8 +1338,10 @@ export function findIncompleteLesson(progressOnItems, currentContentId, contentT
|
|
|
1361
1338
|
|
|
1362
1339
|
async function popPinnedItemFromContentsOrPlaylistMap(pinned, contentsMap, playlistItems) {
|
|
1363
1340
|
if (!pinned) return null
|
|
1364
|
-
const { id,
|
|
1341
|
+
const { id, pinnedAt } = pinned
|
|
1365
1342
|
let item = null
|
|
1343
|
+
const progressType = pinned.progressType ?? pinned.type;
|
|
1344
|
+
|
|
1366
1345
|
if (progressType === 'content') {
|
|
1367
1346
|
const pinnedId = parseInt(id)
|
|
1368
1347
|
if (contentsMap.has(pinnedId)) {
|
|
@@ -1399,15 +1378,19 @@ async function popPinnedItemFromContentsOrPlaylistMap(pinned, contentsMap, playl
|
|
|
1399
1378
|
}
|
|
1400
1379
|
|
|
1401
1380
|
function popContentAndRemoveChildrenFromContentsMap(content, contentsMap) {
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
contentsMap.delete(child)
|
|
1381
|
+
if (!content.children || content.children.length === 0){
|
|
1382
|
+
console.warn(`content ${content.id} has no children`, content);
|
|
1383
|
+
} else {
|
|
1384
|
+
const children = content.children.map((child) => child.id)
|
|
1385
|
+
if (contentsMap.has(content.id)) {
|
|
1386
|
+
contentsMap.delete(content.id)
|
|
1409
1387
|
}
|
|
1410
|
-
|
|
1388
|
+
children.forEach((child) => {
|
|
1389
|
+
if (contentsMap.has(child)) {
|
|
1390
|
+
contentsMap.delete(child)
|
|
1391
|
+
}
|
|
1392
|
+
})
|
|
1393
|
+
}
|
|
1411
1394
|
return contentsMap
|
|
1412
1395
|
}
|
|
1413
1396
|
|
|
@@ -1427,7 +1410,7 @@ function popContentAndRemoveChildrenFromContentsMap(content, contentsMap) {
|
|
|
1427
1410
|
export async function pinProgressRow(brand, id, progressType) {
|
|
1428
1411
|
const url = `/api/user-management-system/v1/progress/pin?brand=${brand}&id=${id}&progressType=${progressType}`
|
|
1429
1412
|
const response = await fetchHandler(url, 'PUT', null)
|
|
1430
|
-
if (response && !response.error
|
|
1413
|
+
if (response && !response.error) {
|
|
1431
1414
|
await updateUserPinnedProgressRow(brand, {
|
|
1432
1415
|
id,
|
|
1433
1416
|
progressType,
|