fcad-core-dragon 2.0.0-beta.1 → 2.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/.editorconfig +33 -33
  2. package/.eslintignore +29 -29
  3. package/{.eslintrc.js → .eslintrc.cjs} +81 -86
  4. package/CHANGELOG +364 -364
  5. package/README.md +71 -71
  6. package/bk.scss +117 -0
  7. package/package.json +61 -63
  8. package/src/$locales/en.json +143 -179
  9. package/src/$locales/fr.json +105 -181
  10. package/src/assets/data/onboardingMessages.json +47 -47
  11. package/src/components/AppBase.vue +1054 -614
  12. package/src/components/AppBaseButton.vue +87 -63
  13. package/src/components/AppBaseErrorDisplay.vue +438 -420
  14. package/src/components/AppBaseFlipCard.vue +84 -83
  15. package/src/components/AppBaseModule.vue +1673 -1842
  16. package/src/components/AppBasePage.vue +779 -312
  17. package/src/components/AppBasePopover.vue +41 -0
  18. package/src/components/AppCompAudio.vue +234 -0
  19. package/src/components/AppCompBranchButtons.vue +552 -582
  20. package/src/components/AppCompButtonProgress.vue +126 -147
  21. package/src/components/AppCompCarousel.vue +298 -192
  22. package/src/components/AppCompInputCheckBoxNext.vue +195 -0
  23. package/src/components/AppCompInputDropdownNext.vue +159 -0
  24. package/src/components/AppCompInputRadioNext.vue +152 -0
  25. package/src/components/{AppCompInputTextBox.vue → AppCompInputTextNext.vue} +106 -91
  26. package/src/components/AppCompInputTextTableNext.vue +141 -0
  27. package/src/components/AppCompInputTextToFillDropdownNext.vue +230 -0
  28. package/src/components/{AppCompInputTextToFillText.vue → AppCompInputTextToFillNext.vue} +171 -164
  29. package/src/components/AppCompJauge.vue +74 -55
  30. package/src/components/AppCompMenu.vue +413 -209
  31. package/src/components/AppCompMenuItem.vue +228 -174
  32. package/src/components/AppCompNavigation.vue +960 -949
  33. package/src/components/AppCompNoteCall.vue +133 -126
  34. package/src/components/AppCompNoteCredit.vue +292 -164
  35. package/src/components/AppCompPlayBar.vue +1218 -1319
  36. package/src/components/AppCompPlayBarNext.vue +2052 -0
  37. package/src/components/AppCompPlayBarProgress.vue +82 -0
  38. package/src/components/AppCompPopUpNext.vue +503 -0
  39. package/src/components/{AppCompQuiz.vue → AppCompQuizNext.vue} +2904 -2989
  40. package/src/components/AppCompQuizRecall.vue +276 -250
  41. package/src/components/AppCompSVGNext.vue +347 -0
  42. package/src/components/AppCompSettingsMenu.vue +172 -171
  43. package/src/components/AppCompTableOfContent.vue +387 -264
  44. package/src/components/AppCompTranscript.vue +24 -19
  45. package/src/components/AppCompVideoPlayer.vue +368 -336
  46. package/src/components/AppCompViewDisplay.vue +6 -6
  47. package/src/components/BaseModule.vue +72 -67
  48. package/src/composables/useQuiz.js +206 -0
  49. package/src/externalComps/ModuleView.vue +22 -0
  50. package/src/externalComps/SummaryView.vue +91 -0
  51. package/src/main.js +272 -227
  52. package/src/mixins/$mediaMixins.js +819 -0
  53. package/src/mixins/timerMixin.js +155 -156
  54. package/src/module/stores/appStore.js +893 -0
  55. package/src/module/xapi/ADL.js +376 -339
  56. package/src/module/xapi/Crypto/Hasher.js +241 -241
  57. package/src/module/xapi/Crypto/WordArray.js +278 -278
  58. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  59. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -319
  60. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  61. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  62. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  63. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  64. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  65. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  66. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  67. package/src/module/xapi/Crypto/index.js +53 -53
  68. package/src/module/xapi/Statement/activity.js +47 -47
  69. package/src/module/xapi/Statement/agent.js +55 -55
  70. package/src/module/xapi/Statement/group.js +26 -26
  71. package/src/module/xapi/Statement/index.js +259 -259
  72. package/src/module/xapi/Statement/statement.js +253 -253
  73. package/src/module/xapi/Statement/statementRef.js +23 -23
  74. package/src/module/xapi/Statement/substatement.js +22 -22
  75. package/src/module/xapi/Statement/verb.js +36 -36
  76. package/src/module/xapi/activitytypes.js +17 -17
  77. package/src/module/xapi/launch.js +157 -157
  78. package/src/module/xapi/utils.js +167 -167
  79. package/src/module/xapi/verbs.js +294 -294
  80. package/src/module/xapi/wrapper.js +1963 -1890
  81. package/src/module/xapi/xapiStatement.js +444 -444
  82. package/src/plugins/bus.js +8 -3
  83. package/src/plugins/gsap.js +14 -17
  84. package/src/plugins/helper.js +308 -295
  85. package/src/plugins/i18n.js +44 -31
  86. package/src/plugins/idb.js +219 -212
  87. package/src/plugins/save.js +37 -37
  88. package/src/plugins/scorm.js +287 -287
  89. package/src/plugins/xapi.js +11 -11
  90. package/src/public/index.html +33 -21
  91. package/src/router/index.js +43 -41
  92. package/src/router/routes.js +312 -337
  93. package/src/shared/generalfuncs.js +210 -188
  94. package/src/shared/validators.js +1069 -249
  95. package/vite.config.js +27 -0
  96. package/.prettierrc.js +0 -5
  97. package/babel.config.js +0 -3
  98. package/src/components/AppBaseDragChoice.vue +0 -91
  99. package/src/components/AppBaseDropZone.vue +0 -112
  100. package/src/components/AppCompBif.vue +0 -120
  101. package/src/components/AppCompDragAndDrop.vue +0 -339
  102. package/src/components/AppCompInputAssociation.vue +0 -332
  103. package/src/components/AppCompInputCheckBox.vue +0 -227
  104. package/src/components/AppCompInputDropdown.vue +0 -184
  105. package/src/components/AppCompInputRadio.vue +0 -169
  106. package/src/components/AppCompInputTextTable.vue +0 -155
  107. package/src/components/AppCompInputTextToFillDropdown.vue +0 -255
  108. package/src/components/AppCompMediaPlayer.vue +0 -397
  109. package/src/components/AppCompPopUp.vue +0 -522
  110. package/src/components/AppCompPopover.vue +0 -27
  111. package/src/components/AppCompSVG.vue +0 -309
  112. package/src/mixins/$pageMixins.js +0 -459
  113. package/src/mixins/$quizMixins.js +0 -456
  114. package/src/module/store.js +0 -895
  115. package/src/plugins/timeManager.js +0 -77
  116. package/src/routes_bckp.js +0 -313
  117. package/src/routes_static.js +0 -344
  118. package/vue.config.js +0 -83
@@ -0,0 +1,893 @@
1
+ import { defineStore } from 'pinia'
2
+ import { fileAssets } from '../../shared/generalfuncs.js'
3
+ import { mappedFiles } from '../../router/routes.js'
4
+ const allFiles = fileAssets.getActivities()
5
+
6
+ export const useAppStore = defineStore('$appStore', {
7
+ //=======================STATE
8
+ state: () => {
9
+ return {
10
+ status: '',
11
+ anchorStatus: null,
12
+ thisModule: { activities: mappedFiles },
13
+ appDebugMode: false,
14
+ currentActivity: null,
15
+ currentPage: null,
16
+ currentBranchPage: null,
17
+ currentBranching: null,
18
+ currentSection: null,
19
+ currentPageMediaElements: [], // array containing all media of the page
20
+ currentMediaDuration: null,
21
+ currentPageTimeline: null,
22
+ bookmark: null,
23
+ currentBrowser: null,
24
+ isMobile: null,
25
+ deviceType: null,
26
+ introAcitve: null,
27
+ userMetaData: {},
28
+ appConfigs: null,
29
+ menuSetting: null,
30
+ dataNc: {},
31
+ ncIsOpen: false,
32
+ applicationSettings: {},
33
+ routeHistory: null,
34
+ mediaVolume: 0.5,
35
+ mediaMuted: false,
36
+ mediaSubtitles: false,
37
+ mediaPlaybarValues: {
38
+ subtitles: false,
39
+ volume: 0.5
40
+ },
41
+ navA11y: false,
42
+ showPrimaryCtrl: true,
43
+ showNavLeftCtrl: true,
44
+ showNavRightCtrl: true,
45
+ prevActivity: null,
46
+ nextActivity: null,
47
+ lrsConfig: null,
48
+ compStatusTracker: [],
49
+ dataFromServer: null,
50
+ errMenuSetting: null,
51
+ endPopUp: false
52
+ //_allFiles: [],
53
+ //allModuleRoutes: null
54
+ }
55
+ },
56
+ //=======================GETTERS
57
+ getters: {
58
+ getAppDebugMode: (state) => {
59
+ return state.appDebugMode
60
+ },
61
+ /**
62
+ * @description: Check if subtitles are enabled or not
63
+ */
64
+ getMediaSubtitles: (state) => {
65
+ return state.mediaSubtitles
66
+ },
67
+ /**
68
+ * @description: get media volume for the playbar
69
+ */
70
+ getMediaVolume: (state) => {
71
+ return state.mediaVolume
72
+ },
73
+
74
+ /**
75
+ * @description: get media muted for the playbar
76
+ */
77
+ getMediaMuted: (state) => {
78
+ return state.mediaMuted
79
+ },
80
+
81
+ /**
82
+ * @description: Check if automatic video playback is enabled in application settings
83
+ */
84
+
85
+ getAutoplayEnabled: (state) => {
86
+ return state.applicationSettings.autoplay
87
+ ? state.applicationSettings.autoplay
88
+ : null
89
+ },
90
+
91
+ /**
92
+ * @description: Check if onboarding is enabled in application settings
93
+ */
94
+ getOnboardingEnabled: (state) => {
95
+ return state.applicationSettings.onboarding
96
+ ? state.applicationSettings.onboarding
97
+ : null
98
+ },
99
+
100
+ /**
101
+ * @description: Check if auto-show subtitles is enabled in application settings
102
+ */
103
+ getShowSubtitles: (state) => {
104
+ return state.applicationSettings.subtitles
105
+ ? state.applicationSettings.subtitles
106
+ : null
107
+ },
108
+
109
+ /**
110
+ * @description: Getter to return the app status
111
+ */
112
+ getAppStatus: (state) => {
113
+ return state.compStatusTracker.length ? 'loading' : 'ready'
114
+ },
115
+
116
+ /**
117
+ * @description: Getter to return the compStatusTracker
118
+ */
119
+ getCompStatusTracker: (state) => {
120
+ return state.compStatusTracker
121
+ },
122
+
123
+ getErrorMenu: (state) => {
124
+ return state.errMenuSetting
125
+ },
126
+ getSkipMenu: (state) => {
127
+ if (state.appConfigs.noMenu) return state.appConfigs.noMenu
128
+ else return false
129
+ },
130
+ /**
131
+ * @description: Getter to return the content of a page
132
+ * @param {String} activity_Id: ID of the activity
133
+ * @param {String} page_Id: ID of the page
134
+ * @return {Object} : data of the search result
135
+ */
136
+ getPageData: (state) => {
137
+ return (activity_Id, page_Id) => {
138
+ //Must have activity_Id, page_Id params
139
+ if (!activity_Id || !page_Id)
140
+ throw new Error(
141
+ ` ⚠️ Invalid call to getPageData \n 🚩 Missing required arguments`
142
+ )
143
+
144
+ if (state.thisModule.activities.get(activity_Id)) {
145
+ let page
146
+
147
+ //handle the case for branching and normal pages
148
+ if (page_Id.length > 3) {
149
+ const splitted = page_Id.split('_')
150
+ page = state.thisModule.activities
151
+ .get(activity_Id)
152
+ .get(splitted[0])
153
+ .get(splitted[1])
154
+ .get(page_Id)
155
+ } else {
156
+ const p = state.thisModule.activities.get(activity_Id).get(page_Id)
157
+ if (p)
158
+ switch (p.constructor) {
159
+ //Branching root page
160
+ case Map:
161
+ page = p.get(page_Id)
162
+ break
163
+ //Normal page
164
+ default:
165
+ page = state.thisModule.activities
166
+ .get(activity_Id)
167
+ .get(page_Id)
168
+ break
169
+ }
170
+ }
171
+
172
+ if (page) return page.content
173
+ }
174
+
175
+ return false
176
+ }
177
+ },
178
+ /**
179
+ * @description: Getter to return an activity of the module. The getter will return all the activities if no id is given
180
+ * @param id: id of a activity to return
181
+ */
182
+ getAllActivities: (state) => {
183
+ return (id) => {
184
+ if (
185
+ !Object.keys(state.thisModule).length ||
186
+ !state.thisModule.activities
187
+ )
188
+ return {}
189
+
190
+ if (!id)
191
+ return new Object({
192
+ list: state.thisModule.activities,
193
+ pageSize: (() => {
194
+ let size = 0
195
+ state.thisModule.activities.forEach((value, key) => {
196
+ const aSize = allFiles.filter((f) =>
197
+ f.name.includes(key)
198
+ ).length
199
+ size = size + aSize
200
+ })
201
+ return size
202
+ })()
203
+ })
204
+
205
+ return new Object({
206
+ list: state.thisModule.activities.get(id),
207
+ pageSize: allFiles.filter((f) => f.includes(id)).length
208
+ })
209
+ }
210
+ },
211
+
212
+ getAnchorStatus: (state) => {
213
+ return state.anchorStatus
214
+ },
215
+ getIntroStatus() {
216
+ let activities = this.getAllActivities().list
217
+ return activities.get('A00') ? true : false
218
+ },
219
+ getConcluStatus() {
220
+ let activities = this.getAllActivities().list
221
+ return activities.get('A99') ? true : false
222
+ },
223
+ getModuleInfo: (state) => {
224
+ if (state.thisModule.info) return state.thisModule.info
225
+ else return state.thisModule
226
+ },
227
+ getAppConfigs: (state) => {
228
+ if (state.appConfigs) return state.appConfigs
229
+ else return false
230
+ },
231
+ getRouteHistory: (state) => {
232
+ return state.routeHistory ? state.routeHistory : []
233
+ },
234
+ hasMediaElOrTimeline: (state) => {
235
+ return state.currentPageMediaElements.length || state.currentPageTimeline
236
+ },
237
+ /**
238
+ * @description: Getter to return the current page
239
+ * @returns: page {Object}
240
+ */
241
+ getCurrentPage: (state) => {
242
+ let page = null
243
+ if (state.currentPage !== null) {
244
+ page = {
245
+ ...state.currentPage
246
+ }
247
+ page.mElements = state.currentPageMediaElements
248
+ page.timeline = state.currentPageTimeline
249
+ }
250
+ return page
251
+ },
252
+ /**
253
+ * @description: Getter to return the current branching page
254
+ * @returns: page {Object}
255
+ */
256
+ getCurrentBranching: (state) => {
257
+ return state.currentBranching
258
+ },
259
+ /**
260
+ * @description: Getter to return the current branch page in a branching
261
+ * @returns: page {Object}
262
+ */
263
+ getCurrentBranchPage: (state) => {
264
+ return state.currentBranchPage
265
+ },
266
+ /**
267
+ * @description: Getter to return the current Media Duration
268
+ */
269
+ getCurrentMediaDuration: (state) => {
270
+ return state.currentMediaDuration
271
+ },
272
+
273
+ /**
274
+ * @description: Getter to return the browser
275
+ */
276
+ getCurrentBrowser: (state) => {
277
+ return state.currentBrowser
278
+ },
279
+
280
+ getIsMobile: (state) => {
281
+ return state.isMobile
282
+ },
283
+ /**
284
+ * @description: Getter to return the type of device on which app is running (iosDevice, Android device or Desktop)
285
+ */
286
+ getDeviceType: (state) => {
287
+ return state.deviceType
288
+ },
289
+ /**
290
+ * @description: Getter to return the current enabled user settings
291
+ */
292
+ getApplicationSettings: (state) => {
293
+ return state.applicationSettings
294
+ },
295
+
296
+ /**
297
+ * @description: Getter to return the playbar values - Will return an attribut state by it key or the entire mediaPLaybar values
298
+ *
299
+ */
300
+ getMediaPlaybarValues: (state) => {
301
+ return (key) =>
302
+ key && state.mediaPlaybarValues[key]
303
+ ? state.mediaPlaybarValues[key]
304
+ : state.mediaPlaybarValues
305
+ },
306
+
307
+ /**
308
+ * @description: Getter to return the userMetadata
309
+ * * @returns: {Object}
310
+ */
311
+ getUserInteraction: (state) => {
312
+ return state.userMetaData
313
+ },
314
+
315
+ /**
316
+ * @description: Getter to return the interaction on a page
317
+ * * @returns: {Object} - userIneraction
318
+ */
319
+ getPageInteraction() {
320
+ return (activity = null, id = null) => {
321
+ if (!activity || !id) return null
322
+ const allInteraction = this.getUserInteraction
323
+ if (!allInteraction[activity] || !allInteraction[activity][id])
324
+ return {}
325
+
326
+ return allInteraction[activity][id] //allInteraction
327
+ }
328
+ },
329
+ /**
330
+ * @description: Getter to return all states of the activities
331
+ * @returns: progess {Object}
332
+ */
333
+ getAllActivitiesState(state) {
334
+ const activities = this.getAllActivities().list
335
+ let progress = {}
336
+ // search this acvitity in the userInteraction
337
+ activities.forEach((aValue, aKey) => {
338
+ let allStates
339
+ let temp = []
340
+
341
+ if (state.userMetaData[aKey]) {
342
+ const activity = Object.entries(state.userMetaData[aKey])
343
+
344
+ // get all the completed acitivities
345
+ allStates = activity.map((page) => {
346
+ // return only all the pages which state are completed or started
347
+ if (
348
+ page[1].userInteraction.state === 'completed' ||
349
+ page[1].userInteraction.state === 'started'
350
+ ) {
351
+ return {
352
+ ...allStates,
353
+ [page[0]]: page[1].userInteraction.state
354
+ }
355
+ }
356
+ })
357
+ }
358
+ if (allStates && allStates.length) {
359
+ temp = [...allStates]
360
+ }
361
+
362
+ // Getting the(Map type Object) length of the activities including the branching
363
+ let z = [] //placeholder
364
+ const getLength = (el) => {
365
+ if (el.size && el.size > 0) {
366
+ el.forEach((v) => {
367
+ // v is a map get its length with a recursive call to its elements
368
+ if (v && v.constructor === Map && v.size > 0) getLength(v)
369
+ else z.push(v) // v is an object add it to z
370
+ })
371
+ }
372
+ return z.length //return the length of the placeholder
373
+ }
374
+
375
+ // Update the progress with new values
376
+ progress = {
377
+ ...progress,
378
+ [aKey]: {
379
+ size: getLength(aValue),
380
+ progressions: [...temp]
381
+ }
382
+ }
383
+ })
384
+ return progress
385
+ },
386
+
387
+ /**
388
+ * @description: Getter to return only completed activities
389
+ * @returns: record {Object}
390
+ */
391
+ getAllCompleted(state) {
392
+ const allActivities = this.getAllActivitiesState
393
+ let record = {}
394
+
395
+ for (const key in allActivities) {
396
+ // get only activities that are completed
397
+ const completed = allActivities[key].progressions.filter((page) => {
398
+ if (page) return Object.values(page)[0] === 'completed'
399
+ })
400
+ // add the activity and its completed pages
401
+ if (completed.length)
402
+ record = {
403
+ ...record,
404
+ [key]: [...completed]
405
+ } // add the complete array to the record
406
+ }
407
+ return record
408
+ },
409
+
410
+ // for the quizzes
411
+ getAllQuizAnswers: (state) => {
412
+ return state.quizAnswers
413
+ },
414
+ getAllPollAnswers: (state) => {
415
+ return state.pollAnswers
416
+ },
417
+ getQuizAnswers: (state) => {
418
+ return (question_id) => {
419
+ const indexQuestion = state.quizAnswers.findIndex(function (element) {
420
+ return element.questionId == question_id
421
+ })
422
+ if (indexQuestion !== -1) {
423
+ return state.quizAnswers[indexQuestion]
424
+ }
425
+ return false
426
+ }
427
+ },
428
+ getPollAnswers: (state) => {
429
+ return (question_id) => {
430
+ const indexQuestion = state.pollAnswers.findIndex(function (element) {
431
+ return element.questionId == question_id
432
+ })
433
+ if (indexQuestion !== -1) {
434
+ return state.pollAnswers[indexQuestion]
435
+ }
436
+ return false
437
+ }
438
+ },
439
+ getBifChoice(state) {
440
+ const activities = this.getUserInteraction
441
+ let data = {}
442
+
443
+ let act = null
444
+ let page = null
445
+ for (const c in activities) {
446
+ act = c
447
+ const activity = state.userMetaData[c]
448
+ for (const b in activity) {
449
+ page = b
450
+ if (
451
+ activity[b] &&
452
+ [b].userInteractionactivity &&
453
+ [b].userInteraction.bifChoice
454
+ ) {
455
+ let choix = activity[b].userInteraction.bifChoice
456
+ data = { ...data, act, page, choix }
457
+ }
458
+ }
459
+ }
460
+
461
+ return data
462
+ },
463
+ /**
464
+ * @description: Getter to return the connection information of the app
465
+ * @returns: record {Object}
466
+ */
467
+ getConnectionInfo() {
468
+ return this.getLrsInfo
469
+ },
470
+
471
+ /**
472
+ * @description: Getter to return the menu setting
473
+ * @returns: record {Object}
474
+ */
475
+ getMenuSettings: (state) => {
476
+ return state.menuSetting
477
+ },
478
+
479
+ /**
480
+ * @description: Getter to return the menu setting
481
+ * @returns: record {Array}: liste of all the anchors by activity
482
+ */
483
+ getMenuAnchors(state) {
484
+ const menu = this.getMenuSettings
485
+ let anchors = []
486
+ for (const c in menu) {
487
+ anchors = [...anchors, { [c]: menu[c].anchors }]
488
+ }
489
+ return anchors
490
+ },
491
+
492
+ /**
493
+ * @description: Getter to return the menu setting
494
+ * @params ID {String}: id of the Activity
495
+ * @returns: record {ArrayOfObject}
496
+ */
497
+ getAnchorsForActivity(state) {
498
+ const allAnchors = this.getMenuAnchors
499
+ return (id) => {
500
+ const result = allAnchors.find((a) => a[id]) // find the object which has id
501
+
502
+ if (result) return result[id]
503
+ else return []
504
+ }
505
+ },
506
+
507
+ /**
508
+ * @description: Getter to return the current Section
509
+ * @returns: {Object}
510
+ */
511
+ getCurrentSection: (state) => {
512
+ if (state.currentSection) return state.currentSection
513
+ else return {}
514
+ },
515
+
516
+ getShowPrimaryCtrl: (state) => {
517
+ return state.showPrimaryCtrl
518
+ },
519
+
520
+ getShowNavLeftCtrl: (state) => {
521
+ return state.showNavLeftCtrl
522
+ },
523
+
524
+ getShowNavRightCtrl: (state) => {
525
+ return state.showNavRightCtrl
526
+ },
527
+
528
+ getLrsInfo: (state) => {
529
+ return state.lrsConfig
530
+ },
531
+
532
+ getNextActivity: (state) => {
533
+ return state.nextActivity
534
+ },
535
+
536
+ getPreviousActivity: (state) => {
537
+ return state.prevActivity
538
+ },
539
+
540
+ getDataFromServer: (state) => {
541
+ return state.dataFromServer
542
+ },
543
+ getDataNoteCredit: (state) => {
544
+ return state.dataNc
545
+ },
546
+ getWidgetOpen(state) {
547
+ return state.ncIsOpen
548
+ },
549
+
550
+ getSettingsFromStore: (state) => {
551
+ return (sName = null) => {
552
+ if (!state.appConfigs || state.appConfigs[sName] == undefined)
553
+ return null
554
+
555
+ if (sName) return state.appConfigs[sName]
556
+ else return state.appConfigs
557
+ }
558
+ },
559
+
560
+ getA11yStatus: (state) => {
561
+ return state.navA11y
562
+ },
563
+
564
+ getEndPopUp: (state) => {
565
+ return state.endPopUp
566
+ }
567
+ },
568
+ //=======================ACTIONS
569
+ actions: {
570
+ updateAppStatus(status) {
571
+ this.status = status
572
+ },
573
+
574
+ updateAnchorStatus(status) {
575
+ this.anchorStatus = status
576
+ },
577
+
578
+ updateIntroStatus(status) {
579
+ this.introAcitve = status
580
+ },
581
+
582
+ setAppDebugMode(state, bool) {
583
+ this.appDebugMode = bool
584
+ },
585
+
586
+ setMobileState(status) {
587
+ this.isMobile = status
588
+ },
589
+ setCurrentBrowser(browser) {
590
+ this.currentBrowser = browser
591
+ },
592
+ setDeviceType(device) {
593
+ this.deviceType = device
594
+ },
595
+ setErrorMenu(state, error) {
596
+ this.errMenuSetting = error
597
+ },
598
+ setApplicationSettings(settings) {
599
+ this.applicationSettings = settings
600
+ },
601
+
602
+ setMediaVolume(volume) {
603
+ this.mediaVolume = volume
604
+ },
605
+
606
+ setMediaMuted(state, bool) {
607
+ this.mediaMuted = bool
608
+ },
609
+
610
+ setMediaSubtitles(subtitlesEnabled) {
611
+ this.mediaSubtitles = subtitlesEnabled
612
+ },
613
+
614
+ setMediaPlaybarValues(data) {
615
+ // update the playbar attributes
616
+ for (const k in data) {
617
+ this.mediaPlaybarValues[k] = data[k]
618
+ }
619
+ },
620
+
621
+ setAllFiles(data) {
622
+ this.allFiles = data
623
+ },
624
+
625
+ /* set/update the Application configuration*/
626
+ setAppConfigs(data) {
627
+ this.appConfigs = data
628
+ const {
629
+ id,
630
+ crs_id: courseID,
631
+ idb_id: idbID,
632
+ specification: packageType
633
+ } = data
634
+ // Update the Module information when setting config
635
+ this.updateModule({
636
+ key: 'info',
637
+ data: { id, courseID, idbID, packageType }
638
+ })
639
+ },
640
+
641
+ setRouteHistory(data) {
642
+ this.routeHistory = data
643
+ },
644
+ /* set/update the Menu configuration*/
645
+ setMenu(data) {
646
+ this.menuSetting = data
647
+ },
648
+
649
+ /* set/update the Branching information*/
650
+ updateCurrentBranching(data) {
651
+ this.currentBranching = data
652
+ },
653
+ /* set/update the branch page information*/
654
+ updateCurrentBranchPage(data) {
655
+ this.currentBranchPage = data
656
+ },
657
+ /* set/update page information*/
658
+ updateCurrentPage({ activity_Id, page_Id }) {
659
+ if (activity_Id && page_Id) {
660
+ let page
661
+ //id type case PXX_EXX_PXX
662
+ if (page_Id.length > 3) {
663
+ const splitted = page_Id.split('_')
664
+ page = this.thisModule.activities
665
+ .get(activity_Id)
666
+ .get(splitted[0])
667
+ .get(page_Id).content
668
+ } else {
669
+ const p = this.thisModule.activities.get(activity_Id).get(page_Id)
670
+
671
+ //this branching page if the constructor is a map
672
+ if (p && p.constructor === Map) {
673
+ page = this.thisModule.activities
674
+ .get(activity_Id)
675
+ .get(page_Id)
676
+ .get(page_Id).content
677
+ } else
678
+ page = this.thisModule.activities
679
+ .get(activity_Id)
680
+ .get(page_Id).content
681
+ }
682
+ this.currentPage = page
683
+ } else this.currentPage = {}
684
+ },
685
+ /**
686
+ @description update the module data.
687
+ If no key is passed update the entire module with new data. if key is passed add/update the key
688
+ @param {String} key : a key to add/update in the module
689
+ @param {String} data : data for the key to add/update in the module
690
+ */
691
+ updateModule({ key, data }) {
692
+ if (key || this.thisModule[key]) this.thisModule[key] = data
693
+ else this.thisModule = data
694
+ },
695
+
696
+ updateCurrentTimeline(data) {
697
+ this.currentPageTimeline = data
698
+ },
699
+
700
+ async updateCurrentMediaElements(data) {
701
+ if (data && data.constructor === Array && !data.length)
702
+ return (this.currentPageMediaElements = [])
703
+
704
+ const search = this.currentPageMediaElements.findIndex(
705
+ (e) => e.id == data.id
706
+ )
707
+ //If already existe update the current media information
708
+ if (search !== -1) return (this.currentPageMediaElements[search] = data)
709
+ //Add the ref in list
710
+ this.currentPageMediaElements.push(data)
711
+ },
712
+
713
+ updateCurrentMediaDuration(data) {
714
+ this.currentMediaDuration = data
715
+ },
716
+
717
+ updateCurrentSection(data) {
718
+ // update when new data
719
+ if (
720
+ !this.currentSection ||
721
+ this.currentSection.anchorName !== data.anchorName
722
+ )
723
+ this.currentSection = data
724
+ },
725
+ updateCurrentnoteCredit(data) {
726
+ this.dataNc = data
727
+ },
728
+ /**
729
+ * @description: Save user interaction on a page to store
730
+ * USe to Update existing userMetadata
731
+ */
732
+ updateUserMetaData(data) {
733
+ const _keys = Object.keys(data) // get all keys in the passed data
734
+ // ckeck if the Activity existe in the user data
735
+ if (data.activityRef) {
736
+ if (this.userMetaData[data.activityRef]) {
737
+ const activity = this.userMetaData[data.activityRef] // get targeted activity in the user data
738
+ const page = data.id // page id
739
+
740
+ // check if the page exist in the the activity
741
+ if (Object.keys(activity).includes(page)) {
742
+ // add entry for new key in user data for the target page
743
+ _keys.forEach((key) => {
744
+ // add add value of new key in the record : discart key=ActivityRef and key ===
745
+ if (key !== _keys[0] && key !== _keys[1]) {
746
+ // store the current user interaction in a variable
747
+ const oldValue = activity[page][key]
748
+
749
+ // update the user data by copying the old value and add new data
750
+ activity[page][key] = {
751
+ ...oldValue,
752
+ ...data[key]
753
+ }
754
+ }
755
+ })
756
+ } else {
757
+ /**
758
+ * add the page reference as an object to the user data
759
+ * and create entry for user interaction
760
+ * */
761
+ _keys.forEach((key) => {
762
+ // if (key !== _keys[0] && key !== _keys[1]) {
763
+ // Vue.set(activity, [page], {
764
+ // [key]: data[key]
765
+ // })
766
+ // }
767
+ if (key !== _keys[0] && key !== _keys[1]) {
768
+ activity[page] = {
769
+ [key]: data[key]
770
+ }
771
+ }
772
+ })
773
+ }
774
+ } else {
775
+ // create a new entry for the activity
776
+ this.userMetaData = {
777
+ ...this.userMetaData,
778
+ [data.activityRef]: {
779
+ [data.id]: {}
780
+ }
781
+ }
782
+
783
+ // Add data for each new page
784
+ _keys.forEach((key) => {
785
+ if (key !== _keys[0] && key !== _keys[1]) {
786
+ // add the page datas
787
+ this.userMetaData[data.activityRef][data.id] = {
788
+ [key]: data[key]
789
+ }
790
+ }
791
+ })
792
+ }
793
+ }
794
+ },
795
+
796
+ /* set/update the user data with existing record */
797
+ setUserMetaData(data) {
798
+ this.userMetaData = data
799
+ },
800
+
801
+ // to update the answers
802
+ saveAnswersQuiz(answers) {
803
+ const theAnswers = this.getAllQuizAnswers.findIndex(function (element) {
804
+ return element.questionId == answers.questionId
805
+ })
806
+ if (theAnswers == -1) {
807
+ // if the answer already existed
808
+ this.quizAnswers.push(answers)
809
+ } else {
810
+ this.quizAnswers[theAnswers] = answers
811
+ }
812
+ },
813
+
814
+ saveAnswersPoll(answers) {
815
+ const theAnswers = this.getAllPollAnswers.findIndex(function (element) {
816
+ return element.questionId == answers.questionId
817
+ })
818
+ if (theAnswers == -1) {
819
+ // if the answer already existed
820
+ this.pollAnswers.push(answers)
821
+ } else {
822
+ this.pollAnswers[theAnswers] = answers
823
+ }
824
+ },
825
+
826
+ // SET_SHOW_PRIMARY_CONTROL(state, bool) {
827
+ // state.showPrimaryCtrl = bool
828
+ // },
829
+
830
+ // SET_SHOW_NAV_LEFT_CONTROL(state, bool) {
831
+ // state.showNavLeftCtrl = bool
832
+ // },
833
+
834
+ // SET_SHOW_NAV_RIGHT_CONTROL(state, bool) {
835
+ // state.showNavRightCtrl = bool
836
+ // },
837
+
838
+ setLrsConfig(data) {
839
+ if (data) this.lrsConfig = data
840
+ },
841
+
842
+ updateWidgetOpen(state, data) {
843
+ this.ncIsOpen = data
844
+ },
845
+
846
+ updateDataFetchFromServer(data) {
847
+ if (!data || data.constructor !== Object) return
848
+ Object.keys(data).forEach((k) => {
849
+ this.dataFromServer = { ...this.dataFromServer, [k]: data[k] }
850
+ })
851
+ },
852
+
853
+ updatePreviousActivity(data) {
854
+ this.prevActivity = data
855
+ },
856
+
857
+ updateNextActivity(data) {
858
+ this.nextActivity = data
859
+ },
860
+
861
+ updateNavA11y(data) {
862
+ this.navA11y = data
863
+ },
864
+
865
+ updateCompStatusTracker(data) {
866
+ if (!data) return
867
+
868
+ const { name, status } = data
869
+
870
+ if (!name || !status) return
871
+
872
+ let tracker = this.compStatusTracker
873
+
874
+ //search for the component
875
+ let target = tracker.find((e) => e == name)
876
+
877
+ //add component to tracking cue
878
+ if (!target && status == 'loading') tracker.push(name)
879
+
880
+ if (!tracker.length) return
881
+
882
+ //remove component to tracking cue
883
+ if (status == 'ready') {
884
+ const index = tracker.indexOf(target)
885
+
886
+ if (index >= 0) tracker = tracker.splice(index, 1)
887
+ }
888
+ },
889
+ updateEndPopUp(data) {
890
+ this.endPopUp = data
891
+ }
892
+ }
893
+ })