fcad-core-dragon 2.0.0-beta.5 → 2.0.0-beta.7

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