From 342d11ac55ad418d19786352f3be31bf990cc6d3 Mon Sep 17 00:00:00 2001 From: Frank Sauerburger <frank@sauerburger.com> Date: Mon, 25 Mar 2019 14:14:35 +0100 Subject: [PATCH] Implement basic add url interactivity --- app/actions/actionTypes.js | 4 ++++ app/actions/index.js | 30 ++++++++++++++++++++++++++++++ app/components/App.jsx | 8 ++++---- app/components/InputPanel.jsx | 4 ++-- app/components/OutputPanel.jsx | 7 +++---- app/components/RouteTile.jsx | 23 +++++++++++++++++------ app/containers/InputPanel.js | 14 ++++++++++++++ app/containers/OutputPanel.js | 11 +++++++++++ app/helpers/index.js | 24 ++++++++++++++++++++++++ app/initialize.jsx | 8 +++++--- app/reducers/index.js | 19 +++++++++++++++++++ 11 files changed, 133 insertions(+), 19 deletions(-) create mode 100644 app/containers/InputPanel.js create mode 100644 app/containers/OutputPanel.js create mode 100644 app/helpers/index.js diff --git a/app/actions/actionTypes.js b/app/actions/actionTypes.js index e69de29..e100419 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 e69de29..51c5460 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 bace1f3..21d6274 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 a49340f..2f3fda7 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 977b101..2572612 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 9cde62a..321995f 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 0000000..a099b82 --- /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 0000000..d40dca7 --- /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 0000000..87918fc --- /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 9089108..bafa261 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 e69de29..3e8b776 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 -- GitLab