@coorpacademy/app-review 0.7.7-alpha.3 → 0.7.7-alpha.61
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/api/fetch-skill.d.ts +11 -0
- package/es/actions/api/fetch-skill.js +16 -0
- package/es/actions/api/post-progression.js +2 -0
- package/es/index.js +1 -1
- package/es/reducers/data/current-skill.d.ts +5 -0
- package/es/reducers/data/current-skill.js +13 -0
- package/es/reducers/data/index.d.ts +4 -1
- package/es/reducers/data/index.js +10 -1
- package/es/reducers/index.d.ts +2 -1
- package/es/services/fetch-skill.js +2 -1
- package/es/types/common.d.ts +5 -2
- package/es/views/skills/index.d.ts +3 -23
- package/es/views/skills/index.js +17 -11
- package/es/views/slides/index.js +25 -13
- package/es/views/slides/map-api-slide-to-ui.d.ts +2 -2
- package/es/views/slides/map-api-slide-to-ui.js +14 -11
- package/lib/actions/api/fetch-skill.d.ts +11 -0
- package/lib/actions/api/fetch-skill.js +23 -0
- package/lib/actions/api/post-progression.js +2 -0
- package/lib/index.js +1 -1
- package/lib/reducers/data/current-skill.d.ts +5 -0
- package/lib/reducers/data/current-skill.js +15 -0
- package/lib/reducers/data/index.d.ts +4 -1
- package/lib/reducers/data/index.js +10 -1
- package/lib/reducers/index.d.ts +2 -1
- package/lib/services/fetch-skill.js +2 -1
- package/lib/types/common.d.ts +5 -2
- package/lib/views/skills/index.d.ts +3 -23
- package/lib/views/skills/index.js +17 -11
- package/lib/views/slides/index.js +25 -13
- package/lib/views/slides/map-api-slide-to-ui.d.ts +2 -2
- package/lib/views/slides/map-api-slide-to-ui.js +14 -11
- package/locales/.mtslconfig.json +1 -0
- package/locales/cs/review.json +4 -1
- package/locales/de/review.json +4 -1
- package/locales/en/review.json +11 -12
- package/locales/es/review.json +4 -1
- package/locales/fr/review.json +4 -1
- package/locales/hr/review.json +4 -1
- package/locales/hu/review.json +4 -1
- package/locales/id/review.json +4 -1
- package/locales/it/review.json +4 -1
- package/locales/ja/review.json +4 -1
- package/locales/ko/review.json +4 -1
- package/locales/nl/review.json +4 -1
- package/locales/pl/review.json +4 -1
- package/locales/pt/review.json +4 -1
- package/locales/ro/review.json +4 -1
- package/locales/ru/review.json +4 -1
- package/locales/sk/review.json +4 -1
- package/locales/th/review.json +4 -1
- package/locales/tl/review.json +4 -1
- package/locales/tr/review.json +4 -1
- package/locales/uk/review.json +4 -1
- package/locales/vi/review.json +4 -1
- package/locales/zh/review.json +4 -1
- package/locales/zh_TW/review.json +4 -1
- package/package.json +5 -5
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Dispatch } from 'redux';
|
|
2
|
+
import type { StoreState } from '../../reducers';
|
|
3
|
+
import type { Skill, ThunkOptions } from '../../types/common';
|
|
4
|
+
export declare const SKILL_FETCH_REQUEST: "@@skill/FETCH_REQUEST";
|
|
5
|
+
export declare const SKILL_FETCH_SUCCESS: "@@skill/FETCH_SUCCESS";
|
|
6
|
+
export declare const SKILL_FETCH_FAILURE: "@@skill/FETCH_FAILURE";
|
|
7
|
+
export declare type ReceivedSkill = {
|
|
8
|
+
type: typeof SKILL_FETCH_SUCCESS;
|
|
9
|
+
payload: Skill;
|
|
10
|
+
};
|
|
11
|
+
export declare const fetchSkill: (skillRef: string) => (dispatch: Dispatch, getState: () => StoreState, { services }: ThunkOptions) => ReceivedSkill;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import get from 'lodash/fp/get';
|
|
2
|
+
import buildTask from '@coorpacademy/redux-task';
|
|
3
|
+
export const SKILL_FETCH_REQUEST = '@@skill/FETCH_REQUEST';
|
|
4
|
+
export const SKILL_FETCH_SUCCESS = '@@skill/FETCH_SUCCESS';
|
|
5
|
+
export const SKILL_FETCH_FAILURE = '@@skill/FETCH_FAILURE';
|
|
6
|
+
export const fetchSkill = (skillRef) => (dispatch, getState, { services }) => {
|
|
7
|
+
const action = buildTask({
|
|
8
|
+
types: [SKILL_FETCH_REQUEST, SKILL_FETCH_SUCCESS, SKILL_FETCH_FAILURE],
|
|
9
|
+
task: () => {
|
|
10
|
+
const state = getState();
|
|
11
|
+
const token = get(['data', 'token'], state);
|
|
12
|
+
return services.fetchSkill(skillRef, token);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
return dispatch(action);
|
|
16
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import buildTask from '@coorpacademy/redux-task';
|
|
2
2
|
import get from 'lodash/fp/get';
|
|
3
3
|
import { fetchSlide } from './fetch-slide';
|
|
4
|
+
import { fetchSkill } from './fetch-skill';
|
|
4
5
|
export const POST_PROGRESSION_REQUEST = '@@progression/POST_REQUEST';
|
|
5
6
|
export const POST_PROGRESSION_SUCCESS = '@@progression/POST_SUCCESS';
|
|
6
7
|
export const POST_PROGRESSION_FAILURE = '@@progression/POST_FAILURE';
|
|
@@ -16,5 +17,6 @@ export const postProgression = (skillRef) => async (dispatch, getState, { servic
|
|
|
16
17
|
const progression = response.payload;
|
|
17
18
|
const slideRef = progression.state.nextContent.ref;
|
|
18
19
|
await dispatch(fetchSlide(slideRef));
|
|
20
|
+
await dispatch(fetchSkill(skillRef));
|
|
19
21
|
}
|
|
20
22
|
};
|
package/es/index.js
CHANGED
|
@@ -15,7 +15,7 @@ const ConnectedApp = (options) => {
|
|
|
15
15
|
const props = {
|
|
16
16
|
viewName: useSelector((state) => state.ui.navigation[state.ui.navigation.length - 1]),
|
|
17
17
|
slides: useSelector((state) => mapStateToSlidesProps(state, dispatch, options)),
|
|
18
|
-
skills: useSelector((state) => mapStateToSkillsProps(state)),
|
|
18
|
+
skills: useSelector((state) => mapStateToSkillsProps(state, options)),
|
|
19
19
|
navigateBack: () => dispatch(navigateBack),
|
|
20
20
|
onboarding: {}
|
|
21
21
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ReceivedSkill } from '../../actions/api/fetch-skill';
|
|
2
|
+
import { Skill } from '../../types/common';
|
|
3
|
+
export declare type CurrentSkillState = Skill | null;
|
|
4
|
+
declare const reducer: (state: CurrentSkillState | undefined, action: ReceivedSkill) => CurrentSkillState;
|
|
5
|
+
export default reducer;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SKILL_FETCH_SUCCESS } from '../../actions/api/fetch-skill';
|
|
2
|
+
const initialState = null;
|
|
3
|
+
const reducer = (
|
|
4
|
+
// eslint-disable-next-line default-param-last
|
|
5
|
+
state = initialState, action) => {
|
|
6
|
+
switch (action.type) {
|
|
7
|
+
case SKILL_FETCH_SUCCESS:
|
|
8
|
+
return action.payload;
|
|
9
|
+
default:
|
|
10
|
+
return state;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
export default reducer;
|
|
@@ -4,6 +4,7 @@ import { SkillsState } from './skills';
|
|
|
4
4
|
import { SlidesState } from './slides';
|
|
5
5
|
import { TokenState } from './token';
|
|
6
6
|
import { RankState } from './rank';
|
|
7
|
+
import { CurrentSkillState } from './current-skill';
|
|
7
8
|
export declare type DataState = {
|
|
8
9
|
corrections: CorrectionsState;
|
|
9
10
|
progression: ProgressionState;
|
|
@@ -11,6 +12,7 @@ export declare type DataState = {
|
|
|
11
12
|
slides: SlidesState;
|
|
12
13
|
token: TokenState;
|
|
13
14
|
rank: RankState;
|
|
15
|
+
currentSkill: CurrentSkillState;
|
|
14
16
|
};
|
|
15
17
|
declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
16
18
|
corrections: CorrectionsState;
|
|
@@ -19,5 +21,6 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
19
21
|
slides: SlidesState;
|
|
20
22
|
token: string;
|
|
21
23
|
rank: RankState;
|
|
22
|
-
|
|
24
|
+
currentSkill: CurrentSkillState;
|
|
25
|
+
}>, import("../../actions/api/fetch-skill").ReceivedSkill | import("../../actions/api/post-progression").FetchProgression | import("../../actions/api/post-progression").ReceivedProgression | import("./corrections").CorrectionsAction | import("../../actions/api/fetch-rank").RankAction | import("../../actions/api/post-answer").PostAnswerSuccessAction | import("../../actions/api/fetch-skills").ReceivedSkills | import("./slides").SlidesAction | import("../../actions/data/token").StoreToken>;
|
|
23
26
|
export default _default;
|
|
@@ -5,4 +5,13 @@ import skills from './skills';
|
|
|
5
5
|
import slides from './slides';
|
|
6
6
|
import token from './token';
|
|
7
7
|
import rank from './rank';
|
|
8
|
-
|
|
8
|
+
import currentSkill from './current-skill';
|
|
9
|
+
export default combineReducers({
|
|
10
|
+
corrections,
|
|
11
|
+
progression,
|
|
12
|
+
skills,
|
|
13
|
+
slides,
|
|
14
|
+
token,
|
|
15
|
+
rank,
|
|
16
|
+
currentSkill
|
|
17
|
+
});
|
package/es/reducers/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
12
12
|
slides: import("./data/slides").SlidesState;
|
|
13
13
|
token: string;
|
|
14
14
|
rank: import("./data/rank").RankState;
|
|
15
|
+
currentSkill: import("./data/current-skill").CurrentSkillState;
|
|
15
16
|
}>;
|
|
16
17
|
ui: import("redux").CombinedState<{
|
|
17
18
|
currentSlideRef: string;
|
|
@@ -23,7 +24,7 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
23
24
|
showButtonRevising: boolean;
|
|
24
25
|
showCongrats: boolean;
|
|
25
26
|
}>;
|
|
26
|
-
}>, import("../actions/ui/slides").SetCurrentSlideAction | import("../actions/api/post-progression").FetchProgression | import("../actions/api/post-progression").ReceivedProgression | import("./data/corrections").CorrectionsAction | import("../actions/api/fetch-rank").RankAction | import("../actions/api/fetch-slides-to-review-by-skill-ref").ReceivedSlidesToReviewBySkillRef | import("../actions/api/post-answer").PostAnswerRequestAction | import("../actions/api/post-answer").PostAnswerSuccessAction | import("../actions/api/fetch-skills").ReceivedSkills | import("./data/slides").SlidesAction | import("../actions/data/token").StoreToken | import("../actions/ui/next-slide").NextSlideAction | import("../actions/ui/navigation").NavigateToAction | import("../actions/ui/navigation").NavigateBackAction | import("../actions/ui/answers").EditAnswerAction | {
|
|
27
|
+
}>, import("../actions/ui/slides").SetCurrentSlideAction | import("../actions/api/fetch-skill").ReceivedSkill | import("../actions/api/post-progression").FetchProgression | import("../actions/api/post-progression").ReceivedProgression | import("./data/corrections").CorrectionsAction | import("../actions/api/fetch-rank").RankAction | import("../actions/api/fetch-slides-to-review-by-skill-ref").ReceivedSlidesToReviewBySkillRef | import("../actions/api/post-answer").PostAnswerRequestAction | import("../actions/api/post-answer").PostAnswerSuccessAction | import("../actions/api/fetch-skills").ReceivedSkills | import("./data/slides").SlidesAction | import("../actions/data/token").StoreToken | import("../actions/ui/next-slide").NextSlideAction | import("../actions/ui/navigation").NavigateToAction | import("../actions/ui/navigation").NavigateBackAction | import("../actions/ui/answers").EditAnswerAction | {
|
|
27
28
|
type: "@@ui/OPEN_POPIN";
|
|
28
29
|
} | {
|
|
29
30
|
type: "@@ui/CLOSE_POPIN";
|
|
@@ -6,5 +6,6 @@ export const fetchSkill = async (skillRef, token) => {
|
|
|
6
6
|
const response = await crossFetch(`${host}/api/v2/skills?conditions={"ref":"${skillRef}"}`, {
|
|
7
7
|
headers: { authorization: token }
|
|
8
8
|
});
|
|
9
|
-
|
|
9
|
+
const skills = await toJSON(response);
|
|
10
|
+
return skills[0];
|
|
10
11
|
};
|
package/es/types/common.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export declare type ViewName = 'skills' | 'onboarding' | 'slides' | 'loader';
|
|
2
|
+
export interface Translate {
|
|
3
|
+
(key: string, data?: Record<string, string>): string;
|
|
4
|
+
}
|
|
2
5
|
export declare type ChoiceFromAPI = {
|
|
3
6
|
_id: string;
|
|
4
7
|
id?: string;
|
|
@@ -146,13 +149,13 @@ export declare type Options = {
|
|
|
146
149
|
services: Services;
|
|
147
150
|
};
|
|
148
151
|
export declare type ConnectedOptions = {
|
|
149
|
-
translate:
|
|
152
|
+
translate: Translate;
|
|
150
153
|
onQuitClick: () => void;
|
|
151
154
|
};
|
|
152
155
|
export declare type AppOptions = ConnectedOptions & {
|
|
153
156
|
token: string;
|
|
154
157
|
skillRef?: string;
|
|
155
|
-
services
|
|
158
|
+
services?: Services;
|
|
156
159
|
callbackOnViewChanged?: (viewName: ViewName) => void;
|
|
157
160
|
};
|
|
158
161
|
export declare type ThunkOptions = {
|
|
@@ -1,24 +1,4 @@
|
|
|
1
|
+
import { ReviewSkillsProps } from '@coorpacademy/components/es/template/app-review/skills/prop-types';
|
|
1
2
|
import { StoreState } from '../../reducers';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
skillTitle: string;
|
|
5
|
-
skillAriaLabel: string;
|
|
6
|
-
buttonLabel: string;
|
|
7
|
-
buttonAriaLabel: string;
|
|
8
|
-
reviseLabel: string;
|
|
9
|
-
reviseAriaLabel: string;
|
|
10
|
-
isCustom: boolean;
|
|
11
|
-
onClick: () => void;
|
|
12
|
-
};
|
|
13
|
-
declare type NoSkillsProps = {
|
|
14
|
-
iconSkillAriaLabel: string;
|
|
15
|
-
};
|
|
16
|
-
declare type SkillsProps = NoSkillsProps & {
|
|
17
|
-
'aria-label'?: string;
|
|
18
|
-
title: string;
|
|
19
|
-
isLoading?: boolean;
|
|
20
|
-
isLoadingAriaLabel: string;
|
|
21
|
-
listSkills: SkillCard[];
|
|
22
|
-
};
|
|
23
|
-
export { SkillsProps };
|
|
24
|
-
export declare const mapStateToSkillsProps: (state: StoreState) => SkillsProps;
|
|
3
|
+
import type { ConnectedOptions } from '../../types/common';
|
|
4
|
+
export declare const mapStateToSkillsProps: (state: StoreState, options: ConnectedOptions) => ReviewSkillsProps;
|
package/es/views/skills/index.js
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
export const mapStateToSkillsProps = (state) => {
|
|
1
|
+
export const mapStateToSkillsProps = (state, options) => {
|
|
2
|
+
const { translate } = options;
|
|
2
3
|
return {
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
'aria-label': translate('Review Skills Container'),
|
|
5
|
+
title: translate('Skills you can review'),
|
|
5
6
|
isLoading: false,
|
|
6
|
-
isLoadingAriaLabel: '
|
|
7
|
+
isLoadingAriaLabel: 'Review skills container is loading',
|
|
7
8
|
listSkills: state.data.skills.map(skill => ({
|
|
8
|
-
'aria-label': '',
|
|
9
|
+
'aria-label': translate('Skill Card'),
|
|
9
10
|
isCustom: skill.custom,
|
|
10
11
|
skillTitle: skill.name,
|
|
11
|
-
skillAriaLabel:
|
|
12
|
-
buttonLabel: '
|
|
13
|
-
buttonAriaLabel: '
|
|
14
|
-
reviseLabel: '
|
|
15
|
-
reviseAriaLabel: '
|
|
12
|
+
skillAriaLabel: skill.name,
|
|
13
|
+
buttonLabel: translate('Review this skill'),
|
|
14
|
+
buttonAriaLabel: translate('Review this skill'),
|
|
15
|
+
reviseLabel: translate('{{count}} questions to review', { count: `${skill.slidesToReview}` }),
|
|
16
|
+
reviseAriaLabel: translate('{{count}} questions to review', {
|
|
17
|
+
count: `${skill.slidesToReview}`
|
|
18
|
+
}),
|
|
16
19
|
// eslint-disable-next-line no-console
|
|
17
20
|
onClick: () => console.log('@todo plug dispatcher select skill')
|
|
18
|
-
}))
|
|
21
|
+
})),
|
|
22
|
+
titleNoSkills: translate('No skill to revise'),
|
|
23
|
+
textNoSkills: translate('Complete courses before revising'),
|
|
24
|
+
iconSkillAriaLabel: 'Image without information'
|
|
19
25
|
};
|
|
20
26
|
};
|
package/es/views/slides/index.js
CHANGED
|
@@ -60,7 +60,11 @@ const getCurrentSlideRef = (state) => {
|
|
|
60
60
|
const content = progression.state.content;
|
|
61
61
|
return content.ref;
|
|
62
62
|
};
|
|
63
|
-
const
|
|
63
|
+
const isLastSlideAnswered = (slidesRef, slideRef) => {
|
|
64
|
+
return last(slidesRef) === slideRef;
|
|
65
|
+
};
|
|
66
|
+
const buildStackSlides = (state, dispatch, options) => {
|
|
67
|
+
const { translate } = options;
|
|
64
68
|
const currentSlideRef = getCurrentSlideRef(state);
|
|
65
69
|
const progression = state.data.progression;
|
|
66
70
|
if (!currentSlideRef || !progression)
|
|
@@ -69,22 +73,25 @@ const buildStackSlides = (state, dispatch) => {
|
|
|
69
73
|
// @ts-expect-error typescript does not support capped versions of lodash functions
|
|
70
74
|
const stack = reduce.convert({ cap: false })((acc, uiSlide, _index) => {
|
|
71
75
|
const index = toInteger(_index);
|
|
72
|
-
const positions = state.ui.positions;
|
|
73
|
-
const position = positions[index];
|
|
74
76
|
const slideRef = slideRefs[index];
|
|
77
|
+
const lastAnsweredSlideRef = isLastSlideAnswered(progression.state.slides, slideRef);
|
|
78
|
+
const positions = state.ui.positions;
|
|
79
|
+
// when unstack the last answered slide (position -1), we set the position to 0 only during the animation
|
|
80
|
+
// to avoid to hide the slide (caused by the position -1).
|
|
81
|
+
const position = lastAnsweredSlideRef && positions[index] === -1 ? 0 : positions[index];
|
|
75
82
|
if (!slideRef)
|
|
76
83
|
return set(index, { ...uiSlide, position }, acc);
|
|
77
84
|
const slideFromAPI = get(slideRef, state.data.slides);
|
|
78
85
|
if (!slideFromAPI)
|
|
79
86
|
return set(index, { ...uiSlide, position }, acc);
|
|
80
87
|
const answers = getOr([], ['ui', 'answers', slideRef], state);
|
|
81
|
-
const { questionText, answerUI } = mapApiSlideToUi(dispatch)(slideFromAPI, answers);
|
|
88
|
+
const { questionText, answerUI } = mapApiSlideToUi(dispatch, translate)(slideFromAPI, answers);
|
|
82
89
|
const { title: parentContentTitle, type: parentContentType } = slideFromAPI.parentContentTitle;
|
|
83
90
|
const isCurrentSlideRef = currentSlideRef === slideRef;
|
|
84
91
|
const slideUI = get(['ui', 'slide', slideRef], state);
|
|
85
92
|
const animateCorrectionPopin = isCurrentSlideRef && slideUI.animateCorrectionPopin;
|
|
86
93
|
const showCorrectionPopin = isCurrentSlideRef && slideUI.showCorrectionPopin;
|
|
87
|
-
const animationType = slideUI.animationType;
|
|
94
|
+
const animationType = lastAnsweredSlideRef ? slideUI.animationType : undefined;
|
|
88
95
|
const updatedUiSlide = {
|
|
89
96
|
...uiSlide,
|
|
90
97
|
position,
|
|
@@ -93,7 +100,10 @@ const buildStackSlides = (state, dispatch) => {
|
|
|
93
100
|
loading: false,
|
|
94
101
|
questionText,
|
|
95
102
|
answerUI,
|
|
96
|
-
parentContentTitle:
|
|
103
|
+
parentContentTitle: translate('Content Parent Title', {
|
|
104
|
+
contentTitle: parentContentTitle,
|
|
105
|
+
contentType: parentContentType
|
|
106
|
+
}),
|
|
97
107
|
animationType
|
|
98
108
|
};
|
|
99
109
|
return set(index, updatedUiSlide, acc);
|
|
@@ -167,7 +177,8 @@ export const buildStepItems = (state) => {
|
|
|
167
177
|
});
|
|
168
178
|
return steps;
|
|
169
179
|
};
|
|
170
|
-
const getCorrectionPopinProps = (dispatch) => (isCorrect, correctAnswer, klf, translate) => {
|
|
180
|
+
const getCorrectionPopinProps = (dispatch) => (isCorrect, correctAnswer, klf, translate, endReview) => {
|
|
181
|
+
const nextLabel = endReview ? translate('Continue') : translate('Next Question');
|
|
171
182
|
return {
|
|
172
183
|
klf: isCorrect
|
|
173
184
|
? undefined
|
|
@@ -178,11 +189,11 @@ const getCorrectionPopinProps = (dispatch) => (isCorrect, correctAnswer, klf, tr
|
|
|
178
189
|
resultLabel: isCorrect ? translate('Correct Answer') : translate('Wrong Answer'),
|
|
179
190
|
information: {
|
|
180
191
|
label: isCorrect ? translate('KLF') : translate('Correct Answer'),
|
|
181
|
-
message: isCorrect ? klf : join(',', correctAnswer)
|
|
192
|
+
message: isCorrect ? klf : join(', ', correctAnswer)
|
|
182
193
|
},
|
|
183
194
|
next: {
|
|
184
|
-
'aria-label':
|
|
185
|
-
label:
|
|
195
|
+
'aria-label': nextLabel,
|
|
196
|
+
label: nextLabel,
|
|
186
197
|
onClick: () => {
|
|
187
198
|
dispatch(nextSlide);
|
|
188
199
|
}
|
|
@@ -309,10 +320,11 @@ export const mapStateToSlidesProps = (state, dispatch, options) => {
|
|
|
309
320
|
const klf = getOr('', ['data', 'slides', currentSlideRef, 'klf'], state);
|
|
310
321
|
const showQuitPopin = get(['ui', 'showQuitPopin'], state);
|
|
311
322
|
const showCongrats = get(['ui', 'showCongrats'], state);
|
|
323
|
+
const skillName = getOr('', ['data', 'currentSkill', 'name'], state);
|
|
312
324
|
return {
|
|
313
325
|
header: {
|
|
314
326
|
mode: translate('Review Title'),
|
|
315
|
-
skillName
|
|
327
|
+
skillName,
|
|
316
328
|
onQuitClick: () => dispatch(openQuitPopin),
|
|
317
329
|
'aria-label': 'aria-header-wrapper',
|
|
318
330
|
closeButtonAriaLabel: 'aria-close-button',
|
|
@@ -320,7 +332,7 @@ export const mapStateToSlidesProps = (state, dispatch, options) => {
|
|
|
320
332
|
hiddenSteps: showCongrats
|
|
321
333
|
},
|
|
322
334
|
stack: {
|
|
323
|
-
slides: buildStackSlides(state, dispatch),
|
|
335
|
+
slides: buildStackSlides(state, dispatch, options),
|
|
324
336
|
validateButton: {
|
|
325
337
|
label: translate('Validate'),
|
|
326
338
|
disabled: !get(['ui', 'slide', currentSlideRef, 'validateButton'], state),
|
|
@@ -329,7 +341,7 @@ export const mapStateToSlidesProps = (state, dispatch, options) => {
|
|
|
329
341
|
}
|
|
330
342
|
},
|
|
331
343
|
correctionPopinProps: correction &&
|
|
332
|
-
getCorrectionPopinProps(dispatch)(isCorrect, correction.correctAnswer, klf, translate),
|
|
344
|
+
getCorrectionPopinProps(dispatch)(isCorrect, correction.correctAnswer, klf, translate, endReview),
|
|
333
345
|
endReview: endReview && state.ui.showCongrats
|
|
334
346
|
},
|
|
335
347
|
congrats: buildCongratsProps(state, dispatch, options),
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Dispatch } from 'redux';
|
|
2
2
|
import { AnswerUI } from '../../types/slides';
|
|
3
|
-
import { Question, SlideFromAPI } from '../../types/common';
|
|
3
|
+
import { Question, SlideFromAPI, Translate } from '../../types/common';
|
|
4
4
|
export declare const getQuestionType: (question: Question) => Question['type'];
|
|
5
|
-
export declare const mapApiSlideToUi: (dispatch: Dispatch) => (slide: SlideFromAPI, answers: string[]) => {
|
|
5
|
+
export declare const mapApiSlideToUi: (dispatch: Dispatch, translate: Translate) => (slide: SlideFromAPI, answers: string[]) => {
|
|
6
6
|
questionText: string;
|
|
7
7
|
answerUI: AnswerUI;
|
|
8
8
|
};
|
|
@@ -54,11 +54,11 @@ const updateTemplateAnswer = (text, _answers, index, max) => {
|
|
|
54
54
|
const answers = isEmpty(_answers) ? times(constant(undefined), max) : _answers;
|
|
55
55
|
return map(a => (isNil(a) ? '' : a), set(index, text, answers));
|
|
56
56
|
};
|
|
57
|
-
const templateTextProps = (dispatch, answers, choice, index, maxLength) => {
|
|
57
|
+
const templateTextProps = (dispatch, translate, answers, choice, index, maxLength) => {
|
|
58
58
|
return {
|
|
59
59
|
type: 'text',
|
|
60
60
|
name: getOr('', 'name', choice),
|
|
61
|
-
placeholder: 'Type here',
|
|
61
|
+
placeholder: translate('Type here'),
|
|
62
62
|
value: get(index, answers),
|
|
63
63
|
onChange: (text) => {
|
|
64
64
|
const newAnswers = updateTemplateAnswer(text, answers, index, maxLength);
|
|
@@ -66,10 +66,10 @@ const templateTextProps = (dispatch, answers, choice, index, maxLength) => {
|
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
68
|
};
|
|
69
|
-
const templateSelectProps = (dispatch, answers, choice, index, maxLength) => {
|
|
69
|
+
const templateSelectProps = (dispatch, translate, answers, choice, index, maxLength) => {
|
|
70
70
|
const answer = get(index, answers);
|
|
71
71
|
const temporaryOption = {
|
|
72
|
-
name: 'Select an answer',
|
|
72
|
+
name: translate('Select an answer'),
|
|
73
73
|
value: '',
|
|
74
74
|
validOption: false,
|
|
75
75
|
selected: true
|
|
@@ -93,15 +93,15 @@ const templateSelectProps = (dispatch, answers, choice, index, maxLength) => {
|
|
|
93
93
|
options: isEmpty(answer) ? concat([temporaryOption], selectOptions) : selectOptions
|
|
94
94
|
};
|
|
95
95
|
};
|
|
96
|
-
const templateProps = (dispatch) => (answers, question) => {
|
|
96
|
+
const templateProps = (dispatch, translate) => (answers, question) => {
|
|
97
97
|
const choices = question.content.choices;
|
|
98
98
|
const maxLength = size(choices);
|
|
99
99
|
return {
|
|
100
100
|
type: 'template',
|
|
101
101
|
template: get('content.template', question),
|
|
102
102
|
answers: choices.map((choice, index) => choice.type === 'text'
|
|
103
|
-
? templateTextProps(dispatch, answers, choice, index, maxLength)
|
|
104
|
-
: templateSelectProps(dispatch, answers, choice, index, maxLength))
|
|
103
|
+
? templateTextProps(dispatch, translate, answers, choice, index, maxLength)
|
|
104
|
+
: templateSelectProps(dispatch, translate, answers, choice, index, maxLength))
|
|
105
105
|
};
|
|
106
106
|
};
|
|
107
107
|
const basicProps = (dispatch) => (answers, question) => {
|
|
@@ -144,7 +144,7 @@ const sliderProps = (dispatch) => (answers, question) => {
|
|
|
144
144
|
};
|
|
145
145
|
export const getQuestionType = (question) => question.type;
|
|
146
146
|
const getHelp = (slide) => get('question.explanation', slide);
|
|
147
|
-
const getAnswerUIModel = (question, answers, dispatch) => {
|
|
147
|
+
const getAnswerUIModel = (question, answers, dispatch, translate) => {
|
|
148
148
|
const type = getQuestionType(question);
|
|
149
149
|
switch (type) {
|
|
150
150
|
case 'qcm':
|
|
@@ -156,17 +156,20 @@ const getAnswerUIModel = (question, answers, dispatch) => {
|
|
|
156
156
|
case 'basic':
|
|
157
157
|
return basicProps(dispatch)(answers, question);
|
|
158
158
|
case 'template':
|
|
159
|
-
return templateProps(dispatch)(answers, question);
|
|
159
|
+
return templateProps(dispatch, translate)(answers, question);
|
|
160
160
|
case 'slider':
|
|
161
161
|
return sliderProps(dispatch)(answers, question);
|
|
162
162
|
default:
|
|
163
163
|
throw new Error(`${type} is not an handled question.type`);
|
|
164
164
|
}
|
|
165
165
|
};
|
|
166
|
-
export const mapApiSlideToUi = (dispatch) => (slide, answers) => {
|
|
166
|
+
export const mapApiSlideToUi = (dispatch, translate) => (slide, answers) => {
|
|
167
167
|
const questionText = getOr('', 'question.header', slide);
|
|
168
168
|
return {
|
|
169
169
|
questionText,
|
|
170
|
-
answerUI: {
|
|
170
|
+
answerUI: {
|
|
171
|
+
model: getAnswerUIModel(slide.question, answers, dispatch, translate),
|
|
172
|
+
help: getHelp(slide)
|
|
173
|
+
}
|
|
171
174
|
};
|
|
172
175
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Dispatch } from 'redux';
|
|
2
|
+
import type { StoreState } from '../../reducers';
|
|
3
|
+
import type { Skill, ThunkOptions } from '../../types/common';
|
|
4
|
+
export declare const SKILL_FETCH_REQUEST: "@@skill/FETCH_REQUEST";
|
|
5
|
+
export declare const SKILL_FETCH_SUCCESS: "@@skill/FETCH_SUCCESS";
|
|
6
|
+
export declare const SKILL_FETCH_FAILURE: "@@skill/FETCH_FAILURE";
|
|
7
|
+
export declare type ReceivedSkill = {
|
|
8
|
+
type: typeof SKILL_FETCH_SUCCESS;
|
|
9
|
+
payload: Skill;
|
|
10
|
+
};
|
|
11
|
+
export declare const fetchSkill: (skillRef: string) => (dispatch: Dispatch, getState: () => StoreState, { services }: ThunkOptions) => ReceivedSkill;
|
|
@@ -0,0 +1,23 @@
|
|
|
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.fetchSkill = exports.SKILL_FETCH_FAILURE = exports.SKILL_FETCH_SUCCESS = exports.SKILL_FETCH_REQUEST = void 0;
|
|
7
|
+
const get_1 = __importDefault(require("lodash/fp/get"));
|
|
8
|
+
const redux_task_1 = __importDefault(require("@coorpacademy/redux-task"));
|
|
9
|
+
exports.SKILL_FETCH_REQUEST = '@@skill/FETCH_REQUEST';
|
|
10
|
+
exports.SKILL_FETCH_SUCCESS = '@@skill/FETCH_SUCCESS';
|
|
11
|
+
exports.SKILL_FETCH_FAILURE = '@@skill/FETCH_FAILURE';
|
|
12
|
+
const fetchSkill = (skillRef) => (dispatch, getState, { services }) => {
|
|
13
|
+
const action = (0, redux_task_1.default)({
|
|
14
|
+
types: [exports.SKILL_FETCH_REQUEST, exports.SKILL_FETCH_SUCCESS, exports.SKILL_FETCH_FAILURE],
|
|
15
|
+
task: () => {
|
|
16
|
+
const state = getState();
|
|
17
|
+
const token = (0, get_1.default)(['data', 'token'], state);
|
|
18
|
+
return services.fetchSkill(skillRef, token);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return dispatch(action);
|
|
22
|
+
};
|
|
23
|
+
exports.fetchSkill = fetchSkill;
|
|
@@ -7,6 +7,7 @@ exports.postProgression = exports.POST_PROGRESSION_FAILURE = exports.POST_PROGRE
|
|
|
7
7
|
const redux_task_1 = __importDefault(require("@coorpacademy/redux-task"));
|
|
8
8
|
const get_1 = __importDefault(require("lodash/fp/get"));
|
|
9
9
|
const fetch_slide_1 = require("./fetch-slide");
|
|
10
|
+
const fetch_skill_1 = require("./fetch-skill");
|
|
10
11
|
exports.POST_PROGRESSION_REQUEST = '@@progression/POST_REQUEST';
|
|
11
12
|
exports.POST_PROGRESSION_SUCCESS = '@@progression/POST_SUCCESS';
|
|
12
13
|
exports.POST_PROGRESSION_FAILURE = '@@progression/POST_FAILURE';
|
|
@@ -22,6 +23,7 @@ const postProgression = (skillRef) => async (dispatch, getState, { services }) =
|
|
|
22
23
|
const progression = response.payload;
|
|
23
24
|
const slideRef = progression.state.nextContent.ref;
|
|
24
25
|
await dispatch((0, fetch_slide_1.fetchSlide)(slideRef));
|
|
26
|
+
await dispatch((0, fetch_skill_1.fetchSkill)(skillRef));
|
|
25
27
|
}
|
|
26
28
|
};
|
|
27
29
|
exports.postProgression = postProgression;
|
package/lib/index.js
CHANGED
|
@@ -43,7 +43,7 @@ const ConnectedApp = (options) => {
|
|
|
43
43
|
const props = {
|
|
44
44
|
viewName: (0, react_redux_1.useSelector)((state) => state.ui.navigation[state.ui.navigation.length - 1]),
|
|
45
45
|
slides: (0, react_redux_1.useSelector)((state) => (0, slides_1.mapStateToSlidesProps)(state, dispatch, options)),
|
|
46
|
-
skills: (0, react_redux_1.useSelector)((state) => (0, skills_1.mapStateToSkillsProps)(state)),
|
|
46
|
+
skills: (0, react_redux_1.useSelector)((state) => (0, skills_1.mapStateToSkillsProps)(state, options)),
|
|
47
47
|
navigateBack: () => dispatch(navigation_1.navigateBack),
|
|
48
48
|
onboarding: {}
|
|
49
49
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ReceivedSkill } from '../../actions/api/fetch-skill';
|
|
2
|
+
import { Skill } from '../../types/common';
|
|
3
|
+
export declare type CurrentSkillState = Skill | null;
|
|
4
|
+
declare const reducer: (state: CurrentSkillState | undefined, action: ReceivedSkill) => CurrentSkillState;
|
|
5
|
+
export default reducer;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const fetch_skill_1 = require("../../actions/api/fetch-skill");
|
|
4
|
+
const initialState = null;
|
|
5
|
+
const reducer = (
|
|
6
|
+
// eslint-disable-next-line default-param-last
|
|
7
|
+
state = initialState, action) => {
|
|
8
|
+
switch (action.type) {
|
|
9
|
+
case fetch_skill_1.SKILL_FETCH_SUCCESS:
|
|
10
|
+
return action.payload;
|
|
11
|
+
default:
|
|
12
|
+
return state;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
exports.default = reducer;
|
|
@@ -4,6 +4,7 @@ import { SkillsState } from './skills';
|
|
|
4
4
|
import { SlidesState } from './slides';
|
|
5
5
|
import { TokenState } from './token';
|
|
6
6
|
import { RankState } from './rank';
|
|
7
|
+
import { CurrentSkillState } from './current-skill';
|
|
7
8
|
export declare type DataState = {
|
|
8
9
|
corrections: CorrectionsState;
|
|
9
10
|
progression: ProgressionState;
|
|
@@ -11,6 +12,7 @@ export declare type DataState = {
|
|
|
11
12
|
slides: SlidesState;
|
|
12
13
|
token: TokenState;
|
|
13
14
|
rank: RankState;
|
|
15
|
+
currentSkill: CurrentSkillState;
|
|
14
16
|
};
|
|
15
17
|
declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
16
18
|
corrections: CorrectionsState;
|
|
@@ -19,5 +21,6 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
19
21
|
slides: SlidesState;
|
|
20
22
|
token: string;
|
|
21
23
|
rank: RankState;
|
|
22
|
-
|
|
24
|
+
currentSkill: CurrentSkillState;
|
|
25
|
+
}>, import("../../actions/api/fetch-skill").ReceivedSkill | import("../../actions/api/post-progression").FetchProgression | import("../../actions/api/post-progression").ReceivedProgression | import("./corrections").CorrectionsAction | import("../../actions/api/fetch-rank").RankAction | import("../../actions/api/post-answer").PostAnswerSuccessAction | import("../../actions/api/fetch-skills").ReceivedSkills | import("./slides").SlidesAction | import("../../actions/data/token").StoreToken>;
|
|
23
26
|
export default _default;
|
|
@@ -10,4 +10,13 @@ const skills_1 = __importDefault(require("./skills"));
|
|
|
10
10
|
const slides_1 = __importDefault(require("./slides"));
|
|
11
11
|
const token_1 = __importDefault(require("./token"));
|
|
12
12
|
const rank_1 = __importDefault(require("./rank"));
|
|
13
|
-
|
|
13
|
+
const current_skill_1 = __importDefault(require("./current-skill"));
|
|
14
|
+
exports.default = (0, redux_1.combineReducers)({
|
|
15
|
+
corrections: corrections_1.default,
|
|
16
|
+
progression: progression_1.default,
|
|
17
|
+
skills: skills_1.default,
|
|
18
|
+
slides: slides_1.default,
|
|
19
|
+
token: token_1.default,
|
|
20
|
+
rank: rank_1.default,
|
|
21
|
+
currentSkill: current_skill_1.default
|
|
22
|
+
});
|
package/lib/reducers/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
12
12
|
slides: import("./data/slides").SlidesState;
|
|
13
13
|
token: string;
|
|
14
14
|
rank: import("./data/rank").RankState;
|
|
15
|
+
currentSkill: import("./data/current-skill").CurrentSkillState;
|
|
15
16
|
}>;
|
|
16
17
|
ui: import("redux").CombinedState<{
|
|
17
18
|
currentSlideRef: string;
|
|
@@ -23,7 +24,7 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
23
24
|
showButtonRevising: boolean;
|
|
24
25
|
showCongrats: boolean;
|
|
25
26
|
}>;
|
|
26
|
-
}>, import("../actions/ui/slides").SetCurrentSlideAction | import("../actions/api/post-progression").FetchProgression | import("../actions/api/post-progression").ReceivedProgression | import("./data/corrections").CorrectionsAction | import("../actions/api/fetch-rank").RankAction | import("../actions/api/fetch-slides-to-review-by-skill-ref").ReceivedSlidesToReviewBySkillRef | import("../actions/api/post-answer").PostAnswerRequestAction | import("../actions/api/post-answer").PostAnswerSuccessAction | import("../actions/api/fetch-skills").ReceivedSkills | import("./data/slides").SlidesAction | import("../actions/data/token").StoreToken | import("../actions/ui/next-slide").NextSlideAction | import("../actions/ui/navigation").NavigateToAction | import("../actions/ui/navigation").NavigateBackAction | import("../actions/ui/answers").EditAnswerAction | {
|
|
27
|
+
}>, import("../actions/ui/slides").SetCurrentSlideAction | import("../actions/api/fetch-skill").ReceivedSkill | import("../actions/api/post-progression").FetchProgression | import("../actions/api/post-progression").ReceivedProgression | import("./data/corrections").CorrectionsAction | import("../actions/api/fetch-rank").RankAction | import("../actions/api/fetch-slides-to-review-by-skill-ref").ReceivedSlidesToReviewBySkillRef | import("../actions/api/post-answer").PostAnswerRequestAction | import("../actions/api/post-answer").PostAnswerSuccessAction | import("../actions/api/fetch-skills").ReceivedSkills | import("./data/slides").SlidesAction | import("../actions/data/token").StoreToken | import("../actions/ui/next-slide").NextSlideAction | import("../actions/ui/navigation").NavigateToAction | import("../actions/ui/navigation").NavigateBackAction | import("../actions/ui/answers").EditAnswerAction | {
|
|
27
28
|
type: "@@ui/OPEN_POPIN";
|
|
28
29
|
} | {
|
|
29
30
|
type: "@@ui/CLOSE_POPIN";
|
|
@@ -12,6 +12,7 @@ const fetchSkill = async (skillRef, token) => {
|
|
|
12
12
|
const response = await (0, cross_fetch_1.default)(`${host}/api/v2/skills?conditions={"ref":"${skillRef}"}`, {
|
|
13
13
|
headers: { authorization: token }
|
|
14
14
|
});
|
|
15
|
-
|
|
15
|
+
const skills = await (0, fetch_responses_1.toJSON)(response);
|
|
16
|
+
return skills[0];
|
|
16
17
|
};
|
|
17
18
|
exports.fetchSkill = fetchSkill;
|
package/lib/types/common.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export declare type ViewName = 'skills' | 'onboarding' | 'slides' | 'loader';
|
|
2
|
+
export interface Translate {
|
|
3
|
+
(key: string, data?: Record<string, string>): string;
|
|
4
|
+
}
|
|
2
5
|
export declare type ChoiceFromAPI = {
|
|
3
6
|
_id: string;
|
|
4
7
|
id?: string;
|
|
@@ -146,13 +149,13 @@ export declare type Options = {
|
|
|
146
149
|
services: Services;
|
|
147
150
|
};
|
|
148
151
|
export declare type ConnectedOptions = {
|
|
149
|
-
translate:
|
|
152
|
+
translate: Translate;
|
|
150
153
|
onQuitClick: () => void;
|
|
151
154
|
};
|
|
152
155
|
export declare type AppOptions = ConnectedOptions & {
|
|
153
156
|
token: string;
|
|
154
157
|
skillRef?: string;
|
|
155
|
-
services
|
|
158
|
+
services?: Services;
|
|
156
159
|
callbackOnViewChanged?: (viewName: ViewName) => void;
|
|
157
160
|
};
|
|
158
161
|
export declare type ThunkOptions = {
|