fcad-core-dragon 2.0.1 → 2.0.2-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 (90) hide show
  1. package/.editorconfig +33 -33
  2. package/.eslintignore +29 -29
  3. package/.eslintrc.cjs +81 -81
  4. package/CHANGELOG +17 -1
  5. package/bk.scss +117 -117
  6. package/package.json +1 -1
  7. package/src/$locales/en.json +18 -4
  8. package/src/$locales/fr.json +17 -3
  9. package/src/assets/data/onboardingMessages.json +47 -47
  10. package/src/components/AppBase.vue +36 -341
  11. package/src/components/AppBaseErrorDisplay.vue +438 -438
  12. package/src/components/AppBaseFlipCard.vue +84 -84
  13. package/src/components/AppBaseModule.vue +16 -21
  14. package/src/components/AppBasePage.vue +45 -14
  15. package/src/components/AppBasePopover.vue +41 -41
  16. package/src/components/AppBaseSkeleton.vue +45 -0
  17. package/src/components/AppCompAudio.vue +12 -3
  18. package/src/components/AppCompButtonProgress.vue +13 -2
  19. package/src/components/AppCompCarousel.vue +12 -4
  20. package/src/components/AppCompInputCheckBoxNx.vue +324 -0
  21. package/src/components/AppCompInputDropdownNx.vue +295 -0
  22. package/src/components/AppCompInputRadioNx.vue +264 -0
  23. package/src/components/AppCompInputTextNx.vue +148 -0
  24. package/src/components/AppCompInputTextTableNx.vue +198 -0
  25. package/src/components/AppCompInputTextToFillDropdownNx.vue +291 -0
  26. package/src/components/AppCompInputTextToFillNx.vue +277 -0
  27. package/src/components/AppCompJauge.vue +11 -4
  28. package/src/components/AppCompMenu.vue +7 -14
  29. package/src/components/AppCompMenuItem.vue +7 -5
  30. package/src/components/AppCompNavigation.vue +21 -21
  31. package/src/components/AppCompNoteCall.vue +1 -0
  32. package/src/components/AppCompNoteCredit.vue +2 -1
  33. package/src/components/AppCompPlayBarNext.vue +94 -41
  34. package/src/components/AppCompPlayBarProgress.vue +82 -82
  35. package/src/components/AppCompPopUpNext.vue +6 -6
  36. package/src/components/AppCompQuiz.vue +500 -0
  37. package/src/components/AppCompQuizRecall.vue +113 -66
  38. package/src/components/AppCompSettingsMenu.vue +172 -172
  39. package/src/components/AppCompTableOfContent.vue +39 -10
  40. package/src/components/AppCompVideoPlayer.vue +1 -1
  41. package/src/components/AppCompViewDisplay.vue +6 -6
  42. package/src/composables/useQuiz.js +62 -179
  43. package/src/directives/nvdaFix.js +53 -0
  44. package/src/externalComps/ModuleView.vue +22 -22
  45. package/src/externalComps/SummaryView.vue +91 -91
  46. package/src/main.js +227 -30
  47. package/src/mixins/$mediaMixins.js +1 -11
  48. package/src/module/stores/appStore.js +29 -11
  49. package/src/module/xapi/Crypto/Hasher.js +241 -241
  50. package/src/module/xapi/Crypto/WordArray.js +278 -278
  51. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  52. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
  53. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  54. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  55. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  56. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  57. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  58. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  59. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  60. package/src/module/xapi/Crypto/index.js +53 -53
  61. package/src/module/xapi/Statement/activity.js +47 -47
  62. package/src/module/xapi/Statement/agent.js +55 -55
  63. package/src/module/xapi/Statement/group.js +26 -26
  64. package/src/module/xapi/Statement/index.js +259 -259
  65. package/src/module/xapi/Statement/statement.js +253 -253
  66. package/src/module/xapi/Statement/statementRef.js +23 -23
  67. package/src/module/xapi/Statement/substatement.js +22 -22
  68. package/src/module/xapi/Statement/verb.js +36 -36
  69. package/src/module/xapi/activitytypes.js +17 -17
  70. package/src/module/xapi/utils.js +167 -167
  71. package/src/module/xapi/verbs.js +294 -294
  72. package/src/module/xapi/xapiStatement.js +444 -444
  73. package/src/plugins/bus.js +8 -8
  74. package/src/plugins/gsap.js +14 -14
  75. package/src/plugins/i18n.js +44 -44
  76. package/src/plugins/idb.js +1 -1
  77. package/src/plugins/save.js +37 -37
  78. package/src/plugins/scorm.js +287 -287
  79. package/src/plugins/xapi.js +11 -11
  80. package/src/public/index.html +33 -33
  81. package/src/shared/generalfuncs.js +134 -0
  82. package/src/shared/validators.js +308 -234
  83. package/src/components/AppCompInputCheckBoxNext.vue +0 -205
  84. package/src/components/AppCompInputDropdownNext.vue +0 -201
  85. package/src/components/AppCompInputRadioNext.vue +0 -158
  86. package/src/components/AppCompInputTextNext.vue +0 -124
  87. package/src/components/AppCompInputTextTableNext.vue +0 -142
  88. package/src/components/AppCompInputTextToFillDropdownNext.vue +0 -238
  89. package/src/components/AppCompInputTextToFillNext.vue +0 -171
  90. package/src/components/AppCompQuizNext.vue +0 -2908
@@ -70,7 +70,7 @@
70
70
  :disabled="disablePrev"
71
71
  @click="prevSlide()"
72
72
  >
73
- <svg>
73
+ <svg aria-hidden="true" focusable="false">
74
74
  <use href="#fleche-gauche-icon"></use>
75
75
  </svg>
76
76
  </app-base-button>
@@ -85,7 +85,7 @@
85
85
  :disabled="disableNext"
86
86
  @click="nextSlide()"
87
87
  >
88
- <svg>
88
+ <svg aria-hidden="true" focusable="false">
89
89
  <use href="#fleche-droite-icon"></use>
90
90
  </svg>
91
91
  </app-base-button>
@@ -93,19 +93,21 @@
93
93
  </div>
94
94
  </template>
95
95
  <div class="carousel-index">
96
- <p aria-hidden="true">{{ currentSlide }}/{{ slideLength }}</p>
96
+ <p aria-hidden="true">{{ sliderPagination }}</p>
97
97
  </div>
98
98
  </section>
99
99
  </template>
100
100
 
101
101
  <script>
102
102
  import AppBaseErrorDisplay from './AppBaseErrorDisplay.vue'
103
+ import { mapState } from 'pinia'
104
+ import { useAppStore } from '../module/stores/appStore'
103
105
  export default {
104
106
  name: 'AppCompSlider',
105
107
  components: { AppBaseErrorDisplay },
106
108
  props: {
107
109
  slides: { type: Array, required: true }, //Array of slides {imgSrc, imgAlt, title, hypertext}
108
- name: { type: String, default: 'toto cool' }
110
+ name: { type: String, default: 'Sooo cool' }
109
111
  },
110
112
  data() {
111
113
  return {
@@ -116,6 +118,7 @@ export default {
116
118
  }
117
119
  },
118
120
  computed: {
121
+ ...mapState(useAppStore, ['getAppConfigs']),
119
122
  disablePrev() {
120
123
  return !(this.currentSlide > 1)
121
124
  },
@@ -124,6 +127,11 @@ export default {
124
127
  },
125
128
  slideLength() {
126
129
  return this.slides ? this.slides.length : 0
130
+ },
131
+ sliderPagination() {
132
+ return this.getAppConfigs.lang.toLowerCase() == 'en'
133
+ ? `${this.currentSlide}/${this.slideLength}`
134
+ : `${this.currentSlide} / ${this.slideLength}`
127
135
  }
128
136
  },
129
137
  created() {
@@ -0,0 +1,324 @@
1
+ <!-- About this Component--
2
+ * Renders a checkboxe input type for the Quiz component
3
+ * Related Quiz to question: REPONSE_MULTIPLE
4
+ * Receives the a data object defined by user
5
+ * Used by AppCompQuiz
6
+ -->
7
+ <template>
8
+ <div :id="id" class="input-box">
9
+ <fieldset :aria-label="fieldsetLabel">
10
+ <template
11
+ v-for="(choixReponse, index) in inputData"
12
+ :Key="`div_chx_${id}_${choixReponse.id}`"
13
+ >
14
+ <div class="box-checkbox" role="group">
15
+ <label
16
+ :key="`lbl_chx_${id}-${choixReponse.id}`"
17
+ :for="`boxchx_${id}_${choixReponse.id}`"
18
+ class="checkbox-label"
19
+ :class="[
20
+ {
21
+ answerSlct: isSelected(choixReponse.value)
22
+ },
23
+ `${retro[index]}`
24
+ ]"
25
+ >
26
+ <input
27
+ :id="`boxchx_${id}_${choixReponse.id}`"
28
+ :key="`boxchx_${id}_${id}-${choixReponse.id}`"
29
+ :checked="isSelected(choixReponse.value)"
30
+ type="checkbox"
31
+ :name="`btn-checkbox-${id}`"
32
+ :aria-labelledby="`span_${id}_${choixReponse.id}`"
33
+ :aria-describedby="`${id}_${choixReponse.id}-msg-erreur`"
34
+ @change="onSelectUpdate($event, choixReponse.value)"
35
+ />
36
+ <span
37
+ :id="`span_${id}_${choixReponse.id}`"
38
+ class="checkbox-contenu"
39
+ aria-hidden="true"
40
+ v-html="choixReponse.value"
41
+ ></span>
42
+ <span
43
+ :id="`${id}_${choixReponse.id}-msg-erreur`"
44
+ :key="`msg_chx_${id}_${choixReponse.id}`"
45
+ class="sr-only"
46
+ >
47
+ {{ messageAccessibility[index] }}
48
+ </span>
49
+ </label>
50
+ </div>
51
+ </template>
52
+ </fieldset>
53
+ </div>
54
+ </template>
55
+ <script>
56
+ import { useQuiz } from '../composables/useQuiz'
57
+ import { validateObjType } from '../shared/validators'
58
+ export default {
59
+ name: 'AppCompInputCheckBoxNx',
60
+ /* PROPS USED FOR PARENT TO COMMUNICATE DATA TO CHILD */
61
+ props: {
62
+ modelValue: {
63
+ type: Array,
64
+ default: () => []
65
+ },
66
+ inputData: {
67
+ type: Array,
68
+ default: () => []
69
+ },
70
+ solution: {
71
+ type: Array,
72
+ default: () => []
73
+ },
74
+ id: {
75
+ type: String,
76
+ default: ''
77
+ }
78
+ },
79
+ emits: ['update:modelValue', 'enable-submit'],
80
+ setup() {
81
+ const { retroType, addRetroStyle, resetRetroStyle } = useQuiz()
82
+
83
+ return { retroType, addRetroStyle, resetRetroStyle }
84
+ },
85
+ data() {
86
+ return {
87
+ quizInputDataValue: [],
88
+ result: null,
89
+ retro: [],
90
+ messageAccessibility: [],
91
+ selectedItems: []
92
+ }
93
+ },
94
+ computed: {
95
+ fieldsetLabel() {
96
+ return `${this.$t('quizState.checkboxFieldset')} ${this.inputData.length} ${this.$t('quizState.options')}`
97
+ },
98
+ /* INTERNAL REACTIVE VALUE THAT BIND WITH MODELVALUE PROPS */
99
+ inputsValue: {
100
+ get() {
101
+ return this.modelValue
102
+ },
103
+
104
+ set(newValue) {
105
+ if (
106
+ (this.$el && this.$el.id !== this.id) ||
107
+ newValue.constructor !== Array
108
+ )
109
+ return
110
+
111
+ this.$emit('update:modelValue', newValue)
112
+ }
113
+ },
114
+ /**
115
+ * internal reactive value that map the options to add SELECTED attribute on each option
116
+ * this attribute value can be changed when user select the option
117
+ */
118
+ mappedOptions() {
119
+ const options = this.inputData.map((op) => {
120
+ const selectedItem = this.modelValue.find((i) => i.id === op.id)
121
+ return {
122
+ ...op,
123
+ selected: selectedItem ? selectedItem.selected : false
124
+ }
125
+ })
126
+
127
+ return options
128
+ }
129
+ },
130
+ watch: {
131
+ inputsValue: {
132
+ handler(newVal) {
133
+ this.$emit('enable-submit', newVal.length > 0)
134
+ },
135
+ deep: true,
136
+ immediate: true
137
+ }
138
+ },
139
+ created() {
140
+ if (import.meta.env.DEV) {
141
+ let errors = this.validateInputData()
142
+
143
+ if (errors && errors.errorList.length)
144
+ return this.$bus.$emit('input-error', { e: this.id, errors })
145
+ }
146
+
147
+ this.quizInputDataValue = this.inputData
148
+ },
149
+ mounted() {},
150
+
151
+ methods: {
152
+ /**
153
+ * @description validate the raw data received by the component to render is view
154
+ * @returns {Object} errors - errorList: to display in view and errorConsole, to be displayed in console
155
+ */
156
+ validateInputData() {
157
+ let errors = null //array for errors dectected
158
+ let stringType = ['id', 'value']
159
+
160
+ if (!this.inputData.length) return errors
161
+ for (let i = 0; i < this.inputData.length; i++) {
162
+ errors = validateObjType(
163
+ this.inputData[i],
164
+ { stringType },
165
+ null,
166
+ `choix_reponse #${i + 1}`
167
+ )
168
+ const { errorList, errorInConsole } = errors
169
+
170
+ if (errorList.length || errorInConsole.length) return errors
171
+ }
172
+
173
+ return errors
174
+ },
175
+
176
+ /**
177
+ * @description inicate wether the element is checked or not.
178
+ * Element is selected if in the modelValue
179
+ * @param value value of tje element to be checked
180
+ */
181
+ isSelected(value) {
182
+ const existing = this.modelValue.includes(value)
183
+ return existing
184
+ },
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
+ onSelectUpdate(event, value) {
193
+ if (this.$el && this.$el.id !== this.id) return //prevent event from firing on other input
194
+
195
+ const isChecked = event.target.checked
196
+ this.resetRetroStyle([this.retro, this.messageAccessibility])
197
+ let updatedValue = [...this.modelValue]
198
+
199
+ if (isChecked) {
200
+ const existing = updatedValue.includes(value)
201
+ if (!existing) updatedValue.push(value)
202
+ } else updatedValue = updatedValue.filter((v) => v !== value)
203
+
204
+ this.$emit('update:modelValue', updatedValue)
205
+ },
206
+ /**
207
+ * @description Component validation method to validate the user input against the solution
208
+ * can handle logic of Css style to apply (correct/wrong Answer) and return the result
209
+ * @return {Object} result
210
+ */
211
+ validateAnswer() {
212
+ // Validate the user answer
213
+ //Created a custom validated object for inputData
214
+ let mappedResults
215
+ if (this.solution != null) {
216
+ mappedResults = this.inputData.map(
217
+ (a) =>
218
+ (a = {
219
+ ...a,
220
+ correct: this.solution.includes(a.id)
221
+ })
222
+ )
223
+ } else {
224
+ mappedResults = this.inputData.map(
225
+ (a) =>
226
+ (a = {
227
+ ...a,
228
+ correct: null
229
+ })
230
+ )
231
+ }
232
+
233
+ let { classRetro, mesA11y } = this.addRetroStyle(
234
+ this.solution,
235
+ mappedResults,
236
+ this.inputData.length
237
+ )
238
+
239
+ this.retro = classRetro
240
+ this.messageAccessibility = mesA11y
241
+
242
+ //filer mapped to return a customized object of the user selection
243
+ this.result = mappedResults
244
+ .filter((a) => this.inputsValue.includes(a.value))
245
+ .map((a) => {
246
+ const { id, value, correct } = a
247
+ return { id, selected: value, correct }
248
+ })
249
+
250
+ let retro = this.retroType(this.solution, this.result)
251
+
252
+ let cAns
253
+ if (this.solution != null) cAns = this.computeResult(this.result)
254
+ else cAns = false
255
+
256
+ //Object to return validation to parent
257
+ return {
258
+ userAnswer: this.result,
259
+ correctAnswer: cAns,
260
+ retroType: retro
261
+ }
262
+ },
263
+ /**
264
+ * @description - compute the correct elements in user response
265
+ * compare with the solution and return wether user succeeded or failed
266
+ * @param {Object} result - user responses
267
+ * @retuns boolean
268
+ */
269
+ computeResult(result) {
270
+ const res = this.result.filter((el) => el.correct)
271
+
272
+ return (
273
+ res.length == this.solution.length &&
274
+ this.solution.length == this.result.length
275
+ )
276
+ }
277
+ }
278
+ }
279
+ </script>
280
+ <style lang="scss">
281
+ fieldset {
282
+ border: inherit;
283
+ }
284
+
285
+ .custom-control-input:focus ~ .custom-control-label::before {
286
+ border: inherit;
287
+ }
288
+
289
+ .custom-control-input:focus ~ .custom-control-label::before {
290
+ box-shadow: inherit;
291
+ -webkit-box-shadow: inherit;
292
+ }
293
+
294
+ fieldset {
295
+ border: inherit;
296
+ }
297
+
298
+ .custom-checkbox {
299
+ width: 100%;
300
+ height: 100%;
301
+ padding-left: 0;
302
+
303
+ input {
304
+ width: 100%;
305
+ height: 100%;
306
+ }
307
+
308
+ label {
309
+ width: 100%;
310
+ height: 100%;
311
+
312
+ &:after,
313
+ &:before {
314
+ border: inherit;
315
+ top: 0px;
316
+ left: 0px;
317
+ height: 0;
318
+ width: 0;
319
+ background-color: inherit;
320
+ border: inherit;
321
+ }
322
+ }
323
+ }
324
+ </style>
@@ -0,0 +1,295 @@
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
+ div.texteatrou {
256
+ display: inline !important;
257
+ .cnt-input {
258
+ display: inline;
259
+
260
+ .v-input {
261
+ display: inline-block !important;
262
+
263
+ .v-input__control,
264
+ .v-field {
265
+ width: 240px !important;
266
+ grid-area: inherit !important;
267
+
268
+ .v-field__field {
269
+ height: 25px !important;
270
+ padding: 0 !important;
271
+ min-height: inherit !important;
272
+
273
+ .v-field__input {
274
+ padding-top: 0 !important;
275
+ padding-bottom: 0 !important;
276
+ min-height: inherit !important;
277
+
278
+ .v-select__selection {
279
+ min-height: inherit !important;
280
+ }
281
+ }
282
+ }
283
+
284
+ .v-field__append-inner {
285
+ margin-right: 6px;
286
+ }
287
+ }
288
+
289
+ .v-input__details {
290
+ display: none;
291
+ }
292
+ }
293
+ }
294
+ }
295
+ </style>