fcad-core-dragon 2.0.0-beta.0 β 2.0.0-beta.1
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/README.md +1 -1
- package/package.json +7 -9
- package/src/$locales/en.json +39 -15
- package/src/$locales/fr.json +48 -23
- package/src/components/AppBase.vue +245 -266
- package/src/components/AppBaseErrorDisplay.vue +29 -0
- package/src/components/AppBaseModule.vue +485 -232
- package/src/components/AppBasePage.vue +28 -54
- package/src/components/AppCompBif.vue +120 -0
- package/src/components/AppCompBranchButtons.vue +31 -30
- package/src/components/AppCompButtonProgress.vue +35 -46
- package/src/components/AppCompCarousel.vue +154 -247
- package/src/components/AppCompJauge.vue +1 -2
- package/src/components/AppCompMediaPlayer.vue +106 -74
- package/src/components/AppCompMenu.vue +87 -81
- package/src/components/AppCompMenuItem.vue +48 -90
- package/src/components/AppCompNavigation.vue +949 -0
- package/src/components/AppCompNoteCall.vue +126 -0
- package/src/components/AppCompNoteCredit.vue +164 -0
- package/src/components/AppCompPlayBar.vue +864 -1085
- package/src/components/AppCompPopUp.vue +26 -27
- package/src/components/AppCompPopover.vue +27 -0
- package/src/components/AppCompQuiz.vue +27 -36
- package/src/components/AppCompQuizRecall.vue +250 -0
- package/src/components/AppCompSVG.vue +309 -0
- package/src/components/AppCompSettingsMenu.vue +1 -0
- package/src/components/AppCompTableOfContent.vue +140 -85
- package/src/components/AppCompTranscript.vue +19 -0
- package/src/components/AppCompVideoPlayer.vue +336 -0
- package/src/components/BaseModule.vue +24 -105
- package/src/main.js +18 -9
- package/src/mixins/$pageMixins.js +106 -28
- package/src/mixins/timerMixin.js +31 -7
- package/src/module/store.js +33 -12
- package/src/module/xapi/Crypto/encoders/Hex.js +2 -1
- package/src/module/xapi/wrapper.js +4 -4
- package/src/plugins/gsap.js +4 -1
- package/src/plugins/helper.js +53 -18
- package/src/plugins/idb.js +1 -0
- package/src/public/index.html +1 -1
- package/src/router/index.js +41 -0
- package/src/router/routes.js +337 -0
- package/src/routes_bckp.js +313 -0
- package/src/routes_static.js +344 -0
- package/src/shared/generalfuncs.js +79 -4
- package/src/shared/validators.js +249 -0
- package/src/components/AppCompNavigationFull.vue +0 -1791
- package/src/components/AppCompToolTip.vue +0 -94
- package/src/routes.js +0 -734
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import Router from 'vue-router'
|
|
2
|
+
import AppCompViewDisplay from './components/AppCompViewDisplay.vue'
|
|
3
|
+
import store from './module/store'
|
|
4
|
+
import { fileAssets } from './shared/generalfuncs'
|
|
5
|
+
// const _path = require('path')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The router Module defines the routes of the App by:
|
|
9
|
+
* loading the required files for module and activities pages,
|
|
10
|
+
* dynamically creating the navigation route of module base on the file in VIEWS folder
|
|
11
|
+
* dynamically creating the navigation routes of activities and branchings base on the files contained in the MODULE
|
|
12
|
+
* Creating Redirection routes for navigation error
|
|
13
|
+
* Adding the pages for the module in the STORE
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const _routes = [] // routes of the app
|
|
17
|
+
let errorType = null
|
|
18
|
+
let newRoute = null // wrapper for module routes
|
|
19
|
+
const _allFiles = fileAssets.getActivities()
|
|
20
|
+
let mappedFiles = fileAssets.buildMapTree(_allFiles)
|
|
21
|
+
let menuCreated = false
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 1- Preparing the router to catch failing navigation error from browser by
|
|
25
|
+
* Redefining the Router push method
|
|
26
|
+
* ref: https://stackoverflow.com/questions/57837758/ navigationduplicated-navigating-to-current-location-search-is-not-allowed
|
|
27
|
+
*/
|
|
28
|
+
const originalPush = Router.prototype.push
|
|
29
|
+
Router.prototype.push = function push(location) {
|
|
30
|
+
return originalPush.call(this, location).catch((err) => err)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Creating 1st route: redirection for none existing route to home(Module)
|
|
34
|
+
_routes.push({
|
|
35
|
+
path: '*',
|
|
36
|
+
redirect: {
|
|
37
|
+
name: '404'
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 2 - Creating the 2nd route: The App module route
|
|
43
|
+
*/
|
|
44
|
+
// Load all the files in the VIEWS folder
|
|
45
|
+
|
|
46
|
+
const defaultRoute = {
|
|
47
|
+
path: '/',
|
|
48
|
+
component: AppCompViewDisplay,
|
|
49
|
+
children: []
|
|
50
|
+
}
|
|
51
|
+
errorType = false
|
|
52
|
+
|
|
53
|
+
const staticSummary = {
|
|
54
|
+
path: '/menu',
|
|
55
|
+
component: () =>
|
|
56
|
+
import(/* webpackChunkName: "menu" */ `@/views/SummaryView.vue`),
|
|
57
|
+
name: 'menu',
|
|
58
|
+
meta: {
|
|
59
|
+
type: 'page_menu'
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const staticModule = {
|
|
64
|
+
path: '',
|
|
65
|
+
component: () =>
|
|
66
|
+
import(/* webpackChunkName: "home" */ `@/views/ModuleView.vue`),
|
|
67
|
+
name: 'module',
|
|
68
|
+
children: [
|
|
69
|
+
{
|
|
70
|
+
path: 'introduction',
|
|
71
|
+
component: AppCompViewDisplay,
|
|
72
|
+
children: [
|
|
73
|
+
{
|
|
74
|
+
path: 'page-1',
|
|
75
|
+
name: 'introduction',
|
|
76
|
+
component: () =>
|
|
77
|
+
import(/* webpackChunkName: "gpNested" */ `@/module/A02/P01.vue`),
|
|
78
|
+
meta: {
|
|
79
|
+
id: 'P01',
|
|
80
|
+
activity_ref: 'A00',
|
|
81
|
+
type: 'normal',
|
|
82
|
+
parent: {
|
|
83
|
+
_ref: 'P01',
|
|
84
|
+
_path: 'introduction',
|
|
85
|
+
_namedRoute: 'introduction'
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
meta: {
|
|
91
|
+
id: 'A00',
|
|
92
|
+
children: [
|
|
93
|
+
{
|
|
94
|
+
_ref: 'P01',
|
|
95
|
+
_path: 'page-1',
|
|
96
|
+
_namedRoute: 'introduction'
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
path: 'activite-1',
|
|
103
|
+
component: AppCompViewDisplay,
|
|
104
|
+
children: [
|
|
105
|
+
{
|
|
106
|
+
path: 'page-1',
|
|
107
|
+
name: 'activite_1',
|
|
108
|
+
component: () =>
|
|
109
|
+
import(/* webpackChunkName: "gpNested" */ `@/module/A01/P01.vue`),
|
|
110
|
+
meta: {
|
|
111
|
+
id: 'P01',
|
|
112
|
+
activity_ref: 'A01',
|
|
113
|
+
type: 'normal',
|
|
114
|
+
parent: {
|
|
115
|
+
_ref: 'P01',
|
|
116
|
+
_path: 'activite-1',
|
|
117
|
+
_namedRoute: 'activity_1'
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
path: 'page-2',
|
|
123
|
+
name: 'activite_1.page_2',
|
|
124
|
+
component: () =>
|
|
125
|
+
import(/* webpackChunkName: "gpNested" */ `@/module/A01/P02.vue`),
|
|
126
|
+
meta: {
|
|
127
|
+
id: 'P02',
|
|
128
|
+
activity_ref: 'A01',
|
|
129
|
+
type: 'branching',
|
|
130
|
+
parent: {
|
|
131
|
+
_ref: 'P01',
|
|
132
|
+
_path: 'activite-1',
|
|
133
|
+
_namedRoute: 'activity_1'
|
|
134
|
+
},
|
|
135
|
+
children: [
|
|
136
|
+
{
|
|
137
|
+
_ref: 'P02_E01',
|
|
138
|
+
_path: 'branch-1',
|
|
139
|
+
_namedRoute: 'A01.page_2.branching_1.branch_1'
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
_ref: 'P02_E02',
|
|
143
|
+
_path: 'branch-2',
|
|
144
|
+
_namedRoute: 'A01.page_2.branching_1.branch_2'
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
_ref: 'P02_E03',
|
|
148
|
+
_path: 'branch-3',
|
|
149
|
+
_namedRoute: 'A01.page_2.branching_1.branch_3'
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
},
|
|
153
|
+
children: [
|
|
154
|
+
{
|
|
155
|
+
path: 'branch-1',
|
|
156
|
+
name: 'A01.page_2.branching_1.branch_1',
|
|
157
|
+
component: () =>
|
|
158
|
+
import(
|
|
159
|
+
/* webpackChunkName: "gpNested" */ `@/module/A01/P02_E01.vue`
|
|
160
|
+
),
|
|
161
|
+
meta: {
|
|
162
|
+
id: 'P02_E01',
|
|
163
|
+
activity_ref: 'A01',
|
|
164
|
+
type: 'branch',
|
|
165
|
+
branching_ref: 'A01.P02.branching_1',
|
|
166
|
+
parent: {
|
|
167
|
+
_ref: 'P02',
|
|
168
|
+
_path: 'activite-1.page-2',
|
|
169
|
+
_namedRoute: 'activity_1.page_2'
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
path: 'branch-2',
|
|
175
|
+
name: 'A01.page_2.branching_1.branch_2',
|
|
176
|
+
component: () =>
|
|
177
|
+
import(
|
|
178
|
+
/* webpackChunkName: "gpNested" */ `@/module/A01/P02_E02.vue`
|
|
179
|
+
),
|
|
180
|
+
meta: {
|
|
181
|
+
id: 'P02_E02',
|
|
182
|
+
activity_ref: 'A01',
|
|
183
|
+
type: 'branch',
|
|
184
|
+
branching_ref: 'A01.P02.branching_1',
|
|
185
|
+
parent: {
|
|
186
|
+
_ref: 'P02',
|
|
187
|
+
_path: 'activite-1.page-2',
|
|
188
|
+
_namedRoute: 'activity_1.page_2'
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
path: 'branch-3',
|
|
194
|
+
name: 'A01.page_2.branching_1.branch_3',
|
|
195
|
+
component: () =>
|
|
196
|
+
import(
|
|
197
|
+
/* webpackChunkName: "gpNested" */ `@/module/A01/P02_E03.vue`
|
|
198
|
+
),
|
|
199
|
+
meta: {
|
|
200
|
+
id: 'P02_E03',
|
|
201
|
+
activity_ref: 'A01',
|
|
202
|
+
type: 'branch',
|
|
203
|
+
branching_ref: 'A01.P02.branching_1',
|
|
204
|
+
parent: {
|
|
205
|
+
_ref: 'P02',
|
|
206
|
+
_path: 'activite-1.page-2',
|
|
207
|
+
_namedRoute: 'activity_1.page_2'
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
path: 'page-3',
|
|
215
|
+
name: 'activite_1.page_3',
|
|
216
|
+
component: () =>
|
|
217
|
+
import(/* webpackChunkName: "gpNested" */ `@/module/A01/P03.vue`),
|
|
218
|
+
meta: {
|
|
219
|
+
id: 'P03',
|
|
220
|
+
activity_ref: 'A01',
|
|
221
|
+
type: 'normal',
|
|
222
|
+
parent: {
|
|
223
|
+
_ref: 'P01',
|
|
224
|
+
_path: 'activite-1',
|
|
225
|
+
_namedRoute: 'activity_1'
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
],
|
|
230
|
+
meta: {
|
|
231
|
+
id: 'A01',
|
|
232
|
+
children: [
|
|
233
|
+
{
|
|
234
|
+
_ref: 'P01',
|
|
235
|
+
_path: 'page-1',
|
|
236
|
+
_namedRoute: 'activite_1'
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
_ref: 'P02',
|
|
240
|
+
_path: 'page-2',
|
|
241
|
+
_namedRoute: 'activite_1.page_2'
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
_ref: 'P03',
|
|
245
|
+
_path: 'page-3',
|
|
246
|
+
_namedRoute: 'activite_1.page_3'
|
|
247
|
+
}
|
|
248
|
+
]
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
path: 'activite-2',
|
|
253
|
+
component: AppCompViewDisplay,
|
|
254
|
+
children: [
|
|
255
|
+
{
|
|
256
|
+
path: 'page-1',
|
|
257
|
+
name: 'activite_2',
|
|
258
|
+
component: () =>
|
|
259
|
+
import(/* webpackChunkName: "gpNested" */ `@/module/A02/P01.vue`),
|
|
260
|
+
meta: {
|
|
261
|
+
id: 'P01',
|
|
262
|
+
activity_ref: 'A02',
|
|
263
|
+
type: 'normal',
|
|
264
|
+
parent: {
|
|
265
|
+
_ref: 'P01',
|
|
266
|
+
_path: 'activite-2',
|
|
267
|
+
_namedRoute: 'activity_2'
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
],
|
|
272
|
+
meta: {
|
|
273
|
+
id: 'A02',
|
|
274
|
+
children: [
|
|
275
|
+
{
|
|
276
|
+
_ref: 'P01',
|
|
277
|
+
_path: 'page-1',
|
|
278
|
+
_namedRoute: 'activite_2'
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
],
|
|
284
|
+
meta: {
|
|
285
|
+
id: 'mod_00100',
|
|
286
|
+
type: 'normal',
|
|
287
|
+
children: [
|
|
288
|
+
{
|
|
289
|
+
_ref: 'A01',
|
|
290
|
+
_path: 'introduction',
|
|
291
|
+
_namedRoute: 'introduction'
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
_ref: 'A01',
|
|
295
|
+
_path: 'activite-1',
|
|
296
|
+
_namedRoute: 'activite_1'
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
_ref: 'A02',
|
|
300
|
+
_path: 'activite-2',
|
|
301
|
+
_namedRoute: 'activite_2'
|
|
302
|
+
}
|
|
303
|
+
]
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
defaultRoute.children.push(staticModule)
|
|
307
|
+
defaultRoute.children.push(staticSummary)
|
|
308
|
+
if (!errorType) {
|
|
309
|
+
// add the newRoute to the routes array
|
|
310
|
+
_routes.push(defaultRoute)
|
|
311
|
+
} else {
|
|
312
|
+
// create Route for error non-existing files
|
|
313
|
+
_routes.push({
|
|
314
|
+
path: '/',
|
|
315
|
+
component: () =>
|
|
316
|
+
import(
|
|
317
|
+
/* webpackChunkName: "gpNested" */ `./components/AppBaseErrorDisplay.vue`
|
|
318
|
+
),
|
|
319
|
+
props: {
|
|
320
|
+
errorMessage: errorType
|
|
321
|
+
}
|
|
322
|
+
})
|
|
323
|
+
}
|
|
324
|
+
// Routes for errors : 404
|
|
325
|
+
_routes.push({
|
|
326
|
+
path: '/404',
|
|
327
|
+
name: '404',
|
|
328
|
+
component: () =>
|
|
329
|
+
import(
|
|
330
|
+
/* webpackChunkName: "gpNested" */ `./components/AppBaseErrorDisplay.vue`
|
|
331
|
+
),
|
|
332
|
+
props: {
|
|
333
|
+
errorMessage: '404'
|
|
334
|
+
}
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
// Add register Module pages to store
|
|
338
|
+
store.state.thisModule.activities = mappedFiles
|
|
339
|
+
|
|
340
|
+
// exporting routes object
|
|
341
|
+
export default {
|
|
342
|
+
base: process.env.BASE_URL,
|
|
343
|
+
routes: [..._routes]
|
|
344
|
+
}
|
|
@@ -2,16 +2,16 @@ const allfile = require.context('@/', true, /\.vue$/) //get all .vue file at the
|
|
|
2
2
|
|
|
3
3
|
const fileAssets = {
|
|
4
4
|
// return the collection of all the files in the project directory
|
|
5
|
-
allFiles: () => allfile,
|
|
5
|
+
allFiles: () => allfile.keys(),
|
|
6
6
|
|
|
7
7
|
// Return all the file in './views' with the Name Module
|
|
8
|
-
|
|
9
|
-
return
|
|
8
|
+
getViews: () => {
|
|
9
|
+
return fileAssets.allFiles().filter((file) => file.startsWith('./views'))
|
|
10
10
|
},
|
|
11
11
|
// return all files that are in the folder './src/module' of the project with name respecting following condition:
|
|
12
12
|
// must start with a capital P followed by a digit (P0, P1, P2...) and not contain keyword "copy"
|
|
13
13
|
getActivities: () => {
|
|
14
|
-
return
|
|
14
|
+
return fileAssets.allFiles().filter((file) => {
|
|
15
15
|
if (
|
|
16
16
|
file.startsWith('./module/A') &&
|
|
17
17
|
/^P[0-9]{2,3}/.test(file.split('/')[3]) &&
|
|
@@ -107,6 +107,81 @@ const fileAssets = {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
return err
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @description Validator for the content of menu setting file
|
|
114
|
+
* @param {String} a- array of file for use case
|
|
115
|
+
* @param {Object} [requiredArgs] list of arguments to include consider in validation ()
|
|
116
|
+
*/
|
|
117
|
+
buildMapTree: (a) => {
|
|
118
|
+
// Load files in module folder
|
|
119
|
+
if (a.length < 0) return
|
|
120
|
+
|
|
121
|
+
const mapTree = new Map()
|
|
122
|
+
// There is a file in the module folder
|
|
123
|
+
|
|
124
|
+
a.forEach((key) => {
|
|
125
|
+
const fileRef = key.replace(/(\.\/)/g, '')
|
|
126
|
+
const splitted = fileRef.split('/')
|
|
127
|
+
const activityName = splitted[1]
|
|
128
|
+
const fileName = splitted[splitted.length - 1].replace(/(\.vue)/g, '')
|
|
129
|
+
const fileContent = fileAssets.fetchFileContent(`./${fileRef}`).default
|
|
130
|
+
|
|
131
|
+
if (!Object.keys(fileContent).includes('data')) return
|
|
132
|
+
// Handling single page type
|
|
133
|
+
// adding the page in a map for the Pages
|
|
134
|
+
|
|
135
|
+
// Add the key in the map for the routes if it is not in the map, with its data as new Map;
|
|
136
|
+
if (!mapTree.get(activityName)) {
|
|
137
|
+
mapTree.set(activityName, new Map())
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (fileName.length === 3) {
|
|
141
|
+
mapTree.get(activityName).set(fileName, {
|
|
142
|
+
ref: fileRef,
|
|
143
|
+
content: fileContent.data()
|
|
144
|
+
}) // add entry for the page
|
|
145
|
+
}
|
|
146
|
+
// Handleling Groupe page type
|
|
147
|
+
else if (fileName.length > 3 && fileName.includes('_')) {
|
|
148
|
+
const keyToFind = fileName.split('_', 1)[0] // Pxx
|
|
149
|
+
const KeyToAdd = fileName.split('_')[1] // Exx
|
|
150
|
+
|
|
151
|
+
// // search for the page key in the map
|
|
152
|
+
if (!mapTree.get(activityName).has(keyToFind)) return
|
|
153
|
+
|
|
154
|
+
// save a reference for the value of the key
|
|
155
|
+
const tempSave = mapTree.get(activityName).get(keyToFind)
|
|
156
|
+
|
|
157
|
+
// transform value of found key to a new map
|
|
158
|
+
if (!mapTree.get(activityName).get(keyToFind).size) {
|
|
159
|
+
mapTree.get(activityName).set(keyToFind, new Map())
|
|
160
|
+
// Update reference of key's
|
|
161
|
+
mapTree
|
|
162
|
+
.get(activityName)
|
|
163
|
+
.get(keyToFind)
|
|
164
|
+
.set(keyToFind, tempSave)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Add page EXX in Map if it is not already added
|
|
168
|
+
if (
|
|
169
|
+
!mapTree
|
|
170
|
+
.get(activityName)
|
|
171
|
+
.get(keyToFind)
|
|
172
|
+
.get(KeyToAdd)
|
|
173
|
+
)
|
|
174
|
+
mapTree
|
|
175
|
+
.get(activityName)
|
|
176
|
+
.get(keyToFind)
|
|
177
|
+
.set(fileName, {
|
|
178
|
+
ref: fileRef,
|
|
179
|
+
content: fileContent.data()
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
return mapTree
|
|
110
185
|
}
|
|
111
186
|
}
|
|
112
187
|
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description Validator for the content of menu setting file
|
|
3
|
+
* @param {String} fName- name of the file for use case
|
|
4
|
+
* @param {Object} fData: file's data to validate
|
|
5
|
+
* @param {Object} [requiredArgs] list of arguments to include consider in validation ()
|
|
6
|
+
*/
|
|
7
|
+
const validatefileContent = (fName, fData, requiredArgs = {}) => {
|
|
8
|
+
let err = null
|
|
9
|
+
if (process.env.NODE_ENV === 'development') {
|
|
10
|
+
switch (fName) {
|
|
11
|
+
case 'menuSettings': {
|
|
12
|
+
const { keys4Activity, keys4Anchors } = requiredArgs
|
|
13
|
+
|
|
14
|
+
//*validate that data is an {Object}. if Not send error message
|
|
15
|
+
if (fData.constructor !== Object)
|
|
16
|
+
err = 'π₯Invalid file provided for menu settings'
|
|
17
|
+
|
|
18
|
+
if (Object.entries(fData).length > 0) {
|
|
19
|
+
const content = Object.entries(fData)
|
|
20
|
+
|
|
21
|
+
for (let el of content) {
|
|
22
|
+
// validate that the content of each entry is an object
|
|
23
|
+
if (el[1].constructor !== Object || !Object.keys(el[1]).length) {
|
|
24
|
+
err = `π₯ invalid data provided for key π ${el[0]} π in β‘ menu.setting.js \n π©Must be of type {Object}`
|
|
25
|
+
break
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Validate that each entry has the required key
|
|
29
|
+
if (!err) {
|
|
30
|
+
for (let el of content) {
|
|
31
|
+
const entry = el[1]
|
|
32
|
+
for (let k of keys4Activity) {
|
|
33
|
+
if (!entry[k]) {
|
|
34
|
+
err = `π₯ Missing π ${k} π in ${el[0]} in β‘ menu.setting.js \n π©Allowed indexes are: π ${keys4Activity}`
|
|
35
|
+
break
|
|
36
|
+
} else {
|
|
37
|
+
//validate that each entry as correct value type
|
|
38
|
+
switch (k) {
|
|
39
|
+
case 'anchors':
|
|
40
|
+
if (entry[k].constructor !== Array)
|
|
41
|
+
err = `π₯ Invalid anchors declaration for π ${el[0]} π in β‘ menu.setting.j \n π©Must be of type {Array}`
|
|
42
|
+
else {
|
|
43
|
+
const anchors = entry.anchors
|
|
44
|
+
|
|
45
|
+
for (let a of anchors) {
|
|
46
|
+
//trow error if numbers of keys are not the same as required
|
|
47
|
+
const a_numb = anchors.indexOf(a) + 1
|
|
48
|
+
if (Object.keys(a).length !== keys4Anchors.length) {
|
|
49
|
+
err = `π₯ Invalid declaration in πanchor ${a_numb}π for β‘ ${el[0]} in β‘ menu.setting.js \n π© Allowed indexes are: π ${keys4Anchors}`
|
|
50
|
+
break
|
|
51
|
+
}
|
|
52
|
+
// Validated that required keys condition and type is met
|
|
53
|
+
for (let k of keys4Anchors) {
|
|
54
|
+
if (!a[k]) {
|
|
55
|
+
err = `π₯ Missing π ${k} π for anchor ${a_numb} β‘ ${el[0]} β‘ menu.setting.js \n π© Allowed indexes are: π ${keys4Anchors}`
|
|
56
|
+
} else if (a[k].constructor !== String) {
|
|
57
|
+
err = `π₯ Invalid π ${k} π declaration for anchor ${a_numb} β‘ ${el[0]} β‘ menu.setting.js \n π© Must be of type {String}`
|
|
58
|
+
}
|
|
59
|
+
if (err) break
|
|
60
|
+
}
|
|
61
|
+
if (err) break
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
break
|
|
66
|
+
default:
|
|
67
|
+
if (entry[k].constructor !== String)
|
|
68
|
+
err = `Invalid π ${k} π declaration for β‘ ${el[0]} in β‘ menu.setting.js \n π© Must be of type {String}`
|
|
69
|
+
break
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (err) break
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
break
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return err
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @description Validator for the content of menu setting file
|
|
87
|
+
* @param {Object} data- Object definition to validate
|
|
88
|
+
**/
|
|
89
|
+
const validateVideoData = (data) => {
|
|
90
|
+
const errorList = []
|
|
91
|
+
if (process.env.NODE_ENV === 'development') {
|
|
92
|
+
let errStringInConsole = null
|
|
93
|
+
let errString = null
|
|
94
|
+
const expectedKeys = ['mSources', 'mSubtitles', 'mPoster', 'mTranscript']
|
|
95
|
+
|
|
96
|
+
if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
|
|
97
|
+
errStringInConsole = `\n π₯ Invalid declaration for video element`
|
|
98
|
+
console.warn(
|
|
99
|
+
`%c WARNING!>>> VIDEO: ${errStringInConsole}`,
|
|
100
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
101
|
+
)
|
|
102
|
+
errString = `Declaration invalide pour Objet video.`
|
|
103
|
+
errorList.push(errString)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (!data['mSources']) {
|
|
107
|
+
errStringInConsole = ` Missing π mSources π declaration for video element`
|
|
108
|
+
|
|
109
|
+
errString = `l'Attribut π mSources π pour l'Objet video n'est pas defini. `
|
|
110
|
+
console.warn(
|
|
111
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
112
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
113
|
+
)
|
|
114
|
+
errorList.push(errString)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
//Start validation of keys in data
|
|
118
|
+
if (!errString) {
|
|
119
|
+
expectedKeys.forEach((k) => {
|
|
120
|
+
if (!data[k] && k !== 'mSources') return
|
|
121
|
+
|
|
122
|
+
switch (k) {
|
|
123
|
+
case 'mSources':
|
|
124
|
+
if (
|
|
125
|
+
data['mSources'].constructor !== Array ||
|
|
126
|
+
data['mSources'].length < 1
|
|
127
|
+
) {
|
|
128
|
+
errStringInConsole =
|
|
129
|
+
'\n π₯ Invalid type declaration for mSources.\n π© Must be of type Array'
|
|
130
|
+
|
|
131
|
+
errString = `l'Attribut π mSources π pour le media doit Γͺtre de type Array`
|
|
132
|
+
|
|
133
|
+
errorList.push(errString)
|
|
134
|
+
console.warn(
|
|
135
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
136
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
break
|
|
140
|
+
|
|
141
|
+
case 'mSubtitles':
|
|
142
|
+
{
|
|
143
|
+
//Validate required keys in Subtitle definition
|
|
144
|
+
let expectedKeys = ['label', 'src', 'srclang']
|
|
145
|
+
//we only accept one subtitle and must be defined as an Object with 3 keys
|
|
146
|
+
if (
|
|
147
|
+
data['mSubtitles'].constructor !== Array ||
|
|
148
|
+
!data['mSubtitles'].length
|
|
149
|
+
) {
|
|
150
|
+
errStringInConsole = `\n π₯ Invalid type declaration for mSubtitles.\n π© Must be of type Array with at list one Object defined with: ${expectedKeys}`
|
|
151
|
+
|
|
152
|
+
errString = `l'Attribut π mSubtitles π doit Γͺtre de type Array avec au moins un Objet: {${expectedKeys}} `
|
|
153
|
+
|
|
154
|
+
console.warn(
|
|
155
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
156
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return errorList.push(errString)
|
|
160
|
+
}
|
|
161
|
+
//Validate definition for each Subtitle Object
|
|
162
|
+
for (const obj of data['mSubtitles']) {
|
|
163
|
+
const objIndex = data['mSubtitles'].indexOf(obj)
|
|
164
|
+
expectedKeys.forEach((expected) => {
|
|
165
|
+
if (!obj[expected]) {
|
|
166
|
+
errStringInConsole = `\n π₯ Missing key π ${expected} π for mSubtitles No.${objIndex +
|
|
167
|
+
1}.\n π© required keys are: ${expectedKeys} `
|
|
168
|
+
|
|
169
|
+
errString = `l'Attribut π ${expected} π pour le sous-titre No.${objIndex +
|
|
170
|
+
1} n'est pas dΓ©fini`
|
|
171
|
+
|
|
172
|
+
console.warn(
|
|
173
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
174
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
175
|
+
)
|
|
176
|
+
return errorList.push(errString)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Only none empty String type Accepted
|
|
180
|
+
if (
|
|
181
|
+
obj[expected].constructor === String &&
|
|
182
|
+
obj[expected].trim().length
|
|
183
|
+
)
|
|
184
|
+
return
|
|
185
|
+
|
|
186
|
+
errStringInConsole = `\n π₯ Invalid type declaration for π${expected}π in mSubtitles No.${objIndex +
|
|
187
|
+
1}.\n π© Must be none-empty String `
|
|
188
|
+
|
|
189
|
+
errString = `l'Attribut π${expected}π du sous-titre No.${objIndex +
|
|
190
|
+
1} doit Γͺtre de type String et ne peut pas Γͺtre vide. `
|
|
191
|
+
|
|
192
|
+
console.warn(
|
|
193
|
+
`%c WARNING!>>> ${errStringInConsole}`,
|
|
194
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
errorList.push(errString)
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
break
|
|
202
|
+
case 'mPoster':
|
|
203
|
+
//Only type String allowed and must not be empty
|
|
204
|
+
if (
|
|
205
|
+
data['mPoster'] &&
|
|
206
|
+
data['mPoster'].constructor == String &&
|
|
207
|
+
data['mPoster'].trim().length
|
|
208
|
+
)
|
|
209
|
+
return
|
|
210
|
+
|
|
211
|
+
errStringInConsole = `\n π₯ Invalid type declaration for π mPoster π.\n π© Must be none-empty String `
|
|
212
|
+
|
|
213
|
+
errString = `l'Attribut π mPoster π doit Γͺtre de type String et ne peut pas Γͺtre vide. `
|
|
214
|
+
|
|
215
|
+
errorList.push(errString)
|
|
216
|
+
console.warn(
|
|
217
|
+
`%c WARNING!>>> VIDEO: ${errStringInConsole}`,
|
|
218
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
break
|
|
222
|
+
case 'mTranscript':
|
|
223
|
+
//Only type String allowed and must not be empty
|
|
224
|
+
if (
|
|
225
|
+
data['mTranscript'] &&
|
|
226
|
+
data['mTranscript'].constructor == String &&
|
|
227
|
+
data['mTranscript'].trim().length
|
|
228
|
+
)
|
|
229
|
+
return
|
|
230
|
+
|
|
231
|
+
errStringInConsole = `\n π₯ Invalid type declaration for π mTranscript π .\n π© Must be none-empty String `
|
|
232
|
+
|
|
233
|
+
errString = `l'Attribut π mTranscript π doit Γͺtre de type String et ne peut pas Γͺtre vide. `
|
|
234
|
+
|
|
235
|
+
console.warn(
|
|
236
|
+
`%c WARNING!>>> VIDEO: ${errStringInConsole}`,
|
|
237
|
+
'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
|
|
238
|
+
)
|
|
239
|
+
errorList.push(errString)
|
|
240
|
+
|
|
241
|
+
break
|
|
242
|
+
}
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return errorList
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export { validateVideoData, validatefileContent }
|