fcad-core-dragon 2.0.0-beta.0 → 2.0.0-beta.10
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/.editorconfig +6 -31
- package/.prettierrc +11 -0
- package/.vscode/extensions.json +8 -0
- package/.vscode/settings.json +16 -0
- package/CHANGELOG +153 -0
- package/README.md +28 -43
- package/documentation/.vitepress/config.js +114 -0
- package/documentation/api-examples.md +49 -0
- package/documentation/composants/app-base-button.md +58 -0
- package/documentation/composants/app-base-error-display.md +59 -0
- package/documentation/composants/app-base-popover.md +68 -0
- package/documentation/composants/app-comp-audio.md +75 -0
- package/documentation/composants/app-comp-branch-buttons.md +111 -0
- package/documentation/composants/app-comp-button-progress.md +53 -0
- package/documentation/composants/app-comp-carousel.md +53 -0
- package/documentation/composants/app-comp-container.md +53 -0
- package/documentation/composants/app-comp-input-checkbox-next.md +42 -0
- package/documentation/composants/app-comp-input-dropdown-next.md +34 -0
- package/documentation/composants/app-comp-input-radio-next.md +39 -0
- package/documentation/composants/app-comp-input-text-next.md +35 -0
- package/documentation/composants/app-comp-input-text-table-next.md +34 -0
- package/documentation/composants/app-comp-input-text-to-fill-dropdown-next.md +53 -0
- package/documentation/composants/app-comp-input-text-to-fill-next.md +31 -0
- package/documentation/composants/app-comp-jauge.md +31 -0
- package/documentation/composants/app-comp-menu-item.md +55 -0
- package/documentation/composants/app-comp-menu.md +29 -0
- package/documentation/composants/app-comp-navigation.md +41 -0
- package/documentation/composants/app-comp-note-call.md +53 -0
- package/documentation/composants/app-comp-note-credit.md +53 -0
- package/documentation/composants/app-comp-play-bar-next.md +53 -0
- package/documentation/composants/app-comp-pop-up-next.md +93 -0
- package/documentation/composants/app-comp-quiz-next.md +235 -0
- package/documentation/composants/app-comp-quiz-recall.md +53 -0
- package/documentation/composants/app-comp-svg-next.md +53 -0
- package/documentation/composants/app-comp-table-of-content.md +50 -0
- package/documentation/composants/app-comp-video-player.md +82 -0
- package/documentation/composants.md +46 -0
- package/documentation/composants_critiques/ModelPageComposant.md +53 -0
- package/documentation/composants_critiques/app-base-module.md +43 -0
- package/documentation/composants_critiques/app-base-page.md +48 -0
- package/documentation/composants_critiques/app-base.md +311 -0
- package/documentation/composants_critiques/main.md +15 -0
- package/documentation/demarrage.md +50 -0
- package/documentation/deploiement.md +58 -0
- package/documentation/index.md +33 -0
- package/documentation/markdown-examples.md +85 -0
- package/documentation/public/npm_version.png +0 -0
- package/documentation/public/vite.svg +15 -0
- package/documentation/public/vuejs.svg +2 -0
- package/documentation/public/vuetify.svg +6 -0
- package/eslint.config.js +60 -0
- package/package.json +43 -49
- package/src/$locales/en.json +94 -92
- package/src/$locales/fr.json +77 -113
- package/src/assets/data/onboardingMessages.json +1 -1
- package/src/components/AppBase.vue +971 -437
- package/src/components/AppBaseButton.test.js +21 -0
- package/src/components/AppBaseButton.vue +42 -10
- package/src/components/AppBaseErrorDisplay.vue +209 -162
- package/src/components/AppBaseFlipCard.vue +1 -0
- package/src/components/AppBaseModule.vue +1021 -976
- package/src/components/AppBasePage.vue +656 -128
- package/src/components/AppBasePopover.vue +41 -0
- package/src/components/AppBaseSkeleton.vue +66 -0
- package/src/components/AppCompAudio.vue +256 -0
- package/src/components/AppCompBranchButtons.vue +108 -181
- package/src/components/AppCompButtonProgress.vue +44 -70
- package/src/components/AppCompCarousel.vue +284 -233
- package/src/components/AppCompContainer.vue +29 -0
- package/src/components/AppCompInputCheckBoxNx.vue +323 -0
- package/src/components/AppCompInputDropdownNx.vue +299 -0
- package/src/components/AppCompInputRadioNx.vue +284 -0
- package/src/components/AppCompInputTextNx.vue +153 -0
- package/src/components/AppCompInputTextTableNx.vue +202 -0
- package/src/components/AppCompInputTextToFillDropdownNx.vue +340 -0
- package/src/components/AppCompInputTextToFillNx.vue +313 -0
- package/src/components/AppCompJauge.vue +36 -11
- package/src/components/AppCompMenu.vue +312 -92
- package/src/components/AppCompMenuItem.vue +129 -105
- package/src/components/AppCompNavigation.vue +972 -0
- package/src/components/AppCompNoteCall.vue +161 -0
- package/src/components/AppCompNoteCredit.vue +491 -0
- package/src/components/AppCompPlayBarNext.vue +2288 -0
- package/src/components/AppCompPopUpNext.vue +504 -0
- package/src/components/AppCompQuizNext.vue +510 -0
- package/src/components/AppCompQuizRecall.vue +350 -0
- package/src/components/AppCompSVGNext.vue +346 -0
- package/src/components/AppCompSettingsMenu.vue +18 -16
- package/src/components/AppCompTableOfContent.vue +340 -122
- package/src/components/AppCompVideoPlayer.vue +377 -0
- package/src/components/BaseModule.vue +24 -117
- package/src/components/tests__/AppBaseButton.spec.js +53 -0
- package/src/components/tests__/useTimer.spec.js +91 -0
- package/src/composables/useIdleDetector.js +56 -0
- package/src/composables/useQuiz.js +89 -0
- package/src/composables/useTimer.js +172 -0
- package/src/directives/nvdaFix.js +53 -0
- package/src/externalComps/ModuleView.vue +22 -0
- package/src/externalComps/SummaryView.vue +91 -0
- package/src/main.js +400 -142
- package/src/module/stores/appStore.js +947 -0
- package/src/module/xapi/ADL.js +241 -60
- package/src/module/xapi/Crypto/Hasher.js +8 -8
- package/src/module/xapi/Crypto/WordArray.js +6 -6
- package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +4 -4
- package/src/module/xapi/Crypto/algorithms/C_algo.js +14 -18
- package/src/module/xapi/Crypto/algorithms/HMAC.js +1 -1
- package/src/module/xapi/Crypto/algorithms/SHA1.js +1 -1
- package/src/module/xapi/Crypto/encoders/Base.js +7 -7
- package/src/module/xapi/Crypto/encoders/Base64.js +3 -3
- package/src/module/xapi/Crypto/encoders/Hex.js +4 -3
- package/src/module/xapi/Crypto/encoders/Latin1.js +3 -3
- package/src/module/xapi/Crypto/encoders/Utf8.js +3 -3
- package/src/module/xapi/Statement/index.js +3 -3
- package/src/module/xapi/launch.js +10 -10
- package/src/module/xapi/utils.js +17 -17
- package/src/module/xapi/wrapper.js +223 -218
- package/src/module/xapi/xapiStatement.js +29 -29
- package/src/plugins/analytics.js +34 -0
- package/src/plugins/bus.js +7 -2
- package/src/plugins/gsap.js +9 -8
- package/src/plugins/helper.js +141 -43
- package/src/plugins/i18n.js +13 -18
- package/src/plugins/idb.js +46 -30
- package/src/plugins/save.js +1 -1
- package/src/plugins/scorm.js +15 -15
- package/src/plugins/xapi.js +2 -2
- package/src/public/index.html +23 -11
- package/src/router/index.js +57 -0
- package/src/router/routes.js +312 -0
- package/src/shared/generalfuncs.js +241 -10
- package/src/shared/validators.js +1018 -0
- package/vitest.config.js +19 -0
- package/.eslintignore +0 -29
- package/.eslintrc.js +0 -86
- package/.prettierrc.js +0 -5
- package/babel.config.js +0 -3
- package/src/components/AppBaseDragChoice.vue +0 -91
- package/src/components/AppBaseDropZone.vue +0 -112
- package/src/components/AppCompDragAndDrop.vue +0 -339
- package/src/components/AppCompInputAssociation.vue +0 -332
- package/src/components/AppCompInputCheckBox.vue +0 -227
- package/src/components/AppCompInputDropdown.vue +0 -184
- package/src/components/AppCompInputRadio.vue +0 -169
- package/src/components/AppCompInputTextBox.vue +0 -91
- package/src/components/AppCompInputTextTable.vue +0 -155
- package/src/components/AppCompInputTextToFillDropdown.vue +0 -255
- package/src/components/AppCompInputTextToFillText.vue +0 -164
- package/src/components/AppCompMediaPlayer.vue +0 -365
- package/src/components/AppCompNavigationFull.vue +0 -1791
- package/src/components/AppCompPlayBar.vue +0 -1540
- package/src/components/AppCompPopUp.vue +0 -523
- package/src/components/AppCompQuiz.vue +0 -2998
- package/src/components/AppCompToolTip.vue +0 -94
- package/src/mixins/$pageMixins.js +0 -381
- package/src/mixins/$quizMixins.js +0 -456
- package/src/mixins/timerMixin.js +0 -132
- package/src/module/store.js +0 -874
- package/src/plugins/timeManager.js +0 -77
- package/src/routes.js +0 -734
- package/vue.config.js +0 -83
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@ Description:
|
|
3
|
+
@ What it does:
|
|
4
|
+
-->
|
|
5
|
+
<template>
|
|
6
|
+
<div
|
|
7
|
+
:id="`rnt_${pageRef}__${stripRefNote}`"
|
|
8
|
+
:ref="`#rnt_${stripRefNote}`"
|
|
9
|
+
:data-ref="`nt_${pageRef}__${stripRefNote}`"
|
|
10
|
+
class="callEndNote"
|
|
11
|
+
>
|
|
12
|
+
<button
|
|
13
|
+
v-if="!error"
|
|
14
|
+
class="nrlm"
|
|
15
|
+
tabindex="0"
|
|
16
|
+
:title="$t('text.title_link_call')"
|
|
17
|
+
:aria-label="`${$t('label.note_reference')} ${stripRefNote}`"
|
|
18
|
+
@click="openNote()"
|
|
19
|
+
>
|
|
20
|
+
<sup>{{ stripRefNote }}</sup>
|
|
21
|
+
</button>
|
|
22
|
+
|
|
23
|
+
<div v-else class="nrlm error-Nc" tabindex="0">
|
|
24
|
+
<sup>{{ $t('text.error') }}</sup>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
<script>
|
|
29
|
+
import { mapState } from 'pinia'
|
|
30
|
+
import { useAppStore } from '../module/stores/appStore'
|
|
31
|
+
export default {
|
|
32
|
+
props: {
|
|
33
|
+
refNote: {
|
|
34
|
+
type: String,
|
|
35
|
+
default: ' '
|
|
36
|
+
},
|
|
37
|
+
pageRef: {
|
|
38
|
+
type: String,
|
|
39
|
+
default: ' '
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
data() {
|
|
43
|
+
return {
|
|
44
|
+
notes: null
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
computed: {
|
|
48
|
+
...mapState(useAppStore, ['getNotes', 'getWidgetOpen']),
|
|
49
|
+
// Return the number for the note
|
|
50
|
+
stripRefNote() {
|
|
51
|
+
let newRef
|
|
52
|
+
|
|
53
|
+
let ref = this.refNote
|
|
54
|
+
let toStrip = ref.indexOf('_')
|
|
55
|
+
newRef = this.refNote.substr(toStrip + 1)
|
|
56
|
+
return newRef
|
|
57
|
+
},
|
|
58
|
+
linkedNote() {
|
|
59
|
+
const _notes = this.getNotes(
|
|
60
|
+
this.$route.meta.activity_ref,
|
|
61
|
+
this.$route.meta.id
|
|
62
|
+
)
|
|
63
|
+
if (!_notes) return null
|
|
64
|
+
let thisPageNotes = null
|
|
65
|
+
|
|
66
|
+
for (let p of _notes) {
|
|
67
|
+
//find the related page and get its notes
|
|
68
|
+
if (Object.keys(p)[0] !== this.pageRef) continue
|
|
69
|
+
thisPageNotes = p[this.pageRef]
|
|
70
|
+
}
|
|
71
|
+
//return weither the note exist or note
|
|
72
|
+
return thisPageNotes && thisPageNotes.find((n) => n.id == this.refNote)
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
error() {
|
|
76
|
+
let err = false
|
|
77
|
+
if (!this.linkedNote) {
|
|
78
|
+
err = true
|
|
79
|
+
console.warn(
|
|
80
|
+
`%c WARNING!>>> AppCompNoteCall: cette note n'existe pas nt_${this.pageRef}__${this.stripRefNote}.`,
|
|
81
|
+
'background: orange; color: white; display: block; margin:5px;'
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
return err
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
beforeUnmount() {
|
|
88
|
+
this.$bus.$off('close-widget', this.onCloseWidget)
|
|
89
|
+
this.$bus.$off('credit-note', this.onCreditNote)
|
|
90
|
+
},
|
|
91
|
+
mounted() {
|
|
92
|
+
this.$bus.$on('close-widget', this.onCloseWidget)
|
|
93
|
+
this.$bus.$on('credit-note', this.onCreditNote)
|
|
94
|
+
},
|
|
95
|
+
methods: {
|
|
96
|
+
onCreditNote(data) {
|
|
97
|
+
this.notes = data.note
|
|
98
|
+
},
|
|
99
|
+
onCloseWidget() {
|
|
100
|
+
let el = document.getElementsByClassName('callEndNote')
|
|
101
|
+
|
|
102
|
+
for (let element of el) {
|
|
103
|
+
element.setAttribute('datacurrentnote', false)
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
//open the widget and give information to highlight
|
|
107
|
+
openNote() {
|
|
108
|
+
if (!this.getWidgetOpen) {
|
|
109
|
+
this.$bus.$emit('open-notes')
|
|
110
|
+
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
this.$bus.$emit('note-to-show', this.$el)
|
|
113
|
+
|
|
114
|
+
let e = document.getElementsByClassName('callEndNote')
|
|
115
|
+
let t = this.$el.getAttribute('id')
|
|
116
|
+
|
|
117
|
+
for (let element of e) {
|
|
118
|
+
element.setAttribute('dataCurrentnote', false)
|
|
119
|
+
if (element.id === t) {
|
|
120
|
+
element.setAttribute('dataCurrentnote', true)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}, 200)
|
|
124
|
+
} else {
|
|
125
|
+
this.$bus.$emit('close-widget')
|
|
126
|
+
this.$bus.$emit('note-to-show', this.$el)
|
|
127
|
+
let e = document.getElementsByClassName('callEndNote')
|
|
128
|
+
let t = this.$el.getAttribute('id')
|
|
129
|
+
|
|
130
|
+
for (let element of e) {
|
|
131
|
+
element.setAttribute('dataCurrentnote', false)
|
|
132
|
+
if (element.id === t) {
|
|
133
|
+
element.setAttribute('dataCurrentnote', true)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
lookForElement(elId) {
|
|
140
|
+
let clcn = document.getElementsByClassName('endNoteLink')
|
|
141
|
+
|
|
142
|
+
for (let element of clcn) {
|
|
143
|
+
if (element.id === elId) {
|
|
144
|
+
return element
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
</script>
|
|
151
|
+
<style lang="scss">
|
|
152
|
+
.callEndNote {
|
|
153
|
+
display: inline-block;
|
|
154
|
+
margin-left: -4px;
|
|
155
|
+
|
|
156
|
+
.error-Nc {
|
|
157
|
+
color: red;
|
|
158
|
+
font-weight: bold;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
</style>
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
----------------- MUST ADD ERROR GESTION ------------------
|
|
3
|
+
----------------- MUST ADD css ------------------
|
|
4
|
+
|
|
5
|
+
@ Description:
|
|
6
|
+
@ What it does:
|
|
7
|
+
-->
|
|
8
|
+
<template>
|
|
9
|
+
<div id="noteCredit" :class="{ openW: showWidget }">
|
|
10
|
+
<app-base-button
|
|
11
|
+
id="close-nc"
|
|
12
|
+
:title="$t('button.closePopUp')"
|
|
13
|
+
:aria-label="$t('button.closePopUp')"
|
|
14
|
+
@click="close()"
|
|
15
|
+
>
|
|
16
|
+
<svg aria-hidden="true" focusable="false">
|
|
17
|
+
<use href="#close-square-icon" />
|
|
18
|
+
</svg>
|
|
19
|
+
</app-base-button>
|
|
20
|
+
<div class="box-nc">
|
|
21
|
+
<app-base-error-display
|
|
22
|
+
v-if="errorData.length"
|
|
23
|
+
:error-group="'component'"
|
|
24
|
+
:error-title="'ERREUR: NOTES ET CREDITS'"
|
|
25
|
+
:errors-list="errorData"
|
|
26
|
+
:error-text="`Vous avez une/des erreur(s) dans la création des notes/crédits.`"
|
|
27
|
+
></app-base-error-display>
|
|
28
|
+
<template v-else>
|
|
29
|
+
<div v-if="notes" class="ctn-note">
|
|
30
|
+
<p class="t-note">{{ $t('text.title_note') }}</p>
|
|
31
|
+
<div id="notes-list">
|
|
32
|
+
<template
|
|
33
|
+
v-for="(note, index) of notes"
|
|
34
|
+
:key="`nt_${note.page_ref}__${note.id.substring(3)}`"
|
|
35
|
+
>
|
|
36
|
+
<div class="note-item">
|
|
37
|
+
<span>{{ index + 1 }}.</span>
|
|
38
|
+
<app-base-button
|
|
39
|
+
:id="`nt_${note.page_ref}__${note.id.substring(3)}`"
|
|
40
|
+
type="button"
|
|
41
|
+
:title="$t('text.title_link_bas')"
|
|
42
|
+
class="backToNoteRef"
|
|
43
|
+
:data-ref="`rnt_${note.page_ref}__${note.id.substring(3)}`"
|
|
44
|
+
:note-ref="`rnt_${note.page_ref}__${note.id.substring(3)}`"
|
|
45
|
+
:pageref="note.page_ref"
|
|
46
|
+
:class="
|
|
47
|
+
note.hasError ? 'widget-note note-error' : 'widget-note'
|
|
48
|
+
"
|
|
49
|
+
@click="
|
|
50
|
+
handleNoteDisplay(
|
|
51
|
+
`nt_${note.page_ref}__${note.id.substring(3)}`
|
|
52
|
+
)
|
|
53
|
+
"
|
|
54
|
+
>
|
|
55
|
+
<div
|
|
56
|
+
class="btref-content"
|
|
57
|
+
data-content=""
|
|
58
|
+
v-html="`${note.text}`"
|
|
59
|
+
></div>
|
|
60
|
+
</app-base-button>
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
<div v-if="credits" class="ctn-credit">
|
|
66
|
+
<p class="t-crdt">{{ $t('text.title_credit') }}</p>
|
|
67
|
+
|
|
68
|
+
<ul id="credits-list">
|
|
69
|
+
<li
|
|
70
|
+
v-for="(credit, index) of credits"
|
|
71
|
+
:key="`credit_${index + 1}`"
|
|
72
|
+
:ref="`#nt_${index + 1}`"
|
|
73
|
+
v-html="credit"
|
|
74
|
+
></li>
|
|
75
|
+
</ul>
|
|
76
|
+
</div>
|
|
77
|
+
</template>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</template>
|
|
81
|
+
<script>
|
|
82
|
+
import { mapState, mapActions } from 'pinia'
|
|
83
|
+
import { useAppStore } from '../module/stores/appStore'
|
|
84
|
+
import { validateObjType } from '../shared/validators'
|
|
85
|
+
|
|
86
|
+
export default {
|
|
87
|
+
props: {},
|
|
88
|
+
data() {
|
|
89
|
+
return {
|
|
90
|
+
current: false,
|
|
91
|
+
showWidget: false,
|
|
92
|
+
sideBarIsOpen: null,
|
|
93
|
+
prevNote: null,
|
|
94
|
+
shouldDeactivate: false,
|
|
95
|
+
errorData: [],
|
|
96
|
+
notes: null,
|
|
97
|
+
credits: null
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
computed: {
|
|
101
|
+
...mapState(useAppStore, [
|
|
102
|
+
'getDataNoteCredit',
|
|
103
|
+
'getAllActivities',
|
|
104
|
+
'getCurrentPage',
|
|
105
|
+
'getNotes',
|
|
106
|
+
'getCredits'
|
|
107
|
+
])
|
|
108
|
+
},
|
|
109
|
+
created() {},
|
|
110
|
+
beforeUnmount() {
|
|
111
|
+
this.$bus.$off('credit-note', this.onCreditNote)
|
|
112
|
+
this.$bus.$off('toggle-widget', this.onToggleWidget)
|
|
113
|
+
this.$bus.$off('close-widget', this.close)
|
|
114
|
+
this.$bus.$off('note-to-show', this.onNoteToShow)
|
|
115
|
+
this.$bus.$off('side-bar-open', this.onSidebarVisible)
|
|
116
|
+
},
|
|
117
|
+
mounted() {
|
|
118
|
+
// close or open widget depending which btn was click
|
|
119
|
+
this.$bus.$on('toggle-widget', this.onToggleWidget)
|
|
120
|
+
//close widget
|
|
121
|
+
this.$bus.$on('close-widget', this.close)
|
|
122
|
+
// show widget when note click and higligth note
|
|
123
|
+
this.$bus.$on('note-to-show', this.onNoteToShow)
|
|
124
|
+
this.$bus.$on('side-bar-open', this.onSidebarVisible)
|
|
125
|
+
},
|
|
126
|
+
methods: {
|
|
127
|
+
...mapActions(useAppStore, ['updateWidgetOpen']),
|
|
128
|
+
getPageNotes(data) {
|
|
129
|
+
if (!data) return
|
|
130
|
+
const _notes = data
|
|
131
|
+
let formatedNotes = []
|
|
132
|
+
_notes.forEach((g) => {
|
|
133
|
+
let count = 0
|
|
134
|
+
Object.values(g)[0].map((n) => {
|
|
135
|
+
count++
|
|
136
|
+
if (
|
|
137
|
+
this.validateData('note', {
|
|
138
|
+
n,
|
|
139
|
+
details: `${count} ${Object.keys(g)[0]} `
|
|
140
|
+
})
|
|
141
|
+
)
|
|
142
|
+
return
|
|
143
|
+
n['page_ref'] = `${Object.keys(g)[0]}`
|
|
144
|
+
})
|
|
145
|
+
//Add all the note to the temp array
|
|
146
|
+
formatedNotes.push(...Object.values(g)[0])
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
return formatedNotes
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
getPageCredits(data) {
|
|
153
|
+
if (!data) return
|
|
154
|
+
|
|
155
|
+
let credits = data
|
|
156
|
+
let count = 0
|
|
157
|
+
for (const c of credits) {
|
|
158
|
+
count++
|
|
159
|
+
if (this.validateData('credit', { c, details: count })) return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return credits
|
|
163
|
+
},
|
|
164
|
+
setPageNotesAndCredits(data) {
|
|
165
|
+
const { notes, credits } = data
|
|
166
|
+
this.notes = this.getPageNotes(notes)
|
|
167
|
+
this.credits = this.getPageCredits(credits)
|
|
168
|
+
},
|
|
169
|
+
/**
|
|
170
|
+
* @description method to validate that the data for the note and credit.
|
|
171
|
+
* @param {String} ctx context of the validation : credit | note.
|
|
172
|
+
* @param {String| Object} data the data to be validate- Object type for note and String type for credit
|
|
173
|
+
* @return {boolean}
|
|
174
|
+
*/
|
|
175
|
+
validateData(ctx, data) {
|
|
176
|
+
let errConsole = []
|
|
177
|
+
if (this.errorData.length) this.errorData = [] //reset the error tracker
|
|
178
|
+
|
|
179
|
+
switch (ctx) {
|
|
180
|
+
case 'note': {
|
|
181
|
+
if (data.constructor !== Object) {
|
|
182
|
+
this.errorData.push(
|
|
183
|
+
"Mauvais d'éclaration de la note. Doit être de type <i>Objet</i>"
|
|
184
|
+
)
|
|
185
|
+
throw Error(
|
|
186
|
+
`Unexpected definition the note. Expecting Object but received ${typeof data}`
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
let stringType = ['id', 'text'] //expected attribute in the note declaration
|
|
191
|
+
|
|
192
|
+
let { errorInConsole, errorList } = validateObjType(
|
|
193
|
+
data.n,
|
|
194
|
+
{
|
|
195
|
+
stringType
|
|
196
|
+
},
|
|
197
|
+
null,
|
|
198
|
+
`Note ${data.details}`
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
if (errorInConsole.length) errConsole.push(...errorInConsole)
|
|
202
|
+
if (errorList.length) this.errorData.push(...errorList)
|
|
203
|
+
break
|
|
204
|
+
}
|
|
205
|
+
case 'credit':
|
|
206
|
+
if (data.c.constructor !== String) {
|
|
207
|
+
this.errorData.push(
|
|
208
|
+
`Mauvaise déclaration du <b>crédit ${data.details}</b>. Doit être de type <i>String</i>`
|
|
209
|
+
)
|
|
210
|
+
console.warn(
|
|
211
|
+
`\n 💥 Invalid type declaration for 👉\x1B[1mcredit ${data.details} 👈\x1B[0m. Expecting type String \uD83D\uDEABtype ${typeof data.c}`
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (errConsole.length) {
|
|
216
|
+
errConsole.forEach((err) => console.warn(err))
|
|
217
|
+
}
|
|
218
|
+
return this.errorData.length
|
|
219
|
+
},
|
|
220
|
+
onNoteToShow(el) {
|
|
221
|
+
this.showWidget = true
|
|
222
|
+
this.updateWidgetOpen(true)
|
|
223
|
+
|
|
224
|
+
if (el) {
|
|
225
|
+
let ref = el.getAttribute('data-Ref')
|
|
226
|
+
|
|
227
|
+
const reg1 = /.*(P\d{2}(_E\d{2})?).*/gm //reg for the content of data-ref
|
|
228
|
+
const id = `$1`
|
|
229
|
+
const pageRef = ref.replace(reg1, id) //replace all to page id
|
|
230
|
+
|
|
231
|
+
if (this.sideBarIsOpen && pageRef.length == 3)
|
|
232
|
+
this.$bus.$emit('close-sidebar', 'ctxBranching') //send close signal if sibebar is open and note to focus is in parent page
|
|
233
|
+
|
|
234
|
+
this.removehighlight()
|
|
235
|
+
|
|
236
|
+
let elAtt = document.getElementsByClassName('widget-note')
|
|
237
|
+
let arr = Array.from(elAtt)
|
|
238
|
+
|
|
239
|
+
for (let element of arr) {
|
|
240
|
+
if (ref == element.getAttribute('id')) {
|
|
241
|
+
element.setAttribute('datacurrent', true)
|
|
242
|
+
element.focus()
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
onToggleWidget(data) {
|
|
249
|
+
if (data.type !== 'noteCredit') return (this.showWidget = false)
|
|
250
|
+
const { notes, credits } = data.content
|
|
251
|
+
|
|
252
|
+
this.setPageNotesAndCredits({ notes, credits })
|
|
253
|
+
this.showWidget = !this.showWidget
|
|
254
|
+
this.updateWidgetOpen(this.showWidget) //update data in store
|
|
255
|
+
},
|
|
256
|
+
close() {
|
|
257
|
+
let elNote = document.getElementsByClassName('widget-note')
|
|
258
|
+
let elCall = document.getElementsByClassName('callEndNote')
|
|
259
|
+
|
|
260
|
+
let arrNote = Array.from(elNote)
|
|
261
|
+
let arrCall = Array.from(elCall)
|
|
262
|
+
|
|
263
|
+
for (let element of arrNote) {
|
|
264
|
+
element.setAttribute('datacurrent', false)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
for (let element of arrCall) {
|
|
268
|
+
element.setAttribute('datacurrentnote', false)
|
|
269
|
+
}
|
|
270
|
+
this.showWidget = false
|
|
271
|
+
this.updateWidgetOpen(false)
|
|
272
|
+
},
|
|
273
|
+
removehighlight() {
|
|
274
|
+
let elAtt = document.querySelectorAll("[datacurrent='true']")
|
|
275
|
+
|
|
276
|
+
let arr = Array.from(elAtt)
|
|
277
|
+
|
|
278
|
+
for (let element of arr) {
|
|
279
|
+
element.setAttribute('datacurrent', false)
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
focusNote(el, page) {
|
|
284
|
+
this.remove()
|
|
285
|
+
const DOMPages = document.getElementsByClassName(`app-page`)
|
|
286
|
+
const targetPage = DOMPages.namedItem(page) //get the desired page
|
|
287
|
+
|
|
288
|
+
let e = document.getElementsByClassName('callEndNote')
|
|
289
|
+
|
|
290
|
+
if (!targetPage) return
|
|
291
|
+
let nts = targetPage.getElementsByClassName('callEndNote')
|
|
292
|
+
|
|
293
|
+
let t = el.getAttribute('note-ref')
|
|
294
|
+
let s = document.querySelectorAll(`[data-ref="${t}"]`)
|
|
295
|
+
|
|
296
|
+
if (s && s[0]) s[0].setAttribute('datacurrent', true)
|
|
297
|
+
|
|
298
|
+
for (let element of e) {
|
|
299
|
+
element.setAttribute('datacurrentnote', false) //reset the data attribute of all notes
|
|
300
|
+
}
|
|
301
|
+
let targetNote = nts.namedItem(t)
|
|
302
|
+
|
|
303
|
+
if (targetNote) {
|
|
304
|
+
targetNote.setAttribute('datacurrentnote', true)
|
|
305
|
+
|
|
306
|
+
targetNote.childNodes[0].focus()
|
|
307
|
+
} else {
|
|
308
|
+
el.setAttribute('aria-disabled', 'true')
|
|
309
|
+
el.setAttribute('disabled', 'true')
|
|
310
|
+
el.querySelector('.btref-content').setAttribute(
|
|
311
|
+
'data-content',
|
|
312
|
+
'\u26A0\uFE0F'
|
|
313
|
+
)
|
|
314
|
+
el.querySelector('div').style =
|
|
315
|
+
'color:red; text-decoration:line-through;'
|
|
316
|
+
el.style.color = 'red'
|
|
317
|
+
|
|
318
|
+
el.removeEventListener('click', this.handleNoteDisplay)
|
|
319
|
+
}
|
|
320
|
+
this.prevNote = el
|
|
321
|
+
},
|
|
322
|
+
|
|
323
|
+
remove() {
|
|
324
|
+
let e = document.getElementsByClassName('widget-note')
|
|
325
|
+
for (let element of e) {
|
|
326
|
+
element.setAttribute('datacurrent', false)
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
onSidebarVisible(state) {
|
|
331
|
+
this.sideBarIsOpen = state
|
|
332
|
+
},
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* @description method handle the behavior of note displaying
|
|
336
|
+
* @param {Object} evt - the event that trigger the action
|
|
337
|
+
* @emits event - 'open-sidebar' to display notes in branch | 'close-sidebar' to display not in parent when branch open
|
|
338
|
+
*
|
|
339
|
+
*/
|
|
340
|
+
handleNoteDisplay(ref) {
|
|
341
|
+
/*
|
|
342
|
+
* Note:
|
|
343
|
+
* Element target (button) is wrongly referenced when Screen-reader is active and element selected With TAB
|
|
344
|
+
* The Div in the button is selected not the button.
|
|
345
|
+
* This ensure that the button is always set as targeted element
|
|
346
|
+
*/
|
|
347
|
+
const widgetContent = document.getElementsByClassName('backToNoteRef') //target all the button of in the notes widget
|
|
348
|
+
const elTarget = widgetContent.namedItem(ref) // Target current button
|
|
349
|
+
const pageRef = elTarget.getAttribute('pageref')
|
|
350
|
+
|
|
351
|
+
if (!this.sideBarIsOpen) this.prevNote = null //reset previous when sidebar is opened
|
|
352
|
+
|
|
353
|
+
let prevPageref = this.prevNote
|
|
354
|
+
? this.prevNote.getAttribute('pageref')
|
|
355
|
+
: null
|
|
356
|
+
|
|
357
|
+
switch (true) {
|
|
358
|
+
case pageRef && pageRef.length > 3: {
|
|
359
|
+
//this is the branching page Send message to open the side bar
|
|
360
|
+
this.$bus.$emit('open-sidebar', {
|
|
361
|
+
ctx: 'ctxBranching',
|
|
362
|
+
e: pageRef,
|
|
363
|
+
persist: this.sideBarIsOpen || pageRef == prevPageref //this will prevent the sidebar to close when the note is in same page
|
|
364
|
+
})
|
|
365
|
+
//Should set focus after side bar is opened. Need to delay to not interfere with side bar focus
|
|
366
|
+
pageRef == prevPageref
|
|
367
|
+
? setTimeout(() => this.focusNote(elTarget, pageRef), 100)
|
|
368
|
+
: setTimeout(() => this.focusNote(elTarget, pageRef), 400)
|
|
369
|
+
|
|
370
|
+
break
|
|
371
|
+
}
|
|
372
|
+
default:
|
|
373
|
+
//Should have the side bar close if it is opened and note is in parent page
|
|
374
|
+
if (this.sideBarIsOpen && pageRef.length == 3)
|
|
375
|
+
this.$bus.$emit('close-sidebar', 'ctxBranching')
|
|
376
|
+
|
|
377
|
+
return setTimeout(() => this.focusNote(elTarget, pageRef), 100) //Need to delay to not have side bar close animation finished
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
this.prevNote = elTarget
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
</script>
|
|
385
|
+
<style lang="scss">
|
|
386
|
+
#noteCredit {
|
|
387
|
+
display: none;
|
|
388
|
+
pointer-events: none;
|
|
389
|
+
position: absolute;
|
|
390
|
+
left: 75px;
|
|
391
|
+
top: 0;
|
|
392
|
+
width: 419px;
|
|
393
|
+
transition: left 0.5s ease-in-out;
|
|
394
|
+
|
|
395
|
+
&.openW {
|
|
396
|
+
pointer-events: all;
|
|
397
|
+
display: block;
|
|
398
|
+
opacity: 1;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
#close-nc {
|
|
402
|
+
padding: 11px;
|
|
403
|
+
position: absolute;
|
|
404
|
+
right: 24px;
|
|
405
|
+
margin-bottom: 0;
|
|
406
|
+
|
|
407
|
+
&:focus {
|
|
408
|
+
box-shadow: inherit !important;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// .note-txt {
|
|
413
|
+
// pointer-events: none;
|
|
414
|
+
// }
|
|
415
|
+
|
|
416
|
+
.box-nc {
|
|
417
|
+
margin-top: 54px;
|
|
418
|
+
overflow-y: auto;
|
|
419
|
+
min-height: 160px;
|
|
420
|
+
max-height: 321px;
|
|
421
|
+
padding-right: 26px;
|
|
422
|
+
|
|
423
|
+
.t-note {
|
|
424
|
+
margin-bottom: 8px;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
#notes-list {
|
|
428
|
+
.note-item {
|
|
429
|
+
display: flex;
|
|
430
|
+
flex-direction: row;
|
|
431
|
+
flex-wrap: wrap;
|
|
432
|
+
margin-bottom: 5px;
|
|
433
|
+
|
|
434
|
+
color: #deeff8;
|
|
435
|
+
|
|
436
|
+
span {
|
|
437
|
+
font-size: 0.65rem;
|
|
438
|
+
padding: 8px 0 0 0;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.backToNoteRef {
|
|
442
|
+
width: 90%;
|
|
443
|
+
margin-left: 5px;
|
|
444
|
+
padding-left: 5px;
|
|
445
|
+
|
|
446
|
+
.btref-content {
|
|
447
|
+
text-align: left;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
#credits-list {
|
|
455
|
+
list-style-type: none;
|
|
456
|
+
padding: 0;
|
|
457
|
+
margin: 0;
|
|
458
|
+
}
|
|
459
|
+
#notes-list {
|
|
460
|
+
padding: 0;
|
|
461
|
+
margin: 0;
|
|
462
|
+
|
|
463
|
+
.widget-note {
|
|
464
|
+
padding: 5px 0;
|
|
465
|
+
|
|
466
|
+
&.note-error {
|
|
467
|
+
background-color: firebrick;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.btref-content {
|
|
471
|
+
pointer-events: none;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
.overlay-w {
|
|
476
|
+
width: 100%;
|
|
477
|
+
height: 100%;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.app-nav {
|
|
482
|
+
&.show,
|
|
483
|
+
&:hover {
|
|
484
|
+
.ctn-w {
|
|
485
|
+
#noteCredit {
|
|
486
|
+
left: 120px;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
</style>
|