diff --git a/README.md b/README.md index 17d8ae9..8849b7e 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ * [react](https://github.com/facebook/react) * [react-router](https://github.com/ReactTraining/react-router) * [react-router-dom](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-dom) +* [redux](https://github.com/reduxjs/redux) +* [react-redux](https://github.com/reduxjs/react-redux) ## DevDependencies * [prettier](https://github.com/prettier/prettier) diff --git a/index.html b/index.html index aefb0b8..a2de2f3 100644 --- a/index.html +++ b/index.html @@ -5,14 +5,6 @@ - - Starter diff --git a/package.json b/package.json index 904664e..24cf2bc 100644 --- a/package.json +++ b/package.json @@ -25,10 +25,15 @@ ] }, "dependencies": { + "deox": "^1.4.0", "react": "^16.4.2", "react-dom": "^16.4.2", + "react-redux": "^7.0.2", "react-router": "^4.3.1", - "react-router-dom": "^4.3.1" + "react-router-dom": "^4.3.1", + "redux": "^4.0.1", + "redux-react-hook": "^3.3.1", + "redux-saga": "^1.0.2" }, "devDependencies": { "@types/enzyme": "^3.9.0", @@ -36,6 +41,7 @@ "@types/jest": "^24.0.9", "@types/react": "^16.4.11", "@types/react-dom": "^16.0.7", + "@types/react-redux": "^7.0.8", "@types/react-router": "^4.4.4", "@types/react-router-dom": "^4.3.1", "enzyme": "^3.9.0", diff --git a/src/configureStore.ts b/src/configureStore.ts new file mode 100644 index 0000000..f6fae52 --- /dev/null +++ b/src/configureStore.ts @@ -0,0 +1,20 @@ +import { createStore, Dispatch, applyMiddleware } from 'redux'; + +import { rootReducer } from './rootReducer'; +import { UserState } from './modules/user/reducer/user.reducer'; +import { default as createSagaMiddleware } from '@redux-saga/core'; +import rootSaga from './rootSaga'; + +export interface ConnectedReduxProps { + dispatch: Dispatch; +} + +export interface ApplicationState { + userState: UserState; +} + +const sagaMiddleware = createSagaMiddleware(); + +export const store = createStore(rootReducer, applyMiddleware(sagaMiddleware)); + +sagaMiddleware.run(rootSaga); diff --git a/src/index.tsx b/src/index.tsx index d7e4b45..1391a06 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,15 +1,19 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; - +import { Provider } from 'react-redux'; +import { StoreContext } from 'redux-react-hook'; declare let module: any; import { App } from './App'; +import { store } from './configureStore'; const RenderApp = () => ( - - - + + + + + ); ReactDOM.render(, document.getElementById('root') as HTMLElement); diff --git a/src/modules/user/reducer/user.reducer.ts b/src/modules/user/reducer/user.reducer.ts new file mode 100644 index 0000000..147e615 --- /dev/null +++ b/src/modules/user/reducer/user.reducer.ts @@ -0,0 +1,19 @@ +import { User, createUser, createUserSucceeded } from '../user.actions'; +import { createReducer } from 'deox'; + +export interface UserState { + user: User; +} + +const userDefaultState: UserState = { + user: { + firstName: 'john', + lastName: 'doe', + }, +}; + +export const userReducer = createReducer(userDefaultState, handle => [ + handle(createUserSucceeded, (state, action) => { + return { ...state, user: action.payload }; + }), +]); diff --git a/src/modules/user/sagas/user.sagas.test.ts b/src/modules/user/sagas/user.sagas.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/user/sagas/user.sagas.ts b/src/modules/user/sagas/user.sagas.ts new file mode 100644 index 0000000..d2a0028 --- /dev/null +++ b/src/modules/user/sagas/user.sagas.ts @@ -0,0 +1,27 @@ +import { takeLatest, call, put } from 'redux-saga/effects'; +import { + ActionTypeKeys, + createUserFailed, + createUserSucceeded, + User, + CreateUserRequestedAction, +} from '../user.actions'; +import { userEditRequest } from '../user.api'; + +export function* userEditSaga(action: CreateUserRequestedAction) { + try { + // define type explicitly because of lack of return types of generators: + // https://github.com/redux-saga/redux-saga/issues/1286#issuecomment-482866473 + const fetchedUser: User = yield call(userEditRequest, { + firstName: 'nico', + lastName: 'peham', + }); + yield put(createUserSucceeded(fetchedUser)); + } catch (error) { + yield put(createUserFailed()); + } +} + +export const userSagas = [ + takeLatest(ActionTypeKeys.CreateUserRequested, userEditSaga), +]; diff --git a/src/modules/user/scenes/UserEdit.scene.tsx b/src/modules/user/scenes/userEdit/UserEdit.scene.tsx similarity index 66% rename from src/modules/user/scenes/UserEdit.scene.tsx rename to src/modules/user/scenes/userEdit/UserEdit.scene.tsx index c1eb011..09f81a0 100644 --- a/src/modules/user/scenes/UserEdit.scene.tsx +++ b/src/modules/user/scenes/userEdit/UserEdit.scene.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { RouteComponentProps } from 'react-router'; -import { SceneParams } from '../../../shared/types/routing'; +import { SceneParams } from '../../../../shared/types/routing'; +import { UserEditFormContainer } from './userEditForm/UserEditForm.container'; export interface UserEditSceneParams extends SceneParams { userId: string; @@ -16,6 +17,9 @@ export const UserEditSene: React.SFC< userId --> {userId}
projId --> {projId} +
+
+ ); }; diff --git a/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.container.tsx b/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.container.tsx new file mode 100644 index 0000000..63c4fe5 --- /dev/null +++ b/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.container.tsx @@ -0,0 +1,52 @@ +// tslint:disable-next-line:import-name +import React, { useCallback } from 'react'; + +import { ApplicationState } from '../../../../../configureStore'; +import { UserEditForm } from './UserEditForm'; +import { + User, + createUser, + createUserRequested, + createUserSucceeded, +} from '../../../user.actions'; +// tslint:disable-next-line:import-name +// import React, { useCallback } from 'react'; +import { useMappedState, useDispatch } from 'redux-react-hook'; + +// const { useCallback } = React; + +type UserEditFormContainerStateMapProps = { + user: User; +}; + +type RegisterFormContainerProps = { + passedProp: string; +}; + +export const UserEditFormContainer: React.FunctionComponent< + RegisterFormContainerProps +> = ({ passedProp }) => { + const mapState = useCallback( + (state: ApplicationState): UserEditFormContainerStateMapProps => ({ + user: state.userState.user, + }), + [], + ); + const dispatch = useDispatch(); + + const { user } = useMappedState(mapState); + + const handleRegisterFormSubmit = (values: User) => { + dispatch(createUserRequested(user)); + }; + + return ( + <> +
passed: {passedProp}
+
user in state: {JSON.stringify(user)}
+
+
+ {' '} + + ); +}; diff --git a/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.tsx b/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.tsx new file mode 100644 index 0000000..5257f86 --- /dev/null +++ b/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; +import { User } from '../../../user.actions'; + +type UserEditFormProps = { + onSubmit: (userEdited: User) => void; +}; + +export const UserEditForm: React.SFC = ({ onSubmit }) => { + const userEdited: User = { + firstName: 'susan', + lastName: 'jackson', + }; + + const onUserEdited = () => onSubmit(userEdited); + return ( + <> + + + ); +}; diff --git a/src/modules/user/user.actions.ts b/src/modules/user/user.actions.ts new file mode 100644 index 0000000..d19f539 --- /dev/null +++ b/src/modules/user/user.actions.ts @@ -0,0 +1,37 @@ +import { createAction, Action } from 'deox'; + +export type User = { + firstName: string; + lastName: string; +}; + +// https://redux.js.org/advanced/async-actions choose! +export enum ActionTypeKeys { + CreateUserRequested = 'USER::CREATE_REQUESTED', + CreateUserFailed = 'USER::CREATE_FAILED', + CreateUserSucceeded = 'USER::CREATE_SUCCEEDED', + CreateUser = 'USER::CREATE', +} + +export const createUser = createAction( + ActionTypeKeys.CreateUser, + resolve => (user: User) => resolve(user), +); + +export type CreateUserRequestedAction = Action< + ActionTypeKeys.CreateUserRequested +> & { + payload: User; +}; + +export const createUserRequested = createAction( + ActionTypeKeys.CreateUserRequested, + resolve => (user: User) => resolve(user), +); + +export const createUserSucceeded = createAction( + ActionTypeKeys.CreateUserSucceeded, + resolve => (user: User) => resolve(user), +); + +export const createUserFailed = createAction(ActionTypeKeys.CreateUserFailed); diff --git a/src/modules/user/user.api.ts b/src/modules/user/user.api.ts new file mode 100644 index 0000000..fa647c7 --- /dev/null +++ b/src/modules/user/user.api.ts @@ -0,0 +1,6 @@ +import { User } from './user.actions'; + +export const userEditRequest = async (user: User): Promise => { + const fetchedUser: User = { firstName: 'ie', lastName: 'sei' }; + return new Promise(resolve => setTimeout(() => resolve(fetchedUser), 1000)); +}; diff --git a/src/modules/user/user.routing.ts b/src/modules/user/user.routing.ts index da89134..36f3fbc 100644 --- a/src/modules/user/user.routing.ts +++ b/src/modules/user/user.routing.ts @@ -1,6 +1,9 @@ -import { UserEditSene, UserEditSceneParams } from './scenes/UserEdit.scene'; import { UserListScene } from './scenes/UserList.scene'; import { AppRoute, IScene } from '../../shared/types/routing'; +import { + UserEditSene, + UserEditSceneParams, +} from './scenes/userEdit/UserEdit.scene'; export enum UserRoute { List = '/user/list', diff --git a/src/rootReducer.ts b/src/rootReducer.ts new file mode 100644 index 0000000..96952b2 --- /dev/null +++ b/src/rootReducer.ts @@ -0,0 +1,4 @@ +import { combineReducers } from 'redux'; +import { userReducer } from './modules/user/reducer/user.reducer'; + +export const rootReducer = combineReducers({ userState: userReducer }); diff --git a/src/rootSaga.ts b/src/rootSaga.ts new file mode 100644 index 0000000..03cb4f4 --- /dev/null +++ b/src/rootSaga.ts @@ -0,0 +1,7 @@ +import { userSagas } from './modules/user/sagas/user.sagas'; +import { all } from 'redux-saga/effects'; + +// https://github.com/redux-saga/redux-saga/issues/160#issuecomment-308540204 +export default function* rootSaga() { + yield all([...userSagas]); +} diff --git a/src/setupEnzyme.ts b/src/setupEnzyme.ts index fbb8910..8c03ca5 100644 --- a/src/setupEnzyme.ts +++ b/src/setupEnzyme.ts @@ -1,3 +1,3 @@ import { configure } from 'enzyme'; -import * as EnzymeAdapter from 'enzyme-adapter-react-16'; +import EnzymeAdapter from 'enzyme-adapter-react-16'; configure({ adapter: new EnzymeAdapter() }); diff --git a/tsconfig.json b/tsconfig.json index a25079a..3e28f69 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,7 @@ "skipLibCheck": true, "target": "es5", "strictNullChecks": true, + "esModuleInterop": true }, "include": ["./src/**/**/*"], "exclude": ["node_modules"] diff --git a/tslint.json b/tslint.json index c296ecb..0bf6d87 100644 --- a/tslint.json +++ b/tslint.json @@ -1,6 +1,9 @@ { "extends": ["tslint-config-airbnb", "tslint-react", "tslint-config-prettier"], "rules": { - "variable-name": [true, "allow-pascal-case"] + "variable-name": [true, "allow-pascal-case"], + "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks + "react-hooks/exhaustive-deps": "warn", // Checks effect dependencies + "import-name": false } } diff --git a/yarn.lock b/yarn.lock index b88b0ab..a034245 100644 --- a/yarn.lock +++ b/yarn.lock @@ -105,6 +105,13 @@ dependencies: regenerator-runtime "^0.12.0" +"@babel/runtime@^7.0.0": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d" + integrity sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg== + dependencies: + regenerator-runtime "^0.13.2" + "@babel/runtime@^7.1.2": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" @@ -112,6 +119,13 @@ dependencies: regenerator-runtime "^0.12.0" +"@babel/runtime@^7.4.3": + version "7.4.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.3.tgz#79888e452034223ad9609187a0ad1fe0d2ad4bdc" + integrity sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA== + dependencies: + regenerator-runtime "^0.13.2" + "@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": version "7.2.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" @@ -309,6 +323,50 @@ "@types/istanbul-lib-coverage" "^1.1.0" "@types/yargs" "^12.0.9" +"@redux-saga/core@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@redux-saga/core/-/core-1.0.2.tgz#4336a5bb4253e5ca69681c25a863fbbc03ea6d88" + integrity sha512-AsJYcpuYfM1cmxJvfhXs9HAFSZVEG17TMsLPlXH7+Hq5a5ZP4GqcbtijEmS2AC7NR5lLJHy8csxpqz22PeW5dw== + dependencies: + "@babel/runtime" "^7.0.0" + "@redux-saga/deferred" "^1.0.1" + "@redux-saga/delay-p" "^1.0.1" + "@redux-saga/is" "^1.0.2" + "@redux-saga/symbols" "^1.0.1" + "@redux-saga/types" "^1.0.2" + redux ">=0.10 <5" + typescript-tuple "^2.1.0" + +"@redux-saga/deferred@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@redux-saga/deferred/-/deferred-1.0.1.tgz#c895445e486bded90acf0b873b4e978fbfe458c2" + integrity sha512-+gW5xQ93QXOOmRLAmX8x2Hx1HpbTG6CM6+HcdTSbJovh4uMWaGyeDECnqXSt8QqA/ja3s2nqYXLqXFKepIQ1hw== + +"@redux-saga/delay-p@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@redux-saga/delay-p/-/delay-p-1.0.1.tgz#d69fc6103c7509ae80faa144ea17bbc69e51e029" + integrity sha512-0SnNDyDLUyB4NThtptAwiprNOnbCNhoed/Rp5JwS7SB+a/AdWynVgg/E6BmjsggLFNr07KW0bzn05tsPRBuU7Q== + dependencies: + "@redux-saga/symbols" "^1.0.1" + +"@redux-saga/is@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@redux-saga/is/-/is-1.0.2.tgz#7f4be014c97061898d7efb11d6c9de31e943ed38" + integrity sha512-WnaUOwYvPK2waWjzebT4uhL8zY76XNkzzpJ2EQJe8bN1tByvAjvT7MuJZTSshOhdHL5PsRO0MsH224XIXBJidQ== + dependencies: + "@redux-saga/symbols" "^1.0.1" + "@redux-saga/types" "^1.0.2" + +"@redux-saga/symbols@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@redux-saga/symbols/-/symbols-1.0.1.tgz#46512ae1275f88df061c42168d0f600ddb170c1e" + integrity sha512-akKkzcVnb1RzJaZV2LQFbi51abvdICMuAKwwLoCjjxLbLAGIw9EJxk5ucNnWSSCEsoEQMeol5tkAcK+Xzuv1Bg== + +"@redux-saga/types@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.0.2.tgz#1d94f02800b094753f9271c206a26c2a06ca14ee" + integrity sha512-8/qcMh15507AnXJ3lBeuhsdFwnWQqnp68EpUuHlYPixJ5vjVmls7/Jq48cnUlrZI8Jd9U1jkhfCl0gaT5KMgVw== + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -376,6 +434,14 @@ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.2.tgz#0e670ea254d559241b6eeb3894f8754991e73220" integrity sha512-ui3WwXmjTaY73fOQ3/m3nnajU/Orhi6cEu5rzX+BrAAJxa3eITXZ5ch9suPqtM03OWhAHhPSyBGCN4UKoxO20Q== +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/istanbul-lib-coverage@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz#2cc2ca41051498382b43157c8227fea60363f94a" @@ -415,6 +481,15 @@ dependencies: "@types/react" "*" +"@types/react-redux@^7.0.8": + version "7.0.8" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.0.8.tgz#c928863058e334d41031c6bedd0f113bc514e234" + integrity sha512-vIBC15E84ehN6RzdGwRVa41whp9e4CkfPm+WfD0r6y6vqBf4tQPKZeKEBfLLM8k79uSwQC7rh3rH/MFaN1IESQ== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + redux "^4.0.0" + "@types/react-router-dom@^4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.1.tgz#71fe2918f8f60474a891520def40a63997dafe04" @@ -1633,6 +1708,11 @@ csstype@^2.2.0: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.3.tgz#b701e5968245bf9b08d54ac83d00b624e622a9fa" integrity sha512-rINUZXOkcBmoHWEyu7JdHu5JMzkGRoMX4ov9830WNgxf5UYxcBUO0QTKAqeJ5EZfSdlrcJYkC8WwfVW7JYi4yg== +curriable@^1.2.4: + version "1.2.5" + resolved "https://registry.yarnpkg.com/curriable/-/curriable-1.2.5.tgz#fb6ff7ad8740927ea09db15d395d9d26ca9d2726" + integrity sha512-hQwrkCn8DNiCw5CG8OS0td2wfpCDtxo1dmrVYxCDWUBHQPkpAvN9RqBVbmC64oSQaBqPQD2SOCXcTWH1zXe2mA== + cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" @@ -1768,6 +1848,15 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +deox@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/deox/-/deox-1.4.0.tgz#7511c082cbe80ffee4c5095aa7efe0138d6057c4" + integrity sha512-J9lQse+5LG2/q4hZsjn5Jun2yJP2Al0OfAECQ1KtMXSh5eJYSRn6bh9XBTiBxxi4qymAb/ovC3HPdK760z4OAQ== + dependencies: + redux-starter-kit "0.4.3" + rxjs "^6.3.3" + tslib "^1.9.3" + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -2280,6 +2369,11 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-equals@^1.2.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-1.6.2.tgz#f1762bde0d571b5e9d4e1c4ae0599792f6a6df5f" + integrity sha512-6FiKwHkrHIqdvo9I92yzCR/zuWE6iy5ldcOszStPbmo7Zzj3OoVeng++GE//JqO4i6JQ4vH/BVAfCmUCki+C3g== + fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -2752,7 +2846,7 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.1.0: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA== @@ -2882,6 +2976,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: dependencies: safer-buffer ">= 2.1.2 < 3" +identitate@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/identitate/-/identitate-1.0.1.tgz#4b8bed39454f1d7a476e60ff0e4f82a094841dfc" + integrity sha512-xnDJ0JYhiZjBDuJRKbHoVzj5yP9FhATxLyUYswQyPdnJrwzGVBqS6DOmvKJi1lk7P+4dkL+hhUhuOZIcOUtG5A== + dependencies: + pathington "^1.0.1" + ieee754@^1.1.4: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" @@ -2899,6 +3000,11 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" +immer@^1.10.5: + version "1.12.1" + resolved "https://registry.yarnpkg.com/immer/-/immer-1.12.1.tgz#40c6e5b292c00560836c2993bda3a24379d466f5" + integrity sha512-3fmKM6ovaqDt0CdC9daXpNi5x/YCYS3i4cwLdTVkhJdk5jrDXoPs7lCm3IqM3yhfSnz4tjjxbRG2CziQ7m8ztg== + import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" @@ -2958,7 +3064,7 @@ interpret@^1.1.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== -invariant@^2.2.4: +invariant@^2.1.0, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -3766,7 +3872,7 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= -json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= @@ -4891,6 +4997,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +pathington@^1.0.1, pathington@^1.1.5: + version "1.1.7" + resolved "https://registry.yarnpkg.com/pathington/-/pathington-1.1.7.tgz#caf2d2db899a31fea4e81e3657af6acde5171903" + integrity sha512-JxzhUzagDfNIOm4qqwQqP3rWeo7rNNOfIahy4n+3GTEdwXLqw5cJHUR0soSopQtNEv763lzxb6eA2xBllpR8zw== + pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -5204,6 +5315,23 @@ react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2" integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA== +react-is@^16.8.6: + version "16.8.6" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" + integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== + +react-redux@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.0.2.tgz#34b280a3482aaf60e7d4a504b1295165cbe6b86a" + integrity sha512-uKRuMgQt8dWbcz0U75oFK5tDo3boyAKrqvf/j94vpqRFFZfyDDy4kofUgloFIGyuKTq2Zz51zgK9RzOTFXk5ew== + dependencies: + "@babel/runtime" "^7.4.3" + hoist-non-react-statics "^3.3.0" + invariant "^2.2.4" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-is "^16.8.6" + react-router-dom@^4.3.1: version "4.4.0" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.4.0.tgz#fad67b46375f7081a76d1c92a83a92d28b5abc35" @@ -5318,6 +5446,56 @@ realpath-native@^1.1.0: dependencies: util.promisify "^1.0.0" +redux-devtools-extension@^2.13.7: + version "2.13.8" + resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz#37b982688626e5e4993ff87220c9bbb7cd2d96e1" + integrity sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg== + +redux-immutable-state-invariant@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/redux-immutable-state-invariant/-/redux-immutable-state-invariant-2.1.0.tgz#308fd3cc7415a0e7f11f51ec997b6379c7055ce1" + integrity sha512-3czbDKs35FwiBRsx/3KabUk5zSOoTXC+cgVofGkpBNv3jQcqIe5JrHcF5AmVt7B/4hyJ8MijBIpCJ8cife6yJg== + dependencies: + invariant "^2.1.0" + json-stringify-safe "^5.0.1" + +redux-react-hook@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/redux-react-hook/-/redux-react-hook-3.3.1.tgz#3fc91c0def8a49b873c92879843b3f76c8ae7cf4" + integrity sha512-a5RHGYT2ZV8Zo1ATP2ubxQGm0fPwn62loSieTeCL7PRgGfdTi8jR0S1K+1/1b4P6RSnEXvs5qC9IVlh2clPbxg== + +redux-saga@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-1.0.2.tgz#0599703f975438f1b2f9d2b9a965ec58f0fdfcd7" + integrity sha512-dHV256by3eF2AnBPx1l3HqazQFkErZ82HDXgh4jSRpT72OrX31wyg8DA1q8+0HvENRfJAyhT/4qT5yH/vVqFfw== + dependencies: + "@redux-saga/core" "^1.0.2" + +redux-starter-kit@0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/redux-starter-kit/-/redux-starter-kit-0.4.3.tgz#66a583cde1f1995ae59782d87cc462260ca85fa8" + integrity sha512-T3HXtwEGyFLCy63QlZEM95rDzTQ5BKbBhhTINNVFD1yWgHBKtgN3tXw4/sX9+Ve1Y8mAtXbAhep/E7I0YVvZPg== + dependencies: + immer "^1.10.5" + redux "^4.0.0" + redux-devtools-extension "^2.13.7" + redux-immutable-state-invariant "^2.1.0" + redux-thunk "^2.2.0" + selectorator "^4.0.1" + +redux-thunk@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" + integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== + +"redux@>=0.10 <5", redux@^4.0.0, redux@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.1.tgz#436cae6cc40fbe4727689d7c8fae44808f1bfef5" + integrity sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg== + dependencies: + loose-envify "^1.4.0" + symbol-observable "^1.2.0" + reflect-metadata@^0.1.12: version "0.1.13" resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" @@ -5328,6 +5506,11 @@ regenerator-runtime@^0.12.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== +regenerator-runtime@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447" + integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA== + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -5419,6 +5602,11 @@ require-main-filename@^1.0.1: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= +reselect@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" + integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== + resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -5575,6 +5763,16 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" +selectorator@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/selectorator/-/selectorator-4.0.3.tgz#d33b11027da7e6838de277cd6eb1134125aa788b" + integrity sha512-A8+paRhzTab4Qm/38RAVnCgEZFbpn5xIWLyTCDqvyU3Obhmo94RS6UK1H00bVH7+U609sOhqbFJha09POsWURA== + dependencies: + fast-equals "^1.2.1" + identitate "^1.0.0" + reselect "^4.0.0" + unchanged "^2.0.1" + semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -6025,7 +6223,7 @@ supports-color@^6.0.0, supports-color@^6.1.0: dependencies: has-flag "^3.0.0" -symbol-observable@^1.1.0: +symbol-observable@^1.1.0, symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== @@ -6230,7 +6428,7 @@ tslib@1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== -tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== @@ -6363,6 +6561,25 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript-compare@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/typescript-compare/-/typescript-compare-0.0.2.tgz#7ee40a400a406c2ea0a7e551efd3309021d5f425" + integrity sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA== + dependencies: + typescript-logic "^0.0.0" + +typescript-logic@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/typescript-logic/-/typescript-logic-0.0.0.tgz#66ebd82a2548f2b444a43667bec120b496890196" + integrity sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q== + +typescript-tuple@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/typescript-tuple/-/typescript-tuple-2.2.1.tgz#7d9813fb4b355f69ac55032e0363e8bb0f04dad2" + integrity sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q== + dependencies: + typescript-compare "^0.0.2" + typescript@^3.3.3333: version "3.3.3333" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.3333.tgz#171b2c5af66c59e9431199117a3bcadc66fdcfd6" @@ -6381,6 +6598,14 @@ uglify-js@3.4.x, uglify-js@^3.1.4: commander "~2.19.0" source-map "~0.6.1" +unchanged@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unchanged/-/unchanged-2.1.0.tgz#16308dde5bec15925032d91651f5c3843b957de6" + integrity sha512-CYVU0Mz35N821Pjxf+iG6JMPx/Yb6wStUq8uuhR52/+AU3vMiueOTrJ6u1vBKYSke7a75FAi2/jCdQkXcHaNGQ== + dependencies: + curriable "^1.2.4" + pathington "^1.1.5" + union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"