fcad-core-dragon 2.0.1 → 2.0.2-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/.editorconfig +33 -33
  2. package/.eslintignore +29 -29
  3. package/.eslintrc.cjs +81 -81
  4. package/CHANGELOG +17 -1
  5. package/bk.scss +117 -117
  6. package/package.json +1 -1
  7. package/src/$locales/en.json +18 -4
  8. package/src/$locales/fr.json +17 -3
  9. package/src/assets/data/onboardingMessages.json +47 -47
  10. package/src/components/AppBase.vue +36 -341
  11. package/src/components/AppBaseErrorDisplay.vue +438 -438
  12. package/src/components/AppBaseFlipCard.vue +84 -84
  13. package/src/components/AppBaseModule.vue +16 -21
  14. package/src/components/AppBasePage.vue +45 -14
  15. package/src/components/AppBasePopover.vue +41 -41
  16. package/src/components/AppBaseSkeleton.vue +45 -0
  17. package/src/components/AppCompAudio.vue +12 -3
  18. package/src/components/AppCompButtonProgress.vue +13 -2
  19. package/src/components/AppCompCarousel.vue +12 -4
  20. package/src/components/AppCompInputCheckBoxNx.vue +324 -0
  21. package/src/components/AppCompInputDropdownNx.vue +295 -0
  22. package/src/components/AppCompInputRadioNx.vue +264 -0
  23. package/src/components/AppCompInputTextNx.vue +148 -0
  24. package/src/components/AppCompInputTextTableNx.vue +198 -0
  25. package/src/components/AppCompInputTextToFillDropdownNx.vue +291 -0
  26. package/src/components/AppCompInputTextToFillNx.vue +277 -0
  27. package/src/components/AppCompJauge.vue +11 -4
  28. package/src/components/AppCompMenu.vue +7 -14
  29. package/src/components/AppCompMenuItem.vue +7 -5
  30. package/src/components/AppCompNavigation.vue +21 -21
  31. package/src/components/AppCompNoteCall.vue +1 -0
  32. package/src/components/AppCompNoteCredit.vue +2 -1
  33. package/src/components/AppCompPlayBarNext.vue +94 -41
  34. package/src/components/AppCompPlayBarProgress.vue +82 -82
  35. package/src/components/AppCompPopUpNext.vue +6 -6
  36. package/src/components/AppCompQuiz.vue +500 -0
  37. package/src/components/AppCompQuizRecall.vue +113 -66
  38. package/src/components/AppCompSettingsMenu.vue +172 -172
  39. package/src/components/AppCompTableOfContent.vue +39 -10
  40. package/src/components/AppCompVideoPlayer.vue +1 -1
  41. package/src/components/AppCompViewDisplay.vue +6 -6
  42. package/src/composables/useQuiz.js +62 -179
  43. package/src/directives/nvdaFix.js +53 -0
  44. package/src/externalComps/ModuleView.vue +22 -22
  45. package/src/externalComps/SummaryView.vue +91 -91
  46. package/src/main.js +227 -30
  47. package/src/mixins/$mediaMixins.js +1 -11
  48. package/src/module/stores/appStore.js +29 -11
  49. package/src/module/xapi/Crypto/Hasher.js +241 -241
  50. package/src/module/xapi/Crypto/WordArray.js +278 -278
  51. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  52. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
  53. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  54. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  55. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  56. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  57. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  58. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  59. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  60. package/src/module/xapi/Crypto/index.js +53 -53
  61. package/src/module/xapi/Statement/activity.js +47 -47
  62. package/src/module/xapi/Statement/agent.js +55 -55
  63. package/src/module/xapi/Statement/group.js +26 -26
  64. package/src/module/xapi/Statement/index.js +259 -259
  65. package/src/module/xapi/Statement/statement.js +253 -253
  66. package/src/module/xapi/Statement/statementRef.js +23 -23
  67. package/src/module/xapi/Statement/substatement.js +22 -22
  68. package/src/module/xapi/Statement/verb.js +36 -36
  69. package/src/module/xapi/activitytypes.js +17 -17
  70. package/src/module/xapi/utils.js +167 -167
  71. package/src/module/xapi/verbs.js +294 -294
  72. package/src/module/xapi/xapiStatement.js +444 -444
  73. package/src/plugins/bus.js +8 -8
  74. package/src/plugins/gsap.js +14 -14
  75. package/src/plugins/i18n.js +44 -44
  76. package/src/plugins/idb.js +1 -1
  77. package/src/plugins/save.js +37 -37
  78. package/src/plugins/scorm.js +287 -287
  79. package/src/plugins/xapi.js +11 -11
  80. package/src/public/index.html +33 -33
  81. package/src/shared/generalfuncs.js +134 -0
  82. package/src/shared/validators.js +308 -234
  83. package/src/components/AppCompInputCheckBoxNext.vue +0 -205
  84. package/src/components/AppCompInputDropdownNext.vue +0 -201
  85. package/src/components/AppCompInputRadioNext.vue +0 -158
  86. package/src/components/AppCompInputTextNext.vue +0 -124
  87. package/src/components/AppCompInputTextTableNext.vue +0 -142
  88. package/src/components/AppCompInputTextToFillDropdownNext.vue +0 -238
  89. package/src/components/AppCompInputTextToFillNext.vue +0 -171
  90. package/src/components/AppCompQuizNext.vue +0 -2908
@@ -1,84 +1,84 @@
1
- <template>
2
- <!--
3
- inspire by : https://vuejsexamples.com/generic-flip-card-in-vue-that-allows-completely-arbitrary-content-on-each-side/
4
- -->
5
- <div class="flip-card" role="button" aria-pressed="false" @click="fnClick">
6
- <div class="inside-card" :class="{ flip: isFlipped }">
7
- <div class="front-card" name="front-card">
8
- <slot name="front-card" />
9
- </div>
10
- <div class="back-card">
11
- <slot name="back-card" />
12
- </div>
13
- </div>
14
- </div>
15
- </template>
16
- <script>
17
- export default {
18
- props: {
19
- isActive: {
20
- type: Boolean,
21
- default: false
22
- }
23
- },
24
- emits: ['click'],
25
- data() {
26
- return {
27
- isFlipped: false
28
- }
29
- },
30
- methods: {
31
- /**
32
- * @fires click to parent componant or page
33
- */
34
- fnClick() {
35
- this.$emit('click', this.$el)
36
- this.isFlipped = !this.isFlipped
37
- }
38
- }
39
- }
40
- </script>
41
- <style lang="scss">
42
- .flip-card {
43
- height: auto;
44
- cursor: pointer;
45
-
46
- /***** Parameretre modifiable *****/
47
- perspective: 100%;
48
- width: 90%;
49
-
50
- .inside-card {
51
- position: relative;
52
- width: 100%;
53
- height: 100%;
54
-
55
- /***** Parameretre modifiable *****/
56
- transform-style: preserve-3d;
57
- transition: transform 0.5s;
58
-
59
- &.flip {
60
- /***** Parameretre modifiable *****/
61
- transform: rotateY(180deg);
62
- }
63
-
64
- .front-card,
65
- .back-card {
66
- position: absolute;
67
- width: 100%;
68
- height: 100%;
69
- -webkit-backface-visibility: hidden;
70
- backface-visibility: hidden;
71
-
72
- .img-flip-card {
73
- width: 90%;
74
- height: auto;
75
- }
76
- }
77
-
78
- .back-card {
79
- /***** Parameretre modifiable *****/
80
- transform: rotateY(180deg);
81
- }
82
- }
83
- }
84
- </style>
1
+ <template>
2
+ <!--
3
+ inspire by : https://vuejsexamples.com/generic-flip-card-in-vue-that-allows-completely-arbitrary-content-on-each-side/
4
+ -->
5
+ <div class="flip-card" role="button" aria-pressed="false" @click="fnClick">
6
+ <div class="inside-card" :class="{ flip: isFlipped }">
7
+ <div class="front-card" name="front-card">
8
+ <slot name="front-card" />
9
+ </div>
10
+ <div class="back-card">
11
+ <slot name="back-card" />
12
+ </div>
13
+ </div>
14
+ </div>
15
+ </template>
16
+ <script>
17
+ export default {
18
+ props: {
19
+ isActive: {
20
+ type: Boolean,
21
+ default: false
22
+ }
23
+ },
24
+ emits: ['click'],
25
+ data() {
26
+ return {
27
+ isFlipped: false
28
+ }
29
+ },
30
+ methods: {
31
+ /**
32
+ * @fires click to parent componant or page
33
+ */
34
+ fnClick() {
35
+ this.$emit('click', this.$el)
36
+ this.isFlipped = !this.isFlipped
37
+ }
38
+ }
39
+ }
40
+ </script>
41
+ <style lang="scss">
42
+ .flip-card {
43
+ height: auto;
44
+ cursor: pointer;
45
+
46
+ /***** Parameretre modifiable *****/
47
+ perspective: 100%;
48
+ width: 90%;
49
+
50
+ .inside-card {
51
+ position: relative;
52
+ width: 100%;
53
+ height: 100%;
54
+
55
+ /***** Parameretre modifiable *****/
56
+ transform-style: preserve-3d;
57
+ transition: transform 0.5s;
58
+
59
+ &.flip {
60
+ /***** Parameretre modifiable *****/
61
+ transform: rotateY(180deg);
62
+ }
63
+
64
+ .front-card,
65
+ .back-card {
66
+ position: absolute;
67
+ width: 100%;
68
+ height: 100%;
69
+ -webkit-backface-visibility: hidden;
70
+ backface-visibility: hidden;
71
+
72
+ .img-flip-card {
73
+ width: 90%;
74
+ height: auto;
75
+ }
76
+ }
77
+
78
+ .back-card {
79
+ /***** Parameretre modifiable *****/
80
+ transform: rotateY(180deg);
81
+ }
82
+ }
83
+ }
84
+ </style>
@@ -76,10 +76,9 @@
76
76
  )
77
77
  "
78
78
  >
79
- <svg>
79
+ <svg aria-hidden="true" focusable="false">
80
80
  <use href="#close-square-icon" />
81
81
  </svg>
82
- <span class="sr-only">{{ $t('button.closePopUp') }}</span>
83
82
  </app-base-button>
84
83
  </div>
85
84
 
@@ -151,7 +150,6 @@ export default {
151
150
  customContentVisible: false,
152
151
  customContent: null,
153
152
  lessonCompletionStatus: false,
154
- checkedDataFromServer: 0,
155
153
  rightSidebarEvent: new CustomEvent('sidebarEvent', {
156
154
  bubbles: true,
157
155
  detail: {
@@ -175,9 +173,10 @@ export default {
175
173
  'getMenuSettings',
176
174
  'getRouteHistory',
177
175
  'getOnboardingEnabled',
178
- 'getDataFromServer',
179
176
  'getApplicationSettings',
180
- 'getCompStatusTracker'
177
+ 'getCompStatusTracker',
178
+ 'getLessonPosition',
179
+ 'getCompletionState'
181
180
  ]),
182
181
  isMenu() {
183
182
  return this.$route.name === 'menu'
@@ -385,14 +384,13 @@ export default {
385
384
  getAllCompleted: {
386
385
  handler() {
387
386
  // Check once the server to set the completion status of the lesson
388
- if (this.getDataFromServer && this.checkedDataFromServer < 1) {
389
- const { completedState } = this.getDataFromServer
387
+ if (this.getCompletionState) {
388
+ const completedState = this.getCompletionState
390
389
 
391
390
  this.lessonCompletionStatus =
392
391
  !completedState || !completedState.completion
393
392
  ? false
394
393
  : completedState.completion
395
- this.checkedDataFromServer += 1
396
394
  }
397
395
 
398
396
  if (!this.lessonCompletionStatus) this.sendCompletionStatus('LESSON')
@@ -412,10 +410,9 @@ export default {
412
410
  this.getModuleInfo.packageType === 'xapi' &&
413
411
  this.getConnectionInfo &&
414
412
  this.getConnectionInfo.actor &&
415
- this.getConnectionInfo.remote &&
416
- this.getDataFromServer
413
+ this.getConnectionInfo.remote
417
414
  ) {
418
- const { lessonPosition } = this.getDataFromServer
415
+ const lessonPosition = this.getLessonPosition
419
416
 
420
417
  const lastReached = lessonPosition.length ? lessonPosition[0] : ''
421
418
 
@@ -568,8 +565,8 @@ export default {
568
565
  'updateCurrentTimeline',
569
566
  'updateCurrentMediaElements',
570
567
  'updateCurrentPage',
571
- 'updateDataFetchFromServer',
572
568
  'updatesideBIsOpen',
569
+ 'setCompletionState',
573
570
  'updatepopIsOpen'
574
571
  ]),
575
572
  onNavMouseleave() {
@@ -1352,7 +1349,6 @@ export default {
1352
1349
  !this.getConnectionInfo ||
1353
1350
  !this.getConnectionInfo.actor ||
1354
1351
  !this.getConnectionInfo.remote ||
1355
- !this.getDataFromServer ||
1356
1352
  !context
1357
1353
  )
1358
1354
  return
@@ -1370,9 +1366,8 @@ export default {
1370
1366
  thisActivityProgressLength,
1371
1367
  thisActivityLength
1372
1368
 
1373
- const { userProgress } = this.getDataFromServer
1374
1369
  const thisActivityServerState =
1375
- userProgress[this.$route.meta.activity_ref]
1370
+ this.getUserInteraction[this.$route.meta.activity_ref]
1376
1371
 
1377
1372
  if (thisActivityServerState)
1378
1373
  recordInServerLength = Object.keys(thisActivityServerState).length
@@ -1497,9 +1492,7 @@ export default {
1497
1492
  duration: this.lessonDuration,
1498
1493
  completion: this.lessonCompletionStatus
1499
1494
  }
1500
- this.updateDataFetchFromServer({
1501
- completedState
1502
- })
1495
+ this.setCompletionState(completedState)
1503
1496
  }
1504
1497
 
1505
1498
  break
@@ -1517,7 +1510,7 @@ export default {
1517
1510
  */
1518
1511
 
1519
1512
  sendStartStatement(a) {
1520
- if (!a || !this.getDataFromServer) return
1513
+ if (!a) return
1521
1514
  const { id } = a
1522
1515
  let aName = null
1523
1516
 
@@ -1544,8 +1537,10 @@ export default {
1544
1537
  /*
1545
1538
  *Determine if activity as been initialized. Activity is initialized when it is in the serverRecords
1546
1539
  */
1547
- const { userProgress } = this.getDataFromServer
1548
- const thisActivityServerState = userProgress[id] ? userProgress[id] : {}
1540
+
1541
+ const thisActivityServerState = this.getUserInteraction[id]
1542
+ ? this.getUserInteraction[id]
1543
+ : {}
1549
1544
  const recordInServerLength = Object.keys(thisActivityServerState).length
1550
1545
 
1551
1546
  const stmt = {
@@ -83,6 +83,7 @@ export default {
83
83
  //Getting initial existing userIntaction from store
84
84
  const { userInteraction: previousInteraction = {} } =
85
85
  store.getPageInteraction(activityRef, pageID)
86
+
86
87
  return { store, previousInteraction, pageID, pageType }
87
88
  },
88
89
 
@@ -124,6 +125,9 @@ export default {
124
125
  getUserInteraction() {
125
126
  return this.store.getUserInteraction
126
127
  },
128
+ getPageInteraction() {
129
+ return this.store.getPageInteraction
130
+ },
127
131
 
128
132
  getCurrentPage() {
129
133
  return this.store.getCurrentPage
@@ -153,10 +157,6 @@ export default {
153
157
  return this.store.getBifChoice
154
158
  },
155
159
 
156
- getDataFromServer() {
157
- return this.store.getDataFromServer
158
- },
159
-
160
160
  isBranchingPage() {
161
161
  return this.$route.meta.type === 'branching' && this.type !== 'pg_branch'
162
162
  },
@@ -332,13 +332,13 @@ export default {
332
332
  },
333
333
  watch: {
334
334
  userInteraction: {
335
- handler(newValue) {
335
+ async handler(newValue) {
336
336
  /**
337
- * Objserve changes in the number of poperties to dispatch updates in the userdata in the Store
337
+ * Observe changes in the number of poperties to dispatch updates in the userdata in the Store
338
338
  */
339
339
 
340
340
  if (newValue && Object.entries(this.userInteraction).length) {
341
- this.store.updateUserMetaData({
341
+ await this.store.updateUserMetaData({
342
342
  activityRef: this.pageData.activityRef,
343
343
  id: this.pageData.id,
344
344
  userInteraction: { ...this.userInteraction }
@@ -347,6 +347,14 @@ export default {
347
347
  },
348
348
  immediate: true,
349
349
  deep: true
350
+ },
351
+ 'store.userDataLoaded': {
352
+ async handler() {
353
+ if (!this.store.userDataLoaded) return
354
+ this.userInteraction = await this.setInitialInteraction()
355
+ },
356
+ immediate: true,
357
+ deep: true
350
358
  }
351
359
  },
352
360
  created() {
@@ -367,7 +375,6 @@ export default {
367
375
  // Handeling presence of animation in the page
368
376
  if (this.pageData.animation) {
369
377
  // update the store with the information of currentTimeline
370
- //this.store.updateCurrentTimeline(this.$gsap.timeline({ paused: true }))
371
378
  }
372
379
 
373
380
  if (this.type == 'pg_branch')
@@ -378,6 +385,7 @@ export default {
378
385
  this.$bus.$on('media-viewed', this.setMediaViewed)
379
386
  this.$bus.$on('manage-media-players', this.managePlayingMedia)
380
387
  this.$bus.$on('video-transcript-toggle', this.onVideoTranscriptToggle)
388
+ this.$bus.$on('save-quiz-answers', this.saveQuizAnswers)
381
389
  },
382
390
  mounted() {
383
391
  //Fix for firefox not updating aria-labelledby (was stuck saying Activite 1, page 1 on every pages)
@@ -424,6 +432,7 @@ export default {
424
432
  this.$bus.$off('media-viewed', this.setMediaViewed)
425
433
  this.$bus.$off('manage-media-players', this.managePlayingMedia)
426
434
  this.$bus.$off('video-transcript-toggle', this.onVideoTranscriptToggle)
435
+ this.$bus.$off('save-quiz-answers', this.saveQuizAnswers)
427
436
  window.removeEventListener('scroll', this.onFirstScroll, { once: true }) //in case user did not scroll
428
437
  window.removeEventListener('scroll', this.handleScroll)
429
438
  },
@@ -440,7 +449,10 @@ export default {
440
449
  handleScroll(event) {
441
450
  event
442
451
  /*
443
- * DocumentElement properties does not alway work properly on all Browser. To Ensure reliable value of its properties on all * Broswer we will calculate the Document Height by taking the maximum of body and documentElement height poperties.
452
+ * DocumentElement properties does not alway work properly on all Browser.
453
+ * To Ensure reliable value of its properties on all.
454
+ * Browser we will calculate the Document Height by taking the maximum of
455
+ * body and documentElement height poperties.
444
456
  * ref:https://javascript.info/size-and-scroll-window
445
457
  */
446
458
 
@@ -515,10 +527,7 @@ export default {
515
527
  getProgress(id) {
516
528
  id = id || this.pageData.id
517
529
 
518
- const record = this.store.getPageInteraction(
519
- this.pageData.activityRef,
520
- id
521
- )
530
+ const record = this.getPageInteraction(this.pageData.activityRef, id)
522
531
 
523
532
  if (Object.entries(record).length) {
524
533
  const { userInteraction } = record
@@ -620,7 +629,7 @@ export default {
620
629
  })
621
630
  },
622
631
  getAnchorComplete() {
623
- const records = this.store.getPageInteraction(
632
+ const records = this.getPageInteraction(
624
633
  this.pageData.activityRef,
625
634
  this.pageData.id
626
635
  )
@@ -671,6 +680,7 @@ export default {
671
680
 
672
681
  this.userInteraction.mediasViewed = mediasViewed
673
682
  }
683
+
674
684
  //Should add ID in media viewed list if viewed for the 1st time
675
685
  if (mediasViewed.includes(mediaID)) return
676
686
 
@@ -729,6 +739,27 @@ export default {
729
739
  const playbarInstance = m[attrKeys[3]]
730
740
  playbarInstance.otherVideoTranscriptShown = transcriptShown
731
741
  })
742
+ },
743
+ setInitialInteraction() {
744
+ const { activityRef, id: pageID } = this.pageData
745
+ const { userInteraction: previousInteraction = {} } =
746
+ this.getPageInteraction(activityRef, pageID)
747
+
748
+ return previousInteraction
749
+ },
750
+ saveQuizAnswers(el, quiz) {
751
+ if (!this.userInteraction.quizAnswers)
752
+ return (this.userInteraction.quizAnswers = { ...quiz })
753
+ const quizID = Object.keys(quiz)[0]
754
+
755
+ if (!this.userInteraction.quizAnswers[quizID])
756
+ return (this.userInteraction.quizAnswers = {
757
+ ...this.userInteraction.quizAnswers,
758
+ ...quiz
759
+ })
760
+ const quizValue = Object.values(quiz)[0]
761
+ this.userInteraction.quizAnswers[quizID] = quizValue
762
+ // const {}
732
763
  }
733
764
  }
734
765
  }
@@ -1,41 +1,41 @@
1
- <!--
2
- @ Description: This component is used to create a popover that is accessible via keyboard navigation (tab + space/enter)
3
- -->
4
- <template>
5
- <v-tooltip
6
- ref="tooltip"
7
- v-bind="$attrs"
8
- v-model="show"
9
- transition="false"
10
- :open-on-click="true"
11
- :persistent="false"
12
- >
13
- <slot></slot>
14
- </v-tooltip>
15
- </template>
16
-
17
- <script>
18
- export default {
19
- name: 'AppBasePopover',
20
- data() {
21
- return {
22
- show: false,
23
- alertContainer: null
24
- }
25
- },
26
- watch: {
27
- show: {
28
- handler(newValue) {
29
- if (newValue) {
30
- const content = this.$refs.tooltip.contentEl.textContent
31
- this.alertContainer.textContent = ''
32
- this.alertContainer.textContent = content
33
- }
34
- }
35
- }
36
- },
37
- mounted() {
38
- this.alertContainer = document.getElementById('hiddenAlertContainer')
39
- }
40
- }
41
- </script>
1
+ <!--
2
+ @ Description: This component is used to create a popover that is accessible via keyboard navigation (tab + space/enter)
3
+ -->
4
+ <template>
5
+ <v-tooltip
6
+ ref="tooltip"
7
+ v-bind="$attrs"
8
+ v-model="show"
9
+ transition="false"
10
+ :open-on-click="true"
11
+ :persistent="false"
12
+ >
13
+ <slot></slot>
14
+ </v-tooltip>
15
+ </template>
16
+
17
+ <script>
18
+ export default {
19
+ name: 'AppBasePopover',
20
+ data() {
21
+ return {
22
+ show: false,
23
+ alertContainer: null
24
+ }
25
+ },
26
+ watch: {
27
+ show: {
28
+ handler(newValue) {
29
+ if (newValue) {
30
+ const content = this.$refs.tooltip.contentEl.textContent
31
+ this.alertContainer.textContent = ''
32
+ this.alertContainer.textContent = content
33
+ }
34
+ }
35
+ }
36
+ },
37
+ mounted() {
38
+ this.alertContainer = document.getElementById('hiddenAlertContainer')
39
+ }
40
+ }
41
+ </script>
@@ -0,0 +1,45 @@
1
+ <!--
2
+ @ Description: This component is used to display skeleton screens while content is loading.
3
+
4
+ -->
5
+
6
+ <template>
7
+ <div class="skeleton-wrapper">
8
+ <div v-if="skeletonText" class="skeleton-text">{{ skeletonText }}</div>
9
+ <div v-for="line in skeletonLines" :key="line" class="skeleton-line"></div>
10
+ </div>
11
+ </template>
12
+
13
+ <script>
14
+ export default {
15
+ name: 'AppBaseSkeleton',
16
+ props: {
17
+ skeletonLines: { type: Number, default: 1 }, //number of skeleton lines to display
18
+ skeletonText: { type: String, default: `⏳ LOADING...` } //number of skeleton lines to display
19
+ }
20
+ }
21
+ </script>
22
+
23
+ <style lang="scss">
24
+ .skeleton-wrapper {
25
+ display: flex;
26
+ flex-direction: column;
27
+ width: 100%;
28
+ gap: 8px;
29
+ }
30
+ skeleton-text {
31
+ font-size: larger;
32
+ }
33
+ .skeleton-line {
34
+ height: 25px;
35
+ background: linear-gradient(90deg, #ddd, #eee, #ddd);
36
+ background-size: 200% 100%;
37
+ animation: skeleton-loading 1.2s infinite linear;
38
+ border-radius: 4px;
39
+ }
40
+ @keyframes skeleton-loading {
41
+ to {
42
+ background-position-x: -200%;
43
+ }
44
+ }
45
+ </style>
@@ -29,7 +29,7 @@
29
29
  <div v-show="!isLoading && !hasSourceLoadingError" class="audio-content">
30
30
  <img v-if="mPoster" class="audio-img" :src="mPoster" :alt="mAlt" />
31
31
  <div class="audio-media">
32
- <h5>{{ mTitle }}</h5>
32
+ <span>{{ mTitle }}</span>
33
33
  <div class="audio-media-player">
34
34
  <audio
35
35
  :id="id"
@@ -174,13 +174,17 @@ export default {
174
174
  </script>
175
175
  <style scoped lang="scss">
176
176
  .audio-card {
177
- // --primary100: #deeff8;
178
- // --primary700: #005c8d;
179
177
  position: relative;
180
178
  border-radius: 4px;
181
179
  padding: 24px;
180
+ min-width: 425px;
182
181
  max-width: 600px;
183
182
  box-shadow: 0px 3px 6px rgb(26 25 25 / 0.16);
183
+
184
+ @media screen and (max-width: 1000px) {
185
+ display: flex;
186
+ flex-direction: column;
187
+ }
184
188
  .audio-img {
185
189
  width: 128px;
186
190
  margin-right: 24px;
@@ -190,6 +194,11 @@ export default {
190
194
  flex-direction: row;
191
195
  align-items: center;
192
196
  padding-bottom: 24px;
197
+
198
+ @media screen and (max-width: 1000px) {
199
+ display: flex;
200
+ flex-direction: column;
201
+ }
193
202
  .audio-media {
194
203
  width: 100%;
195
204
  h5 {
@@ -3,7 +3,10 @@
3
3
  <app-base-button
4
4
  :id="`btn_branch_${branchData.id}`"
5
5
  :target-ref="branchData.id"
6
+ aria-controls="right-sidebar"
6
7
  :title="btnTitle || $t('text.place_holder.for_title_btn_progress')"
8
+ :aria-label="btnTitle || $t('text.place_holder.for_title_btn_progress')"
9
+ :aria-expanded="isActive"
7
10
  :class="
8
11
  branchData.state === status.COMPLETE
9
12
  ? 'branch-btn-default branche-complete'
@@ -11,10 +14,18 @@
11
14
  "
12
15
  @click="openBranch(branchData.id)"
13
16
  >
14
- <svg v-if="branchData.state === status.COMPLETE">
17
+ <svg
18
+ v-if="branchData.state === status.COMPLETE"
19
+ aria-hidden="true"
20
+ focusable="false"
21
+ >
15
22
  <use href="#check-icon"></use>
16
23
  </svg>
17
- <svg v-if="branchData.state != status.COMPLETE">
24
+ <svg
25
+ v-if="branchData.state != status.COMPLETE"
26
+ aria-hidden="true"
27
+ focusable="false"
28
+ >
18
29
  <use href="#navigate-next-icon"></use>
19
30
  </svg>
20
31
  </app-base-button>