fcad-core-dragon 2.1.0-beta.2 → 2.1.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 (67) hide show
  1. package/.editorconfig +33 -33
  2. package/.eslintignore +29 -29
  3. package/.eslintrc.cjs +81 -81
  4. package/CHANGELOG +20 -0
  5. package/bk.scss +117 -117
  6. package/package.json +30 -31
  7. package/src/assets/data/onboardingMessages.json +47 -47
  8. package/src/components/AppBase.vue +167 -39
  9. package/src/components/AppBaseButton.test.js +0 -1
  10. package/src/components/AppBaseErrorDisplay.vue +438 -438
  11. package/src/components/AppBaseFlipCard.vue +84 -84
  12. package/src/components/AppBaseModule.vue +103 -116
  13. package/src/components/AppBasePage.vue +13 -13
  14. package/src/components/AppBasePopover.vue +41 -41
  15. package/src/components/AppCompMenu.vue +2 -1
  16. package/src/components/AppCompPlayBarNext.vue +157 -16
  17. package/src/components/AppCompPopUpNext.vue +3 -3
  18. package/src/components/AppCompQuizRecall.vue +2 -3
  19. package/src/components/AppCompSettingsMenu.vue +172 -172
  20. package/src/components/AppCompTableOfContent.vue +1 -1
  21. package/src/components/AppCompViewDisplay.vue +6 -6
  22. package/src/components/tests__/useTimer.spec.js +91 -0
  23. package/src/composables/useIdleDetector.js +56 -0
  24. package/src/composables/useQuiz.js +1 -1
  25. package/src/composables/useTimer.js +175 -0
  26. package/src/externalComps/ModuleView.vue +22 -22
  27. package/src/externalComps/SummaryView.vue +91 -91
  28. package/src/main.js +2 -0
  29. package/src/module/stores/appStore.js +10 -34
  30. package/src/module/xapi/ADL.js +1 -0
  31. package/src/module/xapi/Crypto/Hasher.js +241 -241
  32. package/src/module/xapi/Crypto/WordArray.js +278 -278
  33. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  34. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
  35. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  36. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  37. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  38. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  39. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  40. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  41. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  42. package/src/module/xapi/Crypto/index.js +53 -53
  43. package/src/module/xapi/Statement/activity.js +47 -47
  44. package/src/module/xapi/Statement/agent.js +55 -55
  45. package/src/module/xapi/Statement/group.js +26 -26
  46. package/src/module/xapi/Statement/index.js +259 -259
  47. package/src/module/xapi/Statement/statement.js +253 -253
  48. package/src/module/xapi/Statement/statementRef.js +23 -23
  49. package/src/module/xapi/Statement/substatement.js +22 -22
  50. package/src/module/xapi/Statement/verb.js +36 -36
  51. package/src/module/xapi/activitytypes.js +17 -17
  52. package/src/module/xapi/utils.js +167 -167
  53. package/src/module/xapi/verbs.js +294 -294
  54. package/src/module/xapi/xapiStatement.js +444 -444
  55. package/src/plugins/analytics.js +34 -0
  56. package/src/plugins/bus.js +8 -8
  57. package/src/plugins/gsap.js +14 -14
  58. package/src/plugins/i18n.js +26 -44
  59. package/src/plugins/save.js +37 -37
  60. package/src/plugins/scorm.js +287 -287
  61. package/src/plugins/xapi.js +11 -11
  62. package/src/public/index.html +33 -33
  63. package/src/router/index.js +6 -3
  64. package/src/components/AppCompPlayBarProgress.vue +0 -82
  65. package/src/mixins/$mediaMixins.js +0 -809
  66. package/src/mixins/timerMixin.js +0 -195
  67. package/src/module/xapi/wrapper copy.js +0 -1963
@@ -0,0 +1,175 @@
1
+ export class Timer {
2
+ static timers = new Map() // Store all timers by ID
3
+
4
+ constructor(timerID) {
5
+ this.timerID = timerID || this.createTimerID() //timerID of the timer
6
+ this.timeCounter = 0 //time counter
7
+ this.elapsedCounter = 0 //elapsed time counter how lofg the timer is running
8
+ this.interval = null //interval for the timer
9
+ this.timerState = 'stopped' //state of the timer, can be 'started' or 'stopped'
10
+ Timer.timers.set(this.timerID, this) // Store the timer in the static map
11
+ }
12
+
13
+ /**
14
+ * @description Start the timer
15
+ */
16
+ start() {
17
+ if (this.getTimerState() == 'stopped') {
18
+ this.interval = setInterval(() => {
19
+ this.timeCounter += 1
20
+ this.elapsedCounter += 1
21
+ }, 1000)
22
+ this.timerState = 'started'
23
+
24
+ }
25
+ }
26
+
27
+ /** @description Pause the timer */
28
+ pause() {
29
+ if (this.getTimerState() == 'started') {
30
+ clearInterval(this.interval)
31
+ this.timerState = 'stopped'
32
+ }
33
+ }
34
+
35
+ /** @description Stop the timer and reset the timer to zero */
36
+ stop() {
37
+ if (this.getTimerState() == 'started') {
38
+ clearInterval(this.interval)
39
+ this.timeCounter = 0
40
+ this.elapsedCounter = 0
41
+ this.timerState = 'stopped'
42
+
43
+ }
44
+ }
45
+
46
+ /** @description Destroy the timer instance */
47
+ destroy() {
48
+ this.pause()
49
+ Timer.timers.delete(this.timerID)
50
+ }
51
+
52
+ /** @description Get the timer ID */
53
+ getTimerID() {
54
+ return this.timerID
55
+ }
56
+
57
+ /**
58
+ *
59
+ * @description retrive a timer instance by its ID
60
+ * If no ID is provided, it returns the current timer instance.
61
+ * @param {String} id - the ID of the timer to retrieve
62
+ * If no ID is provided, it returns the current timer instance.
63
+ *
64
+ * @throws {Error} - if the timer with the specified ID does not exist
65
+ *
66
+ * @returns {Timer} - the timer instance
67
+ */
68
+ getTimer(id=null) {
69
+ if (!id) {
70
+ console.warn('No timer ID provided. Returning the current timer.')
71
+ return this
72
+ }
73
+ if (!Timer.timers.has(id)) throw new Error(`Timer with ID ${id} does not exist.`)
74
+ return Timer.timers.get(id)
75
+ }
76
+
77
+ /**
78
+ * @description Get the current time counter in seconds
79
+ *
80
+ * @returns {Number} - the time counter in seconds
81
+ */
82
+ getTime() {
83
+ return this.timeCounter
84
+ }
85
+ /**
86
+ * @description Get the current state of the timer
87
+ *
88
+ * @returns {String} - timer state, can be 'started' or 'stopped'
89
+ */
90
+ getTimerState() {
91
+ return this.timerState
92
+ }
93
+ /**
94
+ * @description Get the elapsed time for the timer
95
+ * This is the time the timer has been running since it was started.
96
+ * It is not reset when the timer is paused.
97
+ *
98
+ * @returns {Number} - the time count in seconds
99
+ */
100
+ getElapsedTime() {
101
+ return this.elapsedCounter
102
+ }
103
+
104
+
105
+ /**
106
+ * @description Get all existing timers
107
+ *
108
+ * @returns {Map} - a map of all timer instances with their IDs as keys
109
+ */
110
+
111
+ static getAllTimers() {
112
+ return Timer.timers
113
+ }
114
+
115
+ /**
116
+ * @description - This method generates a unique timer ID
117
+ *
118
+ * @returns {String} - a unique timer ID
119
+ */
120
+ createTimerID() {
121
+ const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
122
+ let str = ''
123
+ const n = 2
124
+ for (let i = 0; i < n; i++) {
125
+ str = `${str}${alphabet[Math.floor(Math.random() * alphabet.length)]}`
126
+ }
127
+
128
+ const id = `Tm$${str}${Math.floor(Math.random() * 1000)}`
129
+
130
+ return id
131
+ }
132
+
133
+
134
+ /**
135
+ * @description Format seconds to ISO 8601 format
136
+ * Example of ISO 8601 time format of 24 chars: "1970-01-04T14:50:00.000Z"
137
+ * @param {Number} seconds - time in seconds
138
+ *
139
+ * @returns {String} - ISO 8601 formatted time string // YYYY-MM-DDTHH:mm:ss.sssZ
140
+ */
141
+ formatToISOString(seconds) {
142
+ let d = new Date(null) //create a default date ref
143
+ d.setSeconds(seconds) //set the time with passed numbers of seconds
144
+
145
+ let ISOTime = d.toISOString()
146
+
147
+ return ISOTime
148
+ }
149
+
150
+ /**
151
+ * @description gives time period in the format of HH:mm:ss
152
+ * @param {Number} seconds - time in seconds
153
+ *
154
+ * @returns {String} - time period in the format of HH:mm:ss
155
+ */
156
+ ISOTimeParser(seconds) {
157
+ let ISOTimePeriod = this.formatToISOString(seconds).substring(8, 19) // only the time portion of it
158
+ ISOTimePeriod = ISOTimePeriod.split('T')
159
+ const DDToHrs = (parseInt(ISOTimePeriod[0]) - 1) * 24 // convert xxT to hrs
160
+ const periodOfTime = ISOTimePeriod[1] ? ISOTimePeriod[1].split(':') : null
161
+
162
+ if (!periodOfTime) return '00:00:00'
163
+
164
+ let timeString = ''
165
+ let HH = (DDToHrs + parseInt(periodOfTime[0])).toString()
166
+ let mm = periodOfTime[1]
167
+ let ss = periodOfTime[2]
168
+
169
+ if (HH.length === 1) HH = `0${HH}`
170
+
171
+ timeString = `${HH}:${mm}:${ss}`
172
+
173
+ return timeString
174
+ }
175
+ }
@@ -1,22 +1,22 @@
1
- <template>
2
- <app-base-module :module-config="$data" />
3
- </template>
4
-
5
- <script>
6
- export default {
7
- data() {
8
- return {
9
- id: 'module_99',
10
- consigneBehavior: 'onHover', //Controle the behavior of desplaying instruction
11
- bookmarkActive: true, // Controle the use of saved point
12
- allowNavigationToActivity: null
13
-
14
- //main:''// Edit to define the ID of the node that will be main. When skipping to main content in the page.
15
- }
16
- },
17
- created() {
18
- this.allowNavigationToActivity =
19
- this.$helper.getSettingsFromStore('auto_next_activity')
20
- }
21
- }
22
- </script>
1
+ <template>
2
+ <app-base-module :module-config="$data" />
3
+ </template>
4
+
5
+ <script>
6
+ export default {
7
+ data() {
8
+ return {
9
+ id: 'module_99',
10
+ consigneBehavior: 'onHover', //Controle the behavior of desplaying instruction
11
+ bookmarkActive: true, // Controle the use of saved point
12
+ allowNavigationToActivity: null
13
+
14
+ //main:''// Edit to define the ID of the node that will be main. When skipping to main content in the page.
15
+ }
16
+ },
17
+ created() {
18
+ this.allowNavigationToActivity =
19
+ this.$helper.getSettingsFromStore('auto_next_activity')
20
+ }
21
+ }
22
+ </script>
@@ -1,91 +1,91 @@
1
- <template>
2
- <div>
3
- <app-comp-menu></app-comp-menu>
4
- <!-- <h6>normal</h6>
5
- <div class="t normal"></div>
6
- <h6>red</h6>
7
- <div class="t red"></div>
8
- <h6>green</h6>
9
- <div class="t green"></div>
10
- <h6>hue</h6>
11
- <div class="t hue"></div>
12
- <h6>Saturation</h6>
13
- <div class="t saturation"></div>
14
- <h6>desaturation</h6>
15
- <div class="t desaturation"></div>
16
- <h6>lighteness</h6>
17
- <div class="t lighteness"></div>
18
- <h6>darkness</h6>
19
- <div class="t darkness"></div>
20
- <h6>whiteness</h6>
21
- <div class="t whiteness"></div>
22
- <h6>blackness</h6>
23
- <div class="t blackness"></div> -->
24
- </div>
25
- </template>
26
-
27
- <script>
28
- export default {
29
- data() {
30
- return {}
31
- }
32
- }
33
- </script>
34
- <!-- <style lang="scss">
35
- @use 'sass:color';
36
- $color: #f11532;
37
- $color-red: color.change($color, $red: 155);
38
- $color-green: color.change($color, $green: 255);
39
- $color-hue: adjust-hue($color, -30deg);
40
- $color-saturation: color.scale($color, $saturation: 100%);
41
- $color-desaturate: color.scale($color, $saturation: -50%);
42
- $color-lighteness: color.scale($color, $lightness: 50%);
43
- $color-darkness: color.scale($color, $lightness: -50%);
44
- $color-whiteness: color.scale($color, $whiteness: 50%);
45
- $color-blackness: color.scale($color, $blackness: 50%);
46
-
47
- .t {
48
- width: 50px;
49
- height: 50px;
50
-
51
- &.normal {
52
- background: $color;
53
- }
54
-
55
- &.red {
56
- background: $color-red;
57
- }
58
-
59
- &.green {
60
- background: $color-green;
61
- }
62
-
63
- &.hue {
64
- background: $color-hue;
65
- }
66
-
67
- &.saturation {
68
- background: $color-saturation;
69
- }
70
-
71
- &.desaturation {
72
- background: $color-desaturate;
73
- }
74
-
75
- &.lighteness {
76
- background: $color-lighteness;
77
- }
78
-
79
- &.darkness {
80
- background: $color-darkness;
81
- }
82
-
83
- &.whiteness {
84
- background: $color-whiteness;
85
- }
86
-
87
- &.blackness {
88
- background: $color-blackness;
89
- }
90
- }
91
- </style> -->
1
+ <template>
2
+ <div>
3
+ <app-comp-menu></app-comp-menu>
4
+ <!-- <h6>normal</h6>
5
+ <div class="t normal"></div>
6
+ <h6>red</h6>
7
+ <div class="t red"></div>
8
+ <h6>green</h6>
9
+ <div class="t green"></div>
10
+ <h6>hue</h6>
11
+ <div class="t hue"></div>
12
+ <h6>Saturation</h6>
13
+ <div class="t saturation"></div>
14
+ <h6>desaturation</h6>
15
+ <div class="t desaturation"></div>
16
+ <h6>lighteness</h6>
17
+ <div class="t lighteness"></div>
18
+ <h6>darkness</h6>
19
+ <div class="t darkness"></div>
20
+ <h6>whiteness</h6>
21
+ <div class="t whiteness"></div>
22
+ <h6>blackness</h6>
23
+ <div class="t blackness"></div> -->
24
+ </div>
25
+ </template>
26
+
27
+ <script>
28
+ export default {
29
+ data() {
30
+ return {}
31
+ }
32
+ }
33
+ </script>
34
+ <!-- <style lang="scss">
35
+ @use 'sass:color';
36
+ $color: #f11532;
37
+ $color-red: color.change($color, $red: 155);
38
+ $color-green: color.change($color, $green: 255);
39
+ $color-hue: adjust-hue($color, -30deg);
40
+ $color-saturation: color.scale($color, $saturation: 100%);
41
+ $color-desaturate: color.scale($color, $saturation: -50%);
42
+ $color-lighteness: color.scale($color, $lightness: 50%);
43
+ $color-darkness: color.scale($color, $lightness: -50%);
44
+ $color-whiteness: color.scale($color, $whiteness: 50%);
45
+ $color-blackness: color.scale($color, $blackness: 50%);
46
+
47
+ .t {
48
+ width: 50px;
49
+ height: 50px;
50
+
51
+ &.normal {
52
+ background: $color;
53
+ }
54
+
55
+ &.red {
56
+ background: $color-red;
57
+ }
58
+
59
+ &.green {
60
+ background: $color-green;
61
+ }
62
+
63
+ &.hue {
64
+ background: $color-hue;
65
+ }
66
+
67
+ &.saturation {
68
+ background: $color-saturation;
69
+ }
70
+
71
+ &.desaturation {
72
+ background: $color-desaturate;
73
+ }
74
+
75
+ &.lighteness {
76
+ background: $color-lighteness;
77
+ }
78
+
79
+ &.darkness {
80
+ background: $color-darkness;
81
+ }
82
+
83
+ &.whiteness {
84
+ background: $color-whiteness;
85
+ }
86
+
87
+ &.blackness {
88
+ background: $color-blackness;
89
+ }
90
+ }
91
+ </style> -->
package/src/main.js CHANGED
@@ -27,6 +27,7 @@ import AppBaseSkeleton from './components/AppBaseSkeleton.vue'
27
27
  import GsapPlugin from './plugins/gsap'
28
28
  import eventBus from './plugins/bus'
29
29
  import helper from './plugins/helper'
30
+ import analytics from './plugins/analytics'
30
31
  import mergeLocales from './plugins/i18n'
31
32
  import { scormPlugin } from './plugins/scorm'
32
33
  import { xapiPlugin } from './plugins/xapi'
@@ -470,5 +471,6 @@ export default {
470
471
  //mergeLocales
471
472
  mergeLocales(options.i18n.global)
472
473
  app.use(helper, '$helper')
474
+ app.use(analytics, '$analytics')
473
475
  }
474
476
  }
@@ -10,7 +10,7 @@ export const useAppStore = defineStore('$appStore', {
10
10
  status: '',
11
11
  anchorStatus: null,
12
12
  thisModule: { activities: mappedFiles },
13
- appDebugMode: false,
13
+ appDebugMode: false, //
14
14
  currentActivity: null,
15
15
  currentPage: null,
16
16
  currentBranchPage: null,
@@ -125,7 +125,9 @@ export const useAppStore = defineStore('$appStore', {
125
125
  * @description: Getter to return the app status
126
126
  */
127
127
  getAppStatus: (state) => {
128
- return state.compStatusTracker.length ? 'loading' : 'ready'
128
+ return !state.userDataLoaded || state.compStatusTracker.length
129
+ ? 'loading'
130
+ : 'ready'
129
131
  },
130
132
 
131
133
  /**
@@ -286,15 +288,11 @@ export const useAppStore = defineStore('$appStore', {
286
288
  * @returns: page {Object}
287
289
  */
288
290
  getCurrentPage: (state) => {
289
- let page = null
290
291
  if (state.currentPage !== null) {
291
- page = {
292
- ...state.currentPage
293
- }
294
- page.mElements = state.currentPageMediaElements
295
- page.timeline = state.currentPageTimeline
292
+ state.currentPage['mElements'] = state.currentPageMediaElements
293
+ state.currentPage['timeline'] = state.currentPageTimeline
296
294
  }
297
- return page
295
+ return state.currentPage
298
296
  },
299
297
  /**
300
298
  * @description: Getter to return the current branching page
@@ -722,7 +720,7 @@ export const useAppStore = defineStore('$appStore', {
722
720
  this.currentBranchPage = data
723
721
  },
724
722
  /* set/update page information*/
725
- updateCurrentPage({ activity_Id, page_Id }) {
723
+ updateCurrentPage({ activity_Id, page_Id }, caller = null) {
726
724
  if (activity_Id && page_Id) {
727
725
  let page
728
726
  //id type case PXX_EXX_PXX
@@ -748,6 +746,7 @@ export const useAppStore = defineStore('$appStore', {
748
746
  }
749
747
  this.currentPage = page
750
748
  } else this.currentPage = {}
749
+ if (caller) console.log('🤙 updateCurrentPage called by', caller)
751
750
  },
752
751
  /**
753
752
  @description update the module data.
@@ -826,11 +825,7 @@ export const useAppStore = defineStore('$appStore', {
826
825
  * and create entry for user interaction
827
826
  * */
828
827
  _keys.forEach((key) => {
829
- // if (key !== _keys[0] && key !== _keys[1]) {
830
- // Vue.set(activity, [page], {
831
- // [key]: data[key]
832
- // })
833
- // }
828
+
834
829
  if (key !== _keys[0] && key !== _keys[1]) {
835
830
  activity[page] = {
836
831
  [key]: data[key]
@@ -890,18 +885,6 @@ export const useAppStore = defineStore('$appStore', {
890
885
  }
891
886
  },
892
887
 
893
- // SET_SHOW_PRIMARY_CONTROL(state, bool) {
894
- // state.showPrimaryCtrl = bool
895
- // },
896
-
897
- // SET_SHOW_NAV_LEFT_CONTROL(state, bool) {
898
- // state.showNavLeftCtrl = bool
899
- // },
900
-
901
- // SET_SHOW_NAV_RIGHT_CONTROL(state, bool) {
902
- // state.showNavRightCtrl = bool
903
- // },
904
-
905
888
  setLrsConfig(data) {
906
889
  if (data) this.lrsConfig = data
907
890
  },
@@ -922,13 +905,6 @@ export const useAppStore = defineStore('$appStore', {
922
905
  this.sideBIsOpen = data
923
906
  },
924
907
 
925
- // async updateDataFetchFromServer(data) {
926
- // if (!data || data.constructor !== Object) return
927
- // Object.keys(data).forEach((k) => {
928
- // this.dataFromServer = { ...this.dataFromServer, [k]: data[k] }
929
- // })
930
- // },
931
-
932
908
  updatePreviousActivity(data) {
933
909
  this.prevActivity = data
934
910
  },
@@ -74,6 +74,7 @@ export default class ADL {
74
74
  statements.forEach((statement) => {
75
75
  const withResult =
76
76
  statement.verb.id.includes('answered') ||
77
+ statement.verb.id.includes('played') ||
77
78
  statement.verb.id.includes('suspended') ||
78
79
  statement.verb.id.includes('completed')
79
80