Skip to content

Commit

Permalink
refactor: refactor ResponsiveWebapp and some other things
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

refactored example.js, ResponsiveWebapp and associated component signatures to use components provided to component context
  • Loading branch information
evansiroky committed Mar 10, 2021
1 parent cab1eec commit a1e63b3
Show file tree
Hide file tree
Showing 12 changed files with 200 additions and 205 deletions.
2 changes: 1 addition & 1 deletion __tests__/reducers/create-otp-reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ describe('lib > reducers > create-otp-reducer', () => {

it('should be able to create the initial state', () => {
setDefaultTestTime()
expect(getInitialState({}, {})).toMatchSnapshot()
expect(getInitialState({})).toMatchSnapshot()
})
})
7 changes: 4 additions & 3 deletions __tests__/test-utils/mock-data/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ const storeMiddleWare = [
* Get the initial stop of the redux reducer for otp-rr
*/
export function getMockInitialState () {
const mockConfig = {}
const mockInitialQuery = {}
const mockConfig = {
initialQuery: {}
}
return clone({
otp: getInitialState(mockConfig, mockInitialQuery),
otp: getInitialState(mockConfig),
router: connectRouter(history)
})
}
Expand Down
156 changes: 52 additions & 104 deletions example.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,37 @@ import 'es6-math'
import {ClassicLegIcon, ClassicModeIcon} from '@opentripplanner/icons'
import { createHashHistory } from 'history'
import { connectRouter, routerMiddleware } from 'connected-react-router'
import React, { Component } from 'react'
import React from 'react'
import { render } from 'react-dom'
import { createStore, combineReducers, applyMiddleware, compose } from 'redux'
import { Provider } from 'react-redux'
import thunk from 'redux-thunk'
import createLogger from 'redux-logger'

// import Bootstrap Grid components for layout
import { Grid, Row, Col } from 'react-bootstrap'

// import OTP-RR components
import {
BatchRoutingPanel,
BatchSearchScreen,
CallTakerControls,
CallTakerPanel,
CallTakerWindows,
DefaultItinerary,
DefaultMainPanel,
DesktopNav,
BatchRoutingPanel,
Map,
MobileMain,
MobileSearchScreen,
ResponsiveWebapp,
createCallTakerReducer,
createOtpReducer,
createUserReducer
createUserReducer,
otpUtils
} from './lib'
// load the OTP configuration
import otpConfig from './config.yml'

const isBatchRoutingEnabled = otpUtils.itinerary.isBatchRoutingEnabled(
otpConfig
)
const isCallTakerModuleEnabled = !!otpConfig.datastoreUrl

// Set useCustomIcons to true to override classic icons with the exports from
// custom-icons.js
const useCustomIcons = false
Expand All @@ -49,18 +51,32 @@ if (useCustomIcons) {

// define some application-wide components that should be used in
// various places. The following components can be provided here:
// - defaultMobileTitle (required)
// - ItineraryBody (required)
// - ItineraryFooter (optional)
// - LegIcon (required)
// - MainControls (optional)
// - MainPanel (required)
// - MapWindows (optional)
// - MobileSearchScreen (required)
// - ModeIcon (required)
const components = {
defaultMobileTitle: () => <div className='navbar-title'>OpenTripPlanner</div>,
ItineraryBody: DefaultItinerary,
LegIcon: MyLegIcon,
MainControls: isCallTakerModuleEnabled ? CallTakerControls : null,
MainPanel: isCallTakerModuleEnabled
? CallTakerPanel
: isBatchRoutingEnabled
? BatchRoutingPanel
: DefaultMainPanel,
MapWindows: isCallTakerModuleEnabled ? CallTakerWindows : null,
MobileSearchScreen: isBatchRoutingEnabled
? BatchSearchScreen
: MobileSearchScreen,
ModeIcon: MyModeIcon
}

// Get the initial query from config (for demo/testing purposes).
const {initialQuery} = otpConfig
const history = createHashHistory()
const middleware = [
thunk,
Expand All @@ -76,109 +92,41 @@ if (process.env.NODE_ENV === 'development') {
const store = createStore(
combineReducers({
callTaker: createCallTakerReducer(),
otp: createOtpReducer(otpConfig, initialQuery),
otp: createOtpReducer(otpConfig),
user: createUserReducer(),
router: connectRouter(history)
}),
compose(applyMiddleware(...middleware))
)

// define a simple responsive UI using Bootstrap and OTP-RR
class OtpRRExample extends Component {
render () {
/** desktop view **/
const desktopView = (
<div className='otp'>
<DesktopNav />
<Grid>
<Row className='main-row'>
<Col sm={6} md={4} className='sidebar'>
{/*
Note: the main tag provides a way for users of screen readers
to skip to the primary page content.
TODO: Find a better place.
*/}
<main>
{/* TODO: extract the BATCH elements out of CallTakerPanel. */}
{otpConfig.datastoreUrl
? <CallTakerPanel />
: otpConfig.routingTypes.find(t => t.key === 'BATCH')
? <BatchRoutingPanel />
: <DefaultMainPanel />
}
</main>
</Col>
{otpConfig.datastoreUrl ? <CallTakerControls /> : null}
<Col sm={6} md={8} className='map-container'>
{otpConfig.datastoreUrl ? <CallTakerWindows /> : null}
<Map />
</Col>
</Row>
</Grid>
</div>
)

/** mobile view **/
const mobileView = (
// <main> Needed for accessibility checks. TODO: Find a better place.
<main>
<MobileMain
map={<Map />}
title={<div className='navbar-title'>OpenTripPlanner</div>}
/>
</main>
)

/**
* The main webapp.
*
* Note: the ResponsiveWebapp creates a React context provider
* (./util/contexts#ComponentContext to be specific) to supply custom
* components to various other subcomponents throughout otp-react-redux. If
* the ResponsiveWebapp is not used and instead some subcomponents that use
* the components in the `components` variable are imported and rendered
* outside of the ResponsiveWebapp component, then the ComponentContext will
* need to wrap that component in order for the subcomponents to be able to
* access the component context. For example:
*
* ```js
* import RouteViewer from 'otp-react-redux/build/components/viewers/route-viewer'
* import { ComponentContext } from 'otp-react-redux/build/util/contexts'
*
* const components = {
* ModeIcon: MyCustomModeIconComponent
* }
* const ContextAwareRouteViewer = () => (
* <ComponentContext.Provider value={components}>
* <RouteViewer />
* <ComponentContext.Provider/>
* )
* ```
*/
return (
<ResponsiveWebapp
components={components}
desktopView={desktopView}
mobileView={mobileView}
/>
)
}
}

// render the app
render(
(
<Provider store={store}>
{ /**
* If not using router history, simply include OtpRRExample here:
* e.g.
* <OtpRRExample />
*/
}
<OtpRRExample />
{/**
* Note: the ResponsiveWebapp creates a React context provider
* (./util/contexts#ComponentContext to be specific) to supply custom
* components to various other subcomponents throughout otp-react-redux. If
* the ResponsiveWebapp is not used and instead some subcomponents that use
* the components in the `components` variable are imported and rendered
* outside of the ResponsiveWebapp component, then the ComponentContext will
* need to wrap that component in order for the subcomponents to be able to
* access the component context. For example:
*
* ```js
* import RouteViewer from 'otp-react-redux/build/components/viewers/route-viewer'
* import { ComponentContext } from 'otp-react-redux/build/util/contexts'
*
* const components = { ModeIcon: MyCustomModeIconComponent }
* const ContextAwareRouteViewer = () => (
* <ComponentContext.Provider value={components}>
* <RouteViewer />
* <ComponentContext.Provider/>
* )
* ```
*/}
<ResponsiveWebapp components={components} />
</Provider>
)
,

),
document.getElementById('root')
)
1 change: 0 additions & 1 deletion lib/components/app/batch-routing-panel.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import coreUtils from '@opentripplanner/core-utils'
import React, { Component } from 'react'
import { connect } from 'react-redux'
import styled from 'styled-components'
Expand Down
48 changes: 44 additions & 4 deletions lib/components/app/responsive-webapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import isEqual from 'lodash.isequal'
import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Col, Grid, Row } from 'react-bootstrap'
import { connect } from 'react-redux'
import { Redirect, Route, Switch, withRouter } from 'react-router'

Expand All @@ -16,6 +17,9 @@ import * as formActions from '../../actions/form'
import * as locationActions from '../../actions/location'
import * as mapActions from '../../actions/map'
import * as uiActions from '../../actions/ui'
import Map from '../map/map'
import MobileMain from '../mobile/main'
import DesktopNav from './desktop-nav'
import { getAuth0Config } from '../../util/auth'
import {
ACCOUNT_PATH,
Expand All @@ -39,12 +43,12 @@ const { isMobile } = coreUtils.ui

class ResponsiveWebapp extends Component {
static propTypes = {
desktopView: PropTypes.element,
initZoomOnLocate: PropTypes.number,
mobileView: PropTypes.element,
query: PropTypes.object
}

static contextType = ComponentContext

/** Lifecycle methods **/

componentDidUpdate (prevProps) {
Expand Down Expand Up @@ -144,9 +148,45 @@ class ResponsiveWebapp extends Component {
window.removeEventListener('popstate', this.props.handleBackButtonPress)
}

renderDesktopView = () => {
const { MainControls, MainPanel, MapWindows } = this.context
return (
<div className='otp'>
<DesktopNav />
<Grid>
<Row className='main-row'>
<Col sm={6} md={4} className='sidebar'>
{/*
Note: the main tag provides a way for users of screen readers
to skip to the primary page content.
TODO: Find a better place.
*/}
<main>
{<MainPanel />}
</main>
</Col>
{MainControls && <MainControls />}
<Col sm={6} md={8} className='map-container'>
{MapWindows && <MapWindows />}
<Map />
</Col>
</Row>
</Grid>
</div>
)
}

renderMobileView = () => {
return (
// <main> Needed for accessibility checks. TODO: Find a better place.
<main>
<MobileMain />
</main>
)
}

render () {
const { desktopView, mobileView } = this.props
return isMobile() ? mobileView : desktopView
return isMobile() ? this.renderMobileView() : this.renderDesktopView()
}
}

Expand Down
Loading

0 comments on commit a1e63b3

Please sign in to comment.