musora-content-services 2.101.1 → 2.102.1
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
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
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.102.1](https://github.com/railroadmedia/musora-content-services/compare/v2.102.0...v2.102.1) (2025-12-10)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **agi:** offset default and slug clause on artistBySlug ([10cc6d0](https://github.com/railroadmedia/musora-content-services/commit/10cc6d0390a12715aeba01c5dc72ecdb53d0f236))
|
|
11
|
+
|
|
12
|
+
## [2.102.0](https://github.com/railroadmedia/musora-content-services/compare/v2.101.1...v2.102.0) (2025-12-10)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* **BEH-1457:** method progress duplication ([#617](https://github.com/railroadmedia/musora-content-services/issues/617)) ([917cb9d](https://github.com/railroadmedia/musora-content-services/commit/917cb9dedce2a21c64af4e39eef013a30b236e77))
|
|
18
|
+
|
|
5
19
|
### [2.101.1](https://github.com/railroadmedia/musora-content-services/compare/v2.101.0...v2.101.1) (2025-12-10)
|
|
6
20
|
|
|
7
21
|
|
package/package.json
CHANGED
|
@@ -89,7 +89,7 @@ export async function fetchArtistBySlug(
|
|
|
89
89
|
|
|
90
90
|
const q = query()
|
|
91
91
|
.and(`_type == "artist"`)
|
|
92
|
-
.and(
|
|
92
|
+
.and(`slug.current == '${slug}'`)
|
|
93
93
|
.select(
|
|
94
94
|
'name',
|
|
95
95
|
`"slug": slug.current`,
|
|
@@ -139,7 +139,7 @@ export async function fetchArtistLessons(
|
|
|
139
139
|
{
|
|
140
140
|
sort = '-published_on',
|
|
141
141
|
searchTerm = '',
|
|
142
|
-
offset =
|
|
142
|
+
offset = 0,
|
|
143
143
|
limit = 10,
|
|
144
144
|
includedFields = [],
|
|
145
145
|
progressIds = [],
|
|
@@ -388,30 +388,29 @@ async function resetIfPossible(contentId: number, collection: CollectionParamete
|
|
|
388
388
|
}
|
|
389
389
|
|
|
390
390
|
export async function onContentCompletedLearningPathListener(event) {
|
|
391
|
-
|
|
392
|
-
if (event?.collection?.type !== 'learning-path-v2') return
|
|
391
|
+
if (event?.collection?.type !== COLLECTION_TYPE.LEARNING_PATH) return
|
|
393
392
|
if (event.contentId !== event?.collection?.id) return
|
|
393
|
+
|
|
394
394
|
const learningPathId = event.contentId
|
|
395
395
|
const learningPath = await getEnrichedLearningPath(learningPathId)
|
|
396
|
-
|
|
396
|
+
|
|
397
397
|
const brand = learningPath.brand
|
|
398
398
|
const activeLearningPath = await getActivePath(brand)
|
|
399
|
-
|
|
399
|
+
|
|
400
400
|
if (activeLearningPath.active_learning_path_id !== learningPathId) return
|
|
401
401
|
const method = await fetchMethodV2Structure(brand)
|
|
402
|
-
|
|
402
|
+
|
|
403
403
|
const currentIndex = method.learning_paths.findIndex((lp) => lp.id === learningPathId)
|
|
404
404
|
if (currentIndex === -1) {
|
|
405
405
|
return
|
|
406
406
|
}
|
|
407
407
|
const nextLearningPath = method.learning_paths[currentIndex + 1]
|
|
408
|
-
console.log('Next LP', nextLearningPath)
|
|
409
408
|
if (!nextLearningPath) {
|
|
410
409
|
return
|
|
411
410
|
}
|
|
412
411
|
|
|
413
412
|
await startLearningPath(brand, nextLearningPath.id)
|
|
414
413
|
const nextLearningPathData = await getEnrichedLearningPath(nextLearningPath.id)
|
|
415
|
-
|
|
414
|
+
|
|
416
415
|
await contentStatusReset(nextLearningPathData.intro_video.id)
|
|
417
416
|
}
|
|
@@ -12,7 +12,7 @@ const STATE_COMPLETED = STATE.COMPLETED
|
|
|
12
12
|
const MAX_DEPTH = 3
|
|
13
13
|
|
|
14
14
|
export async function getProgressState(contentId, collection = null) {
|
|
15
|
-
return getById(contentId, collection, 'state', '')
|
|
15
|
+
return getById(normalizeContentId(contentId), normalizeCollection(collection), 'state', '')
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export async function getProgressStateByIds(contentIds, collection = null) {
|
|
@@ -472,13 +472,17 @@ async function saveContentProgress(contentId, collection, progress, currentSecon
|
|
|
472
472
|
// note - previous implementation explicitly did not trickle progress to children here
|
|
473
473
|
// (only to siblings/parents via le bubbles)
|
|
474
474
|
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
collection
|
|
479
|
-
)
|
|
475
|
+
const hierarchy = await getHierarchy(contentId, collection)
|
|
476
|
+
|
|
477
|
+
const bubbledProgresses = await bubbleProgress(hierarchy, contentId, collection)
|
|
480
478
|
await db.contentProgress.recordProgressesTentative(bubbledProgresses, collection)
|
|
481
479
|
|
|
480
|
+
if (collection && collection.type === COLLECTION_TYPE.LEARNING_PATH) {
|
|
481
|
+
let exportIds = bubbledProgresses
|
|
482
|
+
exportIds[contentId] = progress
|
|
483
|
+
await duplicateLearningPathProgressToExternalContents(exportIds, collection, hierarchy)
|
|
484
|
+
}
|
|
485
|
+
|
|
482
486
|
for (const [bubbledContentId, bubbledProgress] of Object.entries(bubbledProgresses)) {
|
|
483
487
|
if (bubbledProgress === 100) {
|
|
484
488
|
emitContentCompleted(Number(bubbledContentId), collection)
|
|
@@ -490,25 +494,56 @@ async function saveContentProgress(contentId, collection, progress, currentSecon
|
|
|
490
494
|
async function setStartedOrCompletedStatus(contentId, collection, isCompleted) {
|
|
491
495
|
const progress = isCompleted ? 100 : 0
|
|
492
496
|
const response = await db.contentProgress.recordProgress(contentId, collection, progress)
|
|
497
|
+
|
|
493
498
|
if (progress === 100) emitContentCompleted(contentId, collection)
|
|
499
|
+
|
|
494
500
|
const hierarchy = await getHierarchy(contentId, collection)
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
])
|
|
501
|
+
|
|
502
|
+
let ids = {
|
|
503
|
+
...trickleProgress(hierarchy, contentId, collection, progress),
|
|
504
|
+
...await bubbleProgress(hierarchy, contentId, collection)
|
|
505
|
+
}
|
|
506
|
+
await db.contentProgress.recordProgressesTentative(ids, collection)
|
|
507
|
+
|
|
508
|
+
if (collection && collection.type === COLLECTION_TYPE.LEARNING_PATH) {
|
|
509
|
+
let exportIds = ids
|
|
510
|
+
exportIds[contentId] = progress
|
|
511
|
+
await duplicateLearningPathProgressToExternalContents(exportIds, collection, hierarchy)
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
for (const [id, progress] of Object.entries(ids)) {
|
|
515
|
+
if (progress === 100) {
|
|
516
|
+
emitContentCompleted(Number(id), collection)
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
509
520
|
return response
|
|
510
521
|
}
|
|
511
522
|
|
|
523
|
+
async function duplicateLearningPathProgressToExternalContents(ids, collection, hierarchy) {
|
|
524
|
+
// filter out LPs. we dont want to duplicate to LP's while we dont have a-la-cart LP's set up.
|
|
525
|
+
let filteredIds = Object.fromEntries(
|
|
526
|
+
Object.entries(ids).filter((id) => {
|
|
527
|
+
return hierarchy.parents[parseInt(id)] !== null
|
|
528
|
+
})
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
const extProgresses = await getProgressDataByIds(Object.keys(filteredIds), null)
|
|
532
|
+
|
|
533
|
+
// overwrite if LP progress greater, unless LP progress was reset to 0
|
|
534
|
+
filteredIds = Object.entries(filteredIds).filter(([id, pct]) => {
|
|
535
|
+
const extPct = extProgresses[id]?.progress
|
|
536
|
+
return (pct !== 0)
|
|
537
|
+
? pct > extPct
|
|
538
|
+
: false
|
|
539
|
+
})
|
|
540
|
+
|
|
541
|
+
// each handles its own bubbling.
|
|
542
|
+
filteredIds.forEach(([id, pct]) => {
|
|
543
|
+
saveContentProgress(parseInt(id), null, pct)
|
|
544
|
+
})
|
|
545
|
+
}
|
|
546
|
+
|
|
512
547
|
async function getHierarchy(contentId, collection) {
|
|
513
548
|
if (collection && collection.type === COLLECTION_TYPE.LEARNING_PATH) {
|
|
514
549
|
return await fetchLearningPathHierarchy(contentId, collection)
|
|
@@ -519,13 +554,10 @@ async function getHierarchy(contentId, collection) {
|
|
|
519
554
|
|
|
520
555
|
async function setStartedOrCompletedStatuses(contentIds, collection, isCompleted) {
|
|
521
556
|
const progress = isCompleted ? 100 : 0
|
|
522
|
-
// we explicitly pessimistically await a remote push here
|
|
523
|
-
// because awards may be generated (on server) on completion
|
|
524
|
-
// which we would want to toast the user about *in band*
|
|
525
557
|
const response = await db.contentProgress.recordProgresses(contentIds, collection, progress)
|
|
526
558
|
|
|
527
559
|
// we assume this is used only for contents within the same hierarchy
|
|
528
|
-
const hierarchy = await getHierarchy(
|
|
560
|
+
const hierarchy = await getHierarchy(collection.id, collection)
|
|
529
561
|
|
|
530
562
|
let ids = {}
|
|
531
563
|
for (const contentId of contentIds) {
|
|
@@ -535,25 +567,34 @@ async function setStartedOrCompletedStatuses(contentIds, collection, isCompleted
|
|
|
535
567
|
...(await bubbleProgress(hierarchy, contentId, collection)),
|
|
536
568
|
}
|
|
537
569
|
}
|
|
570
|
+
await db.contentProgress.recordProgressesTentative(ids, collection)
|
|
538
571
|
|
|
539
|
-
|
|
572
|
+
if (collection && collection.type === COLLECTION_TYPE.LEARNING_PATH) {
|
|
573
|
+
let exportIds = ids
|
|
574
|
+
for (const contentId of contentIds){
|
|
575
|
+
exportIds[contentId] = progress
|
|
576
|
+
}
|
|
577
|
+
await duplicateLearningPathProgressToExternalContents(exportIds, collection, hierarchy)
|
|
578
|
+
}
|
|
540
579
|
|
|
541
580
|
return response
|
|
542
581
|
}
|
|
543
582
|
|
|
544
583
|
async function resetStatus(contentId, collection = null) {
|
|
584
|
+
const progress = 0
|
|
545
585
|
const response = await db.contentProgress.eraseProgress(contentId, collection)
|
|
546
586
|
const hierarchy = await getHierarchy(contentId, collection)
|
|
547
587
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
588
|
+
let ids = {
|
|
589
|
+
...trickleProgress(hierarchy, contentId, collection, progress),
|
|
590
|
+
...await bubbleProgress(hierarchy, contentId, collection)
|
|
591
|
+
}
|
|
592
|
+
await db.contentProgress.recordProgressesTentative(ids, collection)
|
|
593
|
+
|
|
594
|
+
if (collection && collection.type === COLLECTION_TYPE.LEARNING_PATH) {
|
|
595
|
+
ids[contentId] = progress
|
|
596
|
+
await duplicateLearningPathProgressToExternalContents(ids, collection, hierarchy)
|
|
597
|
+
}
|
|
557
598
|
|
|
558
599
|
return response
|
|
559
600
|
}
|