fcad-core-dragon 2.1.1 → 2.1.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.
- package/.editorconfig +7 -7
- package/.gitlab-ci.yml +124 -0
- package/.prettierrc +11 -11
- package/.vscode/extensions.json +8 -8
- package/.vscode/settings.json +46 -16
- package/CHANGELOG +520 -520
- package/README.md +57 -57
- package/documentation/.vitepress/config.js +114 -114
- package/documentation/api-examples.md +49 -49
- package/documentation/composants/app-base-button.md +58 -58
- package/documentation/composants/app-base-error-display.md +59 -59
- package/documentation/composants/app-base-popover.md +68 -68
- package/documentation/composants/app-comp-audio.md +75 -75
- package/documentation/composants/app-comp-branch-buttons.md +111 -111
- package/documentation/composants/app-comp-button-progress.md +53 -53
- package/documentation/composants/app-comp-carousel.md +53 -53
- package/documentation/composants/app-comp-container.md +53 -53
- package/documentation/composants/app-comp-input-checkbox-next.md +42 -42
- package/documentation/composants/app-comp-input-dropdown-next.md +34 -34
- package/documentation/composants/app-comp-input-radio-next.md +39 -39
- package/documentation/composants/app-comp-input-text-next.md +35 -35
- package/documentation/composants/app-comp-input-text-table-next.md +34 -34
- package/documentation/composants/app-comp-input-text-to-fill-dropdown-next.md +53 -53
- package/documentation/composants/app-comp-input-text-to-fill-next.md +31 -31
- package/documentation/composants/app-comp-jauge.md +31 -31
- package/documentation/composants/app-comp-menu-item.md +55 -55
- package/documentation/composants/app-comp-menu.md +29 -29
- package/documentation/composants/app-comp-navigation.md +41 -41
- package/documentation/composants/app-comp-note-call.md +53 -53
- package/documentation/composants/app-comp-note-credit.md +53 -53
- package/documentation/composants/app-comp-play-bar-next.md +53 -53
- package/documentation/composants/app-comp-pop-up-next.md +93 -93
- package/documentation/composants/app-comp-quiz-next.md +235 -235
- package/documentation/composants/app-comp-quiz-recall.md +53 -53
- package/documentation/composants/app-comp-svg-next.md +53 -53
- package/documentation/composants/app-comp-table-of-content.md +50 -50
- package/documentation/composants/app-comp-video-player.md +82 -82
- package/documentation/composants.md +46 -46
- package/documentation/composants_critiques/ModelPageComposant.md +53 -53
- package/documentation/composants_critiques/app-base-module.md +43 -43
- package/documentation/composants_critiques/app-base-page.md +48 -48
- package/documentation/composants_critiques/app-base.md +311 -311
- package/documentation/composants_critiques/main.md +15 -15
- package/documentation/demarrage.md +50 -50
- package/documentation/deploiement.md +57 -57
- package/documentation/index.md +33 -33
- package/documentation/markdown-examples.md +85 -85
- package/documentation/public/vite.svg +14 -14
- package/documentation/public/vuejs.svg +1 -1
- package/documentation/public/vuetify.svg +5 -5
- package/eslint.config.js +60 -60
- package/junit-report.xml +182 -0
- package/package.json +66 -59
- package/playwright/index.html +12 -0
- package/playwright/index.js +21 -0
- package/playwright-ct.config.js +95 -0
- package/src/$locales/en.json +157 -157
- package/src/$locales/fr.json +120 -120
- package/src/assets/data/onboardingMessages.json +47 -47
- package/src/components/AppBase.vue +1171 -1169
- package/src/components/AppBaseButton.vue +90 -95
- package/src/components/AppBaseErrorDisplay.vue +438 -438
- package/src/components/AppBaseFlipCard.vue +84 -84
- package/src/components/AppBaseModule.vue +1639 -1634
- package/src/components/AppBasePage.vue +867 -866
- package/src/components/AppBasePopover.vue +41 -41
- package/src/components/AppBaseSkeleton.vue +66 -66
- package/src/components/AppCompAudio.vue +261 -256
- package/src/components/AppCompBranchButtons.vue +508 -508
- package/src/components/AppCompButtonProgress.vue +137 -132
- package/src/components/AppCompCarousel.vue +342 -336
- package/src/components/AppCompContainer.vue +29 -29
- package/src/components/AppCompInputCheckBoxNx.vue +325 -323
- package/src/components/AppCompInputDropdownNx.vue +302 -299
- package/src/components/AppCompInputRadioNx.vue +287 -284
- package/src/components/AppCompInputTextNx.vue +156 -153
- package/src/components/AppCompInputTextTableNx.vue +205 -202
- package/src/components/AppCompInputTextToFillDropdownNx.vue +343 -340
- package/src/components/AppCompInputTextToFillNx.vue +316 -313
- package/src/components/AppCompJauge.vue +81 -81
- package/src/components/AppCompMenu.vue +6 -1
- package/src/components/AppCompMenuItem.vue +246 -240
- package/src/components/AppCompNavigation.vue +977 -972
- package/src/components/AppCompNoteCall.vue +167 -161
- package/src/components/AppCompNoteCredit.vue +496 -491
- package/src/components/AppCompPlayBarNext.vue +2290 -2288
- package/src/components/AppCompPopUpNext.vue +508 -504
- package/src/components/AppCompQuizNext.vue +515 -510
- package/src/components/AppCompQuizRecall.vue +355 -350
- package/src/components/AppCompSVGNext.vue +346 -346
- package/src/components/AppCompSettingsMenu.vue +177 -172
- package/src/components/AppCompTableOfContent.vue +433 -427
- package/src/components/AppCompVideoPlayer.vue +377 -377
- package/src/components/AppCompViewDisplay.vue +6 -6
- package/src/components/BaseModule.vue +55 -55
- package/src/composables/useIdleDetector.js +56 -56
- package/src/composables/useQuiz.js +89 -89
- package/src/composables/useTimer.js +172 -172
- package/src/directives/nvdaFix.js +53 -53
- package/src/externalComps/ModuleView.vue +22 -22
- package/src/externalComps/SummaryView.vue +91 -91
- package/src/main.js +493 -476
- package/src/module/stores/appStore.js +960 -947
- package/src/module/xapi/ADL.js +520 -520
- 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/launch.js +157 -157
- package/src/module/xapi/utils.js +167 -167
- package/src/module/xapi/verbs.js +294 -294
- package/src/module/xapi/wrapper.js +1895 -1895
- package/src/module/xapi/xapiStatement.js +444 -444
- package/src/plugins/analytics.js +34 -34
- package/src/plugins/bus.js +12 -8
- package/src/plugins/gsap.js +17 -17
- package/src/plugins/helper.js +355 -358
- package/src/plugins/i18n.js +27 -26
- package/src/plugins/idb.js +227 -227
- 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 +57 -57
- package/src/router/routes.js +312 -312
- package/src/shared/generalfuncs.js +344 -344
- package/src/shared/validators.js +1018 -1018
- package/tests/component/AppBaseButton.spec.js +53 -0
- package/tests/component/pinia.spec.js +24 -0
- package/{src/components/tests__ → tests/unit}/AppBaseButton.spec.js +53 -53
- package/tests/unit/AppCompInputCheckBoxNx.spec.js +59 -0
- package/tests/unit/AppCompInputDropdownNx.spec.js +51 -0
- package/tests/unit/AppCompInputRadioNx.spec.js +59 -0
- package/tests/unit/AppCompInputTextNx.spec.js +44 -0
- package/tests/unit/AppCompInputTextTableNx.spec.js +77 -0
- package/tests/unit/AppCompInputTextToFillDropdownNx.spec.js +60 -0
- package/tests/unit/AppCompInputTextToFillNx.spec.js +45 -0
- package/tests/unit/AppCompQuizNext.spec.js +114 -0
- package/tests/unit/AppCompVideoPlayer.spec.js +177 -0
- package/{src/components/tests__ → tests/unit}/useTimer.spec.js +91 -91
- package/vitest.config.js +28 -19
- package/vitest.setup.js +28 -0
- package/src/components/AppBaseButton.test.js +0 -21
package/src/shared/validators.js
CHANGED
|
@@ -1,1018 +1,1018 @@
|
|
|
1
|
-
// Errors message to display in the console
|
|
2
|
-
const ERR_TYPE = {
|
|
3
|
-
err0: `\n 💥 Missing \x1B[1m$attr$ \x1B[0mfor $comp$. \x1B[1m$attr$ \x1B[0m should be provided with following attributes: \x1B[1m{$data$}`,
|
|
4
|
-
err1: `\n 💥 Invalid declaration for \x1B[1m$wrd$ \x1B[0m object`,
|
|
5
|
-
err2: `\n 💥 Invalid type declaration for 👉\x1B[1m$attr$ \x1B[0m👈 in \x1B[1m$el$\x1B[0m. Expected is \x1B[3m$type$ \x1B[0mtype with some value`,
|
|
6
|
-
err3: `\n 💥 Missing required argument 👉\x1B[1m$key$\x1B[0m👈 in \x1B[1m$el$\x1B[0m. Required arguments are: \x1B[1m$args$`,
|
|
7
|
-
err4: `\n 💥 Missing required argument 👉\x1B[1m$key$\x1B[0m👈 in \x1B[1m$el$\x1B[0m. Required arguments are: \x1B[1m$args$`
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// Errors message to display in Appplication UI
|
|
11
|
-
const ERR_TYPE_MSG = {
|
|
12
|
-
err0: `\n Données manquantes pour <span style='text-transform: uppercase;'>$comp$</span>. Assurez-vous que le composant reçoit l'attribut <b>$attr$</b> avec des données pour: <b>$data$</b>`,
|
|
13
|
-
err1: `\n Déclaration invalide pour <b>$wrd$</b>. Assurez-vous que l'application a du data.`,
|
|
14
|
-
err2: `\n Vous avez une declaration invalide dans <b>$attr$</b>. 👉<b>$el$</b>👈 n'accepte que le type <i>$type$</i> et ne peut pas être vide`,
|
|
15
|
-
err3: `\n L'attribut 👉<b>$key$</b>👈 est manquant dans <b>$el$</b>. Les attributs requis sont: <b>$args$</b>`
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
//Get all the invalids properties from the object
|
|
19
|
-
/*Add element from target array that are NOT in arr to the wrongArray*/
|
|
20
|
-
const checkerWrong = (arr, target) => {
|
|
21
|
-
let wrongArray = []
|
|
22
|
-
target.every((v) => {
|
|
23
|
-
if (arr.includes(v)) {
|
|
24
|
-
return true
|
|
25
|
-
} else {
|
|
26
|
-
wrongArray.push(v)
|
|
27
|
-
return true
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
return wrongArray
|
|
31
|
-
}
|
|
32
|
-
//Get all the required properties that are missing from the object
|
|
33
|
-
/*Add element from the arr that are NOT in target arr to the missingArray*/
|
|
34
|
-
const checkerMissing = (arr, target) => {
|
|
35
|
-
let missingArray = []
|
|
36
|
-
arr.every((v) => {
|
|
37
|
-
if (target.includes(v)) {
|
|
38
|
-
return true
|
|
39
|
-
} else {
|
|
40
|
-
missingArray.push(v)
|
|
41
|
-
return true
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
return missingArray
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @description - Method to validate that given object attributes hold expected types
|
|
49
|
-
* @param {Object} Obj - object to validate
|
|
50
|
-
* @param {Object} Args - List of expected type groups - each type group must be an array of attributes with the same type
|
|
51
|
-
* @param {Array} notRequiredArgs - list of field that should be considered as optional in the object. Will not give error if not * provided but will be validated if they are present with wrong type or empty
|
|
52
|
-
* @param {Array} compName - Name of the component- will be display in error message
|
|
53
|
-
* @param {Array} err - list off errors to be added to
|
|
54
|
-
* @return {Object} list of errors - {errorInConsole, errorList} : errorlist can be used to display messages on template and
|
|
55
|
-
* errorInConsole to display messages in browser console
|
|
56
|
-
* @exemple - Given $user= {name:'toto', username:'totoEscargot', id:'id001', age:23, books:['one', 'two', 'three'] }
|
|
57
|
-
* Use validator on $user: validateObjType($user, {stringType:['name', 'username' , 'id'], numbType:['age'], arrayType:['books']})
|
|
58
|
-
* Will fail if any listed attribute not in $user or have wrong value. Error messages will be in console
|
|
59
|
-
*
|
|
60
|
-
*/
|
|
61
|
-
|
|
62
|
-
const validateObjType = (
|
|
63
|
-
Obj,
|
|
64
|
-
Args = {
|
|
65
|
-
boolType: null,
|
|
66
|
-
arrayType: null,
|
|
67
|
-
stringType: null,
|
|
68
|
-
objectType: null,
|
|
69
|
-
numbType: null
|
|
70
|
-
},
|
|
71
|
-
notRequiredArgs = null,
|
|
72
|
-
compName = 'component',
|
|
73
|
-
err = null
|
|
74
|
-
) => {
|
|
75
|
-
let errorInConsole = err && err.errorInConsole ? err.errorInConsole : []
|
|
76
|
-
let errorList = err && err.errorList ? err.errorLIst : []
|
|
77
|
-
let optionalArgs =
|
|
78
|
-
notRequiredArgs && notRequiredArgs.length ? notRequiredArgs : []
|
|
79
|
-
//=====Expected Arguments validation =================//
|
|
80
|
-
//Should have an object argument
|
|
81
|
-
if (!Obj) throw new Error(`No valid arguments provided`)
|
|
82
|
-
|
|
83
|
-
//List required attributes
|
|
84
|
-
const required = []
|
|
85
|
-
|
|
86
|
-
for (const _type in Args) {
|
|
87
|
-
// Should be a required type
|
|
88
|
-
if (
|
|
89
|
-
![
|
|
90
|
-
'boolType',
|
|
91
|
-
'arrayType',
|
|
92
|
-
'stringType',
|
|
93
|
-
'objectType',
|
|
94
|
-
'numberType'
|
|
95
|
-
].includes(_type)
|
|
96
|
-
)
|
|
97
|
-
throw new Error(`Unknown types declaration : ${_type}`)
|
|
98
|
-
|
|
99
|
-
if (Args[_type] && Args[_type].length) {
|
|
100
|
-
for (let el of Args[_type]) {
|
|
101
|
-
//Check that each given element is a string
|
|
102
|
-
if (el.constructor !== String)
|
|
103
|
-
throw new Error(
|
|
104
|
-
`Invalid type detected in ${JSON.stringify(
|
|
105
|
-
Args[_type]
|
|
106
|
-
)}. Item ${Args[_type].indexOf(el) + 1} should be a String`
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
if (!optionalArgs.includes(el)) required.push(el)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
//validate Args Keys type
|
|
115
|
-
for (const _type in Args) {
|
|
116
|
-
for (let el of Args[_type]) {
|
|
117
|
-
let reg = /(\$el\$)|(\$type\$)|(\$attr\$)/g
|
|
118
|
-
|
|
119
|
-
switch (true) {
|
|
120
|
-
// Check That each given element exist in data if not optional
|
|
121
|
-
case Obj[el] === undefined && required.includes(el): {
|
|
122
|
-
reg = /(\$key\$)|(\$el\$)|(\$args\$)/g
|
|
123
|
-
const reg2 = /\[|\]|/g
|
|
124
|
-
|
|
125
|
-
errorInConsole.push(
|
|
126
|
-
ERR_TYPE.err3.replace(reg, (e) => {
|
|
127
|
-
if (e == '$key$') return el
|
|
128
|
-
if (e == '$el$') return compName
|
|
129
|
-
if (e == '$args$') return JSON.stringify(required)
|
|
130
|
-
})
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
errorList.push(
|
|
134
|
-
ERR_TYPE_MSG.err3.replace(reg, (e) => {
|
|
135
|
-
if (e == '$key$') return el
|
|
136
|
-
if (e == '$el$') return compName || 'Composant'
|
|
137
|
-
if (e == '$args$')
|
|
138
|
-
return JSON.stringify(required).replaceAll(reg2, '')
|
|
139
|
-
})
|
|
140
|
-
)
|
|
141
|
-
break
|
|
142
|
-
}
|
|
143
|
-
//Should have Correct Types $attr$ $el$ $type$
|
|
144
|
-
case _type == 'boolType' &&
|
|
145
|
-
Obj[el] !== undefined &&
|
|
146
|
-
Obj[el].constructor !== Boolean:
|
|
147
|
-
errorInConsole.push(
|
|
148
|
-
ERR_TYPE.err2.replace(reg, (e) => {
|
|
149
|
-
if (e == '$attr$') return compName || 'Composant'
|
|
150
|
-
if (e == '$el$') return el
|
|
151
|
-
if (e == '$type$') return 'Boolean'
|
|
152
|
-
})
|
|
153
|
-
)
|
|
154
|
-
errorList.push(
|
|
155
|
-
ERR_TYPE_MSG.err2.replace(reg, (e) => {
|
|
156
|
-
if (e == '$attr$') return compName || 'Composant'
|
|
157
|
-
if (e == '$el$') return el
|
|
158
|
-
if (e == '$type$') return 'Boolean'
|
|
159
|
-
})
|
|
160
|
-
)
|
|
161
|
-
break
|
|
162
|
-
|
|
163
|
-
case _type == 'stringType' &&
|
|
164
|
-
Obj[el] !== undefined &&
|
|
165
|
-
(Obj[el].constructor !== String || !Obj[el].trim().length):
|
|
166
|
-
errorInConsole.push(
|
|
167
|
-
ERR_TYPE.err2.replace(reg, (e) => {
|
|
168
|
-
if (e == '$attr$') return compName || 'Composant'
|
|
169
|
-
if (e == '$el$') return el
|
|
170
|
-
if (e == '$type$') return 'String'
|
|
171
|
-
})
|
|
172
|
-
)
|
|
173
|
-
errorList.push(
|
|
174
|
-
ERR_TYPE_MSG.err2.replace(reg, (e) => {
|
|
175
|
-
if (e == '$attr$') return compName || 'Composant'
|
|
176
|
-
if (e == '$el$') return el
|
|
177
|
-
if (e == '$type$') return 'String'
|
|
178
|
-
})
|
|
179
|
-
)
|
|
180
|
-
break
|
|
181
|
-
|
|
182
|
-
case _type == 'arrayType' &&
|
|
183
|
-
Obj[el] !== null &&
|
|
184
|
-
Obj[el] !== undefined &&
|
|
185
|
-
(Obj[el].constructor !== Array || !Obj[el].length):
|
|
186
|
-
errorInConsole.push(
|
|
187
|
-
ERR_TYPE.err2.replace(reg, (e) => {
|
|
188
|
-
if (e == '$attr$') return compName || 'Composant'
|
|
189
|
-
if (e == '$el$') return el
|
|
190
|
-
if (e == '$type$') return 'Array'
|
|
191
|
-
})
|
|
192
|
-
)
|
|
193
|
-
errorList.push(
|
|
194
|
-
ERR_TYPE_MSG.err2.replace(reg, (e) => {
|
|
195
|
-
if (e == '$attr$') return compName || 'Composant'
|
|
196
|
-
if (e == '$el$') return el
|
|
197
|
-
if (e == '$type$') return 'Array'
|
|
198
|
-
})
|
|
199
|
-
)
|
|
200
|
-
break
|
|
201
|
-
|
|
202
|
-
case _type == 'numberType' &&
|
|
203
|
-
Obj[el] !== undefined &&
|
|
204
|
-
Obj[el].constructor !== Number:
|
|
205
|
-
errorInConsole.push(
|
|
206
|
-
ERR_TYPE.err2.replace(reg, (e) => {
|
|
207
|
-
if (e == '$attr$') return compName || 'Composant'
|
|
208
|
-
if (e == '$el$') return el
|
|
209
|
-
if (e == '$type$') return 'Number'
|
|
210
|
-
})
|
|
211
|
-
)
|
|
212
|
-
errorList.push(
|
|
213
|
-
ERR_TYPE_MSG.err2.replace(reg, (e) => {
|
|
214
|
-
if (e == '$attr$') return compName || 'Composant'
|
|
215
|
-
if (e == '$el$') return el
|
|
216
|
-
if (e == '$type$') return 'Number'
|
|
217
|
-
})
|
|
218
|
-
)
|
|
219
|
-
break
|
|
220
|
-
|
|
221
|
-
case _type == 'objectType' &&
|
|
222
|
-
Obj[el] !== undefined &&
|
|
223
|
-
Obj[el].constructor !== Object:
|
|
224
|
-
errorInConsole.push(
|
|
225
|
-
ERR_TYPE.err2.replace(reg, (e) => {
|
|
226
|
-
if (e == '$attr$') return compName || 'Composant'
|
|
227
|
-
if (e == '$el$') return el
|
|
228
|
-
if (e == '$type$') return 'Object'
|
|
229
|
-
})
|
|
230
|
-
)
|
|
231
|
-
errorList.push(
|
|
232
|
-
ERR_TYPE_MSG.err2.replace(reg, (e) => {
|
|
233
|
-
if (e == '$attr$') return compName || 'Composant'
|
|
234
|
-
if (e == '$el$') return el
|
|
235
|
-
if (e == '$type$') return 'Object'
|
|
236
|
-
})
|
|
237
|
-
)
|
|
238
|
-
break
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return { errorInConsole, errorList }
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* @description Validator for the content of menu setting file
|
|
248
|
-
* @param {String} fName- name of the file for use case
|
|
249
|
-
* @param {Object} fData: file's data to validate
|
|
250
|
-
* @param {Object} [requiredArgs] list of arguments to include consider in validation ()
|
|
251
|
-
*/
|
|
252
|
-
const validatefileContent = (fName, fData, requiredArgs = {}) => {
|
|
253
|
-
let err = null
|
|
254
|
-
if (import.meta.env.DEV) {
|
|
255
|
-
switch (fName) {
|
|
256
|
-
case 'menuSettings': {
|
|
257
|
-
const {
|
|
258
|
-
keys4Lesson,
|
|
259
|
-
keys4ActivityMandatory,
|
|
260
|
-
keys4ActivityOpt,
|
|
261
|
-
keys4Anchors
|
|
262
|
-
} = requiredArgs
|
|
263
|
-
|
|
264
|
-
//*validate that data is an {Object}. if Not send error message
|
|
265
|
-
if (fData.constructor !== Object)
|
|
266
|
-
err = '💥Invalid file provided for menu settings'
|
|
267
|
-
if (Object.keys(fData).length > 0) {
|
|
268
|
-
const content = Object.keys(fData)
|
|
269
|
-
//Check if lessonTitle exists
|
|
270
|
-
if (typeof fData.lessonTitle === 'undefined') {
|
|
271
|
-
err = `!!!! 💥 Missing 👉 lessonTitle 👈 variable in ➡ menu.setting.js \n 🚩 This variable is mandatory.`
|
|
272
|
-
break
|
|
273
|
-
}
|
|
274
|
-
//Check if lessonNumber exists
|
|
275
|
-
if (typeof fData.lessonNumber === 'undefined') {
|
|
276
|
-
err = `!!!! 💥 Missing 👉 lessonNumber 👈 variable in ➡ menu.setting.js \n 🚩 This variable is mandatory.`
|
|
277
|
-
break
|
|
278
|
-
}
|
|
279
|
-
if (content.length != keys4Lesson.length) {
|
|
280
|
-
err = `!!!! 💥 Missing activity in➡ menu.setting.js \n 🚩Must declare all activity in menu.setting.js`
|
|
281
|
-
break
|
|
282
|
-
} else {
|
|
283
|
-
for (let el of content) {
|
|
284
|
-
//validate that the content of each entry is valide
|
|
285
|
-
if (!keys4Lesson.includes(el)) {
|
|
286
|
-
err = `!!!! 💥 invalid data provided for key 👉 ${el} 👈 in ➡ menu.setting.js \n 🚩 All activity must be listed and you must have a lesson title`
|
|
287
|
-
break
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Validate that each entry has the required key
|
|
293
|
-
if (!err) {
|
|
294
|
-
const reg = /^A[0-9]{2}$/ // target only activities
|
|
295
|
-
const contentActivities = content.filter((data) => data.match(reg)) //Get only the activities
|
|
296
|
-
|
|
297
|
-
for (let el of contentActivities) {
|
|
298
|
-
const entry = fData[el]
|
|
299
|
-
|
|
300
|
-
const tabEntrykey = Object.keys(entry)
|
|
301
|
-
//Validate that entry has optional key
|
|
302
|
-
if (
|
|
303
|
-
!tabEntrykey.includes(keys4ActivityOpt[0]) ||
|
|
304
|
-
!tabEntrykey.includes(keys4ActivityOpt[1])
|
|
305
|
-
) {
|
|
306
|
-
err = `💥 Missing 👉 ${keys4ActivityOpt[0]} or ${keys4ActivityOpt[1]} 👈 in ${el} in ➡ menu.setting.js \n 🚩One of thess two keys are mandatory : 👉 ${keys4ActivityOpt}`
|
|
307
|
-
break
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
//Validate that entry has mandatory key
|
|
311
|
-
for (let m of keys4ActivityMandatory) {
|
|
312
|
-
if (!tabEntrykey.includes(m)) {
|
|
313
|
-
err = `💥 Missing 👉 ${m} 👈 in ${el} in ➡ menu.setting.js \n 🚩All this key are mandatory : 👉 ${keys4ActivityMandatory}`
|
|
314
|
-
break
|
|
315
|
-
} else {
|
|
316
|
-
switch (m) {
|
|
317
|
-
case 'anchors':
|
|
318
|
-
if (entry[m].constructor !== Array)
|
|
319
|
-
err = `💥 Invalid anchors declaration for 👉 ${el} 👈 in ➡ menu.setting.j \n 🚩Must be of type {Array}`
|
|
320
|
-
else {
|
|
321
|
-
const anchors = entry.anchors
|
|
322
|
-
|
|
323
|
-
for (let a of anchors) {
|
|
324
|
-
//trow error if numbers of keys are not the same as required
|
|
325
|
-
const a_numb = anchors.indexOf(a) + 1
|
|
326
|
-
if (Object.keys(a).length !== keys4Anchors.length) {
|
|
327
|
-
err = `💥 Invalid declaration in 👉anchor ${a_numb}👈 for ➡ ${el} in ➡ menu.setting.js \n 🚩 Allowed indexes are: 👉 ${keys4Anchors}`
|
|
328
|
-
break
|
|
329
|
-
}
|
|
330
|
-
// Validated that required keys condition and type is met
|
|
331
|
-
for (let k of keys4Anchors) {
|
|
332
|
-
if (!a[k]) {
|
|
333
|
-
err = `💥 Missing 👉 ${k} 👈 for anchor ${a_numb} ➡ ${el} ➡ menu.setting.js \n 🚩 Allowed indexes are: 👉 ${keys4Anchors}`
|
|
334
|
-
} else if (a[k].constructor !== String) {
|
|
335
|
-
err = `💥 Invalid 👉 ${k} 👈 declaration for anchor ${a_numb} ➡ ${el} ➡ menu.setting.js \n 🚩 Must be of type {String}`
|
|
336
|
-
}
|
|
337
|
-
if (err) break
|
|
338
|
-
}
|
|
339
|
-
if (err) break
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
break
|
|
344
|
-
default:
|
|
345
|
-
if (entry[m].constructor !== String)
|
|
346
|
-
err = `Invalid 👉 ${m} 👈 declaration for ➡ ${el} in ➡ menu.setting.js \n 🚩 Must be of type {String}`
|
|
347
|
-
break
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
break
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
return err
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* @description Validator for the content of menu setting file
|
|
363
|
-
* @param {Object} data- Object definition to validate
|
|
364
|
-
**/
|
|
365
|
-
const validateVideoData = (data) => {
|
|
366
|
-
const errorList = []
|
|
367
|
-
if (import.meta.env.DEV) {
|
|
368
|
-
let errStringInConsole = null
|
|
369
|
-
let errString = null
|
|
370
|
-
const expectedKeys = [
|
|
371
|
-
'id',
|
|
372
|
-
'mSources',
|
|
373
|
-
'mSubtitles',
|
|
374
|
-
'mPoster',
|
|
375
|
-
'mTranscript'
|
|
376
|
-
]
|
|
377
|
-
|
|
378
|
-
if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
|
|
379
|
-
errStringInConsole = `\n 💥 Invalid declaration for video element`
|
|
380
|
-
console.warn(
|
|
381
|
-
`%c WARNING!>>> VIDEO: ${errStringInConsole}`,
|
|
382
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
383
|
-
)
|
|
384
|
-
errString = `Declaration invalide pour Objet video.`
|
|
385
|
-
errorList.push(errString)
|
|
386
|
-
}
|
|
387
|
-
//Must have mSources
|
|
388
|
-
if (!data['mSources']) {
|
|
389
|
-
errStringInConsole = ` Missing 👉 mSources 👈 declaration for video element`
|
|
390
|
-
|
|
391
|
-
errString = `l'Attribut <b>mSources</b> pour l'Objet video n'est pas defini. `
|
|
392
|
-
console.warn(
|
|
393
|
-
`%c WARNING!>>> ${errStringInConsole}`,
|
|
394
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
395
|
-
)
|
|
396
|
-
errorList.push(errString)
|
|
397
|
-
}
|
|
398
|
-
//Must have id
|
|
399
|
-
if (!data['id']) {
|
|
400
|
-
errStringInConsole = ` Missing 👉 id 👈 declaration for video element`
|
|
401
|
-
|
|
402
|
-
errString = `l'Attribut <b>id</b> pour l'objet video n'est pas defini. `
|
|
403
|
-
console.warn(
|
|
404
|
-
`%c WARNING!>>> ${errStringInConsole}`,
|
|
405
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
406
|
-
)
|
|
407
|
-
errorList.push(errString)
|
|
408
|
-
}
|
|
409
|
-
//Start validation of keys in data
|
|
410
|
-
if (!errString) {
|
|
411
|
-
expectedKeys.forEach((k) => {
|
|
412
|
-
if (!data[k] && k !== 'mSources') return
|
|
413
|
-
|
|
414
|
-
switch (k) {
|
|
415
|
-
case 'id':
|
|
416
|
-
if (data['id'].constructor !== String || data['id'].length < 1) {
|
|
417
|
-
errStringInConsole =
|
|
418
|
-
'\n 💥 Invalid type declaration for id.\n 🚩 Must be of type Array'
|
|
419
|
-
|
|
420
|
-
errString = `l'Attribut <b>id</b> pour le media doit être de type <i>String</i>`
|
|
421
|
-
|
|
422
|
-
errorList.push(errString)
|
|
423
|
-
console.warn(
|
|
424
|
-
`%c WARNING!>>> ${errStringInConsole}`,
|
|
425
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
426
|
-
)
|
|
427
|
-
}
|
|
428
|
-
break
|
|
429
|
-
case 'mSources':
|
|
430
|
-
if (
|
|
431
|
-
data['mSources'].constructor !== Array ||
|
|
432
|
-
data['mSources'].length < 1
|
|
433
|
-
) {
|
|
434
|
-
errStringInConsole =
|
|
435
|
-
'\n 💥 Invalid type declaration for mSources.\n 🚩 Must be of type Array'
|
|
436
|
-
|
|
437
|
-
errString = `l'Attribut 👉 mSources 👈 pour le media doit être de type Array`
|
|
438
|
-
|
|
439
|
-
errorList.push(errString)
|
|
440
|
-
console.warn(
|
|
441
|
-
`%c WARNING!>>> ${errStringInConsole}`,
|
|
442
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
443
|
-
)
|
|
444
|
-
}
|
|
445
|
-
break
|
|
446
|
-
|
|
447
|
-
case 'mSubtitles':
|
|
448
|
-
{
|
|
449
|
-
//Validate required keys in Subtitle definition
|
|
450
|
-
let expectedKeys = ['label', 'src', 'srclang']
|
|
451
|
-
//we only accept one subtitle and must be defined as an Object with 3 keys
|
|
452
|
-
if (
|
|
453
|
-
data['mSubtitles'].constructor !== Array ||
|
|
454
|
-
!data['mSubtitles'].length
|
|
455
|
-
) {
|
|
456
|
-
errStringInConsole = `\n 💥 Invalid type declaration for mSubtitles.\n 🚩 Must be of type Array with at list one Object defined with: ${expectedKeys}`
|
|
457
|
-
|
|
458
|
-
errString = `l'Attribut 👉 mSubtitles 👈 doit être de type Array avec au moins un Objet: {${expectedKeys}} `
|
|
459
|
-
|
|
460
|
-
console.warn(
|
|
461
|
-
`%c WARNING!>>> ${errStringInConsole}`,
|
|
462
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
463
|
-
)
|
|
464
|
-
|
|
465
|
-
return errorList.push(errString)
|
|
466
|
-
}
|
|
467
|
-
//Validate definition for each Subtitle Object
|
|
468
|
-
for (const obj of data['mSubtitles']) {
|
|
469
|
-
const objIndex = data['mSubtitles'].indexOf(obj)
|
|
470
|
-
expectedKeys.forEach((expected) => {
|
|
471
|
-
if (!obj[expected]) {
|
|
472
|
-
errStringInConsole = `\n 💥 Missing key 👉 ${expected} 👈 for mSubtitles No.${
|
|
473
|
-
objIndex + 1
|
|
474
|
-
}.\n 🚩 required keys are: ${expectedKeys} `
|
|
475
|
-
|
|
476
|
-
errString = `l'Attribut 👉 ${expected} 👈 pour le sous-titre No.${
|
|
477
|
-
objIndex + 1
|
|
478
|
-
} n'est pas défini`
|
|
479
|
-
|
|
480
|
-
console.warn(
|
|
481
|
-
`%c WARNING!>>> ${errStringInConsole}`,
|
|
482
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
483
|
-
)
|
|
484
|
-
return errorList.push(errString)
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// Only none empty String type Accepted
|
|
488
|
-
if (
|
|
489
|
-
obj[expected].constructor === String &&
|
|
490
|
-
obj[expected].trim().length
|
|
491
|
-
)
|
|
492
|
-
return
|
|
493
|
-
|
|
494
|
-
errStringInConsole = `\n 💥 Invalid type declaration for 👉${expected}👈 in mSubtitles No.${
|
|
495
|
-
objIndex + 1
|
|
496
|
-
}.\n 🚩 Must be none-empty String `
|
|
497
|
-
|
|
498
|
-
errString = `l'Attribut 👉${expected}👈 du sous-titre No.${
|
|
499
|
-
objIndex + 1
|
|
500
|
-
} doit être de type String et ne peut pas être vide. `
|
|
501
|
-
|
|
502
|
-
console.warn(
|
|
503
|
-
`%c WARNING!>>> ${errStringInConsole}`,
|
|
504
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
errorList.push(errString)
|
|
508
|
-
})
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
break
|
|
512
|
-
case 'mPoster':
|
|
513
|
-
//Only type String allowed and must not be empty
|
|
514
|
-
if (
|
|
515
|
-
data['mPoster'] &&
|
|
516
|
-
data['mPoster'].constructor == String &&
|
|
517
|
-
data['mPoster'].trim().length
|
|
518
|
-
)
|
|
519
|
-
return
|
|
520
|
-
|
|
521
|
-
errStringInConsole = `\n 💥 Invalid type declaration for 👉 mPoster 👈.\n 🚩 Must be none-empty String `
|
|
522
|
-
|
|
523
|
-
errString = `l'Attribut 👉 mPoster 👈 doit être de type String et ne peut pas être vide. `
|
|
524
|
-
|
|
525
|
-
errorList.push(errString)
|
|
526
|
-
console.warn(
|
|
527
|
-
`%c WARNING!>>> VIDEO: ${errStringInConsole}`,
|
|
528
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
529
|
-
)
|
|
530
|
-
|
|
531
|
-
break
|
|
532
|
-
case 'mTranscript':
|
|
533
|
-
//Only type String allowed and must not be empty
|
|
534
|
-
if (
|
|
535
|
-
data['mTranscript'] &&
|
|
536
|
-
data['mTranscript'].constructor == String &&
|
|
537
|
-
data['mTranscript'].trim().length
|
|
538
|
-
)
|
|
539
|
-
return
|
|
540
|
-
|
|
541
|
-
errStringInConsole = `\n 💥 Invalid type declaration for 👉 mTranscript 👈 .\n 🚩 Must be none-empty String `
|
|
542
|
-
|
|
543
|
-
errString = `l'Attribut 👉 mTranscript 👈 doit être de type String et ne peut pas être vide. `
|
|
544
|
-
|
|
545
|
-
console.warn(
|
|
546
|
-
`%c WARNING!>>> VIDEO: ${errStringInConsole}`,
|
|
547
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
548
|
-
)
|
|
549
|
-
errorList.push(errString)
|
|
550
|
-
|
|
551
|
-
break
|
|
552
|
-
}
|
|
553
|
-
})
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
return errorList
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* @description Validator for the content of audio props
|
|
561
|
-
* @param {Object} data- Object definition to validate
|
|
562
|
-
**/
|
|
563
|
-
const validateAudioData = (data) => {
|
|
564
|
-
const errorList = []
|
|
565
|
-
let currentProperties = Object.getOwnPropertyNames(data)
|
|
566
|
-
if (process.env.NODE_ENV === 'development') {
|
|
567
|
-
//errorList.push('test')
|
|
568
|
-
|
|
569
|
-
const requiredProperties = ['id', 'mTitle', 'mSources', 'mTranscript']
|
|
570
|
-
|
|
571
|
-
const optionalProperties = ['mPoster', 'mAlt']
|
|
572
|
-
|
|
573
|
-
const allProperties = [
|
|
574
|
-
...requiredProperties,
|
|
575
|
-
...optionalProperties,
|
|
576
|
-
...['__ob__']
|
|
577
|
-
]
|
|
578
|
-
|
|
579
|
-
let errStringInConsole = null
|
|
580
|
-
let errString = null
|
|
581
|
-
|
|
582
|
-
//** Validate if data exist and is an object**/
|
|
583
|
-
if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
|
|
584
|
-
errStringInConsole = `\n 💥 Invalid declaration for audio element`
|
|
585
|
-
console.warn(
|
|
586
|
-
`%c WARNING!>>> AUDIO: ${errStringInConsole}`,
|
|
587
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
588
|
-
)
|
|
589
|
-
errString = `Déclaration invalide pour Objet audData. Ce doit être un objet non vide.`
|
|
590
|
-
errorList.push(errString)
|
|
591
|
-
return errorList
|
|
592
|
-
}
|
|
593
|
-
//** Validate if all the properties are right**/
|
|
594
|
-
let wrongProperties = checkerWrong(allProperties, currentProperties)
|
|
595
|
-
|
|
596
|
-
if (wrongProperties.length > 0) {
|
|
597
|
-
console.warn(
|
|
598
|
-
`%c WARNING!>>> AppCompAudio : audData property ${wrongProperties} invalid. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
|
|
599
|
-
'background: orange; color: white; display: block; margin:5px;'
|
|
600
|
-
)
|
|
601
|
-
errString = `Propriété invalide pour audData: ${wrongProperties}. Les propriétés requises sont: ${requiredProperties} et les propriétés facultatives sont: ${optionalProperties}`
|
|
602
|
-
errorList.push(errString)
|
|
603
|
-
return errorList
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
//** Validate if all the required properties are in the data */
|
|
607
|
-
let missingRequired = checkerMissing(requiredProperties, currentProperties)
|
|
608
|
-
|
|
609
|
-
if (missingRequired.length > 0) {
|
|
610
|
-
console.warn(
|
|
611
|
-
`%c WARNING!>>> AppCompAudio : audData missing required ${missingRequired} property. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
|
|
612
|
-
'background: orange; color: white; display: block; margin:5px;'
|
|
613
|
-
)
|
|
614
|
-
errString = `Propriété requise manquante pour audData: <b>${missingRequired}</b>. Les propriétés requises sont: <i>${requiredProperties}</i> et les propriétés facultatives sont: <i>${optionalProperties}</i>`
|
|
615
|
-
errorList.push(errString)
|
|
616
|
-
return errorList
|
|
617
|
-
}
|
|
618
|
-
/***Validate data values */
|
|
619
|
-
if (errorList.length == 0) {
|
|
620
|
-
let invalidString = []
|
|
621
|
-
let invalidArray = []
|
|
622
|
-
let invalidProperties = []
|
|
623
|
-
currentProperties.forEach((p) => {
|
|
624
|
-
switch (p) {
|
|
625
|
-
case 'mTitle':
|
|
626
|
-
case 'mTranscript':
|
|
627
|
-
case 'mPoster':
|
|
628
|
-
case 'mAlt':
|
|
629
|
-
if (data[p] && data[p].constructor == String) {
|
|
630
|
-
data[p].trim().length == 0 ? invalidString.push(p) : ''
|
|
631
|
-
} else {
|
|
632
|
-
invalidString.push(p)
|
|
633
|
-
}
|
|
634
|
-
break
|
|
635
|
-
case 'mSources': {
|
|
636
|
-
if (data[p] && data[p].constructor == Array) {
|
|
637
|
-
data[p].length == 0 ? invalidArray.push(p) : ''
|
|
638
|
-
} else {
|
|
639
|
-
invalidArray.push(p)
|
|
640
|
-
}
|
|
641
|
-
if (invalidArray.length === 0) {
|
|
642
|
-
//Valider les attributs de mSources
|
|
643
|
-
for (let i in data[p]) {
|
|
644
|
-
let object = data[p][i]
|
|
645
|
-
if ('src' in object && 'type' in object) {
|
|
646
|
-
if (
|
|
647
|
-
object['src'].constructor != String &&
|
|
648
|
-
object['type'].constructor != String
|
|
649
|
-
) {
|
|
650
|
-
invalidProperties.push(p)
|
|
651
|
-
} else {
|
|
652
|
-
object['src'].trim().length == 0
|
|
653
|
-
? invalidString.push(p)
|
|
654
|
-
: ''
|
|
655
|
-
object['type'].trim().length == 0
|
|
656
|
-
? invalidString.push(p)
|
|
657
|
-
: ''
|
|
658
|
-
}
|
|
659
|
-
} else {
|
|
660
|
-
invalidProperties.push(p)
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
break
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
})
|
|
668
|
-
//Display error for each type
|
|
669
|
-
//String
|
|
670
|
-
let sL = invalidString.length
|
|
671
|
-
if (sL > 0) {
|
|
672
|
-
errStringInConsole = `\n 💥 Invalid value type for 👉${invalidString}👈 \n 🚩 Must be none-empty String `
|
|
673
|
-
|
|
674
|
-
errString = `${sL > 1 ? 'Les ' : "L'"}attribut${
|
|
675
|
-
sL > 1 ? 's ' : ''
|
|
676
|
-
} 👉${invalidString}👈 doi${
|
|
677
|
-
sL > 1 ? 'ven' : ''
|
|
678
|
-
}t être de type String et ne peu${sL > 1 ? 'ven' : ''}t pas être vide. `
|
|
679
|
-
|
|
680
|
-
console.warn(
|
|
681
|
-
`%c WARNING!>>> ${errStringInConsole}`,
|
|
682
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
683
|
-
)
|
|
684
|
-
errorList.push(errString)
|
|
685
|
-
}
|
|
686
|
-
//Array
|
|
687
|
-
let aL = invalidArray.length
|
|
688
|
-
if (aL > 0) {
|
|
689
|
-
errStringInConsole = `\n 💥 Invalid value type for 👉${invalidArray}👈 \n 🚩 Must be none-empty Array`
|
|
690
|
-
|
|
691
|
-
errString = `${aL > 1 ? 'Les ' : "L'"}attribut${
|
|
692
|
-
aL > 1 ? 's ' : ''
|
|
693
|
-
} 👉${invalidArray}👈 doi${
|
|
694
|
-
sL > 1 ? 'ven' : ''
|
|
695
|
-
}t être de type Array et ne peu${aL > 1 ? 'ven' : ''}t pas être vide. `
|
|
696
|
-
|
|
697
|
-
console.warn(
|
|
698
|
-
`%c WARNING!>>> ${errStringInConsole}`,
|
|
699
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
700
|
-
)
|
|
701
|
-
errorList.push(errString)
|
|
702
|
-
}
|
|
703
|
-
let pL = invalidProperties.length
|
|
704
|
-
if (pL > 0) {
|
|
705
|
-
errStringInConsole = `\n 💥 Invalid value type for 👉src and/or type👈 in mSources \n 🚩 They are required and must be none-empty strings`
|
|
706
|
-
|
|
707
|
-
errString = `${pL > 1 ? 'Les ' : "L'"}attribut${
|
|
708
|
-
pL > 1 ? 's ' : ''
|
|
709
|
-
} 👉src and/or type👈 de mSources doi${
|
|
710
|
-
sL > 1 ? 'ven' : ''
|
|
711
|
-
}t être de type String et ne peu${pL > 1 ? 'ven' : ''}t pas être vide. `
|
|
712
|
-
|
|
713
|
-
console.warn(
|
|
714
|
-
`%c WARNING!>>> ${errStringInConsole}`,
|
|
715
|
-
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
716
|
-
)
|
|
717
|
-
errorList.push(errString)
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
return errorList
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
/**
|
|
725
|
-
* @description Validator for the content of app data.
|
|
726
|
-
* App data is used as setting for the application
|
|
727
|
-
* @param {Object} data - the Object definition to validate
|
|
728
|
-
* @param {Boolean} silent - if Validator should diplay error in console
|
|
729
|
-
*
|
|
730
|
-
**/
|
|
731
|
-
|
|
732
|
-
const validateAppContent = (data, silent = false) => {
|
|
733
|
-
let errorInConsole = []
|
|
734
|
-
let errorList = []
|
|
735
|
-
|
|
736
|
-
const requiredArgs = [
|
|
737
|
-
'lang',
|
|
738
|
-
'specification',
|
|
739
|
-
'id',
|
|
740
|
-
'crs_id',
|
|
741
|
-
'idb_id',
|
|
742
|
-
'no_menu',
|
|
743
|
-
'is_single_activity',
|
|
744
|
-
'auto_next_activity'
|
|
745
|
-
]
|
|
746
|
-
|
|
747
|
-
//Validate not empty data
|
|
748
|
-
if (Object.keys(data).length == 0) {
|
|
749
|
-
const reg = /(\$comp\$)|(\$data\$)|(\$attr\$)/g
|
|
750
|
-
|
|
751
|
-
errorInConsole.push(
|
|
752
|
-
ERR_TYPE.err0.replace(reg, (e) => {
|
|
753
|
-
if (e == '$comp$') return 'app-base'
|
|
754
|
-
if (e == '$data$') return requiredArgs.toString().replaceAll(',', ', ')
|
|
755
|
-
if (e == '$attr$') return 'app-config'
|
|
756
|
-
})
|
|
757
|
-
)
|
|
758
|
-
|
|
759
|
-
errorList.push(
|
|
760
|
-
ERR_TYPE_MSG.err0.replace(reg, (e) => {
|
|
761
|
-
if (e == '$comp$') return 'app-base'
|
|
762
|
-
if (e == '$data$') return requiredArgs.toString().replaceAll(',', ', ')
|
|
763
|
-
if (e == '$attr$') return 'app-config'
|
|
764
|
-
})
|
|
765
|
-
)
|
|
766
|
-
|
|
767
|
-
console.warn(errorInConsole[0])
|
|
768
|
-
|
|
769
|
-
return errorList
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
let stringType = ['lang', 'specification', 'id', 'crs_id', 'idb_id']
|
|
773
|
-
let boolType = [
|
|
774
|
-
'no_menu',
|
|
775
|
-
'is_single_activity',
|
|
776
|
-
'auto_next_activity',
|
|
777
|
-
'remote'
|
|
778
|
-
]
|
|
779
|
-
let objectType = ['actor', 'linkedResource']
|
|
780
|
-
let optionalArgs = ['remote', 'actor', 'linkedResource']
|
|
781
|
-
|
|
782
|
-
const { errorInConsole: errCons, errorList: errList } = validateObjType(
|
|
783
|
-
data,
|
|
784
|
-
{
|
|
785
|
-
stringType,
|
|
786
|
-
boolType,
|
|
787
|
-
objectType
|
|
788
|
-
},
|
|
789
|
-
optionalArgs,
|
|
790
|
-
'App.vue'
|
|
791
|
-
)
|
|
792
|
-
|
|
793
|
-
errorList = [...errorList, ...errList]
|
|
794
|
-
errorInConsole = [...errorInConsole, ...errCons]
|
|
795
|
-
|
|
796
|
-
//===========Optional Keys should be of correct type when declared =================//
|
|
797
|
-
// Has actor defined
|
|
798
|
-
if (data['actor']) {
|
|
799
|
-
let { errorInConsole: err1, errorList: err2 } = validateObjType(
|
|
800
|
-
data['actor'],
|
|
801
|
-
{
|
|
802
|
-
stringType: ['name', 'mbox']
|
|
803
|
-
},
|
|
804
|
-
'actor'
|
|
805
|
-
)
|
|
806
|
-
|
|
807
|
-
errorList = [...errorList, ...err2]
|
|
808
|
-
errorInConsole = [...errorInConsole, ...err1]
|
|
809
|
-
}
|
|
810
|
-
// Has LinkedResource defined
|
|
811
|
-
if (data['linkedResource']) {
|
|
812
|
-
let { errorInConsole: err1, errorList: err2 } = validateObjType(
|
|
813
|
-
data['linkedResource'],
|
|
814
|
-
{
|
|
815
|
-
stringType: ['url', 'id']
|
|
816
|
-
},
|
|
817
|
-
'linkedResource'
|
|
818
|
-
)
|
|
819
|
-
|
|
820
|
-
errorList = [...errorList, ...err2]
|
|
821
|
-
errorInConsole = [...errorInConsole, ...err1]
|
|
822
|
-
}
|
|
823
|
-
// Has endpointConfig defined
|
|
824
|
-
if (data['endpointConfig']) {
|
|
825
|
-
let { errorInConsole: err1, errorList: err2 } = validateObjType(
|
|
826
|
-
data['endpointConfig'],
|
|
827
|
-
{
|
|
828
|
-
stringType: ['auth', 'endpoint']
|
|
829
|
-
},
|
|
830
|
-
'endpointConfig'
|
|
831
|
-
)
|
|
832
|
-
errorList = [...errorList, ...err2]
|
|
833
|
-
errorInConsole = [...errorInConsole, ...err1]
|
|
834
|
-
}
|
|
835
|
-
//================== END Optional Keys ====================//
|
|
836
|
-
|
|
837
|
-
//Should display error to console
|
|
838
|
-
if (errorList.length && !silent) {
|
|
839
|
-
let txt = '⚠️ You have the following Errors:'
|
|
840
|
-
console.group(`%c ${txt}`, 'background:#ffc13a7d')
|
|
841
|
-
errorInConsole.forEach((err) => console.warn(err))
|
|
842
|
-
console.groupEnd()
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
return errorList
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
/**
|
|
849
|
-
* @description - Method validate the definition of SVG data.
|
|
850
|
-
* @param {Array || Object } SVGData - the data defining the SVG to render
|
|
851
|
-
* @return true - if valid
|
|
852
|
-
* */
|
|
853
|
-
|
|
854
|
-
const validateSvgDefinition = (SVGData) => {
|
|
855
|
-
//Should be Array of Object
|
|
856
|
-
if (SVGData.constructor !== Array && SVGData.constructor !== Object)
|
|
857
|
-
throw new Error('Unsupported Type for SVG data')
|
|
858
|
-
let Errors = []
|
|
859
|
-
let SVGDef = SVGData.constructor == Object ? new Array(SVGData) : SVGData
|
|
860
|
-
//Should validate the entries for each SVG definition as the required entries
|
|
861
|
-
|
|
862
|
-
for (const s_def of SVGDef) {
|
|
863
|
-
let i = SVGDef.indexOf(s_def)
|
|
864
|
-
let stringType = ['id', 'viewBox']
|
|
865
|
-
let arrayType = ['paths']
|
|
866
|
-
let { errorInConsole: errCons } = validateObjType(
|
|
867
|
-
s_def,
|
|
868
|
-
{
|
|
869
|
-
stringType,
|
|
870
|
-
arrayType
|
|
871
|
-
},
|
|
872
|
-
'viewBox',
|
|
873
|
-
`SVG ${i + 1}`
|
|
874
|
-
)
|
|
875
|
-
Errors.push(...errCons)
|
|
876
|
-
if (errCons.length) {
|
|
877
|
-
errCons.forEach((err) => console.warn(err))
|
|
878
|
-
break
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
//Should validate that each element in the path attributes is an object of type string and has the id attribute
|
|
882
|
-
|
|
883
|
-
for (const _path of s_def.paths) {
|
|
884
|
-
let index = s_def.paths.indexOf(_path)
|
|
885
|
-
if (_path.constructor !== Object)
|
|
886
|
-
throw Error(
|
|
887
|
-
`Unexpected definition for path ${index + 1} in SVG ${i + 1}. Expecting Object but received ${typeof _path}`
|
|
888
|
-
)
|
|
889
|
-
|
|
890
|
-
let stringType = ['d']
|
|
891
|
-
|
|
892
|
-
let { errorInConsole: errCons } = validateObjType(
|
|
893
|
-
_path,
|
|
894
|
-
{
|
|
895
|
-
stringType
|
|
896
|
-
},
|
|
897
|
-
null,
|
|
898
|
-
`SVG path ${index + 1}`
|
|
899
|
-
)
|
|
900
|
-
Errors.push(...errCons)
|
|
901
|
-
if (errCons.length) {
|
|
902
|
-
errCons.forEach((err) => console.warn(err))
|
|
903
|
-
break
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
//validate each entries in path
|
|
907
|
-
for (const _key in _path) {
|
|
908
|
-
if (_key == 'd') continue //skip
|
|
909
|
-
//all keys in path should be of type String and not empty
|
|
910
|
-
let stringType = [_key]
|
|
911
|
-
|
|
912
|
-
let { errorInConsole: errCons } = validateObjType(
|
|
913
|
-
_path,
|
|
914
|
-
{
|
|
915
|
-
stringType
|
|
916
|
-
},
|
|
917
|
-
null,
|
|
918
|
-
`SVG path ${index + 1}`
|
|
919
|
-
)
|
|
920
|
-
Errors.push(...errCons)
|
|
921
|
-
if (errCons.length) {
|
|
922
|
-
errCons.forEach((err) => console.log(err))
|
|
923
|
-
break
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
if (Errors.length) throw new Error('Error SVG')
|
|
930
|
-
return true
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
/**
|
|
934
|
-
* @description - Method validate the definition data forthe quiz.
|
|
935
|
-
* @param {Object} data - the data defining the SVG to render
|
|
936
|
-
* @return true - if valid
|
|
937
|
-
* */
|
|
938
|
-
const validateQuizData = (data) => {
|
|
939
|
-
let errors
|
|
940
|
-
let stringType = ['ennonce', 'id', 'type_question', 'texte_base']
|
|
941
|
-
let arrayType = ['choix_reponse', 'solution']
|
|
942
|
-
let objectType = ['retroaction']
|
|
943
|
-
let numberType = ['valeur_point', 'max_tentative']
|
|
944
|
-
let optionalArgs = ['valeur_point', 'max_tentative', 'texte_base']
|
|
945
|
-
|
|
946
|
-
errors = validateObjType(
|
|
947
|
-
data,
|
|
948
|
-
{ stringType, arrayType, objectType, numberType },
|
|
949
|
-
optionalArgs,
|
|
950
|
-
'quizData'
|
|
951
|
-
)
|
|
952
|
-
|
|
953
|
-
let hasError = errors.errorInConsole.length || errors.errorList.length
|
|
954
|
-
|
|
955
|
-
if (hasError) return errors
|
|
956
|
-
|
|
957
|
-
//validate Containt for retroaction
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
// if(data.solution !=null){
|
|
961
|
-
// console.log('ici')
|
|
962
|
-
// }else{
|
|
963
|
-
// console.log('la')
|
|
964
|
-
// }
|
|
965
|
-
|
|
966
|
-
switch (true) {
|
|
967
|
-
case data.retroaction != null:
|
|
968
|
-
objectType = ['retro_positive', 'retro_negative', 'retro_neutre']
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
errors = validateObjType(
|
|
972
|
-
data.retroaction,
|
|
973
|
-
{ objectType },
|
|
974
|
-
null,
|
|
975
|
-
'quizData retraoction'
|
|
976
|
-
)
|
|
977
|
-
|
|
978
|
-
hasError = errors.errorInConsole.length || errors.errorList.length
|
|
979
|
-
|
|
980
|
-
//console.log(hasError)
|
|
981
|
-
if (hasError) return errors
|
|
982
|
-
|
|
983
|
-
// Validate containt of retroaction attributes
|
|
984
|
-
stringType = ['title', 'hypertext']
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
for (const key of Object.keys(data.retroaction)) {
|
|
988
|
-
|
|
989
|
-
if(key == "retro_neutre") continue //skip
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
errors = validateObjType(
|
|
994
|
-
data.retroaction[key],
|
|
995
|
-
{ stringType },
|
|
996
|
-
null,
|
|
997
|
-
key
|
|
998
|
-
)
|
|
999
|
-
|
|
1000
|
-
hasError = errors.errorInConsole.length || errors.errorList.length
|
|
1001
|
-
|
|
1002
|
-
if (hasError) return errors
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
break
|
|
1006
|
-
}
|
|
1007
|
-
return errors
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
export {
|
|
1011
|
-
validateObjType,
|
|
1012
|
-
validateVideoData,
|
|
1013
|
-
validateAudioData,
|
|
1014
|
-
validatefileContent,
|
|
1015
|
-
validateAppContent,
|
|
1016
|
-
validateSvgDefinition,
|
|
1017
|
-
validateQuizData
|
|
1018
|
-
}
|
|
1
|
+
// Errors message to display in the console
|
|
2
|
+
const ERR_TYPE = {
|
|
3
|
+
err0: `\n 💥 Missing \x1B[1m$attr$ \x1B[0mfor $comp$. \x1B[1m$attr$ \x1B[0m should be provided with following attributes: \x1B[1m{$data$}`,
|
|
4
|
+
err1: `\n 💥 Invalid declaration for \x1B[1m$wrd$ \x1B[0m object`,
|
|
5
|
+
err2: `\n 💥 Invalid type declaration for 👉\x1B[1m$attr$ \x1B[0m👈 in \x1B[1m$el$\x1B[0m. Expected is \x1B[3m$type$ \x1B[0mtype with some value`,
|
|
6
|
+
err3: `\n 💥 Missing required argument 👉\x1B[1m$key$\x1B[0m👈 in \x1B[1m$el$\x1B[0m. Required arguments are: \x1B[1m$args$`,
|
|
7
|
+
err4: `\n 💥 Missing required argument 👉\x1B[1m$key$\x1B[0m👈 in \x1B[1m$el$\x1B[0m. Required arguments are: \x1B[1m$args$`
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Errors message to display in Appplication UI
|
|
11
|
+
const ERR_TYPE_MSG = {
|
|
12
|
+
err0: `\n Données manquantes pour <span style='text-transform: uppercase;'>$comp$</span>. Assurez-vous que le composant reçoit l'attribut <b>$attr$</b> avec des données pour: <b>$data$</b>`,
|
|
13
|
+
err1: `\n Déclaration invalide pour <b>$wrd$</b>. Assurez-vous que l'application a du data.`,
|
|
14
|
+
err2: `\n Vous avez une declaration invalide dans <b>$attr$</b>. 👉<b>$el$</b>👈 n'accepte que le type <i>$type$</i> et ne peut pas être vide`,
|
|
15
|
+
err3: `\n L'attribut 👉<b>$key$</b>👈 est manquant dans <b>$el$</b>. Les attributs requis sont: <b>$args$</b>`
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//Get all the invalids properties from the object
|
|
19
|
+
/*Add element from target array that are NOT in arr to the wrongArray*/
|
|
20
|
+
const checkerWrong = (arr, target) => {
|
|
21
|
+
let wrongArray = []
|
|
22
|
+
target.every((v) => {
|
|
23
|
+
if (arr.includes(v)) {
|
|
24
|
+
return true
|
|
25
|
+
} else {
|
|
26
|
+
wrongArray.push(v)
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
return wrongArray
|
|
31
|
+
}
|
|
32
|
+
//Get all the required properties that are missing from the object
|
|
33
|
+
/*Add element from the arr that are NOT in target arr to the missingArray*/
|
|
34
|
+
const checkerMissing = (arr, target) => {
|
|
35
|
+
let missingArray = []
|
|
36
|
+
arr.every((v) => {
|
|
37
|
+
if (target.includes(v)) {
|
|
38
|
+
return true
|
|
39
|
+
} else {
|
|
40
|
+
missingArray.push(v)
|
|
41
|
+
return true
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
return missingArray
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @description - Method to validate that given object attributes hold expected types
|
|
49
|
+
* @param {Object} Obj - object to validate
|
|
50
|
+
* @param {Object} Args - List of expected type groups - each type group must be an array of attributes with the same type
|
|
51
|
+
* @param {Array} notRequiredArgs - list of field that should be considered as optional in the object. Will not give error if not * provided but will be validated if they are present with wrong type or empty
|
|
52
|
+
* @param {Array} compName - Name of the component- will be display in error message
|
|
53
|
+
* @param {Array} err - list off errors to be added to
|
|
54
|
+
* @return {Object} list of errors - {errorInConsole, errorList} : errorlist can be used to display messages on template and
|
|
55
|
+
* errorInConsole to display messages in browser console
|
|
56
|
+
* @exemple - Given $user= {name:'toto', username:'totoEscargot', id:'id001', age:23, books:['one', 'two', 'three'] }
|
|
57
|
+
* Use validator on $user: validateObjType($user, {stringType:['name', 'username' , 'id'], numbType:['age'], arrayType:['books']})
|
|
58
|
+
* Will fail if any listed attribute not in $user or have wrong value. Error messages will be in console
|
|
59
|
+
*
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
const validateObjType = (
|
|
63
|
+
Obj,
|
|
64
|
+
Args = {
|
|
65
|
+
boolType: null,
|
|
66
|
+
arrayType: null,
|
|
67
|
+
stringType: null,
|
|
68
|
+
objectType: null,
|
|
69
|
+
numbType: null
|
|
70
|
+
},
|
|
71
|
+
notRequiredArgs = null,
|
|
72
|
+
compName = 'component',
|
|
73
|
+
err = null
|
|
74
|
+
) => {
|
|
75
|
+
let errorInConsole = err && err.errorInConsole ? err.errorInConsole : []
|
|
76
|
+
let errorList = err && err.errorList ? err.errorLIst : []
|
|
77
|
+
let optionalArgs =
|
|
78
|
+
notRequiredArgs && notRequiredArgs.length ? notRequiredArgs : []
|
|
79
|
+
//=====Expected Arguments validation =================//
|
|
80
|
+
//Should have an object argument
|
|
81
|
+
if (!Obj) throw new Error(`No valid arguments provided`)
|
|
82
|
+
|
|
83
|
+
//List required attributes
|
|
84
|
+
const required = []
|
|
85
|
+
|
|
86
|
+
for (const _type in Args) {
|
|
87
|
+
// Should be a required type
|
|
88
|
+
if (
|
|
89
|
+
![
|
|
90
|
+
'boolType',
|
|
91
|
+
'arrayType',
|
|
92
|
+
'stringType',
|
|
93
|
+
'objectType',
|
|
94
|
+
'numberType'
|
|
95
|
+
].includes(_type)
|
|
96
|
+
)
|
|
97
|
+
throw new Error(`Unknown types declaration : ${_type}`)
|
|
98
|
+
|
|
99
|
+
if (Args[_type] && Args[_type].length) {
|
|
100
|
+
for (let el of Args[_type]) {
|
|
101
|
+
//Check that each given element is a string
|
|
102
|
+
if (el.constructor !== String)
|
|
103
|
+
throw new Error(
|
|
104
|
+
`Invalid type detected in ${JSON.stringify(
|
|
105
|
+
Args[_type]
|
|
106
|
+
)}. Item ${Args[_type].indexOf(el) + 1} should be a String`
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if (!optionalArgs.includes(el)) required.push(el)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
//validate Args Keys type
|
|
115
|
+
for (const _type in Args) {
|
|
116
|
+
for (let el of Args[_type]) {
|
|
117
|
+
let reg = /(\$el\$)|(\$type\$)|(\$attr\$)/g
|
|
118
|
+
|
|
119
|
+
switch (true) {
|
|
120
|
+
// Check That each given element exist in data if not optional
|
|
121
|
+
case Obj[el] === undefined && required.includes(el): {
|
|
122
|
+
reg = /(\$key\$)|(\$el\$)|(\$args\$)/g
|
|
123
|
+
const reg2 = /\[|\]|/g
|
|
124
|
+
|
|
125
|
+
errorInConsole.push(
|
|
126
|
+
ERR_TYPE.err3.replace(reg, (e) => {
|
|
127
|
+
if (e == '$key$') return el
|
|
128
|
+
if (e == '$el$') return compName
|
|
129
|
+
if (e == '$args$') return JSON.stringify(required)
|
|
130
|
+
})
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
errorList.push(
|
|
134
|
+
ERR_TYPE_MSG.err3.replace(reg, (e) => {
|
|
135
|
+
if (e == '$key$') return el
|
|
136
|
+
if (e == '$el$') return compName || 'Composant'
|
|
137
|
+
if (e == '$args$')
|
|
138
|
+
return JSON.stringify(required).replaceAll(reg2, '')
|
|
139
|
+
})
|
|
140
|
+
)
|
|
141
|
+
break
|
|
142
|
+
}
|
|
143
|
+
//Should have Correct Types $attr$ $el$ $type$
|
|
144
|
+
case _type == 'boolType' &&
|
|
145
|
+
Obj[el] !== undefined &&
|
|
146
|
+
Obj[el].constructor !== Boolean:
|
|
147
|
+
errorInConsole.push(
|
|
148
|
+
ERR_TYPE.err2.replace(reg, (e) => {
|
|
149
|
+
if (e == '$attr$') return compName || 'Composant'
|
|
150
|
+
if (e == '$el$') return el
|
|
151
|
+
if (e == '$type$') return 'Boolean'
|
|
152
|
+
})
|
|
153
|
+
)
|
|
154
|
+
errorList.push(
|
|
155
|
+
ERR_TYPE_MSG.err2.replace(reg, (e) => {
|
|
156
|
+
if (e == '$attr$') return compName || 'Composant'
|
|
157
|
+
if (e == '$el$') return el
|
|
158
|
+
if (e == '$type$') return 'Boolean'
|
|
159
|
+
})
|
|
160
|
+
)
|
|
161
|
+
break
|
|
162
|
+
|
|
163
|
+
case _type == 'stringType' &&
|
|
164
|
+
Obj[el] !== undefined &&
|
|
165
|
+
(Obj[el].constructor !== String || !Obj[el].trim().length):
|
|
166
|
+
errorInConsole.push(
|
|
167
|
+
ERR_TYPE.err2.replace(reg, (e) => {
|
|
168
|
+
if (e == '$attr$') return compName || 'Composant'
|
|
169
|
+
if (e == '$el$') return el
|
|
170
|
+
if (e == '$type$') return 'String'
|
|
171
|
+
})
|
|
172
|
+
)
|
|
173
|
+
errorList.push(
|
|
174
|
+
ERR_TYPE_MSG.err2.replace(reg, (e) => {
|
|
175
|
+
if (e == '$attr$') return compName || 'Composant'
|
|
176
|
+
if (e == '$el$') return el
|
|
177
|
+
if (e == '$type$') return 'String'
|
|
178
|
+
})
|
|
179
|
+
)
|
|
180
|
+
break
|
|
181
|
+
|
|
182
|
+
case _type == 'arrayType' &&
|
|
183
|
+
Obj[el] !== null &&
|
|
184
|
+
Obj[el] !== undefined &&
|
|
185
|
+
(Obj[el].constructor !== Array || !Obj[el].length):
|
|
186
|
+
errorInConsole.push(
|
|
187
|
+
ERR_TYPE.err2.replace(reg, (e) => {
|
|
188
|
+
if (e == '$attr$') return compName || 'Composant'
|
|
189
|
+
if (e == '$el$') return el
|
|
190
|
+
if (e == '$type$') return 'Array'
|
|
191
|
+
})
|
|
192
|
+
)
|
|
193
|
+
errorList.push(
|
|
194
|
+
ERR_TYPE_MSG.err2.replace(reg, (e) => {
|
|
195
|
+
if (e == '$attr$') return compName || 'Composant'
|
|
196
|
+
if (e == '$el$') return el
|
|
197
|
+
if (e == '$type$') return 'Array'
|
|
198
|
+
})
|
|
199
|
+
)
|
|
200
|
+
break
|
|
201
|
+
|
|
202
|
+
case _type == 'numberType' &&
|
|
203
|
+
Obj[el] !== undefined &&
|
|
204
|
+
Obj[el].constructor !== Number:
|
|
205
|
+
errorInConsole.push(
|
|
206
|
+
ERR_TYPE.err2.replace(reg, (e) => {
|
|
207
|
+
if (e == '$attr$') return compName || 'Composant'
|
|
208
|
+
if (e == '$el$') return el
|
|
209
|
+
if (e == '$type$') return 'Number'
|
|
210
|
+
})
|
|
211
|
+
)
|
|
212
|
+
errorList.push(
|
|
213
|
+
ERR_TYPE_MSG.err2.replace(reg, (e) => {
|
|
214
|
+
if (e == '$attr$') return compName || 'Composant'
|
|
215
|
+
if (e == '$el$') return el
|
|
216
|
+
if (e == '$type$') return 'Number'
|
|
217
|
+
})
|
|
218
|
+
)
|
|
219
|
+
break
|
|
220
|
+
|
|
221
|
+
case _type == 'objectType' &&
|
|
222
|
+
Obj[el] !== undefined &&
|
|
223
|
+
Obj[el].constructor !== Object:
|
|
224
|
+
errorInConsole.push(
|
|
225
|
+
ERR_TYPE.err2.replace(reg, (e) => {
|
|
226
|
+
if (e == '$attr$') return compName || 'Composant'
|
|
227
|
+
if (e == '$el$') return el
|
|
228
|
+
if (e == '$type$') return 'Object'
|
|
229
|
+
})
|
|
230
|
+
)
|
|
231
|
+
errorList.push(
|
|
232
|
+
ERR_TYPE_MSG.err2.replace(reg, (e) => {
|
|
233
|
+
if (e == '$attr$') return compName || 'Composant'
|
|
234
|
+
if (e == '$el$') return el
|
|
235
|
+
if (e == '$type$') return 'Object'
|
|
236
|
+
})
|
|
237
|
+
)
|
|
238
|
+
break
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return { errorInConsole, errorList }
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* @description Validator for the content of menu setting file
|
|
248
|
+
* @param {String} fName- name of the file for use case
|
|
249
|
+
* @param {Object} fData: file's data to validate
|
|
250
|
+
* @param {Object} [requiredArgs] list of arguments to include consider in validation ()
|
|
251
|
+
*/
|
|
252
|
+
const validatefileContent = (fName, fData, requiredArgs = {}) => {
|
|
253
|
+
let err = null
|
|
254
|
+
if (import.meta.env.DEV) {
|
|
255
|
+
switch (fName) {
|
|
256
|
+
case 'menuSettings': {
|
|
257
|
+
const {
|
|
258
|
+
keys4Lesson,
|
|
259
|
+
keys4ActivityMandatory,
|
|
260
|
+
keys4ActivityOpt,
|
|
261
|
+
keys4Anchors
|
|
262
|
+
} = requiredArgs
|
|
263
|
+
|
|
264
|
+
//*validate that data is an {Object}. if Not send error message
|
|
265
|
+
if (fData.constructor !== Object)
|
|
266
|
+
err = '💥Invalid file provided for menu settings'
|
|
267
|
+
if (Object.keys(fData).length > 0) {
|
|
268
|
+
const content = Object.keys(fData)
|
|
269
|
+
//Check if lessonTitle exists
|
|
270
|
+
if (typeof fData.lessonTitle === 'undefined') {
|
|
271
|
+
err = `!!!! 💥 Missing 👉 lessonTitle 👈 variable in ➡ menu.setting.js \n 🚩 This variable is mandatory.`
|
|
272
|
+
break
|
|
273
|
+
}
|
|
274
|
+
//Check if lessonNumber exists
|
|
275
|
+
if (typeof fData.lessonNumber === 'undefined') {
|
|
276
|
+
err = `!!!! 💥 Missing 👉 lessonNumber 👈 variable in ➡ menu.setting.js \n 🚩 This variable is mandatory.`
|
|
277
|
+
break
|
|
278
|
+
}
|
|
279
|
+
if (content.length != keys4Lesson.length) {
|
|
280
|
+
err = `!!!! 💥 Missing activity in➡ menu.setting.js \n 🚩Must declare all activity in menu.setting.js`
|
|
281
|
+
break
|
|
282
|
+
} else {
|
|
283
|
+
for (let el of content) {
|
|
284
|
+
//validate that the content of each entry is valide
|
|
285
|
+
if (!keys4Lesson.includes(el)) {
|
|
286
|
+
err = `!!!! 💥 invalid data provided for key 👉 ${el} 👈 in ➡ menu.setting.js \n 🚩 All activity must be listed and you must have a lesson title`
|
|
287
|
+
break
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Validate that each entry has the required key
|
|
293
|
+
if (!err) {
|
|
294
|
+
const reg = /^A[0-9]{2}$/ // target only activities
|
|
295
|
+
const contentActivities = content.filter((data) => data.match(reg)) //Get only the activities
|
|
296
|
+
|
|
297
|
+
for (let el of contentActivities) {
|
|
298
|
+
const entry = fData[el]
|
|
299
|
+
|
|
300
|
+
const tabEntrykey = Object.keys(entry)
|
|
301
|
+
//Validate that entry has optional key
|
|
302
|
+
if (
|
|
303
|
+
!tabEntrykey.includes(keys4ActivityOpt[0]) ||
|
|
304
|
+
!tabEntrykey.includes(keys4ActivityOpt[1])
|
|
305
|
+
) {
|
|
306
|
+
err = `💥 Missing 👉 ${keys4ActivityOpt[0]} or ${keys4ActivityOpt[1]} 👈 in ${el} in ➡ menu.setting.js \n 🚩One of thess two keys are mandatory : 👉 ${keys4ActivityOpt}`
|
|
307
|
+
break
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
//Validate that entry has mandatory key
|
|
311
|
+
for (let m of keys4ActivityMandatory) {
|
|
312
|
+
if (!tabEntrykey.includes(m)) {
|
|
313
|
+
err = `💥 Missing 👉 ${m} 👈 in ${el} in ➡ menu.setting.js \n 🚩All this key are mandatory : 👉 ${keys4ActivityMandatory}`
|
|
314
|
+
break
|
|
315
|
+
} else {
|
|
316
|
+
switch (m) {
|
|
317
|
+
case 'anchors':
|
|
318
|
+
if (entry[m].constructor !== Array)
|
|
319
|
+
err = `💥 Invalid anchors declaration for 👉 ${el} 👈 in ➡ menu.setting.j \n 🚩Must be of type {Array}`
|
|
320
|
+
else {
|
|
321
|
+
const anchors = entry.anchors
|
|
322
|
+
|
|
323
|
+
for (let a of anchors) {
|
|
324
|
+
//trow error if numbers of keys are not the same as required
|
|
325
|
+
const a_numb = anchors.indexOf(a) + 1
|
|
326
|
+
if (Object.keys(a).length !== keys4Anchors.length) {
|
|
327
|
+
err = `💥 Invalid declaration in 👉anchor ${a_numb}👈 for ➡ ${el} in ➡ menu.setting.js \n 🚩 Allowed indexes are: 👉 ${keys4Anchors}`
|
|
328
|
+
break
|
|
329
|
+
}
|
|
330
|
+
// Validated that required keys condition and type is met
|
|
331
|
+
for (let k of keys4Anchors) {
|
|
332
|
+
if (!a[k]) {
|
|
333
|
+
err = `💥 Missing 👉 ${k} 👈 for anchor ${a_numb} ➡ ${el} ➡ menu.setting.js \n 🚩 Allowed indexes are: 👉 ${keys4Anchors}`
|
|
334
|
+
} else if (a[k].constructor !== String) {
|
|
335
|
+
err = `💥 Invalid 👉 ${k} 👈 declaration for anchor ${a_numb} ➡ ${el} ➡ menu.setting.js \n 🚩 Must be of type {String}`
|
|
336
|
+
}
|
|
337
|
+
if (err) break
|
|
338
|
+
}
|
|
339
|
+
if (err) break
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
break
|
|
344
|
+
default:
|
|
345
|
+
if (entry[m].constructor !== String)
|
|
346
|
+
err = `Invalid 👉 ${m} 👈 declaration for ➡ ${el} in ➡ menu.setting.js \n 🚩 Must be of type {String}`
|
|
347
|
+
break
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
break
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return err
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* @description Validator for the content of menu setting file
|
|
363
|
+
* @param {Object} data- Object definition to validate
|
|
364
|
+
**/
|
|
365
|
+
const validateVideoData = (data) => {
|
|
366
|
+
const errorList = []
|
|
367
|
+
if (import.meta.env.DEV) {
|
|
368
|
+
let errStringInConsole = null
|
|
369
|
+
let errString = null
|
|
370
|
+
const expectedKeys = [
|
|
371
|
+
'id',
|
|
372
|
+
'mSources',
|
|
373
|
+
'mSubtitles',
|
|
374
|
+
'mPoster',
|
|
375
|
+
'mTranscript'
|
|
376
|
+
]
|
|
377
|
+
|
|
378
|
+
if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
|
|
379
|
+
errStringInConsole = `\n 💥 Invalid declaration for video element`
|
|
380
|
+
console.warn(
|
|
381
|
+
`%c WARNING!>>> VIDEO: ${errStringInConsole}`,
|
|
382
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
383
|
+
)
|
|
384
|
+
errString = `Declaration invalide pour Objet video.`
|
|
385
|
+
errorList.push(errString)
|
|
386
|
+
}
|
|
387
|
+
//Must have mSources
|
|
388
|
+
if (!data['mSources']) {
|
|
389
|
+
errStringInConsole = ` Missing 👉 mSources 👈 declaration for video element`
|
|
390
|
+
|
|
391
|
+
errString = `l'Attribut <b>mSources</b> pour l'Objet video n'est pas defini. `
|
|
392
|
+
console.warn(
|
|
393
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
394
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
395
|
+
)
|
|
396
|
+
errorList.push(errString)
|
|
397
|
+
}
|
|
398
|
+
//Must have id
|
|
399
|
+
if (!data['id']) {
|
|
400
|
+
errStringInConsole = ` Missing 👉 id 👈 declaration for video element`
|
|
401
|
+
|
|
402
|
+
errString = `l'Attribut <b>id</b> pour l'objet video n'est pas defini. `
|
|
403
|
+
console.warn(
|
|
404
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
405
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
406
|
+
)
|
|
407
|
+
errorList.push(errString)
|
|
408
|
+
}
|
|
409
|
+
//Start validation of keys in data
|
|
410
|
+
if (!errString) {
|
|
411
|
+
expectedKeys.forEach((k) => {
|
|
412
|
+
if (!data[k] && k !== 'mSources') return
|
|
413
|
+
|
|
414
|
+
switch (k) {
|
|
415
|
+
case 'id':
|
|
416
|
+
if (data['id'].constructor !== String || data['id'].length < 1) {
|
|
417
|
+
errStringInConsole =
|
|
418
|
+
'\n 💥 Invalid type declaration for id.\n 🚩 Must be of type Array'
|
|
419
|
+
|
|
420
|
+
errString = `l'Attribut <b>id</b> pour le media doit être de type <i>String</i>`
|
|
421
|
+
|
|
422
|
+
errorList.push(errString)
|
|
423
|
+
console.warn(
|
|
424
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
425
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
426
|
+
)
|
|
427
|
+
}
|
|
428
|
+
break
|
|
429
|
+
case 'mSources':
|
|
430
|
+
if (
|
|
431
|
+
data['mSources'].constructor !== Array ||
|
|
432
|
+
data['mSources'].length < 1
|
|
433
|
+
) {
|
|
434
|
+
errStringInConsole =
|
|
435
|
+
'\n 💥 Invalid type declaration for mSources.\n 🚩 Must be of type Array'
|
|
436
|
+
|
|
437
|
+
errString = `l'Attribut 👉 mSources 👈 pour le media doit être de type Array`
|
|
438
|
+
|
|
439
|
+
errorList.push(errString)
|
|
440
|
+
console.warn(
|
|
441
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
442
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
443
|
+
)
|
|
444
|
+
}
|
|
445
|
+
break
|
|
446
|
+
|
|
447
|
+
case 'mSubtitles':
|
|
448
|
+
{
|
|
449
|
+
//Validate required keys in Subtitle definition
|
|
450
|
+
let expectedKeys = ['label', 'src', 'srclang']
|
|
451
|
+
//we only accept one subtitle and must be defined as an Object with 3 keys
|
|
452
|
+
if (
|
|
453
|
+
data['mSubtitles'].constructor !== Array ||
|
|
454
|
+
!data['mSubtitles'].length
|
|
455
|
+
) {
|
|
456
|
+
errStringInConsole = `\n 💥 Invalid type declaration for mSubtitles.\n 🚩 Must be of type Array with at list one Object defined with: ${expectedKeys}`
|
|
457
|
+
|
|
458
|
+
errString = `l'Attribut 👉 mSubtitles 👈 doit être de type Array avec au moins un Objet: {${expectedKeys}} `
|
|
459
|
+
|
|
460
|
+
console.warn(
|
|
461
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
462
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
return errorList.push(errString)
|
|
466
|
+
}
|
|
467
|
+
//Validate definition for each Subtitle Object
|
|
468
|
+
for (const obj of data['mSubtitles']) {
|
|
469
|
+
const objIndex = data['mSubtitles'].indexOf(obj)
|
|
470
|
+
expectedKeys.forEach((expected) => {
|
|
471
|
+
if (!obj[expected]) {
|
|
472
|
+
errStringInConsole = `\n 💥 Missing key 👉 ${expected} 👈 for mSubtitles No.${
|
|
473
|
+
objIndex + 1
|
|
474
|
+
}.\n 🚩 required keys are: ${expectedKeys} `
|
|
475
|
+
|
|
476
|
+
errString = `l'Attribut 👉 ${expected} 👈 pour le sous-titre No.${
|
|
477
|
+
objIndex + 1
|
|
478
|
+
} n'est pas défini`
|
|
479
|
+
|
|
480
|
+
console.warn(
|
|
481
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
482
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
483
|
+
)
|
|
484
|
+
return errorList.push(errString)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Only none empty String type Accepted
|
|
488
|
+
if (
|
|
489
|
+
obj[expected].constructor === String &&
|
|
490
|
+
obj[expected].trim().length
|
|
491
|
+
)
|
|
492
|
+
return
|
|
493
|
+
|
|
494
|
+
errStringInConsole = `\n 💥 Invalid type declaration for 👉${expected}👈 in mSubtitles No.${
|
|
495
|
+
objIndex + 1
|
|
496
|
+
}.\n 🚩 Must be none-empty String `
|
|
497
|
+
|
|
498
|
+
errString = `l'Attribut 👉${expected}👈 du sous-titre No.${
|
|
499
|
+
objIndex + 1
|
|
500
|
+
} doit être de type String et ne peut pas être vide. `
|
|
501
|
+
|
|
502
|
+
console.warn(
|
|
503
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
504
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
errorList.push(errString)
|
|
508
|
+
})
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
break
|
|
512
|
+
case 'mPoster':
|
|
513
|
+
//Only type String allowed and must not be empty
|
|
514
|
+
if (
|
|
515
|
+
data['mPoster'] &&
|
|
516
|
+
data['mPoster'].constructor == String &&
|
|
517
|
+
data['mPoster'].trim().length
|
|
518
|
+
)
|
|
519
|
+
return
|
|
520
|
+
|
|
521
|
+
errStringInConsole = `\n 💥 Invalid type declaration for 👉 mPoster 👈.\n 🚩 Must be none-empty String `
|
|
522
|
+
|
|
523
|
+
errString = `l'Attribut 👉 mPoster 👈 doit être de type String et ne peut pas être vide. `
|
|
524
|
+
|
|
525
|
+
errorList.push(errString)
|
|
526
|
+
console.warn(
|
|
527
|
+
`%c WARNING!>>> VIDEO: ${errStringInConsole}`,
|
|
528
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
break
|
|
532
|
+
case 'mTranscript':
|
|
533
|
+
//Only type String allowed and must not be empty
|
|
534
|
+
if (
|
|
535
|
+
data['mTranscript'] &&
|
|
536
|
+
data['mTranscript'].constructor == String &&
|
|
537
|
+
data['mTranscript'].trim().length
|
|
538
|
+
)
|
|
539
|
+
return
|
|
540
|
+
|
|
541
|
+
errStringInConsole = `\n 💥 Invalid type declaration for 👉 mTranscript 👈 .\n 🚩 Must be none-empty String `
|
|
542
|
+
|
|
543
|
+
errString = `l'Attribut 👉 mTranscript 👈 doit être de type String et ne peut pas être vide. `
|
|
544
|
+
|
|
545
|
+
console.warn(
|
|
546
|
+
`%c WARNING!>>> VIDEO: ${errStringInConsole}`,
|
|
547
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
548
|
+
)
|
|
549
|
+
errorList.push(errString)
|
|
550
|
+
|
|
551
|
+
break
|
|
552
|
+
}
|
|
553
|
+
})
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return errorList
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* @description Validator for the content of audio props
|
|
561
|
+
* @param {Object} data- Object definition to validate
|
|
562
|
+
**/
|
|
563
|
+
const validateAudioData = (data) => {
|
|
564
|
+
const errorList = []
|
|
565
|
+
let currentProperties = Object.getOwnPropertyNames(data)
|
|
566
|
+
if (process.env.NODE_ENV === 'development') {
|
|
567
|
+
//errorList.push('test')
|
|
568
|
+
|
|
569
|
+
const requiredProperties = ['id', 'mTitle', 'mSources', 'mTranscript']
|
|
570
|
+
|
|
571
|
+
const optionalProperties = ['mPoster', 'mAlt']
|
|
572
|
+
|
|
573
|
+
const allProperties = [
|
|
574
|
+
...requiredProperties,
|
|
575
|
+
...optionalProperties,
|
|
576
|
+
...['__ob__']
|
|
577
|
+
]
|
|
578
|
+
|
|
579
|
+
let errStringInConsole = null
|
|
580
|
+
let errString = null
|
|
581
|
+
|
|
582
|
+
//** Validate if data exist and is an object**/
|
|
583
|
+
if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
|
|
584
|
+
errStringInConsole = `\n 💥 Invalid declaration for audio element`
|
|
585
|
+
console.warn(
|
|
586
|
+
`%c WARNING!>>> AUDIO: ${errStringInConsole}`,
|
|
587
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
588
|
+
)
|
|
589
|
+
errString = `Déclaration invalide pour Objet audData. Ce doit être un objet non vide.`
|
|
590
|
+
errorList.push(errString)
|
|
591
|
+
return errorList
|
|
592
|
+
}
|
|
593
|
+
//** Validate if all the properties are right**/
|
|
594
|
+
let wrongProperties = checkerWrong(allProperties, currentProperties)
|
|
595
|
+
|
|
596
|
+
if (wrongProperties.length > 0) {
|
|
597
|
+
console.warn(
|
|
598
|
+
`%c WARNING!>>> AppCompAudio : audData property ${wrongProperties} invalid. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
|
|
599
|
+
'background: orange; color: white; display: block; margin:5px;'
|
|
600
|
+
)
|
|
601
|
+
errString = `Propriété invalide pour audData: ${wrongProperties}. Les propriétés requises sont: ${requiredProperties} et les propriétés facultatives sont: ${optionalProperties}`
|
|
602
|
+
errorList.push(errString)
|
|
603
|
+
return errorList
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
//** Validate if all the required properties are in the data */
|
|
607
|
+
let missingRequired = checkerMissing(requiredProperties, currentProperties)
|
|
608
|
+
|
|
609
|
+
if (missingRequired.length > 0) {
|
|
610
|
+
console.warn(
|
|
611
|
+
`%c WARNING!>>> AppCompAudio : audData missing required ${missingRequired} property. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
|
|
612
|
+
'background: orange; color: white; display: block; margin:5px;'
|
|
613
|
+
)
|
|
614
|
+
errString = `Propriété requise manquante pour audData: <b>${missingRequired}</b>. Les propriétés requises sont: <i>${requiredProperties}</i> et les propriétés facultatives sont: <i>${optionalProperties}</i>`
|
|
615
|
+
errorList.push(errString)
|
|
616
|
+
return errorList
|
|
617
|
+
}
|
|
618
|
+
/***Validate data values */
|
|
619
|
+
if (errorList.length == 0) {
|
|
620
|
+
let invalidString = []
|
|
621
|
+
let invalidArray = []
|
|
622
|
+
let invalidProperties = []
|
|
623
|
+
currentProperties.forEach((p) => {
|
|
624
|
+
switch (p) {
|
|
625
|
+
case 'mTitle':
|
|
626
|
+
case 'mTranscript':
|
|
627
|
+
case 'mPoster':
|
|
628
|
+
case 'mAlt':
|
|
629
|
+
if (data[p] && data[p].constructor == String) {
|
|
630
|
+
data[p].trim().length == 0 ? invalidString.push(p) : ''
|
|
631
|
+
} else {
|
|
632
|
+
invalidString.push(p)
|
|
633
|
+
}
|
|
634
|
+
break
|
|
635
|
+
case 'mSources': {
|
|
636
|
+
if (data[p] && data[p].constructor == Array) {
|
|
637
|
+
data[p].length == 0 ? invalidArray.push(p) : ''
|
|
638
|
+
} else {
|
|
639
|
+
invalidArray.push(p)
|
|
640
|
+
}
|
|
641
|
+
if (invalidArray.length === 0) {
|
|
642
|
+
//Valider les attributs de mSources
|
|
643
|
+
for (let i in data[p]) {
|
|
644
|
+
let object = data[p][i]
|
|
645
|
+
if ('src' in object && 'type' in object) {
|
|
646
|
+
if (
|
|
647
|
+
object['src'].constructor != String &&
|
|
648
|
+
object['type'].constructor != String
|
|
649
|
+
) {
|
|
650
|
+
invalidProperties.push(p)
|
|
651
|
+
} else {
|
|
652
|
+
object['src'].trim().length == 0
|
|
653
|
+
? invalidString.push(p)
|
|
654
|
+
: ''
|
|
655
|
+
object['type'].trim().length == 0
|
|
656
|
+
? invalidString.push(p)
|
|
657
|
+
: ''
|
|
658
|
+
}
|
|
659
|
+
} else {
|
|
660
|
+
invalidProperties.push(p)
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
break
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
})
|
|
668
|
+
//Display error for each type
|
|
669
|
+
//String
|
|
670
|
+
let sL = invalidString.length
|
|
671
|
+
if (sL > 0) {
|
|
672
|
+
errStringInConsole = `\n 💥 Invalid value type for 👉${invalidString}👈 \n 🚩 Must be none-empty String `
|
|
673
|
+
|
|
674
|
+
errString = `${sL > 1 ? 'Les ' : "L'"}attribut${
|
|
675
|
+
sL > 1 ? 's ' : ''
|
|
676
|
+
} 👉${invalidString}👈 doi${
|
|
677
|
+
sL > 1 ? 'ven' : ''
|
|
678
|
+
}t être de type String et ne peu${sL > 1 ? 'ven' : ''}t pas être vide. `
|
|
679
|
+
|
|
680
|
+
console.warn(
|
|
681
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
682
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
683
|
+
)
|
|
684
|
+
errorList.push(errString)
|
|
685
|
+
}
|
|
686
|
+
//Array
|
|
687
|
+
let aL = invalidArray.length
|
|
688
|
+
if (aL > 0) {
|
|
689
|
+
errStringInConsole = `\n 💥 Invalid value type for 👉${invalidArray}👈 \n 🚩 Must be none-empty Array`
|
|
690
|
+
|
|
691
|
+
errString = `${aL > 1 ? 'Les ' : "L'"}attribut${
|
|
692
|
+
aL > 1 ? 's ' : ''
|
|
693
|
+
} 👉${invalidArray}👈 doi${
|
|
694
|
+
sL > 1 ? 'ven' : ''
|
|
695
|
+
}t être de type Array et ne peu${aL > 1 ? 'ven' : ''}t pas être vide. `
|
|
696
|
+
|
|
697
|
+
console.warn(
|
|
698
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
699
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
700
|
+
)
|
|
701
|
+
errorList.push(errString)
|
|
702
|
+
}
|
|
703
|
+
let pL = invalidProperties.length
|
|
704
|
+
if (pL > 0) {
|
|
705
|
+
errStringInConsole = `\n 💥 Invalid value type for 👉src and/or type👈 in mSources \n 🚩 They are required and must be none-empty strings`
|
|
706
|
+
|
|
707
|
+
errString = `${pL > 1 ? 'Les ' : "L'"}attribut${
|
|
708
|
+
pL > 1 ? 's ' : ''
|
|
709
|
+
} 👉src and/or type👈 de mSources doi${
|
|
710
|
+
sL > 1 ? 'ven' : ''
|
|
711
|
+
}t être de type String et ne peu${pL > 1 ? 'ven' : ''}t pas être vide. `
|
|
712
|
+
|
|
713
|
+
console.warn(
|
|
714
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
715
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
716
|
+
)
|
|
717
|
+
errorList.push(errString)
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return errorList
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* @description Validator for the content of app data.
|
|
726
|
+
* App data is used as setting for the application
|
|
727
|
+
* @param {Object} data - the Object definition to validate
|
|
728
|
+
* @param {Boolean} silent - if Validator should diplay error in console
|
|
729
|
+
*
|
|
730
|
+
**/
|
|
731
|
+
|
|
732
|
+
const validateAppContent = (data, silent = false) => {
|
|
733
|
+
let errorInConsole = []
|
|
734
|
+
let errorList = []
|
|
735
|
+
|
|
736
|
+
const requiredArgs = [
|
|
737
|
+
'lang',
|
|
738
|
+
'specification',
|
|
739
|
+
'id',
|
|
740
|
+
'crs_id',
|
|
741
|
+
'idb_id',
|
|
742
|
+
'no_menu',
|
|
743
|
+
'is_single_activity',
|
|
744
|
+
'auto_next_activity'
|
|
745
|
+
]
|
|
746
|
+
|
|
747
|
+
//Validate not empty data
|
|
748
|
+
if (Object.keys(data).length == 0) {
|
|
749
|
+
const reg = /(\$comp\$)|(\$data\$)|(\$attr\$)/g
|
|
750
|
+
|
|
751
|
+
errorInConsole.push(
|
|
752
|
+
ERR_TYPE.err0.replace(reg, (e) => {
|
|
753
|
+
if (e == '$comp$') return 'app-base'
|
|
754
|
+
if (e == '$data$') return requiredArgs.toString().replaceAll(',', ', ')
|
|
755
|
+
if (e == '$attr$') return 'app-config'
|
|
756
|
+
})
|
|
757
|
+
)
|
|
758
|
+
|
|
759
|
+
errorList.push(
|
|
760
|
+
ERR_TYPE_MSG.err0.replace(reg, (e) => {
|
|
761
|
+
if (e == '$comp$') return 'app-base'
|
|
762
|
+
if (e == '$data$') return requiredArgs.toString().replaceAll(',', ', ')
|
|
763
|
+
if (e == '$attr$') return 'app-config'
|
|
764
|
+
})
|
|
765
|
+
)
|
|
766
|
+
|
|
767
|
+
console.warn(errorInConsole[0])
|
|
768
|
+
|
|
769
|
+
return errorList
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
let stringType = ['lang', 'specification', 'id', 'crs_id', 'idb_id']
|
|
773
|
+
let boolType = [
|
|
774
|
+
'no_menu',
|
|
775
|
+
'is_single_activity',
|
|
776
|
+
'auto_next_activity',
|
|
777
|
+
'remote'
|
|
778
|
+
]
|
|
779
|
+
let objectType = ['actor', 'linkedResource']
|
|
780
|
+
let optionalArgs = ['remote', 'actor', 'linkedResource']
|
|
781
|
+
|
|
782
|
+
const { errorInConsole: errCons, errorList: errList } = validateObjType(
|
|
783
|
+
data,
|
|
784
|
+
{
|
|
785
|
+
stringType,
|
|
786
|
+
boolType,
|
|
787
|
+
objectType
|
|
788
|
+
},
|
|
789
|
+
optionalArgs,
|
|
790
|
+
'App.vue'
|
|
791
|
+
)
|
|
792
|
+
|
|
793
|
+
errorList = [...errorList, ...errList]
|
|
794
|
+
errorInConsole = [...errorInConsole, ...errCons]
|
|
795
|
+
|
|
796
|
+
//===========Optional Keys should be of correct type when declared =================//
|
|
797
|
+
// Has actor defined
|
|
798
|
+
if (data['actor']) {
|
|
799
|
+
let { errorInConsole: err1, errorList: err2 } = validateObjType(
|
|
800
|
+
data['actor'],
|
|
801
|
+
{
|
|
802
|
+
stringType: ['name', 'mbox']
|
|
803
|
+
},
|
|
804
|
+
'actor'
|
|
805
|
+
)
|
|
806
|
+
|
|
807
|
+
errorList = [...errorList, ...err2]
|
|
808
|
+
errorInConsole = [...errorInConsole, ...err1]
|
|
809
|
+
}
|
|
810
|
+
// Has LinkedResource defined
|
|
811
|
+
if (data['linkedResource']) {
|
|
812
|
+
let { errorInConsole: err1, errorList: err2 } = validateObjType(
|
|
813
|
+
data['linkedResource'],
|
|
814
|
+
{
|
|
815
|
+
stringType: ['url', 'id']
|
|
816
|
+
},
|
|
817
|
+
'linkedResource'
|
|
818
|
+
)
|
|
819
|
+
|
|
820
|
+
errorList = [...errorList, ...err2]
|
|
821
|
+
errorInConsole = [...errorInConsole, ...err1]
|
|
822
|
+
}
|
|
823
|
+
// Has endpointConfig defined
|
|
824
|
+
if (data['endpointConfig']) {
|
|
825
|
+
let { errorInConsole: err1, errorList: err2 } = validateObjType(
|
|
826
|
+
data['endpointConfig'],
|
|
827
|
+
{
|
|
828
|
+
stringType: ['auth', 'endpoint']
|
|
829
|
+
},
|
|
830
|
+
'endpointConfig'
|
|
831
|
+
)
|
|
832
|
+
errorList = [...errorList, ...err2]
|
|
833
|
+
errorInConsole = [...errorInConsole, ...err1]
|
|
834
|
+
}
|
|
835
|
+
//================== END Optional Keys ====================//
|
|
836
|
+
|
|
837
|
+
//Should display error to console
|
|
838
|
+
if (errorList.length && !silent) {
|
|
839
|
+
let txt = '⚠️ You have the following Errors:'
|
|
840
|
+
console.group(`%c ${txt}`, 'background:#ffc13a7d')
|
|
841
|
+
errorInConsole.forEach((err) => console.warn(err))
|
|
842
|
+
console.groupEnd()
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
return errorList
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* @description - Method validate the definition of SVG data.
|
|
850
|
+
* @param {Array || Object } SVGData - the data defining the SVG to render
|
|
851
|
+
* @return true - if valid
|
|
852
|
+
* */
|
|
853
|
+
|
|
854
|
+
const validateSvgDefinition = (SVGData) => {
|
|
855
|
+
//Should be Array of Object
|
|
856
|
+
if (SVGData.constructor !== Array && SVGData.constructor !== Object)
|
|
857
|
+
throw new Error('Unsupported Type for SVG data')
|
|
858
|
+
let Errors = []
|
|
859
|
+
let SVGDef = SVGData.constructor == Object ? new Array(SVGData) : SVGData
|
|
860
|
+
//Should validate the entries for each SVG definition as the required entries
|
|
861
|
+
|
|
862
|
+
for (const s_def of SVGDef) {
|
|
863
|
+
let i = SVGDef.indexOf(s_def)
|
|
864
|
+
let stringType = ['id', 'viewBox']
|
|
865
|
+
let arrayType = ['paths']
|
|
866
|
+
let { errorInConsole: errCons } = validateObjType(
|
|
867
|
+
s_def,
|
|
868
|
+
{
|
|
869
|
+
stringType,
|
|
870
|
+
arrayType
|
|
871
|
+
},
|
|
872
|
+
'viewBox',
|
|
873
|
+
`SVG ${i + 1}`
|
|
874
|
+
)
|
|
875
|
+
Errors.push(...errCons)
|
|
876
|
+
if (errCons.length) {
|
|
877
|
+
errCons.forEach((err) => console.warn(err))
|
|
878
|
+
break
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
//Should validate that each element in the path attributes is an object of type string and has the id attribute
|
|
882
|
+
|
|
883
|
+
for (const _path of s_def.paths) {
|
|
884
|
+
let index = s_def.paths.indexOf(_path)
|
|
885
|
+
if (_path.constructor !== Object)
|
|
886
|
+
throw Error(
|
|
887
|
+
`Unexpected definition for path ${index + 1} in SVG ${i + 1}. Expecting Object but received ${typeof _path}`
|
|
888
|
+
)
|
|
889
|
+
|
|
890
|
+
let stringType = ['d']
|
|
891
|
+
|
|
892
|
+
let { errorInConsole: errCons } = validateObjType(
|
|
893
|
+
_path,
|
|
894
|
+
{
|
|
895
|
+
stringType
|
|
896
|
+
},
|
|
897
|
+
null,
|
|
898
|
+
`SVG path ${index + 1}`
|
|
899
|
+
)
|
|
900
|
+
Errors.push(...errCons)
|
|
901
|
+
if (errCons.length) {
|
|
902
|
+
errCons.forEach((err) => console.warn(err))
|
|
903
|
+
break
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
//validate each entries in path
|
|
907
|
+
for (const _key in _path) {
|
|
908
|
+
if (_key == 'd') continue //skip
|
|
909
|
+
//all keys in path should be of type String and not empty
|
|
910
|
+
let stringType = [_key]
|
|
911
|
+
|
|
912
|
+
let { errorInConsole: errCons } = validateObjType(
|
|
913
|
+
_path,
|
|
914
|
+
{
|
|
915
|
+
stringType
|
|
916
|
+
},
|
|
917
|
+
null,
|
|
918
|
+
`SVG path ${index + 1}`
|
|
919
|
+
)
|
|
920
|
+
Errors.push(...errCons)
|
|
921
|
+
if (errCons.length) {
|
|
922
|
+
errCons.forEach((err) => console.log(err))
|
|
923
|
+
break
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
if (Errors.length) throw new Error('Error SVG')
|
|
930
|
+
return true
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* @description - Method validate the definition data forthe quiz.
|
|
935
|
+
* @param {Object} data - the data defining the SVG to render
|
|
936
|
+
* @return true - if valid
|
|
937
|
+
* */
|
|
938
|
+
const validateQuizData = (data) => {
|
|
939
|
+
let errors
|
|
940
|
+
let stringType = ['ennonce', 'id', 'type_question', 'texte_base']
|
|
941
|
+
let arrayType = ['choix_reponse', 'solution']
|
|
942
|
+
let objectType = ['retroaction']
|
|
943
|
+
let numberType = ['valeur_point', 'max_tentative']
|
|
944
|
+
let optionalArgs = ['valeur_point', 'max_tentative', 'texte_base']
|
|
945
|
+
|
|
946
|
+
errors = validateObjType(
|
|
947
|
+
data,
|
|
948
|
+
{ stringType, arrayType, objectType, numberType },
|
|
949
|
+
optionalArgs,
|
|
950
|
+
'quizData'
|
|
951
|
+
)
|
|
952
|
+
|
|
953
|
+
let hasError = errors.errorInConsole.length || errors.errorList.length
|
|
954
|
+
|
|
955
|
+
if (hasError) return errors
|
|
956
|
+
|
|
957
|
+
//validate Containt for retroaction
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
// if(data.solution !=null){
|
|
961
|
+
// console.log('ici')
|
|
962
|
+
// }else{
|
|
963
|
+
// console.log('la')
|
|
964
|
+
// }
|
|
965
|
+
|
|
966
|
+
switch (true) {
|
|
967
|
+
case data.retroaction != null:
|
|
968
|
+
objectType = ['retro_positive', 'retro_negative', 'retro_neutre']
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
errors = validateObjType(
|
|
972
|
+
data.retroaction,
|
|
973
|
+
{ objectType },
|
|
974
|
+
null,
|
|
975
|
+
'quizData retraoction'
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
hasError = errors.errorInConsole.length || errors.errorList.length
|
|
979
|
+
|
|
980
|
+
//console.log(hasError)
|
|
981
|
+
if (hasError) return errors
|
|
982
|
+
|
|
983
|
+
// Validate containt of retroaction attributes
|
|
984
|
+
stringType = ['title', 'hypertext']
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
for (const key of Object.keys(data.retroaction)) {
|
|
988
|
+
|
|
989
|
+
if(key == "retro_neutre") continue //skip
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
|
|
993
|
+
errors = validateObjType(
|
|
994
|
+
data.retroaction[key],
|
|
995
|
+
{ stringType },
|
|
996
|
+
null,
|
|
997
|
+
key
|
|
998
|
+
)
|
|
999
|
+
|
|
1000
|
+
hasError = errors.errorInConsole.length || errors.errorList.length
|
|
1001
|
+
|
|
1002
|
+
if (hasError) return errors
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
break
|
|
1006
|
+
}
|
|
1007
|
+
return errors
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
export {
|
|
1011
|
+
validateObjType,
|
|
1012
|
+
validateVideoData,
|
|
1013
|
+
validateAudioData,
|
|
1014
|
+
validatefileContent,
|
|
1015
|
+
validateAppContent,
|
|
1016
|
+
validateSvgDefinition,
|
|
1017
|
+
validateQuizData
|
|
1018
|
+
}
|