musora-content-services 2.7.3 → 2.8.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 +9 -0
- package/docs/ContentOrganization.html +2 -2
- package/docs/Gamification.html +2 -2
- package/docs/UserManagementSystem.html +2 -2
- package/docs/api_types.js.html +2 -2
- package/docs/config.js.html +2 -2
- package/docs/content-org_content-org.js.html +2 -2
- package/docs/content-org_playlists-types.js.html +2 -2
- package/docs/content-org_playlists.js.html +2 -4
- package/docs/content.js.html +2 -2
- package/docs/gamification_awards.js.html +2 -2
- package/docs/gamification_gamification.js.html +2 -2
- package/docs/gamification_types.js.html +2 -2
- package/docs/global.html +2 -2
- package/docs/index.html +2 -2
- package/docs/module-Awards.html +2 -2
- package/docs/module-Config.html +2 -2
- package/docs/module-Content-Services-V2.html +2 -2
- package/docs/module-Interests.html +2 -2
- package/docs/module-Permissions.html +2 -2
- package/docs/module-Playlists.html +13 -13
- package/docs/module-Railcontent-Services.html +2 -2
- package/docs/module-Sanity-Services.html +2 -2
- package/docs/module-Sessions.html +2 -2
- package/docs/module-User-Activity.html +7 -7
- package/docs/module-UserManagement.html +448 -23
- package/docs/module-UserProfile.html +2 -2
- package/docs/railcontent.js.html +2 -2
- package/docs/sanity.js.html +2 -2
- package/docs/userActivity.js.html +2 -12
- package/docs/user_interests.js.html +2 -2
- package/docs/user_management.js.html +85 -12
- package/docs/user_permissions.js.html +2 -2
- package/docs/user_profile.js.html +2 -2
- package/docs/user_sessions.js.html +2 -2
- package/docs/user_types.js.html +2 -2
- package/docs/user_user-management-system.js.html +2 -2
- package/link_mcs.sh +0 -0
- package/package.json +1 -1
- package/src/contentMetaData.js +2 -2
- package/src/contentTypeConfig.js +10 -5
- package/src/index.d.ts +9 -1
- package/src/index.js +9 -1
- package/src/lib/httpHelper.js +60 -20
- package/src/services/dateUtils.js +29 -0
- package/src/services/user/management.js +83 -10
- package/src/services/userActivity.js +194 -43
- package/test/userActivity.test.js +0 -0
package/src/index.d.ts
CHANGED
|
@@ -68,6 +68,7 @@ import {
|
|
|
68
68
|
import {
|
|
69
69
|
convertToTimeZone,
|
|
70
70
|
getMonday,
|
|
71
|
+
getTimeRemainingUntilLocal,
|
|
71
72
|
getWeekNumber,
|
|
72
73
|
isNextDay,
|
|
73
74
|
isSameDate
|
|
@@ -221,7 +222,10 @@ import {
|
|
|
221
222
|
|
|
222
223
|
import {
|
|
223
224
|
blockUser,
|
|
224
|
-
|
|
225
|
+
deletePicture,
|
|
226
|
+
unblockUser,
|
|
227
|
+
uploadPicture,
|
|
228
|
+
uploadPictureFromS3
|
|
225
229
|
} from './services/user/management.js';
|
|
226
230
|
|
|
227
231
|
import {
|
|
@@ -282,6 +286,7 @@ declare module 'musora-content-services' {
|
|
|
282
286
|
createPracticeNotes,
|
|
283
287
|
deleteComment,
|
|
284
288
|
deleteItemsFromPlaylist,
|
|
289
|
+
deletePicture,
|
|
285
290
|
deletePlaylist,
|
|
286
291
|
deletePracticeSession,
|
|
287
292
|
deleteUserActivity,
|
|
@@ -396,6 +401,7 @@ declare module 'musora-content-services' {
|
|
|
396
401
|
getScheduleContentRows,
|
|
397
402
|
getSortOrder,
|
|
398
403
|
getTabResults,
|
|
404
|
+
getTimeRemainingUntilLocal,
|
|
399
405
|
getUserMonthlyStats,
|
|
400
406
|
getUserPractices,
|
|
401
407
|
getUserWeeklyStats,
|
|
@@ -459,6 +465,8 @@ declare module 'musora-content-services' {
|
|
|
459
465
|
updatePlaylist,
|
|
460
466
|
updatePracticeNotes,
|
|
461
467
|
updateUserPractice,
|
|
468
|
+
uploadPicture,
|
|
469
|
+
uploadPictureFromS3,
|
|
462
470
|
verifyImageSRC,
|
|
463
471
|
verifyLocalDataContext,
|
|
464
472
|
}
|
package/src/index.js
CHANGED
|
@@ -68,6 +68,7 @@ import {
|
|
|
68
68
|
import {
|
|
69
69
|
convertToTimeZone,
|
|
70
70
|
getMonday,
|
|
71
|
+
getTimeRemainingUntilLocal,
|
|
71
72
|
getWeekNumber,
|
|
72
73
|
isNextDay,
|
|
73
74
|
isSameDate
|
|
@@ -221,7 +222,10 @@ import {
|
|
|
221
222
|
|
|
222
223
|
import {
|
|
223
224
|
blockUser,
|
|
224
|
-
|
|
225
|
+
deletePicture,
|
|
226
|
+
unblockUser,
|
|
227
|
+
uploadPicture,
|
|
228
|
+
uploadPictureFromS3
|
|
225
229
|
} from './services/user/management.js';
|
|
226
230
|
|
|
227
231
|
import {
|
|
@@ -281,6 +285,7 @@ export {
|
|
|
281
285
|
createPracticeNotes,
|
|
282
286
|
deleteComment,
|
|
283
287
|
deleteItemsFromPlaylist,
|
|
288
|
+
deletePicture,
|
|
284
289
|
deletePlaylist,
|
|
285
290
|
deletePracticeSession,
|
|
286
291
|
deleteUserActivity,
|
|
@@ -395,6 +400,7 @@ export {
|
|
|
395
400
|
getScheduleContentRows,
|
|
396
401
|
getSortOrder,
|
|
397
402
|
getTabResults,
|
|
403
|
+
getTimeRemainingUntilLocal,
|
|
398
404
|
getUserMonthlyStats,
|
|
399
405
|
getUserPractices,
|
|
400
406
|
getUserWeeklyStats,
|
|
@@ -458,6 +464,8 @@ export {
|
|
|
458
464
|
updatePlaylist,
|
|
459
465
|
updatePracticeNotes,
|
|
460
466
|
updateUserPractice,
|
|
467
|
+
uploadPicture,
|
|
468
|
+
uploadPictureFromS3,
|
|
461
469
|
verifyImageSRC,
|
|
462
470
|
verifyLocalDataContext,
|
|
463
471
|
};
|
package/src/lib/httpHelper.js
CHANGED
|
@@ -1,44 +1,84 @@
|
|
|
1
1
|
import { globalConfig } from '../services/config.js'
|
|
2
2
|
|
|
3
|
-
export async function fetchJSONHandler(
|
|
4
|
-
|
|
3
|
+
export async function fetchJSONHandler(
|
|
4
|
+
url,
|
|
5
|
+
token,
|
|
6
|
+
baseUrl,
|
|
7
|
+
method = 'get',
|
|
8
|
+
dataVersion = null,
|
|
9
|
+
body = null
|
|
10
|
+
) {
|
|
11
|
+
const headers = {
|
|
5
12
|
'Content-Type': 'application/json',
|
|
6
13
|
Accept: 'application/json',
|
|
7
14
|
'X-CSRF-TOKEN': token,
|
|
8
15
|
}
|
|
9
16
|
|
|
17
|
+
if (body) {
|
|
18
|
+
body = JSON.stringify(body)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const response = await fetchHandler(url, token, baseUrl, method, headers, dataVersion, body)
|
|
23
|
+
|
|
24
|
+
if (response.ok) {
|
|
25
|
+
const contentType = response.headers.get('content-type')
|
|
26
|
+
if (
|
|
27
|
+
contentType &&
|
|
28
|
+
contentType.indexOf('application/json') !== -1 &&
|
|
29
|
+
response.status !== 204
|
|
30
|
+
) {
|
|
31
|
+
return await response.json()
|
|
32
|
+
} else {
|
|
33
|
+
return await response.text()
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
console.error(`Fetch error: ${method} ${url} ${response.status} ${response.statusText}`)
|
|
37
|
+
console.log(response)
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('Fetch error:', error)
|
|
41
|
+
}
|
|
42
|
+
return null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function fetchHandler(
|
|
46
|
+
url,
|
|
47
|
+
token,
|
|
48
|
+
baseUrl,
|
|
49
|
+
method = 'get',
|
|
50
|
+
headers = {},
|
|
51
|
+
dataVersion = null,
|
|
52
|
+
body = null
|
|
53
|
+
) {
|
|
54
|
+
let reqHeaders = {
|
|
55
|
+
...headers,
|
|
56
|
+
Accept: 'application/json',
|
|
57
|
+
'X-CSRF-TOKEN': token,
|
|
58
|
+
}
|
|
59
|
+
|
|
10
60
|
if (!globalConfig.isMA) {
|
|
11
61
|
const params = new URLSearchParams(window.location.search)
|
|
12
62
|
if (params.get('testNow')) {
|
|
13
|
-
|
|
63
|
+
reqHeaders['testNow'] = params.get('testNow')
|
|
14
64
|
}
|
|
15
65
|
if (params.get('timezone')) {
|
|
16
|
-
|
|
66
|
+
reqHeaders['M-Client-Timezone'] = params.get('timezone')
|
|
17
67
|
}
|
|
18
68
|
}
|
|
19
69
|
|
|
20
|
-
if (globalConfig.localTimezoneString)
|
|
21
|
-
|
|
70
|
+
if (globalConfig.localTimezoneString)
|
|
71
|
+
reqHeaders['M-Client-Timezone'] = globalConfig.localTimezoneString
|
|
72
|
+
if (dataVersion) reqHeaders['Data-Version'] = dataVersion
|
|
22
73
|
const options = {
|
|
23
74
|
method,
|
|
24
|
-
headers,
|
|
75
|
+
headers: reqHeaders,
|
|
25
76
|
}
|
|
26
|
-
if (body) options.body =
|
|
77
|
+
if (body) options.body = body
|
|
27
78
|
if (token) options.headers['Authorization'] = `Bearer ${token}`
|
|
28
79
|
if (baseUrl && url.startsWith('/')) url = baseUrl + url
|
|
29
80
|
try {
|
|
30
|
-
|
|
31
|
-
if (response.ok) {
|
|
32
|
-
const contentType = response.headers.get("content-type");
|
|
33
|
-
if (contentType && contentType.indexOf("application/json") !== -1) {
|
|
34
|
-
return await response.json()
|
|
35
|
-
} else {
|
|
36
|
-
return await response.text()
|
|
37
|
-
}
|
|
38
|
-
} else {
|
|
39
|
-
console.error(`Fetch error: ${method} ${url} ${response.status} ${response.statusText}`)
|
|
40
|
-
console.log(response)
|
|
41
|
-
}
|
|
81
|
+
return fetch(url, options)
|
|
42
82
|
} catch (error) {
|
|
43
83
|
console.error('Fetch error:', error)
|
|
44
84
|
}
|
|
@@ -53,3 +53,32 @@ export function isNextDay(prev, current) {
|
|
|
53
53
|
);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
export function getTimeRemainingUntilLocal(targetUtcIsoString, {withTotalSeconds} = {}) {
|
|
57
|
+
const targetUTC = new Date(targetUtcIsoString);
|
|
58
|
+
if (isNaN(targetUTC.getTime())) {
|
|
59
|
+
return "00:00:00";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const now = new Date();
|
|
63
|
+
const diff = targetUTC.getTime() - now.getTime();
|
|
64
|
+
|
|
65
|
+
if (diff <= 0) {
|
|
66
|
+
return "00:00:00";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const totalSeconds = Math.floor(diff / 1000);
|
|
70
|
+
const hours = String(Math.floor(totalSeconds / 3600)).padStart(2, '0');
|
|
71
|
+
const minutes = String(Math.floor((totalSeconds % 3600) / 60)).padStart(2, '0');
|
|
72
|
+
const seconds = String(totalSeconds % 60).padStart(2, '0');
|
|
73
|
+
if(withTotalSeconds) {
|
|
74
|
+
return {
|
|
75
|
+
totalSeconds,
|
|
76
|
+
formatted: `${hours}:${minutes}:${seconds}`
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return `${hours}:${minutes}:${seconds}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module UserManagement
|
|
3
3
|
*/
|
|
4
|
-
import { fetchHandler } from '../railcontent.js'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* Exported functions that are excluded from index generation.
|
|
8
|
-
*
|
|
9
|
-
* @type {string[]}
|
|
10
|
-
*/
|
|
11
|
-
const excludeFromGeneratedIndex = []
|
|
4
|
+
import { fetchHandler as railcontentFetchHandler } from '../railcontent.js'
|
|
5
|
+
import { fetchHandler, fetchJSONHandler } from '../../lib/httpHelper.js'
|
|
6
|
+
import { globalConfig } from '../config.js'
|
|
12
7
|
|
|
13
8
|
const baseUrl = `/api/user-management-system`
|
|
14
9
|
|
|
@@ -19,7 +14,7 @@ const baseUrl = `/api/user-management-system`
|
|
|
19
14
|
*/
|
|
20
15
|
export async function blockUser(userId) {
|
|
21
16
|
const url = `${baseUrl}/v1/block/${userId}`
|
|
22
|
-
return
|
|
17
|
+
return railcontentFetchHandler(url, 'post')
|
|
23
18
|
}
|
|
24
19
|
|
|
25
20
|
/**
|
|
@@ -29,5 +24,83 @@ export async function blockUser(userId) {
|
|
|
29
24
|
*/
|
|
30
25
|
export async function unblockUser(userId) {
|
|
31
26
|
const url = `${baseUrl}/v1/unblock/${userId}`
|
|
32
|
-
return
|
|
27
|
+
return railcontentFetchHandler(url, 'post')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Upload a picture to the server
|
|
32
|
+
* @param {string} fieldKey
|
|
33
|
+
* @param {File} file
|
|
34
|
+
* @returns {Promise<any|string|null>}
|
|
35
|
+
*/
|
|
36
|
+
export async function uploadPicture(fieldKey, file) {
|
|
37
|
+
const formData = new FormData()
|
|
38
|
+
formData.append('file', file)
|
|
39
|
+
formData.append('fieldKey', fieldKey)
|
|
40
|
+
const apiUrl = `${baseUrl}/v1/picture`
|
|
41
|
+
|
|
42
|
+
const response = await fetchHandler(
|
|
43
|
+
apiUrl,
|
|
44
|
+
globalConfig.sessionConfig.token,
|
|
45
|
+
globalConfig.baseUrl,
|
|
46
|
+
'POST',
|
|
47
|
+
null,
|
|
48
|
+
null,
|
|
49
|
+
formData
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
const problemDetails = await response.json()
|
|
54
|
+
console.log('Error uploading picture:', problemDetails.detail)
|
|
55
|
+
throw new Error(`Upload failed: ${problemDetails.detail}`)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const { url } = await response.json()
|
|
59
|
+
console.log('Picture uploaded successfully:', url)
|
|
60
|
+
|
|
61
|
+
return url
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Saves a picture uploaded to S3
|
|
66
|
+
* @param {string} fieldKey
|
|
67
|
+
* @param {string} s3_bucket_path
|
|
68
|
+
* @returns {Promise<any|string|null>}
|
|
69
|
+
*/
|
|
70
|
+
export async function uploadPictureFromS3(fieldKey, s3_bucket_path) {
|
|
71
|
+
const apiUrl = `${baseUrl}/v1/picture/s3`
|
|
72
|
+
|
|
73
|
+
const response = await fetchJSONHandler(
|
|
74
|
+
apiUrl,
|
|
75
|
+
globalConfig.sessionConfig.token,
|
|
76
|
+
globalConfig.baseUrl,
|
|
77
|
+
'POST',
|
|
78
|
+
null,
|
|
79
|
+
{
|
|
80
|
+
fieldKey,
|
|
81
|
+
s3_bucket_path,
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
const problemDetails = await response.json()
|
|
87
|
+
console.log('Error uploading picture:', problemDetails.detail)
|
|
88
|
+
throw new Error(`Upload failed: ${problemDetails.detail}`)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const { url } = await response.json()
|
|
92
|
+
|
|
93
|
+
return url
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {string} pictureUrl
|
|
98
|
+
* @returns {Promise<any>}
|
|
99
|
+
*/
|
|
100
|
+
export async function deletePicture(pictureUrl) {
|
|
101
|
+
const apiUrl = `${baseUrl}/v1/picture`
|
|
102
|
+
|
|
103
|
+
fetchJSONHandler(apiUrl, globalConfig.sessionConfig.token, globalConfig.baseUrl, 'DELETE', null, {
|
|
104
|
+
picture_url: pictureUrl,
|
|
105
|
+
})
|
|
33
106
|
}
|