fcad-core-dragon 2.0.0-beta.1 → 2.0.0-beta.10

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.
Files changed (163) hide show
  1. package/.editorconfig +6 -31
  2. package/.prettierrc +11 -0
  3. package/.vscode/extensions.json +8 -0
  4. package/.vscode/settings.json +16 -0
  5. package/CHANGELOG +153 -0
  6. package/README.md +28 -43
  7. package/documentation/.vitepress/config.js +114 -0
  8. package/documentation/api-examples.md +49 -0
  9. package/documentation/composants/app-base-button.md +58 -0
  10. package/documentation/composants/app-base-error-display.md +59 -0
  11. package/documentation/composants/app-base-popover.md +68 -0
  12. package/documentation/composants/app-comp-audio.md +75 -0
  13. package/documentation/composants/app-comp-branch-buttons.md +111 -0
  14. package/documentation/composants/app-comp-button-progress.md +53 -0
  15. package/documentation/composants/app-comp-carousel.md +53 -0
  16. package/documentation/composants/app-comp-container.md +53 -0
  17. package/documentation/composants/app-comp-input-checkbox-next.md +42 -0
  18. package/documentation/composants/app-comp-input-dropdown-next.md +34 -0
  19. package/documentation/composants/app-comp-input-radio-next.md +39 -0
  20. package/documentation/composants/app-comp-input-text-next.md +35 -0
  21. package/documentation/composants/app-comp-input-text-table-next.md +34 -0
  22. package/documentation/composants/app-comp-input-text-to-fill-dropdown-next.md +53 -0
  23. package/documentation/composants/app-comp-input-text-to-fill-next.md +31 -0
  24. package/documentation/composants/app-comp-jauge.md +31 -0
  25. package/documentation/composants/app-comp-menu-item.md +55 -0
  26. package/documentation/composants/app-comp-menu.md +29 -0
  27. package/documentation/composants/app-comp-navigation.md +41 -0
  28. package/documentation/composants/app-comp-note-call.md +53 -0
  29. package/documentation/composants/app-comp-note-credit.md +53 -0
  30. package/documentation/composants/app-comp-play-bar-next.md +53 -0
  31. package/documentation/composants/app-comp-pop-up-next.md +93 -0
  32. package/documentation/composants/app-comp-quiz-next.md +235 -0
  33. package/documentation/composants/app-comp-quiz-recall.md +53 -0
  34. package/documentation/composants/app-comp-svg-next.md +53 -0
  35. package/documentation/composants/app-comp-table-of-content.md +50 -0
  36. package/documentation/composants/app-comp-video-player.md +82 -0
  37. package/documentation/composants.md +46 -0
  38. package/documentation/composants_critiques/ModelPageComposant.md +53 -0
  39. package/documentation/composants_critiques/app-base-module.md +43 -0
  40. package/documentation/composants_critiques/app-base-page.md +48 -0
  41. package/documentation/composants_critiques/app-base.md +311 -0
  42. package/documentation/composants_critiques/main.md +15 -0
  43. package/documentation/demarrage.md +50 -0
  44. package/documentation/deploiement.md +58 -0
  45. package/documentation/index.md +33 -0
  46. package/documentation/markdown-examples.md +85 -0
  47. package/documentation/public/npm_version.png +0 -0
  48. package/documentation/public/vite.svg +15 -0
  49. package/documentation/public/vuejs.svg +2 -0
  50. package/documentation/public/vuetify.svg +6 -0
  51. package/eslint.config.js +60 -0
  52. package/package.json +43 -47
  53. package/src/$locales/en.json +86 -108
  54. package/src/$locales/fr.json +66 -127
  55. package/src/assets/data/onboardingMessages.json +1 -1
  56. package/src/components/AppBase.vue +960 -405
  57. package/src/components/AppBaseButton.test.js +21 -0
  58. package/src/components/AppBaseButton.vue +42 -10
  59. package/src/components/AppBaseErrorDisplay.vue +207 -189
  60. package/src/components/AppBaseFlipCard.vue +1 -0
  61. package/src/components/AppBaseModule.vue +769 -977
  62. package/src/components/AppBasePage.vue +635 -81
  63. package/src/components/AppBasePopover.vue +41 -0
  64. package/src/components/AppBaseSkeleton.vue +66 -0
  65. package/src/components/AppCompAudio.vue +256 -0
  66. package/src/components/AppCompBranchButtons.vue +79 -153
  67. package/src/components/AppCompButtonProgress.vue +21 -36
  68. package/src/components/AppCompCarousel.vue +231 -87
  69. package/src/components/{AppCompTranscript.vue → AppCompContainer.vue} +12 -2
  70. package/src/components/AppCompInputCheckBoxNx.vue +323 -0
  71. package/src/components/AppCompInputDropdownNx.vue +299 -0
  72. package/src/components/AppCompInputRadioNx.vue +284 -0
  73. package/src/components/AppCompInputTextNx.vue +153 -0
  74. package/src/components/AppCompInputTextTableNx.vue +202 -0
  75. package/src/components/AppCompInputTextToFillDropdownNx.vue +340 -0
  76. package/src/components/AppCompInputTextToFillNx.vue +313 -0
  77. package/src/components/AppCompJauge.vue +36 -10
  78. package/src/components/AppCompMenu.vue +246 -32
  79. package/src/components/AppCompMenuItem.vue +87 -21
  80. package/src/components/AppCompNavigation.vue +470 -447
  81. package/src/components/AppCompNoteCall.vue +93 -58
  82. package/src/components/AppCompNoteCredit.vue +423 -96
  83. package/src/components/AppCompPlayBarNext.vue +2288 -0
  84. package/src/components/AppCompPopUpNext.vue +504 -0
  85. package/src/components/AppCompQuizNext.vue +510 -0
  86. package/src/components/AppCompQuizRecall.vue +199 -99
  87. package/src/components/AppCompSVGNext.vue +346 -0
  88. package/src/components/AppCompSettingsMenu.vue +17 -16
  89. package/src/components/AppCompTableOfContent.vue +262 -99
  90. package/src/components/AppCompVideoPlayer.vue +183 -142
  91. package/src/components/BaseModule.vue +8 -20
  92. package/src/components/tests__/AppBaseButton.spec.js +53 -0
  93. package/src/components/tests__/useTimer.spec.js +91 -0
  94. package/src/composables/useIdleDetector.js +56 -0
  95. package/src/composables/useQuiz.js +89 -0
  96. package/src/composables/useTimer.js +172 -0
  97. package/src/directives/nvdaFix.js +53 -0
  98. package/src/externalComps/ModuleView.vue +22 -0
  99. package/src/externalComps/SummaryView.vue +91 -0
  100. package/src/main.js +397 -148
  101. package/src/module/stores/appStore.js +947 -0
  102. package/src/module/xapi/ADL.js +241 -60
  103. package/src/module/xapi/Crypto/Hasher.js +8 -8
  104. package/src/module/xapi/Crypto/WordArray.js +6 -6
  105. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +4 -4
  106. package/src/module/xapi/Crypto/algorithms/C_algo.js +14 -18
  107. package/src/module/xapi/Crypto/algorithms/HMAC.js +1 -1
  108. package/src/module/xapi/Crypto/algorithms/SHA1.js +1 -1
  109. package/src/module/xapi/Crypto/encoders/Base.js +7 -7
  110. package/src/module/xapi/Crypto/encoders/Base64.js +3 -3
  111. package/src/module/xapi/Crypto/encoders/Hex.js +2 -2
  112. package/src/module/xapi/Crypto/encoders/Latin1.js +3 -3
  113. package/src/module/xapi/Crypto/encoders/Utf8.js +3 -3
  114. package/src/module/xapi/Statement/index.js +3 -3
  115. package/src/module/xapi/launch.js +10 -10
  116. package/src/module/xapi/utils.js +17 -17
  117. package/src/module/xapi/wrapper.js +219 -214
  118. package/src/module/xapi/xapiStatement.js +29 -29
  119. package/src/plugins/analytics.js +34 -0
  120. package/src/plugins/bus.js +7 -2
  121. package/src/plugins/gsap.js +5 -7
  122. package/src/plugins/helper.js +97 -34
  123. package/src/plugins/i18n.js +13 -18
  124. package/src/plugins/idb.js +45 -30
  125. package/src/plugins/save.js +1 -1
  126. package/src/plugins/scorm.js +15 -15
  127. package/src/plugins/xapi.js +2 -2
  128. package/src/public/index.html +22 -10
  129. package/src/router/index.js +29 -13
  130. package/src/router/routes.js +29 -54
  131. package/src/shared/generalfuncs.js +186 -30
  132. package/src/shared/validators.js +809 -40
  133. package/vitest.config.js +19 -0
  134. package/.eslintignore +0 -29
  135. package/.eslintrc.js +0 -86
  136. package/.prettierrc.js +0 -5
  137. package/babel.config.js +0 -3
  138. package/src/components/AppBaseDragChoice.vue +0 -91
  139. package/src/components/AppBaseDropZone.vue +0 -112
  140. package/src/components/AppCompBif.vue +0 -120
  141. package/src/components/AppCompDragAndDrop.vue +0 -339
  142. package/src/components/AppCompInputAssociation.vue +0 -332
  143. package/src/components/AppCompInputCheckBox.vue +0 -227
  144. package/src/components/AppCompInputDropdown.vue +0 -184
  145. package/src/components/AppCompInputRadio.vue +0 -169
  146. package/src/components/AppCompInputTextBox.vue +0 -91
  147. package/src/components/AppCompInputTextTable.vue +0 -155
  148. package/src/components/AppCompInputTextToFillDropdown.vue +0 -255
  149. package/src/components/AppCompInputTextToFillText.vue +0 -164
  150. package/src/components/AppCompMediaPlayer.vue +0 -397
  151. package/src/components/AppCompPlayBar.vue +0 -1319
  152. package/src/components/AppCompPopUp.vue +0 -522
  153. package/src/components/AppCompPopover.vue +0 -27
  154. package/src/components/AppCompQuiz.vue +0 -2989
  155. package/src/components/AppCompSVG.vue +0 -309
  156. package/src/mixins/$pageMixins.js +0 -459
  157. package/src/mixins/$quizMixins.js +0 -456
  158. package/src/mixins/timerMixin.js +0 -156
  159. package/src/module/store.js +0 -895
  160. package/src/plugins/timeManager.js +0 -77
  161. package/src/routes_bckp.js +0 -313
  162. package/src/routes_static.js +0 -344
  163. package/vue.config.js +0 -83
@@ -41,7 +41,7 @@ export default class ADL {
41
41
  let res = null
42
42
  const withResult =
43
43
  statement.verb.id.includes('answered') ||
44
- statement.verb.id.includes('exited') ||
44
+ statement.verb.id.includes('suspended') ||
45
45
  statement.verb.id.includes('completed')
46
46
 
47
47
  if (statement.result && !withResult) {
@@ -56,11 +56,45 @@ export default class ADL {
56
56
 
57
57
  if (withFetch) this.XAPIWrapper.sendStatementWithFetch(statement)
58
58
  else {
59
- this.XAPIWrapper.sendStatement(statement, function(response) {
59
+ this.XAPIWrapper.sendStatement(statement, function (response) {
60
60
  if (cb) cb()
61
61
  res = response
62
62
  })
63
+ return res
64
+ }
65
+ }
66
+
67
+ /*
68
+ * Helper function to Dispatch statement to the LRS
69
+ * @params: Statement {Object}:xapi Statement
70
+ */
71
+ _sendStatements(statements, cb, withFetch = false) {
72
+ //remove the statement Result if it not answer action.
73
+ let res = null
74
+ statements.forEach((statement) => {
75
+ const withResult =
76
+ statement.verb.id.includes('answered') ||
77
+ statement.verb.id.includes('played') ||
78
+ statement.verb.id.includes('suspended') ||
79
+ statement.verb.id.includes('completed')
80
+
81
+ if (statement.result && !withResult) {
82
+ delete statement.result
83
+ }
84
+
85
+ //Clear existing id of the statement if any to allow xapi to generate new ID for the Statement.
86
+ if (statement.id) statement.id = ''
87
+ })
88
+
89
+ // Dispatch the statement to the LRS
90
+ if (!this.XAPIWrapper) return
63
91
 
92
+ if (withFetch) this.XAPIWrapper.sendStatementsWithFetch(statements)
93
+ else {
94
+ this.XAPIWrapper.sendStatements(statements, function (response) {
95
+ if (cb) cb()
96
+ res = response
97
+ })
64
98
  return res
65
99
  }
66
100
  }
@@ -102,58 +136,66 @@ export default class ADL {
102
136
  *
103
137
  * @Params {String} email: user email
104
138
  * @Params {String} activityId: the IRI string of the activity
105
- * @Params {String} verb: the verb to search by completed | exited
139
+ * @Params {String} verb: the verb to search by completed | terminated
106
140
  */
107
- _getProgress(email, activityId, verb) {
141
+
142
+ async _getProgress(email, activityId, verb) {
108
143
  let params
109
- let vb
110
- const validVerbs = ['completed', 'exited']
144
+ const validVerbs = [
145
+ 'progressed',
146
+ 'completed',
147
+ 'suspended',
148
+ 'terminated',
149
+ 'exited'
150
+ ]
111
151
  if (this.XAPIWrapper) params = this.XAPIWrapper.searchParams()
112
152
 
113
- verb && validVerbs.includes(verb) ? (vb = verb) : (vb = 'exited')
153
+ let vb = verb && validVerbs.includes(verb) ? verb : 'terminated'
114
154
 
115
155
  params['verb'] = this.verbs[vb].id // completed state
116
156
  params['activity'] = activityId // this current activity define by this id
117
157
  params['agent'] = `{"mbox": "mailto:${email}"}` // the user identify by this email
118
- params['limit'] = 500 //limit of record to return by the LRS
158
+ params['limit'] = 200 //limit of record to return by the LRS
119
159
  params['ascending'] = true //ordered by the oldest statement recorded
120
160
 
121
161
  let date = new Date()
122
162
  let dd = new Date(date.setDate(date.getDate() + 1)).toISOString() //Date is set to next day(tomorrow) for Lrs to take in account statement registered today.
123
-
124
163
  params['until'] = dd
125
164
 
126
- let completedStmts = this.XAPIWrapper.getStatements(params)
127
- let userData //placeholder for user data
165
+ try {
166
+ let userData //placeholder for user data
167
+ let completedStmts = await this.XAPIWrapper.getStatements(params)
128
168
 
129
- if (
130
- completedStmts &&
131
- completedStmts.statements &&
132
- completedStmts.statements.length
133
- ) {
134
- let length = completedStmts.statements.length
135
- let lastRecord = completedStmts.statements[length - 1] // get last recorded statement
136
- // Verify that the extensions value of the statement as elements
137
169
  if (
138
- lastRecord.object.definition.extensions &&
139
- Object.keys(lastRecord.object.definition.extensions).length
170
+ completedStmts &&
171
+ completedStmts.statements &&
172
+ completedStmts.statements.length
140
173
  ) {
141
- const allExtensionsKeys = Object.keys(
142
- lastRecord.object.definition.extensions
143
- )
144
-
145
- //Search for the user-data entry in the extensions
146
-
147
- const userDataExtension = allExtensionsKeys.filter((extension) =>
148
- extension.includes('user-data')
149
- )
150
- userData = lastRecord.object.definition.extensions[userDataExtension[0]]
174
+ let lastRecord = completedStmts.statements.toReversed()[0] // get last recorded statement
175
+
176
+ // Verify that the extensions value of the statement as elements
177
+ if (
178
+ lastRecord.object.definition.extensions &&
179
+ Object.keys(lastRecord.object.definition.extensions).length
180
+ ) {
181
+ const allExtensionsKeys = Object.keys(
182
+ lastRecord.object.definition.extensions
183
+ )
184
+
185
+ //Search for the user-data entry in the extensions
186
+ const userDataExtension = allExtensionsKeys.filter((extension) =>
187
+ extension.includes('user-data')
188
+ )
189
+ userData =
190
+ lastRecord.object.definition.extensions[userDataExtension[0]]
191
+ }
192
+ } else {
193
+ userData = {}
151
194
  }
152
195
  return userData
153
- } else {
154
- userData = {}
196
+ } catch (err) {
197
+ console.log(err)
155
198
  }
156
- return userData
157
199
  }
158
200
 
159
201
  /*@Description: Helper to The Lesson Status (result) -
@@ -161,24 +203,24 @@ export default class ADL {
161
203
  * @Params {String} email: user email
162
204
  * @Params {String} activityId: the IRI string of the activity
163
205
  */
164
- _getLessonStatus(email, activityId) {
206
+ async _getLessonStatus(email, activityId, verb) {
165
207
  let params
208
+ const validVerbs = ['completed', 'suspended']
166
209
  if (this.XAPIWrapper) params = this.XAPIWrapper.searchParams()
167
-
168
- params['verb'] = this.verbs.completed.id // completed state
210
+ let vb = verb && validVerbs.includes(verb) ? verb : 'suspended'
211
+ params['verb'] = this.verbs[vb].id // completed state
169
212
  params['activity'] = activityId // this current activity define by this id
170
213
  params['agent'] = `{"mbox": "mailto:${email}"}` // the user identify by this email
171
214
  params['ascending'] = true //ordered by the oldest statement recorded
172
215
 
173
- let completedStmts = this.XAPIWrapper.getStatements(params)
216
+ let completedStmts = await this.XAPIWrapper.getStatements(params)
174
217
  let status //placeholder for user data
175
218
  if (
176
219
  completedStmts &&
177
220
  completedStmts.statements &&
178
221
  completedStmts.statements.length
179
222
  ) {
180
- let length = completedStmts.statements.length
181
- let lastRecord = completedStmts.statements[length - 1] // get last recorded statement
223
+ let lastRecord = completedStmts.statements.toReversed()[0] // get last recorded statement
182
224
 
183
225
  // Verify that result exist
184
226
  if (lastRecord.result) status = lastRecord.result
@@ -195,32 +237,32 @@ export default class ADL {
195
237
  * @Params {String} activityId: the IRI string of the activity
196
238
  */
197
239
 
198
- _getLessonPosition(email, activityId) {
240
+ async _getLessonPosition(email, activityId) {
199
241
  let params
200
242
  let savedPoint = []
201
243
  if (this.XAPIWrapper) params = this.XAPIWrapper.searchParams()
202
244
 
203
- params['verb'] = this.verbs.progressed.id // completed state
245
+ params['verb'] = this.verbs.terminated.id // completed state
204
246
  params['activity'] = activityId // this current activity define by this id
205
247
  params['agent'] = `{"mbox": "mailto:${email}"}` // the user identify by this email
206
248
  params['ascending'] = true //ordered by the oldest statement recorded
207
- params['limit'] = 500 //limit of record to return by the LRS
249
+ params['limit'] = 200 //limit of record to return by the LRS
208
250
 
209
251
  let date = new Date()
210
252
  let dd = new Date(date.setDate(date.getDate() + 1)).toISOString() //Date is set to next day(tomorrow) for Lrs to take in account statement registered today.
211
253
 
212
254
  params['until'] = dd
213
255
 
214
- let progressedStmts = this.XAPIWrapper.getStatements(params)
256
+ let progressedStmts = await this.XAPIWrapper.getStatements(params)
215
257
 
216
258
  if (
217
259
  progressedStmts &&
218
260
  progressedStmts.statements &&
219
261
  progressedStmts.statements.length
220
262
  ) {
221
- let length = progressedStmts.statements.length
222
- let lastRecord = progressedStmts.statements[length - 1] // get last recorded statement
263
+ let lastRecord = progressedStmts.statements.toReversed()[0] // get last recorded statement
223
264
  // Verify that the extensions value of the statement has elements
265
+
224
266
  if (
225
267
  lastRecord.object.definition.extensions &&
226
268
  Object.keys(lastRecord.object.definition.extensions).length
@@ -228,6 +270,7 @@ export default class ADL {
228
270
  const allExtensionsKeys = Object.keys(
229
271
  lastRecord.object.definition.extensions
230
272
  )
273
+
231
274
  //Search for the user-data entry in the extensions
232
275
  savedPoint = allExtensionsKeys.map((extension) => {
233
276
  if (extension.includes('ending-point'))
@@ -235,7 +278,8 @@ export default class ADL {
235
278
  })
236
279
  }
237
280
  }
238
- return savedPoint
281
+
282
+ return savedPoint && savedPoint.length > 0 ? savedPoint[0] : ''
239
283
  }
240
284
 
241
285
  /* @description: Helper to get the Preferred Settings of the user
@@ -244,7 +288,7 @@ export default class ADL {
244
288
  * @Params {String} activityId: the IRI string of the activity
245
289
  */
246
290
 
247
- _getPreferredSettings(email, activityId) {
291
+ async _getPreferredSettings(email, activityId) {
248
292
  let params
249
293
  let preferredSettings = []
250
294
  if (this.XAPIWrapper) params = this.XAPIWrapper.searchParams()
@@ -253,22 +297,21 @@ export default class ADL {
253
297
  params['activity'] = activityId // this current activity define by this id
254
298
  params['agent'] = `{"mbox": "mailto:${email}"}` // the user identify by this email
255
299
  params['ascending'] = true //ordered by the oldest statement recorded
256
- params['limit'] = 500 //limit of record to return by the LRS
300
+ params['limit'] = 200 //limit of record to return by the LRS
257
301
 
258
302
  let date = new Date()
259
303
  let dd = new Date(date.setDate(date.getDate() + 1)).toISOString() //Date is set to next day(tomorrow) for Lrs to take in account statement registered today.
260
304
 
261
305
  params['until'] = dd
262
306
 
263
- let preferredStmts = this.XAPIWrapper.getStatements(params)
307
+ let preferredStmts = await this.XAPIWrapper.getStatements(params)
264
308
 
265
309
  if (
266
310
  preferredStmts &&
267
311
  preferredStmts.statements &&
268
312
  preferredStmts.statements.length
269
313
  ) {
270
- let length = preferredStmts.statements.length
271
- let lastRecord = preferredStmts.statements[length - 1] // get last recorded statement
314
+ let lastRecord = preferredStmts.statements.toReversed()[0] // get last recorded statement
272
315
 
273
316
  // Verify that the extensions value of the statement has elements
274
317
  if (
@@ -278,6 +321,7 @@ export default class ADL {
278
321
  const allExtensionsKeys = Object.keys(
279
322
  lastRecord.object.definition.extensions
280
323
  )
324
+
281
325
  //Search for the user-data entry in the extensions
282
326
  preferredSettings = allExtensionsKeys.map((extension) => {
283
327
  if (extension.includes('application-settings'))
@@ -285,7 +329,7 @@ export default class ADL {
285
329
  })
286
330
  }
287
331
  }
288
- return preferredSettings
332
+ return preferredSettings[0] ? preferredSettings[0] : {}
289
333
  }
290
334
 
291
335
  /* @description: Helper to get the Playbar values of the user
@@ -293,7 +337,7 @@ export default class ADL {
293
337
  * @Params {String} activityId: the IRI string of the activity
294
338
  */
295
339
 
296
- _getPlaybarValues(email, activityId) {
340
+ async _getPlaybarValues(email, activityId) {
297
341
  let params
298
342
  let playbarValues = []
299
343
  if (this.XAPIWrapper) params = this.XAPIWrapper.searchParams()
@@ -302,23 +346,21 @@ export default class ADL {
302
346
  params['activity'] = activityId // this current activity define by this id
303
347
  params['agent'] = `{"mbox": "mailto:${email}"}` // the user identify by this email
304
348
  params['ascending'] = true //ordered by the oldest statement recorded
305
- params['limit'] = 500 //limit of record to return by the LRS
349
+ params['limit'] = 200 //limit of record to return by the LRS
306
350
 
307
351
  let date = new Date()
308
352
  let dd = new Date(date.setDate(date.getDate() + 1)).toISOString() //Date is set to next day(tomorrow) for Lrs to take in account statement registered today.
309
353
 
310
354
  params['until'] = dd
311
355
 
312
- let playedStmts = this.XAPIWrapper.getStatements(params)
356
+ let playedStmts = await this.XAPIWrapper.getStatements(params)
313
357
 
314
358
  if (
315
359
  playedStmts &&
316
360
  playedStmts.statements &&
317
361
  playedStmts.statements.length
318
362
  ) {
319
- let length = playedStmts.statements.length
320
- let lastRecord = playedStmts.statements[length - 1] // get last recorded statement
321
-
363
+ let lastRecord = playedStmts.statements.toReversed()[0] // get last recorded statement
322
364
  // Verify that the extensions value of the statement has elements
323
365
  if (
324
366
  lastRecord.object.definition.extensions &&
@@ -334,6 +376,145 @@ export default class ADL {
334
376
  })
335
377
  }
336
378
  }
337
- return playbarValues
379
+ return playbarValues[0] ? playbarValues[0] : {}
380
+ }
381
+ /**
382
+ * Method to get a multiple concurent requests using promiseAll to the server
383
+ * and return all data at once.
384
+ * the following request are made to the server:
385
+ * get application-settings: saved value for the user preferred settings
386
+ * get user-data: saved values for user progression
387
+ * get playbar-value : saved value for the medias play-bar
388
+ * get lesson-status : saved value for the lession status
389
+ *
390
+ * @param {Array} searchParams - Array of Object with key value representing each search paremeter.
391
+ * a parameter object definition is expected to have the following signature:
392
+ * {
393
+ * email{String} agent email,
394
+ * verb {String} verb for the request,
395
+ * activityId {String} - activity id ,
396
+ * }
397
+ * @example here is an exemple of the search param:
398
+ * {email: 'wizardy0@mymailbox.com', verb: 'completed',activityId:'"http://localhost:5173/vuetify_p4/v3"' }
399
+ * @return {object} data with a collection of all the reponses
400
+ * from the promiseAll and the status of last request
401
+ */
402
+ async _getBulkData(searchParams) {
403
+ const validVerbs = [
404
+ 'progressed',
405
+ 'completed',
406
+ 'suspended',
407
+ 'terminated',
408
+ 'preferred',
409
+ 'played',
410
+ 'exited'
411
+ ]
412
+
413
+ const paramList = []
414
+ // account statement registered today.
415
+ let date = new Date()
416
+ let dd = new Date(date.setDate(date.getDate() + 1)).toISOString() //Date is set to next day(tomorrow) for Lrs to take in
417
+
418
+ for (let param of searchParams) {
419
+ let { email, verb, activityId } = param
420
+ let vb = verb && validVerbs.includes(verb) ? verb : 'terminated'
421
+ const params = {}
422
+
423
+ params['verb'] = this.verbs[vb].id // completed state
424
+ params['activity'] = activityId // this current activity define by this id
425
+ params['agent'] = `{"mbox": "mailto:${email}"}` // the user identify by this email
426
+ params['ascending'] = true //ordered by the oldest statement recorded
427
+ params['limit'] = 250 //limit of record to return by the LRS
428
+
429
+ params['until'] = dd
430
+ paramList.push(params)
431
+ }
432
+ const { response } = await this.XAPIWrapper.getStatements(paramList)
433
+
434
+ let userData = {},
435
+ playbarValues = {},
436
+ preferredSettings = {},
437
+ lessonStatus = {},
438
+ savedPoint = ''
439
+
440
+ if (response && response.length > 0) {
441
+ for (const res of response) {
442
+ const { statements } = await res.json()
443
+ if (!statements || statements.length == 0) continue
444
+
445
+ let lastRecord = statements.toReversed()[0] // get last recorded statement
446
+ // Verify that the extensions value of the statement has elements
447
+
448
+ //Handeling Lession comppletion status
449
+ if (lastRecord.verb.id.includes('completed')) {
450
+ lessonStatus = lastRecord.result ? lastRecord.result : {}
451
+ }
452
+
453
+ if (
454
+ lastRecord.object.definition.extensions &&
455
+ Object.keys(lastRecord.object.definition.extensions).length
456
+ ) {
457
+ const allExtensionsKeys = Object.keys(
458
+ lastRecord.object.definition.extensions
459
+ )
460
+
461
+ //Search for the user-data entry in the extensions
462
+ allExtensionsKeys.forEach((extension) => {
463
+ switch (true) {
464
+ case extension.includes('user-data'): {
465
+ //Search for the user-data entry in the extensions
466
+ const userDataExtension = allExtensionsKeys.filter(
467
+ (extension) => extension.includes('user-data')
468
+ )
469
+ userData =
470
+ lastRecord.object.definition.extensions[userDataExtension[0]]
471
+
472
+ break
473
+ }
474
+ case extension.includes('ending-point'): {
475
+ const userDataExtension = allExtensionsKeys.filter(
476
+ (extension) => extension.includes('ending-point')
477
+ )
478
+ savedPoint =
479
+ lastRecord.object.definition.extensions[userDataExtension[0]]
480
+
481
+ break
482
+ }
483
+ case extension.includes('application-settings'): {
484
+ const userDataExtension = allExtensionsKeys.filter(
485
+ (extension) => extension.includes('application-settings')
486
+ )
487
+
488
+ const settingsData =
489
+ lastRecord.object.definition.extensions[userDataExtension[0]]
490
+
491
+ preferredSettings = settingsData ? settingsData : {}
492
+
493
+ break
494
+ }
495
+ case extension.includes('playbar-values'): {
496
+ const userDataExtension = allExtensionsKeys.filter(
497
+ (extension) => extension.includes('playbar-values')
498
+ )
499
+
500
+ const playbarData =
501
+ lastRecord.object.definition.extensions[userDataExtension[0]]
502
+ playbarValues = playbarData ? playbarData : {}
503
+
504
+ break
505
+ }
506
+ }
507
+ })
508
+ }
509
+ }
510
+ }
511
+
512
+ return {
513
+ userData,
514
+ savedPoint,
515
+ preferredSettings,
516
+ playbarValues,
517
+ lessonStatus
518
+ }
338
519
  }
339
520
  }
@@ -21,7 +21,7 @@ export const Hasher = BufferedBlockAlgorithm.extend({
21
21
  *
22
22
  * var hasher = CryptoJS.algo.SHA256.create();
23
23
  */
24
- init: function(cfg) {
24
+ init: function (cfg) {
25
25
  // Apply config defaults
26
26
  this.cfg = this.cfg.extend(cfg)
27
27
 
@@ -36,7 +36,7 @@ export const Hasher = BufferedBlockAlgorithm.extend({
36
36
  *
37
37
  * hasher.reset();
38
38
  */
39
- reset: function() {
39
+ reset: function () {
40
40
  // Reset data buffer
41
41
  BufferedBlockAlgorithm.reset.call(this)
42
42
 
@@ -56,7 +56,7 @@ export const Hasher = BufferedBlockAlgorithm.extend({
56
56
  * hasher.update('message');
57
57
  * hasher.update(wordArray);
58
58
  */
59
- update: function(messageUpdate) {
59
+ update: function (messageUpdate) {
60
60
  // Append
61
61
  this._append(messageUpdate)
62
62
 
@@ -81,7 +81,7 @@ export const Hasher = BufferedBlockAlgorithm.extend({
81
81
  * var hash = hasher.finalize('message');
82
82
  * var hash = hasher.finalize(wordArray);
83
83
  */
84
- finalize: function(messageUpdate) {
84
+ finalize: function (messageUpdate) {
85
85
  // Final message update
86
86
  if (messageUpdate) {
87
87
  this._append(messageUpdate)
@@ -108,8 +108,8 @@ export const Hasher = BufferedBlockAlgorithm.extend({
108
108
  *
109
109
  * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
110
110
  */
111
- _createHelper: function(hasher) {
112
- return function(message, cfg) {
111
+ _createHelper: function (hasher) {
112
+ return function (message, cfg) {
113
113
  return new hasher.init(cfg).finalize(message)
114
114
  }
115
115
  },
@@ -127,8 +127,8 @@ export const Hasher = BufferedBlockAlgorithm.extend({
127
127
  *
128
128
  * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
129
129
  */
130
- _createHmacHelper: function(hasher) {
131
- return function(message, key) {
130
+ _createHmacHelper: function (hasher) {
131
+ return function (message, key) {
132
132
  return new C_algo().HMAC.init(hasher, key).finalize(message)
133
133
  }
134
134
  }
@@ -19,7 +19,7 @@ export const WordArray = Base.extend({
19
19
  * let wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
20
20
  * let wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
21
21
  */
22
- init: function(words, sigBytes) {
22
+ init: function (words, sigBytes) {
23
23
  words = this.words = words || []
24
24
 
25
25
  if (sigBytes != undefined) {
@@ -42,7 +42,7 @@ export const WordArray = Base.extend({
42
42
  * let string = wordArray.toString();
43
43
  * let string = wordArray.toString(CryptoJS.enc.Utf8);
44
44
  */
45
- toString: function(encoder) {
45
+ toString: function (encoder) {
46
46
  return (encoder || Hex).stringify(this)
47
47
  },
48
48
 
@@ -57,7 +57,7 @@ export const WordArray = Base.extend({
57
57
  *
58
58
  * wordArray1.concat(wordArray2);
59
59
  */
60
- concat: function(wordArray) {
60
+ concat: function (wordArray) {
61
61
  // Shortcuts
62
62
  let thisWords = this.words
63
63
  let thatWords = wordArray.words
@@ -97,7 +97,7 @@ export const WordArray = Base.extend({
97
97
  *
98
98
  * wordArray.clamp();
99
99
  */
100
- clamp: function() {
100
+ clamp: function () {
101
101
  // Shortcuts
102
102
  let words = this.words
103
103
  let sigBytes = this.sigBytes
@@ -116,7 +116,7 @@ export const WordArray = Base.extend({
116
116
  *
117
117
  * let clone = wordArray.clone();
118
118
  */
119
- clone: function() {
119
+ clone: function () {
120
120
  let clone = Base.clone.call(this)
121
121
  clone.words = this.words.slice(0)
122
122
 
@@ -136,7 +136,7 @@ export const WordArray = Base.extend({
136
136
  *
137
137
  * let wordArray = CryptoJS.lib.WordArray.random(16);
138
138
  */
139
- random: function(nBytes) {
139
+ random: function (nBytes) {
140
140
  let words = []
141
141
  for (let i = 0; i < nBytes; i += 4) {
142
142
  words.push((Math.random() * 0x100000000) | 0)
@@ -12,7 +12,7 @@ export const BufferedBlockAlgorithm = Base.extend({
12
12
  * @example
13
13
  * bufferedBlockAlgorithm.reset();
14
14
  */
15
- reset: function() {
15
+ reset: function () {
16
16
  // Initial values
17
17
  this._data = new WordArray.init()
18
18
  this._nDataBytes = 0
@@ -25,7 +25,7 @@ export const BufferedBlockAlgorithm = Base.extend({
25
25
  * bufferedBlockAlgorithm._append('data');
26
26
  * bufferedBlockAlgorithm._append(wordArray);
27
27
  */
28
- _append: function(data) {
28
+ _append: function (data) {
29
29
  // Convert string to WordArray, else assume WordArray already
30
30
  if (typeof data == 'string') {
31
31
  data = Utf8.parse(data)
@@ -46,7 +46,7 @@ export const BufferedBlockAlgorithm = Base.extend({
46
46
  * var processedData = bufferedBlockAlgorithm._process();
47
47
  * var processedData = bufferedBlockAlgorithm._process(!!'flush');
48
48
  */
49
- _process: function(doFlush) {
49
+ _process: function (doFlush) {
50
50
  // Shortcuts
51
51
  var data = this._data
52
52
  var dataWords = data.words
@@ -93,7 +93,7 @@ export const BufferedBlockAlgorithm = Base.extend({
93
93
  * @example
94
94
  * var clone = bufferedBlockAlgorithm.clone();
95
95
  */
96
- clone: function() {
96
+ clone: function () {
97
97
  var clone = Base.clone.call(this)
98
98
  clone._data = this._data.clone()
99
99
  return clone