fcad-core-dragon 2.1.0-beta.4 → 2.1.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.
Files changed (73) hide show
  1. package/.editorconfig +8 -33
  2. package/.prettierrc +11 -0
  3. package/.vscode/extensions.json +8 -0
  4. package/.vscode/settings.json +16 -0
  5. package/CHANGELOG +20 -0
  6. package/eslint.config.js +60 -0
  7. package/package.json +9 -9
  8. package/src/$locales/en.json +3 -3
  9. package/src/$locales/fr.json +3 -3
  10. package/src/assets/data/onboardingMessages.json +47 -47
  11. package/src/components/AppBase.vue +5 -6
  12. package/src/components/AppBaseErrorDisplay.vue +438 -438
  13. package/src/components/AppBaseFlipCard.vue +84 -84
  14. package/src/components/AppBaseModule.vue +15 -17
  15. package/src/components/AppBasePage.vue +91 -8
  16. package/src/components/AppBasePopover.vue +41 -41
  17. package/src/components/AppBaseSkeleton.vue +24 -3
  18. package/src/components/AppCompAudio.vue +12 -2
  19. package/src/components/AppCompInputCheckBoxNx.vue +1 -2
  20. package/src/components/AppCompInputRadioNx.vue +8 -2
  21. package/src/components/AppCompInputTextToFillDropdownNx.vue +45 -0
  22. package/src/components/AppCompMenu.vue +423 -423
  23. package/src/components/AppCompNavigation.vue +2 -2
  24. package/src/components/AppCompPlayBarNext.vue +123 -94
  25. package/src/components/AppCompPopUpNext.vue +2 -2
  26. package/src/components/AppCompQuizNext.vue +12 -2
  27. package/src/components/AppCompQuizRecall.vue +10 -4
  28. package/src/components/AppCompSettingsMenu.vue +172 -172
  29. package/src/components/AppCompTableOfContent.vue +1 -4
  30. package/src/components/AppCompVideoPlayer.vue +7 -0
  31. package/src/components/AppCompViewDisplay.vue +6 -6
  32. package/src/composables/useTimer.js +17 -20
  33. package/src/externalComps/ModuleView.vue +22 -22
  34. package/src/externalComps/SummaryView.vue +91 -91
  35. package/src/main.js +5 -5
  36. package/src/module/stores/appStore.js +0 -1
  37. package/src/module/xapi/Crypto/Hasher.js +241 -241
  38. package/src/module/xapi/Crypto/WordArray.js +278 -278
  39. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  40. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
  41. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  42. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  43. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  44. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  45. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  46. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  47. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  48. package/src/module/xapi/Crypto/index.js +53 -53
  49. package/src/module/xapi/Statement/activity.js +47 -47
  50. package/src/module/xapi/Statement/agent.js +55 -55
  51. package/src/module/xapi/Statement/group.js +26 -26
  52. package/src/module/xapi/Statement/index.js +259 -259
  53. package/src/module/xapi/Statement/statement.js +253 -253
  54. package/src/module/xapi/Statement/statementRef.js +23 -23
  55. package/src/module/xapi/Statement/substatement.js +22 -22
  56. package/src/module/xapi/Statement/verb.js +36 -36
  57. package/src/module/xapi/activitytypes.js +17 -17
  58. package/src/module/xapi/utils.js +167 -167
  59. package/src/module/xapi/verbs.js +294 -294
  60. package/src/module/xapi/xapiStatement.js +444 -444
  61. package/src/plugins/analytics.js +4 -4
  62. package/src/plugins/bus.js +8 -8
  63. package/src/plugins/gsap.js +4 -2
  64. package/src/plugins/helper.js +8 -4
  65. package/src/plugins/save.js +37 -37
  66. package/src/plugins/scorm.js +287 -287
  67. package/src/plugins/xapi.js +11 -11
  68. package/src/public/index.html +33 -33
  69. package/src/router/index.js +1 -1
  70. package/src/shared/validators.js +22 -6
  71. package/.eslintignore +0 -29
  72. package/.eslintrc.cjs +0 -81
  73. package/bk.scss +0 -117
@@ -1,423 +1,423 @@
1
- <!--
2
- @ Description: This component is used to create the menu and the ard that will bring you back where you were before the menu.
3
- @ What it does: Look in the store what was the last page you saw before you came to the menu and create the the link for the card. It display's AppCompMenuItem
4
- -->
5
- <template>
6
- <div class="menu-container">
7
- <div
8
- id="page_info_section"
9
- class="sr-only"
10
- aria-labelledby="page_info"
11
- ></div>
12
- <a
13
- class="skip-link"
14
- href=""
15
- @click.prevent="$bus.$emit('move-to-target', 'menu-main')"
16
- >
17
- {{ $t('message.skip_content') }}
18
- </a>
19
- <div class="contain-lr">
20
- <div class="wrapper-lasRoute">
21
- <div class="box-menu">
22
- <h1>{{ getLessonid }}</h1>
23
- <h2 v-html="getLessonTitle"></h2>
24
-
25
- <p class="lesson-progess">
26
- {{ $t('message.progress_card') }} {{ lessonProg() }}
27
- </p>
28
- <router-link
29
- id="btn_last_route"
30
- class="nav_last_route btn-main"
31
- :title="handelLabel"
32
- :to="{ name: GoToLastRoute() }"
33
- data-test="menu-back-btn"
34
- >
35
- {{ handelLabel }}
36
- </router-link>
37
- </div>
38
- </div>
39
- <v-row justify="center" align="center" class="r-menu">
40
- <v-col id="menu-main" md="10" class="wrapper-MenuItem">
41
- <h3>{{ $t('text.activity_title') }}</h3>
42
-
43
- <app-comp-menu-item></app-comp-menu-item>
44
- </v-col>
45
- </v-row>
46
- </div>
47
- <v-row justify="center" align="center">
48
- <v-col md="7">
49
- <div v-show="appDebugMode" id="_debug-area">
50
- <h5>Mode de débogage activé</h5>
51
- <p>
52
- Cliquez sur le bouton pour réinitialiser toutes les données de ce
53
- paquet.
54
- </p>
55
-
56
- <app-base-button
57
- :id="`btn-quiz`"
58
- class="btn lk-btn"
59
- title="Réinitialiser la leçon"
60
- :is-disabled="resetStatus !== false"
61
- @click="askResetUserData"
62
- >
63
- Réinitialiser la leçon
64
- </app-base-button>
65
- <div v-show="resetStatus !== false" id="resetOverlay">
66
- <div
67
- v-show="resetStatus === resetState.LOADING"
68
- class="lds-ellipsis"
69
- >
70
- <div></div>
71
- <div></div>
72
- <div></div>
73
- <div></div>
74
- </div>
75
- <span v-show="resetStatus === resetState.COMPLETE" id="reset_label">
76
- Opération réussie!
77
- </span>
78
- </div>
79
- </div>
80
- </v-col>
81
- </v-row>
82
- <span id="page_info" class="sr-only" aria-hidden="true">
83
- {{ $t('text.title_content_view') }}
84
- </span>
85
- </div>
86
- </template>
87
- <script>
88
- // ...
89
- import { mapState } from 'pinia'
90
- import { useAppStore } from '../module/stores/appStore'
91
- export default {
92
- name: 'AppCompMenu',
93
- data() {
94
- return {
95
- totalAttempts: 0,
96
- resetStatus: false,
97
- resetState: { LOADING: 'LOADING', COMPLETE: 'COMPLETE' }
98
- }
99
- },
100
-
101
- computed: {
102
- ...mapState(useAppStore, [
103
- 'getRouteHistory',
104
- 'getAllActivitiesState',
105
- 'getAllCompleted',
106
- 'getModuleInfo',
107
- 'getMenuSettings',
108
- 'getAppDebugMode',
109
- 'getAppConfigs',
110
- 'getAllCompleted'
111
- ]),
112
- appDebugMode() {
113
- return this.getAppDebugMode
114
- },
115
- handelLabel() {
116
- let label = ''
117
- const { allActivitiesState, allCompleted } = this.progressWithMenu()
118
-
119
- let activity = Object.values(allActivitiesState)
120
- let completeActivity = Object.values(allCompleted)
121
-
122
- if (this.noProgress(activity)) {
123
- label = this.$t('button.menu_item.start')
124
- } else {
125
- if (activity.length == completeActivity.length) {
126
- label = this.$t('button.menu_item.end')
127
- } else {
128
- label = this.$t('button.menu_item.end')
129
- }
130
- }
131
- return label
132
- },
133
- getLessonid() {
134
- let lessonLabel = this.$t('text.lesson')
135
- let lessonId
136
- if (this.getMenuSettings.lessonNumber) {
137
- lessonId = this.getMenuSettings.lessonNumber
138
- } else {
139
- lessonId =
140
- 'La variable lessonNumber est introuvable dans menu.setting.js'
141
- }
142
- return `${lessonLabel} ${lessonId}`
143
- },
144
- getLessonTitle() {
145
- let lessonT
146
- if (this.getMenuSettings.lessonTitle) {
147
- lessonT = this.getMenuSettings.lessonTitle
148
- } else {
149
- lessonT = 'Entrer un titre à pour votre leçon dans menu setting svp.'
150
- }
151
- return `${lessonT}`
152
- }
153
- },
154
- mounted() {
155
- setTimeout(() => {
156
- this.$bus.$emit('move-to-target', 'page_info_section')
157
- }, 200)
158
- },
159
- beforeUnmount() {
160
- this.$bus.$off('reset-complete', this.onResetComplete)
161
- },
162
- methods: {
163
- //When server responds after a reset request
164
- onResetComplete() {
165
- this.$bus.$off('reset-complete', this.onResetComplete)
166
- //show Operation reussie! for 2 seconds then exit debugmode
167
- this.resetStatus = this.resetState.COMPLETE
168
- setTimeout(() => {
169
- window.setDebugMode(false)
170
- if (this.resetStatus) {
171
- this.resetStatus = false
172
- }
173
- }, 2000)
174
- },
175
- //Go to the last route you were before the menu
176
- GoToLastRoute() {
177
- let lastRoute
178
- let path
179
- //Get all activity state (menu not included)
180
- const { allActivitiesState } = this.progressWithMenu()
181
- let state = Object.values(allActivitiesState)
182
-
183
- if (this.getRouteHistory && this.getRouteHistory.length) {
184
- if (this.getRouteHistory.length == 1) {
185
- lastRoute = this.getRouteHistory[0]
186
- } else {
187
- lastRoute = this.getRouteHistory[this.getRouteHistory.length - 1]
188
- }
189
- }
190
-
191
- //if course was not started bring you to the introduction
192
- if (this.noProgress(state)) {
193
- path = 'introduction'
194
- return path
195
- }
196
-
197
- // create path from the last you saw
198
- if (lastRoute) path = this.createdRoute(lastRoute)
199
-
200
- return path
201
- },
202
-
203
- noProgress(obj) {
204
- //validator to see if anything was seen before
205
- for (let i = 0; i < obj.length; i++) {
206
- if (obj[i].progressions.length != 0) return false //something was seen
207
- }
208
- return true //nothing was seen
209
- },
210
- createdRoute(objRoute) {
211
- // create link for activity
212
- let newRoute = objRoute
213
- let activity
214
- let page
215
- let path
216
-
217
- const typesToCatch = ['menu', 'introduction', 'conclusion']
218
- //Define activity
219
- if (typesToCatch.includes(newRoute.type)) {
220
- activity = newRoute.type
221
- } else {
222
- activity =
223
- newRoute.activity_ref && newRoute.activity_ref.charAt(1) == '0'
224
- ? `activite_${newRoute.activity_ref.substring(2)}`
225
- : `activite_${newRoute.activity_ref.substring(1)}`
226
- }
227
-
228
- //Define page
229
- const idToIgnore = ['P01', 'pg_menu']
230
- page = idToIgnore.includes(newRoute.id) ? ' ' : newRoute.id.substring(2)
231
-
232
- //Define path
233
- path = page !== ' ' ? `${activity}.page_${page}` : activity
234
- return path
235
- },
236
- progressWithMenu() {
237
- /*
238
- * Note:
239
- * Assaging by reference would change the property of the getters when the valued are changed in the new object in. * To prevent this behaviour we will make a deep copy of the getter
240
- * cf: https://reactgo.com/javascript-clone-object/
241
- */
242
-
243
- const allActivitiesState = JSON.parse(
244
- JSON.stringify(this.getAllActivitiesState)
245
- )
246
-
247
- const allCompleted = JSON.parse(JSON.stringify(this.getAllCompleted))
248
-
249
- for (let activity in allActivitiesState) {
250
- if (
251
- activity === 'A00' &&
252
- allActivitiesState[activity] &&
253
- allCompleted[activity]
254
- ) {
255
- let completedIntro = allCompleted[activity]
256
-
257
- if (!completedIntro.length) completedIntro = []
258
-
259
- allCompleted[activity] = completedIntro
260
- }
261
- }
262
-
263
- return {
264
- allActivitiesState,
265
- allCompleted
266
- }
267
- },
268
- lessonProg() {
269
- let lstActivity = Object.keys(this.getAllActivitiesState)
270
- let progress = null
271
- let info = this.progressWithMenu()
272
- let page = null
273
- let pageCmplt = null
274
-
275
- lstActivity.forEach((element) => {
276
- //Get the total of all the page
277
- page += info.allActivitiesState[element].size
278
-
279
- if (info.allCompleted[element]) {
280
- // GEt all page complete
281
- pageCmplt += Object.values(info.allCompleted[element]).length
282
- }
283
- })
284
-
285
- // Create pourcentage complete
286
- progress = Math.round((pageCmplt * 100) / page)
287
-
288
- return this.getAppConfigs.lang.toLowerCase() == 'en'
289
- ? `${progress}%`
290
- : `${progress} %`
291
- },
292
- askResetUserData() {
293
- //show loader animation
294
- this.resetStatus = this.resetState.LOADING
295
- //callback on server response
296
- this.$bus.$on('reset-complete', this.onResetComplete)
297
- //launch reset call
298
- this.$bus.$emit('reset-userdata')
299
- }
300
- }
301
- }
302
- </script>
303
- <style lang="scss">
304
- .contain-lr {
305
- display: flex;
306
- flex-direction: column;
307
- flex-wrap: wrap;
308
- width: 100%;
309
-
310
- .wrapper-lasRoute {
311
- display: flex;
312
- justify-content: flex-end;
313
-
314
- .nav_last_route {
315
- display: inline-block;
316
- }
317
- }
318
- }
319
-
320
- .menu-container {
321
- width: 100%;
322
- height: 100%;
323
-
324
- .r-menu {
325
- margin: 0 0 0 0;
326
- }
327
- }
328
-
329
- #_debug-area {
330
- display: flex;
331
- flex-direction: column;
332
- align-items: center;
333
- justify-content: center;
334
- margin: 25px;
335
- padding: 20px;
336
- background-color: #eaabb6b3;
337
- border-block: dotted yellow 5px;
338
- p {
339
- padding: 15px;
340
- text-align: center;
341
- font-size: 1em;
342
- }
343
- button {
344
- background-color: #8dff95;
345
- font-size: 1.3em;
346
- padding: 5px 12px;
347
- }
348
- #resetOverlay {
349
- position: absolute;
350
- display: flex;
351
- flex-direction: column;
352
- width: 33%;
353
- height: 40%;
354
- align-items: center;
355
- justify-content: center;
356
- background-color: rgba($color: #000000, $alpha: 0.9);
357
- border-radius: 10px;
358
- box-shadow: 2px 2px 4px 0px rgba($color: #000000, $alpha: 0.2);
359
- }
360
- #reset_label {
361
- font-family: arial;
362
- color: #fff;
363
- font-weight: bold;
364
- font-size: 18px;
365
- }
366
- .lds-ellipsis {
367
- display: flex;
368
- display: inline-block;
369
- position: relative;
370
- width: 80px;
371
- height: 80px;
372
- }
373
- .lds-ellipsis div {
374
- position: absolute;
375
- top: 33px;
376
- width: 13px;
377
- height: 13px;
378
- border-radius: 50%;
379
- background: #fff;
380
- animation-timing-function: cubic-bezier(0, 1, 1, 0);
381
- }
382
- .lds-ellipsis div:nth-child(1) {
383
- left: 8px;
384
- animation: lds-ellipsis1 0.6s infinite;
385
- }
386
- .lds-ellipsis div:nth-child(2) {
387
- left: 8px;
388
- animation: lds-ellipsis2 0.6s infinite;
389
- }
390
- .lds-ellipsis div:nth-child(3) {
391
- left: 32px;
392
- animation: lds-ellipsis2 0.6s infinite;
393
- }
394
- .lds-ellipsis div:nth-child(4) {
395
- left: 56px;
396
- animation: lds-ellipsis3 0.6s infinite;
397
- }
398
- @keyframes lds-ellipsis1 {
399
- 0% {
400
- transform: scale(0);
401
- }
402
- 100% {
403
- transform: scale(1);
404
- }
405
- }
406
- @keyframes lds-ellipsis3 {
407
- 0% {
408
- transform: scale(1);
409
- }
410
- 100% {
411
- transform: scale(0);
412
- }
413
- }
414
- @keyframes lds-ellipsis2 {
415
- 0% {
416
- transform: translate(0, 0);
417
- }
418
- 100% {
419
- transform: translate(24px, 0);
420
- }
421
- }
422
- }
423
- </style>
1
+ <!--
2
+ @ Description: This component is used to create the menu and the ard that will bring you back where you were before the menu.
3
+ @ What it does: Look in the store what was the last page you saw before you came to the menu and create the the link for the card. It display's AppCompMenuItem
4
+ -->
5
+ <template>
6
+ <div class="menu-container">
7
+ <div
8
+ id="page_info_section"
9
+ class="sr-only"
10
+ aria-labelledby="page_info"
11
+ ></div>
12
+ <a
13
+ class="skip-link"
14
+ href=""
15
+ @click.prevent="$bus.$emit('move-to-target', 'menu-main')"
16
+ >
17
+ {{ $t('message.skip_content') }}
18
+ </a>
19
+ <div class="contain-lr">
20
+ <div class="wrapper-lasRoute">
21
+ <div class="box-menu">
22
+ <h1>{{ getLessonid }}</h1>
23
+ <h2 v-html="getLessonTitle"></h2>
24
+
25
+ <p class="lesson-progess">
26
+ {{ $t('message.progress_card') }} {{ lessonProg() }}
27
+ </p>
28
+ <router-link
29
+ id="btn_last_route"
30
+ class="nav_last_route btn-main"
31
+ :title="handelLabel"
32
+ :to="{ name: GoToLastRoute() }"
33
+ data-test="menu-back-btn"
34
+ >
35
+ {{ handelLabel }}
36
+ </router-link>
37
+ </div>
38
+ </div>
39
+ <v-row justify="center" align="center" class="r-menu">
40
+ <v-col id="menu-main" md="10" class="wrapper-MenuItem">
41
+ <h3>{{ $t('text.activity_title') }}</h3>
42
+
43
+ <app-comp-menu-item></app-comp-menu-item>
44
+ </v-col>
45
+ </v-row>
46
+ </div>
47
+ <v-row justify="center" align="center">
48
+ <v-col md="7">
49
+ <div v-show="appDebugMode" id="_debug-area">
50
+ <h5>Mode de débogage activé</h5>
51
+ <p>
52
+ Cliquez sur le bouton pour réinitialiser toutes les données de ce
53
+ paquet.
54
+ </p>
55
+
56
+ <app-base-button
57
+ :id="`btn-quiz`"
58
+ class="btn lk-btn"
59
+ title="Réinitialiser la leçon"
60
+ :is-disabled="resetStatus !== false"
61
+ @click="askResetUserData"
62
+ >
63
+ Réinitialiser la leçon
64
+ </app-base-button>
65
+ <div v-show="resetStatus !== false" id="resetOverlay">
66
+ <div
67
+ v-show="resetStatus === resetState.LOADING"
68
+ class="lds-ellipsis"
69
+ >
70
+ <div></div>
71
+ <div></div>
72
+ <div></div>
73
+ <div></div>
74
+ </div>
75
+ <span v-show="resetStatus === resetState.COMPLETE" id="reset_label">
76
+ Opération réussie!
77
+ </span>
78
+ </div>
79
+ </div>
80
+ </v-col>
81
+ </v-row>
82
+ <span id="page_info" class="sr-only" aria-hidden="true">
83
+ {{ $t('text.title_content_view') }}
84
+ </span>
85
+ </div>
86
+ </template>
87
+ <script>
88
+ // ...
89
+ import { mapState } from 'pinia'
90
+ import { useAppStore } from '../module/stores/appStore'
91
+ export default {
92
+ name: 'AppCompMenu',
93
+ data() {
94
+ return {
95
+ totalAttempts: 0,
96
+ resetStatus: false,
97
+ resetState: { LOADING: 'LOADING', COMPLETE: 'COMPLETE' }
98
+ }
99
+ },
100
+
101
+ computed: {
102
+ ...mapState(useAppStore, [
103
+ 'getRouteHistory',
104
+ 'getAllActivitiesState',
105
+ 'getAllCompleted',
106
+ 'getModuleInfo',
107
+ 'getMenuSettings',
108
+ 'getAppDebugMode',
109
+ 'getAppConfigs',
110
+ 'getAllCompleted'
111
+ ]),
112
+ appDebugMode() {
113
+ return this.getAppDebugMode
114
+ },
115
+ handelLabel() {
116
+ let label = ''
117
+ const { allActivitiesState, allCompleted } = this.progressWithMenu()
118
+
119
+ let activity = Object.values(allActivitiesState)
120
+ let completeActivity = Object.values(allCompleted)
121
+
122
+ if (this.noProgress(activity)) {
123
+ label = this.$t('button.menu_item.start')
124
+ } else {
125
+ if (activity.length == completeActivity.length) {
126
+ label = this.$t('button.menu_item.end')
127
+ } else {
128
+ label = this.$t('button.menu_item.end')
129
+ }
130
+ }
131
+ return label
132
+ },
133
+ getLessonid() {
134
+ let lessonLabel = this.$t('text.lesson')
135
+ let lessonId
136
+ if (this.getMenuSettings.lessonNumber) {
137
+ lessonId = this.getMenuSettings.lessonNumber
138
+ } else {
139
+ lessonId =
140
+ 'La variable lessonNumber est introuvable dans menu.setting.js'
141
+ }
142
+ return `${lessonLabel} ${lessonId}`
143
+ },
144
+ getLessonTitle() {
145
+ let lessonT
146
+ if (this.getMenuSettings.lessonTitle) {
147
+ lessonT = this.getMenuSettings.lessonTitle
148
+ } else {
149
+ lessonT = 'Entrer un titre à pour votre leçon dans menu setting svp.'
150
+ }
151
+ return `${lessonT}`
152
+ }
153
+ },
154
+ mounted() {
155
+ setTimeout(() => {
156
+ this.$bus.$emit('move-to-target', 'page_info_section')
157
+ }, 200)
158
+ },
159
+ beforeUnmount() {
160
+ this.$bus.$off('reset-complete', this.onResetComplete)
161
+ },
162
+ methods: {
163
+ //When server responds after a reset request
164
+ onResetComplete() {
165
+ this.$bus.$off('reset-complete', this.onResetComplete)
166
+ //show Operation reussie! for 2 seconds then exit debugmode
167
+ this.resetStatus = this.resetState.COMPLETE
168
+ setTimeout(() => {
169
+ window.setDebugMode(false)
170
+ if (this.resetStatus) {
171
+ this.resetStatus = false
172
+ }
173
+ }, 2000)
174
+ },
175
+ //Go to the last route you were before the menu
176
+ GoToLastRoute() {
177
+ let lastRoute
178
+ let path
179
+ //Get all activity state (menu not included)
180
+ const { allActivitiesState } = this.progressWithMenu()
181
+ let state = Object.values(allActivitiesState)
182
+
183
+ if (this.getRouteHistory && this.getRouteHistory.length) {
184
+ if (this.getRouteHistory.length == 1) {
185
+ lastRoute = this.getRouteHistory[0]
186
+ } else {
187
+ lastRoute = this.getRouteHistory[this.getRouteHistory.length - 1]
188
+ }
189
+ }
190
+
191
+ //if course was not started bring you to the introduction
192
+ if (this.noProgress(state)) {
193
+ path = 'introduction'
194
+ return path
195
+ }
196
+
197
+ // create path from the last you saw
198
+ if (lastRoute) path = this.createdRoute(lastRoute)
199
+
200
+ return path
201
+ },
202
+
203
+ noProgress(obj) {
204
+ //validator to see if anything was seen before
205
+ for (let i = 0; i < obj.length; i++) {
206
+ if (obj[i].progressions.length != 0) return false //something was seen
207
+ }
208
+ return true //nothing was seen
209
+ },
210
+ createdRoute(objRoute) {
211
+ // create link for activity
212
+ let newRoute = objRoute
213
+ let activity
214
+ let page
215
+ let path
216
+
217
+ const typesToCatch = ['menu', 'introduction', 'conclusion']
218
+ //Define activity
219
+ if (typesToCatch.includes(newRoute.type)) {
220
+ activity = newRoute.type
221
+ } else {
222
+ activity =
223
+ newRoute.activity_ref && newRoute.activity_ref.charAt(1) == '0'
224
+ ? `activite_${newRoute.activity_ref.substring(2)}`
225
+ : `activite_${newRoute.activity_ref.substring(1)}`
226
+ }
227
+
228
+ //Define page
229
+ const idToIgnore = ['P01', 'pg_menu']
230
+ page = idToIgnore.includes(newRoute.id) ? ' ' : newRoute.id.substring(2)
231
+
232
+ //Define path
233
+ path = page !== ' ' ? `${activity}.page_${page}` : activity
234
+ return path
235
+ },
236
+ progressWithMenu() {
237
+ /*
238
+ * Note:
239
+ * Assaging by reference would change the property of the getters when the valued are changed in the new object in. * To prevent this behaviour we will make a deep copy of the getter
240
+ * cf: https://reactgo.com/javascript-clone-object/
241
+ */
242
+
243
+ const allActivitiesState = JSON.parse(
244
+ JSON.stringify(this.getAllActivitiesState)
245
+ )
246
+
247
+ const allCompleted = JSON.parse(JSON.stringify(this.getAllCompleted))
248
+
249
+ for (let activity in allActivitiesState) {
250
+ if (
251
+ activity === 'A00' &&
252
+ allActivitiesState[activity] &&
253
+ allCompleted[activity]
254
+ ) {
255
+ let completedIntro = allCompleted[activity]
256
+
257
+ if (!completedIntro.length) completedIntro = []
258
+
259
+ allCompleted[activity] = completedIntro
260
+ }
261
+ }
262
+
263
+ return {
264
+ allActivitiesState,
265
+ allCompleted
266
+ }
267
+ },
268
+ lessonProg() {
269
+ let lstActivity = Object.keys(this.getAllActivitiesState)
270
+ let progress = null
271
+ let info = this.progressWithMenu()
272
+ let page = null
273
+ let pageCmplt = null
274
+
275
+ lstActivity.forEach((element) => {
276
+ //Get the total of all the page
277
+ page += info.allActivitiesState[element].size
278
+
279
+ if (info.allCompleted[element]) {
280
+ // GEt all page complete
281
+ pageCmplt += Object.values(info.allCompleted[element]).length
282
+ }
283
+ })
284
+
285
+ // Create pourcentage complete
286
+ progress = Math.round((pageCmplt * 100) / page)
287
+
288
+ return this.getAppConfigs.lang.toLowerCase() == 'en'
289
+ ? `${progress}%`
290
+ : `${progress} %`
291
+ },
292
+ askResetUserData() {
293
+ //show loader animation
294
+ this.resetStatus = this.resetState.LOADING
295
+ //callback on server response
296
+ this.$bus.$on('reset-complete', this.onResetComplete)
297
+ //launch reset call
298
+ this.$bus.$emit('reset-userdata')
299
+ }
300
+ }
301
+ }
302
+ </script>
303
+ <style lang="scss">
304
+ .contain-lr {
305
+ display: flex;
306
+ flex-direction: column;
307
+ flex-wrap: wrap;
308
+ width: 100%;
309
+
310
+ .wrapper-lasRoute {
311
+ display: flex;
312
+ justify-content: flex-end;
313
+
314
+ .nav_last_route {
315
+ display: inline-block;
316
+ }
317
+ }
318
+ }
319
+
320
+ .menu-container {
321
+ width: 100%;
322
+ height: 100%;
323
+
324
+ .r-menu {
325
+ margin: 0 0 0 0;
326
+ }
327
+ }
328
+
329
+ #_debug-area {
330
+ display: flex;
331
+ flex-direction: column;
332
+ align-items: center;
333
+ justify-content: center;
334
+ margin: 25px;
335
+ padding: 20px;
336
+ background-color: #eaabb6b3;
337
+ border-block: dotted yellow 5px;
338
+ p {
339
+ padding: 15px;
340
+ text-align: center;
341
+ font-size: 1em;
342
+ }
343
+ button {
344
+ background-color: #8dff95;
345
+ font-size: 1.3em;
346
+ padding: 5px 12px;
347
+ }
348
+ #resetOverlay {
349
+ position: absolute;
350
+ display: flex;
351
+ flex-direction: column;
352
+ width: 33%;
353
+ height: 40%;
354
+ align-items: center;
355
+ justify-content: center;
356
+ background-color: rgba($color: #000000, $alpha: 0.9);
357
+ border-radius: 10px;
358
+ box-shadow: 2px 2px 4px 0px rgba($color: #000000, $alpha: 0.2);
359
+ }
360
+ #reset_label {
361
+ font-family: arial;
362
+ color: #fff;
363
+ font-weight: bold;
364
+ font-size: 18px;
365
+ }
366
+ .lds-ellipsis {
367
+ display: flex;
368
+ display: inline-block;
369
+ position: relative;
370
+ width: 80px;
371
+ height: 80px;
372
+ }
373
+ .lds-ellipsis div {
374
+ position: absolute;
375
+ top: 33px;
376
+ width: 13px;
377
+ height: 13px;
378
+ border-radius: 50%;
379
+ background: #fff;
380
+ animation-timing-function: cubic-bezier(0, 1, 1, 0);
381
+ }
382
+ .lds-ellipsis div:nth-child(1) {
383
+ left: 8px;
384
+ animation: lds-ellipsis1 0.6s infinite;
385
+ }
386
+ .lds-ellipsis div:nth-child(2) {
387
+ left: 8px;
388
+ animation: lds-ellipsis2 0.6s infinite;
389
+ }
390
+ .lds-ellipsis div:nth-child(3) {
391
+ left: 32px;
392
+ animation: lds-ellipsis2 0.6s infinite;
393
+ }
394
+ .lds-ellipsis div:nth-child(4) {
395
+ left: 56px;
396
+ animation: lds-ellipsis3 0.6s infinite;
397
+ }
398
+ @keyframes lds-ellipsis1 {
399
+ 0% {
400
+ transform: scale(0);
401
+ }
402
+ 100% {
403
+ transform: scale(1);
404
+ }
405
+ }
406
+ @keyframes lds-ellipsis3 {
407
+ 0% {
408
+ transform: scale(1);
409
+ }
410
+ 100% {
411
+ transform: scale(0);
412
+ }
413
+ }
414
+ @keyframes lds-ellipsis2 {
415
+ 0% {
416
+ transform: translate(0, 0);
417
+ }
418
+ 100% {
419
+ transform: translate(24px, 0);
420
+ }
421
+ }
422
+ }
423
+ </style>