@coorpacademy/app-review 0.46.14-alpha.9 → 0.46.14-react18.79
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/reducers/data/corrections.d.ts +1 -1
- package/es/reducers/data/current-skill.d.ts +1 -1
- package/es/reducers/data/index.d.ts +3 -3
- package/es/reducers/data/progression.d.ts +1 -1
- package/es/reducers/data/rank.d.ts +1 -1
- package/es/reducers/data/slides.d.ts +1 -1
- package/es/reducers/data/token.d.ts +1 -1
- package/es/reducers/data/videos.d.ts +1 -1
- package/es/reducers/index.d.ts +3 -7
- package/es/reducers/ui/answers.d.ts +1 -1
- package/es/reducers/ui/current-slide-ref.d.ts +1 -1
- package/es/reducers/ui/index.d.ts +1 -5
- package/es/reducers/ui/navigation.d.ts +1 -1
- package/es/reducers/ui/positions.d.ts +1 -1
- package/es/reducers/ui/quit-popin.d.ts +1 -1
- package/es/reducers/ui/show-button-revising.d.ts +1 -1
- package/es/reducers/ui/show-congrats.d.ts +1 -1
- package/es/reducers/ui/slide.d.ts +1 -1
- package/lib/reducers/data/corrections.d.ts +1 -1
- package/lib/reducers/data/current-skill.d.ts +1 -1
- package/lib/reducers/data/index.d.ts +3 -3
- package/lib/reducers/data/progression.d.ts +1 -1
- package/lib/reducers/data/rank.d.ts +1 -1
- package/lib/reducers/data/slides.d.ts +1 -1
- package/lib/reducers/data/token.d.ts +1 -1
- package/lib/reducers/data/videos.d.ts +1 -1
- package/lib/reducers/index.d.ts +3 -7
- package/lib/reducers/ui/answers.d.ts +1 -1
- package/lib/reducers/ui/current-slide-ref.d.ts +1 -1
- package/lib/reducers/ui/index.d.ts +1 -5
- package/lib/reducers/ui/navigation.d.ts +1 -1
- package/lib/reducers/ui/positions.d.ts +1 -1
- package/lib/reducers/ui/quit-popin.d.ts +1 -1
- package/lib/reducers/ui/show-button-revising.d.ts +1 -1
- package/lib/reducers/ui/show-congrats.d.ts +1 -1
- package/lib/reducers/ui/slide.d.ts +1 -1
- package/package.json +19 -10
- package/es/actions/api/fetch-correction.js +0 -18
- package/es/actions/api/fetch-rank.js +0 -34
- package/es/actions/api/fetch-skill.js +0 -16
- package/es/actions/api/fetch-slide.js +0 -31
- package/es/actions/api/fetch-slides-to-review-by-skill-ref.js +0 -32
- package/es/actions/api/fetch-video-props.js +0 -34
- package/es/actions/api/post-answer.js +0 -36
- package/es/actions/api/post-progression.js +0 -25
- package/es/actions/data/token.js +0 -5
- package/es/actions/ui/answers.js +0 -54
- package/es/actions/ui/navigation.js +0 -26
- package/es/actions/ui/next-slide.js +0 -33
- package/es/actions/ui/quit-popin.js +0 -8
- package/es/actions/ui/show-button-revising.js +0 -6
- package/es/actions/ui/slides.js +0 -10
- package/es/common/index.js +0 -10
- package/es/configure-store.js +0 -26
- package/es/helpers/css-register.js +0 -2
- package/es/index.js +0 -48
- package/es/reducers/data/corrections.js +0 -25
- package/es/reducers/data/current-skill.js +0 -13
- package/es/reducers/data/index.js +0 -17
- package/es/reducers/data/progression.js +0 -20
- package/es/reducers/data/rank.js +0 -27
- package/es/reducers/data/slides.js +0 -20
- package/es/reducers/data/token.js +0 -11
- package/es/reducers/data/videos.js +0 -33
- package/es/reducers/index.js +0 -7
- package/es/reducers/ui/answers.js +0 -28
- package/es/reducers/ui/current-slide-ref.js +0 -21
- package/es/reducers/ui/index.js +0 -19
- package/es/reducers/ui/navigation.js +0 -18
- package/es/reducers/ui/positions.js +0 -30
- package/es/reducers/ui/quit-popin.js +0 -16
- package/es/reducers/ui/show-button-revising.js +0 -17
- package/es/reducers/ui/show-congrats.js +0 -20
- package/es/reducers/ui/slide.js +0 -52
- package/es/types/common.js +0 -1
- package/es/types/slides.js +0 -1
- package/es/views/slides/index.js +0 -387
- package/es/views/slides/map-api-slide-to-ui.js +0 -177
- package/lib/actions/api/fetch-correction.js +0 -25
- package/lib/actions/api/fetch-rank.js +0 -43
- package/lib/actions/api/fetch-skill.js +0 -23
- package/lib/actions/api/fetch-slide.js +0 -38
- package/lib/actions/api/fetch-slides-to-review-by-skill-ref.js +0 -39
- package/lib/actions/api/fetch-video-props.js +0 -43
- package/lib/actions/api/post-answer.js +0 -43
- package/lib/actions/api/post-progression.js +0 -32
- package/lib/actions/data/token.js +0 -9
- package/lib/actions/ui/answers.js +0 -61
- package/lib/actions/ui/navigation.js +0 -31
- package/lib/actions/ui/next-slide.js +0 -40
- package/lib/actions/ui/quit-popin.js +0 -11
- package/lib/actions/ui/show-button-revising.js +0 -10
- package/lib/actions/ui/slides.js +0 -14
- package/lib/common/index.js +0 -17
- package/lib/configure-store.js +0 -32
- package/lib/helpers/css-register.js +0 -7
- package/lib/index.js +0 -76
- package/lib/reducers/data/corrections.js +0 -30
- package/lib/reducers/data/current-skill.js +0 -15
- package/lib/reducers/data/index.js +0 -22
- package/lib/reducers/data/progression.js +0 -22
- package/lib/reducers/data/rank.js +0 -32
- package/lib/reducers/data/slides.js +0 -26
- package/lib/reducers/data/token.js +0 -13
- package/lib/reducers/data/videos.js +0 -36
- package/lib/reducers/index.js +0 -12
- package/lib/reducers/ui/answers.js +0 -31
- package/lib/reducers/ui/current-slide-ref.js +0 -23
- package/lib/reducers/ui/index.js +0 -24
- package/lib/reducers/ui/navigation.js +0 -20
- package/lib/reducers/ui/positions.js +0 -35
- package/lib/reducers/ui/quit-popin.js +0 -18
- package/lib/reducers/ui/show-button-revising.js +0 -19
- package/lib/reducers/ui/show-congrats.js +0 -22
- package/lib/reducers/ui/slide.js +0 -58
- package/lib/types/common.js +0 -2
- package/lib/types/slides.js +0 -2
- package/lib/views/slides/index.js +0 -395
- package/lib/views/slides/map-api-slide-to-ui.js +0 -182
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { NEXT_SLIDE } from '../../actions/ui/next-slide';
|
|
2
|
-
import { POST_PROGRESSION_REQUEST } from '../../actions/api/post-progression';
|
|
3
|
-
const reducer = (
|
|
4
|
-
// eslint-disable-next-line default-param-last
|
|
5
|
-
state = false, action) => {
|
|
6
|
-
switch (action.type) {
|
|
7
|
-
case POST_PROGRESSION_REQUEST: {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
case NEXT_SLIDE: {
|
|
11
|
-
const { nextSlideRef } = action.payload;
|
|
12
|
-
if (nextSlideRef === 'successExitNode')
|
|
13
|
-
return true;
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
default:
|
|
17
|
-
return state;
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
export default reducer;
|
package/es/reducers/ui/slide.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import compact from 'lodash/fp/compact';
|
|
2
|
-
import isEmpty from 'lodash/fp/isEmpty';
|
|
3
|
-
import pipe from 'lodash/fp/pipe';
|
|
4
|
-
import set from 'lodash/fp/set';
|
|
5
|
-
import unset from 'lodash/fp/unset';
|
|
6
|
-
import { EDIT_BASIC, EDIT_QCM, EDIT_QCM_DRAG, EDIT_QCM_GRAPHIC, EDIT_SLIDER, EDIT_TEMPLATE } from '../../actions/ui/answers';
|
|
7
|
-
import { POST_ANSWER_REQUEST } from '../../actions/api/post-answer';
|
|
8
|
-
import { CORRECTION_FETCH_SUCCESS } from '../../actions/api/fetch-correction';
|
|
9
|
-
import { POST_PROGRESSION_REQUEST } from '../../actions/api/post-progression';
|
|
10
|
-
import { SLIDE_FETCH_REQUEST } from '../../actions/api/fetch-slide';
|
|
11
|
-
import { NEXT_SLIDE } from '../../actions/ui/next-slide';
|
|
12
|
-
export const initialState = {};
|
|
13
|
-
const reducer = (
|
|
14
|
-
// eslint-disable-next-line default-param-last
|
|
15
|
-
state = initialState, action) => {
|
|
16
|
-
switch (action.type) {
|
|
17
|
-
case SLIDE_FETCH_REQUEST: {
|
|
18
|
-
return pipe(unset([action.meta.slideRef, 'animationType']), set([action.meta.slideRef], {
|
|
19
|
-
validateButton: false,
|
|
20
|
-
animateCorrectionPopin: false,
|
|
21
|
-
showCorrectionPopin: false,
|
|
22
|
-
pendingAnswerRequest: false
|
|
23
|
-
}))(state);
|
|
24
|
-
}
|
|
25
|
-
case EDIT_QCM:
|
|
26
|
-
case EDIT_QCM_GRAPHIC:
|
|
27
|
-
case EDIT_QCM_DRAG:
|
|
28
|
-
case EDIT_TEMPLATE:
|
|
29
|
-
case EDIT_BASIC:
|
|
30
|
-
case EDIT_SLIDER: {
|
|
31
|
-
return set([action.meta.slideRef, 'validateButton'], !pipe(compact, isEmpty)(action.payload), state);
|
|
32
|
-
}
|
|
33
|
-
case POST_ANSWER_REQUEST: {
|
|
34
|
-
return pipe(set([action.meta.slideRef, 'validateButton'], false), set([action.meta.slideRef, 'pendingAnswerRequest'], true))(state);
|
|
35
|
-
}
|
|
36
|
-
case CORRECTION_FETCH_SUCCESS: {
|
|
37
|
-
return pipe(set([action.meta.slideRef, 'animateCorrectionPopin'], true), set([action.meta.slideRef, 'showCorrectionPopin'], true))(state);
|
|
38
|
-
}
|
|
39
|
-
case NEXT_SLIDE: {
|
|
40
|
-
const { currentSlideRef, nextSlideRef } = action.payload;
|
|
41
|
-
if (nextSlideRef === 'successExitNode')
|
|
42
|
-
return state;
|
|
43
|
-
return pipe(set([currentSlideRef, 'animateCorrectionPopin'], false), set([currentSlideRef, 'animationType'], action.payload.animationType), set([currentSlideRef, 'showCorrectionPopin'], false))(state);
|
|
44
|
-
}
|
|
45
|
-
case POST_PROGRESSION_REQUEST: {
|
|
46
|
-
return initialState;
|
|
47
|
-
}
|
|
48
|
-
default:
|
|
49
|
-
return state;
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
export default reducer;
|
package/es/types/common.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/es/types/slides.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/es/views/slides/index.js
DELETED
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
import findLast from 'lodash/fp/findLast';
|
|
2
|
-
import get from 'lodash/fp/get';
|
|
3
|
-
import getOr from 'lodash/fp/getOr';
|
|
4
|
-
import last from 'lodash/fp/last';
|
|
5
|
-
import reduce from 'lodash/fp/reduce';
|
|
6
|
-
import set from 'lodash/fp/set';
|
|
7
|
-
import toInteger from 'lodash/fp/toInteger';
|
|
8
|
-
import join from 'lodash/fp/join';
|
|
9
|
-
import { closeQuitPopin, openQuitPopin } from '../../actions/ui/quit-popin';
|
|
10
|
-
import { getProgressionSlidesRefs } from '../../common';
|
|
11
|
-
import { postAnswer } from '../../actions/api/post-answer';
|
|
12
|
-
import { postProgression } from '../../actions/api/post-progression';
|
|
13
|
-
import { nextSlide } from '../../actions/ui/next-slide';
|
|
14
|
-
import { mapApiSlideToUi } from './map-api-slide-to-ui';
|
|
15
|
-
const ICON_VALUES = {
|
|
16
|
-
right: 'right',
|
|
17
|
-
wrong: 'wrong',
|
|
18
|
-
'no-answer': 'no-answer'
|
|
19
|
-
};
|
|
20
|
-
const buildConfettiAnimation = (translate) => ({
|
|
21
|
-
'aria-label': translate('Congratulations confetti animation'),
|
|
22
|
-
'data-name': 'default-lottie',
|
|
23
|
-
className: undefined,
|
|
24
|
-
animationSrc: 'https://static-staging.coorpacademy.com/animations/review/confetti.json',
|
|
25
|
-
loop: undefined,
|
|
26
|
-
autoplay: true,
|
|
27
|
-
rendererSettings: {
|
|
28
|
-
hideOnTransparent: false
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
export const initialState = {
|
|
32
|
-
'0': {
|
|
33
|
-
position: 0,
|
|
34
|
-
loading: true
|
|
35
|
-
},
|
|
36
|
-
'1': {
|
|
37
|
-
position: 1,
|
|
38
|
-
loading: true
|
|
39
|
-
},
|
|
40
|
-
'2': {
|
|
41
|
-
position: 2,
|
|
42
|
-
loading: true
|
|
43
|
-
},
|
|
44
|
-
'3': {
|
|
45
|
-
position: 3,
|
|
46
|
-
loading: true
|
|
47
|
-
},
|
|
48
|
-
'4': {
|
|
49
|
-
position: 4,
|
|
50
|
-
loading: true
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
const getCurrentSlideRef = (state) => {
|
|
54
|
-
const currentSlideRef = get(['ui', 'currentSlideRef'], state);
|
|
55
|
-
const endReview = currentSlideRef === 'successExitNode';
|
|
56
|
-
if (!endReview)
|
|
57
|
-
return currentSlideRef;
|
|
58
|
-
const progression = state.data.progression;
|
|
59
|
-
const content = progression.state.content;
|
|
60
|
-
return content.ref;
|
|
61
|
-
};
|
|
62
|
-
const isLastSlideAnswered = (slidesRef, slideRef) => {
|
|
63
|
-
return last(slidesRef) === slideRef;
|
|
64
|
-
};
|
|
65
|
-
const getSlideMedia = (state, slideFromAPI) => {
|
|
66
|
-
const media = get(['question', 'medias', '0'], slideFromAPI);
|
|
67
|
-
if (!media)
|
|
68
|
-
return;
|
|
69
|
-
const { type } = media;
|
|
70
|
-
const resource = get(['src', '0'], media);
|
|
71
|
-
switch (type) {
|
|
72
|
-
case 'img':
|
|
73
|
-
case 'audio': {
|
|
74
|
-
const mediaProps = {
|
|
75
|
-
...resource,
|
|
76
|
-
type,
|
|
77
|
-
url: get('url', resource)
|
|
78
|
-
};
|
|
79
|
-
return mediaProps;
|
|
80
|
-
}
|
|
81
|
-
case 'video': {
|
|
82
|
-
const videoProps = get(['data', 'videos', slideFromAPI._id, 'src', '0'], state);
|
|
83
|
-
return videoProps;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
const buildStackSlides = (state, dispatch, options) => {
|
|
88
|
-
const { translate } = options;
|
|
89
|
-
const currentSlideRef = getCurrentSlideRef(state);
|
|
90
|
-
const progression = state.data.progression;
|
|
91
|
-
if (!currentSlideRef || !progression)
|
|
92
|
-
return initialState;
|
|
93
|
-
const slideRefs = getProgressionSlidesRefs(progression);
|
|
94
|
-
// @ts-expect-error typescript does not support capped versions of lodash functions
|
|
95
|
-
const stack = reduce.convert({ cap: false })((acc, uiSlide, _index) => {
|
|
96
|
-
const index = toInteger(_index);
|
|
97
|
-
const slideRef = slideRefs[index];
|
|
98
|
-
const lastAnsweredSlideRef = isLastSlideAnswered(progression.state.slides, slideRef);
|
|
99
|
-
const positions = state.ui.positions;
|
|
100
|
-
// when unstack the last answered slide (position -1), we set the position to 0 only during the animation
|
|
101
|
-
// to avoid to hide the slide (caused by the position -1).
|
|
102
|
-
const position = lastAnsweredSlideRef && positions[index] === -1 ? 0 : positions[index];
|
|
103
|
-
if (!slideRef)
|
|
104
|
-
return set(index, { ...uiSlide, position }, acc);
|
|
105
|
-
const slideFromAPI = get(slideRef, state.data.slides);
|
|
106
|
-
if (!slideFromAPI)
|
|
107
|
-
return set(index, { ...uiSlide, position }, acc);
|
|
108
|
-
const answers = getOr([], ['ui', 'answers', slideRef], state);
|
|
109
|
-
const media = getSlideMedia(state, slideFromAPI);
|
|
110
|
-
const { questionText, answerUI } = mapApiSlideToUi(dispatch, translate)(slideFromAPI, answers, media);
|
|
111
|
-
const { title: parentContentTitle, type: parentContentType } = slideFromAPI.parentContentTitle;
|
|
112
|
-
const isCurrentSlideRef = currentSlideRef === slideRef;
|
|
113
|
-
const slideUI = get(['ui', 'slide', slideRef], state);
|
|
114
|
-
const animateCorrectionPopin = isCurrentSlideRef && slideUI.animateCorrectionPopin;
|
|
115
|
-
const showCorrectionPopin = isCurrentSlideRef && slideUI.showCorrectionPopin;
|
|
116
|
-
const animationType = lastAnsweredSlideRef ? slideUI.animationType : undefined;
|
|
117
|
-
const disabledContent = get(['ui', 'slide', slideRef, 'pendingAnswerRequest'], state);
|
|
118
|
-
const updatedUiSlide = {
|
|
119
|
-
...uiSlide,
|
|
120
|
-
position,
|
|
121
|
-
showCorrectionPopin,
|
|
122
|
-
animateCorrectionPopin,
|
|
123
|
-
loading: false,
|
|
124
|
-
questionText,
|
|
125
|
-
answerUI,
|
|
126
|
-
disabledContent,
|
|
127
|
-
parentContentTitle: translate('Content Parent Title', {
|
|
128
|
-
contentTitle: parentContentTitle,
|
|
129
|
-
contentType: parentContentType
|
|
130
|
-
}),
|
|
131
|
-
animationType
|
|
132
|
-
};
|
|
133
|
-
return set(index, updatedUiSlide, acc);
|
|
134
|
-
}, initialState, initialState);
|
|
135
|
-
return stack;
|
|
136
|
-
};
|
|
137
|
-
const getIconForCurrentStep = (slideRef, lastGivenAnswerForSlide, currentSlideRef, lastGivenAnswer) => {
|
|
138
|
-
if (slideRef !== currentSlideRef)
|
|
139
|
-
return lastGivenAnswerForSlide.isCorrect ? 'right' : 'wrong';
|
|
140
|
-
if (lastGivenAnswer.slideRef !== slideRef)
|
|
141
|
-
return 'no-answer';
|
|
142
|
-
return lastGivenAnswerForSlide.isCorrect ? 'right' : 'wrong';
|
|
143
|
-
};
|
|
144
|
-
export const buildStepItems = (state) => {
|
|
145
|
-
const { progression } = state.data;
|
|
146
|
-
const { currentSlideRef } = state.ui;
|
|
147
|
-
if (!progression)
|
|
148
|
-
return [];
|
|
149
|
-
const defaultProps = [
|
|
150
|
-
{
|
|
151
|
-
icon: 'no-answer',
|
|
152
|
-
current: true,
|
|
153
|
-
value: '1'
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
icon: 'no-answer',
|
|
157
|
-
current: false,
|
|
158
|
-
value: '2'
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
icon: 'no-answer',
|
|
162
|
-
current: false,
|
|
163
|
-
value: '3'
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
icon: 'no-answer',
|
|
167
|
-
current: false,
|
|
168
|
-
value: '4'
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
icon: 'no-answer',
|
|
172
|
-
current: false,
|
|
173
|
-
value: '5'
|
|
174
|
-
}
|
|
175
|
-
];
|
|
176
|
-
const slideRefs = getProgressionSlidesRefs(progression);
|
|
177
|
-
const allAnswers = progression.state.allAnswers;
|
|
178
|
-
const step = progression.state.step;
|
|
179
|
-
const nextContentRef = progression.state.nextContent.ref;
|
|
180
|
-
const lastGivenAnswer = last(allAnswers);
|
|
181
|
-
if (!lastGivenAnswer)
|
|
182
|
-
return defaultProps;
|
|
183
|
-
const steps = defaultProps.map((stepItem, index) => {
|
|
184
|
-
const slideRef = slideRefs[index];
|
|
185
|
-
if (!slideRef)
|
|
186
|
-
return stepItem; // non fecthed slide pour given index
|
|
187
|
-
const lastGivenAnswerForSlide = findLast(answer => answer.slideRef === slideRef, allAnswers);
|
|
188
|
-
// never answered slide
|
|
189
|
-
if (!lastGivenAnswerForSlide) {
|
|
190
|
-
return {
|
|
191
|
-
...stepItem,
|
|
192
|
-
current: nextContentRef === currentSlideRef && step.current === index + 1
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
// already answered slide, we computed based on the lastGivenAnswer
|
|
196
|
-
return {
|
|
197
|
-
...stepItem,
|
|
198
|
-
icon: getIconForCurrentStep(slideRef, lastGivenAnswerForSlide, currentSlideRef, lastGivenAnswer),
|
|
199
|
-
current: lastGivenAnswerForSlide.slideRef === currentSlideRef
|
|
200
|
-
};
|
|
201
|
-
});
|
|
202
|
-
return steps;
|
|
203
|
-
};
|
|
204
|
-
const getCorrectionPopinProps = (dispatch) => (isCorrect, correctAnswer, klf, translate, endReview) => {
|
|
205
|
-
const nextLabel = endReview ? translate('Continue') : translate('Next Question');
|
|
206
|
-
return {
|
|
207
|
-
klf: isCorrect
|
|
208
|
-
? undefined
|
|
209
|
-
: {
|
|
210
|
-
label: translate('KLF'),
|
|
211
|
-
tooltip: klf
|
|
212
|
-
},
|
|
213
|
-
resultLabel: isCorrect ? translate('Correct Answer') : translate('Wrong Answer'),
|
|
214
|
-
information: {
|
|
215
|
-
label: isCorrect ? translate('KLF') : translate('Correct Answer'),
|
|
216
|
-
message: isCorrect ? klf : join(', ', correctAnswer)
|
|
217
|
-
},
|
|
218
|
-
next: {
|
|
219
|
-
'aria-label': nextLabel,
|
|
220
|
-
label: nextLabel,
|
|
221
|
-
onClick: () => {
|
|
222
|
-
dispatch(nextSlide);
|
|
223
|
-
}
|
|
224
|
-
},
|
|
225
|
-
type: isCorrect ? 'right' : 'wrong'
|
|
226
|
-
};
|
|
227
|
-
};
|
|
228
|
-
const buildQuitPopinProps = (dispatch) => (onQuitClick, translate, skin) => {
|
|
229
|
-
return {
|
|
230
|
-
content: translate('Quit Title'),
|
|
231
|
-
icon: `MoonRocket`,
|
|
232
|
-
mode: 'alert',
|
|
233
|
-
descriptionText: translate('Quit Description Text'),
|
|
234
|
-
firstButton: {
|
|
235
|
-
label: translate('Stop learning'),
|
|
236
|
-
type: 'tertiary',
|
|
237
|
-
customStyle: {
|
|
238
|
-
color: '#ED3436'
|
|
239
|
-
},
|
|
240
|
-
handleOnclick: () => {
|
|
241
|
-
dispatch(closeQuitPopin);
|
|
242
|
-
onQuitClick();
|
|
243
|
-
},
|
|
244
|
-
'aria-label': translate('Stop learning')
|
|
245
|
-
},
|
|
246
|
-
secondButton: {
|
|
247
|
-
label: translate('Continue learning'),
|
|
248
|
-
type: 'primary',
|
|
249
|
-
customStyle: {
|
|
250
|
-
backgroundColor: get(['common', 'primary'], skin)
|
|
251
|
-
},
|
|
252
|
-
handleOnclick: () => {
|
|
253
|
-
dispatch(closeQuitPopin);
|
|
254
|
-
},
|
|
255
|
-
'aria-label': translate('Continue learning')
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
};
|
|
259
|
-
const buildRankCard = (rank, translate) => {
|
|
260
|
-
return {
|
|
261
|
-
'aria-label': 'Review Card Congrats Container',
|
|
262
|
-
'data-name': 'card-rank',
|
|
263
|
-
animationLottie: {
|
|
264
|
-
'aria-label': translate('New rank animation'),
|
|
265
|
-
'data-name': 'default-lottie',
|
|
266
|
-
animationSrc: 'https://static-staging.coorpacademy.com/animations/review/rank.json',
|
|
267
|
-
loop: true,
|
|
268
|
-
autoplay: true
|
|
269
|
-
},
|
|
270
|
-
cardType: 'card-rank',
|
|
271
|
-
iconAriaLabel: 'Image without information',
|
|
272
|
-
className: undefined,
|
|
273
|
-
reviewCardTitle: translate('You are now'),
|
|
274
|
-
reviewCardValue: `${rank}`,
|
|
275
|
-
rankSuffix: 'th',
|
|
276
|
-
timerAnimation: 200
|
|
277
|
-
};
|
|
278
|
-
};
|
|
279
|
-
const buildCongratsProps = (state, dispatch, options) => {
|
|
280
|
-
if (!state.ui.showCongrats)
|
|
281
|
-
return;
|
|
282
|
-
const { translate, onQuitClick } = options;
|
|
283
|
-
const progression = state.data.progression;
|
|
284
|
-
const stars = progression.state.stars;
|
|
285
|
-
const cardCongratsStar = {
|
|
286
|
-
'aria-label': 'Review Card Congrats Container',
|
|
287
|
-
'data-name': 'card-star',
|
|
288
|
-
animationLottie: {
|
|
289
|
-
'aria-label': translate('Acquired stars animation'),
|
|
290
|
-
'data-name': 'default-lottie',
|
|
291
|
-
className: undefined,
|
|
292
|
-
animationSrc: 'https://static-staging.coorpacademy.com/animations/review/star.json',
|
|
293
|
-
loop: false,
|
|
294
|
-
autoplay: undefined,
|
|
295
|
-
rendererSettings: {
|
|
296
|
-
hideOnTransparent: false
|
|
297
|
-
}
|
|
298
|
-
},
|
|
299
|
-
iconAriaLabel: 'Image without information',
|
|
300
|
-
className: undefined,
|
|
301
|
-
cardType: 'card-star',
|
|
302
|
-
reviewCardTitle: translate('You have won'),
|
|
303
|
-
reviewCardValue: `${stars}`,
|
|
304
|
-
timerAnimation: 200
|
|
305
|
-
};
|
|
306
|
-
const { start, end } = state.data.rank;
|
|
307
|
-
const newRank = start - end;
|
|
308
|
-
const cardCongratsRank = !Number.isNaN(newRank) && newRank > 0 ? buildRankCard(end, translate) : undefined;
|
|
309
|
-
const skillRef = progression.content.ref;
|
|
310
|
-
const buttonRevising = state.ui.showButtonRevising
|
|
311
|
-
? {
|
|
312
|
-
'aria-label': translate('Continue reviewing'),
|
|
313
|
-
label: translate('Continue reviewing'),
|
|
314
|
-
onClick: () => {
|
|
315
|
-
dispatch(postProgression(skillRef));
|
|
316
|
-
},
|
|
317
|
-
type: 'tertiary'
|
|
318
|
-
}
|
|
319
|
-
: undefined;
|
|
320
|
-
const buttonRevisingSkill = {
|
|
321
|
-
'aria-label': translate('Revise another skill'),
|
|
322
|
-
label: translate('Revise another skill'),
|
|
323
|
-
onClick: onQuitClick,
|
|
324
|
-
type: 'primary'
|
|
325
|
-
};
|
|
326
|
-
return {
|
|
327
|
-
'aria-label': 'Review Congratulations',
|
|
328
|
-
'data-name': 'review-congrats',
|
|
329
|
-
animationLottie: buildConfettiAnimation(translate),
|
|
330
|
-
title: translate('Congratulations!'),
|
|
331
|
-
cardCongratsStar,
|
|
332
|
-
cardCongratsRank,
|
|
333
|
-
buttonRevising,
|
|
334
|
-
buttonRevisingSkill
|
|
335
|
-
};
|
|
336
|
-
};
|
|
337
|
-
const isEndOfProgression = (progression) => {
|
|
338
|
-
if (!progression)
|
|
339
|
-
return false;
|
|
340
|
-
return progression.state.nextContent.ref === 'successExitNode';
|
|
341
|
-
};
|
|
342
|
-
export const mapStateToSlidesProps = (state, dispatch, options) => {
|
|
343
|
-
const { translate, onQuitClick, skin, backgroundImage } = options;
|
|
344
|
-
const currentSlideRef = getCurrentSlideRef(state);
|
|
345
|
-
const endReview = isEndOfProgression(state.data.progression);
|
|
346
|
-
const correction = get(['data', 'corrections', currentSlideRef], state);
|
|
347
|
-
const isCorrect = get(['data', 'progression', 'state', 'isCorrect'], state);
|
|
348
|
-
const klf = getOr('', ['data', 'slides', currentSlideRef, 'klf'], state);
|
|
349
|
-
const showQuitPopin = get(['ui', 'showQuitPopin'], state);
|
|
350
|
-
const showCongrats = get(['ui', 'showCongrats'], state);
|
|
351
|
-
const skillName = getOr('', ['data', 'currentSkill', 'name'], state);
|
|
352
|
-
return {
|
|
353
|
-
header: {
|
|
354
|
-
mode: translate('Review Title'),
|
|
355
|
-
skillName,
|
|
356
|
-
onQuitClick: showCongrats
|
|
357
|
-
? onQuitClick
|
|
358
|
-
: () => {
|
|
359
|
-
dispatch(openQuitPopin);
|
|
360
|
-
},
|
|
361
|
-
'aria-label': 'aria-header-wrapper',
|
|
362
|
-
closeButtonAriaLabel: 'aria-close-button',
|
|
363
|
-
steps: buildStepItems(state),
|
|
364
|
-
hiddenSteps: showCongrats
|
|
365
|
-
},
|
|
366
|
-
stack: state.data.progression
|
|
367
|
-
? {
|
|
368
|
-
slides: buildStackSlides(state, dispatch, options),
|
|
369
|
-
validateButton: {
|
|
370
|
-
label: translate('Validate'),
|
|
371
|
-
disabled: !get(['ui', 'slide', currentSlideRef, 'validateButton'], state),
|
|
372
|
-
onClick: () => {
|
|
373
|
-
dispatch(postAnswer);
|
|
374
|
-
}
|
|
375
|
-
},
|
|
376
|
-
correctionPopinProps: correction &&
|
|
377
|
-
getCorrectionPopinProps(dispatch)(isCorrect, correction.correctAnswer, klf, translate, endReview),
|
|
378
|
-
endReview: endReview && state.ui.showCongrats
|
|
379
|
-
}
|
|
380
|
-
: null,
|
|
381
|
-
backgroundImage,
|
|
382
|
-
congrats: buildCongratsProps(state, dispatch, options),
|
|
383
|
-
quitPopin: showQuitPopin
|
|
384
|
-
? buildQuitPopinProps(dispatch)(onQuitClick, translate, skin)
|
|
385
|
-
: undefined
|
|
386
|
-
};
|
|
387
|
-
};
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import { concat, constant, divide, get, getOr, head, includes, indexOf, isEmpty, isNil, map, multiply, pipe, rangeStep, round, set, size, times, toInteger, toString as _toString, __ } from 'lodash/fp';
|
|
2
|
-
import { editAnswer } from '../../actions/ui/answers';
|
|
3
|
-
const qcmProps = (dispatch) => (answers, question) => {
|
|
4
|
-
return {
|
|
5
|
-
type: 'qcm',
|
|
6
|
-
answers: map(choice => {
|
|
7
|
-
const label = getOr('', 'label', choice);
|
|
8
|
-
return {
|
|
9
|
-
title: label,
|
|
10
|
-
selected: includes(label, answers),
|
|
11
|
-
onClick: () => {
|
|
12
|
-
dispatch(editAnswer([label]));
|
|
13
|
-
},
|
|
14
|
-
'aria-label': label
|
|
15
|
-
};
|
|
16
|
-
}, question.content.choices)
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
const qcmDragProps = (dispatch) => (answers, question) => {
|
|
20
|
-
return {
|
|
21
|
-
type: 'qcmDrag',
|
|
22
|
-
answers: map(choice => {
|
|
23
|
-
const label = getOr('', 'label', choice);
|
|
24
|
-
const indexInAnswer = indexOf(label, answers);
|
|
25
|
-
return {
|
|
26
|
-
title: label,
|
|
27
|
-
selected: includes(label, answers),
|
|
28
|
-
order: indexInAnswer,
|
|
29
|
-
onClick: () => {
|
|
30
|
-
dispatch(editAnswer([label]));
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
}, question.content.choices)
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
const qcmGraphicProps = (dispatch) => (answers, question) => {
|
|
37
|
-
return {
|
|
38
|
-
type: 'qcmGraphic',
|
|
39
|
-
answers: map(choice => {
|
|
40
|
-
const label = getOr('', 'label', choice);
|
|
41
|
-
return {
|
|
42
|
-
title: label,
|
|
43
|
-
image: get('media.src.0.url', choice),
|
|
44
|
-
selected: includes(label, answers),
|
|
45
|
-
onClick: () => {
|
|
46
|
-
dispatch(editAnswer([label]));
|
|
47
|
-
},
|
|
48
|
-
ariaLabel: label
|
|
49
|
-
};
|
|
50
|
-
}, question.content.choices)
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
const updateTemplateAnswer = (text, _answers, index, max) => {
|
|
54
|
-
const answers = isEmpty(_answers) ? times(constant(undefined), max) : _answers;
|
|
55
|
-
return map(a => (isNil(a) ? '' : a), set(index, text, answers));
|
|
56
|
-
};
|
|
57
|
-
const templateTextProps = (dispatch, translate, answers, choice, index, maxLength) => {
|
|
58
|
-
return {
|
|
59
|
-
type: 'text',
|
|
60
|
-
name: getOr('', 'name', choice),
|
|
61
|
-
placeholder: translate('Type here'),
|
|
62
|
-
value: get(index, answers),
|
|
63
|
-
onChange: (text) => {
|
|
64
|
-
const newAnswers = updateTemplateAnswer(text, answers, index, maxLength);
|
|
65
|
-
dispatch(editAnswer(newAnswers));
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
const templateSelectProps = (dispatch, translate, answers, choice, index, maxLength) => {
|
|
70
|
-
const answer = get(index, answers);
|
|
71
|
-
const temporaryOption = {
|
|
72
|
-
name: translate('Select an answer'),
|
|
73
|
-
value: '',
|
|
74
|
-
validOption: false,
|
|
75
|
-
selected: true
|
|
76
|
-
};
|
|
77
|
-
const selectOptions = choice.items.map((item) => {
|
|
78
|
-
const itemText = getOr('', 'text', item);
|
|
79
|
-
return {
|
|
80
|
-
name: itemText,
|
|
81
|
-
value: itemText,
|
|
82
|
-
validOption: true,
|
|
83
|
-
selected: itemText === answer
|
|
84
|
-
};
|
|
85
|
-
});
|
|
86
|
-
return {
|
|
87
|
-
type: 'select',
|
|
88
|
-
name: getOr('', 'name', choice),
|
|
89
|
-
onChange: (text) => {
|
|
90
|
-
const newAnswers = updateTemplateAnswer(text, answers, index, maxLength);
|
|
91
|
-
dispatch(editAnswer(newAnswers));
|
|
92
|
-
},
|
|
93
|
-
options: isEmpty(answer) ? concat([temporaryOption], selectOptions) : selectOptions,
|
|
94
|
-
'aria-label': translate('Select an answer')
|
|
95
|
-
};
|
|
96
|
-
};
|
|
97
|
-
const templateProps = (dispatch, translate) => (answers, question) => {
|
|
98
|
-
const choices = question.content.choices;
|
|
99
|
-
const maxLength = size(choices);
|
|
100
|
-
return {
|
|
101
|
-
type: 'template',
|
|
102
|
-
template: get('content.template', question),
|
|
103
|
-
answers: choices.map((choice, index) => choice.type === 'text'
|
|
104
|
-
? templateTextProps(dispatch, translate, answers, choice, index, maxLength)
|
|
105
|
-
: templateSelectProps(dispatch, translate, answers, choice, index, maxLength))
|
|
106
|
-
};
|
|
107
|
-
};
|
|
108
|
-
const basicProps = (dispatch) => (answers, question) => {
|
|
109
|
-
return {
|
|
110
|
-
type: 'freeText',
|
|
111
|
-
placeholder: getOr('', 'content.placeholder', question),
|
|
112
|
-
value: getOr('', '0', answers),
|
|
113
|
-
onChange: (text) => {
|
|
114
|
-
dispatch(editAnswer([text]));
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
};
|
|
118
|
-
const sliderProps = (dispatch) => (answers, question) => {
|
|
119
|
-
const values = rangeStep(getOr(1, 'content.step', question), get('content.min', question), get('content.max', question) + 1
|
|
120
|
-
// Lodash doesn't infer the type very well here
|
|
121
|
-
);
|
|
122
|
-
const stateValue = head(answers) || question.content.min;
|
|
123
|
-
const currentValue = toInteger(stateValue);
|
|
124
|
-
const indexValue = indexOf(currentValue, values);
|
|
125
|
-
const maxValue = size(values) - 1;
|
|
126
|
-
const sliderPosition = divide(indexValue, maxValue);
|
|
127
|
-
const unitLabel = get('content.unitLabel', question);
|
|
128
|
-
return {
|
|
129
|
-
type: 'slider',
|
|
130
|
-
placeholder: question.explanation,
|
|
131
|
-
minLabel: `${question.content.min} ${unitLabel}`,
|
|
132
|
-
maxLabel: `${question.content.max} ${unitLabel}`,
|
|
133
|
-
title: `${currentValue} ${question.content.unitLabel}`,
|
|
134
|
-
value: sliderPosition,
|
|
135
|
-
onChange: (position) => {
|
|
136
|
-
// atom/range handler
|
|
137
|
-
const newValue = pipe(multiply(maxValue), round, get(__, values), _toString)(position);
|
|
138
|
-
dispatch(editAnswer([newValue]));
|
|
139
|
-
},
|
|
140
|
-
onSliderChange: (newValue) => {
|
|
141
|
-
// mobile/slider handler
|
|
142
|
-
dispatch(editAnswer([`${newValue}`]));
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
};
|
|
146
|
-
export const getQuestionType = (question) => question.type;
|
|
147
|
-
const getHelp = (slide) => get('question.explanation', slide);
|
|
148
|
-
const getAnswerUIModel = (question, answers, dispatch, translate) => {
|
|
149
|
-
const type = getQuestionType(question);
|
|
150
|
-
switch (type) {
|
|
151
|
-
case 'qcm':
|
|
152
|
-
return qcmProps(dispatch)(answers, question);
|
|
153
|
-
case 'qcmGraphic':
|
|
154
|
-
return qcmGraphicProps(dispatch)(answers, question);
|
|
155
|
-
case 'qcmDrag':
|
|
156
|
-
return qcmDragProps(dispatch)(answers, question);
|
|
157
|
-
case 'basic':
|
|
158
|
-
return basicProps(dispatch)(answers, question);
|
|
159
|
-
case 'template':
|
|
160
|
-
return templateProps(dispatch, translate)(answers, question);
|
|
161
|
-
case 'slider':
|
|
162
|
-
return sliderProps(dispatch)(answers, question);
|
|
163
|
-
default:
|
|
164
|
-
throw new Error(`${type} is not an handled question.type`);
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
export const mapApiSlideToUi = (dispatch, translate) => (slide, answers, media) => {
|
|
168
|
-
const questionText = getOr('', 'question.header', slide);
|
|
169
|
-
return {
|
|
170
|
-
questionText,
|
|
171
|
-
answerUI: {
|
|
172
|
-
model: getAnswerUIModel(slide.question, answers, dispatch, translate),
|
|
173
|
-
help: getHelp(slide),
|
|
174
|
-
media
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.fetchCorrection = exports.CORRECTION_FETCH_FAILURE = exports.CORRECTION_FETCH_SUCCESS = exports.CORRECTION_FETCH_REQUEST = void 0;
|
|
7
|
-
const redux_task_1 = __importDefault(require("@coorpacademy/redux-task"));
|
|
8
|
-
const get_1 = __importDefault(require("lodash/fp/get"));
|
|
9
|
-
exports.CORRECTION_FETCH_REQUEST = '@@correction/FETCH_REQUEST';
|
|
10
|
-
exports.CORRECTION_FETCH_SUCCESS = '@@correction/FETCH_SUCCESS';
|
|
11
|
-
exports.CORRECTION_FETCH_FAILURE = '@@correction/FETCH_FAILURE';
|
|
12
|
-
const fetchCorrection = (dispatch, getState, { services }) => {
|
|
13
|
-
const state = getState();
|
|
14
|
-
const slideRef = (0, get_1.default)(['ui', 'currentSlideRef'], state);
|
|
15
|
-
const token = (0, get_1.default)(['data', 'token'], state);
|
|
16
|
-
const progressionId = (0, get_1.default)(['data', 'progression', '_id'], state);
|
|
17
|
-
const answer = (0, get_1.default)(['ui', 'answers', slideRef], state);
|
|
18
|
-
const action = (0, redux_task_1.default)({
|
|
19
|
-
types: [exports.CORRECTION_FETCH_REQUEST, exports.CORRECTION_FETCH_SUCCESS, exports.CORRECTION_FETCH_FAILURE],
|
|
20
|
-
meta: { slideRef },
|
|
21
|
-
task: () => services.fetchCorrection(slideRef, token, progressionId, answer)
|
|
22
|
-
});
|
|
23
|
-
return dispatch(action);
|
|
24
|
-
};
|
|
25
|
-
exports.fetchCorrection = fetchCorrection;
|