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

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 (103) hide show
  1. package/.editorconfig +33 -33
  2. package/.eslintignore +29 -29
  3. package/.eslintrc.cjs +81 -81
  4. package/CHANGELOG +364 -364
  5. package/README.md +71 -71
  6. package/bk.scss +117 -117
  7. package/package.json +61 -47
  8. package/src/$locales/en.json +143 -193
  9. package/src/$locales/fr.json +105 -194
  10. package/src/assets/data/onboardingMessages.json +47 -47
  11. package/src/components/AppBase.vue +1054 -1049
  12. package/src/components/AppBaseButton.vue +87 -91
  13. package/src/components/AppBaseErrorDisplay.vue +438 -428
  14. package/src/components/AppBaseFlipCard.vue +84 -83
  15. package/src/components/AppBaseModule.vue +1673 -1666
  16. package/src/components/AppBasePage.vue +779 -324
  17. package/src/components/AppBasePopover.vue +41 -0
  18. package/src/components/AppCompAudio.vue +234 -266
  19. package/src/components/AppCompBranchButtons.vue +552 -571
  20. package/src/components/AppCompButtonProgress.vue +126 -132
  21. package/src/components/AppCompCarousel.vue +298 -196
  22. package/src/components/{AppCompInputCheckBox.vue → AppCompInputCheckBoxNext.vue} +195 -233
  23. package/src/components/AppCompInputDropdownNext.vue +159 -0
  24. package/src/components/{AppCompInputRadio.vue → AppCompInputRadioNext.vue} +152 -162
  25. package/src/components/{AppCompInputTextBox.vue → AppCompInputTextNext.vue} +106 -91
  26. package/src/components/AppCompInputTextTableNext.vue +141 -0
  27. package/src/components/AppCompInputTextToFillDropdownNext.vue +230 -0
  28. package/src/components/{AppCompInputTextToFillText.vue → AppCompInputTextToFillNext.vue} +171 -164
  29. package/src/components/AppCompJauge.vue +74 -67
  30. package/src/components/AppCompMenu.vue +413 -402
  31. package/src/components/AppCompMenuItem.vue +228 -191
  32. package/src/components/AppCompNavigation.vue +960 -945
  33. package/src/components/AppCompNoteCall.vue +133 -141
  34. package/src/components/AppCompNoteCredit.vue +292 -267
  35. package/src/components/AppCompPlayBar.vue +1218 -1271
  36. package/src/components/AppCompPlayBarNext.vue +2052 -0
  37. package/src/components/AppCompPlayBarProgress.vue +82 -73
  38. package/src/components/AppCompPopUpNext.vue +503 -0
  39. package/src/components/{AppCompQuiz.vue → AppCompQuizNext.vue} +2904 -2975
  40. package/src/components/AppCompQuizRecall.vue +276 -277
  41. package/src/components/{AppCompSVG.vue → AppCompSVGNext.vue} +347 -335
  42. package/src/components/AppCompSettingsMenu.vue +172 -169
  43. package/src/components/AppCompTableOfContent.vue +387 -385
  44. package/src/components/AppCompTranscript.vue +24 -19
  45. package/src/components/AppCompVideoPlayer.vue +368 -380
  46. package/src/components/AppCompViewDisplay.vue +6 -6
  47. package/src/components/BaseModule.vue +72 -71
  48. package/src/composables/useQuiz.js +206 -0
  49. package/src/externalComps/ModuleView.vue +22 -0
  50. package/src/externalComps/SummaryView.vue +91 -0
  51. package/src/main.js +272 -263
  52. package/src/mixins/$mediaMixins.js +819 -827
  53. package/src/mixins/timerMixin.js +155 -155
  54. package/src/module/stores/appStore.js +893 -0
  55. package/src/module/xapi/ADL.js +376 -376
  56. package/src/module/xapi/Crypto/Hasher.js +241 -241
  57. package/src/module/xapi/Crypto/WordArray.js +278 -278
  58. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  59. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
  60. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  61. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  62. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  63. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  64. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  65. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  66. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  67. package/src/module/xapi/Crypto/index.js +53 -53
  68. package/src/module/xapi/Statement/activity.js +47 -47
  69. package/src/module/xapi/Statement/agent.js +55 -55
  70. package/src/module/xapi/Statement/group.js +26 -26
  71. package/src/module/xapi/Statement/index.js +259 -259
  72. package/src/module/xapi/Statement/statement.js +253 -253
  73. package/src/module/xapi/Statement/statementRef.js +23 -23
  74. package/src/module/xapi/Statement/substatement.js +22 -22
  75. package/src/module/xapi/Statement/verb.js +36 -36
  76. package/src/module/xapi/activitytypes.js +17 -17
  77. package/src/module/xapi/launch.js +157 -157
  78. package/src/module/xapi/utils.js +167 -167
  79. package/src/module/xapi/verbs.js +294 -294
  80. package/src/module/xapi/wrapper.js +1963 -1963
  81. package/src/module/xapi/xapiStatement.js +444 -444
  82. package/src/plugins/bus.js +8 -3
  83. package/src/plugins/gsap.js +14 -17
  84. package/src/plugins/helper.js +308 -294
  85. package/src/plugins/i18n.js +44 -44
  86. package/src/plugins/idb.js +219 -212
  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 -21
  91. package/src/router/index.js +43 -40
  92. package/src/router/routes.js +312 -317
  93. package/src/shared/generalfuncs.js +210 -195
  94. package/src/shared/validators.js +1069 -959
  95. package/vite.config.js +27 -0
  96. package/src/components/AppCompInputDropdown.vue +0 -182
  97. package/src/components/AppCompInputTextTable.vue +0 -158
  98. package/src/components/AppCompInputTextToFillDropdown.vue +0 -257
  99. package/src/components/AppCompPopUp.vue +0 -583
  100. package/src/components/AppCompPopover.vue +0 -27
  101. package/src/mixins/$pageMixins.js +0 -415
  102. package/src/mixins/$quizMixins.js +0 -442
  103. package/src/module/store.js +0 -1014
@@ -1,277 +1,276 @@
1
- <!--
2
- @ Description: This component is used to display a quiz and its answer from a previous page if it has been completed by the user. The only quiz type supported is open answer (textarea) and the quiz must be in the same lesson.
3
- @ What it does: Retrieve the quizData specific to an activity ID and pageID. Then, retrieve the answers previously saved by the user to this quiz. After, create an html element including title and conditional content. If the answer have been previously saved, a specific hypertext, the question and the answer (disabled textarea) are displayed. If the answer have not been saved, another hypertext is displayed.
4
- -->
5
-
6
- <template>
7
- <section class="quizRecall">
8
- <!--Optionnal title, out of quiz-answer-conditionning, default tag H4, but can be change by user-->
9
- <component
10
- :is="quizRecall.titletag"
11
- v-if="quizRecall.title"
12
- class="quizRecall-title"
13
- >
14
- {{ quizRecall.title }}
15
- </component>
16
- <!--Quiz answer conditionning-->
17
- <template v-if="quizRecall.done == true">
18
- <div
19
- v-if="quizRecall.hypertext_done"
20
- class="quizRecall-text-done"
21
- v-html="quizRecall.hypertext_done"
22
- ></div>
23
- <div class="quizRecall-ennonce" v-html="quizRecall.ennonce"></div>
24
- <textarea
25
- v-model="quizRecall.answer"
26
- disabled
27
- class="form-control"
28
- ></textarea>
29
- </template>
30
- <template v-if="quizRecall.done == false">
31
- <div
32
- v-if="quizRecall.hypertext_undone"
33
- class="quizRecall-text-undone"
34
- v-html="quizRecall.hypertext_undone"
35
- ></div>
36
- </template>
37
- </section>
38
- </template>
39
-
40
- <script>
41
- //Recall mixins has the necessary datas and functions to give back quizRecall statu
42
- import { mapGetters } from 'vuex'
43
- export default {
44
- name: 'AppCompQuizRecall',
45
- props: {
46
- quizRecallData: { type: Object, required: true } //{activityId,pageId,hypertext_done,hypertext_undone,title, titletag}
47
- },
48
- data() {
49
- return {
50
- quizRecall: {
51
- done: false,
52
- answer: '',
53
- ennonce: '',
54
- title: '',
55
- titletag: 'h4',
56
- hypertext_done: `<p>${this.$t(
57
- 'message.recall_done'
58
- )}</p>` /*String traduite par défaut*/,
59
- hypertext_undone: `<p>${this.$t(
60
- 'message.recall_undone'
61
- )}</p>` /*String traduite par défaut*/
62
- },
63
- quizData: null
64
- }
65
- },
66
- computed: {
67
- ...mapGetters(['getAllCompleted', 'getUserInteraction', 'getPageData'])
68
- },
69
- watch: {
70
- //Change quizRecall when userData is changed (it is where answer are saved)
71
- getUserInteraction(newUserData, oldUserData) {
72
- if (this.quizRecallData && this.quizData) {
73
- this.getQuizRecallAnswer(this.quizRecallData, this.quizData)
74
- } else {
75
- this.quizRecall.done == false
76
- }
77
- }
78
- },
79
- mounted() {},
80
- created() {
81
- //Validate quizRecall data
82
- //(no validation to the quiz, only to the new datas)
83
- this.validateQuizRecallData(this.quizRecallData)
84
-
85
- //Get quizData and validate the quiz type
86
- if (this.quizRecallData.activityId && this.quizRecallData.pageId) {
87
- this.getQuizData(
88
- this.quizRecallData.activityId,
89
- this.quizRecallData.pageId
90
- )
91
- }
92
-
93
- //Get quizRecall answer
94
- if (this.quizRecallData && this.quizData) {
95
- this.getQuizRecallAnswer(this.quizRecallData, this.quizData)
96
- } else {
97
- this.quizRecall.done == false
98
- }
99
- },
100
- methods: {
101
- /**
102
- * @description Finds a reponse_ouverte quiz data with specified ID
103
- * @param {Object} searchObject Object that will be iterated over to find the quiz data (The page "data" object)
104
- * @param {String} quizID ID of the quiz we are looking for
105
- */
106
- findQuizdataObject(searchObject, quizID) {
107
- for (let property in searchObject) {
108
- // Check if the current property is an object and has the required properties
109
- if (
110
- typeof searchObject[property] === 'object' &&
111
- searchObject[property] !== null
112
- ) {
113
- if (
114
- searchObject[property].id === quizID &&
115
- searchObject[property].type_question === 'reponse_ouverte'
116
- ) {
117
- return searchObject[property] // Valid Quiz data found
118
- }
119
- }
120
- }
121
-
122
- // No reponse_ouverte quiz data with specified ID was found
123
- return null
124
- },
125
- //Get datas from the original open answer quiz
126
- getQuizData(activityId, pageId) {
127
- if (pageId && activityId) {
128
- let pageData = this.getPageData(activityId, pageId)
129
- if (pageData && pageData.content) {
130
- this.quizData = this.findQuizdataObject(
131
- pageData.content,
132
- this.quizRecallData.quizId
133
- )
134
- //Warn that the specified quiz could not be found
135
- if (this.quizData === null) {
136
- console.warn(
137
- `%c WARNING!>>> Quiz Recall: Unable to find a quiz with type_question 'reponse_ouverte' and id '${this.quizRecallData.quizId}' in ${pageId} of ${activityId}`,
138
- 'background: orange; color: white; display: block; margin:5px;'
139
- )
140
- }
141
- } else {
142
- this.quizRecall.done == false
143
- console.warn(
144
- `%c WARNING!>>> AppCompQuizRecall : QuizData ActivityID and PageID combinaison is invalid.`,
145
- 'background: orange; color: white; display: block; margin:5px;'
146
- )
147
- }
148
- } else {
149
- this.quizRecall.done == false
150
- }
151
- },
152
- //Get datas from quizRecallData and userData and add them to quizRecall object
153
- getQuizRecallAnswer(quizRecallData, quizData) {
154
- //Get userData
155
- let userData = this.getUserInteraction
156
- //Get quizId
157
- let quizId = quizData.id
158
- //Get activityId
159
- let activityId = quizRecallData.activityId
160
- //Get pageId
161
- let pageId = quizRecallData.pageId
162
- //Add hypertext_done and undone to quizRecall
163
- if (quizRecallData.hypertext_done) {
164
- this.quizRecall.hypertext_done = quizRecallData.hypertext_done
165
- }
166
- if (quizRecallData.hypertext_undone) {
167
- this.quizRecall.hypertext_undone = quizRecallData.hypertext_undone
168
- }
169
- //Add the title if it exists
170
- if (quizRecallData.title) {
171
- this.quizRecall.title = quizRecallData.title
172
- //Modify le titletag
173
- if (quizRecallData.titletag) {
174
- let validator = this.validateTitleTag(this.quizRecallData.titletag)
175
- if (validator) {
176
- this.quizRecall.titletag = this.quizRecallData.titletag
177
- }
178
- }
179
- }
180
-
181
- //If quiz answer exists in userData, quizRecall done is true and add the quiz answer to quizRecall
182
- if (
183
- userData &&
184
- userData[activityId] &&
185
- userData[activityId][pageId] &&
186
- userData[activityId][pageId].userInteraction &&
187
- userData[activityId][pageId].userInteraction.quizAnswers &&
188
- userData[activityId][pageId].userInteraction.quizAnswers[quizId]
189
- ) {
190
- this.quizRecall.done = true
191
- this.quizRecall.answer =
192
- userData[activityId][pageId].userInteraction.quizAnswers[quizId]
193
- this.quizRecall.ennonce = quizData.ennonce
194
- } else {
195
- //If the quiz answer doesn't exist
196
- this.quizRecall.done = false
197
- }
198
- },
199
-
200
- //Validate quizRecallData
201
- /*Validate if the required properties are present in the object and that there is not invalid properties */
202
- validateQuizRecallData(value) {
203
- let requiredProperties = [
204
- 'quizId',
205
- 'activityId',
206
- 'pageId',
207
- 'hypertext_done',
208
- 'hypertext_undone'
209
- ]
210
- let optionalProperties = ['title', 'titletag']
211
- let allProperties = requiredProperties.concat(optionalProperties)
212
-
213
- //Verify if the properties are valid
214
- let recallDataProperties = Object.keys(value)
215
- let wrongProperties = []
216
- let missingRequired = []
217
-
218
- //Get all the invalids properties from recallQuizData
219
- /*Add element from target array that are NOT in arr to the wrongArray*/
220
- let checkerWrong = (arr, target, wrongArray) =>
221
- target.every((v) => {
222
- if (arr.includes(v)) {
223
- return true
224
- } else {
225
- wrongArray.push(v)
226
- return true
227
- }
228
- })
229
- //Get all the required properties that are missing from recallQuizData
230
- /*Add element from the arr that are NOT in target arr to the missingArray*/
231
-
232
- let checkerMissing = (arr, target, missingArray) =>
233
- arr.every((v) => {
234
- if (target.includes(v)) {
235
- return true
236
- } else {
237
- missingArray.push(v)
238
- return true
239
- }
240
- })
241
-
242
- checkerWrong(allProperties, recallDataProperties, wrongProperties)
243
- checkerMissing(requiredProperties, recallDataProperties, missingRequired)
244
-
245
- //Validate if all properties in quizRecallData are valid
246
- if (wrongProperties.length > 0) {
247
- console.warn(
248
- `%c WARNING!>>> AppCompQuizRecall : QuizRecallData ${wrongProperties} invalid. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
249
- 'background: orange; color: white; display: block; margin:5px;'
250
- )
251
- }
252
- //Validate if all required properties are present in quizRecallData
253
- if (missingRequired.length > 0) {
254
- console.warn(
255
- `%c WARNING!>>> AppCompQuizRecall : QuizRecallData missing required ${missingRequired} property. Required properties: activityId and pageId. Optional properties: title, titletag, hypertext_done and hypertext_undone.`,
256
- 'background: orange; color: white; display: block; margin:5px;'
257
- )
258
- }
259
- },
260
- /*Get a title tag (string). Return true if the tag is valid and false is it's not*/
261
-
262
- validateTitleTag(value) {
263
- let tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span']
264
- let lowerValue = value.toLowerCase()
265
- if (tags && value && tags.find((element) => element == lowerValue))
266
- return true
267
- else {
268
- console.warn(
269
- '%c WARNING!>>> recallMixins: Your quizRecallData titletag is not valid. You can use h1,h2,h3,h4,h5,h6,p,or span',
270
- 'background: orange; color: white; display: block; margin:5px;'
271
- )
272
- return false
273
- }
274
- }
275
- }
276
- }
277
- </script>
1
+ <!--
2
+ @ Description: This component is used to display a quiz and its answer from a previous page if it has been completed by the user. The only quiz type supported is open answer (textarea) and the quiz must be in the same lesson.
3
+ @ What it does: Retrieve the quizData specific to an activity ID and pageID. Then, retrieve the answers previously saved by the user to this quiz. After, create an html element including title and conditional content. If the answer have been previously saved, a specific hypertext, the question and the answer (disabled textarea) are displayed. If the answer have not been saved, another hypertext is displayed.
4
+ @How to use: in a page call <app-comp-quiz-recall :quiz-recall-data="defineDQuizRecallData">
5
+ ** where "defineDQuizRecallData" refers to data object of quiz to pass to component
6
+ ** data object should containt following attributes: quizId,activityId,pageId,hypertext_done',hypertext_undone,title,titletag
7
+ -->
8
+ <template>
9
+ <section class="quizRecall">
10
+ <!--Optionnal title, out of quiz-answer-conditionning, default tag H4, but can be change by user-->
11
+ <component
12
+ :is="quizRecall.titletag"
13
+ v-if="quizRecall.title"
14
+ class="quizRecall-title"
15
+ >
16
+ {{ quizRecall.title }}
17
+ </component>
18
+ <!--Quiz answer conditionning-->
19
+ <template v-if="quizRecall.done == true">
20
+ <div
21
+ v-if="quizRecall.hypertext_done"
22
+ class="quizRecall-text-done"
23
+ v-html="quizRecall.hypertext_done"
24
+ ></div>
25
+ <div class="quizRecall-ennonce" v-html="quizRecall.ennonce"></div>
26
+ <textarea
27
+ v-model="quizRecall.answer"
28
+ disabled
29
+ class="form-control"
30
+ ></textarea>
31
+ </template>
32
+ <template v-if="quizRecall.done == false">
33
+ <div
34
+ v-if="quizRecall.hypertext_undone"
35
+ class="quizRecall-text-undone"
36
+ v-html="quizRecall.hypertext_undone"
37
+ ></div>
38
+ </template>
39
+ </section>
40
+ </template>
41
+
42
+ <script>
43
+ //Recall mixins has the necessary datas and functions to give back quizRecall statu
44
+ import { mapState } from 'pinia'
45
+ import { useAppStore } from '../module/stores/appStore'
46
+
47
+ export default {
48
+ name: 'AppCompQuizRecall',
49
+ props: {
50
+ quizRecallData: { type: Object, required: true } //{activityId,pageId,hypertext_done,hypertext_undone,title, titletag}
51
+ },
52
+ data() {
53
+ return {
54
+ quizRecall: {
55
+ done: false,
56
+ answer: '',
57
+ ennonce: '',
58
+ title: '',
59
+ titletag: 'h4',
60
+ hypertext_done: `<p>${this.$t('message.recall_done')}</p>` /*String traduite par défaut*/,
61
+ hypertext_undone: `<p>${this.$t(
62
+ 'message.recall_undone'
63
+ )}</p>` /*String traduite par défaut*/
64
+ },
65
+ quizData: null
66
+ }
67
+ },
68
+ computed: {
69
+ ...mapState(useAppStore, [
70
+ 'getAllCompleted',
71
+ 'getUserInteraction',
72
+ 'getPageInteraction',
73
+ 'getPageData'
74
+ ])
75
+ },
76
+ created() {
77
+ //Validate quizRecall data
78
+ //(no validation to the quiz, only to the new datas)
79
+ this.validateQuizRecallData(this.quizRecallData)
80
+ const { activityId, pageId } = this.quizRecallData
81
+ //Get quizData and validate the quiz type
82
+ if (activityId && pageId) {
83
+ this.getQuizData(activityId, pageId)
84
+ }
85
+
86
+ //Get quizRecall answer
87
+ if (this.quizRecallData && this.quizData) {
88
+ this.getQuizRecallAnswer(this.quizRecallData, this.quizData)
89
+ } else {
90
+ this.quizRecall.done == false
91
+ }
92
+ },
93
+ methods: {
94
+ /**
95
+ * @description Finds a reponse_ouverte quiz data with specified ID
96
+ * @param {Object} searchObject Object that will be iterated over to find the quiz data (The page "data" object)
97
+ * @param {String} quizID ID of the quiz we are looking for
98
+ */
99
+ findQuizdataObject(searchObject, quizID) {
100
+ for (let property in searchObject) {
101
+ // Should only check for Object or Array property
102
+ if (
103
+ searchObject[property].constructor !== Array &&
104
+ searchObject[property].constructor !== Object
105
+ )
106
+ continue
107
+
108
+ // Convert if it not an Array but an Objet
109
+ const searchArray =
110
+ searchObject[property].constructor === Object
111
+ ? [searchObject[property]]
112
+ : searchObject[property]
113
+
114
+ //Only Search for quiz:
115
+ //Search Array is a list of quiz if one of its element has at least the property 'type_question'
116
+ return searchArray[0]['type_question']
117
+ ? searchArray.find(
118
+ (e) => e.id === quizID && e.type_question === 'reponse_ouverte'
119
+ )
120
+ : null
121
+ }
122
+ },
123
+ //Get datas from the original open answer quiz
124
+ getQuizData(activityId, pageId) {
125
+ if (pageId && activityId) {
126
+ let pageData = this.getPageData(activityId, pageId)
127
+ if (pageData) {
128
+ this.quizData = this.findQuizdataObject(
129
+ pageData,
130
+ this.quizRecallData.quizId
131
+ )
132
+
133
+ //Warn that the specified quiz could not be found
134
+ if (!this.quizData) {
135
+ console.warn(
136
+ `%c WARNING!>>> Quiz Recall: Unable to find a quiz with type_question 'reponse_ouverte' and id '${this.quizRecallData.quizId}' in ${pageId} of ${activityId}`,
137
+ 'background: orange; color: white; display: block; margin:5px;'
138
+ )
139
+ }
140
+ } else {
141
+ this.quizRecall.done == false
142
+ console.warn(
143
+ `%c WARNING!>>> AppCompQuizRecall : QuizData ActivityID and PageID combinaison is invalid.`,
144
+ 'background: orange; color: white; display: block; margin:5px;'
145
+ )
146
+ }
147
+ } else {
148
+ this.quizRecall.done == false
149
+ }
150
+ },
151
+ //Get datas from quizRecallData and userData and add them to quizRecall object
152
+ getQuizRecallAnswer() {
153
+ //Get userData
154
+ const {
155
+ activityId,
156
+ pageId,
157
+ quizId,
158
+ hypertext_done,
159
+ hypertext_undone,
160
+ title,
161
+ titletag
162
+ } = this.quizRecallData
163
+
164
+ let userData = this.getPageInteraction(activityId, pageId)
165
+
166
+ //Add hypertext_done and undone to quizRecall
167
+ if (hypertext_done) {
168
+ this.quizRecall.hypertext_done = hypertext_done
169
+ }
170
+ if (hypertext_undone) {
171
+ this.quizRecall.hypertext_undone = hypertext_undone
172
+ }
173
+ //Add the title if it exists
174
+ if (title) {
175
+ this.quizRecall.title = title
176
+ //Modify le titletag
177
+ if (titletag) {
178
+ let validator = this.validateTitleTag(titletag)
179
+ if (validator) {
180
+ this.quizRecall.titletag = titletag
181
+ }
182
+ }
183
+ }
184
+
185
+ //If quiz answer exists in userData, quizRecall done is true and add the quiz answer to quizRecall
186
+ if (!userData || !userData.userInteraction)
187
+ return (this.quizRecall.done = false)
188
+
189
+ const { quizAnswers } = userData.userInteraction
190
+
191
+ if (!quizAnswers || !quizAnswers[quizId])
192
+ return (this.quizRecall.done = false)
193
+
194
+ this.quizRecall.done = true
195
+ this.quizRecall.answer = quizAnswers[quizId].value
196
+ this.quizRecall.ennonce = this.quizData.ennonce
197
+ },
198
+
199
+ //Validate quizRecallData
200
+ /*Validate if the required properties are present in the object and that there is not invalid properties */
201
+ validateQuizRecallData(value) {
202
+ let requiredProperties = [
203
+ 'quizId',
204
+ 'activityId',
205
+ 'pageId',
206
+ 'hypertext_done',
207
+ 'hypertext_undone'
208
+ ]
209
+ let optionalProperties = ['title', 'titletag']
210
+ let allProperties = requiredProperties.concat(optionalProperties)
211
+
212
+ //Verify if the properties are valid
213
+ let recallDataProperties = Object.keys(value)
214
+ let wrongProperties = []
215
+ let missingRequired = []
216
+
217
+ //Get all the invalids properties from recallQuizData
218
+ /*Add element from target array that are NOT in arr to the wrongArray*/
219
+ let checkerWrong = (arr, target, wrongArray) =>
220
+ target.every((v) => {
221
+ if (arr.includes(v)) {
222
+ return true
223
+ } else {
224
+ wrongArray.push(v)
225
+ return true
226
+ }
227
+ })
228
+ //Get all the required properties that are missing from recallQuizData
229
+ /*Add element from the arr that are NOT in target arr to the missingArray*/
230
+
231
+ let checkerMissing = (arr, target, missingArray) =>
232
+ arr.every((v) => {
233
+ if (target.includes(v)) {
234
+ return true
235
+ } else {
236
+ missingArray.push(v)
237
+ return true
238
+ }
239
+ })
240
+
241
+ checkerWrong(allProperties, recallDataProperties, wrongProperties)
242
+ checkerMissing(requiredProperties, recallDataProperties, missingRequired)
243
+
244
+ //Validate if all properties in quizRecallData are valid
245
+ if (wrongProperties.length > 0) {
246
+ console.warn(
247
+ `%c WARNING!>>> AppCompQuizRecall : QuizRecallData ${wrongProperties} invalid. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
248
+ 'background: orange; color: white; display: block; margin:5px;'
249
+ )
250
+ }
251
+ //Validate if all required properties are present in quizRecallData
252
+ if (missingRequired.length > 0) {
253
+ console.warn(
254
+ `%c WARNING!>>> AppCompQuizRecall : QuizRecallData missing required ${missingRequired} property. Required properties: activityId and pageId. Optional properties: title, titletag, hypertext_done and hypertext_undone.`,
255
+ 'background: orange; color: white; display: block; margin:5px;'
256
+ )
257
+ }
258
+ },
259
+ /*Get a title tag (string). Return true if the tag is valid and false is it's not*/
260
+
261
+ validateTitleTag(value) {
262
+ let tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span']
263
+ let lowerValue = value.toLowerCase()
264
+ if (tags && value && tags.find((element) => element == lowerValue))
265
+ return true
266
+ else {
267
+ console.warn(
268
+ '%c WARNING!>>> recallMixins: Your quizRecallData titletag is not valid. You can use h1,h2,h3,h4,h5,h6,p,or span',
269
+ 'background: orange; color: white; display: block; margin:5px;'
270
+ )
271
+ return false
272
+ }
273
+ }
274
+ }
275
+ }
276
+ </script>