fcad-core-dragon 2.0.0-beta.0 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +7 -9
- package/src/$locales/en.json +39 -15
- package/src/$locales/fr.json +48 -23
- package/src/components/AppBase.vue +245 -266
- package/src/components/AppBaseErrorDisplay.vue +29 -0
- package/src/components/AppBaseModule.vue +485 -232
- package/src/components/AppBasePage.vue +28 -54
- package/src/components/AppCompBif.vue +120 -0
- package/src/components/AppCompBranchButtons.vue +31 -30
- package/src/components/AppCompButtonProgress.vue +35 -46
- package/src/components/AppCompCarousel.vue +154 -247
- package/src/components/AppCompJauge.vue +1 -2
- package/src/components/AppCompMediaPlayer.vue +106 -74
- package/src/components/AppCompMenu.vue +87 -81
- package/src/components/AppCompMenuItem.vue +48 -90
- package/src/components/AppCompNavigation.vue +949 -0
- package/src/components/AppCompNoteCall.vue +126 -0
- package/src/components/AppCompNoteCredit.vue +164 -0
- package/src/components/AppCompPlayBar.vue +864 -1085
- package/src/components/AppCompPopUp.vue +26 -27
- package/src/components/AppCompPopover.vue +27 -0
- package/src/components/AppCompQuiz.vue +27 -36
- package/src/components/AppCompQuizRecall.vue +250 -0
- package/src/components/AppCompSVG.vue +309 -0
- package/src/components/AppCompSettingsMenu.vue +1 -0
- package/src/components/AppCompTableOfContent.vue +140 -85
- package/src/components/AppCompTranscript.vue +19 -0
- package/src/components/AppCompVideoPlayer.vue +336 -0
- package/src/components/BaseModule.vue +24 -105
- package/src/main.js +18 -9
- package/src/mixins/$pageMixins.js +106 -28
- package/src/mixins/timerMixin.js +31 -7
- package/src/module/store.js +33 -12
- package/src/module/xapi/Crypto/encoders/Hex.js +2 -1
- package/src/module/xapi/wrapper.js +4 -4
- package/src/plugins/gsap.js +4 -1
- package/src/plugins/helper.js +53 -18
- package/src/plugins/idb.js +1 -0
- package/src/public/index.html +1 -1
- package/src/router/index.js +41 -0
- package/src/router/routes.js +337 -0
- package/src/routes_bckp.js +313 -0
- package/src/routes_static.js +344 -0
- package/src/shared/generalfuncs.js +79 -4
- package/src/shared/validators.js +249 -0
- package/src/components/AppCompNavigationFull.vue +0 -1791
- package/src/components/AppCompToolTip.vue +0 -94
- package/src/routes.js +0 -734
|
@@ -19,18 +19,12 @@
|
|
|
19
19
|
id="video"
|
|
20
20
|
ref="video"
|
|
21
21
|
tabindex="0"
|
|
22
|
-
class="m-video"
|
|
22
|
+
class="v-media m-video"
|
|
23
23
|
:poster="media.mPoster"
|
|
24
24
|
@loadedmetadata="updateMediaData($event)"
|
|
25
25
|
@load="() => {}"
|
|
26
26
|
@error="() => {}"
|
|
27
27
|
>
|
|
28
|
-
<!-- <source
|
|
29
|
-
v-for="(aMedia, index) in media.mSources"
|
|
30
|
-
:key="index"
|
|
31
|
-
:src="`${aMedia.src}`"
|
|
32
|
-
:type="`${media.mType}/${aMedia.type}`"
|
|
33
|
-
/> -->
|
|
34
28
|
<source
|
|
35
29
|
v-for="(aMedia, index) in media.mSources"
|
|
36
30
|
:key="index"
|
|
@@ -49,7 +43,7 @@
|
|
|
49
43
|
v-if="media && media.mType === 'audio'"
|
|
50
44
|
ref="audio"
|
|
51
45
|
tabindex="0"
|
|
52
|
-
class="m-audio"
|
|
46
|
+
class="v-media m-audio"
|
|
53
47
|
:poster="media.mPoster"
|
|
54
48
|
@loadedmetadata="updateMediaData($event)"
|
|
55
49
|
>
|
|
@@ -70,14 +64,24 @@
|
|
|
70
64
|
<div
|
|
71
65
|
v-if="media && hasAnimation"
|
|
72
66
|
id="anim-box"
|
|
67
|
+
ref="anim-box"
|
|
73
68
|
class="anim-canvas"
|
|
74
69
|
:class="[animationType]"
|
|
70
|
+
role="figure"
|
|
71
|
+
aria-roledescription="Animation"
|
|
75
72
|
>
|
|
73
|
+
<p class="sr-only">{{ mediaA11Y.srTxt }}</p>
|
|
74
|
+
<a class="skip-link" href="" @click.prevent="skipTo('playbar-play')">
|
|
75
|
+
{{ mediaA11Y.skipToTxt }}
|
|
76
|
+
</a>
|
|
76
77
|
<slot ref="animScene" name="drawingCanvas">
|
|
77
78
|
You have an animation to create
|
|
78
79
|
</slot>
|
|
79
80
|
</div>
|
|
80
|
-
<
|
|
81
|
+
<!-- <div v-if="mData"> -->
|
|
82
|
+
<app-comp-play-bar :media-to-play="mData" />
|
|
83
|
+
<!-- </div> -->
|
|
84
|
+
<!-- <portal-target :key="$route.fullPath" name="playbar-portal"></portal-target> -->
|
|
81
85
|
</div>
|
|
82
86
|
</template>
|
|
83
87
|
|
|
@@ -106,13 +110,18 @@ export default {
|
|
|
106
110
|
timeline: null,
|
|
107
111
|
subtitleMenuButtons: [],
|
|
108
112
|
subtitlesMenu: null,
|
|
109
|
-
randKey: `kid_${Math.floor(Math.random() * 1001)}`,
|
|
110
113
|
fsHeigh: null,
|
|
111
114
|
isMedia: false
|
|
115
|
+
//currentMediaElement: null
|
|
112
116
|
}
|
|
113
117
|
},
|
|
114
118
|
computed: {
|
|
115
|
-
...mapGetters([
|
|
119
|
+
...mapGetters([
|
|
120
|
+
'hasMediaElOrTimeline',
|
|
121
|
+
'getCurrentBrowser',
|
|
122
|
+
'getCurrentPage'
|
|
123
|
+
]),
|
|
124
|
+
|
|
116
125
|
setTimeout() {
|
|
117
126
|
return window.setTimeout
|
|
118
127
|
},
|
|
@@ -149,20 +158,32 @@ export default {
|
|
|
149
158
|
} else {
|
|
150
159
|
return 'chrome'
|
|
151
160
|
}
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
mediaA11Y() {
|
|
164
|
+
let m = {
|
|
165
|
+
srTxt: '',
|
|
166
|
+
skipToTxt: ''
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
this.$i18n.locale === 'fr'
|
|
170
|
+
? (m = {
|
|
171
|
+
srTxt:
|
|
172
|
+
"Le contenu d'apprentissage sera seulement disponible à la fin de la narration. Appuyez le bouton jouer, pour lancer l'animation.",
|
|
173
|
+
skipToTxt: 'Passer au controleur de media'
|
|
174
|
+
})
|
|
175
|
+
: (m = {
|
|
176
|
+
srTxt:
|
|
177
|
+
'The learning content will be available only at the end of the narration. Press the play button to start the animation',
|
|
178
|
+
skipToTxt: 'Skip to play-bar'
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
return m
|
|
152
182
|
}
|
|
153
183
|
},
|
|
154
184
|
watch: {
|
|
155
|
-
media(
|
|
185
|
+
media() {
|
|
156
186
|
let mElement = this.$refs[this.media.mType]
|
|
157
|
-
if (oldVal === null && val !== oldVal) {
|
|
158
|
-
//this.$store.dispatch('updateAppStatus', 'loading')
|
|
159
|
-
//this.$store.dispatch('updateCurrentMediaElement', mElement)
|
|
160
|
-
//this.fecthFromServer(this.media.mSources)
|
|
161
|
-
// for (let m of this.media.mSources) {
|
|
162
|
-
// this.checkRessource(m.src)
|
|
163
|
-
// }
|
|
164
|
-
}
|
|
165
|
-
|
|
166
187
|
/* Handeling media subtitles
|
|
167
188
|
* if there is any subtitle, create the subtitle menu
|
|
168
189
|
*/
|
|
@@ -208,6 +229,7 @@ export default {
|
|
|
208
229
|
if (this.media) {
|
|
209
230
|
window.addEventListener('resize', this.caclWindowHeight)
|
|
210
231
|
}
|
|
232
|
+
this.currentMediaElement
|
|
211
233
|
},
|
|
212
234
|
|
|
213
235
|
beforeDestroy() {
|
|
@@ -293,13 +315,75 @@ export default {
|
|
|
293
315
|
.catch((err) => {
|
|
294
316
|
err
|
|
295
317
|
})
|
|
318
|
+
},
|
|
319
|
+
/**
|
|
320
|
+
* @description- Skip directly to the specify containt/region*
|
|
321
|
+
* main content is Node with defined ID
|
|
322
|
+
* @param {String} targetID- Css selector for the target element
|
|
323
|
+
*/
|
|
324
|
+
|
|
325
|
+
skipTo(targetID) {
|
|
326
|
+
let skipTo = document.querySelector(`#wrapper-content`) //default definition of main element
|
|
327
|
+
|
|
328
|
+
if (targetID) {
|
|
329
|
+
let targetEl = document.querySelector(`#${targetID}`) // search for node element specified as main
|
|
330
|
+
|
|
331
|
+
if (targetEl) skipTo = targetEl
|
|
332
|
+
}
|
|
333
|
+
let targetTop = skipTo.offsetTop
|
|
334
|
+
|
|
335
|
+
let scrollOpt = {
|
|
336
|
+
top: targetTop - 100,
|
|
337
|
+
left: 0,
|
|
338
|
+
behavior: 'auto' //auto
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
//Allowing accessibility control with keyboard
|
|
342
|
+
skipTo.setAttribute('tabIndex', -1)
|
|
343
|
+
window.scrollTo(scrollOpt)
|
|
344
|
+
skipTo.focus()
|
|
345
|
+
},
|
|
346
|
+
|
|
347
|
+
async setMediaElement() {
|
|
348
|
+
const { type } = await this.getCurrentPage
|
|
349
|
+
if (!['pg_media, pg_animation'].includes(type)) return null
|
|
350
|
+
|
|
351
|
+
let mediaObject = {}
|
|
352
|
+
switch (type) {
|
|
353
|
+
case 'pg_media': {
|
|
354
|
+
const {
|
|
355
|
+
animation,
|
|
356
|
+
type,
|
|
357
|
+
mediaData: { mSources, mType, mSubtitle, mPoster, mTranscript },
|
|
358
|
+
timeline,
|
|
359
|
+
mElement
|
|
360
|
+
} = this.getCurrentPage
|
|
361
|
+
|
|
362
|
+
mediaObject = {
|
|
363
|
+
animation,
|
|
364
|
+
type,
|
|
365
|
+
mediaData: { mSources, mType, mSubtitle, mPoster, mTranscript },
|
|
366
|
+
timeline,
|
|
367
|
+
mElement
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
break
|
|
371
|
+
}
|
|
372
|
+
case 'pg_animation': {
|
|
373
|
+
const { animation, type, timeline } = this.getCurrentPage
|
|
374
|
+
mediaObject = { animation, type, timeline }
|
|
375
|
+
break
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return mediaObject
|
|
296
380
|
}
|
|
297
381
|
}
|
|
298
382
|
}
|
|
299
383
|
</script>
|
|
300
384
|
<style lang="scss">
|
|
301
385
|
$widthVideo: 100%;
|
|
302
|
-
$widthAudioAnimation:
|
|
386
|
+
$widthAudioAnimation: 50%;
|
|
303
387
|
|
|
304
388
|
%animation {
|
|
305
389
|
position: absolute;
|
|
@@ -310,56 +394,4 @@ $widthAudioAnimation: 100%;
|
|
|
310
394
|
z-index: 1;
|
|
311
395
|
overflow: hidden;
|
|
312
396
|
}
|
|
313
|
-
|
|
314
|
-
.app-media-player {
|
|
315
|
-
position: relative;
|
|
316
|
-
overflow: hidden;
|
|
317
|
-
|
|
318
|
-
&.AudioAnimation {
|
|
319
|
-
width: $widthAudioAnimation;
|
|
320
|
-
.anim-canvas {
|
|
321
|
-
@extend %animation;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
&.FS,
|
|
326
|
-
&.animationOnly {
|
|
327
|
-
width: 100%;
|
|
328
|
-
position: absolute;
|
|
329
|
-
top: 0;
|
|
330
|
-
left: 0;
|
|
331
|
-
|
|
332
|
-
video {
|
|
333
|
-
min-width: 100% !important;
|
|
334
|
-
min-height: 100% !important;
|
|
335
|
-
position: absolute !important;
|
|
336
|
-
top: 50% !important;
|
|
337
|
-
left: 50% !important;
|
|
338
|
-
transform: translate(-50%, -50%) !important;
|
|
339
|
-
z-index: 9;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
.anim-canvas {
|
|
343
|
-
@extend %animation;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
&.FS,
|
|
348
|
-
&.AudioAnimation {
|
|
349
|
-
width: 100%;
|
|
350
|
-
position: absolute;
|
|
351
|
-
top: 0;
|
|
352
|
-
left: 0;
|
|
353
|
-
|
|
354
|
-
.anim-canvas {
|
|
355
|
-
@extend %animation;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
video {
|
|
361
|
-
&:focus-visible {
|
|
362
|
-
outline-color: transparent;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
397
|
</style>
|
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
<!--
|
|
2
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 AppCompMenuItem
|
|
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
4
|
-->
|
|
5
5
|
<template>
|
|
6
6
|
<div class="menu-container">
|
|
7
|
-
<b-row>
|
|
8
|
-
<b-col md="
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
</b-link>
|
|
7
|
+
<b-row align-v="center" align-h="center">
|
|
8
|
+
<b-col md="10" class="wrapper-lasRoute">
|
|
9
|
+
<div class="box-menu">
|
|
10
|
+
<h1>{{ getLessonid }}</h1>
|
|
11
|
+
<h2 v-html="getLessonTitle"></h2>
|
|
12
|
+
<p class="lesson-progess">{{ lessonProg() }}</p>
|
|
13
|
+
<b-link
|
|
14
|
+
id="btn_last_route"
|
|
15
|
+
class="nav_last_route"
|
|
16
|
+
:title="handelLabel"
|
|
17
|
+
:to="{ name: GoToLastRoute() }"
|
|
18
|
+
>
|
|
19
|
+
{{ handelLabel }}
|
|
20
|
+
</b-link>
|
|
21
|
+
</div>
|
|
25
22
|
</b-col>
|
|
23
|
+
<b-col
|
|
24
|
+
md="10"
|
|
25
|
+
class="wrapper-MenuItem"
|
|
26
|
+
title="table of content for this lesson"
|
|
27
|
+
>
|
|
28
|
+
<h3>{{ $t('text.activity_title') }}</h3>
|
|
26
29
|
|
|
27
|
-
<b-col md="8" class="wrapper-MenuItem">
|
|
28
30
|
<app-comp-menu-item></app-comp-menu-item>
|
|
29
31
|
</b-col>
|
|
30
32
|
</b-row>
|
|
@@ -36,15 +38,23 @@ import { mapGetters } from 'vuex'
|
|
|
36
38
|
|
|
37
39
|
export default {
|
|
38
40
|
name: 'AppCompMenu',
|
|
41
|
+
data() {
|
|
42
|
+
return {
|
|
43
|
+
totalAttempts: 0
|
|
44
|
+
}
|
|
45
|
+
},
|
|
39
46
|
computed: {
|
|
40
47
|
...mapGetters([
|
|
41
48
|
'getRouteHistory',
|
|
42
49
|
'getAllActivitiesState',
|
|
50
|
+
'getAllCompleted',
|
|
51
|
+
'getModuleInfo',
|
|
52
|
+
'getMenuSettings',
|
|
43
53
|
'getAllCompleted'
|
|
44
54
|
]),
|
|
45
55
|
handelLabel() {
|
|
46
56
|
let label = ''
|
|
47
|
-
const { allActivitiesState, allCompleted } = this.
|
|
57
|
+
const { allActivitiesState, allCompleted } = this.progressWithMenu()
|
|
48
58
|
|
|
49
59
|
let activity = Object.values(allActivitiesState)
|
|
50
60
|
let completeActivity = Object.values(allCompleted)
|
|
@@ -59,6 +69,21 @@ export default {
|
|
|
59
69
|
}
|
|
60
70
|
}
|
|
61
71
|
return label
|
|
72
|
+
},
|
|
73
|
+
getLessonid() {
|
|
74
|
+
// ATTENDRE UX*UI poure voir si on garde le concept ou pas
|
|
75
|
+
let lessonLabel = this.$t('text.lesson')
|
|
76
|
+
let lessonId = 99
|
|
77
|
+
return `${lessonLabel} ${lessonId}`
|
|
78
|
+
},
|
|
79
|
+
getLessonTitle() {
|
|
80
|
+
let lessonT
|
|
81
|
+
if (this.getMenuSettings.lessonTitle) {
|
|
82
|
+
lessonT = this.getMenuSettings.lessonTitle
|
|
83
|
+
} else {
|
|
84
|
+
lessonT = 'Entrer un titre à votre dans menu setting svp.'
|
|
85
|
+
}
|
|
86
|
+
return `${lessonT}`
|
|
62
87
|
}
|
|
63
88
|
},
|
|
64
89
|
created() {},
|
|
@@ -69,14 +94,14 @@ export default {
|
|
|
69
94
|
let path
|
|
70
95
|
|
|
71
96
|
//Get all activity state (menu not included)
|
|
72
|
-
const { allActivitiesState } = this.
|
|
97
|
+
const { allActivitiesState } = this.progressWithMenu()
|
|
73
98
|
let state = Object.values(allActivitiesState)
|
|
74
99
|
|
|
75
100
|
if (this.getRouteHistory.length) {
|
|
76
101
|
if (this.getRouteHistory.length == 1) {
|
|
77
102
|
lastRoute = this.getRouteHistory[0]
|
|
78
103
|
} else {
|
|
79
|
-
lastRoute = this.getRouteHistory[this.getRouteHistory.length -
|
|
104
|
+
lastRoute = this.getRouteHistory[this.getRouteHistory.length - 1]
|
|
80
105
|
}
|
|
81
106
|
}
|
|
82
107
|
|
|
@@ -90,6 +115,7 @@ export default {
|
|
|
90
115
|
if (lastRoute) path = this.createdRoute(lastRoute)
|
|
91
116
|
return path
|
|
92
117
|
},
|
|
118
|
+
|
|
93
119
|
noProgress(obj) {
|
|
94
120
|
//validator to see if anything was seen before
|
|
95
121
|
for (let i = 0; i < obj.length; i++) {
|
|
@@ -104,54 +130,27 @@ export default {
|
|
|
104
130
|
let page
|
|
105
131
|
let path
|
|
106
132
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
activity = newRoute.activity_ref.substr(2)
|
|
133
|
+
const typesToCatch = ['menu', 'introduction', 'conclusion']
|
|
134
|
+
//Define activity
|
|
135
|
+
if (typesToCatch.includes(newRoute.type)) {
|
|
136
|
+
activity = newRoute.type
|
|
112
137
|
} else {
|
|
113
|
-
activity =
|
|
138
|
+
activity =
|
|
139
|
+
newRoute.activity_ref.charAt(1) == '0'
|
|
140
|
+
? `activite_${newRoute.activity_ref.substring(2)}`
|
|
141
|
+
: `activite_${newRoute.activity_ref.substring(1)}`
|
|
114
142
|
}
|
|
115
|
-
if (newRoute.activity_ref && newRoute.activity_ref !== 'A00') {
|
|
116
|
-
// create link for page when you are in the intro
|
|
117
|
-
if (newRoute.id.charAt(1) == '0' || newRoute.id.charAt(1) == 0) {
|
|
118
|
-
page = newRoute.id.substr(2)
|
|
119
|
-
} else {
|
|
120
|
-
page = newRoute.id.substr(1)
|
|
121
|
-
}
|
|
122
|
-
// create link for any ativity
|
|
123
|
-
if (page == '1' || page == 1) {
|
|
124
|
-
path = `activite_${activity}`
|
|
125
|
-
} else {
|
|
126
|
-
path = `activite_${activity}.page_${page}`
|
|
127
|
-
}
|
|
128
|
-
} else {
|
|
129
|
-
// create link for page when you are not in the intro
|
|
130
|
-
let str = newRoute.id.substr(newRoute.id.indexOf('-') + 1)
|
|
131
143
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
144
|
+
//Define page
|
|
145
|
+
const idToIgnore = ['P01', 'pg_menu']
|
|
146
|
+
page = idToIgnore.includes(newRoute.id) ? ' ' : newRoute.id.substring(2)
|
|
147
|
+
|
|
148
|
+
//Define path
|
|
149
|
+
path = page !== ' ' ? `${activity}.page_${page}` : activity
|
|
137
150
|
|
|
138
|
-
// CREATE LINK if it was the intro
|
|
139
|
-
if (page == '1' || page == 1) {
|
|
140
|
-
path = `introduction`
|
|
141
|
-
} else if (page == '0' || page == 0) {
|
|
142
|
-
path = `menu`
|
|
143
|
-
} else {
|
|
144
|
-
path = `introduction.page_${page}`
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
151
|
return path
|
|
148
152
|
},
|
|
149
|
-
|
|
150
|
-
//get the page which is defined as the menu
|
|
151
|
-
const toIgnore = this.$helper
|
|
152
|
-
.getRoutesFromVueRouter('A00')
|
|
153
|
-
.all_routes.find((el) => el.name === 'menu').meta.id
|
|
154
|
-
|
|
153
|
+
progressWithMenu() {
|
|
155
154
|
/*
|
|
156
155
|
* Note:
|
|
157
156
|
* 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
|
|
@@ -172,31 +171,38 @@ export default {
|
|
|
172
171
|
) {
|
|
173
172
|
let completedIntro = allCompleted[activity]
|
|
174
173
|
|
|
175
|
-
//remove the "menu page from the completed in intro
|
|
176
|
-
completedIntro = completedIntro.filter(
|
|
177
|
-
(el) => Object.keys(el)[0] !== toIgnore
|
|
178
|
-
)
|
|
179
|
-
|
|
180
174
|
if (!completedIntro.length) completedIntro = []
|
|
181
175
|
|
|
182
176
|
allCompleted[activity] = completedIntro
|
|
183
|
-
|
|
184
|
-
// Remove menu page from the activity state tracking
|
|
185
|
-
let introState = allActivitiesState[activity].progressions
|
|
186
|
-
if (introState.length) {
|
|
187
|
-
introState = introState.filter(
|
|
188
|
-
(el) => Object.keys(el)[0] !== toIgnore
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
allActivitiesState[activity].progressions = introState
|
|
192
|
-
allActivitiesState[activity].size -= 1
|
|
193
|
-
}
|
|
194
177
|
}
|
|
195
178
|
}
|
|
179
|
+
|
|
196
180
|
return {
|
|
197
181
|
allActivitiesState,
|
|
198
182
|
allCompleted
|
|
199
183
|
}
|
|
184
|
+
},
|
|
185
|
+
lessonProg() {
|
|
186
|
+
let lstActivity = Object.keys(this.getAllActivitiesState)
|
|
187
|
+
let progress = null
|
|
188
|
+
let info = this.progressWithMenu()
|
|
189
|
+
let page = null
|
|
190
|
+
let pageCmplt = null
|
|
191
|
+
|
|
192
|
+
lstActivity.forEach((element) => {
|
|
193
|
+
//Get the total of all the page
|
|
194
|
+
page += info.allActivitiesState[element].size
|
|
195
|
+
|
|
196
|
+
if (info.allCompleted[element]) {
|
|
197
|
+
// GEt all page complete
|
|
198
|
+
pageCmplt += Object.values(info.allCompleted[element]).length
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
// Create pourcentage complete
|
|
203
|
+
progress = Math.round((pageCmplt * 100) / page)
|
|
204
|
+
|
|
205
|
+
return `${progress}%`
|
|
200
206
|
}
|
|
201
207
|
}
|
|
202
208
|
}
|