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

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 (95) hide show
  1. package/.editorconfig +33 -33
  2. package/.eslintignore +29 -29
  3. package/.eslintrc.cjs +81 -81
  4. package/CHANGELOG +373 -364
  5. package/README.md +71 -71
  6. package/bk.scss +117 -117
  7. package/package.json +61 -61
  8. package/src/$locales/en.json +143 -143
  9. package/src/$locales/fr.json +105 -105
  10. package/src/assets/data/onboardingMessages.json +47 -47
  11. package/src/components/AppBase.vue +1147 -1054
  12. package/src/components/AppBaseButton.vue +87 -87
  13. package/src/components/AppBaseErrorDisplay.vue +438 -438
  14. package/src/components/AppBaseFlipCard.vue +84 -84
  15. package/src/components/AppBaseModule.vue +1636 -1673
  16. package/src/components/AppBasePage.vue +779 -779
  17. package/src/components/AppBasePopover.vue +41 -41
  18. package/src/components/AppCompAudio.vue +234 -234
  19. package/src/components/AppCompBranchButtons.vue +552 -552
  20. package/src/components/AppCompButtonProgress.vue +126 -126
  21. package/src/components/AppCompCarousel.vue +298 -298
  22. package/src/components/AppCompInputCheckBoxNext.vue +195 -195
  23. package/src/components/AppCompInputDropdownNext.vue +159 -159
  24. package/src/components/AppCompInputRadioNext.vue +152 -152
  25. package/src/components/AppCompInputTextNext.vue +106 -106
  26. package/src/components/AppCompInputTextTableNext.vue +141 -141
  27. package/src/components/AppCompInputTextToFillDropdownNext.vue +230 -230
  28. package/src/components/AppCompInputTextToFillNext.vue +171 -171
  29. package/src/components/AppCompJauge.vue +74 -74
  30. package/src/components/AppCompMenu.vue +423 -413
  31. package/src/components/AppCompMenuItem.vue +228 -228
  32. package/src/components/AppCompNavigation.vue +959 -960
  33. package/src/components/AppCompNoteCall.vue +133 -133
  34. package/src/components/AppCompNoteCredit.vue +292 -292
  35. package/src/components/AppCompPlayBar.vue +1218 -1218
  36. package/src/components/AppCompPlayBarNext.vue +2052 -2052
  37. package/src/components/AppCompPlayBarProgress.vue +82 -82
  38. package/src/components/AppCompPopUpNext.vue +503 -503
  39. package/src/components/AppCompQuizNext.vue +2904 -2904
  40. package/src/components/AppCompQuizRecall.vue +276 -276
  41. package/src/components/AppCompSVGNext.vue +347 -347
  42. package/src/components/AppCompSettingsMenu.vue +172 -172
  43. package/src/components/AppCompTableOfContent.vue +387 -387
  44. package/src/components/AppCompTranscript.vue +24 -24
  45. package/src/components/AppCompVideoPlayer.vue +368 -368
  46. package/src/components/AppCompViewDisplay.vue +6 -6
  47. package/src/components/BaseModule.vue +72 -72
  48. package/src/composables/useQuiz.js +206 -206
  49. package/src/externalComps/ModuleView.vue +22 -22
  50. package/src/externalComps/SummaryView.vue +91 -91
  51. package/src/main.js +272 -272
  52. package/src/mixins/$mediaMixins.js +819 -819
  53. package/src/mixins/timerMixin.js +155 -155
  54. package/src/module/stores/appStore.js +901 -893
  55. package/src/module/xapi/ADL.js +380 -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 -8
  83. package/src/plugins/gsap.js +14 -14
  84. package/src/plugins/helper.js +314 -308
  85. package/src/plugins/i18n.js +44 -44
  86. package/src/plugins/idb.js +227 -219
  87. package/src/plugins/save.js +37 -37
  88. package/src/plugins/scorm.js +287 -287
  89. package/src/plugins/xapi.js +11 -11
  90. package/src/public/index.html +33 -33
  91. package/src/router/index.js +43 -43
  92. package/src/router/routes.js +312 -312
  93. package/src/shared/generalfuncs.js +210 -210
  94. package/src/shared/validators.js +1069 -1069
  95. package/vite.config.js +0 -27
@@ -1,276 +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
- @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>
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>