@coorpacademy/app-review 0.7.6 → 0.7.7-alpha.13

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.
@@ -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
  };
@@ -1,24 +1,4 @@
1
+ import { ReviewSkillsProps } from '@coorpacademy/components/es/template/app-review/skills/prop-types';
1
2
  import { StoreState } from '../../reducers';
2
- declare type SkillCard = {
3
- 'aria-label': string;
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;
@@ -1,20 +1,24 @@
1
- export const mapStateToSkillsProps = (state) => {
1
+ export const mapStateToSkillsProps = (state, options) => {
2
+ const { translate } = options;
2
3
  return {
3
- title: '@todo title',
4
- iconSkillAriaLabel: '@todo iconSkillAriaLabel',
4
+ 'aria-label': translate('Review Skills Container'),
5
+ title: translate('Skills you can review'),
5
6
  isLoading: false,
6
- isLoadingAriaLabel: '@todo loading',
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: '@todo skill aria label',
12
- buttonLabel: '@todo button',
13
- buttonAriaLabel: '@todo button aria label',
14
- reviseLabel: '@todo revise',
15
- reviseAriaLabel: '@todo revise aria label',
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', { count: skill.slidesToReview }),
16
17
  // eslint-disable-next-line no-console
17
18
  onClick: () => console.log('@todo plug dispatcher select skill')
18
- }))
19
+ })),
20
+ titleNoSkills: translate('No skill to revise'),
21
+ textNoSkills: translate('Complete courses before revising'),
22
+ iconSkillAriaLabel: 'Image without information'
19
23
  };
20
24
  };
@@ -60,7 +60,11 @@ const getCurrentSlideRef = (state) => {
60
60
  const content = progression.state.content;
61
61
  return content.ref;
62
62
  };
63
- const buildStackSlides = (state, dispatch) => {
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,9 +73,12 @@ 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);
@@ -84,7 +91,7 @@ const buildStackSlides = (state, dispatch) => {
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: `From "${parentContentTitle}" ${parentContentType}`,
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);
@@ -320,7 +330,7 @@ export const mapStateToSlidesProps = (state, dispatch, options) => {
320
330
  hiddenSteps: showCongrats
321
331
  },
322
332
  stack: {
323
- slides: buildStackSlides(state, dispatch),
333
+ slides: buildStackSlides(state, dispatch, options),
324
334
  validateButton: {
325
335
  label: translate('Validate'),
326
336
  disabled: !get(['ui', 'slide', currentSlideRef, 'validateButton'], state),
@@ -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
  };
@@ -1,24 +1,4 @@
1
+ import { ReviewSkillsProps } from '@coorpacademy/components/es/template/app-review/skills/prop-types';
1
2
  import { StoreState } from '../../reducers';
2
- declare type SkillCard = {
3
- 'aria-label': string;
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;
@@ -1,24 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mapStateToSkillsProps = void 0;
4
- const mapStateToSkillsProps = (state) => {
4
+ const mapStateToSkillsProps = (state, options) => {
5
+ const { translate } = options;
5
6
  return {
6
- title: '@todo title',
7
- iconSkillAriaLabel: '@todo iconSkillAriaLabel',
7
+ 'aria-label': translate('Review Skills Container'),
8
+ title: translate('Skills you can review'),
8
9
  isLoading: false,
9
- isLoadingAriaLabel: '@todo loading',
10
+ isLoadingAriaLabel: 'Review skills container is loading',
10
11
  listSkills: state.data.skills.map(skill => ({
11
- 'aria-label': '',
12
+ 'aria-label': translate('Skill Card'),
12
13
  isCustom: skill.custom,
13
14
  skillTitle: skill.name,
14
- skillAriaLabel: '@todo skill aria label',
15
- buttonLabel: '@todo button',
16
- buttonAriaLabel: '@todo button aria label',
17
- reviseLabel: '@todo revise',
18
- reviseAriaLabel: '@todo revise aria label',
15
+ skillAriaLabel: skill.name,
16
+ buttonLabel: translate('Review this skill'),
17
+ buttonAriaLabel: translate('Review this skill'),
18
+ reviseLabel: translate('{{count}} questions to review', { count: skill.slidesToReview }),
19
+ reviseAriaLabel: translate('{{count}} questions to review', { count: skill.slidesToReview }),
19
20
  // eslint-disable-next-line no-console
20
21
  onClick: () => console.log('@todo plug dispatcher select skill')
21
- }))
22
+ })),
23
+ titleNoSkills: translate('No skill to revise'),
24
+ textNoSkills: translate('Complete courses before revising'),
25
+ iconSkillAriaLabel: 'Image without information'
22
26
  };
23
27
  };
24
28
  exports.mapStateToSkillsProps = mapStateToSkillsProps;
@@ -66,7 +66,11 @@ const getCurrentSlideRef = (state) => {
66
66
  const content = progression.state.content;
67
67
  return content.ref;
68
68
  };
69
- const buildStackSlides = (state, dispatch) => {
69
+ const isLastSlideAnswered = (slidesRef, slideRef) => {
70
+ return (0, last_1.default)(slidesRef) === slideRef;
71
+ };
72
+ const buildStackSlides = (state, dispatch, options) => {
73
+ const { translate } = options;
70
74
  const currentSlideRef = getCurrentSlideRef(state);
71
75
  const progression = state.data.progression;
72
76
  if (!currentSlideRef || !progression)
@@ -75,9 +79,12 @@ const buildStackSlides = (state, dispatch) => {
75
79
  // @ts-expect-error typescript does not support capped versions of lodash functions
76
80
  const stack = reduce_1.default.convert({ cap: false })((acc, uiSlide, _index) => {
77
81
  const index = (0, toInteger_1.default)(_index);
78
- const positions = state.ui.positions;
79
- const position = positions[index];
80
82
  const slideRef = slideRefs[index];
83
+ const lastAnsweredSlideRef = isLastSlideAnswered(progression.state.slides, slideRef);
84
+ const positions = state.ui.positions;
85
+ // when unstack the last answered slide (position -1), we set the position to 0 only during the animation
86
+ // to avoid to hide the slide (caused by the position -1).
87
+ const position = lastAnsweredSlideRef && positions[index] === -1 ? 0 : positions[index];
81
88
  if (!slideRef)
82
89
  return (0, set_1.default)(index, { ...uiSlide, position }, acc);
83
90
  const slideFromAPI = (0, get_1.default)(slideRef, state.data.slides);
@@ -90,7 +97,7 @@ const buildStackSlides = (state, dispatch) => {
90
97
  const slideUI = (0, get_1.default)(['ui', 'slide', slideRef], state);
91
98
  const animateCorrectionPopin = isCurrentSlideRef && slideUI.animateCorrectionPopin;
92
99
  const showCorrectionPopin = isCurrentSlideRef && slideUI.showCorrectionPopin;
93
- const animationType = slideUI.animationType;
100
+ const animationType = lastAnsweredSlideRef ? slideUI.animationType : undefined;
94
101
  const updatedUiSlide = {
95
102
  ...uiSlide,
96
103
  position,
@@ -99,7 +106,10 @@ const buildStackSlides = (state, dispatch) => {
99
106
  loading: false,
100
107
  questionText,
101
108
  answerUI,
102
- parentContentTitle: `From "${parentContentTitle}" ${parentContentType}`,
109
+ parentContentTitle: translate('Content Parent Title', {
110
+ contentTitle: parentContentTitle,
111
+ contentType: parentContentType
112
+ }),
103
113
  animationType
104
114
  };
105
115
  return (0, set_1.default)(index, updatedUiSlide, acc);
@@ -327,7 +337,7 @@ const mapStateToSlidesProps = (state, dispatch, options) => {
327
337
  hiddenSteps: showCongrats
328
338
  },
329
339
  stack: {
330
- slides: buildStackSlides(state, dispatch),
340
+ slides: buildStackSlides(state, dispatch, options),
331
341
  validateButton: {
332
342
  label: translate('Validate'),
333
343
  disabled: !(0, get_1.default)(['ui', 'slide', currentSlideRef, 'validateButton'], state),
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "Review Title": "Review Mode",
3
- "Content Parent Title": "From `{{contentTitle}}` `{{contentType}}`",
3
+ "Content Parent Title": "From \"{{contentTitle}}\" {{contentType}}",
4
4
  "Validate": "Validate",
5
5
  "Next Question": "Next Question",
6
6
  "KLF": "Key point",
@@ -40,15 +40,11 @@
40
40
  }
41
41
  }
42
42
  },
43
- "list_title": "Skills you can review",
44
- "list_aria_label": "Review Skills Container",
45
- "card": {
46
- "aria_label": "Skill Card",
47
- "text": "{{total}} questions to review",
48
- "button_text": "Review this skill"
49
- },
50
- "no_skills": {
51
- "title": "You have no skill to revise yet",
52
- "text": "First you need to complete courses before you can review different skills."
53
- }
43
+ "Review Skills Container": "Review Skills Container",
44
+ "Skills you can review": "Skills you can review",
45
+ "Skill Card": "Skill Card",
46
+ "{{count}} questions to review" : "{{count}} questions to review",
47
+ "Review this skill": "Review this skill",
48
+ "No skill to revise": "You have no skill to revise yet",
49
+ "Complete courses before revising" : "First you need to complete courses before you can review different skills."
54
50
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "Review Title": "Modo revisión",
3
- "Content Parent Title": "De `{{contentTitle}}` `{{contentType}}`",
3
+ "Content Parent Title": "Del {{contentType}} \"{{contentTitle}}\"",
4
4
  "Validate": "Validar",
5
5
  "Next Question": "Siguiente pregunta",
6
6
  "KLF": "Aspecto clave",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "Review Title": "Mode Révision",
3
- "Content Parent Title": "de `{{contentTitle}}` `{{contentType}}`",
3
+ "Content Parent Title": "du {{contentType}} \"{{contentTitle}}\"",
4
4
  "Validate": "Valider",
5
5
  "Next Question": "Question suivante",
6
6
  "KLF": "Point clé",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coorpacademy/app-review",
3
- "version": "0.7.6",
3
+ "version": "0.7.7-alpha.13+c85d1dfbe",
4
4
  "description": "",
5
5
  "engines": {
6
6
  "node": ">=16.15.0"
@@ -35,9 +35,9 @@
35
35
  "main": "lib/index.js",
36
36
  "module": "es/index.js",
37
37
  "dependencies": {
38
- "@coorpacademy/components": "10.27.4",
38
+ "@coorpacademy/components": "10.28.2",
39
39
  "@coorpacademy/redux-task": "1.1.6",
40
- "@coorpacademy/translate": "^6.1.5",
40
+ "@coorpacademy/translate": "6.1.5",
41
41
  "cross-fetch": "^3.1.5",
42
42
  "jwt-decode": "^3.1.2",
43
43
  "react-redux": "^7.2.9",
@@ -51,7 +51,7 @@
51
51
  "devDependencies": {
52
52
  "@coorpacademy/css-modules-require-hook": "3.0.0",
53
53
  "@coorpacademy/eslint-plugin-coorpacademy": "^11.0.0",
54
- "@coorpacademy/webpack-config": "12.0.0",
54
+ "@coorpacademy/webpack-config": "12.0.1",
55
55
  "@testing-library/react": "^12.1.5",
56
56
  "@types/lodash": "^4.14.182",
57
57
  "@typescript-eslint/eslint-plugin": "^5.28.0",
@@ -71,5 +71,5 @@
71
71
  "webpack-cli": "^4.10.0",
72
72
  "webpack-dev-server": "^4.11.1"
73
73
  },
74
- "gitHead": "39e56226e7bed6a8049221c3b99ec10790382e9b"
74
+ "gitHead": "c85d1dfbe401f825c584e68b35f477230642b2cd"
75
75
  }