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.
- package/.editorconfig +33 -33
- package/.eslintignore +29 -29
- package/{.eslintrc.js → .eslintrc.cjs} +81 -86
- package/CHANGELOG +364 -364
- package/README.md +71 -71
- package/bk.scss +117 -0
- package/package.json +61 -63
- package/src/$locales/en.json +143 -179
- package/src/$locales/fr.json +105 -181
- package/src/assets/data/onboardingMessages.json +47 -47
- package/src/components/AppBase.vue +1054 -614
- package/src/components/AppBaseButton.vue +87 -63
- package/src/components/AppBaseErrorDisplay.vue +438 -420
- package/src/components/AppBaseFlipCard.vue +84 -83
- package/src/components/AppBaseModule.vue +1673 -1842
- package/src/components/AppBasePage.vue +779 -312
- package/src/components/AppBasePopover.vue +41 -0
- package/src/components/AppCompAudio.vue +234 -0
- package/src/components/AppCompBranchButtons.vue +552 -582
- package/src/components/AppCompButtonProgress.vue +126 -147
- package/src/components/AppCompCarousel.vue +298 -192
- package/src/components/AppCompInputCheckBoxNext.vue +195 -0
- package/src/components/AppCompInputDropdownNext.vue +159 -0
- package/src/components/AppCompInputRadioNext.vue +152 -0
- package/src/components/{AppCompInputTextBox.vue → AppCompInputTextNext.vue} +106 -91
- package/src/components/AppCompInputTextTableNext.vue +141 -0
- package/src/components/AppCompInputTextToFillDropdownNext.vue +230 -0
- package/src/components/{AppCompInputTextToFillText.vue → AppCompInputTextToFillNext.vue} +171 -164
- package/src/components/AppCompJauge.vue +74 -55
- package/src/components/AppCompMenu.vue +413 -209
- package/src/components/AppCompMenuItem.vue +228 -174
- package/src/components/AppCompNavigation.vue +960 -949
- package/src/components/AppCompNoteCall.vue +133 -126
- package/src/components/AppCompNoteCredit.vue +292 -164
- package/src/components/AppCompPlayBar.vue +1218 -1319
- package/src/components/AppCompPlayBarNext.vue +2052 -0
- package/src/components/AppCompPlayBarProgress.vue +82 -0
- package/src/components/AppCompPopUpNext.vue +503 -0
- package/src/components/{AppCompQuiz.vue → AppCompQuizNext.vue} +2904 -2989
- package/src/components/AppCompQuizRecall.vue +276 -250
- package/src/components/AppCompSVGNext.vue +347 -0
- package/src/components/AppCompSettingsMenu.vue +172 -171
- package/src/components/AppCompTableOfContent.vue +387 -264
- package/src/components/AppCompTranscript.vue +24 -19
- package/src/components/AppCompVideoPlayer.vue +368 -336
- package/src/components/AppCompViewDisplay.vue +6 -6
- package/src/components/BaseModule.vue +72 -67
- package/src/composables/useQuiz.js +206 -0
- package/src/externalComps/ModuleView.vue +22 -0
- package/src/externalComps/SummaryView.vue +91 -0
- package/src/main.js +272 -227
- package/src/mixins/$mediaMixins.js +819 -0
- package/src/mixins/timerMixin.js +155 -156
- package/src/module/stores/appStore.js +893 -0
- package/src/module/xapi/ADL.js +376 -339
- 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 -319
- 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 +1963 -1890
- package/src/module/xapi/xapiStatement.js +444 -444
- package/src/plugins/bus.js +8 -3
- package/src/plugins/gsap.js +14 -17
- package/src/plugins/helper.js +308 -295
- package/src/plugins/i18n.js +44 -31
- package/src/plugins/idb.js +219 -212
- 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 -21
- package/src/router/index.js +43 -41
- package/src/router/routes.js +312 -337
- package/src/shared/generalfuncs.js +210 -188
- package/src/shared/validators.js +1069 -249
- package/vite.config.js +27 -0
- package/.prettierrc.js +0 -5
- package/babel.config.js +0 -3
- package/src/components/AppBaseDragChoice.vue +0 -91
- package/src/components/AppBaseDropZone.vue +0 -112
- package/src/components/AppCompBif.vue +0 -120
- package/src/components/AppCompDragAndDrop.vue +0 -339
- package/src/components/AppCompInputAssociation.vue +0 -332
- package/src/components/AppCompInputCheckBox.vue +0 -227
- package/src/components/AppCompInputDropdown.vue +0 -184
- package/src/components/AppCompInputRadio.vue +0 -169
- package/src/components/AppCompInputTextTable.vue +0 -155
- package/src/components/AppCompInputTextToFillDropdown.vue +0 -255
- package/src/components/AppCompMediaPlayer.vue +0 -397
- package/src/components/AppCompPopUp.vue +0 -522
- package/src/components/AppCompPopover.vue +0 -27
- package/src/components/AppCompSVG.vue +0 -309
- package/src/mixins/$pageMixins.js +0 -459
- package/src/mixins/$quizMixins.js +0 -456
- package/src/module/store.js +0 -895
- package/src/plugins/timeManager.js +0 -77
- package/src/routes_bckp.js +0 -313
- package/src/routes_static.js +0 -344
- 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
|
+
})
|