@coorpacademy/app-review 0.1.4 → 0.1.7

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.
Files changed (103) hide show
  1. package/es/actions/data/progression.d.ts +30 -0
  2. package/es/actions/data/progression.js +12 -0
  3. package/es/actions/data/slides.d.ts +19 -15
  4. package/es/actions/data/slides.js +5 -0
  5. package/es/actions/data/token.d.ts +2 -2
  6. package/es/actions/data/token.js +1 -1
  7. package/es/actions/index.d.ts +2 -1
  8. package/es/configure-store.d.ts +2 -10
  9. package/es/configure-store.js +2 -1
  10. package/es/index.d.ts +1 -1
  11. package/es/index.js +43 -26
  12. package/es/index.test.js +5 -5
  13. package/es/middlewares/on-receive-progression.d.ts +6 -0
  14. package/es/middlewares/on-receive-progression.js +22 -0
  15. package/es/middlewares/on-receive-progression.test.d.ts +1 -0
  16. package/es/middlewares/on-receive-progression.test.js +43 -0
  17. package/es/middlewares/on-start-app.js +13 -5
  18. package/es/middlewares/on-start-app.test.d.ts +1 -0
  19. package/es/middlewares/on-start-app.test.js +53 -0
  20. package/es/reducers/data/index.d.ts +1 -1
  21. package/es/reducers/data/progression.d.ts +14 -8
  22. package/es/reducers/data/progression.js +17 -54
  23. package/es/reducers/data/slides.js +11 -6
  24. package/es/reducers/index.d.ts +1 -1
  25. package/es/services/fetch-skills.js +1 -2
  26. package/es/services/fetch-slide.d.ts +8 -0
  27. package/es/services/fetch-slide.js +26 -0
  28. package/es/services/post-progression.d.ts +8 -0
  29. package/es/services/post-progression.js +33 -0
  30. package/es/services/post-progression.mock.d.ts +5 -0
  31. package/es/services/post-progression.mock.js +31 -0
  32. package/es/services/post-progression.test.d.ts +1 -0
  33. package/es/services/post-progression.test.js +30 -0
  34. package/es/services/tools/fetch-responses.d.ts +1 -1
  35. package/es/services/tools/sleep.d.ts +1 -0
  36. package/es/services/tools/sleep.js +3 -0
  37. package/es/types/common.d.ts +8 -2
  38. package/es/types/ui-progression.d.ts +10 -0
  39. package/es/types/ui-progression.js +1 -0
  40. package/lib/actions/data/progression.d.ts +30 -0
  41. package/lib/actions/data/progression.js +12 -0
  42. package/lib/actions/data/slides.d.ts +19 -15
  43. package/lib/actions/data/slides.js +5 -0
  44. package/lib/actions/data/token.d.ts +2 -2
  45. package/lib/actions/data/token.js +1 -1
  46. package/lib/actions/index.d.ts +2 -1
  47. package/lib/configure-store.d.ts +2 -10
  48. package/lib/configure-store.js +2 -1
  49. package/lib/index.d.ts +1 -1
  50. package/lib/index.js +43 -26
  51. package/lib/index.test.js +5 -7
  52. package/lib/middlewares/on-receive-progression.d.ts +6 -0
  53. package/lib/middlewares/on-receive-progression.js +27 -0
  54. package/lib/middlewares/on-receive-progression.test.d.ts +1 -0
  55. package/lib/middlewares/on-receive-progression.test.js +88 -0
  56. package/lib/middlewares/on-start-app.js +15 -7
  57. package/lib/middlewares/on-start-app.test.d.ts +1 -0
  58. package/lib/middlewares/on-start-app.test.js +98 -0
  59. package/lib/reducers/data/index.d.ts +1 -1
  60. package/lib/reducers/data/progression.d.ts +14 -8
  61. package/lib/reducers/data/progression.js +17 -54
  62. package/lib/reducers/data/slides.js +11 -6
  63. package/lib/reducers/index.d.ts +1 -1
  64. package/lib/services/fetch-skills.js +2 -5
  65. package/lib/services/fetch-slide.d.ts +8 -0
  66. package/lib/services/fetch-slide.js +64 -0
  67. package/lib/services/post-progression.d.ts +8 -0
  68. package/lib/services/post-progression.js +77 -0
  69. package/lib/services/post-progression.mock.d.ts +5 -0
  70. package/lib/services/post-progression.mock.js +31 -0
  71. package/lib/services/post-progression.test.d.ts +1 -0
  72. package/lib/services/post-progression.test.js +84 -0
  73. package/lib/services/tools/fetch-responses.d.ts +1 -1
  74. package/lib/services/tools/sleep.d.ts +1 -0
  75. package/lib/services/tools/sleep.js +5 -0
  76. package/lib/types/common.d.ts +8 -2
  77. package/lib/types/ui-progression.d.ts +10 -0
  78. package/lib/types/ui-progression.js +1 -0
  79. package/package.json +4 -5
  80. package/readme.md +4 -5
  81. package/src/actions/data/progression.ts +50 -0
  82. package/src/actions/data/slides.ts +25 -17
  83. package/src/actions/data/token.ts +2 -2
  84. package/src/actions/index.ts +4 -1
  85. package/src/configure-store.ts +5 -13
  86. package/src/index.test.tsx +5 -7
  87. package/src/index.tsx +54 -29
  88. package/src/middlewares/on-receive-progression.test.ts +60 -0
  89. package/src/middlewares/on-receive-progression.ts +42 -0
  90. package/src/middlewares/on-start-app.test.ts +68 -0
  91. package/src/middlewares/on-start-app.ts +13 -5
  92. package/src/reducers/data/progression.ts +34 -69
  93. package/src/reducers/data/slides.ts +13 -8
  94. package/src/services/fetch-skills.ts +1 -2
  95. package/src/services/fetch-slide.ts +43 -0
  96. package/src/services/post-progression.mock.ts +35 -0
  97. package/src/services/post-progression.test.ts +41 -0
  98. package/src/services/post-progression.ts +50 -0
  99. package/src/services/tools/fetch-responses.ts +1 -1
  100. package/src/services/tools/sleep.ts +4 -0
  101. package/src/types/common.ts +8 -2
  102. package/src/types/globals.d.ts +1 -0
  103. package/src/types/ui-progression.ts +25 -0
@@ -1,6 +1,7 @@
1
1
  import map from 'lodash/fp/map';
2
2
  import { STORE_FIRST_SLIDE, UPDATE_SLIDES_ON_NEXT, UPDATE_SLIDES_ON_VALIDATION } from '../../actions/data/slides';
3
3
  import { HIGHEST_INDEX, slideNumbers, TOTAL_SLIDES_STACK } from '../../common';
4
+ import { slide as qcmSlide } from '../../fixtures/qcm-slide';
4
5
  // -----------------------------------------------------------------------------
5
6
  const getInitialState = () => {
6
7
  const state = {
@@ -30,7 +31,7 @@ const setFirstSlide = (state, slide) => {
30
31
  // ||-------> Handles the updates of a given slide on validation,
31
32
  // & then updates de remaining slides if this given change should impact their content
32
33
  const stateUpdateOnValidation = (state, payload) => {
33
- const { slideNumber, newSlideContent, numberOfFinishedSlides, nextSlide } = payload;
34
+ const { slideNumber, newSlideContent, numberOfFinishedSlides, nextContent } = payload;
34
35
  const _state = {
35
36
  slideNumbers
36
37
  };
@@ -43,7 +44,7 @@ const stateUpdateOnValidation = (state, payload) => {
43
44
  if (numberOfFinishedSlides === HIGHEST_INDEX) {
44
45
  _state[index] = {
45
46
  ...previousValue,
46
- nextSlide,
47
+ nextContent,
47
48
  position: newSlideContent.position,
48
49
  isCorrect: newSlideContent.isCorrect
49
50
  };
@@ -54,7 +55,7 @@ const stateUpdateOnValidation = (state, payload) => {
54
55
  else {
55
56
  // updates the rest of the slides here
56
57
  const { hidden, position } = previousValue;
57
- _state[index] = { ...nextSlide, endReview: newSlideContent.endReview, hidden, position };
58
+ _state[index] = { ...nextContent, endReview: newSlideContent.endReview, hidden, position };
58
59
  }
59
60
  }, state.slideNumbers);
60
61
  return _state;
@@ -72,8 +73,8 @@ const stateUpdateOnNext = (state, payload) => {
72
73
  // the current slide
73
74
  if (index === slideNumber) {
74
75
  // when there is only one slide remaining, updates the slide value
75
- if (numberOfFinishedSlides === HIGHEST_INDEX && previousValue.nextSlide) {
76
- _state[index] = { ...previousValue.nextSlide, position: previousValue.position };
76
+ if (numberOfFinishedSlides === HIGHEST_INDEX && previousValue.nextContent) {
77
+ _state[index] = { ...previousValue.nextContent, position: previousValue.position };
77
78
  }
78
79
  else
79
80
  _state[slideNumber] = newSlideContent;
@@ -97,7 +98,11 @@ const stateUpdateOnNext = (state, payload) => {
97
98
  const reducer = (state = initialState, action) => {
98
99
  switch (action.type) {
99
100
  case STORE_FIRST_SLIDE: {
100
- return setFirstSlide(state, action.payload);
101
+ // TODO: An intermediate slide transform is needed here (or in fetchSlide)
102
+ // const apiSlide = action.payload;
103
+ // apiSlide adapt to uiSlide
104
+ const uiSlide = qcmSlide;
105
+ return setFirstSlide(state, uiSlide);
101
106
  }
102
107
  case UPDATE_SLIDES_ON_VALIDATION: {
103
108
  return stateUpdateOnValidation(state, action.payload);
@@ -11,5 +11,5 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
11
11
  reviewStatus: import("./ui/review-status").ReviewStatusState;
12
12
  stepItems: import("./ui/step-items").StepItems;
13
13
  }>;
14
- }>, import("../actions/data/slides").ValidateSlide | import("../actions/data/slides").SlidesAction | import("../actions/data/skills").ReceivedSkills | import("../actions/data/token").StoreToken | import("../actions/ui/finished-slides").UpdateFinishedSlides | import("../actions/ui/navigation").NavigateTo | import("../actions/ui/navigation").NavigateBack | import("../actions/ui/review-status").UpdateReviewStatus | import("../actions/ui/step-items").StepItemsAction>;
14
+ }>, import("../actions/data/progression").ReceiveProgression | import("../actions/data/slides").ValidateSlide | import("../actions/data/slides").SlidesAction | import("../actions/data/skills").ReceivedSkills | import("../actions/data/token").StoreToken | import("../actions/ui/finished-slides").UpdateFinishedSlides | import("../actions/ui/navigation").NavigateTo | import("../actions/ui/navigation").NavigateBack | import("../actions/ui/review-status").UpdateReviewStatus | import("../actions/ui/step-items").StepItemsAction>;
15
15
  export default _default;
@@ -8,8 +8,7 @@ const fetchSkills = fetch => async (token) => {
8
8
  const response = await fetch(`${host}/api/v2/skills/review/user/${userId}`, {
9
9
  headers: { authorization: token }
10
10
  });
11
- const skills = (await toJSON(response));
12
- return skills;
11
+ return toJSON(response);
13
12
  };
14
13
  // -----------------------------------------------------------------------------
15
14
  const createFetchSkills = () => {
@@ -0,0 +1,8 @@
1
+ import crossFetch from 'cross-fetch';
2
+ import { SlideFromAPI } from '../actions/data/slides';
3
+ declare type FetchSlide = (slideRef: string, token: string) => Promise<SlideFromAPI>;
4
+ declare type FetchSlideBuilder = (fetch: typeof crossFetch) => FetchSlide;
5
+ declare const fetchSlide: FetchSlideBuilder;
6
+ export { fetchSlide };
7
+ declare const _default: FetchSlide;
8
+ export default _default;
@@ -0,0 +1,26 @@
1
+ import crossFetch from 'cross-fetch';
2
+ // import {JWT} from '../types/common';
3
+ // import {toJSON} from './tools/fetch-responses';
4
+ import { okJSONResponse } from './tools/fetch.mocks';
5
+ // -----------------------------------------------------------------------------
6
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, unicorn/consistent-function-scoping, require-await
7
+ const fetchSlide = fetch => async (slideRef, token) => {
8
+ // const {host}: JWT = decode(token);
9
+ // const response = await fetch(`${host}/api/v2/slide/${slideRef}`, {
10
+ // headers: {authorization: token}
11
+ // });
12
+ // const slide = (await toJSON(response)) as SlideFromAPI;
13
+ // return slide;
14
+ return {};
15
+ };
16
+ // -----------------------------------------------------------------------------
17
+ const createFetchSlide = () => {
18
+ if (process.env.SERVICES !== 'mocks') {
19
+ return fetchSlide(crossFetch);
20
+ }
21
+ // TODO: use an appropriate mock
22
+ return fetchSlide(okJSONResponse({}));
23
+ };
24
+ // -----------------------------------------------------------------------------
25
+ export { fetchSlide };
26
+ export default createFetchSlide();
@@ -0,0 +1,8 @@
1
+ import crossFetch from 'cross-fetch';
2
+ import { ProgressionFromAPI } from '../actions/data/progression';
3
+ declare type PostProgression = (skillRef: string, token: string) => Promise<ProgressionFromAPI>;
4
+ declare type CreatePostProgression = (fetch: typeof crossFetch) => PostProgression;
5
+ declare const postProgression: CreatePostProgression;
6
+ export { postProgression };
7
+ declare const _default: PostProgression;
8
+ export default _default;
@@ -0,0 +1,33 @@
1
+ import crossFetch from 'cross-fetch';
2
+ import decode from 'jwt-decode';
3
+ import { toJSON } from './tools/fetch-responses';
4
+ import mockPostProgression from './post-progression.mock';
5
+ // -----------------------------------------------------------------------------
6
+ const postProgression = fetch => async (skillRef, token) => {
7
+ const { host } = decode(token);
8
+ const response = await fetch(`${host}/api/v2/progressions`, {
9
+ method: 'post',
10
+ headers: { authorization: token },
11
+ body: JSON.stringify({
12
+ content: {
13
+ ref: skillRef,
14
+ type: 'slide'
15
+ },
16
+ engine: {
17
+ ref: 'review',
18
+ version: '1'
19
+ }
20
+ })
21
+ });
22
+ return toJSON(response);
23
+ };
24
+ // -----------------------------------------------------------------------------
25
+ const createPostProgression = () => {
26
+ if (process.env.SERVICES !== 'mocks') {
27
+ return postProgression(crossFetch);
28
+ }
29
+ return postProgression(mockPostProgression);
30
+ };
31
+ // -----------------------------------------------------------------------------
32
+ export { postProgression };
33
+ export default createPostProgression();
@@ -0,0 +1,5 @@
1
+ import crossFetch from 'cross-fetch';
2
+ import { ProgressionFromAPI } from '../actions/data/progression';
3
+ export declare const mockedProgression: ProgressionFromAPI;
4
+ declare const mockCreateProgression: typeof crossFetch;
5
+ export default mockCreateProgression;
@@ -0,0 +1,31 @@
1
+ import { okJSONResponse } from './tools/fetch.mocks';
2
+ export const mockedProgression = {
3
+ _id: '62b1d1087aa12f00253f40ee',
4
+ state: {
5
+ // ------------------------------------------------------
6
+ // unused for now / to decide whether to use it when the
7
+ // validation-progression is plugged in
8
+ pendingSlides: [],
9
+ step: {
10
+ current: Number.NaN
11
+ },
12
+ // ------------------------------------------------------
13
+ isCorrect: true,
14
+ nextContent: {
15
+ ref: 'sli_N1XACJobn',
16
+ type: 'slide'
17
+ }
18
+ // slides: [
19
+ // 'sli_NJ3m5KtWh',
20
+ // 'sli_V1gKpYYZ2',
21
+ // 'sli_VJzOgotbh',
22
+ // 'sli_V1ug-dtZn',
23
+ // 'sli_VyZU-ejW3',
24
+ // 'sli_Vy8ChgjZh',
25
+ // 'sli_V1ijS1oWh',
26
+ // 'sli_N1XACJobn'
27
+ // ],
28
+ }
29
+ };
30
+ const mockCreateProgression = okJSONResponse(mockedProgression);
31
+ export default mockCreateProgression;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
1
+ import test from 'ava';
2
+ import { postProgression } from './post-progression';
3
+ import { okJSONResponse, token } from './tools/fetch.mocks';
4
+ const skillRef = '_skill-ref';
5
+ test('should create progression with success', async (t) => {
6
+ const result = {
7
+ _id: '123456123456',
8
+ state: {
9
+ // is "isCorrect" always true for a 1st progression?
10
+ isCorrect: true,
11
+ step: {
12
+ current: 1
13
+ },
14
+ nextContent: {
15
+ type: 'slide',
16
+ ref: 'sli_NJ3m5KtWh'
17
+ },
18
+ pendingSlides: []
19
+ }
20
+ };
21
+ const mockedPostProgression = postProgression(okJSONResponse(result));
22
+ const progression = await mockedPostProgression(skillRef, token);
23
+ t.deepEqual(result, progression);
24
+ });
25
+ test('should reject bad token', async (t) => {
26
+ const badToken = 'token is not a jwt';
27
+ const mockedPostProgression = postProgression(okJSONResponse(null));
28
+ const error = await t.throwsAsync(() => mockedPostProgression(skillRef, badToken));
29
+ t.is(error?.message, "Invalid token specified: Cannot read properties of undefined (reading 'replace')");
30
+ });
@@ -2,6 +2,6 @@ export declare class ResponseError extends Error {
2
2
  statusCode: number;
3
3
  constructor(statusCode: number, statusText: string, body?: string);
4
4
  }
5
- export declare const toJSON: (response: Response) => Promise<unknown>;
5
+ export declare const toJSON: <T = unknown>(response: Response) => Promise<T>;
6
6
  export declare const toText: (response: Response) => Promise<string>;
7
7
  export declare const toVoid: (response: Response) => Promise<void>;
@@ -0,0 +1 @@
1
+ export declare const sleep: (msToSleep: number) => Promise<void>;
@@ -0,0 +1,3 @@
1
+ export const sleep = (msToSleep) => new Promise(resolve => {
2
+ setTimeout(resolve, msToSleep);
3
+ });
@@ -1,9 +1,14 @@
1
- import { Slide } from './slides';
1
+ declare type TemplateContextValues = {
2
+ brandTheme?: unknown;
3
+ theme?: unknown;
4
+ translations?: unknown;
5
+ };
2
6
  export declare type AppOptions = {
3
7
  token: string;
4
8
  theme?: unknown;
5
9
  translations?: unknown;
6
- slide?: Slide;
10
+ templateContext?: TemplateContextValues;
11
+ skillRef?: string;
7
12
  };
8
13
  export declare type JWT = {
9
14
  exp: number;
@@ -17,3 +22,4 @@ export declare type JWT = {
17
22
  export declare type WithRequired<T, K extends keyof T> = T & {
18
23
  [P in K]-?: T[P];
19
24
  };
25
+ export {};
@@ -0,0 +1,10 @@
1
+ export declare type UiProgression = {
2
+ _id?: string;
3
+ slideNumber?: number;
4
+ isCorrect?: boolean;
5
+ exitNode?: 'successExitNode' | 'failExitNode';
6
+ nextContent?: {
7
+ ref: 'successExitNode' | string;
8
+ type: 'success' | 'slide';
9
+ };
10
+ } | null;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
1
+ export declare type ProgressionFromAPI = {
2
+ _id: string;
3
+ state: {
4
+ isCorrect: boolean;
5
+ step: {
6
+ current: number;
7
+ };
8
+ nextContent: {
9
+ type: 'success' | 'slide';
10
+ ref: 'successExitNode' | string;
11
+ };
12
+ pendingSlides: [];
13
+ };
14
+ };
15
+ export declare const RECEIVE_PROGRESSION = "@@data/progression/RECEIVE_PROGRESSION";
16
+ export declare const ERROR_CREATING_PROGRESSION = "@@data/progression/ERROR_CREATING_PROGRESSION";
17
+ export declare type ReceiveProgressionPayload = {
18
+ progression: ProgressionFromAPI;
19
+ token: string;
20
+ };
21
+ export declare type ReceiveProgression = {
22
+ type: typeof RECEIVE_PROGRESSION;
23
+ payload: ReceiveProgressionPayload;
24
+ };
25
+ export declare type ErrorCreatingProgression = {
26
+ type: typeof ERROR_CREATING_PROGRESSION;
27
+ payload: Error;
28
+ };
29
+ export declare const receiveProgression: (payload: ReceiveProgressionPayload) => ReceiveProgression;
30
+ export declare const errorCreatingProgression: (error: Error) => ErrorCreatingProgression;
@@ -0,0 +1,12 @@
1
+ // -----------------------------------------------------------------------------
2
+ export var RECEIVE_PROGRESSION = '@@data/progression/RECEIVE_PROGRESSION';
3
+ export var ERROR_CREATING_PROGRESSION = '@@data/progression/ERROR_CREATING_PROGRESSION';
4
+ // -----------------------------------------------------------------------------
5
+ export var receiveProgression = function (payload) { return ({
6
+ type: RECEIVE_PROGRESSION,
7
+ payload: payload
8
+ }); };
9
+ export var errorCreatingProgression = function (error) { return ({
10
+ type: ERROR_CREATING_PROGRESSION,
11
+ payload: error
12
+ }); };
@@ -1,32 +1,35 @@
1
- import { Slide as SlideFromAPI } from '../../types/slides';
1
+ import { Slide as UISlide } from '../../types/slides';
2
2
  export declare const STORE_FIRST_SLIDE = "@@slide/STORE_FIRST_SLIDE";
3
3
  export declare const UPDATE_SLIDES_ON_VALIDATION = "@@slide/UPDATE_SLIDES_ON_VALIDATION";
4
4
  export declare const UPDATE_SLIDES_ON_NEXT = "@@slide/UPDATE_SLIDES_ON_NEXT";
5
5
  export declare const VALIDATE_SLIDE = "@@slide/VALIDATE";
6
6
  export declare const FETCH_NEXT_CONTENT = "@@slide/FETCH_NEXT_CONTENT";
7
+ export declare const ERROR_FETCHING_SLIDE = "@@data/slide/ERROR_FETCHING_SLIDE";
7
8
  declare type SlideUIAnimations = 'unstack' | 'restack';
8
- export declare type Slide = SlideFromAPI & {
9
+ export declare type Slide = UISlide & {
9
10
  hidden?: boolean;
10
11
  position: number;
11
12
  animationType?: SlideUIAnimations;
12
13
  isCorrect?: boolean;
13
14
  endReview?: boolean;
14
- nextSlide?: Omit<Slide, 'endReview' | 'hidden' | 'position' | 'nextSlide'>;
15
+ nextContent?: Omit<Slide, 'endReview' | 'hidden' | 'position' | 'nextContent'>;
16
+ };
17
+ export declare type SlideFromAPI = {
18
+ question: {
19
+ content: {
20
+ choices: Record<string, unknown>[];
21
+ };
22
+ };
23
+ klf: string;
24
+ universalRef: string;
15
25
  };
16
26
  export declare type ValidationPayload = {
17
27
  slideNumber: number;
18
28
  newSlideContent: Slide;
19
29
  numberOfFinishedSlides: number;
20
- nextSlide: Slide;
21
- };
22
- export declare type OnNextPayload = Omit<ValidationPayload, 'nextSlide'>;
23
- export declare type FetchNextPayload = {
24
- answer: string[];
25
- content: {
26
- ref: string;
27
- type: string;
28
- };
30
+ nextContent: Slide;
29
31
  };
32
+ export declare type OnNextPayload = Omit<ValidationPayload, 'nextContent'>;
30
33
  export declare type StoreFirstSlide = {
31
34
  type: typeof STORE_FIRST_SLIDE;
32
35
  payload: SlideFromAPI;
@@ -42,13 +45,14 @@ export declare type UpdateSlidesOnNext = {
42
45
  export declare type ValidateSlide = {
43
46
  type: typeof VALIDATE_SLIDE;
44
47
  };
45
- export declare type FetchNextContent = {
46
- type: typeof FETCH_NEXT_CONTENT;
47
- payload: FetchNextPayload;
48
+ export declare type ErrorFetchingSlide = {
49
+ type: typeof ERROR_FETCHING_SLIDE;
50
+ payload: Error;
48
51
  };
49
52
  export declare type SlidesAction = StoreFirstSlide | UpdateSlidesOnValidation | UpdateSlidesOnNext;
50
53
  export declare const storeFirstSlide: (slide: SlideFromAPI) => StoreFirstSlide;
51
54
  export declare const updateSlidesOnValidation: (payload: ValidationPayload) => UpdateSlidesOnValidation;
52
55
  export declare const updateSlidesOnNext: (payload: OnNextPayload) => UpdateSlidesOnNext;
53
56
  export declare const validateSlide: () => ValidateSlide;
57
+ export declare const errorFetchingSlide: (error: Error) => ErrorFetchingSlide;
54
58
  export {};
@@ -4,6 +4,7 @@ export var UPDATE_SLIDES_ON_VALIDATION = '@@slide/UPDATE_SLIDES_ON_VALIDATION';
4
4
  export var UPDATE_SLIDES_ON_NEXT = '@@slide/UPDATE_SLIDES_ON_NEXT';
5
5
  export var VALIDATE_SLIDE = '@@slide/VALIDATE';
6
6
  export var FETCH_NEXT_CONTENT = '@@slide/FETCH_NEXT_CONTENT';
7
+ export var ERROR_FETCHING_SLIDE = '@@data/slide/ERROR_FETCHING_SLIDE';
7
8
  // -----------------------------------------------------------------------------
8
9
  export var storeFirstSlide = function (slide) { return ({
9
10
  type: STORE_FIRST_SLIDE,
@@ -20,3 +21,7 @@ export var updateSlidesOnNext = function (payload) { return ({
20
21
  export var validateSlide = function () { return ({
21
22
  type: VALIDATE_SLIDE
22
23
  }); };
24
+ export var errorFetchingSlide = function (error) { return ({
25
+ type: ERROR_FETCHING_SLIDE,
26
+ payload: error
27
+ }); };
@@ -1,6 +1,6 @@
1
- export declare const STORE_TOKEN = "@@token/STORE_TOKEN";
1
+ export declare const STORE_TOKEN = "@@data/token/STORE_TOKEN";
2
2
  export declare type StoreToken = {
3
- type: '@@token/STORE_TOKEN';
3
+ type: typeof STORE_TOKEN;
4
4
  payload: string;
5
5
  };
6
6
  export declare const storeToken: (token: string) => StoreToken;
@@ -1,4 +1,4 @@
1
- export var STORE_TOKEN = '@@token/STORE_TOKEN';
1
+ export var STORE_TOKEN = '@@data/token/STORE_TOKEN';
2
2
  export var storeToken = function (token) { return ({
3
3
  type: STORE_TOKEN,
4
4
  payload: token
@@ -5,7 +5,8 @@ import { updateFinishedSlides } from './ui/finished-slides';
5
5
  import { navigateBack, navigateTo, NavigateBack, NavigateTo, StartApp } from './ui/navigation';
6
6
  import { updateReviewStatus } from './ui/review-status';
7
7
  import { updateStepItemsOnValidation, updateStepItemsOnNext } from './ui/step-items';
8
- export declare type Action = NavigateBack | NavigateTo | ReceivedSkills | ErrorFetchingSkills | StartApp | StoreFirstSlide | StoreToken;
8
+ import { ErrorCreatingProgression, ReceiveProgression } from './data/progression';
9
+ export declare type Action = NavigateBack | NavigateTo | ReceivedSkills | ErrorFetchingSkills | StartApp | StoreFirstSlide | StoreToken | ErrorCreatingProgression | ReceiveProgression;
9
10
  export declare type Dispatchers = {
10
11
  navigateTo: typeof navigateTo;
11
12
  navigateBack: typeof navigateBack;
@@ -6,18 +6,10 @@ import { NavigationState } from './reducers/ui/navigation';
6
6
  import { ReviewStatusState } from './reducers/ui/review-status';
7
7
  import { StepItemsState } from './reducers/ui/step-items';
8
8
  import { FinishedSlidesState } from './reducers/ui/finished-slides';
9
- import { AnswerUI } from './types/slides';
9
+ import { ProgressionState } from './reducers/data/progression';
10
10
  declare type DataState = {
11
11
  isFetching?: boolean;
12
- progression?: {
13
- slideNumber: number;
14
- isCorrect?: boolean;
15
- exitNode?: 'successExitNode' | 'failExitNode';
16
- nextSlide?: {
17
- questionText?: string;
18
- answerUI?: AnswerUI;
19
- };
20
- } | null;
12
+ progression?: ProgressionState;
21
13
  skills: SkillsState;
22
14
  slides: SlidesState;
23
15
  token?: TokenState;
@@ -2,6 +2,7 @@ import { applyMiddleware, compose, createStore } from 'redux';
2
2
  import thunk from 'redux-thunk';
3
3
  import rootReducer from './reducers';
4
4
  import onStartApp from './middlewares/on-start-app';
5
+ import onReceiveProgression from './middlewares/on-receive-progression';
5
6
  // -----------------------------------------------------------------------------
6
7
  export default function configureStore() {
7
8
  var _compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
@@ -11,7 +12,7 @@ export default function configureStore() {
11
12
  traceLimit: 25
12
13
  })
13
14
  : compose;
14
- var enhancer = _compose(applyMiddleware(thunk, onStartApp));
15
+ var enhancer = _compose(applyMiddleware(thunk, onStartApp, onReceiveProgression));
15
16
  var store = createStore(rootReducer, undefined, enhancer);
16
17
  return store;
17
18
  }
package/lib/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { AppOptions } from './types/common';
2
2
  declare const AppReview: ({ options }: {
3
3
  options: AppOptions;
4
- }) => JSX.Element;
4
+ }) => JSX.Element | null;
5
5
  declare global {
6
6
  interface Window {
7
7
  __REDUX_DEVTOOLS_EXTENSION__?: boolean;
package/lib/index.js CHANGED
@@ -37,6 +37,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
37
37
  import React, { useEffect, useState } from 'react';
38
38
  import { connect, Provider } from 'react-redux';
39
39
  import AppReviewTemplate from '@coorpacademy/components/es/template/app-review';
40
+ import { TemplateContext } from '@coorpacademy/components/es/template/app-review/template-context';
40
41
  import configureStore from './configure-store';
41
42
  import { congratsProps, correctionPopinProps } from './fixtures/temp-fixture';
42
43
  import { updateSlidesOnNext, updateSlidesOnValidation, validateSlide } from './actions/data/slides';
@@ -59,29 +60,38 @@ var mapDispatchToProps = {
59
60
  var getCurrentViewName = function (storeState) {
60
61
  return storeState.ui.navigation[storeState.ui.navigation.length - 1];
61
62
  };
62
- var mapStateToSkillsProps = function (state) { return ({
63
- title: '@todo title',
64
- titleNoSkills: '@todo titleNoSkills',
65
- textNoSkills: '@todo textNoSkills',
66
- iconSkillAriaLabel: '@todo iconSkillAriaLabel',
67
- isLoading: false,
68
- isLoadingAriaLabel: '@todo loading',
69
- listSkills: state.data.skills.map(function (skill) { return ({
70
- 'aria-label': '',
71
- isCustom: skill.custom,
72
- skillTitle: skill.name,
73
- skillAriaLabel: '@todo skill aria label',
74
- buttonLabel: '@todo button',
75
- buttonAriaLabel: '@todo button aria label',
76
- reviseLabel: '@todo revise',
77
- reviseAriaLabel: '@todo revise aria label',
78
- // eslint-disable-next-line no-console
79
- onClick: function () { return console.log('@todo plug dispatcher select skill'); }
80
- }); })
81
- }); };
82
- var mapStateToProps = function (state) { return ({
83
- viewName: getCurrentViewName(state),
84
- slides: {
63
+ // -----------------------------------------------------------------------------
64
+ var mapStateToSkillsProps = function (state) {
65
+ if (!state.data.skills) {
66
+ return null;
67
+ }
68
+ return {
69
+ title: '@todo title',
70
+ titleNoSkills: '@todo titleNoSkills',
71
+ textNoSkills: '@todo textNoSkills',
72
+ iconSkillAriaLabel: '@todo iconSkillAriaLabel',
73
+ isLoading: false,
74
+ isLoadingAriaLabel: '@todo loading',
75
+ listSkills: state.data.skills.map(function (skill) { return ({
76
+ 'aria-label': '',
77
+ isCustom: skill.custom,
78
+ skillTitle: skill.name,
79
+ skillAriaLabel: '@todo skill aria label',
80
+ buttonLabel: '@todo button',
81
+ buttonAriaLabel: '@todo button aria label',
82
+ reviseLabel: '@todo revise',
83
+ reviseAriaLabel: '@todo revise aria label',
84
+ // eslint-disable-next-line no-console
85
+ onClick: function () { return console.log('@todo plug dispatcher select skill'); }
86
+ }); })
87
+ };
88
+ };
89
+ // -----------------------------------------------------------------------------
90
+ var mapStateToSlidesProps = function (state) {
91
+ if (!state.data.slides) {
92
+ return null;
93
+ }
94
+ return {
85
95
  headerProps: {
86
96
  mode: '__revision_mode',
87
97
  skillName: '__agility',
@@ -102,7 +112,12 @@ var mapStateToProps = function (state) { return ({
102
112
  correctionPopinProps: correctionPopinProps,
103
113
  congratsProps: congratsProps,
104
114
  progression: state.data.progression
105
- },
115
+ };
116
+ };
117
+ // -----------------------------------------------------------------------------
118
+ var mapStateToProps = function (state) { return ({
119
+ viewName: getCurrentViewName(state),
120
+ slides: mapStateToSlidesProps(state),
106
121
  skills: mapStateToSkillsProps(state)
107
122
  }); };
108
123
  // Props = StaticProps && Dispatchers
@@ -134,9 +149,11 @@ var AppReview = function (_a) {
134
149
  }
135
150
  }, [options, store]);
136
151
  if (!store || !appStarted)
137
- return React.createElement("div", null);
152
+ return null;
153
+ var values = options.templateContext;
138
154
  return (React.createElement(Provider, { store: store },
139
- React.createElement(App, null)));
155
+ React.createElement(TemplateContext, { values: values },
156
+ React.createElement(App, null))));
140
157
  };
141
158
  // -----------------------------------------------------------------------------
142
159
  export default AppReview;
package/lib/index.test.js CHANGED
@@ -38,17 +38,12 @@ import browserEnv from 'browser-env';
38
38
  import test from 'ava';
39
39
  import React from 'react';
40
40
  import { render, fireEvent, act } from '@testing-library/react';
41
- import { slide } from './fixtures/qcm-slide';
41
+ import { sleep } from './services/tools/sleep';
42
42
  import AppReview from '.';
43
43
  browserEnv({ pretendToBeVisual: true });
44
44
  var elementExists = function (foundElements) {
45
45
  return foundElements && foundElements[0];
46
46
  };
47
- var sleep = function (msToSleep) {
48
- return new Promise(function (resolve) {
49
- setTimeout(resolve, msToSleep);
50
- });
51
- };
52
47
  var waitForChanges = function (msToWait) {
53
48
  if (msToWait === void 0) { msToWait = 3000; }
54
49
  return __awaiter(void 0, void 0, void 0, function () {
@@ -134,7 +129,10 @@ var clickAllSlides = function (t, container, accumulator) {
134
129
  };
135
130
  var appOptions = {
136
131
  token: process.env.API_TEST_TOKEN || '',
137
- slide: slide
132
+ templateContext: {
133
+ theme: { color: { primary: '#123' } }
134
+ },
135
+ skillRef: 'skill_NJC0jFKoH'
138
136
  };
139
137
  test('should validate all the slides (all correct scenario)', function (t) { return __awaiter(void 0, void 0, void 0, function () {
140
138
  var container, wrapper, stackedSlidesContainer;
@@ -0,0 +1,6 @@
1
+ import type { Middleware, Store } from 'redux';
2
+ import { Dispatch } from 'redux';
3
+ import { ErrorFetchingSlide, StoreFirstSlide } from '../actions/data/slides';
4
+ import { ReceiveProgression } from '../actions/data/progression';
5
+ declare const onReceiveProgression: Middleware<{}, Store, Dispatch<ReceiveProgression | StoreFirstSlide | ErrorFetchingSlide>>;
6
+ export default onReceiveProgression;