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

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 (44) hide show
  1. package/CHANGELOG +377 -373
  2. package/package.json +61 -61
  3. package/src/$locales/en.json +3 -1
  4. package/src/$locales/fr.json +3 -1
  5. package/src/components/AppBase.vue +20 -17
  6. package/src/components/AppBaseButton.test.js +22 -0
  7. package/src/components/AppBaseButton.vue +11 -5
  8. package/src/components/AppBaseModule.vue +48 -27
  9. package/src/components/AppBasePage.vue +7 -44
  10. package/src/components/AppCompAudio.vue +31 -0
  11. package/src/components/AppCompBranchButtons.vue +20 -16
  12. package/src/components/AppCompButtonProgress.vue +4 -9
  13. package/src/components/AppCompCarousel.vue +120 -90
  14. package/src/components/AppCompInputCheckBoxNext.vue +5 -0
  15. package/src/components/AppCompInputDropdownNext.vue +50 -8
  16. package/src/components/AppCompInputTextNext.vue +21 -2
  17. package/src/components/AppCompInputTextTableNext.vue +1 -0
  18. package/src/components/AppCompInputTextToFillDropdownNext.vue +8 -0
  19. package/src/components/AppCompMenu.vue +428 -423
  20. package/src/components/AppCompNavigation.vue +41 -28
  21. package/src/components/AppCompNoteCall.vue +64 -38
  22. package/src/components/AppCompNoteCredit.vue +303 -105
  23. package/src/components/AppCompPlayBar.vue +4 -5
  24. package/src/components/AppCompPlayBarNext.vue +20 -12
  25. package/src/components/AppCompPopUpNext.vue +1 -4
  26. package/src/components/AppCompQuizNext.vue +8 -4
  27. package/src/components/AppCompQuizRecall.vue +44 -22
  28. package/src/components/AppCompTableOfContent.vue +61 -62
  29. package/src/components/AppCompViewDisplay.vue +6 -6
  30. package/src/components/BaseModule.vue +1 -18
  31. package/src/components/tests__/AppBaseButton.spec.js +53 -0
  32. package/src/main.js +3 -3
  33. package/src/module/stores/appStore.js +58 -5
  34. package/src/module/xapi/Crypto/index.js +53 -53
  35. package/src/module/xapi/Statement/activity.js +47 -47
  36. package/src/module/xapi/Statement/group.js +26 -26
  37. package/src/module/xapi/Statement/statementRef.js +23 -23
  38. package/src/module/xapi/Statement/substatement.js +22 -22
  39. package/src/module/xapi/Statement/verb.js +36 -36
  40. package/src/module/xapi/activitytypes.js +17 -17
  41. package/src/plugins/helper.js +53 -12
  42. package/src/router/index.js +6 -1
  43. package/src/shared/validators.js +36 -179
  44. package/vitest.config.js +19 -0
@@ -263,12 +263,12 @@ mediaMixins is used for all the methods/data shared between audio and video. In
263
263
  @mouseenter="activateLabel($event.currentTarget)"
264
264
  @mouseleave="deactivateLabel($event.currentTarget)"
265
265
  @focus="
266
- activateLabel($event.currentTarget),
267
- changeFocusState('volumeSlider', true)
266
+ (activateLabel($event.currentTarget),
267
+ changeFocusState('volumeSlider', true))
268
268
  "
269
269
  @blur="
270
- deactivateLabel($event.currentTarget),
271
- changeFocusState('volumeSlider', false)
270
+ (deactivateLabel($event.currentTarget),
271
+ changeFocusState('volumeSlider', false))
272
272
  "
273
273
  />
274
274
  <span class="volume-label" aria-hidden="true">
@@ -292,7 +292,7 @@ mediaMixins is used for all the methods/data shared between audio and video. In
292
292
  class="btn subtitleBtns"
293
293
  :aria-label="ccLabel"
294
294
  :data-title="`${ccLabel} (c)`"
295
- :disabled="!hasSubtitle"
295
+ :is-disabled="!hasSubtitle"
296
296
  :class="{
297
297
  md_disabled: !hasSubtitle,
298
298
  displayLabel: btnsLabelDisplay['btn-subtitles'] === true
@@ -320,11 +320,11 @@ mediaMixins is used for all the methods/data shared between audio and video. In
320
320
  class="btn-transcript"
321
321
  :aria-label="transcriptLabel"
322
322
  :data-title="`${transcriptLabel} (t)`"
323
- :disabled="transcriptBtnDisabled"
324
323
  :class="{
325
324
  md_disabled: transcriptBtnDisabled,
326
325
  displayLabel: btnsLabelDisplay['btn-transcript'] === true
327
326
  }"
327
+ :is-disabled="transcriptBtnDisabled"
328
328
  @click="toggleViewTranscript($event)"
329
329
  @mouseenter="activateLabel($event)"
330
330
  @mouseleave="deactivateLabel($event)"
@@ -350,11 +350,11 @@ mediaMixins is used for all the methods/data shared between audio and video. In
350
350
  ref="$btn-fullscreen"
351
351
  class="fullscreenBtns"
352
352
  :aria-label="fullscreenLabel"
353
- :disabled="fullscreenBtnDisabled"
354
353
  :class="{
355
354
  md_disabled: fullscreenBtnDisabled,
356
355
  displayLabel: btnsLabelDisplay['btn-fullscreen'] === true
357
356
  }"
357
+ :is-disabled="fullscreenBtnDisabled"
358
358
  :data-title="`${fullscreenLabel} (f)`"
359
359
  @click="toggleFullScreen()"
360
360
  @mouseenter="activateLabel($event)"
@@ -682,9 +682,8 @@ export default {
682
682
  if (this.firefoxTrack) {
683
683
  this.firefoxTrack.removeEventListener('cuechange', this.fireFoxMoveCC)
684
684
  }
685
- //this.$bus.$off('play-media', this.handleMediaControls)
685
+
686
686
  this.$bus.$off('transcript-hidden', this.resetTranscript)
687
- return this.$bus.$off('close-sidebar', 'ctxTranscript')
688
687
  },
689
688
  methods: {
690
689
  ...mapActions(useAppStore, [
@@ -899,6 +898,7 @@ export default {
899
898
  * @description - Toggle the state fo the sound
900
899
  */
901
900
  toggleMute() {
901
+ if (!this.showControlsValue) this.showControls()
902
902
  //Check first the volume of the media
903
903
  if (this.mediaElement.volume == 0) this.muted = true
904
904
 
@@ -952,7 +952,7 @@ export default {
952
952
 
953
953
  handleMediaControls(e) {
954
954
  e = e.code
955
- this.showControls()
955
+ if (!this.showControlsValue) this.showControls()
956
956
  switch (e) {
957
957
  case 'ArrowLeft':
958
958
  //If focus is on Volume, VolDown
@@ -1334,6 +1334,7 @@ export default {
1334
1334
 
1335
1335
  /** "@description -update the information of the seek tooltip*/
1336
1336
  updateSeekTooltip(evt) {
1337
+ if (!this.showControlsValue) this.showControls()
1337
1338
  //Elm progress Bar
1338
1339
  const progressBar = this.progressBar
1339
1340
  //progressBar position on the page
@@ -1423,6 +1424,7 @@ export default {
1423
1424
  */
1424
1425
  toggleFullScreen() {
1425
1426
  const fullscreenElement = this.mediaContainer
1427
+
1426
1428
  if (document.fullscreenElement) {
1427
1429
  // exitFullscreen is only available on the Document object.
1428
1430
  document.exitFullscreen()
@@ -1435,6 +1437,7 @@ export default {
1435
1437
  * @description update the value of fulls screen state
1436
1438
  */
1437
1439
  updateFullScreenState() {
1440
+ if (!this.showControlsValue) this.showControls()
1438
1441
  this.fullscreenOn = !this.fullscreenOn
1439
1442
  },
1440
1443
 
@@ -1463,6 +1466,7 @@ export default {
1463
1466
  this.setMediaSubtitles(false)
1464
1467
  },
1465
1468
  toggleViewSubtitle() {
1469
+ if (!this.showControlsValue) this.showControls()
1466
1470
  if (this.subtitlesEnabled) return this.hideSubtitles()
1467
1471
  if (!this.subtitlesEnabled) return this.showSubtitles()
1468
1472
  },
@@ -1474,6 +1478,7 @@ export default {
1474
1478
  * @fires 'close-sidebar' to AppBaseModule
1475
1479
  */
1476
1480
  toggleViewTranscript(event) {
1481
+ if (!this.showControlsValue) this.showControls()
1477
1482
  this.transcriptEnabled = !this.transcriptEnabled
1478
1483
  //When the function is called after a user interaction (mouse or keyboard), emit event
1479
1484
  if (event) {
@@ -1550,6 +1555,7 @@ export default {
1550
1555
  * @description Method to reset the transcript state
1551
1556
  */
1552
1557
  resetTranscript(content) {
1558
+ if (!this.showControlsValue) this.showControls()
1553
1559
  this.transcriptEnabled = false
1554
1560
  this.otherVideoTranscriptShown = false
1555
1561
  },
@@ -1685,9 +1691,11 @@ export default {
1685
1691
 
1686
1692
  right: calc(var(--progress-thumb-size) / -2);
1687
1693
  top: calc(
1688
- -1 * (
1694
+ -1 *
1695
+ (
1689
1696
  var(--progress-thumb-size) / 2 - var(--progress-bar-height) / 2
1690
- ) - var(--progress-bar-border-height) / 2
1697
+ ) - var(--progress-bar-border-height) /
1698
+ 2
1691
1699
  );
1692
1700
  display: flex;
1693
1701
  align-items: center;
@@ -208,13 +208,12 @@
208
208
  </template>
209
209
 
210
210
  <script>
211
- import AppBaseErrorDisplay from './AppBaseErrorDisplay.vue'
212
211
  import { mapActions } from 'pinia'
213
212
  import { useAppStore } from '../module/stores/appStore'
214
213
 
215
214
  export default {
216
215
  name: 'AppCompPopUp',
217
- components: { AppBaseErrorDisplay },
216
+
218
217
  data() {
219
218
  return {
220
219
  pType: null,
@@ -397,8 +396,6 @@ export default {
397
396
  this.pType = data.type
398
397
  this.pName = data.name
399
398
 
400
- console.log(this.pType)
401
-
402
399
  if (this.pType == 'popup-endActivity')
403
400
  this.updateEndPopUp(true) //This will handle the activation of the element in the portal
404
401
  else this.updateEndPopUp(false) //This will handle the activation of the element in the portal
@@ -77,7 +77,7 @@
77
77
  :id="`btn_quiz_${quizData.id}`"
78
78
  ref="quiz"
79
79
  class="btn-quiz btn-main"
80
- :is-active="quizIsNotAnswered || attemptsReached"
80
+ :is-disabled="quizIsNotAnswered || attemptsReached"
81
81
  :title="txtBtnSubmit"
82
82
  @click="validateAnswers"
83
83
  >
@@ -306,18 +306,21 @@ export default {
306
306
  break
307
307
  case ['dropdown', 'texte_troue_select', 'texte_tableau'].includes(
308
308
  type_question
309
- ):
309
+ ): {
310
+ const searchedVal = type_question == 'texte_tableau' ? '' : null
310
311
  if (
311
312
  this.quizInputType.length < choix_reponse.length ||
312
- this.$helper.containsValue(this.quizInputType, null)
313
+ this.$helper.containsValue(this.quizInputType, searchedVal)
313
314
  )
314
315
  notAnswer = true
315
316
  break
317
+ }
316
318
 
317
319
  case type_question == 'texte_troue':
318
320
  if (texte_base) {
319
321
  const regex = /\$%\S*%\$/g // regex pattern to match exp: $%number%$
320
322
  let matchAll = texte_base.split(regex)
323
+
321
324
  if (
322
325
  this.quizInputType.length < matchAll.length - 1 ||
323
326
  this.$helper.containsValue(this.quizInputType, '')
@@ -2271,7 +2274,7 @@ export default {
2271
2274
  const { type_question } = this.quizData
2272
2275
  switch (true) {
2273
2276
  case ['choix_unique', 'reponse_ouverte'].includes(type_question):
2274
- if (oldValue !== null) {
2277
+ if (newValue !== null && oldValue !== '') {
2275
2278
  this.showSolution = false
2276
2279
  }
2277
2280
  break
@@ -2870,6 +2873,7 @@ export default {
2870
2873
  const regex = /\$%\S*%\$/g // regex pattern to match exp: $%number%$
2871
2874
  let matchAll = texte_base.split(regex)
2872
2875
  let listInputTextFill = this.quizInputType
2876
+
2873
2877
  if (
2874
2878
  listInputTextFill.length == matchAll.length - 1 &&
2875
2879
  !this.$helper.containsValue(listInputTextFill, null) &&
@@ -16,25 +16,33 @@
16
16
  {{ quizRecall.title }}
17
17
  </component>
18
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>
19
+ <app-base-error-display
20
+ v-if="hasError.length"
21
+ :error-group="'component'"
22
+ :error-title="`ERREUR: COMPOSANT QUIZ RECALL`"
23
+ :errors-list="hasError"
24
+ ></app-base-error-display>
25
+ <template v-else>
26
+ <template v-if="quizRecall.done == true">
27
+ <div
28
+ v-if="quizRecall.hypertext_done"
29
+ class="quizRecall-text-done"
30
+ v-html="quizRecall.hypertext_done"
31
+ ></div>
32
+ <div class="quizRecall-ennonce" v-html="quizRecall.ennonce"></div>
33
+ <textarea
34
+ v-model="quizRecall.answer"
35
+ disabled
36
+ class="form-control"
37
+ ></textarea>
38
+ </template>
39
+ <template v-if="quizRecall.done == false">
40
+ <div
41
+ v-if="quizRecall.hypertext_undone"
42
+ class="quizRecall-text-undone"
43
+ v-html="quizRecall.hypertext_undone"
44
+ ></div>
45
+ </template>
38
46
  </template>
39
47
  </section>
40
48
  </template>
@@ -62,6 +70,7 @@ export default {
62
70
  'message.recall_undone'
63
71
  )}</p>` /*String traduite par défaut*/
64
72
  },
73
+ hasError: [],
65
74
  quizData: null
66
75
  }
67
76
  },
@@ -98,6 +107,8 @@ export default {
98
107
  */
99
108
  findQuizdataObject(searchObject, quizID) {
100
109
  for (let property in searchObject) {
110
+ //Should only check for not null poperties
111
+ if (!searchObject[property]) continue
101
112
  // Should only check for Object or Array property
102
113
  if (
103
114
  searchObject[property].constructor !== Array &&
@@ -124,6 +135,7 @@ export default {
124
135
  getQuizData(activityId, pageId) {
125
136
  if (pageId && activityId) {
126
137
  let pageData = this.getPageData(activityId, pageId)
138
+
127
139
  if (pageData) {
128
140
  this.quizData = this.findQuizdataObject(
129
141
  pageData,
@@ -132,17 +144,21 @@ export default {
132
144
 
133
145
  //Warn that the specified quiz could not be found
134
146
  if (!this.quizData) {
147
+ let msgErr = `Aucun quiz avec id '${this.quizRecallData.quizId}' pour la ${pageId} de ${activityId}`
135
148
  console.warn(
136
149
  `%c WARNING!>>> Quiz Recall: Unable to find a quiz with type_question 'reponse_ouverte' and id '${this.quizRecallData.quizId}' in ${pageId} of ${activityId}`,
137
150
  'background: orange; color: white; display: block; margin:5px;'
138
151
  )
152
+ this.hasError.push(msgErr)
139
153
  }
140
154
  } else {
141
155
  this.quizRecall.done == false
156
+ let msgErr = `Aucun quiz avec id '${this.quizRecallData.quizId}' pour la ${pageId} de ${activityId}`
142
157
  console.warn(
143
158
  `%c WARNING!>>> AppCompQuizRecall : QuizData ActivityID and PageID combinaison is invalid.`,
144
159
  'background: orange; color: white; display: block; margin:5px;'
145
160
  )
161
+ this.hasError.push(msgErr)
146
162
  }
147
163
  } else {
148
164
  this.quizRecall.done == false
@@ -243,17 +259,21 @@ export default {
243
259
 
244
260
  //Validate if all properties in quizRecallData are valid
245
261
  if (wrongProperties.length > 0) {
262
+ let msgErr = `QuizRecallData ${wrongProperties} invalid`
246
263
  console.warn(
247
- `%c WARNING!>>> AppCompQuizRecall : QuizRecallData ${wrongProperties} invalid. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
264
+ `%c WARNING!>>> AppCompQuizRecall : ${msgErr}. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
248
265
  'background: orange; color: white; display: block; margin:5px;'
249
266
  )
267
+ this.hasError.push(msgErr)
250
268
  }
251
269
  //Validate if all required properties are present in quizRecallData
252
270
  if (missingRequired.length > 0) {
271
+ let msgErr = `QuizRecallData missing required ${missingRequired} property`
253
272
  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.`,
273
+ `%c WARNING!>>> AppCompQuizRecall : ${msgErr}. Required properties: activityId and pageId. Optional properties: title, titletag, hypertext_done and hypertext_undone.`,
255
274
  'background: orange; color: white; display: block; margin:5px;'
256
275
  )
276
+ this.hasError.push(msgErr)
257
277
  }
258
278
  },
259
279
  /*Get a title tag (string). Return true if the tag is valid and false is it's not*/
@@ -264,10 +284,12 @@ export default {
264
284
  if (tags && value && tags.find((element) => element == lowerValue))
265
285
  return true
266
286
  else {
287
+ let msgErr = `Your quizRecallData titletag is not valid`
267
288
  console.warn(
268
- '%c WARNING!>>> recallMixins: Your quizRecallData titletag is not valid. You can use h1,h2,h3,h4,h5,h6,p,or span',
289
+ '%c WARNING!>>> AppCompQuizRecall : Your quizRecallData titletag is not valid. You can use h1,h2,h3,h4,h5,h6,p,or span',
269
290
  'background: orange; color: white; display: block; margin:5px;'
270
291
  )
292
+ this.hasError.push(msgErr)
271
293
  return false
272
294
  }
273
295
  }
@@ -8,55 +8,59 @@
8
8
  -->
9
9
 
10
10
  <template>
11
- <div v-if="error" id="sidebar-submenu" :class="{ isOpen: open }">
12
- <app-base-button
13
- id="close-toc"
14
- class="btn-ghost"
15
- :title="$t('button.closePopUp')"
16
- @click="close()"
17
- >
18
- <svg>
19
- <use href="#close-square-icon" />
20
- </svg>
21
- </app-base-button>
22
-
23
- <p class="t-act" v-html="title"></p>
24
-
25
- <div class="box-prog-act">
26
- <p>
27
- {{ $t('text.activity_progress') }}
28
- <span>{{ actProgress }}</span>
29
- </p>
30
- </div>
31
-
32
- <div class="box-anchor">
33
- <p class="t-toc">{{ $t('text.toc') }}</p>
34
-
35
- <a
36
- v-for="(anchor, index) of anchors"
37
- :key="anchor.title"
38
- class="toc-item"
39
- :done="sectionProgress(index)"
40
- @click="closeAndNextPage(anchor.path)"
41
- >
42
- <div class="box-text-anchor">
43
- <div class="text-anchor">
44
- <p class="anchor-t" v-html="anchor.title"></p>
45
- <p class="state">
46
- <svg>
47
- <use href="#check-toc" />
48
- </svg>
49
- {{ $t('text.complete') }}
50
- </p>
51
- </div>
11
+ <div v-if="error" id="sidebar-submenu" :class="{ isOpen: isOpened }">
12
+ <focus-trap :active="isOpened">
13
+ <div ref="target">
14
+ <app-base-button
15
+ id="close-toc"
16
+ class="btn-ghost"
17
+ :title="$t('button.closePopUp')"
18
+ @click="onCloseWidget('toc')"
19
+ >
52
20
  <svg>
53
- <use href="#chevronD-icon" />
21
+ <use href="#close-square-icon" />
54
22
  </svg>
23
+ </app-base-button>
24
+
25
+ <p class="t-act" v-html="title"></p>
26
+
27
+ <div class="box-prog-act">
28
+ <p>
29
+ {{ $t('text.activity_progress') }}
30
+ <span>{{ actProgress }}</span>
31
+ </p>
32
+ </div>
33
+ <div class="box-anchor">
34
+ <p class="t-toc">{{ $t('text.toc') }}</p>
35
+
36
+ <RouterLink
37
+ v-for="(anchor, index) of anchors"
38
+ :key="anchor.title"
39
+ class="toc-item"
40
+ :done="sectionProgress(index)"
41
+ :to="{ name: anchor.path }"
42
+ @click="closeAndNextPage(anchor.path)"
43
+ >
44
+ <div class="box-text-anchor">
45
+ <div class="text-anchor">
46
+ <p class="anchor-t" v-html="anchor.title"></p>
47
+ <p class="state">
48
+ <svg>
49
+ <use href="#check-toc" />
50
+ </svg>
51
+ {{ $t('text.complete') }}
52
+ </p>
53
+ </div>
54
+ <svg>
55
+ <use href="#chevronD-icon" />
56
+ </svg>
57
+ </div>
58
+ </RouterLink>
55
59
  </div>
56
- </a>
57
- </div>
60
+ </div>
61
+ </focus-trap>
58
62
  </div>
59
- <div v-else id="sidebar-submenu" :class="{ isOpen: open }">
63
+ <div v-else id="sidebar-submenu" :class="{ isOpen: isOpened }">
60
64
  <p>
61
65
  Cette activité n'existe pas dans menu setting, svp l'ajouter à votre menu
62
66
  setting
@@ -73,7 +77,7 @@ export default {
73
77
  title: '',
74
78
  anchors: [],
75
79
  activity: '',
76
- open: false,
80
+ isOpened: false,
77
81
  menuInfo: null,
78
82
  actProgress: null,
79
83
  error: true
@@ -101,7 +105,7 @@ export default {
101
105
  methods: {
102
106
  ...mapActions(useAppStore, ['updateWidgetOpen']),
103
107
  onInfoActivity(data) {
104
- //should be condition to avoid event fireing multiple time on call
108
+ //should be conditioned to avoid event firing multiple time on call
105
109
 
106
110
  if (data) {
107
111
  this.reset()
@@ -116,23 +120,18 @@ export default {
116
120
  }
117
121
  },
118
122
  onCloseWidget(data) {
119
- this.open = false
123
+ this.isOpened = false
120
124
  this.updateWidgetOpen(false)
121
125
  this.reset()
122
126
  },
123
127
  onToggleWidget(data) {
124
- if (data == 'toc') {
125
- this.open = !this.open
126
- this.updateWidgetOpen(true)
127
- } else {
128
- this.updateWidgetOpen(false)
129
- this.open = false
130
- }
128
+ if (data.type !== 'toc') return (this.isOpened = false)
129
+ this.isOpened = !this.isOpened
130
+ this.updateWidgetOpen(this.isOpened)
131
131
  },
132
132
  /* @Description:Get and set the section to output
133
133
  * @params: activity {Object}: the activity which sections need to be output
134
134
  */
135
- //
136
135
  getInfoSubMenu(activity) {
137
136
  //get the anchors for this activity from the store
138
137
  let menuInfo = this.getMenuSettings
@@ -226,12 +225,12 @@ export default {
226
225
  }
227
226
  },
228
227
  close() {
229
- this.open = !this.open
230
- this.updateWidgetOpen(this.open)
228
+ this.isOpened = !this.isOpened
229
+ this.updateWidgetOpen(this.isOpened)
231
230
  },
232
231
  closeAndNextPage(NextPage) {
233
- this.open = !this.open
234
- this.updateWidgetOpen(this.open)
232
+ this.isOpened = !this.isOpened
233
+ this.updateWidgetOpen(this.isOpened)
235
234
  this.$router.push({ name: NextPage })
236
235
  },
237
236
  reset() {
@@ -267,10 +266,10 @@ export default {
267
266
  for (let g = 1; g == numPage; g++) {
268
267
  tabPageSec.push(`P${g}`)
269
268
  }
270
-
271
269
  if (
270
+ typeof this.getAllCompleted[this.activity] !== 'undefined' &&
272
271
  this.getAllCompleted[this.activity].length !==
273
- this.getAllActivitiesState[this.activity].size
272
+ this.getAllActivitiesState[this.activity].size
274
273
  )
275
274
  return false
276
275
  }
@@ -1,6 +1,6 @@
1
- <template>
2
- <router-view />
3
- </template>
4
- <script>
5
- export default {}
6
- </script>
1
+ <template>
2
+ <router-view />
3
+ </template>
4
+ <script>
5
+ export default {}
6
+ </script>
@@ -5,11 +5,6 @@
5
5
  -->
6
6
  <template>
7
7
  <div v-if="mData" class="module-wrapper">
8
- <!-- <div
9
- class="overlay-close-widget"
10
- :class="{ blockOverlay: over }"
11
- @click="overlayClose()"
12
- ></div> -->
13
8
  <slot name="mTitle" />
14
9
  <slot>Module</slot>
15
10
  </div>
@@ -32,20 +27,8 @@ export default {
32
27
  }
33
28
  },
34
29
 
35
- mounted() {
36
- // this.$bus.$on('toggle-widget', () => {
37
- // this.over = true
38
- // })
39
- // this.$bus.$on('close-widget', () => {
40
- // this.over = false
41
- // })
42
- },
43
30
  created() {},
44
- methods: {
45
- // overlayClose() {
46
- // this.$bus.$emit('close-widget')
47
- // }
48
- }
31
+ methods: {}
49
32
  }
50
33
  </script>
51
34
 
@@ -0,0 +1,53 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import AppBaseButton from '../AppBaseButton.vue'
3
+ import { describe, expect, test } from 'vitest'
4
+
5
+ describe('AppBaseButton.vue', () => {
6
+ test('It renders a button', () => {
7
+ const wrapper = mount(AppBaseButton)
8
+
9
+ expect(wrapper.text()).toContain('Button')
10
+ })
11
+ // test prop value :type
12
+ test('Button has the correct type', () => {
13
+ const wrapper = mount(AppBaseButton, {
14
+ props: { type: 'submit' }
15
+ })
16
+ // expect(wrapper.props().type).toBe(submit)
17
+ expect(wrapper.get('button').attributes('type')).toBe('submit')
18
+ })
19
+ //test prop value : isActive
20
+ test('Button render a correct state', () => {
21
+ const wrapper = mount(AppBaseButton, {
22
+ props: { isDisabled: true }
23
+ })
24
+ expect(wrapper.get('button').classes()).toEqual(
25
+ expect.arrayContaining(['md_disabled'])
26
+ )
27
+
28
+ // expect(wrapper.props().isActive).toBe(true)
29
+ })
30
+
31
+ //test slot
32
+ test('Renders slot content properly', () => {
33
+ const wrapper = mount(AppBaseButton, {
34
+ slots: {
35
+ default: 'Mon bouton custome'
36
+ }
37
+ })
38
+
39
+ expect(wrapper.get('button').text()).toBe('Mon bouton custome')
40
+ })
41
+
42
+ //test click with event emitter
43
+ test('Emit event with value of the the $el when clicked', () => {
44
+ const wrapper = mount(AppBaseButton, {
45
+ slots: {
46
+ default: 'Mon bouton custome'
47
+ }
48
+ })
49
+ wrapper.get('button').trigger('click')
50
+ const clickEvent = wrapper.emitted('click')[0]
51
+ expect(clickEvent[0]).toEqual(wrapper.vm.$el)
52
+ })
53
+ })
package/src/main.js CHANGED
@@ -143,9 +143,9 @@ export default {
143
143
  if (key === 'menuSettings') {
144
144
  const mapAct = appStore.$state.thisModule.activities
145
145
  if (!mapAct) return
146
- const keys4Lesson = ['lessonTitle', ...mapAct.keys()]
146
+ const keys4Lesson = ['lessonTitle', 'lessonNumber', ...mapAct.keys()]
147
147
  const keys4ActivityOpt = ['title', 'subTitle']
148
- const keys4ActivityMando = ['time', 'anchors']
148
+ const keys4ActivityMandatory = ['time', 'anchors']
149
149
  const keys4Anchors = ['anchorName', 'pageRef', 'page']
150
150
 
151
151
  const errChecked = validatefileContent(
@@ -153,7 +153,7 @@ export default {
153
153
  options.menuSettings,
154
154
  {
155
155
  keys4Lesson,
156
- keys4ActivityMando,
156
+ keys4ActivityMandatory,
157
157
  keys4ActivityOpt,
158
158
  keys4Anchors
159
159
  }