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
@@ -0,0 +1,73 @@
1
+ <!--@ Description: This component is used to display the playbar associate with the videoPlayer
2
+ @ What it does: The component is used to interacted with the videoPlayer via buttons.
3
+ v-media class is used to identified which html elements trigger the playBar to be appear (with focus/click)-->
4
+ <template>
5
+ <!--------------------------------- PLAY-BAR Progress -------------------------------------->
6
+ <div ref="$playbar-timeline" class="pb-timeline">
7
+ <div ref="$progress-area" class="progress-area">
8
+ <div
9
+ id="progress-bar"
10
+ ref="$progress-bar"
11
+ draggable="false"
12
+ tabindex="0"
13
+ class="v-media pb-progress-bar"
14
+ role="slider"
15
+ aria-valuemin="0"
16
+ :aria-label="mediaA11Y.label"
17
+ :aria-valuenow="mediaA11Y.valNow"
18
+ :aria-valuemax="mediaA11Y.valMax"
19
+ :aria-valuetext="mediaA11Y.valueText"
20
+ @focus="changeFocusState('progressBar', true)"
21
+ @blur="changeFocusState('progressBar', false)"
22
+ >
23
+ <!--Class progress-animation is apply when we are not using the thumb to change the progression-->
24
+ <div
25
+ id="progress-indicator"
26
+ ref="$progress-indicator"
27
+ draggable="false"
28
+ class="progress-indicator"
29
+ :class="{ 'progress-animation': !progressThumbDown }"
30
+ :style="{ width: progressBarPercentage + '%' }"
31
+ >
32
+ <!--Mousedown validate if the thumb is cliqued (if yes, the mouse is follow to modify the progress)
33
+ MouseOver/MouseOut deactivate click event on progressBar if the mouse hovered the thumb-->
34
+ <div
35
+ ref="$progress-thumb"
36
+ draggable="false"
37
+ class="progress-thumb"
38
+ style="z-index: 9"
39
+ @mousedown="
40
+ savedIsPlaying = isPlaying
41
+ progressThumbDown = true
42
+ "
43
+ @mouseover="progressThumbHover = true"
44
+ @mouseleave="progressThumbHover = false"
45
+ ></div>
46
+ </div>
47
+ </div>
48
+ <div
49
+ v-if="tooTipTimeCode"
50
+ id="seek-tooltip"
51
+ ref="$seek-tooltip"
52
+ aria-hidden="true"
53
+ class="seek-tooltip"
54
+ >
55
+ {{ tooTipTimeCode }}
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </template>
60
+
61
+ <script>
62
+ import $extendsMedia from '../mixins/$mediaMixins'
63
+
64
+ export default {
65
+ mixins: [$extendsMedia],
66
+ data() {
67
+ return {
68
+ tooTipTimeCode: null
69
+ }
70
+ },
71
+ mounted() {}
72
+ }
73
+ </script>
@@ -9,25 +9,24 @@
9
9
  :content-class="[pType, pName]"
10
10
  :no-fade="animationOff"
11
11
  :header-close-label="$t('button.alert_close')"
12
- v-bind="pContent.$bvArgs"
12
+ v-bind="{ ...pContent.$bvArgs }"
13
13
  @cancel="$cancel(pContent.cb_$cancel)"
14
14
  @ok="$confirm(pContent.cb_$confirm)"
15
15
  @hidden="$close(pContent.cb_$close)"
16
16
  >
17
- <template v-slot:default>
17
+ <template #default>
18
18
  <div class="box-content-popUp" v-html="pContent.hypertext" />
19
19
  </template>
20
20
  </b-modal>
21
21
  <!----------------------- OTHER POPUP ---------------------------->
22
-
23
- +
24
22
  <b-modal
25
23
  v-show="isPopupCustom === false"
26
- :id="getAppState"
24
+ :id="dynamicID"
27
25
  ref="someModal"
28
26
  :header-close-label="$t('button.alert_close')"
29
27
  :hide-footer="true"
30
- :content-class="[pType, pName, typeRetro, getAppState]"
28
+ v-bind="pContent.$bvArgs"
29
+ :content-class="[pType, pName, typeRetro, dynamicID]"
31
30
  :no-fade="animationOff"
32
31
  @hidden="$close(pContent.cb_$close)"
33
32
  >
@@ -38,13 +37,8 @@
38
37
  <h4 v-html="pTitle"></h4>
39
38
  </div>
40
39
 
41
- <div v-if="contentLength > 0" class="box-content-popUp">
42
- <div
43
- v-for="(content, _key, index) of pContent"
44
- :id="`col-ref-${_key}`"
45
- :key="`ref_${_key}_${content}`"
46
- class="col-popUp"
47
- >
40
+ <template v-if="contentLength > 0" class="box-content-popUp">
41
+ <template v-for="(content, _key, index) of pContent">
48
42
  <!-------- Create TEXT element -------------->
49
43
  <p
50
44
  v-if="_key.includes('text') && !_key.includes('hyper')"
@@ -58,7 +52,7 @@
58
52
  <div
59
53
  v-else-if="_key.includes('hypertext')"
60
54
  :id="`${_key}_${index}`"
61
- :key="_key"
55
+ :key="`hyp_${_key}`"
62
56
  v-html="content"
63
57
  />
64
58
 
@@ -66,8 +60,8 @@
66
60
  <img
67
61
  v-else-if="_key.includes('image')"
68
62
  :id="`${_key}_${index}`"
69
- :key="_key"
70
- :src="require(`@/assets/${content.path}`)"
63
+ :key="`img_${_key}`"
64
+ :src="content.path"
71
65
  :alt="content.label || 'image'"
72
66
  />
73
67
 
@@ -75,7 +69,7 @@
75
69
  <a
76
70
  v-else-if="_key.includes('link')"
77
71
  :id="`${_key}_${index}`"
78
- :key="_key"
72
+ :key="`lnk_${_key}`"
79
73
  :href="content.ref"
80
74
  target="_blank"
81
75
  :title="`${content.label}`"
@@ -87,8 +81,8 @@
87
81
  <video
88
82
  v-else-if="_key.includes('video')"
89
83
  :id="`${_key}_${index}`"
90
- :key="_key"
91
- :src="require(`@/assets/${content}`)"
84
+ :key="`vid_${_key}`"
85
+ :src="content"
92
86
  controls
93
87
  disablepictureinpicture
94
88
  controlslist="nofullscreen nodownload"
@@ -98,15 +92,15 @@
98
92
  <audio
99
93
  v-else-if="_key.includes('audio')"
100
94
  :id="`${_key}_${index}`"
101
- :key="_key"
102
- :src="require(`@/assets/${content}`)"
95
+ :key="`aud_${_key}`"
96
+ :src="content"
103
97
  controls
104
98
  controlslist="nodownload"
105
99
  />
106
- </div>
107
- </div>
100
+ </template>
101
+ </template>
108
102
  <!--------Default Button of Pop up --------------->
109
- <div v-show="pType === 'popup-avert'" class="col-bouton">
103
+ <div v-if="pType === 'popup-avert'" class="col-bouton">
110
104
  <app-base-button
111
105
  id="btn-cancel-popup"
112
106
  :name-acces="'Annuler'"
@@ -114,7 +108,7 @@
114
108
  :title="$t('button.cancel_pop')"
115
109
  @click="$cancel(pContent.cb_$cancel)"
116
110
  >
117
- {{ $t('button.cancel_pop') }}
111
+ {{ $t('button.cancel_pop') }} toto
118
112
  </app-base-button>
119
113
  <app-base-button
120
114
  id="btn-confirm-popup"
@@ -126,11 +120,15 @@
126
120
  {{ $t('button.confirm_pop') }}
127
121
  </app-base-button>
128
122
  </div>
129
- <div v-if="pType === 'popup-info'" id="popup-bottom-buttons">
123
+ <div v-if="pType === 'popup-info'" class="popup-bottom-buttons">
130
124
  {{ pType }}
125
+
131
126
  <button
132
127
  id="popup-retro-close-btn"
128
+ type="button"
133
129
  :title="$t('button.alert_close')"
130
+ aria-label="Close"
131
+ class="close"
134
132
  @click="$close(pContent.cb_$close)"
135
133
  >
136
134
  {{ $t('button.alert_close') }}
@@ -141,7 +139,7 @@
141
139
  ></portal-target>
142
140
  </div>
143
141
  <!----------------------------------------------------------------->
144
- <div v-if="pType === 'popup-endActivity'">
142
+ <div v-if="pType === 'popup-endActivity'" class="popup-bottom-buttons">
145
143
  <portal-target
146
144
  id="end-activity"
147
145
  name="wrap-end-activity"
@@ -192,18 +190,14 @@ export default {
192
190
  */
193
191
  let id
194
192
  if (this.isPopupCustom) id = 'popup-custom'
195
- else id = `${this.getAppState}`
193
+ else id = `${this.dynamicID}`
196
194
  const p = this.$bvModal._vm.$children.find((p) => p.id === id)
197
195
  return p
198
196
  },
199
- getAppState() {
200
- let toto
201
- if (!this.$store.state.$appStore.isDr) {
202
- toto = 'not-popup-custom full '
203
- } else {
204
- toto = 'not-popup-custom lites '
205
- }
206
- return toto
197
+ dynamicID() {
198
+ let c
199
+ c = 'not-popup-custom full'
200
+ return c
207
201
  }
208
202
  },
209
203
  mounted() {
@@ -215,11 +209,15 @@ export default {
215
209
  this.$bus.$on('popup-close', (options, cb) => {
216
210
  this.$close(options, cb)
217
211
  })
218
-
219
212
  this.$bus.$on('retro-type', (b) => {
220
213
  this.retroType(b)
221
214
  })
222
215
  },
216
+ beforeUnmount() {
217
+ this.$bus.$off('popup-open')
218
+ this.$bus.$off('popup-close')
219
+ this.$bus.$off('retro-type')
220
+ },
223
221
  methods: {
224
222
  /**
225
223
  * @description - Validate the data for the component
@@ -261,14 +259,14 @@ export default {
261
259
  validObject = true
262
260
  if (validObject) {
263
261
  let KeywordsList
264
- switch (data.type) {
265
- case 'popup-custom':
262
+ switch (true) {
263
+ case data.type === 'popup-custom':
266
264
  KeywordsList = ['hypertext', '$bvArgs'] // accepted keyword in value declartion for pop-up custom
267
265
 
268
266
  for (const key of Object.keys(data.value)) {
269
267
  // search if key match lists
270
268
  if (![...KeywordsList, ...callbacksFunctionList].includes(key))
271
- this.errors.push('Invalid key declaration in value')
269
+ this.errors.push(`Invalid key declaration in value : ${key}`)
272
270
 
273
271
  // Validating content of hypertext key
274
272
  if (
@@ -328,42 +326,87 @@ export default {
328
326
  'audio_',
329
327
  'link_',
330
328
  'hypertext_',
331
- 'object'
329
+ 'object',
330
+ 'cb_$',
331
+ '$bvArgs'
332
332
  ] // accepted keyword in value declaration for pop-up custom
333
333
 
334
334
  for (let key of Object.keys(data.value)) {
335
- const savedKey = key // backup key
335
+ let expectedKey = key
336
336
 
337
+ // search if key match lists
337
338
  if (key.includes('_') && !key.includes('cb_$'))
338
- key = `${key.split('_')[0]}_`
339
+ expectedKey = `${key.split('_')[0]}_`
340
+
341
+ //===============================================
342
+ const test = (regexp) => regexp.test(key) //defining the testing function
343
+
344
+ switch (true) {
345
+ case ![...KeywordsList, ...callbacksFunctionList].includes(
346
+ expectedKey
347
+ ):
348
+ this.errors.push(`Invalid key declaration in value: ${key}`)
349
+ break
350
+
351
+ case test(/\$bvArgs/):
352
+ // validating content of $bvArgs keys. Must be an array.
353
+ // validating content of $bvArgs. Content in $bvArgs must be objects
354
+ if (
355
+ data.value[key].constructor !== Array ||
356
+ data.value[key].length < 1
357
+ )
358
+ this.errors.push(
359
+ `Invalid assignment for ${key}. Must be an Array of Objects`
360
+ )
361
+ else {
362
+ let count = 0
363
+ data.value[key].forEach((element) => {
364
+ if (element.constructor !== Object && count < 1) {
365
+ this.errors.push(
366
+ `Invalid value(s) found in ${key}. Must be an Array of Objects`
367
+ )
368
+ count++
369
+ }
370
+ })
371
+ }
372
+ break
339
373
 
340
- // search if key match lists
341
- if (![...KeywordsList, ...callbacksFunctionList].includes(key))
342
- this.errors.push(`Invalid key declaration in value: ${key}`)
374
+ case test(/link/):
375
+ // Validating content of link element
376
+ if (!data.value[key].ref) {
377
+ this.errors.push('Missing ref for link')
378
+ }
379
+ break
343
380
 
344
- // Validating content of link element
345
- if (key.includes('link') && !data.value[savedKey].ref) {
346
- this.errors.push('Missing ref for link')
347
- }
381
+ case test(/image/):
382
+ // Validating content of link element
383
+ if (!data.value[key].path) {
384
+ this.errors.push('Missing path for image')
385
+ }
386
+ break
348
387
 
349
- // validating content of image element
350
- if (key.includes('image') && !data.value[savedKey].path)
351
- this.errors.push('Missing path for image')
388
+ case test(/cb_\$/):
389
+ // validating content of cb_$ keys to be a function
390
+ if (data.value[key].constructor != Function)
391
+ this.errors.push(
392
+ `Invalid assignment for ${key}. Must be a Function`
393
+ )
394
+ break
352
395
 
353
- // validating content of cb_$ keys
354
- if (
355
- key.includes('cb_$') &&
356
- data.value[key].constructor != Function
357
- )
358
- this.errors.push(
359
- `Invalid assignment for ${key}. Must be a Function`
360
- )
396
+ default: {
397
+ if (data.value[key].constructor != String) {
398
+ this.errors.push(
399
+ 'Invalid assignment for hypertext. Must be a String'
400
+ )
401
+ }
402
+ }
403
+ }
361
404
  }
362
405
  }
363
406
  } else this.errors.push('Invalid object declaration for value')
364
407
  } else this.errors.push('Missing argument - value')
365
408
 
366
- if (process.env.NODE_ENV === 'development') {
409
+ if (import.meta.env.DEV) {
367
410
  for (const err of this.errors)
368
411
  console.warn(
369
412
  `%c WARNING!>>> POP-UP: ${err} `,
@@ -446,74 +489,92 @@ export default {
446
489
  .modal {
447
490
  .modal-dialog {
448
491
  max-width: 100% !important;
449
- height: 100%;
450
492
  margin: 0 0 !important;
451
-
452
- // DR pop-up
453
- .lites {
454
- width: 450px;
493
+ display: flex;
494
+ flex-direction: column;
495
+ flex-wrap: wrap;
496
+ align-content: center;
497
+ justify-content: center;
498
+ align-items: center;
499
+ height: 100vh;
500
+
501
+ .popup-info,
502
+ .popup-noanswer {
503
+ width: 660px;
455
504
  margin: 10% auto;
456
-
457
505
  .modal-header {
458
506
  border-bottom: 0 solid transparent;
459
507
  }
460
-
461
- #popup-bottom-buttons {
462
- display: none;
463
- }
464
508
  }
465
509
 
466
- // full minou pop-up
467
- .full {
468
- &.popup-retro {
469
- width: 50%;
470
- height: 100%;
471
- position: relative;
472
- border-radius: 0;
473
- border-width: 0;
474
-
475
- .modal-header {
476
- position: absolute;
477
- top: 0;
478
- right: 0;
479
- z-index: 2;
480
- border-bottom: 0 solid transparent;
481
- }
510
+ .popup-endActivity {
511
+ justify-content: center;
512
+ align-items: center;
513
+ border-radius: 0;
482
514
 
483
- .modal-body {
484
- #popup-bottom-buttons {
485
- position: absolute;
486
- bottom: 0;
487
- margin-bottom: 65px;
488
-
489
- #popup-retro-close-btn {
490
- display: inline-block;
491
- vertical-align: top;
492
- }
515
+ .modal-header {
516
+ width: 100%;
517
+ border: 0 solid transparent;
493
518
 
494
- #popup_retro_nav_wrapper {
495
- display: inline-block;
496
- vertical-align: top;
497
- }
498
- }
519
+ .close {
520
+ padding: 1rem 1.5rem;
521
+ margin: -1rem -1rem -1rem auto;
499
522
  }
500
523
  }
501
524
 
502
- &.popup-info,
503
- &.popup-noanswer {
504
- width: 660px;
505
- margin: 10% auto;
506
- .modal-header {
507
- border-bottom: 0 solid transparent;
525
+ .modal-body {
526
+ width: 100%;
527
+ display: flex;
528
+ flex-direction: column;
529
+ flex-wrap: wrap;
530
+ justify-content: center;
531
+
532
+ .popup-bottom-buttons {
533
+ margin-left: auto;
534
+ margin-right: auto;
535
+ margin-top: 32px;
536
+ margin-bottom: 25px;
508
537
  }
509
538
 
510
- #popup_retro_nav_wrapper {
511
- display: inline-block;
512
- order: 1;
539
+ #hypertext_1_0 {
540
+ display: flex;
541
+ justify-content: center;
542
+
543
+ p {
544
+ font-size: 1.5rem;
545
+ font-weight: bold;
546
+ }
513
547
  }
514
548
 
515
- #popup-retro-close-btn {
516
- order: 2;
549
+ .popUp-title,
550
+ #end-activity {
551
+ display: flex;
552
+
553
+ .popup_primary_nav_btn {
554
+ border: #005ea1 solid 2px;
555
+ margin: 0 12px;
556
+
557
+ &:nth-child(1) {
558
+ color: #005ea1;
559
+ }
560
+
561
+ &:nth-child(2) {
562
+ background: #005ea1;
563
+ color: #ffffff;
564
+ }
565
+
566
+ &:hover {
567
+ border: #ffffff solid 2px;
568
+ background: #0898ff;
569
+ color: #ffffff;
570
+ }
571
+
572
+ &:active {
573
+ background: #00406e;
574
+ outline: 1px solid #00406e !important;
575
+ color: #ffffff;
576
+ }
577
+ }
517
578
  }
518
579
  }
519
580
  }