@coorpacademy/app-review 0.0.21-alpha.8 → 0.1.2
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/courses.d.ts +0 -1
- package/es/actions/{api → data}/is-fetching.d.ts +0 -1
- package/{lib/actions/api → es/actions/data}/validate-slide.d.ts +0 -1
- package/es/actions/finished-slides.d.ts +0 -1
- package/es/actions/index.d.ts +0 -1
- package/es/actions/navigation.d.ts +0 -1
- package/es/actions/review-status.d.ts +0 -1
- package/es/actions/slides.d.ts +0 -1
- package/es/actions/step-items.d.ts +0 -1
- package/es/actions/token.d.ts +0 -1
- package/es/common/index.d.ts +1 -1
- package/es/common/index.js +1 -0
- package/es/configure-store.d.ts +2 -3
- package/es/configure-store.js +3 -9
- package/es/fixtures/qcm-slide.d.ts +2 -0
- package/es/fixtures/qcm-slide.js +29 -0
- package/es/{temp-fixture.d.ts → fixtures/temp-fixture.d.ts} +1 -2
- package/es/helpers/css-register.js +2 -0
- package/es/index.d.ts +1 -3
- package/es/index.js +43 -27
- package/es/index.test.js +52 -0
- package/es/middlewares/on-start-app.d.ts +0 -1
- package/es/middlewares/on-start-app.js +2 -0
- package/es/reducers/courses.d.ts +0 -1
- package/es/reducers/data.d.ts +7 -0
- package/es/reducers/{api.js → data.js} +15 -8
- package/es/reducers/finished-slides.d.ts +1 -2
- package/es/reducers/finished-slides.js +17 -7
- package/es/reducers/index.d.ts +9 -14
- package/es/reducers/index.js +7 -6
- package/es/reducers/navigation.d.ts +0 -1
- package/es/reducers/navigation.js +1 -1
- package/es/reducers/review-status.d.ts +0 -1
- package/es/reducers/slides.d.ts +1 -2
- package/es/reducers/slides.js +37 -25
- package/es/reducers/step-items.d.ts +1 -2
- package/es/reducers/step-items.js +19 -12
- package/es/reducers/token.d.ts +4 -7
- package/es/reducers/token.js +3 -14
- package/es/services/fetch-demo.d.ts +0 -1
- package/es/services/fetch-demo.test.d.ts +0 -1
- package/es/services/fetch-responses.d.ts +0 -1
- package/es/services/fetch.mocks.d.ts +0 -1
- package/es/types/common.d.ts +0 -1
- package/es/types/data/index.d.ts +14 -0
- package/es/types/data/index.js +1 -0
- package/es/types/dispatchers.d.ts +1 -2
- package/es/types/finished-slides.d.ts +4 -2
- package/es/types/review-status.d.ts +0 -1
- package/es/types/slides.d.ts +4 -2
- package/es/types/states.d.ts +1 -3
- package/es/types/step-items.d.ts +4 -2
- package/es/types/store-state.d.ts +10 -10
- package/es/types/utils.d.ts +0 -1
- package/es/types/views.d.ts +9 -3
- package/lib/actions/courses.d.ts +0 -1
- package/lib/actions/{api → data}/is-fetching.d.ts +0 -1
- package/{es/actions/api → lib/actions/data}/validate-slide.d.ts +0 -1
- package/lib/actions/finished-slides.d.ts +0 -1
- package/lib/actions/index.d.ts +0 -1
- package/lib/actions/navigation.d.ts +0 -1
- package/lib/actions/review-status.d.ts +0 -1
- package/lib/actions/slides.d.ts +0 -1
- package/lib/actions/step-items.d.ts +0 -1
- package/lib/actions/token.d.ts +0 -1
- package/lib/common/index.d.ts +1 -1
- package/lib/common/index.js +1 -0
- package/lib/configure-store.d.ts +2 -3
- package/lib/configure-store.js +10 -66
- package/lib/fixtures/qcm-slide.d.ts +2 -0
- package/lib/fixtures/qcm-slide.js +29 -0
- package/lib/{temp-fixture.d.ts → fixtures/temp-fixture.d.ts} +1 -2
- package/lib/helpers/css-register.d.ts +1 -0
- package/lib/helpers/css-register.js +2 -0
- package/lib/index.d.ts +1 -3
- package/lib/index.js +52 -52
- package/lib/index.test.d.ts +1 -0
- package/lib/index.test.js +160 -0
- package/lib/middlewares/on-start-app.d.ts +0 -1
- package/lib/middlewares/on-start-app.js +2 -0
- package/lib/reducers/courses.d.ts +0 -1
- package/lib/reducers/courses.js +1 -17
- package/lib/reducers/data.d.ts +7 -0
- package/lib/reducers/{api.js → data.js} +15 -8
- package/lib/reducers/finished-slides.d.ts +1 -2
- package/lib/reducers/finished-slides.js +28 -45
- package/lib/reducers/index.d.ts +9 -14
- package/lib/reducers/index.js +7 -6
- package/lib/reducers/navigation.d.ts +0 -1
- package/lib/reducers/navigation.js +3 -19
- package/lib/reducers/review-status.d.ts +0 -1
- package/lib/reducers/slides.d.ts +1 -2
- package/lib/reducers/slides.js +58 -106
- package/lib/reducers/step-items.d.ts +1 -2
- package/lib/reducers/step-items.js +21 -52
- package/lib/reducers/token.d.ts +4 -7
- package/lib/reducers/token.js +3 -15
- package/lib/services/fetch-demo.d.ts +0 -1
- package/lib/services/fetch-demo.test.d.ts +0 -1
- package/lib/services/fetch-responses.d.ts +0 -1
- package/lib/services/fetch.mocks.d.ts +0 -1
- package/lib/types/common.d.ts +0 -1
- package/lib/types/data/index.d.ts +14 -0
- package/lib/types/data/index.js +1 -0
- package/lib/types/dispatchers.d.ts +1 -2
- package/lib/types/finished-slides.d.ts +4 -2
- package/lib/types/review-status.d.ts +0 -1
- package/lib/types/slides.d.ts +4 -2
- package/lib/types/states.d.ts +1 -3
- package/lib/types/step-items.d.ts +4 -2
- package/lib/types/store-state.d.ts +10 -10
- package/lib/types/utils.d.ts +0 -1
- package/lib/types/views.d.ts +9 -3
- package/package.json +10 -7
- package/src/common/index.ts +2 -0
- package/src/configure-store.ts +10 -20
- package/src/fixtures/qcm-slide.ts +31 -0
- package/src/{temp-fixture.ts → fixtures/temp-fixture.ts} +1 -1
- package/src/helpers/css-modules-require-hook.d.ts +4 -0
- package/src/helpers/css-register.ts +3 -0
- package/src/index.test.tsx +82 -0
- package/src/index.tsx +48 -34
- package/src/middlewares/on-start-app.ts +2 -0
- package/src/reducers/{api.ts → data.ts} +17 -14
- package/src/reducers/finished-slides.ts +22 -7
- package/src/reducers/index.ts +8 -6
- package/src/reducers/navigation.ts +1 -1
- package/src/reducers/slides.ts +38 -25
- package/src/reducers/step-items.ts +22 -12
- package/src/reducers/token.ts +5 -17
- package/src/types/data/index.ts +16 -0
- package/src/types/dispatchers.ts +1 -1
- package/src/types/finished-slides.ts +5 -2
- package/src/types/globals.d.ts +6 -0
- package/src/types/slides.ts +6 -3
- package/src/types/states.ts +1 -2
- package/src/types/step-items.ts +4 -1
- package/src/types/store-state.ts +11 -11
- package/src/types/views.tsx +9 -2
- package/es/actions/api/is-fetching.d.ts.map +0 -1
- package/es/actions/api/validate-slide.d.ts.map +0 -1
- package/es/actions/courses.d.ts.map +0 -1
- package/es/actions/finished-slides.d.ts.map +0 -1
- package/es/actions/index.d.ts.map +0 -1
- package/es/actions/navigation.d.ts.map +0 -1
- package/es/actions/review-status.d.ts.map +0 -1
- package/es/actions/slides.d.ts.map +0 -1
- package/es/actions/step-items.d.ts.map +0 -1
- package/es/actions/token.d.ts.map +0 -1
- package/es/common/index.d.ts.map +0 -1
- package/es/configure-store.d.ts.map +0 -1
- package/es/index.d.ts.map +0 -1
- package/es/middlewares/on-start-app.d.ts.map +0 -1
- package/es/reducers/api.d.ts +0 -12
- package/es/reducers/api.d.ts.map +0 -1
- package/es/reducers/courses.d.ts.map +0 -1
- package/es/reducers/finished-slides.d.ts.map +0 -1
- package/es/reducers/index.d.ts.map +0 -1
- package/es/reducers/navigation.d.ts.map +0 -1
- package/es/reducers/review-status.d.ts.map +0 -1
- package/es/reducers/slides.d.ts.map +0 -1
- package/es/reducers/step-items.d.ts.map +0 -1
- package/es/reducers/token.d.ts.map +0 -1
- package/es/services/fetch-demo.d.ts.map +0 -1
- package/es/services/fetch-demo.test.d.ts.map +0 -1
- package/es/services/fetch-responses.d.ts.map +0 -1
- package/es/services/fetch.mocks.d.ts.map +0 -1
- package/es/temp-fixture.d.ts.map +0 -1
- package/es/types/api/index.d.ts +0 -16
- package/es/types/api/index.d.ts.map +0 -1
- package/es/types/common.d.ts.map +0 -1
- package/es/types/dispatchers.d.ts.map +0 -1
- package/es/types/finished-slides.d.ts.map +0 -1
- package/es/types/review-status.d.ts.map +0 -1
- package/es/types/slides.d.ts.map +0 -1
- package/es/types/states.d.ts.map +0 -1
- package/es/types/step-items.d.ts.map +0 -1
- package/es/types/store-state.d.ts.map +0 -1
- package/es/types/utils.d.ts.map +0 -1
- package/es/types/views.d.ts.map +0 -1
- package/lib/actions/api/is-fetching.d.ts.map +0 -1
- package/lib/actions/api/validate-slide.d.ts.map +0 -1
- package/lib/actions/courses.d.ts.map +0 -1
- package/lib/actions/finished-slides.d.ts.map +0 -1
- package/lib/actions/index.d.ts.map +0 -1
- package/lib/actions/navigation.d.ts.map +0 -1
- package/lib/actions/review-status.d.ts.map +0 -1
- package/lib/actions/slides.d.ts.map +0 -1
- package/lib/actions/step-items.d.ts.map +0 -1
- package/lib/actions/token.d.ts.map +0 -1
- package/lib/common/index.d.ts.map +0 -1
- package/lib/configure-store.d.ts.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/middlewares/on-start-app.d.ts.map +0 -1
- package/lib/reducers/api.d.ts +0 -12
- package/lib/reducers/api.d.ts.map +0 -1
- package/lib/reducers/courses.d.ts.map +0 -1
- package/lib/reducers/finished-slides.d.ts.map +0 -1
- package/lib/reducers/index.d.ts.map +0 -1
- package/lib/reducers/navigation.d.ts.map +0 -1
- package/lib/reducers/review-status.d.ts.map +0 -1
- package/lib/reducers/slides.d.ts.map +0 -1
- package/lib/reducers/step-items.d.ts.map +0 -1
- package/lib/reducers/token.d.ts.map +0 -1
- package/lib/services/fetch-demo.d.ts.map +0 -1
- package/lib/services/fetch-demo.test.d.ts.map +0 -1
- package/lib/services/fetch-responses.d.ts.map +0 -1
- package/lib/services/fetch.mocks.d.ts.map +0 -1
- package/lib/temp-fixture.d.ts.map +0 -1
- package/lib/types/api/index.d.ts +0 -16
- package/lib/types/api/index.d.ts.map +0 -1
- package/lib/types/common.d.ts.map +0 -1
- package/lib/types/dispatchers.d.ts.map +0 -1
- package/lib/types/finished-slides.d.ts.map +0 -1
- package/lib/types/review-status.d.ts.map +0 -1
- package/lib/types/slides.d.ts.map +0 -1
- package/lib/types/states.d.ts.map +0 -1
- package/lib/types/step-items.d.ts.map +0 -1
- package/lib/types/store-state.d.ts.map +0 -1
- package/lib/types/utils.d.ts.map +0 -1
- package/lib/types/views.d.ts.map +0 -1
- package/src/types/api/index.ts +0 -16
- /package/es/actions/{api → data}/is-fetching.js +0 -0
- /package/es/actions/{api → data}/validate-slide.js +0 -0
- /package/es/{temp-fixture.js → fixtures/temp-fixture.js} +0 -0
- /package/es/{types/api/index.js → helpers/css-register.d.ts} +0 -0
- /package/{lib/types/api/index.js → es/index.test.d.ts} +0 -0
- /package/lib/actions/{api → data}/is-fetching.js +0 -0
- /package/lib/actions/{api → data}/validate-slide.js +0 -0
- /package/lib/{temp-fixture.js → fixtures/temp-fixture.js} +0 -0
- /package/src/actions/{api → data}/is-fetching.ts +0 -0
- /package/src/actions/{api → data}/validate-slide.ts +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {Slide} from '../types/slides';
|
|
2
|
+
|
|
3
|
+
export const slide: Slide = {
|
|
4
|
+
questionText: 'QCM',
|
|
5
|
+
answerUI: {
|
|
6
|
+
help: '__help',
|
|
7
|
+
model: {
|
|
8
|
+
type: 'qcm',
|
|
9
|
+
choices: [
|
|
10
|
+
{
|
|
11
|
+
selected: false,
|
|
12
|
+
title: 'choix1',
|
|
13
|
+
help: '(help choix1)',
|
|
14
|
+
ariaLabel: '__ariaLabel1'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
selected: false,
|
|
18
|
+
title: 'choix2',
|
|
19
|
+
help: '(help choix2)',
|
|
20
|
+
ariaLabel: '__ariaLabel2'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
selected: false,
|
|
24
|
+
title: 'choix3',
|
|
25
|
+
help: '(help choix3)',
|
|
26
|
+
ariaLabel: '__ariaLabel3'
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import browserEnv from 'browser-env';
|
|
2
|
+
import test from 'ava';
|
|
3
|
+
import type {ExecutionContext} from 'ava';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import {render, fireEvent, act} from '@testing-library/react';
|
|
6
|
+
import {slide} from './fixtures/qcm-slide';
|
|
7
|
+
import type {AppOptions} from './types/common';
|
|
8
|
+
import AppReview from '.';
|
|
9
|
+
|
|
10
|
+
browserEnv({pretendToBeVisual: true});
|
|
11
|
+
|
|
12
|
+
const elementExists = (foundElements: NodeListOf<Element>): Element =>
|
|
13
|
+
foundElements && foundElements[0];
|
|
14
|
+
|
|
15
|
+
const sleep = (msToSleep: number): Promise<void> =>
|
|
16
|
+
new Promise(resolve => {
|
|
17
|
+
setTimeout(resolve, msToSleep);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const waitForChanges = async (msToWait = 3000): Promise<void> => {
|
|
21
|
+
await act(async () => {
|
|
22
|
+
await sleep(msToWait); // wait *just* a little longer than the timeout in the component
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const LIMIT = 5;
|
|
27
|
+
|
|
28
|
+
const clickAllSlides = async (
|
|
29
|
+
t: ExecutionContext<unknown>,
|
|
30
|
+
container: HTMLElement,
|
|
31
|
+
accumulator = 0
|
|
32
|
+
): Promise<void> => {
|
|
33
|
+
if (accumulator === LIMIT) return;
|
|
34
|
+
|
|
35
|
+
// last one needs to wait for more calculations && components updates
|
|
36
|
+
if (accumulator === 4)
|
|
37
|
+
await act(async () => {
|
|
38
|
+
await sleep(1000);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const validateButton = container.querySelectorAll(
|
|
42
|
+
`[data-name="slide-validate-button-${accumulator}"]`
|
|
43
|
+
);
|
|
44
|
+
t.truthy(elementExists(validateButton));
|
|
45
|
+
|
|
46
|
+
await act(async () => {
|
|
47
|
+
await fireEvent.click(validateButton[0]);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const nextButton = container.querySelectorAll(
|
|
51
|
+
`[data-name="next-question-button-${accumulator}"]`
|
|
52
|
+
);
|
|
53
|
+
t.truthy(elementExists(nextButton));
|
|
54
|
+
|
|
55
|
+
await act(async () => {
|
|
56
|
+
await fireEvent.click(nextButton[0]);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await clickAllSlides(t, container, accumulator + 1);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const appOptions: AppOptions = {
|
|
63
|
+
token: process.env.API_TEST_TOKEN || '',
|
|
64
|
+
slide
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
test('should validate all the slides (all correct scenario)', async t => {
|
|
68
|
+
t.plan(13);
|
|
69
|
+
const {container} = render(<AppReview options={appOptions} key={0} />);
|
|
70
|
+
await waitForChanges(1000);
|
|
71
|
+
|
|
72
|
+
const wrapper = container.querySelector('[data-name="slides-revision-container"]');
|
|
73
|
+
t.truthy(wrapper);
|
|
74
|
+
|
|
75
|
+
const stackedSlidesContainer = wrapper.querySelector('[data-name="stacked-slides-container"]');
|
|
76
|
+
|
|
77
|
+
t.truthy(stackedSlidesContainer);
|
|
78
|
+
|
|
79
|
+
await clickAllSlides(t, container);
|
|
80
|
+
|
|
81
|
+
t.pass();
|
|
82
|
+
});
|
package/src/index.tsx
CHANGED
|
@@ -6,15 +6,15 @@ import configureStore from './configure-store';
|
|
|
6
6
|
import {navigateTo, navigateBack, startApp} from './actions/navigation';
|
|
7
7
|
import {updateSlidesOnNext, updateSlidesOnValidation} from './actions/slides';
|
|
8
8
|
import {getCurrentViewName} from './reducers/navigation';
|
|
9
|
-
import {SlidesViewStaticProps} from './types/views';
|
|
10
|
-
import {AppOptions} from './types/common';
|
|
11
|
-
import {StoreState} from './types/store-state';
|
|
12
|
-
import {congratsProps, correctionPopinProps} from './temp-fixture';
|
|
9
|
+
import type {SlidesViewStaticProps} from './types/views';
|
|
10
|
+
import type {AppOptions} from './types/common';
|
|
11
|
+
import type {StoreState} from './types/store-state';
|
|
12
|
+
import {congratsProps, correctionPopinProps} from './fixtures/temp-fixture';
|
|
13
13
|
import {updateFinishedSlides} from './actions/finished-slides';
|
|
14
14
|
import {updateReviewStatus} from './actions/review-status';
|
|
15
15
|
import {updateStepItemsOnValidation, updateStepItemsOnNext} from './actions/step-items';
|
|
16
|
-
import {Dispatchers} from './types/dispatchers';
|
|
17
|
-
import {validateSlide} from './actions/
|
|
16
|
+
import type {Dispatchers} from './types/dispatchers';
|
|
17
|
+
import {validateSlide} from './actions/data/validate-slide';
|
|
18
18
|
|
|
19
19
|
// -----------------------------------------------------------------------------
|
|
20
20
|
|
|
@@ -36,22 +36,34 @@ const mapDispatchToProps: Dispatchers = {
|
|
|
36
36
|
updateStepItemsOnNext,
|
|
37
37
|
updateFinishedSlides
|
|
38
38
|
};
|
|
39
|
-
|
|
40
|
-
const mapStateToProps = (state: StoreState): StaticProps =>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
slides:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
39
|
+
|
|
40
|
+
const mapStateToProps = (state: StoreState): StaticProps => {
|
|
41
|
+
return {
|
|
42
|
+
viewName: getCurrentViewName(state),
|
|
43
|
+
slides: {
|
|
44
|
+
headerProps: {
|
|
45
|
+
mode: '__revision_mode',
|
|
46
|
+
skillName: '__agility',
|
|
47
|
+
onQuitClick: (): void => {
|
|
48
|
+
// eslint-disable-next-line no-console
|
|
49
|
+
console.log('onQuitClick');
|
|
50
|
+
},
|
|
51
|
+
'aria-label': 'aria-header-wrapper',
|
|
52
|
+
closeButtonAriaLabel: 'aria-close-button'
|
|
53
|
+
},
|
|
54
|
+
slides: state.ui.slides,
|
|
55
|
+
validate: {
|
|
56
|
+
label: '__validate'
|
|
57
|
+
},
|
|
58
|
+
finishedSlides: state.ui.finishedSlides,
|
|
59
|
+
stepItems: state.ui.stepItems,
|
|
60
|
+
reviewStatus: state.ui.reviewStatus,
|
|
61
|
+
correctionPopinProps,
|
|
62
|
+
congratsProps,
|
|
63
|
+
slideValidationResult: state.data.slideValidationResult
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
};
|
|
55
67
|
|
|
56
68
|
// Props = StaticProps && Dispatchers
|
|
57
69
|
|
|
@@ -61,18 +73,22 @@ const App = connect(mapStateToProps, mapDispatchToProps)(AppReviewTemplate);
|
|
|
61
73
|
|
|
62
74
|
const AppReview = ({options}: {options: AppOptions}): JSX.Element => {
|
|
63
75
|
const [store, setStore] = useState(null);
|
|
76
|
+
const [appStarted, setAppStarted] = useState(false);
|
|
64
77
|
|
|
65
78
|
useEffect(() => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
if (store) {
|
|
80
|
+
store.dispatch(startApp(options));
|
|
81
|
+
setAppStarted(true);
|
|
82
|
+
} else {
|
|
83
|
+
const _configure = async (): Promise<void> => {
|
|
84
|
+
const _store = await configureStore();
|
|
85
|
+
setStore(_store);
|
|
86
|
+
};
|
|
87
|
+
_configure();
|
|
88
|
+
}
|
|
89
|
+
}, [options, store]);
|
|
90
|
+
|
|
91
|
+
if (!store || !appStarted) return null;
|
|
76
92
|
|
|
77
93
|
return (
|
|
78
94
|
<Provider store={store}>
|
|
@@ -90,8 +106,6 @@ declare global {
|
|
|
90
106
|
}
|
|
91
107
|
}
|
|
92
108
|
|
|
93
|
-
// type Props = {options: AppOptions};
|
|
94
|
-
|
|
95
109
|
// -----------------------------------------------------------------------------
|
|
96
110
|
|
|
97
111
|
export default AppReview;
|
|
@@ -15,6 +15,8 @@ const onStartApp: Middleware<{}, StoreState, Dispatch<Action>> =
|
|
|
15
15
|
next =>
|
|
16
16
|
(action: Action) => {
|
|
17
17
|
if (action.type === START_APP) {
|
|
18
|
+
// eslint-disable-next-line no-warning-comments
|
|
19
|
+
// TODO: fetchProgression + fetchSlide à partir de la progression passée dans les options de l'app
|
|
18
20
|
const {slide} = action.payload;
|
|
19
21
|
if (slide) {
|
|
20
22
|
const {token} = action.payload;
|
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
import getOr from 'lodash/fp/getOr';
|
|
2
2
|
import noop from 'lodash/fp/noop';
|
|
3
3
|
import set from 'lodash/fp/set';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import {StoreToken, STORE_TOKEN} from '../actions/token';
|
|
5
|
+
import {IsFetching, IS_FETCHING_TRUE} from '../actions/data/is-fetching';
|
|
6
|
+
import {ValidateSlide, VALIDATE_SLIDE} from '../actions/data/validate-slide';
|
|
7
|
+
import {DataState} from '../types/data';
|
|
8
|
+
import {setToken} from './token';
|
|
7
9
|
|
|
8
10
|
const defaultState = {
|
|
9
|
-
|
|
11
|
+
isFetching: true,
|
|
12
|
+
slideValidationResult: null,
|
|
13
|
+
token: null
|
|
10
14
|
};
|
|
11
15
|
|
|
12
|
-
type ApiActions = IsFetching | ValidateSlide;
|
|
16
|
+
type ApiActions = IsFetching | ValidateSlide | StoreToken;
|
|
13
17
|
|
|
14
18
|
// eslint-disable-next-line default-param-last
|
|
15
|
-
const
|
|
19
|
+
const data = (state: DataState = defaultState, action: ApiActions): DataState => {
|
|
16
20
|
switch (action.type) {
|
|
21
|
+
case STORE_TOKEN: {
|
|
22
|
+
return setToken(action.payload, state);
|
|
23
|
+
}
|
|
17
24
|
case VALIDATE_SLIDE: {
|
|
18
|
-
const previousSlideNumber: number = getOr(
|
|
19
|
-
-1,
|
|
20
|
-
'entities.slideValidationResult.slideNumber',
|
|
21
|
-
state
|
|
22
|
-
);
|
|
25
|
+
const previousSlideNumber: number = getOr(-1, 'slideValidationResult.slideNumber', state);
|
|
23
26
|
// hard coded for now
|
|
24
27
|
return set(
|
|
25
|
-
|
|
28
|
+
'slideValidationResult',
|
|
26
29
|
{
|
|
27
30
|
slideNumber: previousSlideNumber + 1,
|
|
28
31
|
result: 'success',
|
|
@@ -70,7 +73,7 @@ const api = (state = defaultState, action: ApiActions): ApiState => {
|
|
|
70
73
|
);
|
|
71
74
|
}
|
|
72
75
|
case IS_FETCHING_TRUE: {
|
|
73
|
-
return set('
|
|
76
|
+
return set('isFetching', true, state);
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
// case VALIDATE_SLIDE_FAILURE: {
|
|
@@ -82,4 +85,4 @@ const api = (state = defaultState, action: ApiActions): ApiState => {
|
|
|
82
85
|
}
|
|
83
86
|
};
|
|
84
87
|
|
|
85
|
-
export default
|
|
88
|
+
export default data;
|
|
@@ -1,10 +1,22 @@
|
|
|
1
|
+
import forEach from 'lodash/fp/forEach';
|
|
1
2
|
import {UpdateFinishedSlides, UPDATE_FINISHED_SLIDES} from '../actions/finished-slides';
|
|
3
|
+
import {slideNumbers} from '../common';
|
|
2
4
|
import {FinishedSlides} from '../types/finished-slides';
|
|
3
5
|
|
|
6
|
+
const _forEach: <T>(
|
|
7
|
+
iteratee: (value: T[keyof T], index: number) => void,
|
|
8
|
+
collection: T
|
|
9
|
+
// @ts-expect-error to remove lodash's forEach iteratee args number cap
|
|
10
|
+
) => void = forEach.convert({
|
|
11
|
+
cap: false
|
|
12
|
+
});
|
|
13
|
+
|
|
4
14
|
// -----------------------------------------------------------------------------
|
|
5
15
|
|
|
6
16
|
export type State = FinishedSlides;
|
|
7
|
-
export const initialState: State =
|
|
17
|
+
export const initialState: State = {
|
|
18
|
+
slideNumbers
|
|
19
|
+
};
|
|
8
20
|
|
|
9
21
|
// -----------------------------------------------------------------------------
|
|
10
22
|
|
|
@@ -12,15 +24,18 @@ export const initialState: State = new Map<number, true>();
|
|
|
12
24
|
const reducer = (state: State = initialState, action: UpdateFinishedSlides): State => {
|
|
13
25
|
switch (action.type) {
|
|
14
26
|
case UPDATE_FINISHED_SLIDES: {
|
|
27
|
+
const {slideNumbers: _slideNumbers, ...rest} = state;
|
|
15
28
|
const {slideNumber, value} = action.payload;
|
|
16
|
-
const _state =
|
|
29
|
+
const _state: State = {
|
|
30
|
+
slideNumbers: _slideNumbers
|
|
31
|
+
};
|
|
17
32
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
_state
|
|
21
|
-
}
|
|
33
|
+
_forEach<Omit<State, 'slideNumbers'>>((finishedSlide, index) => {
|
|
34
|
+
const previousValue = finishedSlide;
|
|
35
|
+
_state[index] = previousValue;
|
|
36
|
+
}, rest);
|
|
22
37
|
|
|
23
|
-
_state
|
|
38
|
+
_state[slideNumber] = value;
|
|
24
39
|
return _state;
|
|
25
40
|
}
|
|
26
41
|
default:
|
package/src/reducers/index.ts
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import {combineReducers} from 'redux';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import data from './data';
|
|
4
4
|
import courses from './courses';
|
|
5
5
|
import finishedSlides from './finished-slides';
|
|
6
6
|
import navigation from './navigation';
|
|
7
7
|
import reviewStatus from './review-status';
|
|
8
8
|
import slides from './slides';
|
|
9
9
|
import stepItems from './step-items';
|
|
10
|
-
import token from './token';
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
api,
|
|
11
|
+
const ui = combineReducers({
|
|
14
12
|
courses,
|
|
15
13
|
finishedSlides,
|
|
16
14
|
navigation,
|
|
17
15
|
reviewStatus,
|
|
18
16
|
slides,
|
|
19
|
-
stepItems
|
|
20
|
-
|
|
17
|
+
stepItems
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export default combineReducers({
|
|
21
|
+
ui,
|
|
22
|
+
data
|
|
21
23
|
});
|
|
@@ -29,7 +29,7 @@ const reducer = (state: State = initialState, action: NavigateTo | NavigateBack)
|
|
|
29
29
|
// -----------------------------------------------------------------------------
|
|
30
30
|
|
|
31
31
|
export const getCurrentViewName = (appState: StoreState): ViewPath =>
|
|
32
|
-
appState.navigation[appState.navigation.length - 1];
|
|
32
|
+
appState.ui.navigation[appState.ui.navigation.length - 1];
|
|
33
33
|
|
|
34
34
|
// -----------------------------------------------------------------------------
|
|
35
35
|
|
package/src/reducers/slides.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import map from 'lodash/fp/map';
|
|
1
2
|
import {
|
|
2
3
|
SlidesAction,
|
|
3
4
|
STORE_FIRST_SLIDE,
|
|
4
5
|
UPDATE_SLIDES_ON_NEXT,
|
|
5
6
|
UPDATE_SLIDES_ON_VALIDATION
|
|
6
7
|
} from '../actions/slides';
|
|
7
|
-
import {HIGHEST_INDEX, TOTAL_SLIDES_STACK} from '../common';
|
|
8
|
+
import {HIGHEST_INDEX, slideNumbers, TOTAL_SLIDES_STACK} from '../common';
|
|
8
9
|
import {
|
|
9
10
|
Slide,
|
|
10
11
|
Slides,
|
|
@@ -17,10 +18,12 @@ import {
|
|
|
17
18
|
export type State = Slides;
|
|
18
19
|
|
|
19
20
|
const getInitialState = (): State => {
|
|
20
|
-
const state: State =
|
|
21
|
+
const state: State = {
|
|
22
|
+
slideNumbers
|
|
23
|
+
};
|
|
21
24
|
// eslint-disable-next-line fp/no-loops
|
|
22
25
|
for (let index = 0; index < TOTAL_SLIDES_STACK; index++) {
|
|
23
|
-
state
|
|
26
|
+
state[index] = {hidden: false, position: index};
|
|
24
27
|
}
|
|
25
28
|
return state;
|
|
26
29
|
};
|
|
@@ -30,13 +33,17 @@ export const initialState: State = getInitialState();
|
|
|
30
33
|
// -----------------------------------------------------------------------------
|
|
31
34
|
|
|
32
35
|
const setFirstSlide = (state, slide: Slide): State => {
|
|
33
|
-
const _state: State =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
const _state: State = {
|
|
37
|
+
slideNumbers
|
|
38
|
+
};
|
|
39
|
+
// eslint-disable-next-line lodash-fp/no-unused-result
|
|
40
|
+
map(index => {
|
|
41
|
+
const previousValue = state[index];
|
|
36
42
|
// Only update the 1st one
|
|
37
43
|
const content = index === 0 ? {...previousValue, ...slide} : {...previousValue};
|
|
38
|
-
_state
|
|
39
|
-
}
|
|
44
|
+
_state[index] = {...content};
|
|
45
|
+
}, state.slideNumbers);
|
|
46
|
+
|
|
40
47
|
return _state;
|
|
41
48
|
};
|
|
42
49
|
|
|
@@ -44,27 +51,30 @@ const setFirstSlide = (state, slide: Slide): State => {
|
|
|
44
51
|
// & then updates de remaining slides if this given change should impact their content
|
|
45
52
|
const stateUpdateOnValidation = (state: State, payload: UpdateSlidesOnValidationPayload): State => {
|
|
46
53
|
const {slideNumber, newSlideContent, numberOfFinishedSlides, nextSlide} = payload;
|
|
47
|
-
const _state: State =
|
|
54
|
+
const _state: State = {
|
|
55
|
+
slideNumbers
|
|
56
|
+
};
|
|
48
57
|
|
|
49
|
-
// eslint-disable-next-line fp/no-
|
|
50
|
-
|
|
58
|
+
// eslint-disable-next-line lodash-fp/no-unused-result
|
|
59
|
+
map(index => {
|
|
60
|
+
const previousValue = state[index];
|
|
51
61
|
// the current slide
|
|
52
62
|
if (index === slideNumber) {
|
|
53
63
|
// only one slide remaining, presets the next value
|
|
54
64
|
if (numberOfFinishedSlides === HIGHEST_INDEX) {
|
|
55
|
-
_state
|
|
65
|
+
_state[index] = {
|
|
56
66
|
...previousValue,
|
|
57
67
|
nextSlide,
|
|
58
68
|
position: newSlideContent.position,
|
|
59
69
|
validationResult: newSlideContent.validationResult
|
|
60
|
-
}
|
|
61
|
-
} else _state
|
|
70
|
+
};
|
|
71
|
+
} else _state[slideNumber] = {...previousValue, ...newSlideContent};
|
|
62
72
|
} else {
|
|
63
73
|
// updates the rest of the slides here
|
|
64
74
|
const {hidden, position} = previousValue;
|
|
65
|
-
_state
|
|
75
|
+
_state[index] = {...nextSlide, endReview: newSlideContent.endReview, hidden, position};
|
|
66
76
|
}
|
|
67
|
-
}
|
|
77
|
+
}, state.slideNumbers);
|
|
68
78
|
|
|
69
79
|
return _state;
|
|
70
80
|
};
|
|
@@ -73,28 +83,31 @@ const stateUpdateOnValidation = (state: State, payload: UpdateSlidesOnValidation
|
|
|
73
83
|
// & then updates de remaining slides (updates position to trigger animations)
|
|
74
84
|
const stateUpdateOnNext = (state: State, payload: UpdateSlidesOnNextPayload): State => {
|
|
75
85
|
const {slideNumber, newSlideContent, numberOfFinishedSlides} = payload;
|
|
76
|
-
const _state: State =
|
|
86
|
+
const _state: State = {
|
|
87
|
+
slideNumbers
|
|
88
|
+
};
|
|
77
89
|
|
|
78
|
-
// eslint-disable-next-line fp/no-
|
|
79
|
-
|
|
90
|
+
// eslint-disable-next-line lodash-fp/no-unused-result
|
|
91
|
+
map(index => {
|
|
92
|
+
const previousValue = state[index];
|
|
80
93
|
// the current slide
|
|
81
94
|
if (index === slideNumber) {
|
|
82
95
|
// when there is only one slide remaining, updates the slide value
|
|
83
|
-
if (numberOfFinishedSlides === HIGHEST_INDEX) {
|
|
84
|
-
_state
|
|
85
|
-
} else _state
|
|
96
|
+
if (numberOfFinishedSlides === HIGHEST_INDEX && previousValue.nextSlide) {
|
|
97
|
+
_state[index] = {...previousValue.nextSlide, position: previousValue.position};
|
|
98
|
+
} else _state[slideNumber] = newSlideContent;
|
|
86
99
|
} else {
|
|
87
100
|
// updates the rest of the slides here
|
|
88
101
|
const {hidden, position, answerUI, questionText} = previousValue;
|
|
89
|
-
_state
|
|
102
|
+
_state[index] = {
|
|
90
103
|
hidden,
|
|
91
104
|
position: position - 1, // position shift
|
|
92
105
|
answerUI,
|
|
93
106
|
questionText,
|
|
94
107
|
endReview: newSlideContent.endReview
|
|
95
|
-
}
|
|
108
|
+
};
|
|
96
109
|
}
|
|
97
|
-
}
|
|
110
|
+
}, state.slideNumbers);
|
|
98
111
|
|
|
99
112
|
return _state;
|
|
100
113
|
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import isNil from 'lodash/fp/isNil';
|
|
2
2
|
import get from 'lodash/fp/get';
|
|
3
|
+
import has from 'lodash/fp/has';
|
|
4
|
+
import map from 'lodash/fp/map';
|
|
3
5
|
import {
|
|
4
6
|
StepItemsAction,
|
|
5
7
|
UPDATE_STEP_ITEMS_ON_NEXT,
|
|
6
8
|
UPDATE_STEP_ITEMS_ON_VALIDATION
|
|
7
9
|
} from '../actions/step-items';
|
|
8
|
-
import {HIGHEST_INDEX, TOTAL_SLIDES_STACK} from '../common';
|
|
10
|
+
import {HIGHEST_INDEX, slideNumbers, TOTAL_SLIDES_STACK} from '../common';
|
|
9
11
|
import {SlideNumber} from '../types/slides';
|
|
10
12
|
import {FinishedSlides} from '../types/finished-slides';
|
|
11
13
|
import {StepItem, StepItems} from '../types/step-items';
|
|
@@ -15,11 +17,14 @@ import {StepItem, StepItems} from '../types/step-items';
|
|
|
15
17
|
export type State = StepItems;
|
|
16
18
|
|
|
17
19
|
const getInitialState = (): State => {
|
|
18
|
-
const state: StepItems =
|
|
20
|
+
const state: StepItems = {
|
|
21
|
+
slideNumbers
|
|
22
|
+
};
|
|
23
|
+
|
|
19
24
|
// eslint-disable-next-line fp/no-loops
|
|
20
25
|
for (let index = 0; index < TOTAL_SLIDES_STACK; index++) {
|
|
21
26
|
const current = index === 0;
|
|
22
|
-
state
|
|
27
|
+
state[index] = {current, value: `${index + 1}`, icon: null};
|
|
23
28
|
}
|
|
24
29
|
return state;
|
|
25
30
|
};
|
|
@@ -48,7 +53,7 @@ const calculateNextStepIndex = (
|
|
|
48
53
|
const indexToVisit = getNextIndex(isNil(lastVisitedIndex) ? currentStepNumber : lastVisitedIndex);
|
|
49
54
|
|
|
50
55
|
// if the index is already included in the correctly answered (finished) slides, then we proceed to check for the next one
|
|
51
|
-
return
|
|
56
|
+
return has(indexToVisit, finishedSlides)
|
|
52
57
|
? calculateNextStepIndex(currentStepNumber, finishedSlides, indexToVisit)
|
|
53
58
|
: indexToVisit;
|
|
54
59
|
};
|
|
@@ -63,18 +68,23 @@ const recalculateStepItemsState = (
|
|
|
63
68
|
stepItemToUpdateProps: StepItemToUpdateProps
|
|
64
69
|
): State => {
|
|
65
70
|
const nextIndex: number | null = get('nextIndex', stepItemToUpdateProps);
|
|
66
|
-
const _state: State =
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
const _state: State = {
|
|
72
|
+
slideNumbers
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// eslint-disable-next-line lodash-fp/no-unused-result
|
|
76
|
+
map(index => {
|
|
77
|
+
const previousValue = state[index];
|
|
69
78
|
if (stepNumber === index)
|
|
70
|
-
_state
|
|
79
|
+
_state[stepNumber] = {
|
|
71
80
|
...previousValue,
|
|
72
81
|
...stepItemToUpdateProps
|
|
73
|
-
}
|
|
82
|
+
};
|
|
74
83
|
/* only for UPDATE_STEP_ITEMS_ON_NEXT -> */ else if (nextIndex === index) {
|
|
75
|
-
_state
|
|
76
|
-
} else _state
|
|
77
|
-
}
|
|
84
|
+
_state[index] = {...previousValue, current: true};
|
|
85
|
+
} else _state[index] = previousValue;
|
|
86
|
+
}, state.slideNumbers);
|
|
87
|
+
|
|
78
88
|
return _state;
|
|
79
89
|
};
|
|
80
90
|
|
package/src/reducers/token.ts
CHANGED
|
@@ -1,29 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import set from 'lodash/fp/set';
|
|
2
2
|
import {StoreState} from '../types/store-state';
|
|
3
|
-
import {
|
|
3
|
+
import {DataState} from '../types/data';
|
|
4
4
|
|
|
5
5
|
// -----------------------------------------------------------------------------
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
export const initialState: State = null;
|
|
7
|
+
export const initialState: DataState['token'] = null;
|
|
9
8
|
|
|
10
9
|
// -----------------------------------------------------------------------------
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
const reducer = (state: State = initialState, action: StoreToken): State => {
|
|
14
|
-
switch (action.type) {
|
|
15
|
-
case STORE_TOKEN: {
|
|
16
|
-
return action.payload;
|
|
17
|
-
}
|
|
18
|
-
default:
|
|
19
|
-
return state;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
11
|
+
export const setToken = (token: string, state: DataState): DataState => set('token', token, state);
|
|
22
12
|
|
|
23
13
|
// -----------------------------------------------------------------------------
|
|
24
14
|
|
|
25
|
-
export const getToken = (appState: StoreState): StoreState['token'] => appState.token;
|
|
15
|
+
export const getToken = (appState: StoreState): StoreState['data']['token'] => appState.data.token;
|
|
26
16
|
|
|
27
17
|
// -----------------------------------------------------------------------------
|
|
28
|
-
|
|
29
|
-
export default reducer;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {AnswerUI} from '../slides';
|
|
2
|
+
|
|
3
|
+
export type DataState = {
|
|
4
|
+
isFetching?: boolean;
|
|
5
|
+
slideValidationResult?: {
|
|
6
|
+
slideNumber: number;
|
|
7
|
+
result: 'success' | 'failure';
|
|
8
|
+
// pass down the successExitNode if all slides are finished, not before
|
|
9
|
+
exitNode?: 'successExitNode' | 'failExitNode';
|
|
10
|
+
nextSlide: {
|
|
11
|
+
questionText?: string;
|
|
12
|
+
answerUI?: AnswerUI;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
token?: string;
|
|
16
|
+
};
|
package/src/types/dispatchers.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {validateSlide} from '../actions/
|
|
1
|
+
import {validateSlide} from '../actions/data/validate-slide';
|
|
2
2
|
import {updateFinishedSlides} from '../actions/finished-slides';
|
|
3
3
|
import {navigateBack, navigateTo} from '../actions/navigation';
|
|
4
4
|
import {updateReviewStatus} from '../actions/review-status';
|