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

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 (78) hide show
  1. package/{.eslintrc.js → .eslintrc.cjs} +13 -18
  2. package/bk.scss +117 -0
  3. package/package.json +23 -39
  4. package/src/$locales/en.json +30 -16
  5. package/src/$locales/fr.json +29 -16
  6. package/src/components/AppBase.vue +740 -305
  7. package/src/components/AppBaseButton.vue +33 -5
  8. package/src/components/AppBaseErrorDisplay.vue +43 -35
  9. package/src/components/AppBaseModule.vue +447 -623
  10. package/src/components/AppBasePage.vue +37 -25
  11. package/src/components/AppCompAudio.vue +266 -0
  12. package/src/components/AppCompBranchButtons.vue +52 -63
  13. package/src/components/AppCompButtonProgress.vue +1 -16
  14. package/src/components/AppCompCarousel.vue +43 -39
  15. package/src/components/AppCompInputCheckBox.vue +9 -3
  16. package/src/components/AppCompInputDropdown.vue +2 -4
  17. package/src/components/AppCompInputRadio.vue +8 -15
  18. package/src/components/AppCompInputTextTable.vue +15 -12
  19. package/src/components/AppCompInputTextToFillDropdown.vue +16 -14
  20. package/src/components/AppCompInputTextToFillText.vue +2 -2
  21. package/src/components/AppCompJauge.vue +13 -1
  22. package/src/components/AppCompMenu.vue +203 -10
  23. package/src/components/AppCompMenuItem.vue +20 -3
  24. package/src/components/AppCompNavigation.vue +351 -355
  25. package/src/components/AppCompNoteCall.vue +62 -47
  26. package/src/components/AppCompNoteCredit.vue +182 -79
  27. package/src/components/AppCompPlayBar.vue +975 -1023
  28. package/src/components/AppCompPlayBarProgress.vue +73 -0
  29. package/src/components/AppCompPopUp.vue +175 -114
  30. package/src/components/AppCompQuiz.vue +67 -81
  31. package/src/components/AppCompQuizRecall.vue +32 -5
  32. package/src/components/AppCompSVG.vue +66 -40
  33. package/src/components/AppCompSettingsMenu.vue +6 -8
  34. package/src/components/AppCompTableOfContent.vue +166 -45
  35. package/src/components/AppCompVideoPlayer.vue +154 -110
  36. package/src/components/BaseModule.vue +21 -17
  37. package/src/main.js +124 -88
  38. package/src/mixins/$mediaMixins.js +827 -0
  39. package/src/mixins/$pageMixins.js +65 -109
  40. package/src/mixins/$quizMixins.js +12 -26
  41. package/src/mixins/timerMixin.js +8 -9
  42. package/src/module/store.js +187 -68
  43. package/src/module/xapi/ADL.js +90 -53
  44. package/src/module/xapi/Crypto/Hasher.js +8 -8
  45. package/src/module/xapi/Crypto/WordArray.js +6 -6
  46. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +4 -4
  47. package/src/module/xapi/Crypto/algorithms/C_algo.js +14 -18
  48. package/src/module/xapi/Crypto/algorithms/HMAC.js +1 -1
  49. package/src/module/xapi/Crypto/algorithms/SHA1.js +1 -1
  50. package/src/module/xapi/Crypto/encoders/Base.js +7 -7
  51. package/src/module/xapi/Crypto/encoders/Base64.js +3 -3
  52. package/src/module/xapi/Crypto/encoders/Hex.js +2 -2
  53. package/src/module/xapi/Crypto/encoders/Latin1.js +3 -3
  54. package/src/module/xapi/Crypto/encoders/Utf8.js +3 -3
  55. package/src/module/xapi/Statement/index.js +1 -1
  56. package/src/module/xapi/launch.js +10 -10
  57. package/src/module/xapi/utils.js +17 -17
  58. package/src/module/xapi/wrapper.js +123 -50
  59. package/src/module/xapi/xapiStatement.js +29 -29
  60. package/src/plugins/helper.js +8 -9
  61. package/src/plugins/i18n.js +23 -10
  62. package/src/plugins/scorm.js +14 -14
  63. package/src/router/index.js +3 -4
  64. package/src/router/routes.js +10 -30
  65. package/src/shared/generalfuncs.js +31 -24
  66. package/src/shared/validators.js +730 -20
  67. package/.prettierrc.js +0 -5
  68. package/babel.config.js +0 -3
  69. package/src/components/AppBaseDragChoice.vue +0 -91
  70. package/src/components/AppBaseDropZone.vue +0 -112
  71. package/src/components/AppCompBif.vue +0 -120
  72. package/src/components/AppCompDragAndDrop.vue +0 -339
  73. package/src/components/AppCompInputAssociation.vue +0 -332
  74. package/src/components/AppCompMediaPlayer.vue +0 -397
  75. package/src/plugins/timeManager.js +0 -77
  76. package/src/routes_bckp.js +0 -313
  77. package/src/routes_static.js +0 -344
  78. package/vue.config.js +0 -83
@@ -8,21 +8,7 @@ import { mapGetters } from 'vuex'
8
8
  const $extendsPage = {
9
9
  // lazy laoding of components
10
10
  components: {
11
- AppCompMediaPlayer: () =>
12
- import(
13
- /* webpackChunkName: "MediaPlayerCompnent" */
14
- '../components/AppCompMediaPlayer.vue'
15
- ),
16
- AppCompMenuItem: () =>
17
- import(
18
- /* webpackChunkName: "MenuItemCompenent" */
19
- '../components/AppCompMenuItem.vue'
20
- ),
21
- AppCompQuiz: () =>
22
- import(
23
- /* webpackChunkName: "QuizComponent" */
24
- '../components/AppCompQuiz.vue'
25
- )
11
+ AppCompQuiz: () => import('../components/AppCompQuiz.vue')
26
12
  },
27
13
 
28
14
  data: () => {
@@ -33,8 +19,8 @@ const $extendsPage = {
33
19
  anchorInfo: null,
34
20
  drModeActive: null,
35
21
  error: null,
36
- credits: null,
37
- notes: null
22
+ notes: null,
23
+ credits: null
38
24
  }
39
25
  },
40
26
  watch: {
@@ -90,9 +76,8 @@ const $extendsPage = {
90
76
  }
91
77
 
92
78
  // give notes and credit information must be in tick because of life cycle
93
- this.$nextTick(function() {
94
- this.$bus.$emit('credit-note', data)
95
- })
79
+ this.$store.dispatch('updateCurrentnoteCredit', data)
80
+
96
81
  if (this.type == 'pg_branch') return //do not proceed to add listner when branch page
97
82
 
98
83
  window.addEventListener('scroll', this.onFirstScroll, { once: true }) //listener is removed when event fired
@@ -101,12 +86,17 @@ const $extendsPage = {
101
86
  created() {
102
87
  if (this.type == 'pg_branch')
103
88
  this.$bus.$on('branch-page-viewed', this.completePageBranching)
89
+
104
90
  if (this.isBranchingPage)
105
91
  this.$store.commit('UPDATE_CURRENT_BRANCHING', this.$data)
106
- },
107
92
 
93
+ this.$bus.$on('media-viewed', this.setMediaViewed)
94
+ this.$bus.$on('manage-media-players', this.managePlayingMedia)
95
+ },
108
96
  beforeDestroy() {
109
97
  this.$bus.$off('branch-page-viewed', this.completePageBranching)
98
+ this.$bus.$off('media-viewed', this.setMediaViewed)
99
+ this.$bus.$off('manage-media-players', this.managePlayingMedia)
110
100
  window.removeEventListener('scroll', this.onFirstScroll, { once: true }) //in case user did not scroll
111
101
  window.removeEventListener('scroll', this.handleScroll)
112
102
  },
@@ -164,7 +154,6 @@ const $extendsPage = {
164
154
  this.state = 'completed'
165
155
 
166
156
  this.$set(this.userInteraction, 'state', this.state)
167
- this.sendCompletionToServer()
168
157
  },
169
158
 
170
159
  /**
@@ -193,90 +182,8 @@ const $extendsPage = {
193
182
  'state',
194
183
  currentBranching.state
195
184
  )
196
-
197
- this.sendCompletionToServer()
198
185
  },
199
186
 
200
- /**
201
- * @description - Send xapi statement to indicate the completion of an activity
202
- */
203
- sendCompletionToServer() {
204
- /*
205
- * Send xapi statement to indicate the completion of an activity
206
- * Send completion of activity when all pages in Activity are completed and the page is last page of activity
207
- * Send completion statement for lesson if this is the last page of the last activity in lesson
208
- */
209
-
210
- if (this.getModuleInfo.packageType !== 'xapi') return
211
- if (!this.getConnectionInfo) return
212
- if (!this.getConnectionInfo.remote || !this.getConnectionInfo.actor)
213
- return
214
-
215
- //Get the current acitivty reference from store
216
- const currentActivity = this.getAllActivities.list.get(
217
- this.getCurrentPage.activityRef
218
- )
219
-
220
- const activity_id = `${this.getConnectionInfo.activity_id}/${this.getCurrentPage.activityRef}`
221
-
222
- const record = this.$xapi._getProgress(
223
- this.getConnectionInfo.actor.mbox.replace('mailto:', ''),
224
- activity_id,
225
- 'completed'
226
- )
227
-
228
- //Send a completion statement for the current activity
229
- //When all pages of the activity are completed and the activity recorded is as completed
230
- if (
231
- this.getAllCompleted[this.getCurrentPage.activityRef] &&
232
- this.getAllCompleted[this.getCurrentPage.activityRef].length ===
233
- currentActivity.size &&
234
- !record[this.getCurrentPage.activityRef]
235
- ) {
236
- let aTitle
237
-
238
- //Custom name of the activity
239
- if (this.getCurrentPage.activityRef === 'A00')
240
- aTitle = this.$t('text.introduction')
241
- else if (this.getCurrentPage.activityRef === 'A99')
242
- aTitle = this.$t('text.conclusion')
243
- aTitle = `${this.$t('text.activity')} ${
244
- this.getCurrentPage.activityRef
245
- }`
246
-
247
- //Custom text for description and definition
248
- let text
249
- this.$i18n.locale == 'fr'
250
- ? (text = `L'${aTitle} de ${this.getModuleInfo.id}`)
251
- : (text = `The ${aTitle} of ${this.getModuleInfo.id}`)
252
-
253
- // Retrive only user data in lessons front its interaction that we want to send to the LRS
254
- const { isFistTime, userSettings, ...data } = this.getUserInteraction
255
-
256
- //Dispatch a send statement event
257
- this.$bus.$emit('send-xapi-statement', {
258
- verb: (() => {
259
- //set the verbe to complete if all the state of the pages of the activity are
260
- if (
261
- this.getAllCompleted[this.getCurrentPage.activityRef] &&
262
- this.getAllCompleted[this.getCurrentPage.activityRef].length ===
263
- currentActivity.size
264
- )
265
- return 'completed'
266
- else return 'suspended'
267
- })(),
268
- id: this.getCurrentPage.activityRef,
269
- definition: text,
270
- description: text,
271
- extension: [
272
- {
273
- id: 'user-data',
274
- content: data
275
- }
276
- ]
277
- })
278
- }
279
- },
280
187
  /**
281
188
  * @description Get the user progress for the current page
282
189
  * @param {string} id (Otpional) - the id of the targeted page
@@ -297,7 +204,6 @@ const $extendsPage = {
297
204
  return {}
298
205
  },
299
206
 
300
- //**** SEE TO DELETE */
301
207
  anchorProgress() {
302
208
  const anchors = document.querySelectorAll('.anchor') // look for anchor
303
209
  const options = {
@@ -355,7 +261,7 @@ const $extendsPage = {
355
261
 
356
262
  this.$bus.$emit('anchor-seen', anchorComplete)
357
263
  } else {
358
- if (process.env.NODE_ENV === 'development')
264
+ if (import.meta.env.DEV)
359
265
  console.warn(
360
266
  `%c WARNING!>>> Anchor handeling: 👉${anchorComplete}👈 doesn't exist. Please provide a valid anchor.`,
361
267
  'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
@@ -424,6 +330,54 @@ const $extendsPage = {
424
330
  },
425
331
  openPopup(data) {
426
332
  this.$bus.$emit('open-popup', data)
333
+ },
334
+ /**
335
+ * @description Send to the bd that the media have been view by the user- Add the id of the media to the
336
+ * userInteraction of the page
337
+ */
338
+ setMediaViewed(mediaID) {
339
+ // Should get the userData to check if current mediaElement has entry
340
+ const { userInteraction } =
341
+ this.getUserInteraction[this.activityRef][this.id]
342
+ let { mediasViewed } = userInteraction
343
+
344
+ // Should create entry for medias viewed in userInteraction if none
345
+ if (!mediasViewed) {
346
+ mediasViewed = []
347
+
348
+ this.$set(userInteraction, 'mediasViewed', mediasViewed)
349
+ }
350
+ //Should add ID in media viewed list if viewed for the 1st time
351
+ if (mediasViewed.includes(mediaID)) return
352
+
353
+ mediasViewed.push(mediaID)
354
+ this.$set(userInteraction, 'mediasViewed', mediasViewed) //Update the userInteraction data of the page
355
+ }, //
356
+
357
+ /**
358
+ * @description - Method to manage the playing state of media element in the page.
359
+ * Only one media should play at a time. When receives signal of new media playing
360
+ * get the reference of the previous media in play from the store and
361
+ * put it in stop state.
362
+ * @param {HTMLElement} media - the actual media that is playing
363
+ */
364
+ managePlayingMedia(media) {
365
+ if (!media) return
366
+ //Should get all the media of the page from store
367
+ const { mElements } = this.getCurrentPage
368
+ if (!mElements || !mElements.length) return
369
+
370
+ // Should stop any media playing
371
+ mElements.forEach((m) => {
372
+ if (m.id == media.id) return
373
+
374
+ const attrKeys = Object.keys(m) //
375
+ //Check if the media is playing to stop it. Playing state is given by the instance of the target play-bar
376
+ if (m[attrKeys[3]].isPlaying) {
377
+ m[attrKeys[1]].pause() // target the HTMLmediaElement to control it state
378
+ m[attrKeys[3]].isPlaying = false //change this isPlaying value of the instance
379
+ }
380
+ })
427
381
  }
428
382
  },
429
383
  computed: {
@@ -435,11 +389,13 @@ const $extendsPage = {
435
389
  'getAllCompleted',
436
390
  'getConnectionInfo',
437
391
  'getAnchorsForActivity',
438
- 'getBifChoice'
392
+ 'getBifChoice',
393
+ 'getDataFromServer'
439
394
  ]),
440
395
 
441
- pageMedia() {
442
- return this.$store.getters.getCurrentPage
396
+ pageMedias() {
397
+ const { mElements, timeline } = this.$store.getters.getCurrentPage
398
+ return { mElements, timeline }
443
399
  },
444
400
  console() {
445
401
  return console
@@ -121,14 +121,13 @@ const $extendsQuiz = {
121
121
  this.quizDragDropValue[inputId]
122
122
  ) {
123
123
  //remove sort if order is important
124
- const solution = [...this.solution[inputId]].sort(function(
125
- a,
126
- b
127
- ) {
128
- return a - b
129
- })
124
+ const solution = [...this.solution[inputId]].sort(
125
+ function (a, b) {
126
+ return a - b
127
+ }
128
+ )
130
129
  const values = [...this.quizDragDropValue[inputId]].sort(
131
- function(a, b) {
130
+ function (a, b) {
132
131
  return a - b
133
132
  }
134
133
  )
@@ -235,14 +234,13 @@ const $extendsQuiz = {
235
234
  this.quizDragDropValue[inputId]
236
235
  ) {
237
236
  //remove sort if order is important
238
- const solution = [...this.solution[inputId]].sort(function(
239
- a,
240
- b
241
- ) {
242
- return a - b
243
- })
237
+ const solution = [...this.solution[inputId]].sort(
238
+ function (a, b) {
239
+ return a - b
240
+ }
241
+ )
244
242
  const values = [...this.quizDragDropValue[inputId]].sort(
245
- function(a, b) {
243
+ function (a, b) {
246
244
  return a - b
247
245
  }
248
246
  )
@@ -438,18 +436,6 @@ const $extendsQuiz = {
438
436
  }
439
437
  }
440
438
  this.$emit('quiz-submit', theAnswer)
441
- },
442
- /**
443
- * @description - Method to get the question
444
- */
445
- getQuizQuestion() {
446
- const el = document.querySelector(`#${this.aBy}`)
447
- if (!el || !el.innerHTML) return
448
- const labelFor =
449
- this.$i18n.locale === 'fr'
450
- ? 'Choix de reponse pour la'
451
- : 'Answers available for the'
452
- return `${labelFor} ${el.innerText}`
453
439
  }
454
440
  }
455
441
  }
@@ -116,18 +116,17 @@ export const timerMixin = {
116
116
  return timeString
117
117
  }
118
118
  },
119
+ beforeDestroy() {
120
+ this.$bus.$off('start-timer', this.startTimer)
121
+ this.$bus.$off('stop-timer', this.stopTimer)
122
+ this.$bus.$off('pause-timer', this.pauseTimer)
123
+ },
119
124
  mounted() {
120
- this.$bus.$on('start-timer', (op) => {
121
- this.startTimer(op)
122
- })
125
+ this.$bus.$on('start-timer', this.startTimer)
123
126
 
124
- this.$bus.$on('stop-timer', (op) => {
125
- this.stopTimer(op)
126
- })
127
+ this.$bus.$on('stop-timer', this.stopTimer)
127
128
 
128
- this.$bus.$on('pause-timer', (op) => {
129
- this.pauseTimer(op)
130
- })
129
+ this.$bus.$on('pause-timer', this.pauseTimer)
131
130
 
132
131
  this.elapsedInterval = setInterval(() => {
133
132
  this.elapsedCounter += 1