fcad-core-dragon 2.1.0-beta.1 → 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.
- package/CHANGELOG +40 -0
- package/package.json +30 -31
- package/src/components/AppBase.vue +167 -39
- package/src/components/AppBaseButton.test.js +0 -1
- package/src/components/AppBaseModule.vue +103 -116
- package/src/components/AppBasePage.vue +13 -13
- package/src/components/AppCompInputCheckBoxNx.vue +1 -1
- package/src/components/AppCompInputRadioNx.vue +1 -1
- package/src/components/AppCompMenu.vue +2 -1
- package/src/components/AppCompPlayBarNext.vue +157 -16
- package/src/components/AppCompPopUpNext.vue +3 -3
- package/src/components/AppCompQuizNext.vue +1 -1
- package/src/components/AppCompQuizRecall.vue +2 -3
- package/src/components/AppCompTableOfContent.vue +1 -1
- package/src/components/tests__/useTimer.spec.js +91 -0
- package/src/composables/useIdleDetector.js +56 -0
- package/src/composables/useQuiz.js +1 -1
- package/src/composables/useTimer.js +175 -0
- package/src/main.js +2 -0
- package/src/module/stores/appStore.js +10 -34
- package/src/module/xapi/ADL.js +1 -0
- package/src/plugins/analytics.js +34 -0
- package/src/plugins/i18n.js +9 -27
- package/src/router/index.js +6 -3
- package/src/components/AppCompPlayBarProgress.vue +0 -82
- package/src/mixins/$mediaMixins.js +0 -809
- package/src/mixins/timerMixin.js +0 -195
- package/src/module/xapi/wrapper copy.js +0 -1963
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
|
|
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
|
-
|
|
292
|
-
|
|
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
|
|
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
|
-
|
|
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
|
},
|
package/src/module/xapi/ADL.js
CHANGED
|
@@ -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
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { event } from 'vue-gtag'
|
|
2
|
+
import VueGtag from 'vue-gtag'
|
|
3
|
+
|
|
4
|
+
export default function analytics(app, name) {
|
|
5
|
+
Object.defineProperty(app.config.globalProperties, name, {
|
|
6
|
+
value: {
|
|
7
|
+
analyticsEnabled: false,
|
|
8
|
+
//Initialize the vue-gtag plugin if a valid analytics id is provided in App.vue
|
|
9
|
+
init(analytics_id, router) {
|
|
10
|
+
if (typeof analytics_id !== 'undefined' && analytics_id.length > 1) {
|
|
11
|
+
const pluginConfig = {
|
|
12
|
+
config: { id: analytics_id }
|
|
13
|
+
}
|
|
14
|
+
app.use(VueGtag, pluginConfig, router)
|
|
15
|
+
this.analyticsEnabled = true
|
|
16
|
+
} else {
|
|
17
|
+
console.log(
|
|
18
|
+
'no valid analytics_id provided in App.vue : analytics disabled'
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
//track an event
|
|
23
|
+
sendEvent(name, params) {
|
|
24
|
+
if (this.analyticsEnabled) {
|
|
25
|
+
console.log(`GA|track event named: ${name}`)
|
|
26
|
+
if (params) {
|
|
27
|
+
console.log(`GA|with params:`, params)
|
|
28
|
+
}
|
|
29
|
+
event(name, params)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}
|
package/src/plugins/i18n.js
CHANGED
|
@@ -5,40 +5,22 @@ import _ from 'lodash'
|
|
|
5
5
|
* @param {Object} i18n - vue-i18n internalization object.
|
|
6
6
|
*/
|
|
7
7
|
export default function mergeLocales(i18n) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* setLocaleMessage: ƒ setLocaleMessage(locale, message)// set the message with new message object
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
// This library locales files
|
|
16
|
-
// const thisLocales = require.context(
|
|
17
|
-
// '../$locales',
|
|
18
|
-
// true,
|
|
19
|
-
// /[A-Za-z0-9-_,\s]+\.json$/i
|
|
20
|
-
// )
|
|
21
|
-
|
|
22
|
-
const thisLocales = import.meta.glob('../$locales/*.json', { eager: true })
|
|
8
|
+
const thisLocales = import.meta.glob('../$locales/*.json', {
|
|
9
|
+
import: 'default',
|
|
10
|
+
eager: true
|
|
11
|
+
})
|
|
23
12
|
for (const path in thisLocales) {
|
|
24
13
|
const matched = path.match(/([A-Za-z0-9-_]+)\./i)
|
|
25
14
|
if (matched && matched.length > 1) {
|
|
26
15
|
const locale = matched[1]
|
|
16
|
+
|
|
27
17
|
// Using lodash to deeply merge objects
|
|
28
|
-
const
|
|
29
|
-
const
|
|
18
|
+
const coreMessages = JSON.parse(JSON.stringify(thisLocales[path]))
|
|
19
|
+
const templateMessages = JSON.parse(JSON.stringify(i18n.messages[locale]))
|
|
20
|
+
const mergedMessages = _.merge(coreMessages, templateMessages)
|
|
21
|
+
|
|
30
22
|
// Since merLocalMessage will do a shallow merge of the object. We will use setLocalMessage to replace the message with new message object
|
|
31
23
|
i18n.setLocaleMessage(locale, mergedMessages)
|
|
32
24
|
}
|
|
33
25
|
}
|
|
34
|
-
// thisLocales.keys().forEach((key) => {
|
|
35
|
-
// const matched = key.match(/([A-Za-z0-9-_]+)\./i)
|
|
36
|
-
// if (matched && matched.length > 1) {
|
|
37
|
-
// const locale = matched[1]
|
|
38
|
-
// // Using lodash to deeply merge objects
|
|
39
|
-
// const mergedMessages = deep.merge(i18n.messages[locale], thisLocales(key))
|
|
40
|
-
// // Since merLocalMessage will do a shallow merge of the object. We will use setLocalMessage to replace the message with new message object
|
|
41
|
-
// i18n.setLocaleMessage(locale, mergedMessages)
|
|
42
|
-
// }
|
|
43
|
-
// })
|
|
44
26
|
}
|
package/src/router/index.js
CHANGED
|
@@ -26,20 +26,23 @@ router.beforeResolve((to, from, next) => {
|
|
|
26
26
|
const { getWidgetOpen, getPopupIsOpen, getSidebarIsOpen } = appStore
|
|
27
27
|
const noNavigationToMenu = appStore.getSettingsFromStore('no_menu')
|
|
28
28
|
|
|
29
|
+
if (to.name == 'module') return next({ name: 'menu' }) //redirect to 404 if trying to access module directly
|
|
30
|
+
|
|
29
31
|
if (getWidgetOpen) app.config.globalProperties.$bus.$emit('close-widget') //close opened widget
|
|
30
32
|
if (getPopupIsOpen) app.config.globalProperties.$bus.$emit('close-popup') //close the popup
|
|
31
33
|
if (getSidebarIsOpen) app.config.globalProperties.$bus.$emit('close-sidebar') //close the sidebar
|
|
32
34
|
|
|
33
35
|
if (from.name !== 'module')
|
|
34
36
|
app.config.globalProperties.$bus.$emit('update-route-history', from)
|
|
35
|
-
|
|
37
|
+
|
|
38
|
+
app.config.globalProperties.$bus.$emit('update-content', to) //update the content of the current page
|
|
36
39
|
//hidle detector should be stopped in menu
|
|
37
40
|
if (to.name == 'menu') {
|
|
38
|
-
app.config.globalProperties.$bus.$emit('timer
|
|
41
|
+
app.config.globalProperties.$bus.$emit('stop-app-timer')
|
|
39
42
|
app.config.globalProperties.$bus.$emit('stop-idle-detector')
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
if (noNavigationToMenu && to.name == 'menu') {
|
|
45
|
+
if ((noNavigationToMenu && to.name == 'menu') || to.name == 'module') {
|
|
43
46
|
const r = app.config.globalProperties.$helper.getRoutesFromVueRouter() //This return all the routes defined for the module
|
|
44
47
|
let safeRoute = r.meta.children[0] //get the first navigable route from the module routes
|
|
45
48
|
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
<!--@ Description: This component is used to display the playbar associate with the videoPlayer
|
|
2
|
-
@ What it does: The component is used to interacted with the videoPlayer via buttons.
|
|
3
|
-
v-media class is used to identified which html elements trigger the playBar to be appear (with focus/click)-->
|
|
4
|
-
<template>
|
|
5
|
-
<!--------------------------------- PLAY-BAR Progress -------------------------------------->
|
|
6
|
-
<div ref="$playbar-timeline" class="pb-timeline">
|
|
7
|
-
<div ref="$progress-area" class="progress-area">
|
|
8
|
-
<div
|
|
9
|
-
id="progress-bar"
|
|
10
|
-
ref="$progress-bar"
|
|
11
|
-
draggable="false"
|
|
12
|
-
tabindex="0"
|
|
13
|
-
class="v-media pb-progress-bar"
|
|
14
|
-
role="slider"
|
|
15
|
-
aria-valuemin="0"
|
|
16
|
-
:aria-label="mediaA11Y.label"
|
|
17
|
-
:aria-valuenow="mediaA11Y.valNow"
|
|
18
|
-
:aria-valuemax="mediaA11Y.valMax"
|
|
19
|
-
:aria-valuetext="mediaA11Y.valueText"
|
|
20
|
-
@focus="changeFocusState('progressBar', true)"
|
|
21
|
-
@blur="changeFocusState('progressBar', false)"
|
|
22
|
-
>
|
|
23
|
-
<!--Class progress-animation is apply when we are not using the thumb to change the progression-->
|
|
24
|
-
<div
|
|
25
|
-
id="progress-indicator"
|
|
26
|
-
ref="$progress-indicator"
|
|
27
|
-
draggable="false"
|
|
28
|
-
class="progress-indicator"
|
|
29
|
-
:class="{ 'progress-animation': !progressThumbDown }"
|
|
30
|
-
:style="{ width: progressBarPercentage + '%' }"
|
|
31
|
-
>
|
|
32
|
-
<!--Mousedown validate if the thumb is cliqued (if yes, the mouse is follow to modify the progress)
|
|
33
|
-
MouseOver/MouseOut deactivate click event on progressBar if the mouse hovered the thumb-->
|
|
34
|
-
<!-- <div
|
|
35
|
-
ref="$progress-thumb"
|
|
36
|
-
draggable="false"
|
|
37
|
-
class="progress-thumb"
|
|
38
|
-
style="z-index: 9"
|
|
39
|
-
@mousedown="
|
|
40
|
-
savedIsPlaying = isPlaying
|
|
41
|
-
progressThumbDown = true
|
|
42
|
-
"
|
|
43
|
-
@mouseover="progressThumbHover = true"
|
|
44
|
-
@mouseleave="progressThumbHover = false"
|
|
45
|
-
></div> -->
|
|
46
|
-
|
|
47
|
-
<div
|
|
48
|
-
ref="$progress-thumb"
|
|
49
|
-
draggable="false"
|
|
50
|
-
class="progress-thumb"
|
|
51
|
-
style="z-index: 9"
|
|
52
|
-
@mouseover="progressThumbHover = true"
|
|
53
|
-
@mouseleave="progressThumbHover = false"
|
|
54
|
-
></div>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
<div
|
|
58
|
-
v-if="tooTipTimeCode"
|
|
59
|
-
id="seek-tooltip"
|
|
60
|
-
ref="$seek-tooltip"
|
|
61
|
-
aria-hidden="true"
|
|
62
|
-
class="seek-tooltip"
|
|
63
|
-
>
|
|
64
|
-
{{ tooTipTimeCode }}
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
68
|
-
</template>
|
|
69
|
-
|
|
70
|
-
<script>
|
|
71
|
-
import $extendsMedia from '../mixins/$mediaMixins'
|
|
72
|
-
|
|
73
|
-
export default {
|
|
74
|
-
mixins: [$extendsMedia],
|
|
75
|
-
data() {
|
|
76
|
-
return {
|
|
77
|
-
tooTipTimeCode: null
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
mounted() {}
|
|
81
|
-
}
|
|
82
|
-
</script>
|