fcad-core-dragon 2.0.0-beta.4 β 2.0.0-beta.6
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/.editorconfig +33 -33
- package/.eslintignore +29 -29
- package/.eslintrc.cjs +81 -81
- package/CHANGELOG +19 -0
- package/README.md +71 -71
- package/bk.scss +117 -117
- package/package.json +8 -8
- package/src/$locales/en.json +23 -23
- package/src/$locales/fr.json +22 -21
- package/src/assets/data/onboardingMessages.json +47 -47
- package/src/components/AppBase.vue +186 -116
- package/src/components/AppBaseButton.test.js +22 -0
- package/src/components/AppBaseButton.vue +13 -5
- package/src/components/AppBaseErrorDisplay.vue +438 -438
- package/src/components/AppBaseFlipCard.vue +84 -84
- package/src/components/AppBaseModule.vue +207 -128
- package/src/components/AppBasePage.vue +18 -45
- package/src/components/AppBasePopover.vue +41 -41
- package/src/components/AppCompAudio.vue +20 -17
- package/src/components/AppCompBranchButtons.vue +28 -70
- package/src/components/AppCompButtonProgress.vue +4 -9
- package/src/components/AppCompCarousel.vue +120 -90
- package/src/components/{AppCompTranscript.vue β AppCompContainer.vue} +8 -1
- package/src/components/AppCompInputCheckBoxNext.vue +5 -0
- package/src/components/AppCompInputDropdownNext.vue +50 -8
- package/src/components/AppCompInputRadioNext.vue +152 -152
- package/src/components/AppCompInputTextNext.vue +21 -2
- package/src/components/AppCompInputTextTableNext.vue +1 -0
- package/src/components/AppCompInputTextToFillDropdownNext.vue +8 -0
- package/src/components/AppCompInputTextToFillNext.vue +171 -171
- package/src/components/AppCompJauge.vue +74 -74
- package/src/components/AppCompMenu.vue +13 -7
- package/src/components/AppCompMenuItem.vue +228 -228
- package/src/components/AppCompNavigation.vue +43 -30
- package/src/components/AppCompNoteCall.vue +64 -38
- package/src/components/AppCompNoteCredit.vue +303 -105
- package/src/components/AppCompPlayBarNext.vue +25 -12
- package/src/components/AppCompPlayBarProgress.vue +82 -82
- package/src/components/AppCompPopUpNext.vue +1 -4
- package/src/components/AppCompQuizNext.vue +8 -4
- package/src/components/AppCompQuizRecall.vue +44 -22
- package/src/components/AppCompSVGNext.vue +2 -3
- package/src/components/AppCompSettingsMenu.vue +172 -172
- package/src/components/AppCompTableOfContent.vue +61 -62
- package/src/components/AppCompVideoPlayer.vue +17 -15
- package/src/components/AppCompViewDisplay.vue +6 -6
- package/src/components/BaseModule.vue +1 -18
- package/src/components/tests__/AppBaseButton.spec.js +53 -0
- package/src/composables/useQuiz.js +206 -206
- package/src/externalComps/ModuleView.vue +22 -22
- package/src/externalComps/SummaryView.vue +91 -91
- package/src/main.js +37 -32
- package/src/mixins/$mediaMixins.js +819 -819
- package/src/mixins/timerMixin.js +155 -155
- package/src/module/stores/appStore.js +59 -6
- package/src/module/xapi/ADL.js +144 -4
- package/src/module/xapi/Crypto/Hasher.js +241 -241
- package/src/module/xapi/Crypto/WordArray.js +278 -278
- package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
- package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
- package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
- package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
- package/src/module/xapi/Crypto/encoders/Base.js +105 -105
- package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
- package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
- package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
- package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
- package/src/module/xapi/Crypto/index.js +53 -53
- package/src/module/xapi/Statement/activity.js +47 -47
- package/src/module/xapi/Statement/agent.js +55 -55
- package/src/module/xapi/Statement/group.js +26 -26
- package/src/module/xapi/Statement/index.js +259 -259
- package/src/module/xapi/Statement/statement.js +253 -253
- package/src/module/xapi/Statement/statementRef.js +23 -23
- package/src/module/xapi/Statement/substatement.js +22 -22
- package/src/module/xapi/Statement/verb.js +36 -36
- package/src/module/xapi/activitytypes.js +17 -17
- package/src/module/xapi/utils.js +167 -167
- package/src/module/xapi/verbs.js +294 -294
- package/src/module/xapi/wrapper copy.js +1963 -0
- package/src/module/xapi/wrapper.js +121 -188
- package/src/module/xapi/xapiStatement.js +444 -444
- package/src/plugins/bus.js +8 -8
- package/src/plugins/gsap.js +14 -14
- package/src/plugins/helper.js +52 -12
- package/src/plugins/i18n.js +44 -44
- package/src/plugins/save.js +37 -37
- package/src/plugins/scorm.js +287 -287
- package/src/plugins/xapi.js +11 -11
- package/src/public/index.html +33 -33
- package/src/router/index.js +8 -2
- package/src/router/routes.js +312 -312
- package/src/shared/generalfuncs.js +210 -210
- package/src/shared/validators.js +38 -179
- package/vitest.config.js +19 -0
- package/src/components/AppCompPlayBar.vue +0 -1218
package/src/shared/validators.js
CHANGED
|
@@ -11,7 +11,7 @@ const validatefileContent = (fName, fData, requiredArgs = {}) => {
|
|
|
11
11
|
case 'menuSettings': {
|
|
12
12
|
const {
|
|
13
13
|
keys4Lesson,
|
|
14
|
-
|
|
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
|
-
|
|
24
|
-
|
|
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
|
|
38
|
+
for (let el of content) {
|
|
30
39
|
//validate that the content of each entry is valide
|
|
31
|
-
if (el
|
|
32
|
-
err = `!!!! π₯ invalid data provided for key π ${el
|
|
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
|
-
//
|
|
41
|
-
content.
|
|
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 (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
66
|
+
for (let m of keys4ActivityMandatory) {
|
|
56
67
|
if (!tabEntrykey.includes(m)) {
|
|
57
|
-
err = `π₯ Missing π ${m} π in ${el
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
101
|
+
err = `Invalid π ${m} π declaration for β‘ ${el} in β‘ menu.setting.js \n π© Must be of type {String}`
|
|
91
102
|
break
|
|
92
103
|
}
|
|
93
104
|
}
|
|
@@ -336,6 +347,7 @@ const validateAudioData = (data) => {
|
|
|
336
347
|
}
|
|
337
348
|
//** Validate if all the properties are right**/
|
|
338
349
|
let wrongProperties = checkerWrong(allProperties, currentProperties)
|
|
350
|
+
|
|
339
351
|
if (wrongProperties.length > 0) {
|
|
340
352
|
console.warn(
|
|
341
353
|
`%c WARNING!>>> AppCompAudio : audData property ${wrongProperties} invalid. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
|
|
@@ -348,6 +360,7 @@ const validateAudioData = (data) => {
|
|
|
348
360
|
|
|
349
361
|
//** Validate if all the required properties are in the data */
|
|
350
362
|
let missingRequired = checkerMissing(requiredProperties, currentProperties)
|
|
363
|
+
|
|
351
364
|
if (missingRequired.length > 0) {
|
|
352
365
|
console.warn(
|
|
353
366
|
`%c WARNING!>>> AppCompAudio : audData missing required ${missingRequired} property. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
|
|
@@ -459,161 +472,6 @@ const validateAudioData = (data) => {
|
|
|
459
472
|
errorList.push(errString)
|
|
460
473
|
}
|
|
461
474
|
}
|
|
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
475
|
}
|
|
618
476
|
return errorList
|
|
619
477
|
}
|
|
@@ -1061,6 +919,7 @@ const validateSvgDefinition = (SVGData) => {
|
|
|
1061
919
|
}
|
|
1062
920
|
|
|
1063
921
|
export {
|
|
922
|
+
validateObjType,
|
|
1064
923
|
validateVideoData,
|
|
1065
924
|
validateAudioData,
|
|
1066
925
|
validatefileContent,
|
package/vitest.config.js
ADDED
|
@@ -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
|
+
)
|