fcad-core-dragon 2.1.1 → 2.2.0-beta.1

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 (164) hide show
  1. package/.editorconfig +7 -7
  2. package/.gitlab-ci.yml +106 -0
  3. package/.prettierrc +11 -11
  4. package/.vscode/extensions.json +8 -8
  5. package/.vscode/settings.json +16 -16
  6. package/CHANGELOG +529 -520
  7. package/README.md +57 -57
  8. package/artifacts/playwright-report/index.html +85 -0
  9. package/documentation/.vitepress/config.js +114 -114
  10. package/documentation/api-examples.md +49 -49
  11. package/documentation/composants/app-base-button.md +58 -58
  12. package/documentation/composants/app-base-error-display.md +59 -59
  13. package/documentation/composants/app-base-popover.md +68 -68
  14. package/documentation/composants/app-comp-audio.md +75 -75
  15. package/documentation/composants/app-comp-branch-buttons.md +111 -111
  16. package/documentation/composants/app-comp-button-progress.md +53 -53
  17. package/documentation/composants/app-comp-carousel.md +53 -53
  18. package/documentation/composants/app-comp-container.md +53 -53
  19. package/documentation/composants/app-comp-input-checkbox-next.md +42 -42
  20. package/documentation/composants/app-comp-input-dropdown-next.md +34 -34
  21. package/documentation/composants/app-comp-input-radio-next.md +39 -39
  22. package/documentation/composants/app-comp-input-text-next.md +35 -35
  23. package/documentation/composants/app-comp-input-text-table-next.md +34 -34
  24. package/documentation/composants/app-comp-input-text-to-fill-dropdown-next.md +53 -53
  25. package/documentation/composants/app-comp-input-text-to-fill-next.md +31 -31
  26. package/documentation/composants/app-comp-jauge.md +31 -31
  27. package/documentation/composants/app-comp-menu-item.md +55 -55
  28. package/documentation/composants/app-comp-menu.md +29 -29
  29. package/documentation/composants/app-comp-navigation.md +41 -41
  30. package/documentation/composants/app-comp-note-call.md +53 -53
  31. package/documentation/composants/app-comp-note-credit.md +53 -53
  32. package/documentation/composants/app-comp-play-bar-next.md +53 -53
  33. package/documentation/composants/app-comp-pop-up-next.md +93 -93
  34. package/documentation/composants/app-comp-quiz-next.md +235 -235
  35. package/documentation/composants/app-comp-quiz-recall.md +53 -53
  36. package/documentation/composants/app-comp-svg-next.md +53 -53
  37. package/documentation/composants/app-comp-table-of-content.md +50 -50
  38. package/documentation/composants/app-comp-video-player.md +82 -82
  39. package/documentation/composants.md +46 -46
  40. package/documentation/composants_critiques/ModelPageComposant.md +53 -53
  41. package/documentation/composants_critiques/app-base-module.md +43 -43
  42. package/documentation/composants_critiques/app-base-page.md +48 -48
  43. package/documentation/composants_critiques/app-base.md +311 -311
  44. package/documentation/composants_critiques/main.md +15 -15
  45. package/documentation/demarrage.md +50 -50
  46. package/documentation/deploiement.md +57 -57
  47. package/documentation/index.md +33 -33
  48. package/documentation/markdown-examples.md +85 -85
  49. package/documentation/public/vite.svg +14 -14
  50. package/documentation/public/vuejs.svg +1 -1
  51. package/documentation/public/vuetify.svg +5 -5
  52. package/eslint.config.js +60 -60
  53. package/package.json +69 -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 +862 -866
  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 +326 -323
  74. package/src/components/AppCompInputDropdownNx.vue +302 -299
  75. package/src/components/AppCompInputRadioNx.vue +288 -284
  76. package/src/components/AppCompInputTextNx.vue +154 -153
  77. package/src/components/AppCompInputTextTableNx.vue +205 -202
  78. package/src/components/AppCompInputTextToFillDropdownNx.vue +341 -340
  79. package/src/components/AppCompInputTextToFillNx.vue +293 -313
  80. package/src/components/AppCompJauge.vue +81 -81
  81. package/src/components/AppCompMenu.vue +6 -1
  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 +2288 -2288
  87. package/src/components/AppCompPopUpNext.vue +508 -504
  88. package/src/components/AppCompQuizNext.vue +515 -510
  89. package/src/components/AppCompQuizRecall.vue +365 -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 +378 -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 +506 -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 -17
  134. package/src/plugins/helper.js +355 -358
  135. package/src/plugins/i18n.js +29 -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/AppCompAudio.spec.js +134 -0
  149. package/tests/unit/AppCompCarousel.spec.js +54 -0
  150. package/tests/unit/AppCompInputCheckBoxNx.spec.js +59 -0
  151. package/tests/unit/AppCompInputDropdownNx.spec.js +51 -0
  152. package/tests/unit/AppCompInputRadioNx.spec.js +59 -0
  153. package/tests/unit/AppCompInputTextNx.spec.js +44 -0
  154. package/tests/unit/AppCompInputTextTableNx.spec.js +77 -0
  155. package/tests/unit/AppCompInputTextToFillDropdownNx.spec.js +60 -0
  156. package/tests/unit/AppCompInputTextToFillNx.spec.js +45 -0
  157. package/tests/unit/AppCompNoteCredit.spec.js +58 -0
  158. package/tests/unit/AppCompQuizNext.spec.js +112 -0
  159. package/tests/unit/AppCompVideoPlayer.spec.js +169 -0
  160. package/tests/unit/useQuiz.spec.js +72 -0
  161. package/{src/components/tests__ → tests/unit}/useTimer.spec.js +91 -91
  162. package/vitest.config.js +42 -19
  163. package/vitest.setup.js +96 -0
  164. package/src/components/AppBaseButton.test.js +0 -21
@@ -1,323 +1,326 @@
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">
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
- v-html="choixReponse.value"
40
- ></span>
41
- <span
42
- :id="`${id}_${choixReponse.id}-msg-erreur`"
43
- :key="`msg_chx_${id}_${choixReponse.id}`"
44
- class="sr-only"
45
- >
46
- {{ messageAccessibility[index] }}
47
- </span>
48
- </label>
49
- </div>
50
- </template>
51
- </fieldset>
52
- </div>
53
- </template>
54
- <script>
55
- import { useQuiz } from '../composables/useQuiz'
56
- import { validateObjType } from '../shared/validators'
57
- export default {
58
- name: 'AppCompInputCheckBoxNx',
59
- /* PROPS USED FOR PARENT TO COMMUNICATE DATA TO CHILD */
60
- props: {
61
- modelValue: {
62
- type: Array,
63
- default: () => []
64
- },
65
- inputData: {
66
- type: Array,
67
- default: () => []
68
- },
69
- solution: {
70
- type: Array,
71
- default: () => []
72
- },
73
- id: {
74
- type: String,
75
- default: ''
76
- }
77
- },
78
- emits: ['update:modelValue', 'enable-submit'],
79
- setup() {
80
- const { retroType, addRetroStyle, resetRetroStyle } = useQuiz()
81
-
82
- return { retroType, addRetroStyle, resetRetroStyle }
83
- },
84
- data() {
85
- return {
86
- quizInputDataValue: [],
87
- result: null,
88
- retro: [],
89
- messageAccessibility: [],
90
- selectedItems: []
91
- }
92
- },
93
- computed: {
94
- fieldsetLabel() {
95
- return `${this.$t('quizState.checkboxFieldset')} ${this.inputData.length} ${this.$t('quizState.options')}`
96
- },
97
- /* INTERNAL REACTIVE VALUE THAT BIND WITH MODELVALUE PROPS */
98
- inputsValue: {
99
- get() {
100
- return this.modelValue
101
- },
102
-
103
- set(newValue) {
104
- if (
105
- (this.$el && this.$el.id !== this.id) ||
106
- newValue.constructor !== Array
107
- )
108
- return
109
-
110
- this.$emit('update:modelValue', newValue)
111
- }
112
- },
113
- /**
114
- * internal reactive value that map the options to add SELECTED attribute on each option
115
- * this attribute value can be changed when user select the option
116
- */
117
- mappedOptions() {
118
- const options = this.inputData.map((op) => {
119
- const selectedItem = this.modelValue.find((i) => i.id === op.id)
120
- return {
121
- ...op,
122
- selected: selectedItem ? selectedItem.selected : false
123
- }
124
- })
125
-
126
- return options
127
- }
128
- },
129
- watch: {
130
- inputsValue: {
131
- handler(newVal) {
132
- this.$emit('enable-submit', newVal.length > 0)
133
- },
134
- deep: true,
135
- immediate: true
136
- }
137
- },
138
- created() {
139
- if (import.meta.env.DEV) {
140
- let errors = this.validateInputData()
141
-
142
- if (errors && errors.errorList.length)
143
- return this.$bus.$emit('input-error', { e: this.id, errors })
144
- }
145
-
146
- this.quizInputDataValue = this.inputData
147
- },
148
- mounted() {},
149
-
150
- methods: {
151
- /**
152
- * @description validate the raw data received by the component to render is view
153
- * @returns {Object} errors - errorList: to display in view and errorConsole, to be displayed in console
154
- */
155
- validateInputData() {
156
- let errors = null //array for errors dectected
157
- let stringType = ['id', 'value']
158
-
159
- if (!this.inputData.length) return errors
160
- for (let i = 0; i < this.inputData.length; i++) {
161
- errors = validateObjType(
162
- this.inputData[i],
163
- { stringType },
164
- null,
165
- `choix_reponse #${i + 1}`
166
- )
167
- const { errorList, errorInConsole } = errors
168
-
169
- if (errorList.length || errorInConsole.length) return errors
170
- }
171
-
172
- return errors
173
- },
174
-
175
- /**
176
- * @description inicate wether the element is checked or not.
177
- * Element is selected if in the modelValue
178
- * @param value value of tje element to be checked
179
- */
180
- isSelected(value) {
181
- const existing = this.modelValue.includes(value)
182
- return existing
183
- },
184
-
185
- /**
186
- * @description Method to force update of this.inputsValue.
187
- * this force the old value and new value of the input to be tracked by VUE.
188
- * @param newValue, the new value of the input
189
- * @param index index of the selected element
190
- */
191
- onSelectUpdate(event, value) {
192
- if (this.$el && this.$el.id !== this.id) return //prevent event from firing on other input
193
-
194
- const isChecked = event.target.checked
195
- this.resetRetroStyle([this.retro, this.messageAccessibility])
196
- let updatedValue = [...this.modelValue]
197
-
198
- if (isChecked) {
199
- const existing = updatedValue.includes(value)
200
- if (!existing) updatedValue.push(value)
201
- } else updatedValue = updatedValue.filter((v) => v !== value)
202
-
203
- this.$emit('update:modelValue', updatedValue)
204
- },
205
- /**
206
- * @description Component validation method to validate the user input against the solution
207
- * can handle logic of Css style to apply (correct/wrong Answer) and return the result
208
- * @return {Object} result
209
- */
210
- validateAnswer() {
211
- // Validate the user answer
212
- //Created a custom validated object for inputData
213
- let mappedResults
214
- if (this.solution != null) {
215
- mappedResults = this.inputData.map(
216
- (a) =>
217
- (a = {
218
- ...a,
219
- correct: this.solution.includes(a.id)
220
- })
221
- )
222
- } else {
223
- mappedResults = this.inputData.map(
224
- (a) =>
225
- (a = {
226
- ...a,
227
- correct: null
228
- })
229
- )
230
- }
231
-
232
- let { classRetro, mesA11y } = this.addRetroStyle(
233
- this.solution,
234
- mappedResults,
235
- this.inputData.length
236
- )
237
-
238
- this.retro = classRetro
239
- this.messageAccessibility = mesA11y
240
-
241
- //filer mapped to return a customized object of the user selection
242
- this.result = mappedResults
243
- .filter((a) => this.inputsValue.includes(a.value))
244
- .map((a) => {
245
- const { id, value, correct } = a
246
- return { id, selected: value, correct }
247
- })
248
-
249
- let retro = this.retroType(this.solution, this.result)
250
-
251
- let cAns
252
- if (this.solution != null) cAns = this.computeResult(this.result)
253
- else cAns = false
254
-
255
- //Object to return validation to parent
256
- return {
257
- userAnswer: this.result,
258
- correctAnswer: cAns,
259
- retroType: retro
260
- }
261
- },
262
- /**
263
- * @description - compute the correct elements in user response
264
- * compare with the solution and return wether user succeeded or failed
265
- * @param {Object} result - user responses
266
- * @retuns boolean
267
- */
268
- computeResult(result) {
269
- const res = this.result.filter((el) => el.correct)
270
-
271
- return (
272
- res.length == this.solution.length &&
273
- this.solution.length == this.result.length
274
- )
275
- }
276
- }
277
- }
278
- </script>
279
- <style lang="scss">
280
- fieldset {
281
- border: inherit;
282
- }
283
-
284
- .custom-control-input:focus ~ .custom-control-label::before {
285
- border: inherit;
286
- }
287
-
288
- .custom-control-input:focus ~ .custom-control-label::before {
289
- box-shadow: inherit;
290
- -webkit-box-shadow: inherit;
291
- }
292
-
293
- fieldset {
294
- border: inherit;
295
- }
296
-
297
- .custom-checkbox {
298
- width: 100%;
299
- height: 100%;
300
- padding-left: 0;
301
-
302
- input {
303
- width: 100%;
304
- height: 100%;
305
- }
306
-
307
- label {
308
- width: 100%;
309
- height: 100%;
310
-
311
- &:after,
312
- &:before {
313
- border: inherit;
314
- top: 0px;
315
- left: 0px;
316
- height: 0;
317
- width: 0;
318
- background-color: inherit;
319
- border: inherit;
320
- }
321
- }
322
- }
323
- </style>
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">
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
+ v-html="choixReponse.value"
40
+ ></span>
41
+ <span
42
+ :id="`${id}_${choixReponse.id}-msg-erreur`"
43
+ :key="`msg_chx_${id}_${choixReponse.id}`"
44
+ class="sr-only"
45
+ >
46
+ {{ messageAccessibility[index] }}
47
+ </span>
48
+ </label>
49
+ </div>
50
+ </template>
51
+ </fieldset>
52
+ </div>
53
+ </template>
54
+ <script>
55
+ import { useQuiz } from '../composables/useQuiz'
56
+ import { validateObjType } from '../shared/validators'
57
+ import { useI18n } from 'vue-i18n'
58
+
59
+ export default {
60
+ name: 'AppCompInputCheckBoxNx',
61
+ /* PROPS USED FOR PARENT TO COMMUNICATE DATA TO CHILD */
62
+ props: {
63
+ modelValue: {
64
+ type: Array,
65
+ default: () => []
66
+ },
67
+ inputData: {
68
+ type: Array,
69
+ default: () => []
70
+ },
71
+ solution: {
72
+ type: Array,
73
+ default: () => []
74
+ },
75
+ id: {
76
+ type: String,
77
+ default: ''
78
+ }
79
+ },
80
+ emits: ['update:modelValue', 'enable-submit'],
81
+ setup() {
82
+ const { t } = useI18n()
83
+ const { retroType, addRetroStyle, resetRetroStyle } = useQuiz()
84
+ return { retroType, addRetroStyle, resetRetroStyle, t }
85
+ },
86
+ data() {
87
+ return {
88
+ quizInputDataValue: [],
89
+ result: null,
90
+ retro: [],
91
+ messageAccessibility: [],
92
+ selectedItems: []
93
+ }
94
+ },
95
+ computed: {
96
+ fieldsetLabel() {
97
+ return `${this.$t('quizState.checkboxFieldset')} ${this.inputData.length} ${this.$t('quizState.options')}`
98
+ },
99
+ /* INTERNAL REACTIVE VALUE THAT BIND WITH MODELVALUE PROPS */
100
+ inputsValue: {
101
+ get() {
102
+ return this.modelValue
103
+ },
104
+
105
+ set(newValue) {
106
+ if (
107
+ (this.$el && this.$el.id !== this.id) ||
108
+ newValue.constructor !== Array
109
+ )
110
+ return
111
+
112
+ this.$emit('update:modelValue', newValue)
113
+ }
114
+ },
115
+ /**
116
+ * internal reactive value that map the options to add SELECTED attribute on each option
117
+ * this attribute value can be changed when user select the option
118
+ */
119
+ mappedOptions() {
120
+ const options = this.inputData.map((op) => {
121
+ const selectedItem = this.modelValue.find((i) => i.id === op.id)
122
+ return {
123
+ ...op,
124
+ selected: selectedItem ? selectedItem.selected : false
125
+ }
126
+ })
127
+
128
+ return options
129
+ }
130
+ },
131
+ watch: {
132
+ inputsValue: {
133
+ handler(newVal) {
134
+ this.$emit('enable-submit', newVal.length > 0)
135
+ },
136
+ deep: true,
137
+ immediate: true
138
+ }
139
+ },
140
+ created() {
141
+ if (import.meta.env.DEV) {
142
+ let errors = this.validateInputData()
143
+
144
+ if (errors && errors.errorList.length)
145
+ return this.$bus.$emit('input-error', { e: this.id, errors })
146
+ }
147
+
148
+ this.quizInputDataValue = this.inputData
149
+ },
150
+ mounted() {},
151
+
152
+ methods: {
153
+ /**
154
+ * @description validate the raw data received by the component to render is view
155
+ * @returns {Object} errors - errorList: to display in view and errorConsole, to be displayed in console
156
+ */
157
+ validateInputData() {
158
+ let errors = null //array for errors dectected
159
+ let stringType = ['id', 'value']
160
+
161
+ if (!this.inputData.length) return errors
162
+ for (let i = 0; i < this.inputData.length; i++) {
163
+ errors = validateObjType(
164
+ this.inputData[i],
165
+ { stringType },
166
+ null,
167
+ `choix_reponse #${i + 1}`
168
+ )
169
+ const { errorList, errorInConsole } = errors
170
+
171
+ if (!errorList || !errorInConsole) return null
172
+ return errors
173
+ }
174
+
175
+ return errors
176
+ },
177
+
178
+ /**
179
+ * @description inicate wether the element is checked or not.
180
+ * Element is selected if in the modelValue
181
+ * @param value value of tje element to be checked
182
+ */
183
+ isSelected(value) {
184
+ const existing = this.modelValue.includes(value)
185
+ return existing
186
+ },
187
+
188
+ /**
189
+ * @description Method to force update of this.inputsValue.
190
+ * this force the old value and new value of the input to be tracked by VUE.
191
+ * @param newValue, the new value of the input
192
+ * @param index index of the selected element
193
+ */
194
+ onSelectUpdate(event, value) {
195
+ if (this.$el && this.$el.id !== this.id) return //prevent event from firing on other input
196
+
197
+ const isChecked = event.target.checked
198
+ this.resetRetroStyle([this.retro, this.messageAccessibility])
199
+ let updatedValue = [...this.modelValue]
200
+
201
+ if (isChecked) {
202
+ const existing = updatedValue.includes(value)
203
+ if (!existing) updatedValue.push(value)
204
+ } else updatedValue = updatedValue.filter((v) => v !== value)
205
+
206
+ this.$emit('update:modelValue', updatedValue)
207
+ },
208
+ /**
209
+ * @description Component validation method to validate the user input against the solution
210
+ * can handle logic of Css style to apply (correct/wrong Answer) and return the result
211
+ * @return {Object} result
212
+ */
213
+ validateAnswer() {
214
+ // Validate the user answer
215
+ //Created a custom validated object for inputData
216
+ let mappedResults
217
+ if (this.solution != null) {
218
+ mappedResults = this.inputData.map(
219
+ (a) =>
220
+ (a = {
221
+ ...a,
222
+ correct: this.solution.includes(a.id)
223
+ })
224
+ )
225
+ } else {
226
+ mappedResults = this.inputData.map(
227
+ (a) =>
228
+ (a = {
229
+ ...a,
230
+ correct: null
231
+ })
232
+ )
233
+ }
234
+
235
+ let { classRetro, mesA11y } = this.addRetroStyle(
236
+ this.solution,
237
+ mappedResults,
238
+ this.inputData.length
239
+ )
240
+
241
+ this.retro = classRetro
242
+ this.messageAccessibility = mesA11y
243
+
244
+ //filer mapped to return a customized object of the user selection
245
+ this.result = mappedResults
246
+ .filter((a) => this.inputsValue.includes(a.value))
247
+ .map((a) => {
248
+ const { id, value, correct } = a
249
+ return { id, selected: value, correct }
250
+ })
251
+
252
+ let retro = this.retroType(this.solution, this.result)
253
+
254
+ let cAns
255
+ if (this.solution != null) cAns = this.computeResult(this.result)
256
+ else cAns = false
257
+
258
+ //Object to return validation to parent
259
+ return {
260
+ userAnswer: this.result,
261
+ correctAnswer: cAns,
262
+ retroType: retro
263
+ }
264
+ },
265
+ /**
266
+ * @description - compute the correct elements in user response
267
+ * compare with the solution and return wether user succeeded or failed
268
+ * @param {Object} result - user responses
269
+ * @retuns boolean
270
+ */
271
+ computeResult(result) {
272
+ const res = this.result.filter((el) => el.correct)
273
+
274
+ return (
275
+ res.length == this.solution.length &&
276
+ this.solution.length == this.result.length
277
+ )
278
+ }
279
+ }
280
+ }
281
+ </script>
282
+ <style lang="scss">
283
+ fieldset {
284
+ border: inherit;
285
+ }
286
+
287
+ .custom-control-input:focus ~ .custom-control-label::before {
288
+ border: inherit;
289
+ }
290
+
291
+ .custom-control-input:focus ~ .custom-control-label::before {
292
+ box-shadow: inherit;
293
+ -webkit-box-shadow: inherit;
294
+ }
295
+
296
+ fieldset {
297
+ border: inherit;
298
+ }
299
+
300
+ .custom-checkbox {
301
+ width: 100%;
302
+ height: 100%;
303
+ padding-left: 0;
304
+
305
+ input {
306
+ width: 100%;
307
+ height: 100%;
308
+ }
309
+
310
+ label {
311
+ width: 100%;
312
+ height: 100%;
313
+
314
+ &:after,
315
+ &:before {
316
+ border: inherit;
317
+ top: 0px;
318
+ left: 0px;
319
+ height: 0;
320
+ width: 0;
321
+ background-color: inherit;
322
+ border: inherit;
323
+ }
324
+ }
325
+ }
326
+ </style>