@coorpacademy/app-review 0.1.5 → 0.1.8

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 (192) hide show
  1. package/es/actions/api/fetch-skills.d.ts +10 -0
  2. package/es/actions/api/fetch-skills.js +8 -0
  3. package/es/actions/api/fetch-slide.d.ts +10 -0
  4. package/es/actions/api/fetch-slide.js +8 -0
  5. package/es/actions/api/post-progression.d.ts +10 -0
  6. package/es/actions/api/post-progression.js +15 -0
  7. package/es/actions/data/slides.d.ts +7 -24
  8. package/es/actions/data/slides.js +0 -6
  9. package/es/actions/data/token.d.ts +2 -2
  10. package/es/actions/data/token.js +1 -1
  11. package/es/actions/index.d.ts +5 -3
  12. package/es/actions/ui/navigation.d.ts +0 -1
  13. package/es/actions/ui/navigation.js +0 -4
  14. package/es/actions/ui/step-items.d.ts +2 -8
  15. package/es/actions/ui/step-items.js +0 -6
  16. package/es/configure-store.d.ts +3 -34
  17. package/es/configure-store.js +4 -4
  18. package/es/fixtures/qcm-slide.d.ts +2 -2
  19. package/es/index.d.ts +1 -1
  20. package/es/index.js +78 -42
  21. package/es/reducers/data/index.d.ts +16 -5
  22. package/es/reducers/data/progression.d.ts +14 -9
  23. package/es/reducers/data/progression.js +18 -58
  24. package/es/reducers/data/skills.d.ts +4 -5
  25. package/es/reducers/data/skills.js +3 -6
  26. package/es/reducers/data/slides.d.ts +2 -1
  27. package/es/reducers/data/slides.js +14 -9
  28. package/es/reducers/data/token.d.ts +0 -1
  29. package/es/reducers/data/token.js +1 -5
  30. package/es/reducers/index.d.ts +9 -3
  31. package/es/reducers/ui/finished-slides.d.ts +0 -1
  32. package/es/reducers/ui/finished-slides.js +1 -3
  33. package/es/reducers/ui/index.d.ts +14 -4
  34. package/es/reducers/ui/navigation.d.ts +0 -1
  35. package/es/reducers/ui/navigation.js +1 -3
  36. package/es/reducers/ui/review-status.d.ts +0 -1
  37. package/es/reducers/ui/review-status.js +1 -4
  38. package/es/reducers/ui/step-items.d.ts +5 -5
  39. package/es/reducers/ui/step-items.js +0 -1
  40. package/es/services/fetch-skills.d.ts +2 -8
  41. package/es/services/fetch-skills.js +3 -16
  42. package/es/services/fetch-slide.d.ts +2 -0
  43. package/es/services/fetch-slide.js +11 -0
  44. package/es/services/index.d.ts +2 -0
  45. package/es/services/index.js +8 -0
  46. package/es/services/post-progression.d.ts +2 -0
  47. package/es/services/post-progression.js +21 -0
  48. package/es/services/test/fetch-skills.test.js +29 -0
  49. package/es/services/test/post-progression.test.js +35 -0
  50. package/es/services/tools/fetch-responses.d.ts +1 -1
  51. package/es/services/tools/sleep.d.ts +1 -0
  52. package/es/services/tools/sleep.js +3 -0
  53. package/es/{index.test.js → test/index.test.js} +18 -7
  54. package/es/test/util/services.mock.d.ts +2 -0
  55. package/es/test/util/services.mock.js +68 -0
  56. package/es/types/common.d.ts +66 -2
  57. package/es/types/common.js +5 -0
  58. package/es/types/slides.d.ts +1 -1
  59. package/es/types/ui-progression.d.ts +10 -0
  60. package/es/types/views/slides.d.ts +1 -1
  61. package/lib/actions/api/fetch-skills.d.ts +10 -0
  62. package/lib/actions/api/fetch-skills.js +13 -0
  63. package/lib/actions/api/fetch-slide.d.ts +10 -0
  64. package/lib/actions/api/fetch-slide.js +13 -0
  65. package/lib/actions/api/post-progression.d.ts +10 -0
  66. package/lib/actions/api/post-progression.js +18 -0
  67. package/lib/actions/data/slides.d.ts +7 -24
  68. package/lib/actions/data/slides.js +0 -6
  69. package/lib/actions/data/token.d.ts +2 -2
  70. package/lib/actions/data/token.js +1 -1
  71. package/lib/actions/index.d.ts +5 -3
  72. package/lib/actions/ui/navigation.d.ts +0 -1
  73. package/lib/actions/ui/navigation.js +0 -4
  74. package/lib/actions/ui/step-items.d.ts +2 -8
  75. package/lib/actions/ui/step-items.js +0 -6
  76. package/lib/configure-store.d.ts +3 -34
  77. package/lib/configure-store.js +4 -4
  78. package/lib/fixtures/qcm-slide.d.ts +2 -2
  79. package/lib/index.d.ts +1 -1
  80. package/lib/index.js +78 -86
  81. package/lib/reducers/data/index.d.ts +16 -5
  82. package/lib/reducers/data/progression.d.ts +14 -9
  83. package/lib/reducers/data/progression.js +18 -58
  84. package/lib/reducers/data/skills.d.ts +4 -5
  85. package/lib/reducers/data/skills.js +3 -6
  86. package/lib/reducers/data/slides.d.ts +2 -1
  87. package/lib/reducers/data/slides.js +14 -9
  88. package/lib/reducers/data/token.d.ts +0 -1
  89. package/lib/reducers/data/token.js +1 -5
  90. package/lib/reducers/index.d.ts +9 -3
  91. package/lib/reducers/ui/finished-slides.d.ts +0 -1
  92. package/lib/reducers/ui/finished-slides.js +1 -3
  93. package/lib/reducers/ui/index.d.ts +14 -4
  94. package/lib/reducers/ui/navigation.d.ts +0 -1
  95. package/lib/reducers/ui/navigation.js +1 -3
  96. package/lib/reducers/ui/review-status.d.ts +0 -1
  97. package/lib/reducers/ui/review-status.js +1 -4
  98. package/lib/reducers/ui/step-items.d.ts +5 -5
  99. package/lib/reducers/ui/step-items.js +0 -1
  100. package/lib/services/fetch-skills.d.ts +2 -8
  101. package/lib/services/fetch-skills.js +5 -20
  102. package/lib/services/fetch-slide.d.ts +2 -0
  103. package/lib/services/fetch-slide.js +57 -0
  104. package/lib/services/index.d.ts +2 -0
  105. package/lib/services/index.js +8 -0
  106. package/lib/services/post-progression.d.ts +2 -0
  107. package/lib/services/post-progression.js +65 -0
  108. package/lib/services/{fetch-skills.test.js → test/fetch-skills.test.js} +23 -16
  109. package/lib/services/test/post-progression.test.js +89 -0
  110. package/lib/services/tools/fetch-responses.d.ts +1 -1
  111. package/lib/services/tools/sleep.d.ts +1 -0
  112. package/lib/services/tools/sleep.js +5 -0
  113. package/lib/test/index.test.d.ts +1 -0
  114. package/lib/{index.test.js → test/index.test.js} +23 -15
  115. package/lib/test/util/services.mock.d.ts +2 -0
  116. package/lib/test/util/services.mock.js +68 -0
  117. package/lib/types/common.d.ts +66 -2
  118. package/lib/types/common.js +5 -0
  119. package/lib/types/slides.d.ts +1 -1
  120. package/lib/types/ui-progression.d.ts +10 -0
  121. package/lib/types/ui-progression.js +1 -0
  122. package/lib/types/views/slides.d.ts +1 -1
  123. package/package.json +6 -5
  124. package/readme.md +4 -5
  125. package/src/actions/api/fetch-skills.ts +20 -0
  126. package/src/actions/api/fetch-slide.ts +20 -0
  127. package/src/actions/api/post-progression.ts +26 -0
  128. package/src/actions/data/slides.ts +8 -32
  129. package/src/actions/data/token.ts +2 -2
  130. package/src/actions/index.ts +7 -10
  131. package/src/actions/ui/navigation.ts +0 -5
  132. package/src/actions/ui/step-items.ts +2 -14
  133. package/src/configure-store.ts +6 -45
  134. package/src/fixtures/qcm-slide.ts +2 -2
  135. package/src/index.tsx +94 -45
  136. package/src/reducers/data/index.ts +12 -4
  137. package/src/reducers/data/progression.ts +34 -79
  138. package/src/reducers/data/skills.ts +5 -10
  139. package/src/reducers/data/slides.ts +16 -15
  140. package/src/reducers/data/token.ts +1 -11
  141. package/src/reducers/index.ts +7 -2
  142. package/src/reducers/ui/finished-slides.ts +1 -7
  143. package/src/reducers/ui/index.ts +11 -4
  144. package/src/reducers/ui/navigation.ts +1 -6
  145. package/src/reducers/ui/review-status.ts +1 -8
  146. package/src/reducers/ui/step-items.ts +5 -14
  147. package/src/services/fetch-skills.ts +4 -30
  148. package/src/services/fetch-slide.ts +15 -0
  149. package/src/services/index.ts +10 -0
  150. package/src/services/post-progression.ts +28 -0
  151. package/src/services/test/fetch-skills.test.ts +39 -0
  152. package/src/services/test/post-progression.test.ts +45 -0
  153. package/src/services/tools/fetch-responses.ts +1 -1
  154. package/src/services/tools/sleep.ts +4 -0
  155. package/src/{index.test.tsx → test/index.test.tsx} +16 -10
  156. package/src/test/util/services.mock.ts +70 -0
  157. package/src/types/common.ts +78 -2
  158. package/src/types/globals.d.ts +2 -0
  159. package/src/types/slides.ts +1 -1
  160. package/src/types/ui-progression.ts +25 -0
  161. package/src/types/views/slides.ts +1 -1
  162. package/es/actions/data/skills.d.ts +0 -13
  163. package/es/actions/data/skills.js +0 -10
  164. package/es/middlewares/on-start-app.d.ts +0 -5
  165. package/es/middlewares/on-start-app.js +0 -29
  166. package/es/services/fetch-skills.mock.d.ts +0 -3
  167. package/es/services/fetch-skills.mock.js +0 -17
  168. package/es/services/fetch-skills.test.js +0 -22
  169. package/es/services/tools/fetch.mocks.d.ts +0 -8
  170. package/es/services/tools/fetch.mocks.js +0 -13
  171. package/es/types/skills.d.ts +0 -7
  172. package/lib/actions/data/skills.d.ts +0 -13
  173. package/lib/actions/data/skills.js +0 -10
  174. package/lib/middlewares/on-start-app.d.ts +0 -5
  175. package/lib/middlewares/on-start-app.js +0 -34
  176. package/lib/services/fetch-skills.mock.d.ts +0 -3
  177. package/lib/services/fetch-skills.mock.js +0 -17
  178. package/lib/services/tools/fetch.mocks.d.ts +0 -8
  179. package/lib/services/tools/fetch.mocks.js +0 -35
  180. package/lib/types/skills.d.ts +0 -7
  181. package/src/actions/data/skills.ts +0 -24
  182. package/src/middlewares/on-start-app.ts +0 -42
  183. package/src/services/fetch-skills.mock.ts +0 -21
  184. package/src/services/fetch-skills.test.ts +0 -32
  185. package/src/services/tools/fetch.mocks.ts +0 -41
  186. package/src/types/skills.ts +0 -8
  187. /package/es/services/{fetch-skills.test.d.ts → test/fetch-skills.test.d.ts} +0 -0
  188. /package/es/{index.test.d.ts → services/test/post-progression.test.d.ts} +0 -0
  189. /package/{lib → es/test}/index.test.d.ts +0 -0
  190. /package/es/types/{skills.js → ui-progression.js} +0 -0
  191. /package/lib/services/{fetch-skills.test.d.ts → test/fetch-skills.test.d.ts} +0 -0
  192. /package/lib/{types/skills.js → services/test/post-progression.test.d.ts} +0 -0
@@ -1,20 +1,8 @@
1
- import {FinishedSlidesState} from '../../reducers/ui/finished-slides';
2
-
3
- // -----------------------------------------------------------------------------
1
+ import {FinishedSlides, IconValue} from '../../types/common';
4
2
 
5
3
  export const UPDATE_STEP_ITEMS_ON_VALIDATION = '@@step-items/UPDATE_STEP_ITEMS_ON_VALIDATION';
6
4
  export const UPDATE_STEP_ITEMS_ON_NEXT = '@@step-items/UPDATE_STEP_ITEMS_ON_NEXT';
7
5
 
8
- const ICON_VALUES = {
9
- right: 'right',
10
- wrong: 'wrong',
11
- 'no-answer': 'no-answer'
12
- } as const;
13
-
14
- // -----------------------------------------------------------------------------
15
-
16
- export type IconValue = keyof typeof ICON_VALUES;
17
-
18
6
  type UpdateStepItemsOnValidationClickPayload = {
19
7
  stepNumber: number;
20
8
  icon: IconValue;
@@ -22,7 +10,7 @@ type UpdateStepItemsOnValidationClickPayload = {
22
10
 
23
11
  type UpdateStepItemsOnNextClickPayload = {
24
12
  stepNumber: number;
25
- finishedSlides: FinishedSlidesState;
13
+ finishedSlides: FinishedSlides;
26
14
  current: boolean;
27
15
  };
28
16
 
@@ -1,51 +1,11 @@
1
1
  import {AnyAction, applyMiddleware, compose, createStore, Store} from 'redux';
2
2
  import thunk from 'redux-thunk';
3
+ import rootReducer, {StoreState} from './reducers';
4
+ import {getServices} from './services';
3
5
 
4
- import rootReducer from './reducers';
5
- import onStartApp from './middlewares/on-start-app';
6
+ import {AppOptions} from './types/common';
6
7
 
7
- import {SkillsState} from './reducers/data/skills';
8
- import {SlidesState} from './reducers/data/slides';
9
- import {TokenState} from './reducers/data/token';
10
- import {NavigationState} from './reducers/ui/navigation';
11
- import {ReviewStatusState} from './reducers/ui/review-status';
12
- import {StepItemsState} from './reducers/ui/step-items';
13
- import {FinishedSlidesState} from './reducers/ui/finished-slides';
14
-
15
- import {AnswerUI} from './types/slides';
16
-
17
- // -----------------------------------------------------------------------------
18
-
19
- type DataState = {
20
- isFetching?: boolean;
21
- progression?: {
22
- slideNumber: number;
23
- isCorrect?: boolean;
24
- // pass down the successExitNode if all slides are finished, not before
25
- exitNode?: 'successExitNode' | 'failExitNode';
26
- nextSlide?: {
27
- questionText?: string;
28
- answerUI?: AnswerUI;
29
- };
30
- } | null;
31
- skills: SkillsState;
32
- slides: SlidesState;
33
- token?: TokenState;
34
- };
35
-
36
- export type StoreState = {
37
- ui: {
38
- navigation: NavigationState;
39
- stepItems: StepItemsState;
40
- finishedSlides: FinishedSlidesState;
41
- reviewStatus: ReviewStatusState;
42
- };
43
- data: DataState;
44
- };
45
-
46
- // -----------------------------------------------------------------------------
47
-
48
- export default function configureStore(): Store<StoreState, AnyAction> {
8
+ export default function configureStore(options: AppOptions): Store<StoreState, AnyAction> {
49
9
  const _compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
50
10
  ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
51
11
  name: 'app-review',
@@ -54,7 +14,8 @@ export default function configureStore(): Store<StoreState, AnyAction> {
54
14
  })
55
15
  : compose;
56
16
 
57
- const enhancer = _compose(applyMiddleware(thunk, onStartApp));
17
+ const thunkMiddleware = thunk.withExtraArgument({services: options.services || getServices()});
18
+ const enhancer = _compose(applyMiddleware(thunkMiddleware));
58
19
  const store = createStore(rootReducer, undefined, enhancer);
59
20
 
60
21
  return store;
@@ -1,7 +1,7 @@
1
1
  import noop from 'lodash/fp/noop';
2
- import {Slide} from '../types/slides';
2
+ import {UISlide} from '../types/slides';
3
3
 
4
- export const slide: Slide = {
4
+ export const slide: UISlide = {
5
5
  questionText: 'QCM',
6
6
  answerUI: {
7
7
  help: '__help',
package/src/index.tsx CHANGED
@@ -2,27 +2,33 @@ import React, {useEffect, useState} from 'react';
2
2
  import {AnyAction, Store} from 'redux';
3
3
  import {connect, Provider} from 'react-redux';
4
4
  import AppReviewTemplate from '@coorpacademy/components/es/template/app-review';
5
+ import {TemplateContext} from '@coorpacademy/components/es/template/app-review/template-context';
5
6
 
6
- import configureStore, {StoreState} from './configure-store';
7
+ import configureStore from './configure-store';
7
8
  import {congratsProps, correctionPopinProps} from './fixtures/temp-fixture';
8
9
 
9
10
  import type {AppOptions} from './types/common';
11
+ import type {StoreState} from './reducers';
10
12
  import {SkillsProps} from './types/views/skills';
11
13
  import type {SlidesViewStaticProps} from './types/views/slides';
12
14
 
13
15
  import {Dispatchers} from './actions';
14
16
  import {updateSlidesOnNext, updateSlidesOnValidation, validateSlide} from './actions/data/slides';
15
- import {navigateTo, navigateBack, startApp, ViewPath} from './actions/ui/navigation';
17
+ import {navigateTo, navigateBack, ViewPath} from './actions/ui/navigation';
18
+ import {storeToken} from './actions/data/token';
16
19
  import {updateFinishedSlides} from './actions/ui/finished-slides';
17
20
  import {updateReviewStatus} from './actions/ui/review-status';
18
21
  import {updateStepItemsOnValidation, updateStepItemsOnNext} from './actions/ui/step-items';
22
+ import {fetchSkills} from './actions/api/fetch-skills';
23
+ import {postProgression} from './actions/api/post-progression';
24
+ import {VIEWS} from './common';
19
25
 
20
26
  // -----------------------------------------------------------------------------
21
27
 
22
28
  type StaticProps = {
23
29
  viewName: 'skills' | 'onboarding' | 'slides';
24
- slides: SlidesViewStaticProps;
25
- skills: SkillsProps;
30
+ slides: SlidesViewStaticProps | null;
31
+ skills: SkillsProps | null;
26
32
  };
27
33
 
28
34
  // -----------------------------------------------------------------------------
@@ -42,30 +48,43 @@ const mapDispatchToProps: Dispatchers = {
42
48
  const getCurrentViewName = (storeState: StoreState): ViewPath =>
43
49
  storeState.ui.navigation[storeState.ui.navigation.length - 1];
44
50
 
45
- const mapStateToSkillsProps = (state: StoreState): SkillsProps => ({
46
- title: '@todo title',
47
- titleNoSkills: '@todo titleNoSkills',
48
- textNoSkills: '@todo textNoSkills',
49
- iconSkillAriaLabel: '@todo iconSkillAriaLabel',
50
- isLoading: false,
51
- isLoadingAriaLabel: '@todo loading',
52
- listSkills: state.data.skills.map(skill => ({
53
- 'aria-label': '',
54
- isCustom: skill.custom,
55
- skillTitle: skill.name,
56
- skillAriaLabel: '@todo skill aria label',
57
- buttonLabel: '@todo button',
58
- buttonAriaLabel: '@todo button aria label',
59
- reviseLabel: '@todo revise',
60
- reviseAriaLabel: '@todo revise aria label',
61
- // eslint-disable-next-line no-console
62
- onClick: () => console.log('@todo plug dispatcher select skill')
63
- }))
64
- });
65
-
66
- const mapStateToProps = (state: StoreState): StaticProps => ({
67
- viewName: getCurrentViewName(state),
68
- slides: {
51
+ // -----------------------------------------------------------------------------
52
+
53
+ const mapStateToSkillsProps = (state: StoreState): SkillsProps | null => {
54
+ if (!state.data.skills) {
55
+ return null;
56
+ }
57
+
58
+ return {
59
+ title: '@todo title',
60
+ titleNoSkills: '@todo titleNoSkills',
61
+ textNoSkills: '@todo textNoSkills',
62
+ iconSkillAriaLabel: '@todo iconSkillAriaLabel',
63
+ isLoading: false,
64
+ isLoadingAriaLabel: '@todo loading',
65
+ listSkills: state.data.skills.map(skill => ({
66
+ 'aria-label': '',
67
+ isCustom: skill.custom,
68
+ skillTitle: skill.name,
69
+ skillAriaLabel: '@todo skill aria label',
70
+ buttonLabel: '@todo button',
71
+ buttonAriaLabel: '@todo button aria label',
72
+ reviseLabel: '@todo revise',
73
+ reviseAriaLabel: '@todo revise aria label',
74
+ // eslint-disable-next-line no-console
75
+ onClick: () => console.log('@todo plug dispatcher select skill')
76
+ }))
77
+ };
78
+ };
79
+
80
+ // -----------------------------------------------------------------------------
81
+
82
+ const mapStateToSlidesProps = (state: StoreState): SlidesViewStaticProps | null => {
83
+ if (!state.data.slides) {
84
+ return null;
85
+ }
86
+
87
+ return {
69
88
  headerProps: {
70
89
  mode: '__revision_mode',
71
90
  skillName: '__agility',
@@ -86,9 +105,18 @@ const mapStateToProps = (state: StoreState): StaticProps => ({
86
105
  correctionPopinProps,
87
106
  congratsProps,
88
107
  progression: state.data.progression
89
- },
90
- skills: mapStateToSkillsProps(state)
91
- });
108
+ };
109
+ };
110
+
111
+ // -----------------------------------------------------------------------------
112
+
113
+ const mapStateToProps = (state: StoreState): StaticProps => {
114
+ return {
115
+ viewName: getCurrentViewName(state),
116
+ slides: mapStateToSlidesProps(state),
117
+ skills: mapStateToSkillsProps(state)
118
+ };
119
+ };
92
120
 
93
121
  // Props = StaticProps && Dispatchers
94
122
 
@@ -96,28 +124,49 @@ const App = connect(mapStateToProps, mapDispatchToProps)(AppReviewTemplate);
96
124
 
97
125
  // -----------------------------------------------------------------------------
98
126
 
99
- const AppReview = ({options}: {options: AppOptions}): JSX.Element => {
127
+ const AppReview = ({options}: {options: AppOptions}): JSX.Element | null => {
100
128
  const [store, setStore] = useState<Store<StoreState, AnyAction> | null>(null);
101
- const [appStarted, setAppStarted] = useState<boolean>(false);
102
129
 
103
130
  useEffect(() => {
104
- if (store) {
105
- store.dispatch(startApp(options));
106
- setAppStarted(true);
107
- } else {
108
- const _configure = async (): Promise<void> => {
109
- const newStore = await configureStore();
110
- setStore(newStore);
111
- };
112
- _configure();
113
- }
131
+ if (store) return;
132
+
133
+ const newStore = configureStore(options);
134
+ setStore(newStore);
135
+ }, [options, store]);
136
+
137
+ useEffect(() => {
138
+ if (store === null) return;
139
+
140
+ const {skillRef} = options;
141
+ const initialView: ViewPath = skillRef ? VIEWS.slides : VIEWS.skills;
142
+ store.dispatch(navigateTo(initialView));
143
+ }, [options, store]);
144
+
145
+ useEffect(() => {
146
+ if (store === null) return;
147
+
148
+ const {token} = options;
149
+ store.dispatch(storeToken(token));
114
150
  }, [options, store]);
115
151
 
116
- if (!store || !appStarted) return <div />;
152
+ useEffect(() => {
153
+ if (store === null) return;
154
+
155
+ const {skillRef, token} = options;
156
+ skillRef
157
+ ? store.dispatch(postProgression(skillRef, token))
158
+ : store.dispatch(fetchSkills(token));
159
+ }, [options, store]);
160
+
161
+ if (!store) return null;
162
+
163
+ const {templateContext: values} = options;
117
164
 
118
165
  return (
119
166
  <Provider store={store}>
120
- <App />
167
+ <TemplateContext values={values}>
168
+ <App />
169
+ </TemplateContext>
121
170
  </Provider>
122
171
  );
123
172
  };
@@ -1,9 +1,17 @@
1
1
  import {combineReducers} from 'redux';
2
2
 
3
- import progression from './progression';
4
- import skills from './skills';
5
- import slides from './slides';
6
- import token from './token';
3
+ import progression, {ProgressionState} from './progression';
4
+ import skills, {SkillsState} from './skills';
5
+ import slides, {SlidesState} from './slides';
6
+ import token, {TokenState} from './token';
7
+
8
+ export type DataState = {
9
+ isFetching?: boolean;
10
+ progression?: ProgressionState;
11
+ skills: SkillsState;
12
+ slides: SlidesState;
13
+ token?: TokenState;
14
+ };
7
15
 
8
16
  export default combineReducers({
9
17
  progression,
@@ -1,101 +1,56 @@
1
- import {getOr, noop} from 'lodash/fp';
1
+ import {getOr} from 'lodash/fp';
2
2
  import {ValidateSlide, VALIDATE_SLIDE} from '../../actions/data/slides';
3
- import {AnswerUI} from '../../types/slides';
4
-
5
- // -----------------------------------------------------------------------------
3
+ import {POST_PROGRESSION_SUCCESS, ReceiveProgression} from '../../actions/api/post-progression';
6
4
 
7
5
  export type ProgressionState = {
8
- // virtual field
9
- slideNumber: number;
10
- isCorrect?: boolean;
11
- // pass down the successExitNode if all slides are finished, not before
12
- exitNode?: 'successExitNode' | 'failExitNode';
13
- // TODO: create another action, to retrieve the next slide
14
- // nextSlide should be renamed as nextContent when this new action is created
15
- // ex: nextContent: {ref: "sli_E1n2i2sBo", type: "slide"}
16
- // the middleware should trigger a nextSlide request once the result is
17
- // received && update the state accordingly
18
- nextSlide?: {
19
- questionText?: string;
20
- answerUI?: AnswerUI;
6
+ _id?: string;
7
+ state: {
8
+ isCorrect: boolean;
9
+ nextContent: {
10
+ ref: 'successExitNode' | string;
11
+ type: 'success' | 'slide';
12
+ };
13
+ pendingSlides: string[];
14
+ step: {
15
+ current: number;
16
+ };
21
17
  };
22
- } | null;
23
-
24
- // -----------------------------------------------------------------------------
25
-
26
- export const initialState: ProgressionState = null;
27
-
28
- // -----------------------------------------------------------------------------
18
+ // TO refactor: (slideNumber)
19
+ // virtual field
20
+ slideNumber?: number;
21
+ } | null; // TODO: ça ressemble beaucoup à ProgressionFromAPI et ça devrait l'être
29
22
 
30
23
  const reducer = (
31
24
  // eslint-disable-next-line default-param-last
32
- state: ProgressionState = initialState,
33
- action: ValidateSlide
25
+ state: ProgressionState = null,
26
+ action: ValidateSlide | ReceiveProgression
34
27
  ): ProgressionState => {
35
28
  switch (action.type) {
36
29
  case VALIDATE_SLIDE: {
37
30
  const previousSlideNumber: number = getOr(-1, 'slideNumber', state);
38
31
  // hard coded for now
32
+ // TODO: fix on VALIDATE ticket
39
33
  return {
34
+ _id: '1234',
40
35
  // virtual field
41
36
  slideNumber: previousSlideNumber + 1,
42
- isCorrect: true,
43
- // exitNode
44
- // TODO: create another action, to retrieve the next slide
45
- // nextSlide should be corrected to nextContent, when this new action is created
46
- // ex: nextContent: {ref: "sli_E1n2i2sBo", type: "slide"}
47
- // the middleware should trigger a next content request once the result is
48
- // received && update the state accordingly,
49
- //
50
- nextSlide: {
51
- questionText: 'Test',
52
- answerUI: {
53
- model: {
54
- answers: [
55
- {
56
- title: 'There is no need for a password',
57
- // TODO: onClick of each answer should use a dispatcher to
58
- // update selected answers (in order to use them on validation)
59
- // in each retrieval, the answers of answerUI need to be augmented
60
- // for the onClick prop to achieve this.
61
- onClick: noop,
62
- selected: false,
63
- help: 'help'
64
- },
65
- {
66
- title: 'Lorem ipsum',
67
- onClick: noop,
68
- selected: false,
69
- help: 'help'
70
- },
71
- {
72
- title: 'Lorem',
73
- onClick: noop,
74
- selected: true,
75
- order: 1,
76
- help: 'help'
77
- },
78
- {
79
- title: 'You need to have a password',
80
- onClick: noop,
81
- selected: false,
82
- help: 'help'
83
- },
84
- {
85
- title: 'Pouet',
86
- onClick: noop,
87
- selected: true,
88
- order: 0,
89
- help: 'help'
90
- }
91
- ],
92
- type: 'qcmDrag'
93
- },
94
- help: 'Help text will appear here'
37
+ state: {
38
+ pendingSlides: [],
39
+ step: {
40
+ current: Number.NaN
41
+ },
42
+ isCorrect: true,
43
+ nextContent: {
44
+ ref: 'sli_V1gKpYYZ2',
45
+ type: 'slide'
95
46
  }
96
47
  }
97
48
  };
98
49
  }
50
+ case POST_PROGRESSION_SUCCESS: {
51
+ const progression = action.payload;
52
+ return progression;
53
+ }
99
54
  default:
100
55
  return state;
101
56
  }
@@ -1,21 +1,16 @@
1
- import {ReceivedSkills, RECEIVED_SKILLS} from '../../actions/data/skills';
2
- import {Skills} from '../../types/skills';
1
+ import {Skill} from '../../types/common';
2
+ import {ReceivedSkills, SKILLS_FETCH_SUCCESS} from '../../actions/api/fetch-skills';
3
3
 
4
- export type SkillsState = Skills;
5
- export const initialState: SkillsState = [];
6
-
7
- // -----------------------------------------------------------------------------
4
+ export type SkillsState = Skill[];
8
5
 
9
6
  // eslint-disable-next-line default-param-last
10
- const reducer = (state: SkillsState = initialState, action: ReceivedSkills): SkillsState => {
7
+ const reducer = (state: SkillsState = [], action: ReceivedSkills): SkillsState => {
11
8
  switch (action.type) {
12
- case RECEIVED_SKILLS:
9
+ case SKILLS_FETCH_SUCCESS:
13
10
  return action.payload;
14
11
  default:
15
12
  return state;
16
13
  }
17
14
  };
18
15
 
19
- // -----------------------------------------------------------------------------
20
-
21
16
  export default reducer;
@@ -1,25 +1,22 @@
1
1
  import map from 'lodash/fp/map';
2
2
  import {
3
3
  OnNextPayload,
4
- Slide,
5
4
  SlidesAction,
6
- STORE_FIRST_SLIDE,
7
5
  UPDATE_SLIDES_ON_NEXT,
8
6
  UPDATE_SLIDES_ON_VALIDATION,
9
7
  ValidationPayload
10
8
  } from '../../actions/data/slides';
11
- import {Slide as SlideFromAPI} from '../../types/slides';
9
+ import {UISlide} from '../../types/slides';
12
10
  import {HIGHEST_INDEX, slideNumbers, TOTAL_SLIDES_STACK} from '../../common';
13
-
14
- // -----------------------------------------------------------------------------
11
+ import {slide as qcmSlide} from '../../fixtures/qcm-slide';
12
+ import {SLIDE_FETCH_SUCCESS} from '../../actions/api/fetch-slide';
13
+ import {Slide} from '../../types/common';
15
14
 
16
15
  export type SlidesState = {
17
16
  slideNumbers: number[];
18
17
  [key: number]: Slide;
19
18
  };
20
19
 
21
- // -----------------------------------------------------------------------------
22
-
23
20
  const getInitialState = (): SlidesState => {
24
21
  const state: SlidesState = {
25
22
  slideNumbers
@@ -35,7 +32,7 @@ export const initialState: SlidesState = getInitialState();
35
32
 
36
33
  // -----------------------------------------------------------------------------
37
34
 
38
- const setFirstSlide = (state: SlidesState, slide: SlideFromAPI): SlidesState => {
35
+ const setFirstSlide = (state: SlidesState, slide: UISlide): SlidesState => {
39
36
  const _state: SlidesState = {
40
37
  slideNumbers
41
38
  };
@@ -53,7 +50,7 @@ const setFirstSlide = (state: SlidesState, slide: SlideFromAPI): SlidesState =>
53
50
  // ||-------> Handles the updates of a given slide on validation,
54
51
  // & then updates de remaining slides if this given change should impact their content
55
52
  const stateUpdateOnValidation = (state: SlidesState, payload: ValidationPayload): SlidesState => {
56
- const {slideNumber, newSlideContent, numberOfFinishedSlides, nextSlide} = payload;
53
+ const {slideNumber, newSlideContent, numberOfFinishedSlides, nextContent} = payload;
57
54
  const _state: SlidesState = {
58
55
  slideNumbers
59
56
  };
@@ -67,7 +64,7 @@ const stateUpdateOnValidation = (state: SlidesState, payload: ValidationPayload)
67
64
  if (numberOfFinishedSlides === HIGHEST_INDEX) {
68
65
  _state[index] = {
69
66
  ...previousValue,
70
- nextSlide,
67
+ nextContent,
71
68
  position: newSlideContent.position,
72
69
  isCorrect: newSlideContent.isCorrect
73
70
  };
@@ -75,7 +72,7 @@ const stateUpdateOnValidation = (state: SlidesState, payload: ValidationPayload)
75
72
  } else {
76
73
  // updates the rest of the slides here
77
74
  const {hidden, position} = previousValue;
78
- _state[index] = {...nextSlide, endReview: newSlideContent.endReview, hidden, position};
75
+ _state[index] = {...nextContent, endReview: newSlideContent.endReview, hidden, position};
79
76
  }
80
77
  }, state.slideNumbers);
81
78
 
@@ -96,8 +93,8 @@ const stateUpdateOnNext = (state: SlidesState, payload: OnNextPayload): SlidesSt
96
93
  // the current slide
97
94
  if (index === slideNumber) {
98
95
  // when there is only one slide remaining, updates the slide value
99
- if (numberOfFinishedSlides === HIGHEST_INDEX && previousValue.nextSlide) {
100
- _state[index] = {...previousValue.nextSlide, position: previousValue.position};
96
+ if (numberOfFinishedSlides === HIGHEST_INDEX && previousValue.nextContent) {
97
+ _state[index] = {...previousValue.nextContent, position: previousValue.position};
101
98
  } else _state[slideNumber] = newSlideContent;
102
99
  } else {
103
100
  // updates the rest of the slides here
@@ -120,8 +117,12 @@ const stateUpdateOnNext = (state: SlidesState, payload: OnNextPayload): SlidesSt
120
117
  // eslint-disable-next-line default-param-last
121
118
  const reducer = (state: SlidesState = initialState, action: SlidesAction): SlidesState => {
122
119
  switch (action.type) {
123
- case STORE_FIRST_SLIDE: {
124
- return setFirstSlide(state, action.payload);
120
+ case SLIDE_FETCH_SUCCESS: {
121
+ // TODO: An intermediate slide transform is needed here (or in fetchSlide)
122
+ // const apiSlide = action.payload;
123
+ // apiSlide adapt to uiSlide
124
+ const uiSlide = qcmSlide;
125
+ return setFirstSlide(state, uiSlide);
125
126
  }
126
127
  case UPDATE_SLIDES_ON_VALIDATION: {
127
128
  return stateUpdateOnValidation(state, action.payload);
@@ -1,17 +1,9 @@
1
1
  import {StoreToken, STORE_TOKEN} from '../../actions/data/token';
2
2
 
3
- // -----------------------------------------------------------------------------
4
-
5
3
  export type TokenState = string | null;
6
4
 
7
- // -----------------------------------------------------------------------------
8
-
9
- export const initialState: TokenState = null;
10
-
11
- // -----------------------------------------------------------------------------
12
-
13
5
  // eslint-disable-next-line default-param-last
14
- const reducer = (state: TokenState = initialState, action: StoreToken): TokenState => {
6
+ const reducer = (state: TokenState = null, action: StoreToken): TokenState => {
15
7
  switch (action.type) {
16
8
  case STORE_TOKEN:
17
9
  return action.payload;
@@ -20,6 +12,4 @@ const reducer = (state: TokenState = initialState, action: StoreToken): TokenSta
20
12
  }
21
13
  };
22
14
 
23
- // -----------------------------------------------------------------------------
24
-
25
15
  export default reducer;
@@ -1,7 +1,12 @@
1
1
  import {combineReducers} from 'redux';
2
2
 
3
- import data from './data';
4
- import ui from './ui';
3
+ import data, {DataState} from './data';
4
+ import ui, {UIState} from './ui';
5
+
6
+ export type StoreState = {
7
+ ui: UIState;
8
+ data: DataState;
9
+ };
5
10
 
6
11
  export default combineReducers({
7
12
  data,
@@ -2,21 +2,15 @@ import forEach from 'lodash/fp/forEach';
2
2
  import {UpdateFinishedSlides, UPDATE_FINISHED_SLIDES} from '../../actions/ui/finished-slides';
3
3
  import {slideNumbers} from '../../common';
4
4
 
5
- // -----------------------------------------------------------------------------
6
- // Stores only successful slides
7
5
  export type FinishedSlidesState = {
8
6
  slideNumbers: number[];
9
7
  [key: number]: true;
10
8
  };
11
9
 
12
- // -----------------------------------------------------------------------------
13
-
14
- export const initialState: FinishedSlidesState = {
10
+ const initialState: FinishedSlidesState = {
15
11
  slideNumbers
16
12
  };
17
13
 
18
- // -----------------------------------------------------------------------------
19
-
20
14
  const _forEach: <T>(
21
15
  iteratee: (value: T[keyof T], index: number) => void,
22
16
  collection: T
@@ -1,9 +1,16 @@
1
1
  import {combineReducers} from 'redux';
2
2
 
3
- import finishedSlides from './finished-slides';
4
- import navigation from './navigation';
5
- import reviewStatus from './review-status';
6
- import stepItems from './step-items';
3
+ import finishedSlides, {FinishedSlidesState} from './finished-slides';
4
+ import navigation, {NavigationState} from './navigation';
5
+ import reviewStatus, {ReviewStatusState} from './review-status';
6
+ import stepItems, {StepItemsState} from './step-items';
7
+
8
+ export type UIState = {
9
+ navigation: NavigationState;
10
+ stepItems: StepItemsState;
11
+ finishedSlides: FinishedSlidesState;
12
+ reviewStatus: ReviewStatusState;
13
+ };
7
14
 
8
15
  export default combineReducers({
9
16
  finishedSlides,