fcad-core-dragon 2.0.0-beta.0 → 2.0.0-beta.2

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 (84) hide show
  1. package/{.eslintrc.js → .eslintrc.cjs} +13 -18
  2. package/README.md +1 -1
  3. package/bk.scss +117 -0
  4. package/package.json +22 -40
  5. package/src/$locales/en.json +57 -19
  6. package/src/$locales/fr.json +66 -28
  7. package/src/components/AppBase.vue +790 -376
  8. package/src/components/AppBaseButton.vue +33 -5
  9. package/src/components/AppBaseErrorDisplay.vue +62 -25
  10. package/src/components/AppBaseModule.vue +831 -754
  11. package/src/components/AppBasePage.vue +60 -74
  12. package/src/components/AppCompAudio.vue +266 -0
  13. package/src/components/AppCompBranchButtons.vue +79 -89
  14. package/src/components/AppCompButtonProgress.vue +35 -61
  15. package/src/components/AppCompCarousel.vue +160 -249
  16. package/src/components/AppCompInputCheckBox.vue +9 -3
  17. package/src/components/AppCompInputDropdown.vue +2 -4
  18. package/src/components/AppCompInputRadio.vue +8 -15
  19. package/src/components/AppCompInputTextTable.vue +15 -12
  20. package/src/components/AppCompInputTextToFillDropdown.vue +16 -14
  21. package/src/components/AppCompInputTextToFillText.vue +2 -2
  22. package/src/components/AppCompJauge.vue +14 -3
  23. package/src/components/AppCompMenu.vue +284 -85
  24. package/src/components/AppCompMenuItem.vue +67 -92
  25. package/src/components/AppCompNavigation.vue +945 -0
  26. package/src/components/AppCompNoteCall.vue +141 -0
  27. package/src/components/AppCompNoteCredit.vue +267 -0
  28. package/src/components/AppCompPlayBar.vue +1122 -1391
  29. package/src/components/AppCompPlayBarProgress.vue +73 -0
  30. package/src/components/AppCompPopUp.vue +195 -135
  31. package/src/components/AppCompPopover.vue +27 -0
  32. package/src/components/AppCompQuiz.vue +90 -113
  33. package/src/components/AppCompQuizRecall.vue +277 -0
  34. package/src/components/AppCompSVG.vue +335 -0
  35. package/src/components/AppCompSettingsMenu.vue +7 -8
  36. package/src/components/AppCompTableOfContent.vue +264 -88
  37. package/src/components/AppCompTranscript.vue +19 -0
  38. package/src/components/AppCompVideoPlayer.vue +380 -0
  39. package/src/components/BaseModule.vue +37 -114
  40. package/src/main.js +130 -85
  41. package/src/mixins/$mediaMixins.js +827 -0
  42. package/src/mixins/$pageMixins.js +149 -115
  43. package/src/mixins/$quizMixins.js +12 -26
  44. package/src/mixins/timerMixin.js +39 -16
  45. package/src/module/store.js +218 -78
  46. package/src/module/xapi/ADL.js +90 -53
  47. package/src/module/xapi/Crypto/Hasher.js +8 -8
  48. package/src/module/xapi/Crypto/WordArray.js +6 -6
  49. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +4 -4
  50. package/src/module/xapi/Crypto/algorithms/C_algo.js +14 -18
  51. package/src/module/xapi/Crypto/algorithms/HMAC.js +1 -1
  52. package/src/module/xapi/Crypto/algorithms/SHA1.js +1 -1
  53. package/src/module/xapi/Crypto/encoders/Base.js +7 -7
  54. package/src/module/xapi/Crypto/encoders/Base64.js +3 -3
  55. package/src/module/xapi/Crypto/encoders/Hex.js +4 -3
  56. package/src/module/xapi/Crypto/encoders/Latin1.js +3 -3
  57. package/src/module/xapi/Crypto/encoders/Utf8.js +3 -3
  58. package/src/module/xapi/Statement/index.js +1 -1
  59. package/src/module/xapi/launch.js +10 -10
  60. package/src/module/xapi/utils.js +17 -17
  61. package/src/module/xapi/wrapper.js +127 -54
  62. package/src/module/xapi/xapiStatement.js +29 -29
  63. package/src/plugins/gsap.js +4 -1
  64. package/src/plugins/helper.js +58 -24
  65. package/src/plugins/i18n.js +23 -10
  66. package/src/plugins/idb.js +1 -0
  67. package/src/plugins/scorm.js +14 -14
  68. package/src/public/index.html +1 -1
  69. package/src/router/index.js +40 -0
  70. package/src/router/routes.js +317 -0
  71. package/src/shared/generalfuncs.js +91 -9
  72. package/src/shared/validators.js +959 -0
  73. package/.prettierrc.js +0 -5
  74. package/babel.config.js +0 -3
  75. package/src/components/AppBaseDragChoice.vue +0 -91
  76. package/src/components/AppBaseDropZone.vue +0 -112
  77. package/src/components/AppCompDragAndDrop.vue +0 -339
  78. package/src/components/AppCompInputAssociation.vue +0 -332
  79. package/src/components/AppCompMediaPlayer.vue +0 -365
  80. package/src/components/AppCompNavigationFull.vue +0 -1791
  81. package/src/components/AppCompToolTip.vue +0 -94
  82. package/src/plugins/timeManager.js +0 -77
  83. package/src/routes.js +0 -734
  84. package/vue.config.js +0 -83
@@ -1,45 +1,54 @@
1
1
  <!--
2
+ ----------------- MUST ADD ERROR GESTION ------------------
3
+ ----------------- MUST ADD label terminer ------------------
4
+ ----------------- MUST ADD css ------------------
5
+
2
6
  @ Description: This component is used to display the sub menu to show the anchor of a activity.
3
7
  @ What it does: The component show the data that was enter in menu.json and create de link to the anchor from those information. This componant must be use with app-comp-menu-Item and app-comp-menu.
4
8
  -->
5
9
 
6
10
  <template>
7
- <b-sidebar id="sidebar-submenu" backdrop shadow right>
8
- <div class="box">
9
- <div class="box-time">
10
- <p>{{ time }}</p>
11
- </div>
11
+ <div v-if="error" id="sidebar-submenu" :class="{ isOpen: open }">
12
+ <app-base-button
13
+ id="close-toc"
14
+ :title="$t('button.closePopUp')"
15
+ @click="close()"
16
+ >
17
+ X
18
+ </app-base-button>
12
19
 
13
- <div class="box-contenu">
14
- <div class="box-ttl">
15
- <h2>{{ title }}</h2>
20
+ <p class="t-act" v-html="title"></p>
16
21
 
17
- <h3>{{ subtitle }}</h3>
18
- </div>
22
+ <div class="box-prog-act">
23
+ <p>
24
+ {{ $t('text.activity_progress') }}
25
+ <span>{{ actProgress }}</span>
26
+ </p>
27
+ </div>
19
28
 
20
- <div class="container-anchor">
21
- <div
22
- v-for="(anchor, index) of anchors"
23
- :id="activityId + '-submenu-anchor-' + index"
24
- :key="index"
25
- class="box-sa"
26
- >
27
- <b-link
28
- :to="{
29
- name: anchor.path,
30
- hash: (() => (anchor.anchorTag ? `#${anchor.anchorTag}` : ''))()
31
- }"
32
- @click="scrollToAnchor($event)"
33
- >
34
- <span @click="scrollToAnchor($event)">
35
- {{ anchor.anchorName }}
36
- </span>
37
- </b-link>
38
- </div>
29
+ <div class="box-anchor">
30
+ <p class="t-toc">{{ $t('text.toc') }}</p>
31
+
32
+ <b-link
33
+ v-for="(anchor, index) of anchors"
34
+ :key="anchor.title"
35
+ class="toc-item"
36
+ :done="sectionProgress(index)"
37
+ @click="closeAndNextPage(anchor.path)"
38
+ >
39
+ <div class="box-text-anchor">
40
+ <p class="anchor-t" v-html="anchor.title"></p>
41
+ <p class="state">{{ $t('text.complete') }}</p>
39
42
  </div>
40
- </div>
43
+ </b-link>
41
44
  </div>
42
- </b-sidebar>
45
+ </div>
46
+ <div v-else id="sidebar-submenu" :class="{ isOpen: open }">
47
+ <p>
48
+ Cette activité n'existe pas dans menu setting, svp l'ajouter à votre menu
49
+ setting
50
+ </p>
51
+ </div>
43
52
  </template>
44
53
 
45
54
  <script>
@@ -48,53 +57,116 @@ import { mapGetters } from 'vuex'
48
57
  export default {
49
58
  data() {
50
59
  return {
51
- //activitiSubMenu: [],
52
- activityId: null,
53
60
  title: '',
54
- subtitle: '',
55
- time: '',
56
61
  anchors: [],
57
- activity: ''
62
+ activity: '',
63
+ open: false,
64
+ menuInfo: null,
65
+ actProgress: null,
66
+ error: true
58
67
  }
59
68
  },
60
69
  computed: {
61
- ...mapGetters(['getMenuSettings', 'getAnchorsForActivity', 'getBifChoice'])
70
+ ...mapGetters([
71
+ 'getMenuSettings',
72
+ 'getAnchorsForActivity',
73
+ 'getBifChoice',
74
+ 'getAllCompleted',
75
+ 'getAllActivitiesState'
76
+ ])
77
+ },
78
+ beforeUnmount() {
79
+ this.$bus.$off('toggle-widget', this.onToggleWidget)
80
+ this.$bus.$off('close-widget', this.onCloseWidget)
81
+ this.$bus.$off('info-activity', this.onInfoActivity)
62
82
  },
63
83
  mounted() {
64
- this.$bus.$on('info-activity', (data) => {
84
+ this.$bus.$on('toggle-widget', this.onToggleWidget)
85
+ this.$bus.$on('close-widget', this.onCloseWidget)
86
+ this.$bus.$on('info-activity', this.onInfoActivity)
87
+ },
88
+ methods: {
89
+ onInfoActivity(data) {
65
90
  //should be condition to avoid event fireing multiple time on call
91
+
66
92
  if (data) {
93
+ this.reset()
67
94
  this.activity = data
68
- //this.getInfoSubMenu(this.activity)
69
- this.getInfoSubMenu(data)
95
+
96
+ if (!this.getMenuSettings[data]) {
97
+ return (this.error = false)
98
+ } else {
99
+ this.getInfoSubMenu(data)
100
+ this.getProgressActivity(data)
101
+ }
70
102
  }
71
- })
72
- },
73
- methods: {
103
+ },
104
+ onCloseWidget(data) {
105
+ this.open = false
106
+ this.$store.dispatch('updateWidgetOpen', false)
107
+ this.reset()
108
+ },
109
+ onToggleWidget(data) {
110
+ if (data == 'toc') {
111
+ this.open = !this.open
112
+ this.$store.dispatch('updateWidgetOpen', true)
113
+ } else {
114
+ this.$store.dispatch('updateWidgetOpen', false)
115
+ this.open = false
116
+ }
117
+ },
74
118
  /* @Description:Get and set the section to output
75
119
  * @params: activity {Object}: the activity which sections need to be output
76
120
  */
77
121
  //
78
122
  getInfoSubMenu(activity) {
79
- if (activity) {
80
- this.title = activity.title
81
- this.subtitle = activity.subtitle
82
- this.time = activity.time
83
-
84
- //get the anchors for this activity from the store
85
- let menuInfo = this.getMenuSettings
86
-
87
- if (menuInfo[activity.id] && menuInfo[activity.id].anchors) {
88
- const anchors = menuInfo[activity.id].anchors
89
- this.buildAnchorsRoutes(anchors)
90
- } else this.anchors = []
91
- } else {
92
- this.title = ''
93
- this.subtitle = ''
94
- this.time = ''
123
+ //get the anchors for this activity from the store
124
+ let menuInfo = this.getMenuSettings
125
+
126
+ let nb = null
127
+
128
+ //Get title are if no title construct acitivty
129
+ if (menuInfo[activity] && menuInfo[activity].title)
130
+ this.title = menuInfo[activity].title
131
+
132
+ if (activity.charAt(1) == '0' || activity.charAt(1) == 0)
133
+ nb = activity.substr(2)
134
+ else nb = activity.substr(1)
135
+
136
+ this.title = `${this.$t('text.activity')} ${nb} : ${
137
+ menuInfo[activity].subTitle
138
+ }`
139
+
140
+ let count = 0
141
+
142
+ //create anchors title and path
143
+ if (menuInfo[activity] && menuInfo[activity].anchors) {
144
+ menuInfo[activity].anchors.forEach((element) => {
145
+ count++
146
+
147
+ //
148
+ let _path = null
149
+ let b = null
150
+ if (nb == 0 || nb == '0') {
151
+ b = `introduction`
152
+ } else {
153
+ b = `activite_${nb}`
154
+ }
155
+
156
+ if (element.page == 'page_1') {
157
+ _path = `${b}`
158
+ } else {
159
+ _path = `${b}.${element.page}`
160
+ }
161
+
162
+ let info = {
163
+ title: `${element.anchorName}`,
164
+ path: _path
165
+ }
166
+ this.anchors.push(info)
167
+ })
95
168
  }
96
169
  },
97
-
98
170
  disable(data) {
99
171
  let page = data.pageRef
100
172
  let act = this.getAct(data.path)
@@ -112,7 +184,7 @@ export default {
112
184
  }
113
185
  },
114
186
  getAct(data) {
115
- //return data.substring(data.indexOf('_'))
187
+ //return the id need it
116
188
  if (data) {
117
189
  if (data.substring(data.indexOf('_') + 1).length == 1) {
118
190
  return `A0${data.substring(data.indexOf('_') + 1)}`
@@ -121,49 +193,142 @@ export default {
121
193
  }
122
194
  }
123
195
  },
124
- /* @Description:build the route for the anchors in the menu
196
+ /**
197
+ * @description Gives gives length of completed page for an activity
198
+ * @param {String} idActivity
199
+ * @returns {Number}
125
200
  */
126
- buildAnchorsRoutes(anchors) {
127
- //build the route for each anchors
128
- for (let a of anchors) {
129
- let _path = ''
130
- if (a.page === 'page_1') _path = this.activity.path
131
- else _path = `${this.activity.path}.${a.page}`
132
- a.path = _path
201
+ getProgressActivity(idActivity) {
202
+ /// give all the page that are complete to the gauge
203
+ if (idActivity) {
204
+ let completed = []
205
+ if (this.getAllCompleted[idActivity]) {
206
+ completed = this.getAllCompleted[idActivity] //get all completed page for the activity
207
+ }
208
+
209
+ const allActivitiesState = JSON.parse(
210
+ JSON.stringify(this.getAllActivitiesState)
211
+ )
212
+ let size = allActivitiesState[idActivity]
213
+ ? allActivitiesState[idActivity].size
214
+ : 0
215
+
216
+ // return pourcent of activity completion
217
+ this.actProgress = `${Math.round((completed.length * 100) / size)} %`
133
218
  }
134
- this.anchors = anchors
135
219
  },
220
+ close() {
221
+ this.open = !this.open
222
+ this.$store.dispatch('updateWidgetOpen', this.open)
223
+ },
224
+ closeAndNextPage(NextPage) {
225
+ this.$router.push({ name: NextPage })
226
+ this.open = !this.open
227
+ this.$store.dispatch('updateWidgetOpen', this.open)
228
+ },
229
+ reset() {
230
+ this.anchors = []
231
+ this.activity = ''
232
+ },
233
+ sectionProgress(index) {
234
+ let menuInfo = this.getMenuSettings
235
+ let nextIndex = index + 1
236
+ let nextSec
237
+ let curSec = menuInfo[this.activity].anchors[index].pageRef
136
238
 
137
- /**
138
- * @description signal a scoll action to perform by application.
139
- * - Send an update status for application to the Store
140
- * - send an anchor state update to the Store
141
- * - Send a scoll message to the $bus
142
- * - THIS METHODE DOES NOT PERFORM Scroll. scroll action will be perform by the PAGE after receiving the scroll message
143
- * @param {Object} event - the element that is the scoll target
144
- */
145
- scrollToAnchor(event) {
146
- // Making sure that the method will be executed in write sequence. Adding timeout with delay of 0 to solve asynchronicity issues.
147
- setTimeout(() => {
148
- // if there a Anchor to go to bus give the page the signasl to scroll
149
- if (this.$route.hash) {
150
- this.$store.dispatch('updateAppStatus', 'loading') // set the app status to ready
151
- this.$store.commit('UPDATE_ANCHOR_STATE', false)
152
- this.$bus.$emit('target-to-scroll', event.target)
239
+ let nb
240
+ let tabPageSec = []
241
+ let tabcomplete = []
242
+
243
+ if (nextIndex < menuInfo[this.activity].anchors.length) {
244
+ nextSec = menuInfo[this.activity].anchors[nextIndex].pageRef
245
+ }
246
+
247
+ if (nextSec != undefined) {
248
+ nb = parseInt(nextSec.substring(1))
249
+
250
+ while (nb > parseInt(curSec.substring(1))) {
251
+ nb--
252
+ if (nb < 10) tabPageSec.push(`P0${nb}`)
253
+ else tabPageSec.push(`P${nb}`)
153
254
  }
154
- }, 0)
255
+ } else {
256
+ if (menuInfo[this.activity].anchors.length == 1) {
257
+ let numPage = this.getAllActivitiesState[this.activity].size
258
+
259
+ for (let g = 1; g == numPage; g++) {
260
+ tabPageSec.push(`P${g}`)
261
+ }
262
+
263
+ if (
264
+ this.getAllCompleted[this.activity].length !==
265
+ this.getAllActivitiesState[this.activity].size
266
+ )
267
+ return false
268
+ }
269
+ tabPageSec.push(curSec)
270
+ }
271
+
272
+ let completeActPage = this.getAllCompleted[this.activity]
273
+
274
+ if (completeActPage) {
275
+ completeActPage.find((value) => {
276
+ let w = Object.keys(value)
277
+ tabcomplete.push(w[0])
278
+ })
279
+
280
+ const isSubset = (array1, array2) =>
281
+ array2.every((element) => array1.includes(element))
282
+
283
+ return isSubset(tabcomplete, tabPageSec)
284
+ }
155
285
  }
156
286
  }
157
287
  }
158
288
  </script>
159
289
  <style lang="scss">
160
290
  #sidebar-submenu {
291
+ display: none;
292
+ position: absolute;
293
+ left: 75px;
294
+ top: 0;
295
+ transition: left 0.5s ease-in-out;
296
+
297
+ &::before {
298
+ content: '';
299
+ display: block;
300
+ width: 0;
301
+ height: 0;
302
+ border-top: 10px solid transparent;
303
+ border-bottom: 10px solid transparent;
304
+ border-right: 10px solid;
305
+
306
+ position: absolute;
307
+ left: -10px;
308
+ top: 10px;
309
+ }
310
+
311
+ &.isOpen {
312
+ display: block;
313
+ }
314
+
161
315
  .b-sidebar-header {
162
316
  display: none;
163
317
  pointer-events: none;
164
318
  }
165
319
 
166
- .box {
320
+ .box-anchor {
321
+ .toc-item {
322
+ .state {
323
+ display: none;
324
+ }
325
+ &[done='true'] {
326
+ .state {
327
+ display: block;
328
+ }
329
+ }
330
+ }
331
+
167
332
  .box-time {
168
333
  width: 100%;
169
334
  padding: 10px 20px;
@@ -206,4 +371,15 @@ export default {
206
371
  }
207
372
  }
208
373
  }
374
+
375
+ .navbar {
376
+ &.show,
377
+ &:hover {
378
+ .ctn-w {
379
+ #sidebar-submenu {
380
+ left: 120px;
381
+ }
382
+ }
383
+ }
384
+ }
209
385
  </style>
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <div id="transcript-container" v-html="content"></div>
3
+ </template>
4
+ <script>
5
+ export default {
6
+ props: {
7
+ content: {
8
+ type: String,
9
+ default: `Hello Wolrd!`
10
+ }
11
+ }
12
+ }
13
+ </script>
14
+
15
+ <style lang="scss">
16
+ #transcript-container {
17
+ padding: 30px;
18
+ }
19
+ </style>