From ff0d237cf283d9c29f426511c02651d520ede2b6 Mon Sep 17 00:00:00 2001 From: Justin Walgran Date: Tue, 28 May 2019 15:03:54 -0700 Subject: [PATCH] Fetch client country code and write to app state We need to detect if someone is browsing the app from China so that we can change the way in which we load our map components. To facilitate this we make a request to the free userinfo.io service when the `App` component loads and save the returned country to the app state. --- CHANGELOG.md | 1 + src/app/src/App.jsx | 3 +++ src/app/src/actions/clientInfo.js | 27 +++++++++++++++++++++++ src/app/src/reducers/ClientInfoReducer.js | 21 ++++++++++++++++++ src/app/src/reducers/index.js | 2 ++ src/app/src/util/util.js | 2 ++ 6 files changed, 56 insertions(+) create mode 100644 src/app/src/actions/clientInfo.js create mode 100644 src/app/src/reducers/ClientInfoReducer.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fe4aad29..46d79ed53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Add django-waffle and configure Django & React apps to enable feature flags [#531](https://github.com/open-apparel-registry/open-apparel-registry/pull/531) - Support uploading Excel files [#532](https://github.com/open-apparel-registry/open-apparel-registry/pull/532) +- Fetch client country code based on IP [#541](https://github.com/open-apparel-registry/open-apparel-registry/pull/541) ### Changed - Show active facility list names and descriptions on profile page [#534](https://github.com/open-apparel-registry/open-apparel-registry/pull/534) diff --git a/src/app/src/App.jsx b/src/app/src/App.jsx index 2046f81f3..b3cda396e 100644 --- a/src/app/src/App.jsx +++ b/src/app/src/App.jsx @@ -27,6 +27,7 @@ import './App.css'; import { sessionLogin } from './actions/auth'; import { fetchFeatureFlags } from './actions/featureFlags'; +import { fetchClientInfo } from './actions/clientInfo'; import { mainRoute, @@ -58,6 +59,7 @@ const appStyles = Object.freeze({ class App extends Component { componentDidMount() { this.props.getFeatureFlags(); + this.props.getClientInfo(); return this.props.logIn(); } @@ -137,6 +139,7 @@ App.propTypes = { function mapDispatchToProps(dispatch) { return { getFeatureFlags: () => dispatch(fetchFeatureFlags()), + getClientInfo: () => dispatch(fetchClientInfo()), logIn: () => dispatch(sessionLogin()), }; } diff --git a/src/app/src/actions/clientInfo.js b/src/app/src/actions/clientInfo.js new file mode 100644 index 000000000..c025b20f2 --- /dev/null +++ b/src/app/src/actions/clientInfo.js @@ -0,0 +1,27 @@ +import { createAction } from 'redux-act'; + +import csrfRequest from '../util/csrfRequest'; + +import { + makeGetClientInfoURL, + logErrorAndDispatchFailure, +} from '../util/util'; + +export const startFetchClientInfo = createAction('START_FETCH_CLIENT_INFO'); +export const failFetchClientInfo = createAction('FAIL_FETCH_CLIENT_INFO'); +export const completeFetchClientInfo = createAction('COMPLETE_FETCH_CLIENT_INFO'); + +export function fetchClientInfo() { + return (dispatch) => { + dispatch(startFetchClientInfo()); + + return csrfRequest + .get(makeGetClientInfoURL()) + .then(({ data }) => dispatch(completeFetchClientInfo(data))) + .catch(err => dispatch(logErrorAndDispatchFailure( + err, + 'An error prevented fetching client info', + failFetchClientInfo, + ))); + }; +} diff --git a/src/app/src/reducers/ClientInfoReducer.js b/src/app/src/reducers/ClientInfoReducer.js new file mode 100644 index 000000000..3270147ad --- /dev/null +++ b/src/app/src/reducers/ClientInfoReducer.js @@ -0,0 +1,21 @@ +import { createReducer } from 'redux-act'; +import update from 'immutability-helper'; + +import { + startFetchClientInfo, + failFetchClientInfo, + completeFetchClientInfo, +} from '../actions/clientInfo'; + +const initialState = Object.freeze({ fetched: false, countryCode: null }); + +export default createReducer({ + [startFetchClientInfo]: () => initialState, + [failFetchClientInfo]: state => update(state, { + fetched: { $set: true }, + }), + [completeFetchClientInfo]: (state, payload) => update(state, { + fetched: { $set: true }, + countryCode: { $set: payload.country.code }, + }), +}, initialState); diff --git a/src/app/src/reducers/index.js b/src/app/src/reducers/index.js index 11edc1d6e..2f3e90943 100644 --- a/src/app/src/reducers/index.js +++ b/src/app/src/reducers/index.js @@ -17,6 +17,7 @@ import UIReducer from './UIReducer'; import FacilitiesReducer from './FacilitiesReducer'; import FacilityCountReducer from './FacilityCountReducer'; import FeatureFlagsReducer from './FeatureFlagsReducer'; +import ClientInfoReducer from './ClientInfoReducer'; export default combineReducers({ auth: AuthReducer, @@ -30,4 +31,5 @@ export default combineReducers({ facilities: FacilitiesReducer, facilityCount: FacilityCountReducer, featureFlags: FeatureFlagsReducer, + clientInfo: ClientInfoReducer, }); diff --git a/src/app/src/util/util.js b/src/app/src/util/util.js index b26978319..06798e730 100644 --- a/src/app/src/util/util.js +++ b/src/app/src/util/util.js @@ -93,6 +93,8 @@ export const makeGetFacilitiesCountURL = () => '/api/facilities/count/'; export const makeGetAPIFeatureFlagsURL = () => '/api-feature-flags/'; +export const makeGetClientInfoURL = () => 'https://api.userinfo.io/userinfos'; + export const getValueFromObject = ({ value }) => value; export const createQueryStringFromSearchFilters = ({