diff --git a/app/actions/actionTypes.js b/app/actions/actionTypes.js index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e100419e518f3617d26997f4d136a736fa5c4f2e 100644 --- a/app/actions/actionTypes.js +++ b/app/actions/actionTypes.js @@ -0,0 +1,4 @@ +export const ADD_URL = "ADD_URL" +export const DELETE_ROUTE = "DELETE_ROUTE" +export const CLEAR_ROUTE = "CLEAR_ROUTE" +export const UPDATE_URL= "UPDATE_URL" diff --git a/app/actions/index.js b/app/actions/index.js index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..51c5460424205213c15e42069d6f0ae2fe6bfd19 100644 --- a/app/actions/index.js +++ b/app/actions/index.js @@ -0,0 +1,30 @@ +import * as at from './actionTypes' + +// export const ADD_URL = "ADD_URL" +// export const DELETE_ROUTE = "DELETE_ROUTE" +// export const CLEAR_ROUTE = "CLEAR_ROUTE" +// export const UPDATE_URL= "UPDATE_URL" + +export const mkAddUrl = (url) => ({ + type: at.ADD_URL, + payload: url +}) + + +export const mkDeleteRoute = (i) => ({ + type: at.DELETE_ROUTE, + payload: i +}) + +export const mkClearRoute = (i) => ({ + type: at.CLEAR_ROUTE, + payload: i +}) + +export const mkUpdateRoute = (i, url) => ({ + type: at.CLEAR_ROUTE, + payload: { + index: i, + url: url + } +}) diff --git a/app/components/App.jsx b/app/components/App.jsx index bace1f305a016fa13d44e6084842cb06d17675e9..21d6274cc0845892fdc145d0effb6e19b37a1b1d 100644 --- a/app/components/App.jsx +++ b/app/components/App.jsx @@ -1,11 +1,11 @@ import React from 'react' -import OutputPanel from './OutputPanel' -import InputPanel from './InputPanel' +import OutputPanel from './../containers/OutputPanel' +import InputPanel from './../containers/InputPanel' const App = () => ( <div> - <InputPanel routes={[["a", "b", "c"], [], ["1", "2", "4"]]}/> - <OutputPanel url="https://example.com" stops={["x", "y", "z"]} /> + <InputPanel /> + <OutputPanel /> </div> ) diff --git a/app/components/InputPanel.jsx b/app/components/InputPanel.jsx index a49340fc4a5ffa37598ff8e903eaba483cf26327..2f3fda7c83e6f6f7f1a96ced7402716abc575c65 100644 --- a/app/components/InputPanel.jsx +++ b/app/components/InputPanel.jsx @@ -2,12 +2,12 @@ import React from 'react'; import PropTypes from 'prop-types' import RouteTile from './RouteTile' -const InputPanel = ({routes}) => ( +const InputPanel = ({routes, onAdd}) => ( <div> {routes.map((stops, i) => ( <RouteTile key={i} stops={stops} /> ))} - <RouteTile stops={[]} noStopsText="Add a link to a partial route" /> + <RouteTile onAdd={onAdd} stops={[]} /> </div> ) diff --git a/app/components/OutputPanel.jsx b/app/components/OutputPanel.jsx index 977b101694d12586fefd3bcbf3d535a2b1b47f7c..257261207606d329fa73b1a1cfe7b3e6c8178be6 100644 --- a/app/components/OutputPanel.jsx +++ b/app/components/OutputPanel.jsx @@ -1,17 +1,16 @@ import React from 'react' import PropTypes from 'prop-types' import RouteTile from './RouteTile' +import { buildUrl } from '../helpers' -const OutputPanel = ({url, stops}) => ( +const OutputPanel = ({stops}) => ( <div> <h2>Complete Route</h2> - <RouteTile url={url} stops={stops} - noStopsText="Add links to partial routes on the left" /> + <RouteTile url={buildUrl(stops)} stops={stops} /> </div> ) OutputPanel.propTypes = { - url: PropTypes.string.isRequired, stops: PropTypes.arrayOf(PropTypes.string).isRequired } diff --git a/app/components/RouteTile.jsx b/app/components/RouteTile.jsx index 9cde62ade52e143de2e7b50c5e36911ae514c217..321995f9f388cfde5fe96677f8471868ebe34544 100644 --- a/app/components/RouteTile.jsx +++ b/app/components/RouteTile.jsx @@ -1,11 +1,21 @@ import React from 'react' import PropTypes from 'prop-types' -const RouteTile = ({stops, url}) => ( - stops.length == 0 ? +const RouteTile = ({stops, onAdd, url}) => { + let input + + return stops.length == 0 ? <div> - <input type="text" /> - <input type="button" value="+" /> + <form onSubmit={(e) => { + e.preventDefault() + if (input.value.trim() == "") { + return + } + onAdd(input.value.trim()) + }}> + <input type="text" ref={node => {input = node}} /> + <input type="submit" value="+" /> + </form> </div> : <div> @@ -18,11 +28,12 @@ const RouteTile = ({stops, url}) => ( ))} </ul> </div> -) +} RouteTile.propTypes = { stops: PropTypes.arrayOf(PropTypes.string).isRequired, - url: PropTypes.string + url: PropTypes.string, + onAdd: PropTypes.func.isRequired } export default RouteTile diff --git a/app/containers/InputPanel.js b/app/containers/InputPanel.js new file mode 100644 index 0000000000000000000000000000000000000000..a099b82ed978c0be83482e51642d5ccba41bae42 --- /dev/null +++ b/app/containers/InputPanel.js @@ -0,0 +1,14 @@ +import { connect } from 'react-redux' +import * as at from '../actions/actionTypes' +import InputPanel from '../components/InputPanel' +import { mkAddUrl } from '../actions' + +const mapStateToProps = state => { + return { routes: state.routes } +} + +const mapDispatchToProps = dispatch => ({ + onAdd: (url) => dispatch(mkAddUrl(url)) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(InputPanel) diff --git a/app/containers/OutputPanel.js b/app/containers/OutputPanel.js new file mode 100644 index 0000000000000000000000000000000000000000..d40dca7f0c63a2c998060d731936644d3f4c285f --- /dev/null +++ b/app/containers/OutputPanel.js @@ -0,0 +1,11 @@ +import { connect } from 'react-redux' +import * as at from '../actions/actionTypes' +import OutputPanel from '../components/OutputPanel' + +const mapStateToProps = state => { + return { + stops: [].concat.apply([], state.routes) + } +} + +export default connect(mapStateToProps)(OutputPanel) diff --git a/app/helpers/index.js b/app/helpers/index.js new file mode 100644 index 0000000000000000000000000000000000000000..87918fc57c1f335299a8b4845411e51ca1e08dbd --- /dev/null +++ b/app/helpers/index.js @@ -0,0 +1,24 @@ + + +/* +https://www.google.com/maps/dir/53.1518753,12.4661154/52.1956608,9.1839549/51.9431347,12.9028906/@51.1758057,10.4541194,6z/data=!4m2!4m1!3e0 + +*/ +export const extractStops = (url) => { + const route = url.split("@")[0] + const match = route.match("^https?://(www\.)?google.[a-z]+/maps/dir/") + if (match === null) { + return [] + } + const prefix = match[0] + let stops = route.slice(match[0].length).split("/") + if (stops[stops.length - 1] == "") { + stops.pop() + } + + return stops +} + +export const buildUrl = (stops) => { + return "https://www.google.com/maps/dir/" + stops.join("/") + "/" +} diff --git a/app/initialize.jsx b/app/initialize.jsx index 908910839bcf2941a0d5a96eb3d0a448e0f58234..bafa261fd4365dcb1a9dcc4ad507c2648aeaf0bf 100644 --- a/app/initialize.jsx +++ b/app/initialize.jsx @@ -3,15 +3,17 @@ import React from 'react'; import { Provider } from 'react-redux'; import { createStore } from 'redux'; import App from './components/App'; +import reducer from './reducers' // const store = createStore(counterApp, module.hot && module.hot.data && (module.hot.data.counter || 0)); +const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__() && window.__REDUX_DEVTOOLS_EXTENSION__()) const load = () => { ReactDOM.render( - //<Provider store={store}> + <Provider store={store}> <App /> - //</Provider> - , document.querySelector('#react-root') + </Provider>, + document.querySelector('#react-root') ); }; diff --git a/app/reducers/index.js b/app/reducers/index.js index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3e8b77664680ddb3a8063889fb463e2734893914 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -0,0 +1,19 @@ +import * as at from '../actions/actionTypes' +import { extractStops } from '../helpers' + + +const initialState = { + routes: [], +} + +const reducer = (state = initialState, action) => { + switch (action.type) { + case at.ADD_URL: + return {routes: state.routes.concat([extractStops(action.payload)])} + + default: + return state + } +} + +export default reducer