fcad-core-dragon 2.0.0-beta.4 β†’ 2.0.0-beta.5

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 (44) hide show
  1. package/CHANGELOG +377 -373
  2. package/package.json +61 -61
  3. package/src/$locales/en.json +3 -1
  4. package/src/$locales/fr.json +3 -1
  5. package/src/components/AppBase.vue +20 -17
  6. package/src/components/AppBaseButton.test.js +22 -0
  7. package/src/components/AppBaseButton.vue +11 -5
  8. package/src/components/AppBaseModule.vue +48 -27
  9. package/src/components/AppBasePage.vue +7 -44
  10. package/src/components/AppCompAudio.vue +31 -0
  11. package/src/components/AppCompBranchButtons.vue +20 -16
  12. package/src/components/AppCompButtonProgress.vue +4 -9
  13. package/src/components/AppCompCarousel.vue +120 -90
  14. package/src/components/AppCompInputCheckBoxNext.vue +5 -0
  15. package/src/components/AppCompInputDropdownNext.vue +50 -8
  16. package/src/components/AppCompInputTextNext.vue +21 -2
  17. package/src/components/AppCompInputTextTableNext.vue +1 -0
  18. package/src/components/AppCompInputTextToFillDropdownNext.vue +8 -0
  19. package/src/components/AppCompMenu.vue +428 -423
  20. package/src/components/AppCompNavigation.vue +41 -28
  21. package/src/components/AppCompNoteCall.vue +64 -38
  22. package/src/components/AppCompNoteCredit.vue +303 -105
  23. package/src/components/AppCompPlayBar.vue +4 -5
  24. package/src/components/AppCompPlayBarNext.vue +20 -12
  25. package/src/components/AppCompPopUpNext.vue +1 -4
  26. package/src/components/AppCompQuizNext.vue +8 -4
  27. package/src/components/AppCompQuizRecall.vue +44 -22
  28. package/src/components/AppCompTableOfContent.vue +61 -62
  29. package/src/components/AppCompViewDisplay.vue +6 -6
  30. package/src/components/BaseModule.vue +1 -18
  31. package/src/components/tests__/AppBaseButton.spec.js +53 -0
  32. package/src/main.js +3 -3
  33. package/src/module/stores/appStore.js +58 -5
  34. package/src/module/xapi/Crypto/index.js +53 -53
  35. package/src/module/xapi/Statement/activity.js +47 -47
  36. package/src/module/xapi/Statement/group.js +26 -26
  37. package/src/module/xapi/Statement/statementRef.js +23 -23
  38. package/src/module/xapi/Statement/substatement.js +22 -22
  39. package/src/module/xapi/Statement/verb.js +36 -36
  40. package/src/module/xapi/activitytypes.js +17 -17
  41. package/src/plugins/helper.js +53 -12
  42. package/src/router/index.js +6 -1
  43. package/src/shared/validators.js +36 -179
  44. package/vitest.config.js +19 -0
@@ -21,10 +21,15 @@ const router = createRouter({
21
21
  })
22
22
 
23
23
  router.beforeResolve((to, from, next) => {
24
- const appStore = useAppStore()
25
24
  const app = inject('app')
25
+ const appStore = useAppStore()
26
+ const { getWidgetOpen, getPopupIsOpen, getSidebarIsOpen } = appStore
26
27
  const noNavigationToMenu = appStore.getSettingsFromStore('no_menu')
27
28
 
29
+ if (getWidgetOpen) app.config.globalProperties.$bus.$emit('close-widget') //close opened widget
30
+ if (getPopupIsOpen) app.config.globalProperties.$bus.$emit('close-popup') //close the popup
31
+ if (getSidebarIsOpen) app.config.globalProperties.$bus.$emit('close-sidebar') //close the sidebar
32
+
28
33
  app.config.globalProperties.$bus.$emit('update-route-history', from)
29
34
  app.config.globalProperties.$bus.$emit('update-content', to, from, next)
30
35
 
@@ -11,7 +11,7 @@ const validatefileContent = (fName, fData, requiredArgs = {}) => {
11
11
  case 'menuSettings': {
12
12
  const {
13
13
  keys4Lesson,
14
- keys4ActivityMando,
14
+ keys4ActivityMandatory,
15
15
  keys4ActivityOpt,
16
16
  keys4Anchors
17
17
  } = requiredArgs
@@ -19,17 +19,26 @@ const validatefileContent = (fName, fData, requiredArgs = {}) => {
19
19
  //*validate that data is an {Object}. if Not send error message
20
20
  if (fData.constructor !== Object)
21
21
  err = 'πŸ’₯Invalid file provided for menu settings'
22
-
23
- if (Object.entries(fData).length > 0) {
24
- const content = Object.entries(fData)
22
+ if (Object.keys(fData).length > 0) {
23
+ const content = Object.keys(fData)
24
+ //Check if lessonTitle exists
25
+ if (typeof fData.lessonTitle === 'undefined') {
26
+ err = `!!!! πŸ’₯ Missing πŸ‘‰ lessonTitle πŸ‘ˆ variable in ➑ menu.setting.js \n 🚩 This variable is mandatory.`
27
+ break
28
+ }
29
+ //Check if lessonNumber exists
30
+ if (typeof fData.lessonNumber === 'undefined') {
31
+ err = `!!!! πŸ’₯ Missing πŸ‘‰ lessonNumber πŸ‘ˆ variable in ➑ menu.setting.js \n 🚩 This variable is mandatory.`
32
+ break
33
+ }
25
34
  if (content.length != keys4Lesson.length) {
26
35
  err = `!!!! πŸ’₯ Missing activity in➑ menu.setting.js \n 🚩Must declare all activity in menu.setting.js`
27
36
  break
28
37
  } else {
29
- for (let [index, el] of content.entries()) {
38
+ for (let el of content) {
30
39
  //validate that the content of each entry is valide
31
- if (el[0] !== keys4Lesson[index]) {
32
- err = `!!!! πŸ’₯ invalid data provided for key πŸ‘‰ ${el[0]} πŸ‘ˆ in ➑ menu.setting.js \n 🚩 All activity must be listed and you must have a lesson title`
40
+ if (!keys4Lesson.includes(el)) {
41
+ err = `!!!! πŸ’₯ invalid data provided for key πŸ‘‰ ${el} πŸ‘ˆ in ➑ menu.setting.js \n 🚩 All activity must be listed and you must have a lesson title`
33
42
  break
34
43
  }
35
44
  }
@@ -37,30 +46,32 @@ const validatefileContent = (fName, fData, requiredArgs = {}) => {
37
46
 
38
47
  // Validate that each entry has the required key
39
48
  if (!err) {
40
- // remove key lessonTitle
41
- content.shift()
42
- for (let el of content) {
43
- const entry = el[1]
44
- const tabEntrykey = Object.keys(entry)
49
+ const reg = /^A[0-9]{2}$/ // target only activities
50
+ const contentActivities = content.filter((data) => data.match(reg)) //Get only the activities
45
51
 
52
+ for (let el of contentActivities) {
53
+ const entry = fData[el]
54
+
55
+ const tabEntrykey = Object.keys(entry)
46
56
  //Validate that entry has optional key
47
- if (!tabEntrykey.includes(keys4ActivityOpt[0])) {
48
- if (!tabEntrykey.includes(keys4ActivityOpt[1])) {
49
- err = `πŸ’₯ Missing πŸ‘‰ ${keys4ActivityOpt[0]} or ${keys4ActivityOpt[1]} πŸ‘ˆ in ${el[0]} in ➑ menu.setting.js \n 🚩One of thess two keys are mandatory : πŸ‘‰ ${keys4ActivityOpt}`
50
- break
51
- }
57
+ if (
58
+ !tabEntrykey.includes(keys4ActivityOpt[0]) ||
59
+ !tabEntrykey.includes(keys4ActivityOpt[1])
60
+ ) {
61
+ err = `πŸ’₯ Missing πŸ‘‰ ${keys4ActivityOpt[0]} or ${keys4ActivityOpt[1]} πŸ‘ˆ in ${el} in ➑ menu.setting.js \n 🚩One of thess two keys are mandatory : πŸ‘‰ ${keys4ActivityOpt}`
62
+ break
52
63
  }
53
64
 
54
65
  //Validate that entry has mandatory key
55
- for (let m of keys4ActivityMando) {
66
+ for (let m of keys4ActivityMandatory) {
56
67
  if (!tabEntrykey.includes(m)) {
57
- err = `πŸ’₯ Missing πŸ‘‰ ${m} πŸ‘ˆ in ${el[0]} in ➑ menu.setting.js \n 🚩All this key are mandatory : πŸ‘‰ ${keys4ActivityMando}`
68
+ err = `πŸ’₯ Missing πŸ‘‰ ${m} πŸ‘ˆ in ${el} in ➑ menu.setting.js \n 🚩All this key are mandatory : πŸ‘‰ ${keys4ActivityMandatory}`
58
69
  break
59
70
  } else {
60
71
  switch (m) {
61
72
  case 'anchors':
62
73
  if (entry[m].constructor !== Array)
63
- err = `πŸ’₯ Invalid anchors declaration for πŸ‘‰ ${el[0]} πŸ‘ˆ in ➑ menu.setting.j \n 🚩Must be of type {Array}`
74
+ err = `πŸ’₯ Invalid anchors declaration for πŸ‘‰ ${el} πŸ‘ˆ in ➑ menu.setting.j \n 🚩Must be of type {Array}`
64
75
  else {
65
76
  const anchors = entry.anchors
66
77
 
@@ -68,15 +79,15 @@ const validatefileContent = (fName, fData, requiredArgs = {}) => {
68
79
  //trow error if numbers of keys are not the same as required
69
80
  const a_numb = anchors.indexOf(a) + 1
70
81
  if (Object.keys(a).length !== keys4Anchors.length) {
71
- err = `πŸ’₯ Invalid declaration in πŸ‘‰anchor ${a_numb}πŸ‘ˆ for ➑ ${el[0]} in ➑ menu.setting.js \n 🚩 Allowed indexes are: πŸ‘‰ ${keys4Anchors}`
82
+ err = `πŸ’₯ Invalid declaration in πŸ‘‰anchor ${a_numb}πŸ‘ˆ for ➑ ${el} in ➑ menu.setting.js \n 🚩 Allowed indexes are: πŸ‘‰ ${keys4Anchors}`
72
83
  break
73
84
  }
74
85
  // Validated that required keys condition and type is met
75
86
  for (let k of keys4Anchors) {
76
87
  if (!a[k]) {
77
- err = `πŸ’₯ Missing πŸ‘‰ ${k} πŸ‘ˆ for anchor ${a_numb} ➑ ${el[0]} ➑ menu.setting.js \n 🚩 Allowed indexes are: πŸ‘‰ ${keys4Anchors}`
88
+ err = `πŸ’₯ Missing πŸ‘‰ ${k} πŸ‘ˆ for anchor ${a_numb} ➑ ${el} ➑ menu.setting.js \n 🚩 Allowed indexes are: πŸ‘‰ ${keys4Anchors}`
78
89
  } else if (a[k].constructor !== String) {
79
- err = `πŸ’₯ Invalid πŸ‘‰ ${k} πŸ‘ˆ declaration for anchor ${a_numb} ➑ ${el[0]} ➑ menu.setting.js \n 🚩 Must be of type {String}`
90
+ err = `πŸ’₯ Invalid πŸ‘‰ ${k} πŸ‘ˆ declaration for anchor ${a_numb} ➑ ${el} ➑ menu.setting.js \n 🚩 Must be of type {String}`
80
91
  }
81
92
  if (err) break
82
93
  }
@@ -87,7 +98,7 @@ const validatefileContent = (fName, fData, requiredArgs = {}) => {
87
98
  break
88
99
  default:
89
100
  if (entry[m].constructor !== String)
90
- err = `Invalid πŸ‘‰ ${m} πŸ‘ˆ declaration for ➑ ${el[0]} in ➑ menu.setting.js \n 🚩 Must be of type {String}`
101
+ err = `Invalid πŸ‘‰ ${m} πŸ‘ˆ declaration for ➑ ${el} in ➑ menu.setting.js \n 🚩 Must be of type {String}`
91
102
  break
92
103
  }
93
104
  }
@@ -459,161 +470,6 @@ const validateAudioData = (data) => {
459
470
  errorList.push(errString)
460
471
  }
461
472
  }
462
- /*if (process.env.NODE_ENV === 'development') {
463
- let errStringInConsole = null
464
- let errString = null
465
- const expectedKeys = ['mSources', 'mSubtitles', 'mPoster', 'mTranscript']
466
-
467
- if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
468
- errStringInConsole = `\n πŸ’₯ Invalid declaration for video element`
469
- console.warn(
470
- `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
471
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
472
- )
473
- errString = `Declaration invalide pour Objet video.`
474
- errorList.push(errString)
475
- }
476
-
477
- if (!data['mSources']) {
478
- errStringInConsole = ` Missing πŸ‘‰ mSources πŸ‘ˆ declaration for video element`
479
-
480
- errString = `l'Attribut πŸ‘‰ mSources πŸ‘ˆ pour l'Objet video n'est pas defini. `
481
- console.warn(
482
- `%c WARNING!>>> ${errStringInConsole}`,
483
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
484
- )
485
- errorList.push(errString)
486
- }
487
-
488
- //Start validation of keys in data
489
- if (!errString) {
490
- expectedKeys.forEach((k) => {
491
- if (!data[k] && k !== 'mSources') return
492
-
493
- switch (k) {
494
- case 'mSources':
495
- if (
496
- data['mSources'].constructor !== Array ||
497
- data['mSources'].length < 1
498
- ) {
499
- errStringInConsole =
500
- '\n πŸ’₯ Invalid type declaration for mSources.\n 🚩 Must be of type Array'
501
-
502
- errString = `l'Attribut πŸ‘‰ mSources πŸ‘ˆ pour le media doit Γͺtre de type Array`
503
-
504
- errorList.push(errString)
505
- console.warn(
506
- `%c WARNING!>>> ${errStringInConsole}`,
507
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
508
- )
509
- }
510
- break
511
-
512
- case 'mSubtitles':
513
- {
514
- //Validate required keys in Subtitle definition
515
- let expectedKeys = ['label', 'src', 'srclang']
516
- //we only accept one subtitle and must be defined as an Object with 3 keys
517
- if (
518
- data['mSubtitles'].constructor !== Array ||
519
- !data['mSubtitles'].length
520
- ) {
521
- errStringInConsole = `\n πŸ’₯ Invalid type declaration for mSubtitles.\n 🚩 Must be of type Array with at list one Object defined with: ${expectedKeys}`
522
-
523
- errString = `l'Attribut πŸ‘‰ mSubtitles πŸ‘ˆ doit Γͺtre de type Array avec au moins un Objet: {${expectedKeys}} `
524
-
525
- console.warn(
526
- `%c WARNING!>>> ${errStringInConsole}`,
527
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
528
- )
529
-
530
- return errorList.push(errString)
531
- }
532
- //Validate definition for each Subtitle Object
533
- for (const obj of data['mSubtitles']) {
534
- const objIndex = data['mSubtitles'].indexOf(obj)
535
- expectedKeys.forEach((expected) => {
536
- if (!obj[expected]) {
537
- errStringInConsole = `\n πŸ’₯ Missing key πŸ‘‰ ${expected} πŸ‘ˆ for mSubtitles No.${objIndex +
538
- 1}.\n 🚩 required keys are: ${expectedKeys} `
539
-
540
- errString = `l'Attribut πŸ‘‰ ${expected} πŸ‘ˆ pour le sous-titre No.${objIndex +
541
- 1} n'est pas dΓ©fini`
542
-
543
- console.warn(
544
- `%c WARNING!>>> ${errStringInConsole}`,
545
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
546
- )
547
- return errorList.push(errString)
548
- }
549
-
550
- // Only none empty String type Accepted
551
- if (
552
- obj[expected].constructor === String &&
553
- obj[expected].trim().length
554
- )
555
- return
556
-
557
- errStringInConsole = `\n πŸ’₯ Invalid type declaration for πŸ‘‰${expected}πŸ‘ˆ in mSubtitles No.${objIndex +
558
- 1}.\n 🚩 Must be none-empty String `
559
-
560
- errString = `l'Attribut πŸ‘‰${expected}πŸ‘ˆ du sous-titre No.${objIndex +
561
- 1} doit Γͺtre de type String et ne peut pas Γͺtre vide. `
562
-
563
- console.warn(
564
- `%c WARNING!>>> ${errStringInConsole}`,
565
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
566
- )
567
-
568
- errorList.push(errString)
569
- })
570
- }
571
- }
572
- break
573
- case 'mPoster':
574
- //Only type String allowed and must not be empty
575
- if (
576
- data['mPoster'] &&
577
- data['mPoster'].constructor == String &&
578
- data['mPoster'].trim().length
579
- )
580
- return
581
-
582
- errStringInConsole = `\n πŸ’₯ Invalid type declaration for πŸ‘‰ mPoster πŸ‘ˆ.\n 🚩 Must be none-empty String `
583
-
584
- errString = `l'Attribut πŸ‘‰ mPoster πŸ‘ˆ doit Γͺtre de type String et ne peut pas Γͺtre vide. `
585
-
586
- errorList.push(errString)
587
- console.warn(
588
- `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
589
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
590
- )
591
-
592
- break
593
- case 'mTranscript':
594
- //Only type String allowed and must not be empty
595
- if (
596
- data['mTranscript'] &&
597
- data['mTranscript'].constructor == String &&
598
- data['mTranscript'].trim().length
599
- )
600
- return
601
-
602
- errStringInConsole = `\n πŸ’₯ Invalid type declaration for πŸ‘‰ mTranscript πŸ‘ˆ .\n 🚩 Must be none-empty String `
603
-
604
- errString = `l'Attribut πŸ‘‰ mTranscript πŸ‘ˆ doit Γͺtre de type String et ne peut pas Γͺtre vide. `
605
-
606
- console.warn(
607
- `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
608
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
609
- )
610
- errorList.push(errString)
611
-
612
- break
613
- }
614
- })
615
- }
616
- }*/
617
473
  }
618
474
  return errorList
619
475
  }
@@ -1061,6 +917,7 @@ const validateSvgDefinition = (SVGData) => {
1061
917
  }
1062
918
 
1063
919
  export {
920
+ validateObjType,
1064
921
  validateVideoData,
1065
922
  validateAudioData,
1066
923
  validatefileContent,
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+ import { fileURLToPath, URL } from 'node:url'
5
+ import { mergeConfig, defineConfig, configDefaults } from 'vitest/config'
6
+ import vue from '@vitejs/plugin-vue'
7
+ import viteConfig from './vitest.config'
8
+
9
+ export default mergeConfig(
10
+ viteConfig,
11
+ defineConfig({
12
+ test: {
13
+ environment: 'jsdom',
14
+ exclude: [...configDefaults.exclude, 'e2e/**'],
15
+ root: fileURLToPath(new URL('./', import.meta.url))
16
+ },
17
+ plugins: [vue()]
18
+ })
19
+ )