fcad-core-dragon 2.0.0-beta.9 → 2.0.1-beta.0

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 (64) hide show
  1. package/.editorconfig +33 -33
  2. package/.eslintignore +29 -29
  3. package/.eslintrc.cjs +81 -81
  4. package/CHANGELOG +11 -0
  5. package/README.md +57 -72
  6. package/bk.scss +117 -117
  7. package/package.json +1 -1
  8. package/src/assets/data/onboardingMessages.json +47 -47
  9. package/src/components/AppBase.vue +130 -3
  10. package/src/components/AppBaseErrorDisplay.vue +438 -438
  11. package/src/components/AppBaseFlipCard.vue +84 -84
  12. package/src/components/AppBaseModule.vue +15 -18
  13. package/src/components/AppBasePopover.vue +41 -41
  14. package/src/components/AppCompBranchButtons.vue +5 -5
  15. package/src/components/AppCompInputDropdownNext.vue +1 -1
  16. package/src/components/AppCompInputRadioNext.vue +152 -152
  17. package/src/components/AppCompInputTextToFillNext.vue +171 -171
  18. package/src/components/AppCompJauge.vue +74 -74
  19. package/src/components/AppCompMenuItem.vue +238 -228
  20. package/src/components/AppCompPlayBarProgress.vue +82 -82
  21. package/src/components/AppCompSettingsMenu.vue +172 -172
  22. package/src/components/AppCompTableOfContent.vue +2 -0
  23. package/src/components/AppCompViewDisplay.vue +6 -6
  24. package/src/composables/useQuiz.js +206 -206
  25. package/src/externalComps/ModuleView.vue +22 -22
  26. package/src/externalComps/SummaryView.vue +91 -91
  27. package/src/mixins/$mediaMixins.js +819 -819
  28. package/src/mixins/timerMixin.js +195 -155
  29. package/src/module/stores/appStore.js +3 -3
  30. package/src/module/xapi/ADL.js +0 -1
  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/wrapper.js +0 -1
  55. package/src/module/xapi/xapiStatement.js +444 -444
  56. package/src/plugins/bus.js +8 -8
  57. package/src/plugins/gsap.js +14 -14
  58. package/src/plugins/i18n.js +44 -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 +5 -0
  64. package/src/shared/generalfuncs.js +210 -210
@@ -1,74 +1,74 @@
1
- <template>
2
- <div v-if="!error" class="box-g" :class="state">
3
- <v-progress-linear
4
- class="jauge"
5
- :model-value="value"
6
- :height="12"
7
- :max="maxValue"
8
- aria-hidden="true"
9
- ></v-progress-linear>
10
- <p class="prcnt">{{ getPourcent }} %</p>
11
- </div>
12
- <div v-else>
13
- <div class="warning">
14
- <p class="title">Attention</p>
15
- <p class="info">
16
- Attention les valeurs que vous donnez au composant ne sont pas des
17
- nombres.
18
- </p>
19
- </div>
20
- </div>
21
- </template>
22
- <script>
23
- export default {
24
- props: {
25
- // props Give value to show progress
26
- state: {
27
- type: String,
28
- default: 'started'
29
- },
30
- maxValue: {
31
- type: Number,
32
- default: 100
33
- },
34
- value: { type: Number, default: 0 },
35
- pourcent: { type: Boolean, default: false },
36
- fraction: { type: Boolean, default: false }
37
- },
38
- data() {
39
- return {}
40
- },
41
- computed: {
42
- getPourcent() {
43
- // Calculate on a 100%
44
- let result = (this.value * 100) / this.maxValue
45
- if (result > 100) return 100
46
- else return Math.round(result)
47
- },
48
- error() {
49
- if (typeof this.value != 'number' || typeof this.maxValue != 'number') {
50
- return true
51
- } else {
52
- return false
53
- }
54
- }
55
- },
56
- methods: {}
57
- }
58
- </script>
59
- <style lang="scss">
60
- .box-g {
61
- width: 100%;
62
- display: flex;
63
- flex-direction: row;
64
- flex-wrap: wrap;
65
-
66
- .jauge {
67
- width: 70%;
68
- }
69
-
70
- .prcnt {
71
- margin-left: 10px;
72
- }
73
- }
74
- </style>
1
+ <template>
2
+ <div v-if="!error" class="box-g" :class="state">
3
+ <v-progress-linear
4
+ class="jauge"
5
+ :model-value="value"
6
+ :height="12"
7
+ :max="maxValue"
8
+ aria-hidden="true"
9
+ ></v-progress-linear>
10
+ <p class="prcnt">{{ getPourcent }} %</p>
11
+ </div>
12
+ <div v-else>
13
+ <div class="warning">
14
+ <p class="title">Attention</p>
15
+ <p class="info">
16
+ Attention les valeurs que vous donnez au composant ne sont pas des
17
+ nombres.
18
+ </p>
19
+ </div>
20
+ </div>
21
+ </template>
22
+ <script>
23
+ export default {
24
+ props: {
25
+ // props Give value to show progress
26
+ state: {
27
+ type: String,
28
+ default: 'started'
29
+ },
30
+ maxValue: {
31
+ type: Number,
32
+ default: 100
33
+ },
34
+ value: { type: Number, default: 0 },
35
+ pourcent: { type: Boolean, default: false },
36
+ fraction: { type: Boolean, default: false }
37
+ },
38
+ data() {
39
+ return {}
40
+ },
41
+ computed: {
42
+ getPourcent() {
43
+ // Calculate on a 100%
44
+ let result = (this.value * 100) / this.maxValue
45
+ if (result > 100) return 100
46
+ else return Math.round(result)
47
+ },
48
+ error() {
49
+ if (typeof this.value != 'number' || typeof this.maxValue != 'number') {
50
+ return true
51
+ } else {
52
+ return false
53
+ }
54
+ }
55
+ },
56
+ methods: {}
57
+ }
58
+ </script>
59
+ <style lang="scss">
60
+ .box-g {
61
+ width: 100%;
62
+ display: flex;
63
+ flex-direction: row;
64
+ flex-wrap: wrap;
65
+
66
+ .jauge {
67
+ width: 70%;
68
+ }
69
+
70
+ .prcnt {
71
+ margin-left: 10px;
72
+ }
73
+ }
74
+ </style>
@@ -1,228 +1,238 @@
1
- <!--
2
- @ Description: This component is used to display and create the link's to all the activity creation in module.
3
- @ What it does: Goes trougth all the activity in the router and create a card that open the Table of content (appCompTableOfContent) that display the anchor.Display the title and subtitle enter in menu.json. Must be used with AppCompTableOfContent and AppCompMenu.
4
- -->
5
- <template>
6
- <v-row v-if="activities.length" class="box-msa">
7
- <v-col
8
- v-for="activity of activities"
9
- :key="activity.id"
10
- cols="6"
11
- class="menu-section-activity"
12
- :aria-describedby="activity.id + '-subMenu'"
13
- >
14
- <router-link
15
- :id="activity.id + '-subMenu'"
16
- :title="activity.title"
17
- :data-test="`item-menu-${activity.id}`"
18
- class="btn-menu"
19
- :to="{
20
- name: createRoutes(activity.id)
21
- }"
22
- @click="startActivity(activity)"
23
- >
24
- <div class="menu-card" tag="article">
25
- <v-row>
26
- <div v-if="activity.subtitle === undefined" class="title">
27
- <h4 v-html="activity.title"></h4>
28
- </div>
29
- <div v-else class="title">
30
- <h4 v-html="`${activity.title} : ${activity.subtitle}`"></h4>
31
- </div>
32
-
33
- <div class="cnt-time">
34
- <svg :aria-label="$t('label.timer')">
35
- <use href="#clock-icon" />
36
- </svg>
37
- <p class="time">
38
- {{ activity.time || '00:00' }}
39
- </p>
40
- </div>
41
- <div class="box-gauge">
42
- <app-comp-jauge
43
- :max-value="getActivitySize(activity.id)"
44
- :value="getPageComplete(activity.id)"
45
- />
46
- </div>
47
- </v-row>
48
- </div>
49
- </router-link>
50
- </v-col>
51
- </v-row>
52
- </template>
53
- <script>
54
- // ...
55
- import { mapState } from 'pinia'
56
- import { useAppStore } from '../module/stores/appStore'
57
- import AppCompJauge from './AppCompJauge.vue'
58
- export default {
59
- components: {
60
- AppCompJauge
61
- },
62
- computed: {
63
- ...mapState(useAppStore, [
64
- 'getAllActivities',
65
- 'getAllActivitiesState',
66
- 'getAllCompleted',
67
- 'getAppConfigs',
68
- 'getMenuSettings',
69
- 'getModuleInfo'
70
- ]),
71
- activities() {
72
- // get the data for list of the page for this module from the store and
73
- // get the route of the page from the router to build the menu with its routes
74
- let count = 0
75
- const collection = []
76
-
77
- this.getAllActivities().list.forEach((value, key) => {
78
- let theActivity,
79
- activityTitle,
80
- activitySubTitle,
81
- activityTime = null,
82
- activityPath = ''
83
-
84
- if (this.menuInfo[key]) {
85
- const { title, subTitle, time } = this.menuInfo[key] //get time subTitle time from menu info
86
- //set the title
87
- if (title && title != ' ') activityTitle = title
88
- //set the subtitle
89
- if (subTitle && subTitle != ' ') activitySubTitle = subTitle
90
- //set the time
91
- if (time && time != ' ') activityTime = time
92
- }
93
- // This is the Introduction
94
- if (key === 'A00') {
95
- activityTitle = activityTitle || this.$t('text.introduction')
96
- activityPath = 'introduction'
97
- } else if (key === 'A99') {
98
- activityTitle = activityTitle || this.$t('text.conclusion')
99
- activityPath = 'conclusion'
100
- } else {
101
- count++
102
- activityTitle =
103
- activityTitle || `${this.$t('text.activity')} ${count}`
104
- activityPath = `activite_${count}`
105
- }
106
-
107
- theActivity = {
108
- id: key,
109
- title: activityTitle,
110
- subtitle: activitySubTitle,
111
- time: activityTime,
112
- path: activityPath,
113
- data: value
114
- }
115
-
116
- collection.push(theActivity) // push the activity in the collection
117
- })
118
-
119
- return collection
120
- },
121
- menuInfo() {
122
- let menuInfo = this.getMenuSettings
123
- return menuInfo
124
- }
125
- },
126
- mounted() {},
127
- methods: {
128
- /**
129
- * @description Gives gives length of completed page for an activity
130
- * @param {String} idActivity
131
- * @returns {Number}
132
- */
133
- getPageComplete(idActivity) {
134
- /// give all the page that are complete to the gauge
135
- if (idActivity) {
136
- let completed = []
137
- if (this.getAllCompleted[idActivity]) {
138
- completed = this.getAllCompleted[idActivity] //get all completed page for the activity
139
- }
140
-
141
- return completed.length
142
- }
143
- },
144
- /**
145
- * @description give the size of the state of the activity
146
- * @param {String} activityID
147
- * @returns {Number} size
148
- */
149
- getActivitySize(activityID) {
150
- /*
151
- * Note:
152
- * Assaging by reference would change the property of the getters when the valued are changed in the new object in. * To prevent this behaviour we will make a deep copy of the getter
153
- * cf: https://reactgo.com/javascript-clone-object/
154
- */
155
-
156
- const allActivitiesState = JSON.parse(
157
- JSON.stringify(this.getAllActivitiesState)
158
- )
159
- let size = allActivitiesState[activityID]
160
- ? allActivitiesState[activityID].size
161
- : 0
162
-
163
- return size
164
- },
165
- createRoutes(data) {
166
- let activity
167
-
168
- if (data.charAt(1) == '0' || data.charAt(1) == 0) {
169
- activity = data.substr(2)
170
- } else {
171
- activity = data.substr(1)
172
- }
173
-
174
- if (activity == 0 && activity == '0') return `introduction`
175
- if (activity == '99') return `conclusion`
176
- else return `activite_${activity}`
177
- },
178
- startActivity(a) {
179
- //this.$bus.$emit('send-starting-event', a)
180
- }
181
- }
182
- }
183
- </script>
184
- <style lang="scss">
185
- .menu-card {
186
- width: 100%;
187
- padding: 24px;
188
-
189
- .v-row {
190
- margin: 0;
191
- flex-direction: column;
192
-
193
- .title {
194
- flex-grow: 4;
195
- width: 80%;
196
- margin-bottom: 30px;
197
-
198
- h3 {
199
- text-align: left;
200
- }
201
- }
202
-
203
- .cnt-time {
204
- display: flex;
205
- flex-direction: row;
206
- align-items: center;
207
- margin-bottom: 20px;
208
-
209
- svg {
210
- width: 18px;
211
- height: 18px;
212
- margin-right: 10px;
213
- }
214
- }
215
-
216
- .box-gauge {
217
- display: block;
218
- width: 100%;
219
-
220
- .box-g {
221
- display: flex;
222
- flex-direction: row;
223
- align-items: center;
224
- }
225
- }
226
- }
227
- }
228
- </style>
1
+ <!--
2
+ @ Description: This component is used to display and create the link's to all the activity creation in module.
3
+ @ What it does: Goes trougth all the activity in the router and create a card that open the Table of content (appCompTableOfContent) that display the anchor.Display the title and subtitle enter in menu.json. Must be used with AppCompTableOfContent and AppCompMenu.
4
+ -->
5
+ <template>
6
+ <v-row v-if="activities.length" class="box-msa">
7
+ <v-col
8
+ v-for="activity of activities"
9
+ :key="activity.id"
10
+ cols="6"
11
+ class="menu-section-activity"
12
+ :aria-describedby="activity.id + '-subMenu'"
13
+ >
14
+ <router-link
15
+ :id="activity.id + '-subMenu'"
16
+ :title="activity.title"
17
+ :data-test="`item-menu-${activity.id}`"
18
+ class="btn-menu"
19
+ :to="{
20
+ name: createRoutes(activity.id)
21
+ }"
22
+ @click="startActivity(activity)"
23
+ >
24
+ <div class="menu-card" tag="article">
25
+ <v-row>
26
+ <div v-if="activity.subtitle === undefined" class="title">
27
+ <h4 v-html="activity.title"></h4>
28
+ </div>
29
+ <div v-else class="title">
30
+ <h4
31
+ v-html="
32
+ `${activity.title}${cardTitleSeparator}${activity.subtitle}`
33
+ "
34
+ ></h4>
35
+ </div>
36
+
37
+ <div class="cnt-time">
38
+ <svg :aria-label="$t('label.timer')">
39
+ <use href="#clock-icon" />
40
+ </svg>
41
+ <p class="time">
42
+ {{ activity.time || '00:00' }}
43
+ </p>
44
+ </div>
45
+ <div class="box-gauge">
46
+ <app-comp-jauge
47
+ :max-value="getActivitySize(activity.id)"
48
+ :value="getPageComplete(activity.id)"
49
+ />
50
+ </div>
51
+ </v-row>
52
+ </div>
53
+ </router-link>
54
+ </v-col>
55
+ </v-row>
56
+ </template>
57
+ <script>
58
+ // ...
59
+ import { mapState } from 'pinia'
60
+ import { useAppStore } from '../module/stores/appStore'
61
+ import AppCompJauge from './AppCompJauge.vue'
62
+ export default {
63
+ components: {
64
+ AppCompJauge
65
+ },
66
+ computed: {
67
+ ...mapState(useAppStore, [
68
+ 'getAllActivities',
69
+ 'getAllActivitiesState',
70
+ 'getAllCompleted',
71
+ 'getAppConfigs',
72
+ 'getMenuSettings',
73
+ 'getModuleInfo'
74
+ ]),
75
+ /*
76
+ * Apply different punctuation for colons. No space before a colon in english, one space before a colon in french
77
+ */
78
+ cardTitleSeparator() {
79
+ return this.getAppConfigs.lang === 'en' ? ': ' : ' : '
80
+ },
81
+ activities() {
82
+ // get the data for list of the page for this module from the store and
83
+ // get the route of the page from the router to build the menu with its routes
84
+ let count = 0
85
+ const collection = []
86
+
87
+ this.getAllActivities().list.forEach((value, key) => {
88
+ let theActivity,
89
+ activityTitle,
90
+ activitySubTitle,
91
+ activityTime = null,
92
+ activityPath = ''
93
+
94
+ if (this.menuInfo[key]) {
95
+ const { title, subTitle, time } = this.menuInfo[key] //get time subTitle time from menu info
96
+ //set the title
97
+ if (title && title != ' ') activityTitle = title
98
+ //set the subtitle
99
+ if (subTitle && subTitle != ' ') activitySubTitle = subTitle
100
+ //set the time
101
+ if (time && time != ' ') activityTime = time
102
+ }
103
+ // This is the Introduction
104
+ if (key === 'A00') {
105
+ activityTitle = activityTitle || this.$t('text.introduction')
106
+ activityPath = 'introduction'
107
+ } else if (key === 'A99') {
108
+ activityTitle = activityTitle || this.$t('text.conclusion')
109
+ activityPath = 'conclusion'
110
+ } else {
111
+ count++
112
+ activityTitle =
113
+ activityTitle || `${this.$t('text.activity')} ${count}`
114
+ activityPath = `activite_${count}`
115
+ }
116
+
117
+ theActivity = {
118
+ id: key,
119
+ title: activityTitle,
120
+ subtitle: activitySubTitle,
121
+ time: activityTime,
122
+ path: activityPath,
123
+ data: value
124
+ }
125
+
126
+ collection.push(theActivity) // push the activity in the collection
127
+ })
128
+
129
+ return collection
130
+ },
131
+ menuInfo() {
132
+ let menuInfo = this.getMenuSettings
133
+ return menuInfo
134
+ }
135
+ },
136
+ mounted() {},
137
+ methods: {
138
+ /**
139
+ * @description Gives gives length of completed page for an activity
140
+ * @param {String} idActivity
141
+ * @returns {Number}
142
+ */
143
+ getPageComplete(idActivity) {
144
+ /// give all the page that are complete to the gauge
145
+ if (idActivity) {
146
+ let completed = []
147
+ if (this.getAllCompleted[idActivity]) {
148
+ completed = this.getAllCompleted[idActivity] //get all completed page for the activity
149
+ }
150
+
151
+ return completed.length
152
+ }
153
+ },
154
+ /**
155
+ * @description give the size of the state of the activity
156
+ * @param {String} activityID
157
+ * @returns {Number} size
158
+ */
159
+ getActivitySize(activityID) {
160
+ /*
161
+ * Note:
162
+ * Assaging by reference would change the property of the getters when the valued are changed in the new object in. * To prevent this behaviour we will make a deep copy of the getter
163
+ * cf: https://reactgo.com/javascript-clone-object/
164
+ */
165
+
166
+ const allActivitiesState = JSON.parse(
167
+ JSON.stringify(this.getAllActivitiesState)
168
+ )
169
+ let size = allActivitiesState[activityID]
170
+ ? allActivitiesState[activityID].size
171
+ : 0
172
+
173
+ return size
174
+ },
175
+ createRoutes(data) {
176
+ let activity
177
+
178
+ if (data.charAt(1) == '0' || data.charAt(1) == 0) {
179
+ activity = data.substr(2)
180
+ } else {
181
+ activity = data.substr(1)
182
+ }
183
+
184
+ if (activity == 0 && activity == '0') return `introduction`
185
+ if (activity == '99') return `conclusion`
186
+ else return `activite_${activity}`
187
+ },
188
+ startActivity(a) {
189
+ //this.$bus.$emit('send-starting-event', a)
190
+ }
191
+ }
192
+ }
193
+ </script>
194
+ <style lang="scss">
195
+ .menu-card {
196
+ width: 100%;
197
+ padding: 24px;
198
+
199
+ .v-row {
200
+ margin: 0;
201
+ flex-direction: column;
202
+
203
+ .title {
204
+ flex-grow: 4;
205
+ width: 80%;
206
+ margin-bottom: 30px;
207
+
208
+ h3 {
209
+ text-align: left;
210
+ }
211
+ }
212
+
213
+ .cnt-time {
214
+ display: flex;
215
+ flex-direction: row;
216
+ align-items: center;
217
+ margin-bottom: 20px;
218
+
219
+ svg {
220
+ width: 18px;
221
+ height: 18px;
222
+ margin-right: 10px;
223
+ }
224
+ }
225
+
226
+ .box-gauge {
227
+ display: block;
228
+ width: 100%;
229
+
230
+ .box-g {
231
+ display: flex;
232
+ flex-direction: row;
233
+ align-items: center;
234
+ }
235
+ }
236
+ }
237
+ }
238
+ </style>