musora-content-services 2.107.8 → 2.108.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
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.108.0](https://github.com/railroadmedia/musora-content-services/compare/v2.107.8...v2.108.0) (2026-01-02)
6
+
7
+
8
+ ### Features
9
+
10
+ * adds column and implements for hiding cards ([#679](https://github.com/railroadmedia/musora-content-services/issues/679)) ([35ac42c](https://github.com/railroadmedia/musora-content-services/commit/35ac42cebe397c557d0b197d4fab38907ca08ab7))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * some fixes from Rob ([#676](https://github.com/railroadmedia/musora-content-services/issues/676)) ([7e068ee](https://github.com/railroadmedia/musora-content-services/commit/7e068eee3cabc4de1d0620fe58eadf138532ab56))
16
+
5
17
  ### [2.107.8](https://github.com/railroadmedia/musora-content-services/compare/v2.107.7...v2.107.8) (2025-12-30)
6
18
 
7
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.107.8",
3
+ "version": "2.108.0",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -301,6 +301,7 @@ export const progressTypesMapping = {
301
301
  'guided course': ['guided-course'],
302
302
  pack: ['pack', 'semester-pack'],
303
303
  'learning path': ['learning-path-v2'],
304
+ 'skill pack': skillLessonTypes,
304
305
  'jam track': jamTrackLessonTypes,
305
306
  'course video': ['course-lesson'],
306
307
  }
@@ -343,6 +344,7 @@ export const recentTypes = {
343
344
  home: [
344
345
  ...individualLessonsTypes,
345
346
  ...tutorialsLessonTypes,
347
+ ...skillLessonTypes,
346
348
  ...transcriptionsLessonTypes,
347
349
  ...playAlongLessonTypes,
348
350
  'guided-course',
@@ -467,13 +467,14 @@ export async function contentStatusReset(contentId, collection = null, {skipPush
467
467
  return resetStatus(contentId, collection, {skipPush})
468
468
  }
469
469
 
470
- async function saveContentProgress(contentId, collection, progress, currentSeconds, {skipPush = false} = {}) {
470
+ async function saveContentProgress(contentId, collection, progress, currentSeconds, {skipPush = false, hideFromProgressRow = false} = {}) {
471
471
  const isLP = collection?.type === COLLECTION_TYPE.LEARNING_PATH
472
472
 
473
473
  // filter out contentIds that are setting progress lower than existing
474
474
  const contentIdProgress = await getProgressDataByIds([contentId], collection)
475
- if (progress <= contentIdProgress[contentId].progress) {
476
- return
475
+ const currentProgress = contentIdProgress[contentId].progress;
476
+ if (progress <= currentProgress) {
477
+ progress = currentProgress;
477
478
  }
478
479
 
479
480
  const response = await db.contentProgress.recordProgress(
@@ -481,11 +482,15 @@ async function saveContentProgress(contentId, collection, progress, currentSecon
481
482
  collection,
482
483
  progress,
483
484
  currentSeconds,
484
- {skipPush: true}
485
+ {skipPush: true, hideFromProgressRow}
485
486
  )
486
487
  // note - previous implementation explicitly did not trickle progress to children here
487
488
  // (only to siblings/parents via le bubbles)
488
489
 
490
+ if (progress === currentProgress) {
491
+ return
492
+ }
493
+
489
494
  const hierarchy = await getHierarchy(contentId, collection)
490
495
 
491
496
  const bubbledProgresses = await bubbleProgress(hierarchy, contentId, collection)
@@ -499,7 +504,7 @@ async function saveContentProgress(contentId, collection, progress, currentSecon
499
504
  }
500
505
 
501
506
  // BE bubbling/trickling currently does not work, so we utilize non-tentative pushing when learning path collection
502
- await db.contentProgress.recordProgressMany(bubbledProgresses, collection, {tentative: !isLP, skipPush: true})
507
+ await db.contentProgress.recordProgressMany(bubbledProgresses, collection, {tentative: !isLP, skipPush: true, hideFromProgressRow})
503
508
 
504
509
  if (isLP) {
505
510
  let exportIds = bubbledProgresses
@@ -577,11 +582,11 @@ async function duplicateLearningPathProgressToExternalContents(ids, collection,
577
582
  // each handles its own bubbling.
578
583
  // skipPush on all but last to avoid multiple push requests
579
584
  filteredIds.forEach(([id, pct], index) => {
585
+ let skip = true
580
586
  if (index === filteredIds.length - 1) {
581
- saveContentProgress(parseInt(id), null, pct, null, {skipPush})
582
- } else {
583
- saveContentProgress(parseInt(id), null, pct, null, {skipPush: true})
587
+ skip = skipPush
584
588
  }
589
+ saveContentProgress(parseInt(id), null, pct, null, {skipPush: skip, hideFromProgressRow: true})
585
590
  })
586
591
  }
587
592
 
@@ -53,6 +53,9 @@ export default class ContentProgress extends BaseModel<{
53
53
  get resume_time_seconds() {
54
54
  return (this._getRaw('resume_time_seconds') as number) || null
55
55
  }
56
+ get hide_from_progress_row() {
57
+ return this._getRaw('hide_from_progress_row') as boolean
58
+ }
56
59
 
57
60
  set content_id(value: number) {
58
61
  // unsigned int
@@ -87,5 +90,8 @@ export default class ContentProgress extends BaseModel<{
87
90
  throwIfNotNullableNumber(value)
88
91
  this._setRaw('resume_time_seconds', value !== null ? throwIfOutsideRange(value, 0, 65535) : value)
89
92
  }
93
+ set hide_from_progress_row(value: boolean) {
94
+ this._setRaw('hide_from_progress_row', value)
95
+ }
90
96
 
91
97
  }
@@ -62,6 +62,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
62
62
  Q.where('collection_type', COLLECTION_TYPE.SELF),
63
63
  Q.where('collection_id', COLLECTION_ID_SELF),
64
64
 
65
+ Q.where('hide_from_progress_row', false),
66
+
65
67
  Q.or(Q.where('state', STATE.STARTED), Q.where('state', STATE.COMPLETED)),
66
68
  Q.sortBy('updated_at', 'desc'),
67
69
  ]
@@ -133,7 +135,7 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
133
135
  }
134
136
  }
135
137
 
136
- recordProgress(contentId: number, collection: CollectionParameter | null, progressPct: number, resumeTime?: number, {skipPush = false} = {}) {
138
+ recordProgress(contentId: number, collection: CollectionParameter | null, progressPct: number, resumeTime?: number, {skipPush = false, hideFromProgressRow = false} = {}) {
137
139
  const id = ProgressRepository.generateId(contentId, collection)
138
140
 
139
141
  const result = this.upsertOne(id, (r) => {
@@ -146,6 +148,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
146
148
  if (typeof resumeTime != 'undefined') {
147
149
  r.resume_time_seconds = Math.floor(resumeTime)
148
150
  }
151
+
152
+ r.hide_from_progress_row = hideFromProgressRow
149
153
  }, { skipPush })
150
154
 
151
155
  // Emit event AFTER database write completes
@@ -176,7 +180,7 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
176
180
  recordProgressMany(
177
181
  contentProgresses: Record<string, number>, // Accept plain object
178
182
  collection: CollectionParameter | null,
179
- { tentative = true, skipPush = false }: { tentative?: boolean; skipPush?: boolean } = {}
183
+ { tentative = true, skipPush = false, hideFromProgressRow = false }: { tentative?: boolean; skipPush?: boolean; hideFromProgressRow?: boolean } = {}
180
184
  ) {
181
185
 
182
186
  const data = Object.fromEntries(
@@ -188,6 +192,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
188
192
  r.collection_id = collection?.id ?? COLLECTION_ID_SELF
189
193
 
190
194
  r.progress_percent = progressPct
195
+
196
+ r.hide_from_progress_row = hideFromProgressRow
191
197
  },
192
198
  ])
193
199
  )
@@ -26,6 +26,7 @@ const contentProgressTable = tableSchema({
26
26
  { name: 'state', type: 'string', isIndexed: true },
27
27
  { name: 'progress_percent', type: 'number' },
28
28
  { name: 'resume_time_seconds', type: 'number', isOptional: true },
29
+ { name: 'hide_from_progress_row', type: 'boolean'},
29
30
  { name: 'created_at', type: 'number' },
30
31
  { name: 'updated_at', type: 'number', isIndexed: true }
31
32
  ]