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

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 (96) hide show
  1. package/.editorconfig +33 -33
  2. package/.eslintignore +29 -29
  3. package/.eslintrc.cjs +81 -81
  4. package/CHANGELOG +19 -0
  5. package/README.md +71 -71
  6. package/bk.scss +117 -117
  7. package/package.json +8 -8
  8. package/src/$locales/en.json +23 -23
  9. package/src/$locales/fr.json +22 -21
  10. package/src/assets/data/onboardingMessages.json +47 -47
  11. package/src/components/AppBase.vue +186 -116
  12. package/src/components/AppBaseButton.test.js +22 -0
  13. package/src/components/AppBaseButton.vue +13 -5
  14. package/src/components/AppBaseErrorDisplay.vue +438 -438
  15. package/src/components/AppBaseFlipCard.vue +84 -84
  16. package/src/components/AppBaseModule.vue +207 -128
  17. package/src/components/AppBasePage.vue +18 -45
  18. package/src/components/AppBasePopover.vue +41 -41
  19. package/src/components/AppCompAudio.vue +20 -17
  20. package/src/components/AppCompBranchButtons.vue +28 -70
  21. package/src/components/AppCompButtonProgress.vue +4 -9
  22. package/src/components/AppCompCarousel.vue +120 -90
  23. package/src/components/{AppCompTranscript.vue → AppCompContainer.vue} +8 -1
  24. package/src/components/AppCompInputCheckBoxNext.vue +5 -0
  25. package/src/components/AppCompInputDropdownNext.vue +50 -8
  26. package/src/components/AppCompInputRadioNext.vue +152 -152
  27. package/src/components/AppCompInputTextNext.vue +21 -2
  28. package/src/components/AppCompInputTextTableNext.vue +1 -0
  29. package/src/components/AppCompInputTextToFillDropdownNext.vue +8 -0
  30. package/src/components/AppCompInputTextToFillNext.vue +171 -171
  31. package/src/components/AppCompJauge.vue +74 -74
  32. package/src/components/AppCompMenu.vue +13 -7
  33. package/src/components/AppCompMenuItem.vue +228 -228
  34. package/src/components/AppCompNavigation.vue +43 -30
  35. package/src/components/AppCompNoteCall.vue +64 -38
  36. package/src/components/AppCompNoteCredit.vue +303 -105
  37. package/src/components/AppCompPlayBarNext.vue +25 -12
  38. package/src/components/AppCompPlayBarProgress.vue +82 -82
  39. package/src/components/AppCompPopUpNext.vue +1 -4
  40. package/src/components/AppCompQuizNext.vue +8 -4
  41. package/src/components/AppCompQuizRecall.vue +44 -22
  42. package/src/components/AppCompSVGNext.vue +2 -3
  43. package/src/components/AppCompSettingsMenu.vue +172 -172
  44. package/src/components/AppCompTableOfContent.vue +61 -62
  45. package/src/components/AppCompVideoPlayer.vue +17 -15
  46. package/src/components/AppCompViewDisplay.vue +6 -6
  47. package/src/components/BaseModule.vue +1 -18
  48. package/src/components/tests__/AppBaseButton.spec.js +53 -0
  49. package/src/composables/useQuiz.js +206 -206
  50. package/src/externalComps/ModuleView.vue +22 -22
  51. package/src/externalComps/SummaryView.vue +91 -91
  52. package/src/main.js +37 -32
  53. package/src/mixins/$mediaMixins.js +819 -819
  54. package/src/mixins/timerMixin.js +155 -155
  55. package/src/module/stores/appStore.js +59 -6
  56. package/src/module/xapi/ADL.js +144 -4
  57. package/src/module/xapi/Crypto/Hasher.js +241 -241
  58. package/src/module/xapi/Crypto/WordArray.js +278 -278
  59. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  60. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
  61. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  62. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  63. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  64. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  65. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  66. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  67. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  68. package/src/module/xapi/Crypto/index.js +53 -53
  69. package/src/module/xapi/Statement/activity.js +47 -47
  70. package/src/module/xapi/Statement/agent.js +55 -55
  71. package/src/module/xapi/Statement/group.js +26 -26
  72. package/src/module/xapi/Statement/index.js +259 -259
  73. package/src/module/xapi/Statement/statement.js +253 -253
  74. package/src/module/xapi/Statement/statementRef.js +23 -23
  75. package/src/module/xapi/Statement/substatement.js +22 -22
  76. package/src/module/xapi/Statement/verb.js +36 -36
  77. package/src/module/xapi/activitytypes.js +17 -17
  78. package/src/module/xapi/utils.js +167 -167
  79. package/src/module/xapi/verbs.js +294 -294
  80. package/src/module/xapi/wrapper copy.js +1963 -0
  81. package/src/module/xapi/wrapper.js +121 -188
  82. package/src/module/xapi/xapiStatement.js +444 -444
  83. package/src/plugins/bus.js +8 -8
  84. package/src/plugins/gsap.js +14 -14
  85. package/src/plugins/helper.js +52 -12
  86. package/src/plugins/i18n.js +44 -44
  87. package/src/plugins/save.js +37 -37
  88. package/src/plugins/scorm.js +287 -287
  89. package/src/plugins/xapi.js +11 -11
  90. package/src/public/index.html +33 -33
  91. package/src/router/index.js +8 -2
  92. package/src/router/routes.js +312 -312
  93. package/src/shared/generalfuncs.js +210 -210
  94. package/src/shared/validators.js +38 -179
  95. package/vitest.config.js +19 -0
  96. package/src/components/AppCompPlayBar.vue +0 -1218
@@ -1,41 +1,41 @@
1
- <!--
2
- @ Description: This component is used to create a popover that is accessible via keyboard navigation (tab + space/enter)
3
- -->
4
- <template>
5
- <v-tooltip
6
- ref="tooltip"
7
- v-bind="$attrs"
8
- v-model="show"
9
- transition="false"
10
- :open-on-click="true"
11
- :persistent="false"
12
- >
13
- <slot></slot>
14
- </v-tooltip>
15
- </template>
16
-
17
- <script>
18
- export default {
19
- name: 'AppBasePopover',
20
- data() {
21
- return {
22
- show: false,
23
- alertContainer: null
24
- }
25
- },
26
- watch: {
27
- show: {
28
- handler(newValue) {
29
- if (newValue) {
30
- const content = this.$refs.tooltip.contentEl.textContent
31
- this.alertContainer.textContent = ''
32
- this.alertContainer.textContent = content
33
- }
34
- }
35
- }
36
- },
37
- mounted() {
38
- this.alertContainer = document.getElementById('hiddenAlertContainer')
39
- }
40
- }
41
- </script>
1
+ <!--
2
+ @ Description: This component is used to create a popover that is accessible via keyboard navigation (tab + space/enter)
3
+ -->
4
+ <template>
5
+ <v-tooltip
6
+ ref="tooltip"
7
+ v-bind="$attrs"
8
+ v-model="show"
9
+ transition="false"
10
+ :open-on-click="true"
11
+ :persistent="false"
12
+ >
13
+ <slot></slot>
14
+ </v-tooltip>
15
+ </template>
16
+
17
+ <script>
18
+ export default {
19
+ name: 'AppBasePopover',
20
+ data() {
21
+ return {
22
+ show: false,
23
+ alertContainer: null
24
+ }
25
+ },
26
+ watch: {
27
+ show: {
28
+ handler(newValue) {
29
+ if (newValue) {
30
+ const content = this.$refs.tooltip.contentEl.textContent
31
+ this.alertContainer.textContent = ''
32
+ this.alertContainer.textContent = content
33
+ }
34
+ }
35
+ }
36
+ },
37
+ mounted() {
38
+ this.alertContainer = document.getElementById('hiddenAlertContainer')
39
+ }
40
+ }
41
+ </script>
@@ -34,7 +34,7 @@
34
34
  <audio
35
35
  :id="id"
36
36
  ref="m-audio"
37
- @loadedmetadata="updateMediaData($event)"
37
+ @loadedmetadata="updateMediaDataAudio($event.target)"
38
38
  >
39
39
  <source
40
40
  v-for="(aSource, index) in mSources"
@@ -128,39 +128,42 @@ export default {
128
128
 
129
129
  methods: {
130
130
  ...mapActions(useAppStore, ['updateCurrentMediaElements']),
131
+ /**
132
+ * @description search the DOM for medias with duplicated ID declaration in the page
133
+ * @return return Array of all DOM MediaElement with same id
134
+ */
135
+ checkDuplicatedID() {
136
+ const mediaList = document.querySelectorAll('.__media-container')
137
+ const duplicate = Array.from(mediaList).filter((media) =>
138
+ media.id.includes(this.id)
139
+ )
140
+ return duplicate
141
+ },
131
142
  /**
132
143
  * @description update the information for the mediaElement in the store
133
144
  * @param {htmlElement} e
134
145
  * @fires update-page to AppBaseModule.vue
135
146
  */
136
- updateMediaData(e) {
147
+ updateMediaDataAudio(e) {
137
148
  //dispatch loading status of for this component
138
- this.$bus.$emit('set-comp-status', 'AppCompMediaPlayer', 'loading')
149
+ this.$bus.$emit('set-comp-status', 'AppCompAudioPlayer', 'loading')
139
150
  this.$bus.$emit('update-media-duration')
140
151
 
141
- //Should Check that the the media Element is unique im Media Liste
142
- const { mElements } = this.getCurrentPage
143
-
144
- const hasEntry = mElements.findLastIndex(
145
- (media) => media.id === e.target.id
146
- )
147
-
148
- if (hasEntry !== -1) {
149
- // Should report Error to Console and Component template about this media
150
- const errmsg = `Cet élément a le même ID q'un autre media. Vous ne devez pas avoir de médias avec le même ID dans une page.`
152
+ if (this.checkDuplicatedID().length > 1) {
153
+ const errmsg = `Cet élément a le même ID <b>${this.id}</b>q'un autre media. Vous ne devez pas avoir de médias avec le même ID dans une page.`
151
154
 
152
155
  console.warn(
153
- `%c WARNING!>>> You cannot use the same ID in your media elements for your page.`,
156
+ `%c WARNING!>>> You cannot use the same ID (${this.id}) in your media elements for your page.`,
154
157
  'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
155
158
  )
156
159
 
157
- this.$bus.$emit('set-comp-status', 'AppCompMediaPlayer', 'ready')
160
+ this.$bus.$emit('set-comp-status', 'AppCompAudioPlayer', 'ready')
158
161
  return this.hasErr.push(errmsg)
159
162
  }
160
163
 
161
- this.updateCurrentMediaElements(e.target).then(() => {
164
+ this.updateCurrentMediaElements(e).then(() => {
162
165
  this.isSet = true
163
- this.$bus.$emit('set-comp-status', 'AppCompMediaPlayer', 'ready')
166
+ this.$bus.$emit('set-comp-status', 'AppCompAudioPlayer', 'ready')
164
167
  })
165
168
  },
166
169
  errorHandling(e) {
@@ -38,7 +38,7 @@ Si la composante est appelée sans prop, les boutons par défaut seront génér
38
38
  <v-row v-else>
39
39
  <v-col
40
40
  v-for="branch of branchsStateData"
41
- :id="branch.id"
41
+ :id="`branch_${branch.id}`"
42
42
  :key="branch.id"
43
43
  class="branch-btn"
44
44
  >
@@ -65,24 +65,18 @@ Si la composante est appelée sans prop, les boutons par défaut seront génér
65
65
  v-else-if="isCard && cards.length"
66
66
  class="branch-btn-wrapper branch-btn-card"
67
67
  >
68
- <v-card class="mx-auto" max-width="20rem">
69
- <v-img :src="branch.imgFile" :alt="`${branch.imgAlt}`" cover>
70
- <v-toolbar color="transparent">
71
- <template #append>
72
- <app-comp-button-progress
73
- :set-target="sidebar"
74
- :percent="branch.progression ? branch.progression : 0"
75
- :branch-data="branch"
76
- :btn-title="getMatchingElement(branch.id).btnTitle"
77
- ></app-comp-button-progress>
78
- </template>
79
- </v-toolbar>
80
- </v-img>
81
-
82
- <v-card-title>{{ branch.title }}</v-card-title>
83
- <v-card-text>
84
- {{ branch.text }}
85
- </v-card-text>
68
+ <v-card class="mx-auto" max-width="15rem">
69
+ <v-img :src="branch.imgFile" :alt="`${branch.imgAlt}`" cover />
70
+
71
+ <v-card-title v-html="branch.title"></v-card-title>
72
+ <v-card-text v-html="branch.text"></v-card-text>
73
+
74
+ <app-comp-button-progress
75
+ :set-target="sidebar"
76
+ :percent="branch.progression ? branch.progression : 0"
77
+ :branch-data="branch"
78
+ :btn-title="getMatchingElement(branch.id).btnTitle"
79
+ ></app-comp-button-progress>
86
80
  </v-card>
87
81
  </div>
88
82
  <div v-else class="branch-btn-wrapper">
@@ -98,7 +92,6 @@ Si la composante est appelée sans prop, les boutons par défaut seront génér
98
92
  </v-row>
99
93
  </template>
100
94
  <script>
101
- // ...
102
95
  import { mapState } from 'pinia'
103
96
  import { useAppStore } from '../module/stores/appStore'
104
97
  import AppCompButtonProgress from './AppCompButtonProgress.vue'
@@ -141,35 +134,6 @@ export default {
141
134
  break
142
135
  }
143
136
  }
144
- //Start validation of required keys
145
- if (isValid) {
146
- const requiredKeys = ['imgFile', 'title', 'text', 'brchName']
147
-
148
- for (let el of dataArray) {
149
- //Validate that require key exist for each element in card
150
- for (let k of requiredKeys) {
151
- let index = dataArray.indexOf(el)
152
-
153
- if (!el[k]) {
154
- isValid = false
155
- errMsg = `\n 💥 Missing 👉 ${k} 👈 in object ${
156
- index + 1
157
- } in ➡ card \n 🚩Allowed indexes are: 👉 ${requiredKeys}`
158
- break
159
- } else {
160
- if (el[k].constructor !== String) {
161
- errMsg = `\n 💥 Invalid 👉 ${k} 👈 declaration in ➡ object ${
162
- index + 1
163
- } ➡ of card. \n 🚩 Must be of type {String}`
164
- isValid = false
165
- break
166
- }
167
- }
168
- if (!isValid) break
169
- }
170
- if (!isValid) break
171
- }
172
- }
173
137
  }
174
138
 
175
139
  if (errMsg) console.error(`🧱 app-comp-branch-buttons \n ${errMsg}`)
@@ -304,7 +268,6 @@ export default {
304
268
  let { state = 'new', progression = 0 } = this.getBranchProgression(
305
269
  branchData.id
306
270
  )
307
- // if (!state || !progression) return
308
271
 
309
272
  branchData.state = state
310
273
  branchData.progression = progression
@@ -323,7 +286,11 @@ export default {
323
286
  btnTitle
324
287
  }
325
288
 
326
- if (typeof branchData.imgAlt === 'undefined' && import.meta.env.DEV) {
289
+ if (
290
+ typeof branchData.imgAlt === 'undefined' &&
291
+ branchData.imgFile === 'undefined' &&
292
+ import.meta.env.DEV
293
+ ) {
327
294
  branchData.imgAlt = ''
328
295
  console.warn(
329
296
  `Bouton d’embranchement: ALT image sans valeur définie pour ${branchData.id}`
@@ -413,27 +380,8 @@ export default {
413
380
  }
414
381
  //Start validation of required keys
415
382
  if (isValid) {
416
- const requiredKeys = ['imgFile', 'title', 'text', 'brchName']
417
-
418
383
  for (let el of this.cards) {
419
384
  let index = this.cards.indexOf(el)
420
- //Validate that require key exist for each element in card
421
- for (let k of requiredKeys) {
422
- if (!el[k]) {
423
- isValid = false
424
- errMsg = `l'Attribut 👉 ${k} 👈 pour la carte ${index + 1} n'as pas été défini`
425
- break
426
- } else {
427
- if (el[k].constructor !== String) {
428
- errMsg = `l'Attribut 👉 ${k} 👈 pour la carte ${
429
- index + 1
430
- } doit être de type {String}`
431
- isValid = false
432
- break
433
- }
434
- }
435
- if (!isValid) break
436
- }
437
385
 
438
386
  // Start validation of existing branch for this element
439
387
  let searchEl = this.branchs.find((b) =>
@@ -544,9 +492,19 @@ export default {
544
492
  <style lang="scss">
545
493
  .branch-btn-wrapper {
546
494
  position: relative;
495
+
547
496
  .branch-btn-custom {
548
497
  background-color: transparent;
549
498
  border: none;
550
499
  }
551
500
  }
501
+
502
+ .v-card {
503
+ position: relative;
504
+ .button-progress-wrapper {
505
+ position: absolute;
506
+ right: 55px;
507
+ top: 15px;
508
+ }
509
+ }
552
510
  </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="button-progress-wrapper">
3
- <button
3
+ <app-base-button
4
4
  :id="`btn_branch_${branchData.id}`"
5
5
  :target-ref="branchData.id"
6
6
  :title="btnTitle || $t('text.place_holder.for_title_btn_progress')"
@@ -17,11 +17,13 @@
17
17
  <svg v-if="branchData.state != status.COMPLETE">
18
18
  <use href="#navigate-next-icon"></use>
19
19
  </svg>
20
- </button>
20
+ </app-base-button>
21
21
  </div>
22
22
  </template>
23
23
  <script>
24
+ import AppBaseButton from './AppBaseButton.vue'
24
25
  export default {
26
+ components: { AppBaseButton },
25
27
  props: {
26
28
  mini: {
27
29
  type: Boolean,
@@ -63,7 +65,6 @@ export default {
63
65
  },
64
66
 
65
67
  created() {
66
- // if (isNaN(this.percent)) this.percent = 0
67
68
  this.$bus.$on('branching-hidden', this.resetIsActive)
68
69
  },
69
70
 
@@ -98,12 +99,6 @@ export default {
98
99
  .button-progress-wrapper {
99
100
  &:not(.card-btn) {
100
101
  .branch-btn-default {
101
- // left: 4px;
102
- // top: 4px;
103
- // min-width: 42px;
104
- // min-height: 42px;
105
- right: 15px !important;
106
- top: -15px !important;
107
102
  min-width: 42px;
108
103
  min-height: 42px;
109
104
  }
@@ -3,82 +3,95 @@
3
3
  @ What it does: Create an html element including an array of slides. These slides are objects including required property (imgSrc) and optional properties (imgAlt, Title, Hypertext).
4
4
  -->
5
5
 
6
- <template>
6
+ <template v-if="slides">
7
7
  <section id="carousel" :aria-label="$t('text.carousel')">
8
- <div class="carousel-inner">
9
- <div id="mycarousel-slides" class="carousel-slides" aria-live="polite">
10
- <div
11
- v-for="(slide, index) in slides"
12
- :key="index"
13
- class="carousel-slide"
14
- :class="{
15
- current: currentSlide == index + 1,
16
- prev: currentSlide >= index + 2,
17
- next: currentSlide <= index
18
- }"
19
- role="group"
20
- :aria-hidden="!(currentSlide == index + 1)"
21
- >
22
- <span class="sr-only">
23
- {{
24
- $t('text.slide') +
25
- ' ' +
26
- (index + 1) +
27
- ' ' +
28
- $t('text.of') +
29
- ' ' +
30
- slideLength
31
- }}
32
- </span>
8
+ <app-base-error-display
9
+ v-if="errorsSlider.length"
10
+ :error-group="'component'"
11
+ :error-title="'ERREUR: CRÉATION CAROUSEL'"
12
+ :errors-list="errorsSlider"
13
+ ></app-base-error-display>
14
+ <template v-else>
15
+ <div class="carousel-inner">
16
+ <div id="mycarousel-slides" class="carousel-slides" aria-live="polite">
33
17
  <div
34
- class="carousel-image"
35
- :class="{ 'full-width': !(slide.title || slide.hypertext) }"
18
+ v-for="(slide, index) in slides"
19
+ :key="index"
20
+ class="carousel-slide"
21
+ :class="{
22
+ current: currentSlide == index + 1,
23
+ prev: currentSlide >= index + 2,
24
+ next: currentSlide <= index
25
+ }"
26
+ role="group"
27
+ :aria-hidden="!(currentSlide == index + 1)"
36
28
  >
37
- <img
38
- :src="slide.imgSrc"
39
- :alt="slide.imgAlt"
40
- :aria-hidden="slide.imgAlt == ' ' || !slide.imgAlt ? true : false"
41
- />
42
- </div>
43
- <div v-if="slide.title || slide.hypertext" class="carousel-text">
44
- <h3 v-if="slide.title">
45
- {{ slide.title }}
46
- </h3>
47
- <div v-html="slide.hypertext"></div>
29
+ <span class="sr-only">
30
+ {{
31
+ $t('text.slide') +
32
+ ' ' +
33
+ (index + 1) +
34
+ ' ' +
35
+ $t('text.of') +
36
+ ' ' +
37
+ slideLength
38
+ }}
39
+ </span>
40
+ <div
41
+ class="carousel-image"
42
+ :class="{ 'full-width': !(slide.title || slide.hypertext) }"
43
+ >
44
+ <img
45
+ :src="slide.imgSrc"
46
+ :alt="slide.imgAlt"
47
+ :aria-hidden="
48
+ slide.imgAlt == ' ' || !slide.imgAlt ? true : false
49
+ "
50
+ />
51
+ </div>
52
+ <div v-if="slide.title || slide.hypertext" class="carousel-text">
53
+ <h3 v-if="slide.title">
54
+ {{ slide.title }}
55
+ </h3>
56
+ <div v-html="slide.hypertext"></div>
57
+ </div>
48
58
  </div>
49
59
  </div>
60
+
61
+ <div class="carousel-controls">
62
+ <app-base-button
63
+ id="carousel-btn-prev"
64
+ class="carousel-btn"
65
+ :aria-label="$t('button.carousel_prev')"
66
+ aria-controls="mycarousel-slides"
67
+ :title="$t('button.carousel_prev')"
68
+ :aria-disabled="disablePrev"
69
+ :is-disabled="disablePrev"
70
+ :disabled="disablePrev"
71
+ @click="prevSlide()"
72
+ >
73
+ <svg>
74
+ <use href="#fleche-gauche-icon"></use>
75
+ </svg>
76
+ </app-base-button>
77
+ <app-base-button
78
+ id="carousel-btn-next"
79
+ class="carousel-btn"
80
+ :aria-label="$t('button.carousel_next')"
81
+ aria-controls="mycarousel-slides"
82
+ :title="$t('button.carousel_next')"
83
+ :aria-disabled="disableNext"
84
+ :is-disabled="disableNext"
85
+ :disabled="disableNext"
86
+ @click="nextSlide()"
87
+ >
88
+ <svg>
89
+ <use href="#fleche-droite-icon"></use>
90
+ </svg>
91
+ </app-base-button>
92
+ </div>
50
93
  </div>
51
- <div class="carousel-controls">
52
- <app-base-button
53
- id="carousel-btn-prev"
54
- class="carousel-btn"
55
- :aria-label="$t('button.carousel_prev')"
56
- aria-controls="mycarousel-slides"
57
- :title="$t('button.carousel_prev')"
58
- :disabled="disablePrev"
59
- :aria-disabled="disablePrev"
60
- @click="prevSlide()"
61
- >
62
- <svg>
63
- <use href="#fleche-gauche-icon"></use>
64
- </svg>
65
- </app-base-button>
66
- <app-base-button
67
- id="carousel-btn-next"
68
- class="carousel-btn"
69
- :aria-label="$t('button.carousel_next')"
70
- aria-controls="mycarousel-slides"
71
- :title="$t('button.carousel_next')"
72
- :disabled="disableNext"
73
- :aria-disabled="disableNext"
74
- @click="nextSlide()"
75
- >
76
- <svg>
77
- <use href="#fleche-droite-icon"></use>
78
- </svg>
79
- </app-base-button>
80
- </div>
81
- </div>
94
+ </template>
82
95
  <div class="carousel-index">
83
96
  <p aria-hidden="true">{{ currentSlide }}/{{ slideLength }}</p>
84
97
  </div>
@@ -86,16 +99,20 @@
86
99
  </template>
87
100
 
88
101
  <script>
102
+ import AppBaseErrorDisplay from './AppBaseErrorDisplay.vue'
89
103
  export default {
90
104
  name: 'AppCompSlider',
105
+ components: { AppBaseErrorDisplay },
91
106
  props: {
92
- slides: { type: Array, required: true } //Array of slides {imgSrc, imgAlt, title, hypertext}
107
+ slides: { type: Array, required: true }, //Array of slides {imgSrc, imgAlt, title, hypertext}
108
+ name: { type: String, default: 'toto cool' }
93
109
  },
94
110
  data() {
95
111
  return {
96
- currentSlide: 1, //Slide management
112
+ currentSlide: null, //Slide management
97
113
  requiredProperties: ['imgSrc'], //For slides validation
98
- optionalProperties: ['title', 'imgAlt', 'hypertext'] //For slides validation
114
+ optionalProperties: ['title', 'imgAlt', 'hypertext'], //For slides validation
115
+ errorsSlider: []
99
116
  }
100
117
  },
101
118
  computed: {
@@ -106,26 +123,14 @@ export default {
106
123
  return !(this.currentSlide < this.slideLength)
107
124
  },
108
125
  slideLength() {
109
- return this.slides.length
126
+ return this.slides ? this.slides.length : 0
110
127
  }
111
128
  },
129
+ created() {
130
+ this.currentSlide = this.slides && this.slides.length ? 1 : 0
131
+ },
112
132
  mounted() {
113
- //Validating slides
114
- if (Array.isArray(this.slides) && this.slideLength > 0) {
115
- //Validate properties for all the slides
116
- for (const slide of this.slides) {
117
- this.validateProperties(
118
- this.requiredProperties,
119
- this.optionalProperties,
120
- slide
121
- )
122
- }
123
- } else {
124
- console.warn(
125
- `%c WARNING!>>> AppCompSlider : slides must be an array of at least one item`,
126
- 'background: orange; color: white; display: block; margin:5px;'
127
- )
128
- }
133
+ this.validateCarousel()
129
134
  },
130
135
  methods: {
131
136
  prevSlide() {
@@ -138,6 +143,27 @@ export default {
138
143
  this.currentSlide++
139
144
  }
140
145
  },
146
+ validateCarousel() {
147
+ //Validating slides
148
+
149
+ if (Array.isArray(this.slides) && this.slideLength > 0) {
150
+ //Validate properties for all the slides
151
+ for (const slide of this.slides) {
152
+ this.validateProperties(
153
+ this.requiredProperties,
154
+ this.optionalProperties,
155
+ slide
156
+ )
157
+ }
158
+ } else {
159
+ let msg = `Le corrousel doit avoit au moins un element.`
160
+ this.errorsSlider.push(msg)
161
+ console.warn(
162
+ `%c WARNING!>>> AppCompSlider : slides must be an array of at least one item`,
163
+ 'background: orange; color: white; display: block; margin:5px;'
164
+ )
165
+ }
166
+ },
141
167
  //Validate the properties of a specific object (currentObject)
142
168
  validateProperties(requiredProperties, optionalProperties, currentObject) {
143
169
  let allProperties = requiredProperties.concat(optionalProperties)
@@ -154,6 +180,8 @@ export default {
154
180
  `%c WARNING!>>> AppCompSlider : slides ${wrongProperties} invalid. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
155
181
  'background: orange; color: white; display: block; margin:5px;'
156
182
  )
183
+ let msg = `Attribut(s) invalide(s): <i>${wrongProperties}</i> . Consultez la console pour plus de details.`
184
+ this.errorsSlider.push(msg)
157
185
  }
158
186
  //Validate if all required properties are present in currentObject
159
187
  if (missingRequired.length > 0) {
@@ -161,6 +189,8 @@ export default {
161
189
  `%c WARNING!>>> AppCompQuizSlider : slides missing required ${missingRequired} property. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
162
190
  'background: orange; color: white; display: block; margin:5px;'
163
191
  )
192
+ let msg = `Une/certaines propriété(s) sont manquante(s). Consultez la console pour plus de details.`
193
+ this.errorsSlider.push(msg)
164
194
  }
165
195
  },
166
196
  //Get all the invalids properties from the object
@@ -1,13 +1,20 @@
1
1
  <template>
2
- <div id="transcript-container" v-html="content"></div>
2
+ <div :id="id" v-html="content"></div>
3
3
  </template>
4
4
  <script>
5
5
  export default {
6
6
  props: {
7
+ id: {
8
+ type: String,
9
+ default: 'shadow-container'
10
+ },
7
11
  content: {
8
12
  type: String,
9
13
  default: `Hello Wolrd!`
10
14
  }
15
+ },
16
+ mounted() {
17
+ console.log('😶‍🌫️ ', this.$props.id)
11
18
  }
12
19
  }
13
20
  </script>
@@ -166,6 +166,11 @@ fieldset {
166
166
  -webkit-box-shadow: inherit;
167
167
  }
168
168
 
169
+ fieldset{
170
+ border: inherit;
171
+ }
172
+
173
+
169
174
  .custom-checkbox {
170
175
  width: 100%;
171
176
  height: 100%;