@coorpacademy/app-review 0.1.9 → 0.1.11
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/es/actions/ui/navigation.d.ts +1 -1
- package/es/fixtures/qcm-slide.js +1 -1
- package/es/helpers/map-api-slide-to-ui.d.ts +8 -0
- package/es/helpers/map-api-slide-to-ui.js +175 -0
- package/es/helpers/test/fixtures/free-text.d.ts +4 -0
- package/es/helpers/test/fixtures/free-text.js +24 -0
- package/es/helpers/test/fixtures/qcm-drag.d.ts +4 -0
- package/es/helpers/test/fixtures/qcm-drag.js +106 -0
- package/es/helpers/test/fixtures/qcm-graphic.d.ts +4 -0
- package/es/helpers/test/fixtures/qcm-graphic.js +70 -0
- package/es/helpers/test/fixtures/qcm.d.ts +4 -0
- package/es/helpers/test/fixtures/qcm.js +99 -0
- package/es/helpers/test/fixtures/select-template.d.ts +4 -0
- package/es/helpers/test/fixtures/select-template.js +88 -0
- package/es/helpers/test/fixtures/slider.d.ts +4 -0
- package/es/helpers/test/fixtures/slider.js +27 -0
- package/es/helpers/test/fixtures/text-template.d.ts +4 -0
- package/es/helpers/test/fixtures/text-template.js +48 -0
- package/es/helpers/test/map-api-slide-to-ui.test.d.ts +1 -0
- package/es/helpers/test/map-api-slide-to-ui.test.js +32 -0
- package/es/index.js +29 -9
- package/es/reducers/ui/navigation.d.ts +1 -1
- package/es/test/index.test.js +18 -15
- package/es/test/util/services.mock.js +2 -32
- package/es/types/common.d.ts +62 -5
- package/es/types/slides.d.ts +27 -16
- package/lib/actions/ui/navigation.d.ts +1 -1
- package/lib/fixtures/qcm-slide.js +1 -1
- package/lib/helpers/map-api-slide-to-ui.d.ts +8 -0
- package/lib/helpers/map-api-slide-to-ui.js +181 -0
- package/lib/helpers/test/fixtures/free-text.d.ts +4 -0
- package/lib/helpers/test/fixtures/free-text.js +24 -0
- package/lib/helpers/test/fixtures/qcm-drag.d.ts +4 -0
- package/lib/helpers/test/fixtures/qcm-drag.js +106 -0
- package/lib/helpers/test/fixtures/qcm-graphic.d.ts +4 -0
- package/lib/helpers/test/fixtures/qcm-graphic.js +70 -0
- package/lib/helpers/test/fixtures/qcm.d.ts +4 -0
- package/lib/helpers/test/fixtures/qcm.js +99 -0
- package/lib/helpers/test/fixtures/select-template.d.ts +4 -0
- package/lib/helpers/test/fixtures/select-template.js +88 -0
- package/lib/helpers/test/fixtures/slider.d.ts +4 -0
- package/lib/helpers/test/fixtures/slider.js +27 -0
- package/lib/helpers/test/fixtures/text-template.d.ts +4 -0
- package/lib/helpers/test/fixtures/text-template.js +48 -0
- package/lib/helpers/test/map-api-slide-to-ui.test.d.ts +1 -0
- package/lib/helpers/test/map-api-slide-to-ui.test.js +43 -0
- package/lib/index.js +29 -9
- package/lib/reducers/ui/navigation.d.ts +1 -1
- package/lib/test/index.test.js +19 -16
- package/lib/test/util/services.mock.js +13 -32
- package/lib/types/common.d.ts +62 -5
- package/lib/types/slides.d.ts +27 -16
- package/package.json +4 -3
- package/src/actions/ui/navigation.ts +1 -1
- package/src/fixtures/qcm-slide.ts +1 -1
- package/src/helpers/map-api-slide-to-ui.ts +253 -0
- package/src/helpers/test/fixtures/free-text.ts +28 -0
- package/src/helpers/test/fixtures/qcm-drag.ts +110 -0
- package/src/helpers/test/fixtures/qcm-graphic.ts +74 -0
- package/src/helpers/test/fixtures/qcm.ts +108 -0
- package/src/helpers/test/fixtures/select-template.ts +92 -0
- package/src/helpers/test/fixtures/slider.ts +31 -0
- package/src/helpers/test/fixtures/text-template.ts +52 -0
- package/src/helpers/test/map-api-slide-to-ui.test.ts +55 -0
- package/src/index.tsx +35 -11
- package/src/reducers/ui/navigation.ts +1 -1
- package/src/test/index.test.tsx +23 -12
- package/src/test/util/services.mock.ts +2 -32
- package/src/types/common.ts +74 -5
- package/src/types/slides.ts +29 -12
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import noop from 'lodash/fp/noop';
|
|
2
|
+
import {QcmGraphic} from '../../../types/slides';
|
|
3
|
+
import {SlideFromAPI} from '../../../types/common';
|
|
4
|
+
|
|
5
|
+
export const qcmGraphicSlide: SlideFromAPI = {
|
|
6
|
+
id: 'sli_41~RSVclH',
|
|
7
|
+
universalRef: 'sli_41~RSVclH',
|
|
8
|
+
question: {
|
|
9
|
+
type: 'qcmGraphic',
|
|
10
|
+
header: 'sli_41~RSVclH.header',
|
|
11
|
+
explanation: 'sli_41~RSVclH.explanation',
|
|
12
|
+
content: {
|
|
13
|
+
choices: [
|
|
14
|
+
{
|
|
15
|
+
media: {
|
|
16
|
+
type: 'img',
|
|
17
|
+
src: [
|
|
18
|
+
{
|
|
19
|
+
_id: '5fdce726359bf4003ee66997',
|
|
20
|
+
mimeType: 'image/png',
|
|
21
|
+
url: 'med_4JVRrE5gH.mediaUrl_VkBtUV9gB'
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
posters: [],
|
|
25
|
+
subtitles: []
|
|
26
|
+
},
|
|
27
|
+
_id: '5fdce726359bf4003ee66996',
|
|
28
|
+
label: 'sli_41~RSVclH.choice_V1gN0r4qgS',
|
|
29
|
+
value: 'sli_41~RSVclH.choice_V1gN0r4qgS',
|
|
30
|
+
items: []
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
media: {
|
|
34
|
+
type: 'img',
|
|
35
|
+
src: [
|
|
36
|
+
{
|
|
37
|
+
_id: '5fdce726359bf4003ee66999',
|
|
38
|
+
mimeType: 'image/png',
|
|
39
|
+
url: 'med_Ek8gIEqxB.mediaUrl_EkcFUEclH'
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
posters: [],
|
|
43
|
+
subtitles: []
|
|
44
|
+
},
|
|
45
|
+
_id: '5fdce726359bf4003ee66998',
|
|
46
|
+
label: 'sli_41~RSVclH.choice_4JlLeLE5lS',
|
|
47
|
+
value: 'sli_41~RSVclH.choice_4JlLeLE5lS',
|
|
48
|
+
items: []
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
clue: 'sli_41~RSVclH.clue',
|
|
54
|
+
klf: 'sli_41~RSVclH.klf',
|
|
55
|
+
tips: 'sli_41~RSVclH.tips'
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const qcmGraphicUISlide: QcmGraphic = {
|
|
59
|
+
type: 'qcmGraphic',
|
|
60
|
+
answers: [
|
|
61
|
+
{
|
|
62
|
+
title: 'sli_41~RSVclH.choice_V1gN0r4qgS',
|
|
63
|
+
image: 'med_4JVRrE5gH.mediaUrl_VkBtUV9gB',
|
|
64
|
+
selected: false,
|
|
65
|
+
onClick: noop
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
title: 'sli_41~RSVclH.choice_4JlLeLE5lS',
|
|
69
|
+
image: 'med_Ek8gIEqxB.mediaUrl_EkcFUEclH',
|
|
70
|
+
selected: false,
|
|
71
|
+
onClick: noop
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import noop from 'lodash/fp/noop';
|
|
2
|
+
import {Qcm} from '../../../types/slides';
|
|
3
|
+
import {SlideFromAPI} from '../../../types/common';
|
|
4
|
+
|
|
5
|
+
export const qcmSlide: SlideFromAPI = {
|
|
6
|
+
question: {
|
|
7
|
+
content: {
|
|
8
|
+
media: {
|
|
9
|
+
src: [],
|
|
10
|
+
posters: [],
|
|
11
|
+
subtitles: []
|
|
12
|
+
},
|
|
13
|
+
choices: [
|
|
14
|
+
{
|
|
15
|
+
media: {
|
|
16
|
+
src: [],
|
|
17
|
+
posters: [],
|
|
18
|
+
subtitles: []
|
|
19
|
+
},
|
|
20
|
+
items: [],
|
|
21
|
+
_id: '62c853412d0f9b088718e759',
|
|
22
|
+
label: 'Le créateur peut fixer un pourcentage pour chaque transaction future',
|
|
23
|
+
value: 'sli_N1XACJobn.choice_4JjaSesZh',
|
|
24
|
+
id: '62c853412d0f9b088718e759'
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
media: {
|
|
28
|
+
src: [],
|
|
29
|
+
posters: [],
|
|
30
|
+
subtitles: []
|
|
31
|
+
},
|
|
32
|
+
items: [],
|
|
33
|
+
_id: '62c853412d0f9b088718e75a',
|
|
34
|
+
label:
|
|
35
|
+
"Pour chaque transaction il existe un pourcentage fixe déterminé par le droit d'auteur du pays où se tient la vente",
|
|
36
|
+
value: 'sli_N1XACJobn.choice_Ny78UlsWh',
|
|
37
|
+
id: '62c853412d0f9b088718e75a'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
media: {
|
|
41
|
+
src: [],
|
|
42
|
+
posters: [],
|
|
43
|
+
subtitles: []
|
|
44
|
+
},
|
|
45
|
+
items: [],
|
|
46
|
+
_id: '62c853412d0f9b088718e75b',
|
|
47
|
+
label:
|
|
48
|
+
"Seule la galerie ou la plateforme peut toucher une commission sur la vente d'un NFT",
|
|
49
|
+
value: 'sli_N1XACJobn.choice_Eypt8esW2',
|
|
50
|
+
id: '62c853412d0f9b088718e75b'
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
media: {
|
|
54
|
+
src: [],
|
|
55
|
+
posters: [],
|
|
56
|
+
subtitles: []
|
|
57
|
+
},
|
|
58
|
+
items: [],
|
|
59
|
+
_id: '62c853412d0f9b088718e75c',
|
|
60
|
+
label: "Les NFT payés en ETH ne peuvent pas être soumis au paiement d'une commission",
|
|
61
|
+
value: 'sli_N1XACJobn.choice_VyS3LxjZh',
|
|
62
|
+
id: '62c853412d0f9b088718e75c'
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
type: 'qcm',
|
|
67
|
+
header: "Après la vente d'un NFT, son créateur peut-il toucher de l'argent ?",
|
|
68
|
+
explanation: 'Sélectionnez la bonne réponse.'
|
|
69
|
+
},
|
|
70
|
+
klf: 'Si vous êtes le créateur d’un NFT, vous pouvez choisir le pourcentage de commission pour chaque transaction de votre NFT. Certains choisissent de ne rien toucher pour fluidifier le marché.',
|
|
71
|
+
tips: 'En 2021, le média en ligne Numerama a créé un NFT vendu aux enchères sur OpenSea. Sur cette plateforme, il est obligatoire de mettre un prix de réserve, autrement dit un prix minimum au-dessous duquel la vente ne sera pas automatiquement acceptée. Sur OpenSea il ne peut être inférieur à 1 ETH. Si le prix de réserve est atteint, pas de problème, les "gas fees" (les frais de gaz) sont couverts par OpenSea. Mais, si ce n’est pas le cas, c’est au vendeur de s’en acquitter. <br/>Le NFT en question est parti à 0,021 ETH, soit 40€ au cours de l\'époque, un prix inférieur au prix de réserve. Numerama a dû acquitter des frais de gaz, et payer 190 €. <br/>Avec les NFT, on ne gagne pas à tous les coups.',
|
|
72
|
+
universalRef: 'sli_N1XACJobn',
|
|
73
|
+
hasClue: true,
|
|
74
|
+
id: 'sli_N1XACJobn'
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const qcmUISlide: Qcm = {
|
|
78
|
+
type: 'qcm',
|
|
79
|
+
answers: [
|
|
80
|
+
{
|
|
81
|
+
title: 'Le créateur peut fixer un pourcentage pour chaque transaction future',
|
|
82
|
+
selected: false,
|
|
83
|
+
onClick: noop,
|
|
84
|
+
ariaLabel: 'Le créateur peut fixer un pourcentage pour chaque transaction future'
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
title:
|
|
88
|
+
"Pour chaque transaction il existe un pourcentage fixe déterminé par le droit d'auteur du pays où se tient la vente",
|
|
89
|
+
selected: false,
|
|
90
|
+
onClick: noop,
|
|
91
|
+
ariaLabel:
|
|
92
|
+
"Pour chaque transaction il existe un pourcentage fixe déterminé par le droit d'auteur du pays où se tient la vente"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
title: "Seule la galerie ou la plateforme peut toucher une commission sur la vente d'un NFT",
|
|
96
|
+
selected: false,
|
|
97
|
+
onClick: noop,
|
|
98
|
+
ariaLabel:
|
|
99
|
+
"Seule la galerie ou la plateforme peut toucher une commission sur la vente d'un NFT"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
title: "Les NFT payés en ETH ne peuvent pas être soumis au paiement d'une commission",
|
|
103
|
+
selected: false,
|
|
104
|
+
onClick: noop,
|
|
105
|
+
ariaLabel: "Les NFT payés en ETH ne peuvent pas être soumis au paiement d'une commission"
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import noop from 'lodash/fp/noop';
|
|
2
|
+
import {Template} from '../../../types/slides';
|
|
3
|
+
import {SlideFromAPI} from '../../../types/common';
|
|
4
|
+
|
|
5
|
+
export const selectTemplateSlide: SlideFromAPI = {
|
|
6
|
+
id: 'sli_410xZQxrZ',
|
|
7
|
+
universalRef: 'sli_410xZQxrZ',
|
|
8
|
+
question: {
|
|
9
|
+
type: 'template',
|
|
10
|
+
header: 'sli_410xZQxrZ.header',
|
|
11
|
+
explanation: 'sli_410xZQxrZ.explanation',
|
|
12
|
+
content: {
|
|
13
|
+
template: 'sli_410xZQxrZ.template',
|
|
14
|
+
choices: [
|
|
15
|
+
{
|
|
16
|
+
media: {
|
|
17
|
+
src: [],
|
|
18
|
+
posters: [],
|
|
19
|
+
subtitles: []
|
|
20
|
+
},
|
|
21
|
+
_id: '5fdce726359bf4003ee66967',
|
|
22
|
+
type: 'select',
|
|
23
|
+
name: 'sel36665',
|
|
24
|
+
items: [
|
|
25
|
+
{
|
|
26
|
+
_id: '5fdce726359bf4003ee66968',
|
|
27
|
+
text: 'sli_410xZQxrZ.choice_4yeA4Z7lr~',
|
|
28
|
+
value: 'sli_410xZQxrZ.choice_4yeA4Z7lr~'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
_id: '5fdce726359bf4003ee66969',
|
|
32
|
+
text: 'sli_410xZQxrZ.choice_VJWCN~mgB~',
|
|
33
|
+
value: 'sli_410xZQxrZ.choice_VJWCN~mgB~'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
_id: '5fdce726359bf4003ee6696a',
|
|
37
|
+
text: 'sli_410xZQxrZ.choice_VkaH~XgBb',
|
|
38
|
+
value: 'sli_410xZQxrZ.choice_VkaH~XgBb'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
_id: '5fdce726359bf4003ee6696b',
|
|
42
|
+
text: 'sli_410xZQxrZ.choice_E1uUWXeBb',
|
|
43
|
+
value: 'sli_410xZQxrZ.choice_E1uUWXeBb'
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
clue: 'sli_410xZQxrZ.clue',
|
|
51
|
+
klf: 'sli_410xZQxrZ.klf',
|
|
52
|
+
tips: 'sli_410xZQxrZ.tips'
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const selectTemplateUISlide: Template = {
|
|
56
|
+
type: 'template',
|
|
57
|
+
template: 'sli_410xZQxrZ.template',
|
|
58
|
+
answers: [
|
|
59
|
+
{
|
|
60
|
+
type: 'select',
|
|
61
|
+
name: 'sel36665',
|
|
62
|
+
onChange: noop,
|
|
63
|
+
options: [
|
|
64
|
+
{name: 'Select an answer', value: '', validOption: false, selected: true},
|
|
65
|
+
{
|
|
66
|
+
name: 'sli_410xZQxrZ.choice_4yeA4Z7lr~',
|
|
67
|
+
value: 'sli_410xZQxrZ.choice_4yeA4Z7lr~',
|
|
68
|
+
validOption: true,
|
|
69
|
+
selected: false
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: 'sli_410xZQxrZ.choice_VJWCN~mgB~',
|
|
73
|
+
value: 'sli_410xZQxrZ.choice_VJWCN~mgB~',
|
|
74
|
+
validOption: true,
|
|
75
|
+
selected: false
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'sli_410xZQxrZ.choice_VkaH~XgBb',
|
|
79
|
+
value: 'sli_410xZQxrZ.choice_VkaH~XgBb',
|
|
80
|
+
validOption: true,
|
|
81
|
+
selected: false
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'sli_410xZQxrZ.choice_E1uUWXeBb',
|
|
85
|
+
value: 'sli_410xZQxrZ.choice_E1uUWXeBb',
|
|
86
|
+
validOption: true,
|
|
87
|
+
selected: false
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import noop from 'lodash/fp/noop';
|
|
2
|
+
import {QuestionRange} from '../../../types/slides';
|
|
3
|
+
import {SlideFromAPI} from '../../../types/common';
|
|
4
|
+
|
|
5
|
+
export const sliderSlide: SlideFromAPI = {
|
|
6
|
+
id: 'sli_41D5AovN~',
|
|
7
|
+
universalRef: 'sli_41D5AovN~',
|
|
8
|
+
question: {
|
|
9
|
+
type: 'slider',
|
|
10
|
+
header: 'sli_41D5AovN~.header',
|
|
11
|
+
explanation: 'sli_41D5AovN~.explanation',
|
|
12
|
+
content: {
|
|
13
|
+
min: 1,
|
|
14
|
+
max: 10,
|
|
15
|
+
unitLabel: 'sli_41D5AovN~.unitLabel'
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
clue: 'sli_41D5AovN~.clue',
|
|
19
|
+
klf: 'sli_41D5AovN~.klf',
|
|
20
|
+
tips: 'sli_41D5AovN~.tips'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const sliderUISlide: QuestionRange = {
|
|
24
|
+
type: 'slider',
|
|
25
|
+
placeholder: 'sli_41D5AovN~.explanation',
|
|
26
|
+
minLabel: '1 undefined',
|
|
27
|
+
maxLabel: '10 undefined',
|
|
28
|
+
title: '0 sli_41D5AovN~.unitLabel',
|
|
29
|
+
value: -0.1111111111111111,
|
|
30
|
+
onChange: noop
|
|
31
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import noop from 'lodash/fp/noop';
|
|
2
|
+
import {Template} from '../../../types/slides';
|
|
3
|
+
import {SlideFromAPI} from '../../../types/common';
|
|
4
|
+
|
|
5
|
+
export const textTemplateSlide: SlideFromAPI = {
|
|
6
|
+
question: {
|
|
7
|
+
content: {
|
|
8
|
+
media: {
|
|
9
|
+
src: [],
|
|
10
|
+
posters: [],
|
|
11
|
+
subtitles: []
|
|
12
|
+
},
|
|
13
|
+
template: 'Un {{inp58402}} model.',
|
|
14
|
+
choices: [
|
|
15
|
+
{
|
|
16
|
+
media: {
|
|
17
|
+
src: [],
|
|
18
|
+
posters: [],
|
|
19
|
+
subtitles: []
|
|
20
|
+
},
|
|
21
|
+
items: [],
|
|
22
|
+
_id: '62433c2c58920f02c4950de0',
|
|
23
|
+
type: 'text',
|
|
24
|
+
name: 'inp58402',
|
|
25
|
+
id: '62433c2c58920f02c4950de0'
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
type: 'template',
|
|
30
|
+
header: 'Comment le protégé doit-il percevoir son mentor ?',
|
|
31
|
+
explanation: 'Saisissez votre réponse (en anglais).'
|
|
32
|
+
},
|
|
33
|
+
klf: "Le mentoré voit dans son mentor un <i>role model</i>, c'est-à-dire un exemple inspirant qui lui permet de se projeter dans un poste à responsabilité.",
|
|
34
|
+
tips: "L'origine de l'expression <i>role model</i> est attribué au sociologue Robert K. Merton.",
|
|
35
|
+
universalRef: 'sli_VJKQonm2g',
|
|
36
|
+
hasClue: true,
|
|
37
|
+
id: 'sli_VJKQonm2g'
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const textTemplateUISlide: Template = {
|
|
41
|
+
type: 'template',
|
|
42
|
+
template: 'Un {{inp58402}} model.',
|
|
43
|
+
answers: [
|
|
44
|
+
{
|
|
45
|
+
type: 'text',
|
|
46
|
+
name: 'inp58402',
|
|
47
|
+
placeholder: 'Type here',
|
|
48
|
+
value: undefined,
|
|
49
|
+
onChange: noop
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import {SlideFromAPI} from '../../types/common';
|
|
3
|
+
import {mapApiSlideToUi} from '../map-api-slide-to-ui';
|
|
4
|
+
import {
|
|
5
|
+
QcmDrag,
|
|
6
|
+
Qcm,
|
|
7
|
+
QcmGraphic,
|
|
8
|
+
FreeText,
|
|
9
|
+
DropDown,
|
|
10
|
+
QuestionRange,
|
|
11
|
+
Template
|
|
12
|
+
} from '../../types/slides';
|
|
13
|
+
import {qcmUISlide, qcmSlide} from './fixtures/qcm';
|
|
14
|
+
import {qcmDragUISlide, qcmDragSlide} from './fixtures/qcm-drag';
|
|
15
|
+
import {freeTextSlide, freeTextUISlide} from './fixtures/free-text';
|
|
16
|
+
import {qcmGraphicUISlide, qcmGraphicSlide} from './fixtures/qcm-graphic';
|
|
17
|
+
import {textTemplateSlide, textTemplateUISlide} from './fixtures/text-template';
|
|
18
|
+
import {selectTemplateSlide, selectTemplateUISlide} from './fixtures/select-template';
|
|
19
|
+
import {sliderSlide, sliderUISlide} from './fixtures/slider';
|
|
20
|
+
|
|
21
|
+
const _mapApiSlideToUi = mapApiSlideToUi({translate: (text: string) => text});
|
|
22
|
+
|
|
23
|
+
const macro = test.macro({
|
|
24
|
+
title(providedTitle) {
|
|
25
|
+
return `should handle ${providedTitle} conversion`.trim();
|
|
26
|
+
},
|
|
27
|
+
exec(
|
|
28
|
+
t,
|
|
29
|
+
arg: {
|
|
30
|
+
slide: SlideFromAPI;
|
|
31
|
+
expectedUiSlide: QcmDrag | Qcm | QcmGraphic | FreeText | DropDown | QuestionRange | Template;
|
|
32
|
+
}
|
|
33
|
+
) {
|
|
34
|
+
t.deepEqual(
|
|
35
|
+
JSON.parse(JSON.stringify(_mapApiSlideToUi(arg.slide))),
|
|
36
|
+
JSON.parse(JSON.stringify(arg.expectedUiSlide))
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('qcm', macro, {slide: qcmSlide, expectedUiSlide: qcmUISlide});
|
|
42
|
+
test('qcm drag', macro, {slide: qcmDragSlide, expectedUiSlide: qcmDragUISlide});
|
|
43
|
+
test('qcm graphic', macro, {slide: qcmGraphicSlide, expectedUiSlide: qcmGraphicUISlide});
|
|
44
|
+
test('text template', macro, {slide: textTemplateSlide, expectedUiSlide: textTemplateUISlide});
|
|
45
|
+
test('select template', macro, {
|
|
46
|
+
slide: selectTemplateSlide,
|
|
47
|
+
expectedUiSlide: selectTemplateUISlide
|
|
48
|
+
});
|
|
49
|
+
test('free text', macro, {slide: freeTextSlide, expectedUiSlide: freeTextUISlide});
|
|
50
|
+
test('slider', macro, {slide: sliderSlide, expectedUiSlide: sliderUISlide});
|
|
51
|
+
|
|
52
|
+
test('should throw an error if the question type can not be handled', t => {
|
|
53
|
+
const faultySlide = {...qcmSlide, question: {type: 'lol'}};
|
|
54
|
+
t.throws(() => _mapApiSlideToUi(faultySlide as SlideFromAPI));
|
|
55
|
+
});
|
package/src/index.tsx
CHANGED
|
@@ -5,6 +5,8 @@ import {connect, Provider} from 'react-redux';
|
|
|
5
5
|
import AppReviewTemplate from '@coorpacademy/components/es/template/app-review';
|
|
6
6
|
import {TemplateContext} from '@coorpacademy/components/es/template/app-review/template-context';
|
|
7
7
|
|
|
8
|
+
import isEmpty from 'lodash/fp/isEmpty';
|
|
9
|
+
import get from 'lodash/fp/get';
|
|
8
10
|
import configureStore from './configure-store';
|
|
9
11
|
import {congratsProps, correctionPopinProps} from './fixtures/temp-fixture';
|
|
10
12
|
|
|
@@ -25,7 +27,7 @@ import {postProgression} from './actions/api/post-progression';
|
|
|
25
27
|
import {VIEWS} from './common';
|
|
26
28
|
|
|
27
29
|
type StaticProps = {
|
|
28
|
-
viewName: 'skills' | 'onboarding' | 'slides';
|
|
30
|
+
viewName: 'skills' | 'onboarding' | 'slides' | 'loader';
|
|
29
31
|
slides: SlidesViewStaticProps | null;
|
|
30
32
|
skills: SkillsProps | null;
|
|
31
33
|
};
|
|
@@ -113,6 +115,7 @@ const App = connect(mapStateToProps, mapDispatchToProps)(AppReviewTemplate);
|
|
|
113
115
|
|
|
114
116
|
const AppReview = ({options}: {options: AppOptions}): JSX.Element | null => {
|
|
115
117
|
const [store, setStore] = useState<Store<StoreState, AnyAction> | null>(null);
|
|
118
|
+
const [isSlideFetched, setIsSlideFetched] = useState(false);
|
|
116
119
|
|
|
117
120
|
useEffect(() => {
|
|
118
121
|
if (store) return;
|
|
@@ -122,24 +125,27 @@ const AppReview = ({options}: {options: AppOptions}): JSX.Element | null => {
|
|
|
122
125
|
}, [options, store]);
|
|
123
126
|
|
|
124
127
|
useEffect(() => {
|
|
125
|
-
if (store
|
|
128
|
+
if (!store || isSlideFetched) return;
|
|
126
129
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
130
|
+
return store.subscribe(() => {
|
|
131
|
+
const isSlidePresent = !isEmpty(store.getState().data.slides[0].questionText);
|
|
132
|
+
return isSlidePresent && setIsSlideFetched(isSlidePresent);
|
|
133
|
+
}); // using the first slide questionText for now, should only check for a slide's presence
|
|
134
|
+
// when the refactor is done (slides will be feed one by one on api's side)
|
|
135
|
+
}, [isSlideFetched, options, store]);
|
|
131
136
|
|
|
132
137
|
useEffect(() => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const {token} = options;
|
|
138
|
+
const token = get('token', options);
|
|
139
|
+
if (store === null || isEmpty(token)) return;
|
|
136
140
|
store.dispatch(storeToken(token));
|
|
137
141
|
}, [options, store]);
|
|
138
142
|
|
|
139
143
|
useEffect(() => {
|
|
140
|
-
|
|
144
|
+
const token = get('token', options);
|
|
145
|
+
if (store === null || isEmpty(token)) return;
|
|
146
|
+
|
|
147
|
+
const skillRef = get('skillRef', options);
|
|
141
148
|
|
|
142
|
-
const {skillRef, token} = options;
|
|
143
149
|
// ThunkAction is not assignable to parameter of type 'AnyAction'
|
|
144
150
|
// ts problem describre here = https://github.com/reduxjs/redux-thunk/issues/333
|
|
145
151
|
skillRef
|
|
@@ -147,6 +153,24 @@ const AppReview = ({options}: {options: AppOptions}): JSX.Element | null => {
|
|
|
147
153
|
: store.dispatch(fetchSkills(token));
|
|
148
154
|
}, [options, store]);
|
|
149
155
|
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
if (store === null) return;
|
|
158
|
+
|
|
159
|
+
const {skillRef} = options;
|
|
160
|
+
|
|
161
|
+
if (skillRef && !isSlideFetched) {
|
|
162
|
+
store.dispatch(navigateTo('loader')); // use loader while posting progression
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// TODO: when slides state is refactored (data + mapping),
|
|
167
|
+
// use loader in case a skillRef is found && no slides from the API
|
|
168
|
+
// are found
|
|
169
|
+
|
|
170
|
+
const initialView: ViewPath = skillRef ? VIEWS.slides : VIEWS.skills;
|
|
171
|
+
store.dispatch(navigateTo(initialView));
|
|
172
|
+
}, [isSlideFetched, options, store]);
|
|
173
|
+
|
|
150
174
|
if (!store) return null;
|
|
151
175
|
|
|
152
176
|
const {templateContext: values} = options;
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
NAVIGATE_TO
|
|
6
6
|
} from '../../actions/ui/navigation';
|
|
7
7
|
|
|
8
|
-
export type NavigationState = Array<'skills' | 'onboarding' | 'slides'>;
|
|
8
|
+
export type NavigationState = Array<'skills' | 'onboarding' | 'slides' | 'loader'>;
|
|
9
9
|
|
|
10
10
|
const reducer = (
|
|
11
11
|
// eslint-disable-next-line default-param-last
|
package/src/test/index.test.tsx
CHANGED
|
@@ -65,24 +65,35 @@ const appOptions: AppOptions = {
|
|
|
65
65
|
services
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
-
test('should
|
|
69
|
-
// t.plan(13);
|
|
68
|
+
test('should show the loader while the app is fetching the data', async t => {
|
|
70
69
|
t.plan(2);
|
|
71
|
-
const {container} = render(<AppReview options={appOptions}
|
|
70
|
+
const {container} = render(<AppReview options={appOptions} />);
|
|
71
|
+
|
|
72
72
|
await waitForChanges(1000);
|
|
73
73
|
|
|
74
|
-
const
|
|
75
|
-
t.truthy(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
const loader = container.querySelector('[data-name="loader"]');
|
|
75
|
+
t.truthy(loader);
|
|
76
|
+
|
|
77
|
+
// await waitFor(async () => {
|
|
78
|
+
// // await sleep(500);
|
|
79
|
+
// const result = await t.try(tt => {
|
|
80
|
+
// // rerender(<AppReview options={appOptions} />);
|
|
81
|
+
|
|
82
|
+
// const slidesContainer = container.querySelector('[data-name="slides-revision-container"]');
|
|
83
|
+
|
|
84
|
+
// tt.truthy(slidesContainer);
|
|
85
|
+
// });
|
|
86
|
+
|
|
87
|
+
// if (result.passed) return result.commit();
|
|
88
|
+
// result.discard();
|
|
89
|
+
// throw result.errors;
|
|
90
|
+
// });
|
|
79
91
|
|
|
80
|
-
const stackedSlidesContainer =
|
|
92
|
+
// const stackedSlidesContainer = container.querySelector('[data-name="stacked-slides-container"]');
|
|
81
93
|
|
|
82
|
-
t.truthy(stackedSlidesContainer);
|
|
94
|
+
// t.truthy(stackedSlidesContainer);
|
|
83
95
|
|
|
84
|
-
await clickAllSlides(t, container);
|
|
85
|
-
*/
|
|
96
|
+
// await clickAllSlides(t, container);
|
|
86
97
|
|
|
87
98
|
t.pass();
|
|
88
99
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {qcmSlide} from '../../helpers/test/fixtures/qcm';
|
|
1
2
|
import {Services} from '../../types/common';
|
|
2
3
|
|
|
3
4
|
export const services: Services = {
|
|
@@ -18,38 +19,7 @@ export const services: Services = {
|
|
|
18
19
|
]);
|
|
19
20
|
},
|
|
20
21
|
fetchSlide: ref => {
|
|
21
|
-
|
|
22
|
-
return Promise.resolve({
|
|
23
|
-
question: {
|
|
24
|
-
content: {
|
|
25
|
-
choices: [
|
|
26
|
-
{
|
|
27
|
-
selected: false,
|
|
28
|
-
title: 'choix1',
|
|
29
|
-
help: '(help choix1)',
|
|
30
|
-
ariaLabel: '__ariaLabel1',
|
|
31
|
-
onClick: (): void => undefined
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
selected: false,
|
|
35
|
-
title: 'choix2',
|
|
36
|
-
help: '(help choix2)',
|
|
37
|
-
ariaLabel: '__ariaLabel2',
|
|
38
|
-
onClick: (): void => undefined
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
selected: false,
|
|
42
|
-
title: 'choix3',
|
|
43
|
-
help: '(help choix3)',
|
|
44
|
-
ariaLabel: '__ariaLabel3',
|
|
45
|
-
onClick: (): void => undefined
|
|
46
|
-
}
|
|
47
|
-
]
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
klf: '___klf',
|
|
51
|
-
universalRef: ref
|
|
52
|
-
});
|
|
22
|
+
return Promise.resolve({...qcmSlide, universalRef: ref, id: ref});
|
|
53
23
|
},
|
|
54
24
|
postProgression: () => {
|
|
55
25
|
return Promise.resolve({
|