Skip to content

Commit

Permalink
Merge pull request Vizzuality#36 from Vizzuality/feature/url-to-state
Browse files Browse the repository at this point in the history
feat(NA): Url to state feature.
  • Loading branch information
davidsingal authored Aug 8, 2019
2 parents 2416846 + 34f02ce commit 27eb748
Show file tree
Hide file tree
Showing 16 changed files with 324 additions and 291 deletions.
7 changes: 4 additions & 3 deletions src/config/router.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { connectRoutes } from 'redux-first-router';

import { decodeUrlForState, encodeStateForUrl } from 'utils/stateToUrl';
import queryState from 'utils/query-state';
import { PAGES } from 'modules/pages/constants';

const routes = PAGES.reduce((acc, page) => ({
Expand All @@ -16,9 +16,10 @@ const options = {
location: 'router',
notFoundPath: `${process.env.REACT_APP_BASE_URL}404`,
querySerializer: {
parse: decodeUrlForState,
stringify: encodeStateForUrl
parse: queryState.decode,
stringify: queryState.encode
},
onAfterChange: queryState.inspector,
initialDispatch: false
};

Expand Down
26 changes: 26 additions & 0 deletions src/config/sagas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { all, fork } from 'redux-saga/effects';

import queryState from 'utils/query-state';

import pagesSagas from 'modules/pages/sagas';
import mapSagas from 'modules/map/sagas';
import mapStylesSagas from 'modules/map-styles/sagas';
import layersSagas from 'modules/layers/sagas';
import widgetsSagas from 'modules/widgets/sagas';
import locationsSagas from 'modules/locations/sagas';
import dashboardsSagas from 'modules/dashboards/sagas';
import languagesSagas from 'modules/languages/sagas';

export default function* root() {
yield all([
fork(queryState.sagas.bind(queryState)),
fork(pagesSagas),
fork(mapSagas),
fork(mapStylesSagas),
fork(layersSagas),
fork(widgetsSagas),
fork(locationsSagas),
fork(dashboardsSagas),
fork(languagesSagas),
]);
};
136 changes: 0 additions & 136 deletions src/config/serviceWorker.js

This file was deleted.

37 changes: 3 additions & 34 deletions src/config/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import { createStore, combineReducers, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly';
import createSagaMiddleware from 'redux-saga';
import { handleModule } from 'vizzuality-redux-tools';
import { all, fork } from 'redux-saga/effects';

// import { PAGES } from 'modules/pages/constants';

import * as pages from 'modules/pages';
import * as map from 'modules/map';
Expand All @@ -14,14 +11,9 @@ import * as widgets from 'modules/widgets';
import * as locations from 'modules/locations';
import * as dashboards from 'modules/dashboards';
import * as languages from 'modules/languages';
// Not actually a module, more like middleware
// import { queryState } from 'modules/query-state';

import router from './router';

// queryState.config({
// routerActions: PAGES.map(p => p.name)
// });
import sagas from './sagas';

const modules = [
{ namespace: 'page', components: pages },
Expand All @@ -41,10 +33,6 @@ const {
enhancer: routerEnhancer
} = router;

// const {
// middleware: queryStateMiddleware
// } = queryState;

const sagaMiddleware = createSagaMiddleware();

const reducers = combineReducers({
Expand All @@ -54,30 +42,11 @@ const reducers = combineReducers({
{}
)
});

const middleware = applyMiddleware(
routerMiddleware,
sagaMiddleware,
// queryStateMiddleware
);

const middleware = applyMiddleware(routerMiddleware, sagaMiddleware);
const enhancers = composeWithDevTools(routerEnhancer, middleware);

const store = createStore(reducers, enhancers);

// todo: add a register for this
sagaMiddleware.run(function* root() {
yield all([
fork(pages.sagas),
fork(mapStyles.sagas),
fork(layers.sagas),
fork(widgets.sagas),
fork(locations.sagas),
fork(dashboards.sagas),
fork(map.sagas),
fork(languages.sagas),
]);
});
sagaMiddleware.run(sagas);
initialDispatch();

export default store;
8 changes: 1 addition & 7 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';

import * as serviceWorker from 'config/serviceWorker';
import store from 'config/store';
import Pages from 'components/pages';

Expand All @@ -14,9 +13,4 @@ const App = () => (
</Provider>
);

ReactDOM.render(<App />, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
ReactDOM.render(<App />, document.getElementById('root'));
30 changes: 29 additions & 1 deletion src/modules/map/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
import * as actions from './actions';
import * as reducers from './reducers';
import initialState from './initial-state';
import sagas from './sagas';
import sagas, { restoreMapState } from './sagas';

import queryState from 'utils/query-state';

/**
* queryState.add register the namespace for url to state actions.
* The name property will become the query param.
* It is suppossed to be semantic:
*
* For namespace 'map'
* encode selector
* after any of these actions are triggered.
*
* For namespace 'map'
* decode trigger
* after all of these actions have happened.
*/
queryState.add({
name: 'map',
encode: {
after: [
actions.setBasemap,
],
selector: state => ({ basemap: state.map.basemap })
},
decode: {
trigger: restoreMapState
}
});

export { actions, initialState, reducers, sagas };
18 changes: 17 additions & 1 deletion src/modules/map/sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import WebMercatorViewport from 'viewport-mercator-project';
import bbox from '@turf/bbox';
import { currentLocation } from 'modules/locations/selectors';
import { easeCubic } from 'd3-ease';
import { resetViewport, setViewport } from './actions';
import { resetViewport, setViewport, setBasemap } from './actions';

function* flyToCurrentLocation() {
const state = yield select();
Expand Down Expand Up @@ -34,6 +34,22 @@ function* flyToCurrentLocation() {
}
}

// Part of query state, not normal flow.
// View ./index.js queryState.add for more info.
export function * restoreMapState() {
/**
* A regular selector, it could be on a selectors file with reselect
* or better yet, be created automatically by the package based on registered namespace info.
*/
const basemapSelector = state => (state.router.query
&& state.router.query.map
&& state.router.query.map.basemap) || null;
const basemap = yield select(basemapSelector);
if (basemap) {
yield(put(setBasemap(basemap)));
}
}

export default function* pages() {
yield takeLatest('LOCATIONS/FETCH_SUCCEDED', flyToCurrentLocation);
yield takeLatest('LOCATIONS/SET_CURRENT', flyToCurrentLocation);
Expand Down
Loading

0 comments on commit 27eb748

Please # to comment.