diff --git a/package.json b/package.json index d3aa6ac..23d4b9e 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,17 @@ "version": "0.1.0", "private": true, "dependencies": { + "ajv": "^6.5.1", "axios": "^0.18.0", + "leaflet": "^1.3.1", + "leaflet-draw": "^1.0.2", "lodash": "^4.17.10", "moment": "^2.22.2", "react": "^16.4.1", "react-dom": "^16.4.1", "react-flatpickr": "^3.6.4", + "react-leaflet": "^1.9.1", + "react-leaflet-draw": "^0.18.0", "react-redux": "^5.0.7", "react-router-dom": "^4.3.1", "react-scripts": "1.1.4", diff --git a/public/index.html b/public/index.html index 3e6cca5..62deb6a 100644 --- a/public/index.html +++ b/public/index.html @@ -10,6 +10,8 @@ --> + + @@ -24,7 +26,15 @@ --> Grunt FRONT diff --git a/src/App.js b/src/App.js index 5ff5bff..476001e 100644 --- a/src/App.js +++ b/src/App.js @@ -2,21 +2,19 @@ import React from 'react' // import './App.css' import { Switch, Route } from 'react-router-dom' -import Footer from './components/Footer' import Main from './container/Main' +import Geo from './container/Geo' import Public from './container/Public' import { LOGIN_PATH } from './constants/path' const App = () => ( -
- - {/* both /roster and /roster/:number begin with /roster */} - - - -
+ + {/* both /roster and /roster/:number begin with /roster */} + + + + ) export default App diff --git a/src/actions/index.js b/src/actions/index.js index 5b11b4d..1317976 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -4,16 +4,6 @@ import { login } from '../utils/Auth' import { RSAAHeaders } from '../utils/ApiClient' import { API_URL } from '../constants/Api' - -export const incFirstCounter = _ => ({ - type: types.FIRST_INCREMENT_COUNTER, -}) - -export const assignFirstId = objId => ({ - type: types.FIRST_ASSIGN_ID, - newId: objId -}) - // auth export const reqAuth = _ => { return { @@ -48,6 +38,59 @@ export function fetchAuth(user, passwd) { } } +// geo + +export const geoLocationUpdate = (position) => { + /* + PositionĀ {coords: Coordinates, timestamp: 1530214120419} + Coordinates { + latitude: 13.8462448, longitude: 100.53825479999999, + altitude: null, accuracy: 20, + altitudeAccuracy: null, speed: 20} + */ + const { coords } = position + const newCoords = { + accuracy: coords.accuracy, + altitude: coords.altitude, + altitudeAccuracy: coords.altitudeAccuracy, + heading: coords.heading, + latitude: coords.latitude, + longitude: coords.longitude, + speed: coords.speed, + } + return { + type: types.GEO_LOCATION_SUCCESS, + coords: newCoords, + timestamp: position.timestamp, + } +} + +export const geoLocationFailed = (positionErr) => { + // PositionErrorĀ {code: 3, message: "Timeout expired"} + return { + type: types.GEO_LOCATION_FAILURE, + code: positionErr.code, + message: positionErr.message, + } +} + +export const polygonUpdate = (id, geojson, style) => { + return { + type: types.GEO_POLYGON_UPDATE, + payload: { + id, + geojson, + style: style || {}, + } + } +} + +export const polygonReset = () => { + return { + type: types.GEO_POLYGON_RESET + } +} + // AGENCY export const getAgency = () => ({ diff --git a/src/actions/stoptime.js b/src/actions/stoptime.js new file mode 100644 index 0000000..f574ca0 --- /dev/null +++ b/src/actions/stoptime.js @@ -0,0 +1,67 @@ +import { RSAA } from 'redux-api-middleware' + +import * as types from '../constants/ActionTypes' +import { RSAAHeaders } from '../utils/ApiClient' +import { API_URL } from '../constants/Api' + + +export const getStopTime = (query) => ({ + [RSAA]: { + endpoint: `${API_URL}/stoptime/?${query || ''}`, + method: 'GET', + headers: RSAAHeaders, + bailout: (state) => state.stoptime.fetching, + types: [ + { + type: types.STOPTIME_REQUEST, + meta: { query: query }, + }, + types.STOPTIME_SUCCESS, + types.STOPTIME_FAILURE, + ] + } +}) + +export const updateStopTime = (id, body) => ({ + [RSAA]: { + endpoint: `${API_URL}/stoptime/${id}/`, + body: JSON.stringify(body), + method: 'PATCH', + headers: RSAAHeaders, + types: [ + types.STOPTIME_REQUEST, + types.STOPTIME_UPDATE, + types.STOPTIME_FAILURE, + ] + } +}) + +export const createStopTime = (body) => ({ + [RSAA]: { + endpoint: `${API_URL}/stoptime/`, + body: JSON.stringify(body), + method: 'POST', + headers: RSAAHeaders, + types: [ + types.STOPTIME_REQUEST, + types.STOPTIME_CREATE, + types.STOPTIME_FAILURE, + ] + } +}) + +export const deleteStopTime = (id) => ({ + [RSAA]: { + endpoint: `${API_URL}/stoptime/${id}/`, + method: 'DELETE', + headers: RSAAHeaders, + types: [ + types.STOPTIME_REQUEST, + { + type: types.STOPTIME_DELETE, + meta: { id } + }, + types.STOPTIME_FAILURE, + ] + } +}) diff --git a/src/components/AgencyItem.js b/src/components/AgencyItem.js index f004ab9..f1d8ac0 100644 --- a/src/components/AgencyItem.js +++ b/src/components/AgencyItem.js @@ -3,9 +3,6 @@ import styled from 'styled-components' import { connect } from 'react-redux' import { Link, Redirect, Route } from 'react-router-dom' -// import { getRoute } from '../actions' -// import store from '../store' - import Spinner from './Spinner' import RouteList from './RouteList' import FareAttrList from './FareAttrList' @@ -18,11 +15,14 @@ background: #fafafa; class AgencyItem extends Component { render() { - const { props } = this - const { agencyId, agencyChild } = props.match.params - const { results, fetching } = props.agency + const { agency, match, updateBreadcrumb, children } = this.props + const { agencyId, agencyChild } = match.params + const { results, fetching } = agency const one = results.filter(ele => ele.agency_id === agencyId)[0] + if (updateBreadcrumb !== undefined) + updateBreadcrumb(match.params) + if (!fetching && one === undefined) return @@ -69,7 +69,7 @@ class AgencyItem extends Component { {agencyChild === undefined &&

Pick options on the tab

} - {props.children} + {children} ) } @@ -80,7 +80,7 @@ const mapStateToProps = state => ({ route: state.route, }) -const connectAgencyList = connect( +const connectAgencyItem = connect( mapStateToProps, )(AgencyItem) -export default connectAgencyList +export default connectAgencyItem diff --git a/src/components/AgencyList.js b/src/components/AgencyList.js index 2b2b9b5..3a45526 100644 --- a/src/components/AgencyList.js +++ b/src/components/AgencyList.js @@ -42,7 +42,7 @@ class AgencyList extends Component {

{results && Object.keys(results).map(i => ( - +

Agency ID

diff --git a/src/components/Breadcrumb.js b/src/components/Breadcrumb.js new file mode 100644 index 0000000..346c779 --- /dev/null +++ b/src/components/Breadcrumb.js @@ -0,0 +1,26 @@ +import React from 'react' +import styled from 'styled-components' +import { Link } from 'react-router-dom' + +const StyledBreadcrumb = styled.nav` +padding: 0 5px; +font-size: 0.7rem; +margin-bottom: 5px !important; +` + + +const Breadcrumb = (props) => ( + +
    +
  • ALL
  • + {props.agencyId &&
  • + + {props.agencyId}
  • } + {props.routeId &&
  • + + {props.routeId}
  • } +
+
+) + +export default Breadcrumb diff --git a/src/components/CalendarList.js b/src/components/CalendarList.js index adfb245..e9764e6 100644 --- a/src/components/CalendarList.js +++ b/src/components/CalendarList.js @@ -56,7 +56,7 @@ class CalendarList extends Component {

{results && Object.keys(results).map(i => ( - +

Service ID

diff --git a/src/components/FloatPane.js b/src/components/FloatPane.js new file mode 100644 index 0000000..9b0181f --- /dev/null +++ b/src/components/FloatPane.js @@ -0,0 +1,157 @@ +import React, { Component } from 'react' +import { Link, Route } from 'react-router-dom' +import { connect } from 'react-redux' +import styled from 'styled-components' + +import { logout } from '../utils/Auth' +import RouteList from './RouteList' +import RouteDetail from './RouteDetail' +import Breadcrumb from './Breadcrumb' +import { polygonReset } from '../actions' +import store from '../store' + +const StyledLink = styled(Link)` +&[data-active] { + color: red; +} +` + +const StyledLRPaddingNav = styled.nav` +padding-right: 10px; +padding-left: 0; +margin-bottom: 5px !important; +` + +const StyledFloatPane = styled.div` +min-width: 300px; +height: 100%; +width: 25vw; +z-index: 30; +background: #fefefefe; +border-radius: 0 5px 5px 0; +position: fixed; +left: ${props => props.hidePane ? '-500px' : 0}; +top: 0px; +` + +const StyledPaneToggler = styled.div` +width: 20px +height: 30px; +background: #fefefefe; +color: #209cee; +position: fixed; +text-align: center; +left: ${props => props.hidePane ? 0 : '25vw'}; +top: 30px; +border-radius: 0 5px 5px 0; + +@media (max-width: 1200px) { + left: ${props => props.hidePane ? 0 : '300px'}; +} +` + +const StyledScrollY = styled.div` +height: 100vh; +overflow: auto; +padding-bottom: 5rem; +` + +const SimpleAgencyList = (props) => ( + +) + + + +class FloatPane extends Component { + + state = { hidePane: false, breadcrumb: {} } + + renderTopLevel(loggedIn) { + return ( + +
+ + GoTH + +
+
+ store.dispatch(polygonReset())}> + + + + Clear PG + + {loggedIn && + logout()}> + + + + Logout + + } + {!loggedIn && + + + + + Sign in + + } +
+
+ ) + } + + togglePane() { + this.setState({ hidePane: !this.state.hidePane }) + } + + handleChildMatchParams(params) { + this.setState({ breadcrumb: params }) + } + + render () { + const { loggedIn, agency } = this.props + const { hidePane } = this.state + const { results } = agency + + return ( + + + + + {this.renderTopLevel(loggedIn)} + + + ( + )} /> + ( + )} /> + + ( + )} /> + + + + ) + } +} + +const mapStateToProps = state => ({ + agency: state.agency, +}) +export default connect( + mapStateToProps +)(FloatPane) diff --git a/src/components/Nav.js b/src/components/Nav.js index 466c99f..44cbff0 100644 --- a/src/components/Nav.js +++ b/src/components/Nav.js @@ -4,19 +4,62 @@ import styled from 'styled-components' import { Link } from 'react-router-dom' import { logout } from '../utils/Auth' +import { polygonReset } from '../actions' const StyledLink = styled(Link)` &[data-active] { color: red; } -`; +` class Nav extends Component { state = { expandNavbar: false } - render() { + renderLoggedIn() { const { props } = this + return ( +
+ + Home + +
+ + Service + +
+ + +   new service calendar + +
+
+
+ + Agency + +
+ {props.agency.count > 0 + && props.agency.results.map(ele => ( + + {ele.name || ele.agency_id} + + ))} + + +  Add new agency + +
+
+ + Map + +
+ ) + } + + render() { + const { loggedIn } = this.props return (