musora-content-services 2.3.15 → 2.3.16

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.
@@ -0,0 +1,19 @@
1
+ ## Jira Ticket(s)/RelatedPR(s)
2
+
3
+ - _Provide link to Jira tickets or other connected PRs_
4
+
5
+ ## Description/Design
6
+
7
+ - _Provide a brief description of your changes. The context of why you made changes is more important than the what._
8
+
9
+ ## Testing
10
+
11
+ - _How can this be verified?_
12
+ - _Setup required_
13
+ - _what page(s) are applicable_
14
+ - _what action(s) should a user take_
15
+ - _what is the expected outcome?_
16
+
17
+ ## Additional Notes
18
+
19
+ - _Provide any additional context or notes that might be helpful for the reviewer._
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.3.16](https://github.com/railroadmedia/musora-content-services/compare/v2.3.15...v2.3.16) (2025-04-22)
6
+
5
7
  ### [2.3.15](https://github.com/railroadmedia/musora-content-services/compare/v2.3.14...v2.3.15) (2025-04-11)
6
8
 
7
9
  ### [2.3.14](https://github.com/railroadmedia/musora-content-services/compare/v2.3.13...v2.3.14) (2025-04-11)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.3.15",
3
+ "version": "2.3.16",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -0,0 +1,57 @@
1
+ import { getProgressStateByIds, getProgressPercentageByIds, getResumeTimeSecondsByIds } from "./services/contentProgress"
2
+ import { isContentLikedByIds } from "./services/contentLikes"
3
+ import { fetchLikeCount } from "./services/railcontent"
4
+
5
+ export const addContextToContent = async (dataPromise, ...dataArgs) => {
6
+ const lastArg = dataArgs[dataArgs.length - 1]
7
+ const options = typeof lastArg === 'object' && !Array.isArray(lastArg) ? lastArg : {}
8
+
9
+ const {
10
+ dataField = null,
11
+ addProgressPercentage = false,
12
+ addIsLiked = false,
13
+ addLikeCount = false,
14
+ addStatus = false,
15
+ addResumeTimeSeconds = false
16
+ } = options
17
+
18
+ const dataParam = lastArg === options ? dataArgs.slice(0, -1) : dataArgs
19
+
20
+ const data = await dataPromise(...dataParam)
21
+ if(!data) return false
22
+
23
+ let ids = []
24
+
25
+ if (dataField && data?.[dataField]) {
26
+ ids = data[dataField].map(item => item?.id).filter(Boolean);
27
+ } else if (Array.isArray(data)) {
28
+ ids = data.map(item => item?.id).filter(Boolean);
29
+ } else if (data?.id) {
30
+ ids = [data.id]
31
+ }
32
+
33
+ if(ids.length === 0) return false
34
+
35
+ const [progressPercentageData, statusData, isLikedData, resumeTimeData] = await Promise.all([
36
+ addProgressPercentage ? getProgressPercentageByIds(ids) : Promise.resolve(null),
37
+ addStatus ? getProgressStateByIds(ids) : Promise.resolve(null),
38
+ addIsLiked ? isContentLikedByIds(ids) : Promise.resolve(null),
39
+ addResumeTimeSeconds ? getResumeTimeSecondsByIds(ids) : Promise.resolve(null),
40
+ ])
41
+
42
+ const addContext = async (item) => ({
43
+ ...item,
44
+ ...(addProgressPercentage ? { progressPercentage: progressPercentageData?.[item.id] } : {}),
45
+ ...(addStatus ? { progressStatus: statusData?.[item.id] } : {}),
46
+ ...(addIsLiked ? { isLiked: isLikedData?.[item.id] } : {}),
47
+ ...(addLikeCount && ids.length === 1 ? { likeCount: await fetchLikeCount(item.id) } : {}),
48
+ ...(addResumeTimeSeconds ? { resumeTime: resumeTimeData?.[item.id] } : {}),
49
+ })
50
+
51
+ const newData = Array.isArray(data)
52
+ ? await Promise.all(data.map(addContext))
53
+ : await addContext(data)
54
+
55
+ return newData
56
+ }
57
+
package/src/index.d.ts CHANGED
@@ -137,6 +137,7 @@ import {
137
137
  postContentUnliked,
138
138
  postRecordWatchSession,
139
139
  replyToComment,
140
+ reportComment,
140
141
  reportPlaylist,
141
142
  setStudentViewForUser,
142
143
  unassignModeratorToComment,
@@ -235,8 +236,11 @@ import {
235
236
  updateUserPractice
236
237
  } from './services/userActivity.js';
237
238
 
239
+ import { addContextToContent } from './contentAggregator.js';
240
+
238
241
  declare module 'musora-content-services' {
239
242
  export {
243
+ addContextToContent,
240
244
  addItemToPlaylist,
241
245
  applyCloudflareWrapper,
242
246
  applySanityTransformations,
@@ -402,6 +406,7 @@ declare module 'musora-content-services' {
402
406
  recordWatchSession,
403
407
  removeUserPractice,
404
408
  replyToComment,
409
+ reportComment,
405
410
  reportPlaylist,
406
411
  reset,
407
412
  restorePracticeSession,
package/src/index.js CHANGED
@@ -137,6 +137,7 @@ import {
137
137
  postContentUnliked,
138
138
  postRecordWatchSession,
139
139
  replyToComment,
140
+ reportComment,
140
141
  reportPlaylist,
141
142
  setStudentViewForUser,
142
143
  unassignModeratorToComment,
@@ -235,7 +236,10 @@ import {
235
236
  updateUserPractice
236
237
  } from './services/userActivity.js';
237
238
 
239
+ import { addContextToContent } from './contentAggregator.js';
240
+
238
241
  export {
242
+ addContextToContent,
239
243
  addItemToPlaylist,
240
244
  applyCloudflareWrapper,
241
245
  applySanityTransformations,
@@ -401,6 +405,7 @@ export {
401
405
  recordWatchSession,
402
406
  removeUserPractice,
403
407
  replyToComment,
408
+ reportComment,
404
409
  reportPlaylist,
405
410
  reset,
406
411
  restorePracticeSession,
@@ -16,6 +16,15 @@ export async function isContentLiked(contentId) {
16
16
  return data.includes(contentId)
17
17
  }
18
18
 
19
+ export async function isContentLikedByIds(contentIds) {
20
+ const data = await dataContext.getData()
21
+ const likes = {}
22
+
23
+ contentIds?.forEach((id) => (likes[id] = data.includes(id)))
24
+
25
+ return likes
26
+ }
27
+
19
28
  export async function likeContent(contentId) {
20
29
  contentId = parseInt(contentId)
21
30
  await dataContext.update(
@@ -16,30 +16,38 @@ const DATA_KEY_LAST_UPDATED_TIME = 'u'
16
16
  export let dataContext = new DataContext(ContentProgressVersionKey, fetchContentProgress)
17
17
 
18
18
  export async function getProgressPercentage(contentId) {
19
- let data = await dataContext.getData()
20
- return data[contentId]?.[DATA_KEY_PROGRESS] ?? 0
19
+ return getById(contentIds, DATA_KEY_PROGRESS, 0)
21
20
  }
22
21
 
23
22
  export async function getProgressPercentageByIds(contentIds) {
24
- const data = await dataContext.getData()
25
- let progress = {}
26
-
27
- contentIds?.forEach((id) => (progress[id] = data[id]?.[DATA_KEY_PROGRESS] ?? 0))
28
-
29
- return progress
23
+ return getByIds(contentIds, DATA_KEY_PROGRESS, 0)
30
24
  }
31
25
 
32
26
  export async function getProgressState(contentId) {
33
- let data = await dataContext.getData()
34
- return data[contentId]?.[DATA_KEY_STATUS] ?? ''
27
+ return getById(contentId, DATA_KEY_STATUS, '')
35
28
  }
36
29
 
37
30
  export async function getProgressStateByIds(contentIds) {
38
- const data = await dataContext.getData()
39
- let progress = {}
31
+ return getByIds(contentIds, DATA_KEY_STATUS, '')
32
+ }
40
33
 
41
- contentIds?.forEach((id) => (progress[id] = data[id]?.[DATA_KEY_STATUS] ?? ''))
34
+ export async function getResumeTimeSeconds(contentId) {
35
+ return getById(contentId, DATA_KEY_RESUME_TIME, 0)
36
+ }
42
37
 
38
+ export async function getResumeTimeSecondsByIds(contentIds) {
39
+ return getByIds(contentIds, DATA_KEY_RESUME_TIME, 0)
40
+ }
41
+
42
+ async function getById(contentId, dataKey, defaultValue) {
43
+ let data = await dataContext.getData()
44
+ return data[contentId]?.[dataKey] ?? defaultValue
45
+ }
46
+
47
+ async function getByIds(contentIds, dataKey, defaultValue) {
48
+ let data = await dataContext.getData()
49
+ let progress = {}
50
+ contentIds?.forEach((id) => (progress[id] = data[id]?.[dataKey] ?? defaultValue))
43
51
  return progress
44
52
  }
45
53
 
@@ -112,11 +120,6 @@ export async function getAllStartedOrCompleted(limit = null) {
112
120
  return ids
113
121
  }
114
122
 
115
- export async function getResumeTimeSeconds(contentId) {
116
- let data = await dataContext.getData()
117
- return data[contentId]?.[DATA_KEY_RESUME_TIME] ?? 0
118
- }
119
-
120
123
  export async function assignmentStatusCompleted(assignmentId, parentContentId) {
121
124
  await dataContext.update(
122
125
  async function (localContext) {
@@ -294,6 +294,11 @@ async function deleteDataHandler(url, data) {
294
294
  return fetchHandler(url, 'delete')
295
295
  }
296
296
 
297
+ export async function fetchLikeCount(contendId){
298
+ const url = `/api/content/v1/content/like_count/${contendId}`
299
+ return await fetchDataHandler(url)
300
+ }
301
+
297
302
  export async function fetchUserLikes(currentVersion) {
298
303
  let url = `/api/content/v1/user/likes`
299
304
  return fetchDataHandler(url, currentVersion)
@@ -1175,6 +1180,19 @@ export async function editComment(commentId, comment) {
1175
1180
  return await patchDataHandler(url, data)
1176
1181
  }
1177
1182
 
1183
+ /**
1184
+ * @param {int} commentId
1185
+ * @param {string} issue
1186
+ * @returns {Promise<*|null>}
1187
+ */
1188
+ export async function reportComment(commentId, issue) {
1189
+ const url = `/api/content/v1/comments/${commentId}/report`
1190
+ const data = {
1191
+ issue: issue,
1192
+ }
1193
+ return await postDataHandler(url, data)
1194
+ }
1195
+
1178
1196
  export async function fetchUserPractices(currentVersion) {
1179
1197
  const url = `/api/user/practices/v1/practices`;
1180
1198
  const response = await fetchDataHandler(url, currentVersion);