fcad-core-dragon 2.1.0 → 2.1.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 (160) hide show
  1. package/.editorconfig +7 -7
  2. package/.gitlab-ci.yml +124 -0
  3. package/.prettierrc +11 -11
  4. package/.vscode/extensions.json +8 -8
  5. package/.vscode/settings.json +46 -16
  6. package/CHANGELOG +520 -520
  7. package/README.md +57 -57
  8. package/documentation/.vitepress/config.js +114 -114
  9. package/documentation/api-examples.md +49 -49
  10. package/documentation/composants/app-base-button.md +58 -58
  11. package/documentation/composants/app-base-error-display.md +59 -59
  12. package/documentation/composants/app-base-popover.md +68 -68
  13. package/documentation/composants/app-comp-audio.md +75 -75
  14. package/documentation/composants/app-comp-branch-buttons.md +111 -111
  15. package/documentation/composants/app-comp-button-progress.md +53 -53
  16. package/documentation/composants/app-comp-carousel.md +53 -53
  17. package/documentation/composants/app-comp-container.md +53 -53
  18. package/documentation/composants/app-comp-input-checkbox-next.md +42 -42
  19. package/documentation/composants/app-comp-input-dropdown-next.md +34 -34
  20. package/documentation/composants/app-comp-input-radio-next.md +39 -39
  21. package/documentation/composants/app-comp-input-text-next.md +35 -35
  22. package/documentation/composants/app-comp-input-text-table-next.md +34 -34
  23. package/documentation/composants/app-comp-input-text-to-fill-dropdown-next.md +53 -53
  24. package/documentation/composants/app-comp-input-text-to-fill-next.md +31 -31
  25. package/documentation/composants/app-comp-jauge.md +31 -31
  26. package/documentation/composants/app-comp-menu-item.md +55 -55
  27. package/documentation/composants/app-comp-menu.md +29 -29
  28. package/documentation/composants/app-comp-navigation.md +41 -41
  29. package/documentation/composants/app-comp-note-call.md +53 -53
  30. package/documentation/composants/app-comp-note-credit.md +53 -53
  31. package/documentation/composants/app-comp-play-bar-next.md +53 -53
  32. package/documentation/composants/app-comp-pop-up-next.md +93 -93
  33. package/documentation/composants/app-comp-quiz-next.md +235 -235
  34. package/documentation/composants/app-comp-quiz-recall.md +53 -53
  35. package/documentation/composants/app-comp-svg-next.md +53 -53
  36. package/documentation/composants/app-comp-table-of-content.md +50 -50
  37. package/documentation/composants/app-comp-video-player.md +82 -82
  38. package/documentation/composants.md +46 -46
  39. package/documentation/composants_critiques/ModelPageComposant.md +53 -53
  40. package/documentation/composants_critiques/app-base-module.md +43 -43
  41. package/documentation/composants_critiques/app-base-page.md +48 -48
  42. package/documentation/composants_critiques/app-base.md +311 -311
  43. package/documentation/composants_critiques/main.md +15 -15
  44. package/documentation/demarrage.md +50 -50
  45. package/documentation/deploiement.md +57 -57
  46. package/documentation/index.md +33 -33
  47. package/documentation/markdown-examples.md +85 -85
  48. package/documentation/public/vite.svg +14 -14
  49. package/documentation/public/vuejs.svg +1 -1
  50. package/documentation/public/vuetify.svg +5 -5
  51. package/eslint.config.js +60 -60
  52. package/junit-report.xml +182 -0
  53. package/package.json +66 -59
  54. package/playwright/index.html +12 -0
  55. package/playwright/index.js +21 -0
  56. package/playwright-ct.config.js +95 -0
  57. package/src/$locales/en.json +157 -157
  58. package/src/$locales/fr.json +120 -120
  59. package/src/assets/data/onboardingMessages.json +47 -47
  60. package/src/components/AppBase.vue +1171 -1169
  61. package/src/components/AppBaseButton.vue +90 -95
  62. package/src/components/AppBaseErrorDisplay.vue +438 -438
  63. package/src/components/AppBaseFlipCard.vue +84 -84
  64. package/src/components/AppBaseModule.vue +1639 -1634
  65. package/src/components/AppBasePage.vue +3 -2
  66. package/src/components/AppBasePopover.vue +41 -41
  67. package/src/components/AppBaseSkeleton.vue +66 -66
  68. package/src/components/AppCompAudio.vue +261 -256
  69. package/src/components/AppCompBranchButtons.vue +508 -508
  70. package/src/components/AppCompButtonProgress.vue +137 -132
  71. package/src/components/AppCompCarousel.vue +342 -336
  72. package/src/components/AppCompContainer.vue +29 -29
  73. package/src/components/AppCompInputCheckBoxNx.vue +325 -323
  74. package/src/components/AppCompInputDropdownNx.vue +302 -299
  75. package/src/components/AppCompInputRadioNx.vue +287 -284
  76. package/src/components/AppCompInputTextNx.vue +156 -153
  77. package/src/components/AppCompInputTextTableNx.vue +205 -202
  78. package/src/components/AppCompInputTextToFillDropdownNx.vue +343 -340
  79. package/src/components/AppCompInputTextToFillNx.vue +316 -313
  80. package/src/components/AppCompJauge.vue +81 -81
  81. package/src/components/AppCompMenu.vue +6 -2
  82. package/src/components/AppCompMenuItem.vue +246 -240
  83. package/src/components/AppCompNavigation.vue +977 -972
  84. package/src/components/AppCompNoteCall.vue +167 -161
  85. package/src/components/AppCompNoteCredit.vue +496 -491
  86. package/src/components/AppCompPlayBarNext.vue +2290 -2288
  87. package/src/components/AppCompPopUpNext.vue +508 -504
  88. package/src/components/AppCompQuizNext.vue +515 -510
  89. package/src/components/AppCompQuizRecall.vue +355 -350
  90. package/src/components/AppCompSVGNext.vue +346 -346
  91. package/src/components/AppCompSettingsMenu.vue +177 -172
  92. package/src/components/AppCompTableOfContent.vue +433 -427
  93. package/src/components/AppCompVideoPlayer.vue +377 -377
  94. package/src/components/AppCompViewDisplay.vue +6 -6
  95. package/src/components/BaseModule.vue +55 -55
  96. package/src/composables/useIdleDetector.js +56 -56
  97. package/src/composables/useQuiz.js +89 -89
  98. package/src/composables/useTimer.js +172 -172
  99. package/src/directives/nvdaFix.js +53 -53
  100. package/src/externalComps/ModuleView.vue +22 -22
  101. package/src/externalComps/SummaryView.vue +91 -91
  102. package/src/main.js +493 -476
  103. package/src/module/stores/appStore.js +960 -947
  104. package/src/module/xapi/ADL.js +520 -520
  105. package/src/module/xapi/Crypto/Hasher.js +241 -241
  106. package/src/module/xapi/Crypto/WordArray.js +278 -278
  107. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  108. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
  109. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  110. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  111. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  112. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  113. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  114. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  115. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  116. package/src/module/xapi/Crypto/index.js +53 -53
  117. package/src/module/xapi/Statement/activity.js +47 -47
  118. package/src/module/xapi/Statement/agent.js +55 -55
  119. package/src/module/xapi/Statement/group.js +26 -26
  120. package/src/module/xapi/Statement/index.js +259 -259
  121. package/src/module/xapi/Statement/statement.js +253 -253
  122. package/src/module/xapi/Statement/statementRef.js +23 -23
  123. package/src/module/xapi/Statement/substatement.js +22 -22
  124. package/src/module/xapi/Statement/verb.js +36 -36
  125. package/src/module/xapi/activitytypes.js +17 -17
  126. package/src/module/xapi/launch.js +157 -157
  127. package/src/module/xapi/utils.js +167 -167
  128. package/src/module/xapi/verbs.js +294 -294
  129. package/src/module/xapi/wrapper.js +1895 -1895
  130. package/src/module/xapi/xapiStatement.js +444 -444
  131. package/src/plugins/analytics.js +34 -34
  132. package/src/plugins/bus.js +12 -8
  133. package/src/plugins/gsap.js +17 -15
  134. package/src/plugins/helper.js +355 -358
  135. package/src/plugins/i18n.js +27 -26
  136. package/src/plugins/idb.js +227 -227
  137. package/src/plugins/save.js +37 -37
  138. package/src/plugins/scorm.js +287 -287
  139. package/src/plugins/xapi.js +11 -11
  140. package/src/public/index.html +33 -33
  141. package/src/router/index.js +57 -57
  142. package/src/router/routes.js +312 -312
  143. package/src/shared/generalfuncs.js +344 -344
  144. package/src/shared/validators.js +1018 -1018
  145. package/tests/component/AppBaseButton.spec.js +53 -0
  146. package/tests/component/pinia.spec.js +24 -0
  147. package/{src/components/tests__ → tests/unit}/AppBaseButton.spec.js +53 -53
  148. package/tests/unit/AppCompInputCheckBoxNx.spec.js +59 -0
  149. package/tests/unit/AppCompInputDropdownNx.spec.js +51 -0
  150. package/tests/unit/AppCompInputRadioNx.spec.js +59 -0
  151. package/tests/unit/AppCompInputTextNx.spec.js +44 -0
  152. package/tests/unit/AppCompInputTextTableNx.spec.js +77 -0
  153. package/tests/unit/AppCompInputTextToFillDropdownNx.spec.js +60 -0
  154. package/tests/unit/AppCompInputTextToFillNx.spec.js +45 -0
  155. package/tests/unit/AppCompQuizNext.spec.js +114 -0
  156. package/tests/unit/AppCompVideoPlayer.spec.js +177 -0
  157. package/{src/components/tests__ → tests/unit}/useTimer.spec.js +91 -91
  158. package/vitest.config.js +28 -19
  159. package/vitest.setup.js +28 -0
  160. package/src/components/AppBaseButton.test.js +0 -21
@@ -1,299 +1,302 @@
1
- <!-- About this Component--
2
- * Renders a SELECT input to display choices of response for the Quiz component
3
- * Related Quiz to question: DROPDOWN
4
- * Receives the a data object defined by user
5
- * Used by AppCompQuiz
6
- * Uses useQuiz composable
7
- -->
8
- <template>
9
- <div v-if="inputData.length > 0" :id="id" class="input-box">
10
- <fieldset :aria-label="fieldsetLabel">
11
- <div
12
- v-for="(singleDropdown, index) in inputData"
13
- :key="singleDropdown.id"
14
- class="dropdown-container"
15
- :class="`dropdownlist-${singleDropdown.id}`"
16
- >
17
- <label
18
- :id="`label_dropdown_${id}_${singleDropdown.id}`"
19
- :for="`dropdown_${id}_${singleDropdown.id}`"
20
- v-html="singleDropdown.ennonce"
21
- ></label>
22
-
23
- <div class="cnt-input" :class="`${retro[index] ? retro[index] : ''}`">
24
- <v-select
25
- :id="`dropdown_${id}_${singleDropdown.id}`"
26
- :model-value="inputsValue[singleDropdown.id]"
27
- item-title="text"
28
- :item-props="true"
29
- :items="getItemOptions(index)"
30
- :open-text="`${$t('message.dropdown_list')}_${singleDropdown.ennonce}`"
31
- :aria-describedby="`${id}_${singleDropdown.id}-msg-erreur`"
32
- @update:model-value="onSelectUpdate($event, index)"
33
- ></v-select>
34
-
35
- <span
36
- :id="`${id}_${singleDropdown.id}-msg-erreur`"
37
- :key="`msg_chx_${id}_${singleDropdown.id}`"
38
- class="sr-only"
39
- >
40
- {{ messageAccessibility[index] }}
41
- </span>
42
- </div>
43
- </div>
44
- </fieldset>
45
- </div>
46
- </template>
47
- <script>
48
- import { useQuiz } from '../composables/useQuiz'
49
- import { validateObjType } from '../shared/validators'
50
- export default {
51
- name: 'AppCompInputDropdown',
52
- /* PROPS USED FOR PARENT TO COMMUNICATE DATA TO CHILD */
53
- props: {
54
- modelValue: {
55
- type: Array,
56
- default: () => []
57
- },
58
- inputData: {
59
- type: Array,
60
- default: () => []
61
- },
62
- solution: {
63
- type: Array,
64
- default: () => []
65
- },
66
- id: {
67
- type: String,
68
- default: ''
69
- }
70
- },
71
- emits: ['update:modelValue', 'enable-submit'],
72
- setup(props) {
73
- const { retroType, addRetroStyle, resetRetroStyle } = useQuiz()
74
-
75
- return { retroType, addRetroStyle, resetRetroStyle }
76
- },
77
- data() {
78
- return {
79
- retro: [],
80
- messageAccessibility: [],
81
- result: [],
82
- oldValue: null
83
- }
84
- },
85
- computed: {
86
- fieldsetLabel() {
87
- let label
88
- if (this.inputData.length === 1) {
89
- label = this.$t('quizState.dropdownFieldsetSingle')
90
- } else {
91
- label = `${this.$t('quizState.dropdownFieldsetMulti1')} ${this.inputData.length} ${this.$t('quizState.dropdownFieldsetMulti2')}`
92
- }
93
- return label
94
- },
95
- /* INTERNAL REACTIVE VALUE THAT BIND WITH MODELVALUE PROPS */
96
- inputsValue: {
97
- get() {
98
- return this.modelValue
99
- },
100
- set(newValue) {
101
- this.$emit('update:modelValue', [...newValue])
102
- }
103
- },
104
- mappedOptions() {
105
- if (this.inputData.length === 0) return []
106
-
107
- return this.inputData.map((op) => {
108
- const key = Object.keys(op)[0]
109
- const values = Object.values(op)[2]
110
-
111
- const newValues = [
112
- {
113
- value: null,
114
- disabled: true,
115
- selected: true,
116
- text: this.$t('message.first_option_dropdown')
117
- // text: 'choisir une option'
118
- },
119
- ...values.map((el) => ({
120
- value: el,
121
- text: el,
122
- selected: false
123
- }))
124
- ]
125
-
126
- return {
127
- [key]: newValues
128
- }
129
- })
130
- }
131
- },
132
- watch: {
133
- inputsValue: {
134
- handler() {
135
- if (this.$el && this.$el.id !== this.id) return
136
- const filled = this.modelValue.filter((val) => val && val.trim() !== '')
137
-
138
- this.$emit('enable-submit', filled.length === this.inputData.length)
139
- },
140
- deep: true,
141
- immediate: true
142
- }
143
- },
144
- created() {
145
- if (import.meta.env.DEV) {
146
- let errors = this.validateInputData()
147
- if (errors && errors.errorList.length) {
148
- return this.$bus.$emit('input-error', { e: this.id, errors })
149
- }
150
- }
151
- },
152
- mounted() {},
153
-
154
- methods: {
155
- validateInputData() {
156
- let errors = null
157
- let stringType = ['id', 'ennonce']
158
- let arrayType = ['option']
159
- let e = null
160
-
161
- if (!this.inputData.length) return errors
162
- for (let i = 0; i < this.inputData.length; i++) {
163
- e = validateObjType(
164
- this.inputData[i],
165
- { stringType, arrayType },
166
- null,
167
- `liste déroulante #${i + 1}`
168
- )
169
-
170
- if (e.errorInConsole.length && e.errorList.length) {
171
- errors.errorInConsole.push(e.errorInConsole[0])
172
- errors.errorList.push(e.errorList[0])
173
- }
174
- }
175
-
176
- return errors
177
- },
178
- /**
179
- * @description Method to retrive the options of each selectable input in the mappedOption Object
180
- * @param {Number } index - number representing the index of the item in the array of inputElements
181
- * @Return a collection of item representing the options for a the selectables
182
- */
183
- getItemOptions(index) {
184
- return Object.values(this.mappedOptions[index])[0]
185
- },
186
- /**
187
- * @description Method to force update of this.inputsValue.
188
- * this force the old value and new value of the input to be tracked by VUE.
189
- * @param newValue, the new value of the input
190
- * @param index index of the selected element
191
- */
192
-
193
- onSelectUpdate(newValue, index) {
194
- if (this.$el && this.$el.id !== this.id) return //prevent event from firing on other input
195
- this.resetRetroStyle([this.retro, this.messageAccessibility])
196
- const updated = [...this.inputsValue] //create new array from inputsValue
197
- updated[index] = newValue
198
- this.inputsValue = updated //trigger vue reactivity for inputsValue
199
- },
200
- /**
201
- * @description Component validation method to validate the user input against the solution
202
- * can handle logic of Css style to apply (correct/wrong Answer) and return the result
203
- * @return {Object} result
204
- */
205
- validateAnswer() {
206
- let mappedResults
207
- if (this.solution != null) {
208
- mappedResults = this.inputsValue.map((a, i) => {
209
- const s = this.solution[i]
210
- return { selected: a, correct: s == a }
211
- })
212
- } else {
213
- mappedResults = this.inputsValue.map((a, i) => {
214
- return { selected: a, correct: false }
215
- })
216
- }
217
-
218
- let { classRetro, mesA11y } = this.addRetroStyle(
219
- this.solution,
220
- mappedResults,
221
- this.inputData.length
222
- )
223
-
224
- this.retro = [...classRetro]
225
- this.messageAccessibility = [...mesA11y]
226
-
227
- this.retro = classRetro
228
- this.messageAccessibility = mesA11y
229
-
230
- this.result = mappedResults.filter((a) => a.selected)
231
- let tr = this.retroType(this.solution, this.result)
232
-
233
- let cAns
234
- if (this.solution != null) cAns = this.computeResult(this.result)
235
- else cAns = false
236
-
237
- return {
238
- userAnswer: this.result,
239
- correctAnswer: cAns,
240
- retroType: tr
241
- }
242
- },
243
- computeResult(result) {
244
- const res = result.filter((el) => el.correct)
245
- return res.length == this.solution.length
246
- }
247
- }
248
- }
249
- </script>
250
- <style lang="scss">
251
- .dropdown-container {
252
- position: relative;
253
- }
254
-
255
- fieldset {
256
- border: inherit;
257
- }
258
-
259
- div.texteatrou {
260
- display: inline !important;
261
- .cnt-input {
262
- display: inline;
263
-
264
- .v-input {
265
- display: inline-block !important;
266
-
267
- .v-input__control,
268
- .v-field {
269
- width: 240px !important;
270
- grid-area: inherit !important;
271
-
272
- .v-field__field {
273
- height: 25px !important;
274
- padding: 0 !important;
275
- min-height: inherit !important;
276
-
277
- .v-field__input {
278
- padding-top: 0 !important;
279
- padding-bottom: 0 !important;
280
- min-height: inherit !important;
281
-
282
- .v-select__selection {
283
- min-height: inherit !important;
284
- }
285
- }
286
- }
287
-
288
- .v-field__append-inner {
289
- margin-right: 6px;
290
- }
291
- }
292
-
293
- .v-input__details {
294
- display: none;
295
- }
296
- }
297
- }
298
- }
299
- </style>
1
+ <!-- About this Component--
2
+ * Renders a SELECT input to display choices of response for the Quiz component
3
+ * Related Quiz to question: DROPDOWN
4
+ * Receives the a data object defined by user
5
+ * Used by AppCompQuiz
6
+ * Uses useQuiz composable
7
+ -->
8
+ <template>
9
+ <div v-if="inputData.length > 0" :id="id" class="input-box">
10
+ <fieldset :aria-label="fieldsetLabel">
11
+ <div
12
+ v-for="(singleDropdown, index) in inputData"
13
+ :key="singleDropdown.id"
14
+ class="dropdown-container"
15
+ :class="`dropdownlist-${singleDropdown.id}`"
16
+ >
17
+ <label
18
+ :id="`label_dropdown_${id}_${singleDropdown.id}`"
19
+ :for="`dropdown_${id}_${singleDropdown.id}`"
20
+ v-html="singleDropdown.ennonce"
21
+ ></label>
22
+
23
+ <div class="cnt-input" :class="`${retro[index] ? retro[index] : ''}`">
24
+ <v-select
25
+ :id="`dropdown_${id}_${singleDropdown.id}`"
26
+ :model-value="inputsValue[singleDropdown.id]"
27
+ item-title="text"
28
+ :item-props="true"
29
+ :items="getItemOptions(index)"
30
+ :open-text="`${$t('message.dropdown_list')}_${singleDropdown.ennonce}`"
31
+ :aria-describedby="`${id}_${singleDropdown.id}-msg-erreur`"
32
+ @update:model-value="onSelectUpdate($event, index)"
33
+ ></v-select>
34
+
35
+ <span
36
+ :id="`${id}_${singleDropdown.id}-msg-erreur`"
37
+ :key="`msg_chx_${id}_${singleDropdown.id}`"
38
+ class="sr-only"
39
+ >
40
+ {{ messageAccessibility[index] }}
41
+ </span>
42
+ </div>
43
+ </div>
44
+ </fieldset>
45
+ </div>
46
+ </template>
47
+ <script>
48
+ import { useQuiz } from '../composables/useQuiz'
49
+ import { validateObjType } from '../shared/validators'
50
+ import { useI18n } from 'vue-i18n'
51
+
52
+ export default {
53
+ name: 'AppCompInputDropdown',
54
+ /* PROPS USED FOR PARENT TO COMMUNICATE DATA TO CHILD */
55
+ props: {
56
+ modelValue: {
57
+ type: Array,
58
+ default: () => []
59
+ },
60
+ inputData: {
61
+ type: Array,
62
+ default: () => []
63
+ },
64
+ solution: {
65
+ type: Array,
66
+ default: () => []
67
+ },
68
+ id: {
69
+ type: String,
70
+ default: ''
71
+ }
72
+ },
73
+ emits: ['update:modelValue', 'enable-submit'],
74
+ setup(props) {
75
+ const { t } = useI18n()
76
+ const { retroType, addRetroStyle, resetRetroStyle } = useQuiz()
77
+
78
+ return { retroType, addRetroStyle, resetRetroStyle, t }
79
+ },
80
+ data() {
81
+ return {
82
+ retro: [],
83
+ messageAccessibility: [],
84
+ result: [],
85
+ oldValue: null
86
+ }
87
+ },
88
+ computed: {
89
+ fieldsetLabel() {
90
+ let label
91
+ if (this.inputData.length === 1) {
92
+ label = this.$t('quizState.dropdownFieldsetSingle')
93
+ } else {
94
+ label = `${this.$t('quizState.dropdownFieldsetMulti1')} ${this.inputData.length} ${this.$t('quizState.dropdownFieldsetMulti2')}`
95
+ }
96
+ return label
97
+ },
98
+ /* INTERNAL REACTIVE VALUE THAT BIND WITH MODELVALUE PROPS */
99
+ inputsValue: {
100
+ get() {
101
+ return this.modelValue
102
+ },
103
+ set(newValue) {
104
+ this.$emit('update:modelValue', [...newValue])
105
+ }
106
+ },
107
+ mappedOptions() {
108
+ if (this.inputData.length === 0) return []
109
+
110
+ return this.inputData.map((op) => {
111
+ const key = Object.keys(op)[0]
112
+ const values = Object.values(op)[2]
113
+
114
+ const newValues = [
115
+ {
116
+ value: null,
117
+ disabled: true,
118
+ selected: true,
119
+ text: this.$t('message.first_option_dropdown')
120
+ // text: 'choisir une option'
121
+ },
122
+ ...values.map((el) => ({
123
+ value: el,
124
+ text: el,
125
+ selected: false
126
+ }))
127
+ ]
128
+
129
+ return {
130
+ [key]: newValues
131
+ }
132
+ })
133
+ }
134
+ },
135
+ watch: {
136
+ inputsValue: {
137
+ handler() {
138
+ if (this.$el && this.$el.id !== this.id) return
139
+ const filled = this.modelValue.filter((val) => val && val.trim() !== '')
140
+
141
+ this.$emit('enable-submit', filled.length === this.inputData.length)
142
+ },
143
+ deep: true,
144
+ immediate: true
145
+ }
146
+ },
147
+ created() {
148
+ if (import.meta.env.DEV) {
149
+ let errors = this.validateInputData()
150
+ if (errors && errors.errorList.length) {
151
+ return this.$bus.$emit('input-error', { e: this.id, errors })
152
+ }
153
+ }
154
+ },
155
+ mounted() {},
156
+
157
+ methods: {
158
+ validateInputData() {
159
+ let errors = null
160
+ let stringType = ['id', 'ennonce']
161
+ let arrayType = ['option']
162
+ let e = null
163
+
164
+ if (!this.inputData.length) return errors
165
+ for (let i = 0; i < this.inputData.length; i++) {
166
+ e = validateObjType(
167
+ this.inputData[i],
168
+ { stringType, arrayType },
169
+ null,
170
+ `liste déroulante #${i + 1}`
171
+ )
172
+
173
+ if (e.errorInConsole.length && e.errorList.length) {
174
+ errors.errorInConsole.push(e.errorInConsole[0])
175
+ errors.errorList.push(e.errorList[0])
176
+ }
177
+ }
178
+
179
+ return errors
180
+ },
181
+ /**
182
+ * @description Method to retrive the options of each selectable input in the mappedOption Object
183
+ * @param {Number } index - number representing the index of the item in the array of inputElements
184
+ * @Return a collection of item representing the options for a the selectables
185
+ */
186
+ getItemOptions(index) {
187
+ return Object.values(this.mappedOptions[index])[0]
188
+ },
189
+ /**
190
+ * @description Method to force update of this.inputsValue.
191
+ * this force the old value and new value of the input to be tracked by VUE.
192
+ * @param newValue, the new value of the input
193
+ * @param index index of the selected element
194
+ */
195
+
196
+ onSelectUpdate(newValue, index) {
197
+ if (this.$el && this.$el.id !== this.id) return //prevent event from firing on other input
198
+ this.resetRetroStyle([this.retro, this.messageAccessibility])
199
+ const updated = [...this.inputsValue] //create new array from inputsValue
200
+ updated[index] = newValue
201
+ this.inputsValue = updated //trigger vue reactivity for inputsValue
202
+ },
203
+ /**
204
+ * @description Component validation method to validate the user input against the solution
205
+ * can handle logic of Css style to apply (correct/wrong Answer) and return the result
206
+ * @return {Object} result
207
+ */
208
+ validateAnswer() {
209
+ let mappedResults
210
+ if (this.solution != null) {
211
+ mappedResults = this.inputsValue.map((a, i) => {
212
+ const s = this.solution[i]
213
+ return { selected: a, correct: s == a }
214
+ })
215
+ } else {
216
+ mappedResults = this.inputsValue.map((a, i) => {
217
+ return { selected: a, correct: false }
218
+ })
219
+ }
220
+
221
+ let { classRetro, mesA11y } = this.addRetroStyle(
222
+ this.solution,
223
+ mappedResults,
224
+ this.inputData.length
225
+ )
226
+
227
+ this.retro = [...classRetro]
228
+ this.messageAccessibility = [...mesA11y]
229
+
230
+ this.retro = classRetro
231
+ this.messageAccessibility = mesA11y
232
+
233
+ this.result = mappedResults.filter((a) => a.selected)
234
+ let tr = this.retroType(this.solution, this.result)
235
+
236
+ let cAns
237
+ if (this.solution != null) cAns = this.computeResult(this.result)
238
+ else cAns = false
239
+
240
+ return {
241
+ userAnswer: this.result,
242
+ correctAnswer: cAns,
243
+ retroType: tr
244
+ }
245
+ },
246
+ computeResult(result) {
247
+ const res = result.filter((el) => el.correct)
248
+ return res.length == this.solution.length
249
+ }
250
+ }
251
+ }
252
+ </script>
253
+ <style lang="scss">
254
+ .dropdown-container {
255
+ position: relative;
256
+ }
257
+
258
+ fieldset {
259
+ border: inherit;
260
+ }
261
+
262
+ div.texteatrou {
263
+ display: inline !important;
264
+ .cnt-input {
265
+ display: inline;
266
+
267
+ .v-input {
268
+ display: inline-block !important;
269
+
270
+ .v-input__control,
271
+ .v-field {
272
+ width: 240px !important;
273
+ grid-area: inherit !important;
274
+
275
+ .v-field__field {
276
+ height: 25px !important;
277
+ padding: 0 !important;
278
+ min-height: inherit !important;
279
+
280
+ .v-field__input {
281
+ padding-top: 0 !important;
282
+ padding-bottom: 0 !important;
283
+ min-height: inherit !important;
284
+
285
+ .v-select__selection {
286
+ min-height: inherit !important;
287
+ }
288
+ }
289
+ }
290
+
291
+ .v-field__append-inner {
292
+ margin-right: 6px;
293
+ }
294
+ }
295
+
296
+ .v-input__details {
297
+ display: none;
298
+ }
299
+ }
300
+ }
301
+ }
302
+ </style>