Commit 4efaf25f authored by Oleksii Savran's avatar Oleksii Savran Committed by Matija Obreza
Browse files

Redux

parent b4ffa2fd
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
"error", "error",
{ {
"types": { "types": {
// "object": false "object": "false"
} }
} }
], ],
...@@ -120,7 +120,7 @@ ...@@ -120,7 +120,7 @@
"import/no-internal-modules": "off", "import/no-internal-modules": "off",
"import/order": "off", "import/order": "off",
"indent": [2, 2, {"SwitchCase": 1}], "indent": [2, 2, {"SwitchCase": 1}],
// "no-restricted-imports": ["error", {"patterns": ["../*"]}], "no-restricted-imports": ["error", {"patterns": ["../*"]}],
"max-classes-per-file": [ "max-classes-per-file": [
"error", "error",
10 10
......
import React from 'react'; import React from 'react';
import { connect } from 'react-redux';
import { AccessionService } from '@genesys/client/service'; import { AccessionService } from '@genesys/client/service';
import { Property } from 'ui/common/Property'; import { Property } from 'ui/common/Property';
...@@ -221,4 +222,8 @@ class AccessionDetailsPage extends React.Component<IAccessionDetailsPage & WithT ...@@ -221,4 +222,8 @@ class AccessionDetailsPage extends React.Component<IAccessionDetailsPage & WithT
}; };
} }
export default withTranslation()(AccessionDetailsPage); const mapStateToProps = (state) => ({
apiUrl: state.appConfig.config.apiUrl,
});
export default connect(mapStateToProps)(withTranslation()(AccessionDetailsPage));
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { parse } from 'query-string'; import { parse } from 'query-string';
import { connect } from 'react-redux';
import { AccessionService } from '@genesys/client/service'; import { AccessionService } from '@genesys/client/service';
import AccessionFilter from '@genesys/client/model/accession/AccessionFilter'; import AccessionFilter from '@genesys/client/model/accession/AccessionFilter';
...@@ -240,4 +241,8 @@ class AccessionListPage extends React.Component<IAccessionListPageProps & WithTr ...@@ -240,4 +241,8 @@ class AccessionListPage extends React.Component<IAccessionListPageProps & WithTr
}; };
} }
export default withTranslation()(AccessionListPage); const mapStateToProps = (state) => ({
filter: state.appConfig.config.filter,
});
export default connect(mapStateToProps)(withTranslation()(AccessionListPage));
...@@ -3,39 +3,25 @@ import { withTranslation, WithTranslation } from 'react-i18next'; ...@@ -3,39 +3,25 @@ import { withTranslation, WithTranslation } from 'react-i18next';
// model // model
import AccessionOverview from '@genesys/client/model/accession/AccessionOverview'; import AccessionOverview from '@genesys/client/model/accession/AccessionOverview';
import PropertiesCard from 'ui/common/PropertiesCard'; import PropertiesCard from 'ui/common/PropertiesCard';
import { VocabularyService } from '@genesys/client/service'; import { connect } from 'react-redux';
interface IAccessionOverviewPageState {
countryCodes: object;
}
interface IAccessionOverviewPageProps extends React.ClassAttributes<any> { interface IAccessionOverviewPageProps extends React.ClassAttributes<any> {
overview: AccessionOverview; overview: AccessionOverview;
countryCodes: Record<string, string>;
} }
class AccessionOverviewSection extends React.Component<IAccessionOverviewPageProps & WithTranslation, IAccessionOverviewPageState> { class AccessionOverviewSection extends React.Component<IAccessionOverviewPageProps & WithTranslation> {
public constructor(props) { public constructor(props) {
super(props); super(props);
this.state = {
countryCodes: null,
}
} }
private overviewKeys = ['institute.code', 'institute.country.code3', 'cropName', 'crop.shortName', 'sampStat', 'taxonomy.genus', 'taxonomy.genusSpecies', private overviewKeys = ['institute.code', 'institute.country.code3', 'cropName', 'crop.shortName', 'sampStat', 'taxonomy.genus', 'taxonomy.genusSpecies',
'taxonomy.grinTaxonomySpecies.name', 'taxonomy.currentTaxonomySpecies.name', 'taxonomy.grinTaxonomySpecies.name', 'taxonomy.currentTaxonomySpecies.name',
'countryOfOrigin.code3', 'donorCode', 'mlsStatus', 'available', 'duplSite', 'sgsv', 'storage', 'breederCode', 'aegis']; 'countryOfOrigin.code3', 'donorCode', 'mlsStatus', 'available', 'duplSite', 'sgsv', 'storage', 'breederCode', 'aegis'];
public async componentDidMount() {
const codes = await VocabularyService.decode3166Alpha3Terms(this.props.i18n.language);
this.setState({ countryCodes: codes })
}
public render() { public render() {
const { overview, t } = this.props; const { overview, t, countryCodes } = this.props;
const { countryCodes } = this.state;
if (!overview) { if (!overview) {
return null; return null;
...@@ -206,4 +192,8 @@ class AccessionOverviewSection extends React.Component<IAccessionOverviewPagePro ...@@ -206,4 +192,8 @@ class AccessionOverviewSection extends React.Component<IAccessionOverviewPagePro
} }
} }
export default withTranslation()(AccessionOverviewSection); const mapStateToProps = (state) => ({
countryCodes: state.decoding.codes,
});
export default connect(mapStateToProps)(withTranslation()(AccessionOverviewSection));
import * as React from 'react'; import * as React from 'react';
import { WithTranslation, withTranslation } from 'react-i18next'; import { WithTranslation, withTranslation } from 'react-i18next';
import { connect } from 'react-redux';
// Models // Models
import { AccessionService } from '@genesys/client/service'; import { AccessionService } from '@genesys/client/service';
...@@ -63,4 +64,8 @@ class BrowsePage extends React.Component<IOverviewPageProps, any> { ...@@ -63,4 +64,8 @@ class BrowsePage extends React.Component<IOverviewPageProps, any> {
} }
} }
export default withTranslation()(BrowsePage); const mapStateToProps = (state) => ({
filter: state.appConfig.config.filter,
});
export default connect(mapStateToProps)(withTranslation()(BrowsePage));
import { RECEIVE_APP_CONFIG } from 'core/constants/appConfig';
import { Config } from 'config/config';
export const setConfig = (config: Config) => ({
type: RECEIVE_APP_CONFIG,
payload: config,
});
import { VocabularyService } from '@genesys/client/service';
import { RECEIVE_COUNTRY_CODES_DECODED } from 'core/constants/decoding';
export const getCountryCodes = (lang: string) => (dispatch) => {
return VocabularyService
.decode3166Alpha3Terms(lang)
.then((codes) => {
dispatch({
type: RECEIVE_COUNTRY_CODES_DECODED,
payload: codes,
});
})
.catch((e) => {
console.log('Loading country codes decoding failed: ', e);
})
};
export const RECEIVE_APP_CONFIG = 'core/appConfig/RECEIVE';
export const RECEIVE_COUNTRY_CODES_DECODED = 'core/decoding/RECEIVE';
import update from 'immutability-helper';
import { RECEIVE_APP_CONFIG } from 'core/constants/appConfig';
import { Config } from 'config/config';
const INITIAL_STATE: {
config: Partial<Config>,
} = {
config: null,
};
export default (state = INITIAL_STATE, action: { type?: string, payload?: any } = { type: '', payload: {} }) => {
switch (action.type) {
case RECEIVE_APP_CONFIG: {
return update(state, {
config: { $set: action.payload },
});
}
default:
return state;
}
}
import update from 'immutability-helper';
import { RECEIVE_COUNTRY_CODES_DECODED } from 'core/constants/decoding';
const INITIAL_STATE: {
codes: Record<string, string>,
} = {
codes: null,
};
export default (state = INITIAL_STATE, action: { type?: string, payload?: any } = { type: '', payload: {} }) => {
switch (action.type) {
case RECEIVE_COUNTRY_CODES_DECODED: {
return update(state, {
codes: { $set: action.payload },
});
}
default:
return state;
}
}
import { combineReducers } from 'redux';
import appConfig from 'core/reducer/appConfig';
import decoding from './decoding';
const rootReducer = () => (combineReducers({
appConfig,
decoding,
}));
export default rootReducer;
import * as React from 'react'; import * as React from 'react';
import * as ReactDOM from 'react-dom'; import * as ReactDOM from 'react-dom';
import initI18n from './i18n'; import initI18n from './i18n';
import { applyMiddleware, compose, createStore } from 'redux';
import { log } from '@genesys/client/utilities/debug'; import { log } from '@genesys/client/utilities/debug';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
// import * as cookies from 'es-cookie'; // import * as cookies from 'es-cookie';
import { reconfigureServiceAxios, LoginService } from '@genesys/client/service'; import { reconfigureServiceAxios, LoginService } from '@genesys/client/service';
import App from 'ui/core/App'; import App from 'ui/core/App';
import ApiAccessError from 'ui/core/ApiAccessError'; import ApiAccessError from 'ui/core/ApiAccessError';
import { Config, DefaultConfig } from '../config/config'; import { Config, DefaultConfig } from 'config/config';
import rootReducer from 'core/reducer';
import { setConfig } from 'core/actions/appConfig';
import OverviewPage from 'accession/OverviewPage'; import OverviewPage from 'accession/OverviewPage';
// declare const window: Window & { devToolsExtension: any, __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: any, initialLanguage: any, initialI18nStore: any, localeMapping: any }; declare const window: Window & { devToolsExtension: any, __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: any };
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const initialState = {};
const store = composeEnhancers(applyMiddleware(thunk))(createStore)(rootReducer(), initialState);
// const AUTH_COOKIE = 'GENESYS_AUTH'; // const AUTH_COOKIE = 'GENESYS_AUTH';
console.log('Loading Genesys UI library'); console.log('Loading Genesys UI library');
...@@ -44,15 +52,18 @@ function checkAccessTokens(apiUrl: string, clientId: string, clientSecret: strin ...@@ -44,15 +52,18 @@ function checkAccessTokens(apiUrl: string, clientId: string, clientSecret: strin
}; };
export function showGenesysUI(holdingNode: HTMLElement, config: Config = DefaultConfig, language: string = 'en') { export function showGenesysUI(holdingNode: HTMLElement, config: Config = DefaultConfig, language: string = 'en') {
const { apiUrl, clientId, clientKey, filter } = config; const { apiUrl, clientId, clientKey } = config;
reconfigureServiceAxios({ apiUrl }); reconfigureServiceAxios({ apiUrl });
initI18n(language); initI18n(language);
store.dispatch(setConfig(config));
checkAccessTokens(apiUrl, clientId, clientKey).then( (result) => { checkAccessTokens(apiUrl, clientId, clientKey).then( (result) => {
ReactDOM.render( ReactDOM.render(
<App filter={ filter } apiUrl={ apiUrl } />, <Provider store={ store }>
<App/>
</Provider>,
holdingNode, holdingNode,
); );
}).catch((err) => { }).catch((err) => {
......
import React from 'react'; import React from 'react';
import { connect } from 'react-redux';
import { HashRouter as Router, Route, Switch } from 'react-router-dom'; import { HashRouter as Router, Route, Switch } from 'react-router-dom';
import NotFound from 'ui/core/NotFound'; import NotFound from 'ui/core/NotFound';
import ApiInfoPage from 'serverinfo/ApiInfoPage'; import ApiInfoPage from 'serverinfo/ApiInfoPage';
import AccessionList from 'accession/AccessionListPage'; import AccessionList from 'accession/AccessionListPage';
import AccessionDetails from 'accession/AccessionDetailsPage'; import AccessionDetails from 'accession/AccessionDetailsPage';
import { createHashHistory } from 'history'; import { createHashHistory } from 'history';
import { bindActionCreators } from 'redux';
import { getCountryCodes } from 'core/actions/decoding';
import { withTranslation, WithTranslation } from 'react-i18next';
import CartPage from 'request/CartPage'; import CartPage from 'request/CartPage';
import OverviewPage from 'accession/OverviewPage'; import OverviewPage from 'accession/OverviewPage';
import RequestPage from 'request/RequestPage'; import RequestPage from 'request/RequestPage';
const hashHistory = createHashHistory({}); const hashHistory = createHashHistory({});
interface IAppProps extends React.ClassAttributes<any> { interface IAppProps extends React.ClassAttributes<any>, WithTranslation {
apiUrl: string; apiUrl: string;
filter: object; filter: object;
getCountryCodes: (lang: string) => Promise<Record<string, string>>;
} }
export default class App extends React.Component<IAppProps, any> { class App extends React.Component<IAppProps, any> {
public componentDidMount() {
const { getCountryCodes, i18n } = this.props;
getCountryCodes(i18n.language);
}
public render() { public render() {
const { apiUrl } = this.props; const { apiUrl } = this.props;
console.log('Using filter', this.props.filter); console.log('Using filter', this.props.filter);
...@@ -25,11 +36,11 @@ export default class App extends React.Component<IAppProps, any> { ...@@ -25,11 +36,11 @@ export default class App extends React.Component<IAppProps, any> {
<Router> <Router>
<div> <div>
<Switch> <Switch>
<Route path="/a/:uuid" exact render={ (props) => <AccessionDetails { ...props } apiUrl={ apiUrl } /> } /> <Route path="/a/:uuid" exact component={ AccessionDetails } />
<Route path="/" exact render={ (props) => <AccessionList { ...props } filter={ this.props.filter } /> }/> <Route path="/" exact component={ AccessionList }/>
<Route path="/api-info" exact component={ ApiInfoPage }/> <Route path="/api-info" exact component={ ApiInfoPage }/>
<Route path="/cart" exact component={ CartPage }/> <Route path="/cart" exact component={ CartPage }/>
<Route path="/overview" exact render={ (props) => <OverviewPage { ...props } filter={ this.props.filter } /> }/> <Route path="/overview" exact component={ OverviewPage }/>
<Route path="/request" exact component={ RequestPage }/> <Route path="/request" exact component={ RequestPage }/>
<Route component={ NotFound }/> <Route component={ NotFound }/>
</Switch> </Switch>
...@@ -45,4 +56,15 @@ export default class App extends React.Component<IAppProps, any> { ...@@ -45,4 +56,15 @@ export default class App extends React.Component<IAppProps, any> {
}; };
} }
const mapStateToProps = (state) => ({
apiUrl: state.appConfig.config.apiUrl,
filter: state.appConfig.config.filter,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
getCountryCodes,
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(withTranslation()(App));
export { hashHistory as history }; export { hashHistory as history };
...@@ -72,9 +72,9 @@ ...@@ -72,9 +72,9 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*": "@types/node@*":
version "14.14.8" version "14.14.9"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.8.tgz#2127bd81949a95c8b7d3240f3254352d72563aec" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.9.tgz#04afc9a25c6ff93da14deabd65dc44485b53c8d6"
integrity sha512-z/5Yd59dCKI5kbxauAJgw6dLPzW+TNOItNE00PkpzNwUIEwdj/Lsqwq94H5DdYBX7C13aRA0CY32BK76+neEUA== integrity sha512-JsoLXFppG62tWTklIoO4knA+oDTYsmqWxHRvd4lpmfQRNhX6osheUOWETP2jMoV/2bEHuMra8Pp3Dmo/stBFcw==
"@types/prop-types@*": "@types/prop-types@*":
version "15.7.3" version "15.7.3"
...@@ -104,9 +104,9 @@ ...@@ -104,9 +104,9 @@
"@types/react" "*" "@types/react" "*"
"@types/react@*", "@types/react@^16.0.0": "@types/react@*", "@types/react@^16.0.0":
version "16.9.56" version "16.14.0"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.56.tgz#ea25847b53c5bec064933095fc366b1462e2adf0" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.0.tgz#bc022cfe1609899b0f2196376b267724e7300f0e"
integrity sha512-gIkl4J44G/qxbuC6r2Xh+D3CGZpJ+NdWTItAPmZbR5mUS+JQ8Zvzpl0ea5qT/ZT3ZNTUcDKUVqV3xBE8wv/DyQ== integrity sha512-jJjHo1uOe+NENRIBvF46tJimUvPnmbQ41Ax0pEm7pRvhPg+wuj8VMOHHiMvaGmZRzRrCtm7KnL5OOE/6kHPK8w==
dependencies: dependencies:
"@types/prop-types" "*" "@types/prop-types" "*"
csstype "^3.0.2" csstype "^3.0.2"
...@@ -597,9 +597,9 @@ awesome-typescript-loader@^5.0.0: ...@@ -597,9 +597,9 @@ awesome-typescript-loader@^5.0.0:
webpack-log "^1.2.0" webpack-log "^1.2.0"
axe-core@^4.0.2: axe-core@^4.0.2:
version "4.1.0" version "4.1.1"
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.1.0.tgz#93d395e6262ecdde5cb52a5d06533d0a0c7bb4cd" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.1.1.tgz#70a7855888e287f7add66002211a423937063eaf"
integrity sha512-9atDIOTDLsWL+1GbBec6omflaT5Cxh88J0GtJtGfCVIXpI02rXHkju59W5mMqWa7eiC5OR168v3TK3kUKBW98g== integrity sha512-5Kgy8Cz6LPC9DJcNb3yjAXTu3XihQgEdnIg50c//zOC/MyLP0Clg+Y8Sh9ZjjnvBrDZU4DgXS9C3T9r4/scGZQ==
axobject-query@^2.2.0: axobject-query@^2.2.0:
version "2.2.0" version "2.2.0"
...@@ -2064,9 +2064,9 @@ ejs@^2.6.1: ...@@ -2064,9 +2064,9 @@ ejs@^2.6.1:
integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
electron-to-chromium@^1.3.591: electron-to-chromium@^1.3.591:
version "1.3.601" version "1.3.603"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.601.tgz#881824eaef0b2f97c89e1abb5835fdd224997d34" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.603.tgz#1b71bec27fb940eccd79245f6824c63d5f7e8abf"
integrity sha512-ctRyXD9y0mZu8pgeNwBUhLP3Guyr5YuqkfLKYmpTwYx7o9JtCEJme9JVX4xBXPr5ZNvr/iBXUvHLFEVJQThATg== integrity sha512-J8OHxOeJkoSLgBXfV9BHgKccgfLMHh+CoeRo6wJsi6m0k3otaxS/5vrHpMNSEYY4MISwewqanPOuhAtuE8riQQ==
elliptic@^6.5.3: elliptic@^6.5.3:
version "6.5.3" version "6.5.3"
...@@ -3093,7 +3093,7 @@ hmac-drbg@^1.0.0: ...@@ -3093,7 +3093,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0" minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1" minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0: hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
version "3.3.2" version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
...@@ -3292,6 +3292,11 @@ ignore@^4.0.6: ...@@ -3292,6 +3292,11 @@ ignore@^4.0.6:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
immutability-helper@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/immutability-helper/-/immutability-helper-3.1.1.tgz#2b86b2286ed3b1241c9e23b7b21e0444f52f77b7"
integrity sha512-Q0QaXjPjwIju/28TsugCHNEASwoCcJSyJV3uO1sOIQGI0jKgm9f41Lvz0DZj3n46cNCyAZTsEYoY4C2bVRUzyQ==
import-fresh@^2.0.0: import-fresh@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
...@@ -5271,11 +5276,22 @@ react-i18next@^11.0.0: ...@@ -5271,11 +5276,22 @@ react-i18next@^11.0.0:
"@babel/runtime" "^7.3.1" "@babel/runtime" "^7.3.1"
html-parse-stringify2 "2.0.1" html-parse-stringify2 "2.0.1"
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1" version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-redux@^7.0.0:
version "7.2.2"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.2.tgz#03862e803a30b6b9ef8582dadcc810947f74b736"
integrity sha512-8+CQ1EvIVFkYL/vu6Olo7JFLWop1qRUeb46sGtIMDCSpgwPQq8fPLpirIB0iTqFe9XYEFPHssdX8/UwN6pAkEA==
dependencies:
"@babel/runtime" "^7.12.1"
hoist-non-react-statics "^3.3.2"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^16.13.1"
react-router-dom@^5.0.0: react-router-dom@^5.0.0:
version "5.2.0" version "5.2.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662"
...@@ -5369,6 +5385,24 @@ readdirp@~3.5.0: ...@@ -5369,6 +5385,24 @@ readdirp@~3.5.0:
dependencies: dependencies:
picomatch "^2.2.1" picomatch "^2.2.1"
redux-devtools-extension@^2.13.8:
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-thunk@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==
redux@^4.0.0:
version "4.0.5"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"