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

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 (72) hide show
  1. package/.eslintrc.cjs +1 -1
  2. package/CHANGELOG +9 -0
  3. package/package.json +26 -12
  4. package/src/$locales/en.json +37 -87
  5. package/src/$locales/fr.json +17 -106
  6. package/src/assets/data/onboardingMessages.json +1 -1
  7. package/src/components/AppBase.vue +241 -143
  8. package/src/components/AppBaseButton.vue +2 -6
  9. package/src/components/AppBaseErrorDisplay.vue +193 -183
  10. package/src/components/AppBaseFlipCard.vue +1 -0
  11. package/src/components/AppBaseModule.vue +195 -225
  12. package/src/components/AppBasePage.vue +519 -64
  13. package/src/components/AppBasePopover.vue +41 -0
  14. package/src/components/AppCompAudio.vue +32 -64
  15. package/src/components/AppCompBranchButtons.vue +52 -71
  16. package/src/components/AppCompButtonProgress.vue +12 -18
  17. package/src/components/AppCompCarousel.vue +102 -0
  18. package/src/components/{AppCompInputCheckBox.vue → AppCompInputCheckBoxNext.vue} +56 -94
  19. package/src/components/AppCompInputDropdownNext.vue +159 -0
  20. package/src/components/{AppCompInputRadio.vue → AppCompInputRadioNext.vue} +53 -63
  21. package/src/components/AppCompInputTextNext.vue +106 -0
  22. package/src/components/AppCompInputTextTableNext.vue +141 -0
  23. package/src/components/AppCompInputTextToFillDropdownNext.vue +230 -0
  24. package/src/components/{AppCompInputTextToFillText.vue → AppCompInputTextToFillNext.vue} +71 -64
  25. package/src/components/AppCompJauge.vue +16 -9
  26. package/src/components/AppCompMenu.vue +50 -29
  27. package/src/components/AppCompMenuItem.vue +52 -15
  28. package/src/components/AppCompNavigation.vue +225 -211
  29. package/src/components/AppCompNoteCall.vue +22 -30
  30. package/src/components/AppCompNoteCredit.vue +45 -20
  31. package/src/components/AppCompPlayBar.vue +55 -108
  32. package/src/components/AppCompPlayBarNext.vue +2052 -0
  33. package/src/components/AppCompPlayBarProgress.vue +10 -1
  34. package/src/components/AppCompPopUpNext.vue +503 -0
  35. package/src/components/{AppCompQuiz.vue → AppCompQuizNext.vue} +632 -703
  36. package/src/components/AppCompQuizRecall.vue +74 -75
  37. package/src/components/{AppCompSVG.vue → AppCompSVGNext.vue} +111 -99
  38. package/src/components/AppCompSettingsMenu.vue +11 -8
  39. package/src/components/AppCompTableOfContent.vue +78 -76
  40. package/src/components/AppCompTranscript.vue +5 -0
  41. package/src/components/AppCompVideoPlayer.vue +30 -42
  42. package/src/components/BaseModule.vue +1 -0
  43. package/src/composables/useQuiz.js +206 -0
  44. package/src/externalComps/ModuleView.vue +22 -0
  45. package/src/externalComps/SummaryView.vue +91 -0
  46. package/src/main.js +99 -90
  47. package/src/mixins/$mediaMixins.js +13 -21
  48. package/src/mixins/timerMixin.js +1 -1
  49. package/src/module/stores/appStore.js +901 -0
  50. package/src/module/xapi/ADL.js +8 -4
  51. package/src/plugins/bus.js +7 -2
  52. package/src/plugins/gsap.js +4 -7
  53. package/src/plugins/helper.js +33 -13
  54. package/src/plugins/i18n.js +2 -2
  55. package/src/plugins/idb.js +44 -29
  56. package/src/plugins/save.js +1 -1
  57. package/src/plugins/scorm.js +2 -2
  58. package/src/plugins/xapi.js +2 -2
  59. package/src/public/index.html +22 -10
  60. package/src/router/index.js +13 -10
  61. package/src/router/routes.js +20 -25
  62. package/src/shared/generalfuncs.js +33 -18
  63. package/src/shared/validators.js +116 -6
  64. package/src/components/AppCompInputDropdown.vue +0 -182
  65. package/src/components/AppCompInputTextBox.vue +0 -91
  66. package/src/components/AppCompInputTextTable.vue +0 -158
  67. package/src/components/AppCompInputTextToFillDropdown.vue +0 -257
  68. package/src/components/AppCompPopUp.vue +0 -583
  69. package/src/components/AppCompPopover.vue +0 -27
  70. package/src/mixins/$pageMixins.js +0 -415
  71. package/src/mixins/$quizMixins.js +0 -442
  72. package/src/module/store.js +0 -1014
@@ -1,583 +0,0 @@
1
- <template>
2
- <div>
3
- <div v-show="errors.length <= 0" class="p_popup">
4
- <!----------------------- POPUP CUSTOM ---------------------------->
5
- <b-modal
6
- v-show="isPopupCustom === true"
7
- id="popup-custom"
8
- ref="popup-custom"
9
- :content-class="[pType, pName]"
10
- :no-fade="animationOff"
11
- :header-close-label="$t('button.alert_close')"
12
- v-bind="{ ...pContent.$bvArgs }"
13
- @cancel="$cancel(pContent.cb_$cancel)"
14
- @ok="$confirm(pContent.cb_$confirm)"
15
- @hidden="$close(pContent.cb_$close)"
16
- >
17
- <template #default>
18
- <div class="box-content-popUp" v-html="pContent.hypertext" />
19
- </template>
20
- </b-modal>
21
- <!----------------------- OTHER POPUP ---------------------------->
22
- <b-modal
23
- v-show="isPopupCustom === false"
24
- :id="dynamicID"
25
- ref="someModal"
26
- :header-close-label="$t('button.alert_close')"
27
- :hide-footer="true"
28
- v-bind="pContent.$bvArgs"
29
- :content-class="[pType, pName, typeRetro, dynamicID]"
30
- :no-fade="animationOff"
31
- @hidden="$close(pContent.cb_$close)"
32
- >
33
- <!------------------- Custom DIV: Use to add any custom Css (visual) to your Popup ------------------------->
34
- <!-- <div v-show="pType == 'popup-retro'" class="pop-deco"></div> -->
35
- <!----------------------------- END Custom DIV ------------------------------------->
36
- <div class="popUp-title">
37
- <h4 v-html="pTitle"></h4>
38
- </div>
39
-
40
- <template v-if="contentLength > 0" class="box-content-popUp">
41
- <template v-for="(content, _key, index) of pContent">
42
- <!-------- Create TEXT element -------------->
43
- <p
44
- v-if="_key.includes('text') && !_key.includes('hyper')"
45
- :id="`${_key}_${index}`"
46
- :key="_key"
47
- >
48
- {{ content }}
49
- </p>
50
-
51
- <!-------- Create HTMLelement -------------->
52
- <div
53
- v-else-if="_key.includes('hypertext')"
54
- :id="`${_key}_${index}`"
55
- :key="`hyp_${_key}`"
56
- v-html="content"
57
- />
58
-
59
- <!-------- Create IMAGE element ------------->
60
- <img
61
- v-else-if="_key.includes('image')"
62
- :id="`${_key}_${index}`"
63
- :key="`img_${_key}`"
64
- :src="content.path"
65
- :alt="content.label || 'image'"
66
- />
67
-
68
- <!-------- Create LINK element -------------->
69
- <a
70
- v-else-if="_key.includes('link')"
71
- :id="`${_key}_${index}`"
72
- :key="`lnk_${_key}`"
73
- :href="content.ref"
74
- target="_blank"
75
- :title="`${content.label}`"
76
- >
77
- {{ content.label }}
78
- </a>
79
-
80
- <!-------- Create VIDEO element ------------->
81
- <video
82
- v-else-if="_key.includes('video')"
83
- :id="`${_key}_${index}`"
84
- :key="`vid_${_key}`"
85
- :src="content"
86
- controls
87
- disablepictureinpicture
88
- controlslist="nofullscreen nodownload"
89
- />
90
-
91
- <!--------Create AUDIO element--------------->
92
- <audio
93
- v-else-if="_key.includes('audio')"
94
- :id="`${_key}_${index}`"
95
- :key="`aud_${_key}`"
96
- :src="content"
97
- controls
98
- controlslist="nodownload"
99
- />
100
- </template>
101
- </template>
102
- <!--------Default Button of Pop up --------------->
103
- <div v-if="pType === 'popup-avert'" class="col-bouton">
104
- <app-base-button
105
- id="btn-cancel-popup"
106
- :name-acces="'Annuler'"
107
- class="btn-cancel"
108
- :title="$t('button.cancel_pop')"
109
- @click="$cancel(pContent.cb_$cancel)"
110
- >
111
- {{ $t('button.cancel_pop') }} toto
112
- </app-base-button>
113
- <app-base-button
114
- id="btn-confirm-popup"
115
- :name-acces="'Confirmer'"
116
- class="btn-confirm"
117
- :title="$t('button.confirm_pop')"
118
- @click="$confirm(pContent.cb_$confirm)"
119
- >
120
- {{ $t('button.confirm_pop') }}
121
- </app-base-button>
122
- </div>
123
- <div v-if="pType === 'popup-info'" class="popup-bottom-buttons">
124
- {{ pType }}
125
-
126
- <button
127
- id="popup-retro-close-btn"
128
- type="button"
129
- :title="$t('button.alert_close')"
130
- aria-label="Close"
131
- class="close"
132
- @click="$close(pContent.cb_$close)"
133
- >
134
- {{ $t('button.alert_close') }}
135
- </button>
136
- <portal-target
137
- id="end-activity"
138
- name="wrap-end-activity"
139
- ></portal-target>
140
- </div>
141
- <!----------------------------------------------------------------->
142
- <div v-if="pType === 'popup-endActivity'" class="popup-bottom-buttons">
143
- <portal-target
144
- id="end-activity"
145
- name="wrap-end-activity"
146
- ></portal-target>
147
- </div>
148
- </b-modal>
149
- </div>
150
- <div v-show="errors.length > 0" class="pop-error">
151
- <app-base-error-display :errors-list="errors" :doc-link="docLink" />
152
- </div>
153
- </div>
154
- </template>
155
-
156
- <script>
157
- //import { mapGetters } from 'vuex'
158
- export default {
159
- name: 'AppCompPopUp',
160
- data() {
161
- return {
162
- pType: 'popup-info',
163
- pName: 'noName',
164
- typeRetro: 'none',
165
- pContent: {},
166
- pContenttype: 'pg_normal',
167
- pTitle: '',
168
- errors: [],
169
- docLink:
170
- 'https://fcaddocumentation.netlify.app/guide/ressources.html#creer-un-popup-custom',
171
- animationOff: false
172
- }
173
- },
174
- computed: {
175
- contentLength() {
176
- let size = null
177
- if (this.pType && this.pType !== 'popup-custom') {
178
- if (this.pContent && Object.keys(this.pContent).length > 0)
179
- size = Object.keys(this.pContent).length
180
- }
181
- return size
182
- },
183
- isPopupCustom() {
184
- if (this.pType && this.pType === 'popup-custom') return true
185
- return false
186
- },
187
- popup() {
188
- /**
189
- * Get the istance of the bvModal that is open and return it as our active popup
190
- */
191
- let id
192
- if (this.isPopupCustom) id = 'popup-custom'
193
- else id = `${this.dynamicID}`
194
- const p = this.$bvModal._vm.$children.find((p) => p.id === id)
195
- return p
196
- },
197
- dynamicID() {
198
- let c
199
- c = 'not-popup-custom full'
200
- return c
201
- }
202
- },
203
- mounted() {
204
- this.$bus.$on('popup-open', (e) => {
205
- if (e) {
206
- this.validateContent(e)
207
- }
208
- })
209
- this.$bus.$on('popup-close', (options, cb) => {
210
- this.$close(options, cb)
211
- })
212
- this.$bus.$on('retro-type', (b) => {
213
- this.retroType(b)
214
- })
215
- },
216
- beforeUnmount() {
217
- this.$bus.$off('popup-open')
218
- this.$bus.$off('popup-close')
219
- this.$bus.$off('retro-type')
220
- },
221
- methods: {
222
- /**
223
- * @description - Validate the data for the component
224
- * @param {Object} data
225
- */
226
- validateContent(data) {
227
- const typeList = [
228
- 'popup-info',
229
- 'popup-retro',
230
- 'popup-avert',
231
- 'popup-custom',
232
- 'popup-noanswer',
233
- 'popup-endActivity'
234
- ]
235
- const callbacksFunctionList = [
236
- 'cb_$confirm',
237
- 'cb_$cancel',
238
- 'cb_$open',
239
- 'cb_$close'
240
- ]
241
-
242
- if (this.errors.length > 0) this.errors = []
243
-
244
- if (data.type) {
245
- // validate the type value of popup
246
- const validType = typeList.includes(data.type)
247
-
248
- if (!validType) this.errors.push('Invalid value for type')
249
- } else this.errors.push('Missing argument: type')
250
-
251
- // validate value of the popup according to popup type
252
- // Content must be String|Object
253
- if (data.value) {
254
- let validObject = false
255
- if (
256
- data.value.constructor === Object &&
257
- Object.keys(data.value).length > 0
258
- )
259
- validObject = true
260
- if (validObject) {
261
- let KeywordsList
262
- switch (true) {
263
- case data.type === 'popup-custom':
264
- KeywordsList = ['hypertext', '$bvArgs'] // accepted keyword in value declartion for pop-up custom
265
-
266
- for (const key of Object.keys(data.value)) {
267
- // search if key match lists
268
- if (![...KeywordsList, ...callbacksFunctionList].includes(key))
269
- this.errors.push(`Invalid key declaration in value : ${key}`)
270
-
271
- // Validating content of hypertext key
272
- if (
273
- key.includes('hypertext') &&
274
- data.value[key].constructor != String
275
- ) {
276
- this.errors.push(
277
- 'Invalid assignment for hypertext. Must be a String'
278
- )
279
- }
280
-
281
- // validating content of cb_$ keys
282
- if (
283
- key.includes('cb_$') &&
284
- data.value[key].constructor != Function
285
- ) {
286
- this.errors.push(
287
- `Invalid assignment for ${key}. Must be a Function`
288
- )
289
- }
290
-
291
- // validating content of $bvArgs keys. Must be an array.
292
- // validating content of $bvArgs. Content in $bvArgs must be objects
293
- if (
294
- (key.includes('$bvArgs') &&
295
- data.value[key].constructor != Array) ||
296
- (data.value[key].constructor === Array &&
297
- data.value[key].length < 1)
298
- ) {
299
- this.errors.push(
300
- `Invalid assignment for ${key}. Must be an Array of Objects`
301
- )
302
- } else if (
303
- key.includes('$bvArgs') &&
304
- data.value[key].constructor === Array &&
305
- data.value[key].length > 0
306
- ) {
307
- let count = 0
308
- data.value[key].forEach((element) => {
309
- if (element.constructor !== Object && count < 1) {
310
- this.errors.push(
311
- `Invalid value(s) found in ${key}. Must be an Array of Objects`
312
- )
313
- count++
314
- }
315
- })
316
- }
317
- }
318
- break
319
-
320
- default:
321
- KeywordsList = [
322
- 'title',
323
- 'text_',
324
- 'image_',
325
- 'video_',
326
- 'audio_',
327
- 'link_',
328
- 'hypertext_',
329
- 'object',
330
- 'cb_$',
331
- '$bvArgs'
332
- ] // accepted keyword in value declaration for pop-up custom
333
-
334
- for (let key of Object.keys(data.value)) {
335
- let expectedKey = key
336
-
337
- // search if key match lists
338
- if (key.includes('_') && !key.includes('cb_$'))
339
- expectedKey = `${key.split('_')[0]}_`
340
-
341
- //===============================================
342
- const test = (regexp) => regexp.test(key) //defining the testing function
343
-
344
- switch (true) {
345
- case ![...KeywordsList, ...callbacksFunctionList].includes(
346
- expectedKey
347
- ):
348
- this.errors.push(`Invalid key declaration in value: ${key}`)
349
- break
350
-
351
- case test(/\$bvArgs/):
352
- // validating content of $bvArgs keys. Must be an array.
353
- // validating content of $bvArgs. Content in $bvArgs must be objects
354
- if (
355
- data.value[key].constructor !== Array ||
356
- data.value[key].length < 1
357
- )
358
- this.errors.push(
359
- `Invalid assignment for ${key}. Must be an Array of Objects`
360
- )
361
- else {
362
- let count = 0
363
- data.value[key].forEach((element) => {
364
- if (element.constructor !== Object && count < 1) {
365
- this.errors.push(
366
- `Invalid value(s) found in ${key}. Must be an Array of Objects`
367
- )
368
- count++
369
- }
370
- })
371
- }
372
- break
373
-
374
- case test(/link/):
375
- // Validating content of link element
376
- if (!data.value[key].ref) {
377
- this.errors.push('Missing ref for link')
378
- }
379
- break
380
-
381
- case test(/image/):
382
- // Validating content of link element
383
- if (!data.value[key].path) {
384
- this.errors.push('Missing path for image')
385
- }
386
- break
387
-
388
- case test(/cb_\$/):
389
- // validating content of cb_$ keys to be a function
390
- if (data.value[key].constructor != Function)
391
- this.errors.push(
392
- `Invalid assignment for ${key}. Must be a Function`
393
- )
394
- break
395
-
396
- default: {
397
- if (data.value[key].constructor != String) {
398
- this.errors.push(
399
- 'Invalid assignment for hypertext. Must be a String'
400
- )
401
- }
402
- }
403
- }
404
- }
405
- }
406
- } else this.errors.push('Invalid object declaration for value')
407
- } else this.errors.push('Missing argument - value')
408
-
409
- if (import.meta.env.DEV) {
410
- for (const err of this.errors)
411
- console.warn(
412
- `%c WARNING!>>> POP-UP: ${err} `,
413
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
414
- )
415
- }
416
-
417
- // No error detected proceed
418
- if (!this.errors.length) {
419
- if (data.type === 'popup-endActivity') {
420
- const { title, ...filtered } = data.value
421
- this.pContent = filtered
422
- this.pTitle = title
423
- } else if (data.type === 'popup-custom') {
424
- this.pContent = data.value
425
- } else {
426
- const { title, ...filtered } = data.value
427
- this.pContent = filtered
428
- this.pTitle = title
429
- }
430
- this.pType = data.type
431
- this.pName = data.name
432
- const cb_open = data.value.cb_$open || null
433
- this.$open(cb_open)
434
- }
435
- },
436
-
437
- /**
438
- * @param {String} type
439
- */
440
- retroType(type) {
441
- this.typeRetro = type
442
- return this.typeRetro
443
- },
444
- /**
445
- * @description - method to open the popup
446
- * @param {Function} cb
447
- */
448
- $open(cb) {
449
- if (this.animationOff === true) this.animationOff = false
450
- this.popup.show()
451
- if (cb && typeof cb === 'function') cb()
452
- },
453
- /**
454
- * @description - method to close the popup
455
- * @param {Function} cb
456
- */
457
- $close(options, cb) {
458
- //this.animationOff =true
459
- if (options && options.animationOff) {
460
- this.animationOff = options.animationOff
461
- }
462
- this.popup.hide()
463
- //reset popup class name
464
- this.typeRetro = 'none'
465
- if (cb && typeof cb === 'function') cb()
466
- },
467
- /**
468
- * @description - method for action confirm
469
- * @param {Function} cb
470
- */
471
- $confirm(cb) {
472
- cb = cb || null
473
- this.popup.hide()
474
- if (cb && typeof cb === 'function') cb()
475
- },
476
- /**
477
- * @description - method for action cancel
478
- * @param {Function} cb
479
- */
480
- $cancel(cb) {
481
- cb = cb || null
482
- this.popup.hide()
483
- if (cb && typeof cb === 'function') cb()
484
- }
485
- }
486
- }
487
- </script>
488
- <style lang="scss">
489
- .modal {
490
- .modal-dialog {
491
- max-width: 100% !important;
492
- margin: 0 0 !important;
493
- display: flex;
494
- flex-direction: column;
495
- flex-wrap: wrap;
496
- align-content: center;
497
- justify-content: center;
498
- align-items: center;
499
- height: 100vh;
500
-
501
- .popup-info,
502
- .popup-noanswer {
503
- width: 660px;
504
- margin: 10% auto;
505
- .modal-header {
506
- border-bottom: 0 solid transparent;
507
- }
508
- }
509
-
510
- .popup-endActivity {
511
- justify-content: center;
512
- align-items: center;
513
- border-radius: 0;
514
-
515
- .modal-header {
516
- width: 100%;
517
- border: 0 solid transparent;
518
-
519
- .close {
520
- padding: 1rem 1.5rem;
521
- margin: -1rem -1rem -1rem auto;
522
- }
523
- }
524
-
525
- .modal-body {
526
- width: 100%;
527
- display: flex;
528
- flex-direction: column;
529
- flex-wrap: wrap;
530
- justify-content: center;
531
-
532
- .popup-bottom-buttons {
533
- margin-left: auto;
534
- margin-right: auto;
535
- margin-top: 32px;
536
- margin-bottom: 25px;
537
- }
538
-
539
- #hypertext_1_0 {
540
- display: flex;
541
- justify-content: center;
542
-
543
- p {
544
- font-size: 1.5rem;
545
- font-weight: bold;
546
- }
547
- }
548
-
549
- .popUp-title,
550
- #end-activity {
551
- display: flex;
552
-
553
- .popup_primary_nav_btn {
554
- border: #005ea1 solid 2px;
555
- margin: 0 12px;
556
-
557
- &:nth-child(1) {
558
- color: #005ea1;
559
- }
560
-
561
- &:nth-child(2) {
562
- background: #005ea1;
563
- color: #ffffff;
564
- }
565
-
566
- &:hover {
567
- border: #ffffff solid 2px;
568
- background: #0898ff;
569
- color: #ffffff;
570
- }
571
-
572
- &:active {
573
- background: #00406e;
574
- outline: 1px solid #00406e !important;
575
- color: #ffffff;
576
- }
577
- }
578
- }
579
- }
580
- }
581
- }
582
- }
583
- </style>
@@ -1,27 +0,0 @@
1
- <!--
2
- @ Description: This component is used to create a popover that is accessible via keyboard navigation (tab + space/enter)
3
- -->
4
- <template>
5
- <b-popover v-bind="$attrs" triggers="hover click" @shown="onShown">
6
- <slot>Popover</slot>
7
- </b-popover>
8
- </template>
9
-
10
- <script>
11
- export default {
12
- name: 'AppCompPopover',
13
- data() {
14
- return {}
15
- },
16
- methods: {
17
- /* focus on the popover when it is shown, pressing tab returns the focus on the popover button*/
18
- onShown(event) {
19
- const button = event.target
20
- event.relatedTarget.onblur = () => {
21
- button.click()
22
- }
23
- event.relatedTarget.focus()
24
- }
25
- }
26
- }
27
- </script>