Skip to content

Commit

Permalink
feat(field-trip): add field trip module (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
landonreed committed Sep 11, 2020
1 parent fd2bfae commit a8160f3
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 36 deletions.
9 changes: 8 additions & 1 deletion example.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
CallTakerControls,
CallTakerPanel,
CallTakerWindows,
FieldTripWindows,
DefaultMainPanel,
DesktopNav,
BatchRoutingPanel,
Expand Down Expand Up @@ -96,7 +97,13 @@ class OtpRRExample extends Component {
</Col>
{otpConfig.datastoreUrl ? <CallTakerControls /> : null}
<Col sm={6} md={8} className='map-container'>
{otpConfig.datastoreUrl ? <CallTakerWindows /> : null}
{otpConfig.datastoreUrl
? <>
<CallTakerWindows />
<FieldTripWindows />
</>
: null
}
<Map />
</Col>
</Row>
Expand Down
26 changes: 26 additions & 0 deletions lib/actions/call-taker.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ const requestingCalls = createAction('REQUESTING_CALLS')
const requestingQueries = createAction('REQUESTING_QUERIES')
const storeSession = createAction('STORE_SESSION')

const receivedFieldTrips = createAction('RECEIVED_FIELD_TRIPS')
const requestingFieldTrips = createAction('REQUESTING_FIELD_TRIPS')

/// PUBLIC ACTIONS

export const beginCall = createAction('BEGIN_CALL')
export const toggleCallHistory = createAction('TOGGLE_CALL_HISTORY')
export const toggleFieldTrips = createAction('TOGGLE_FIELD_TRIPS')

/**
* End the active call and store the queries made during the call.
Expand Down Expand Up @@ -133,6 +137,28 @@ export function fetchCalls () {
}
}

/**
* Fetch latest calls for a particular session.
*/
export function fetchFieldTrips () {
return function (dispatch, getState) {
dispatch(requestingFieldTrips())
const {callTaker, otp} = getState()
if (sessionIsInvalid(callTaker.session)) return
const {datastoreUrl} = otp.config
const {sessionId} = callTaker.session
fetch(`${datastoreUrl}/fieldtrip/getRequestsSummary?${qs.stringify({sessionId})}`)
.then(res => res.json())
.then(fieldTrips => {
console.log('GET field trips response', fieldTrips)
dispatch(receivedFieldTrips({fieldTrips}))
})
.catch(err => {
alert(`Could not fetch field trips: ${JSON.stringify(err)}`)
})
}
}

/**
* @return {boolean} - whether a calltaker session is invalid
*/
Expand Down
110 changes: 76 additions & 34 deletions lib/components/admin/call-taker-controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Icon from '../narrative/icon'
const RED = '#C35134'
const BLUE = '#1C4D89'
const GREEN = '#6B931B'
const PURPLE = '#8134D3'

/**
* This component displays the controls for the Call Taker/Field Trip modules,
Expand All @@ -21,10 +22,17 @@ const GREEN = '#6B931B'
*/
class CallTakerControls extends Component {
componentWillReceiveProps (nextProps) {
const {session} = nextProps
const {
callTakerEnabled,
fetchCalls,
fetchFieldTrips,
fieldTripEnabled,
session
} = nextProps
// Once session is available, fetch calls.
if (session && !this.props.session) {
this.props.fetchCalls()
if (callTakerEnabled) fetchCalls()
if (fieldTripEnabled) fetchFieldTrips()
}
}

Expand Down Expand Up @@ -57,10 +65,12 @@ class CallTakerControls extends Component {

_onToggleCallHistory = () => this.props.toggleCallHistory()

_onToggleFieldTrips = () => this.props.toggleFieldTrips()

_callInProgress = () => Boolean(this.props.activeCall)

render () {
const {session} = this.props
const {callTakerEnabled, fieldTripEnabled, session} = this.props
// If no valid session is found, do not show calltaker controls.
if (!session) return null
// FIXME: styled component
Expand All @@ -75,21 +85,23 @@ class CallTakerControls extends Component {
return (
<>
{/* Start/End Call button */}
<button
style={{
...circleButtonStyle,
top: '154px',
backgroundColor: this._callInProgress() ? RED : BLUE,
height: '80px',
width: '80px',
marginLeft: '-8px'
{callTakerEnabled &&
<button
style={{
...circleButtonStyle,
top: '154px',
backgroundColor: this._callInProgress() ? RED : BLUE,
height: '80px',
width: '80px',
marginLeft: '-8px'

}}
className='call-taker-button'
onClick={this._onClickCall}
>
{this._renderCallButton()}
</button>
}}
className='call-taker-button'
onClick={this._onClickCall}
>
{this._renderCallButton()}
</button>
}
{this._callInProgress()
? <CallTimeCounter style={{
display: 'inline',
Expand All @@ -108,22 +120,41 @@ class CallTakerControls extends Component {
: null
}
{/* Call History toggle button */}
<button
style={{
...circleButtonStyle,
top: '140px',
backgroundColor: GREEN,
height: '40px',
width: '40px',
marginLeft: '69px'

}}
className='call-taker-button'
onClick={this._onToggleCallHistory}
>
<Icon type='history' className='fa-2x' style={{marginLeft: '-3px'}} />
</button>
{callTakerEnabled &&
<button
style={{
...circleButtonStyle,
top: '140px',
backgroundColor: GREEN,
height: '40px',
width: '40px',
marginLeft: '69px'

}}
className='call-taker-button'
onClick={this._onToggleCallHistory}
>
<Icon type='history' className='fa-2x' style={{marginLeft: '-3px'}} />
</button>
}
{/* Field Trip toggle button TODO */}
{fieldTripEnabled &&
<button
style={{
...circleButtonStyle,
top: '190px',
backgroundColor: PURPLE,
height: '50px',
width: '50px',
marginLeft: '80px'

}}
className='call-taker-button'
onClick={this._onToggleFieldTrips}
>
<Icon type='graduation-cap' className='fa-2x' style={{marginLeft: '2px', marginTop: '3px'}} />
</button>
}
</>
)
}
Expand All @@ -132,19 +163,30 @@ class CallTakerControls extends Component {
const mapStateToProps = (state, ownProps) => {
return {
activeCall: state.callTaker.activeCall,
callTakerEnabled: Boolean(state.otp.config.modules.find(m => m.id === 'call')),
fieldTripEnabled: Boolean(state.otp.config.modules.find(m => m.id === 'ft')),
session: state.callTaker.session
}
}

const {beginCall, endCall, fetchCalls, toggleCallHistory} = callTakerActions
const {
beginCall,
endCall,
fetchCalls,
fetchFieldTrips,
toggleCallHistory,
toggleFieldTrips
} = callTakerActions

const mapDispatchToProps = {
beginCall,
endCall,
fetchCalls,
fetchFieldTrips,
routingQuery,
setMainPanelContent,
toggleCallHistory
toggleCallHistory,
toggleFieldTrips
}

export default connect(mapStateToProps, mapDispatchToProps)(CallTakerControls)
67 changes: 67 additions & 0 deletions lib/components/admin/field-trip-windows.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'

import * as callTakerActions from '../../actions/call-taker'
import CallRecord from './call-record'
import DraggableWindow from './draggable-window'
import Icon from '../narrative/icon'

/**
* Collects the various draggable windows used in the Call Taker module to
* display, for example, the call record list and (TODO) the list of field trips.
*/
class FieldTripWindows extends Component {
render () {
const {callTaker, fetchQueries, searches} = this.props
const {activeCall, fieldTrip} = callTaker
console.log(fieldTrip)
return (
<>
{fieldTrip.visible
// Active call window
? <DraggableWindow
draggableProps={{
defaultPosition: fieldTrip.position
}}
header={<span><Icon type='graduation-cap' /> Field Trip Requests</span>}
onClickClose={this.props.toggleCallHistory}
>
{activeCall
? <CallRecord
call={activeCall}
searches={searches}
inProgress />
: null
}
{fieldTrip.requests.data.length > 0
? fieldTrip.requests.data.map((request, i) => (
<div key={request.id}>
{request.startLocation} to {request.endLocation}
</div>
))
: <div>No calls in history</div>
}
</DraggableWindow>
: null
}
</>
)
}
}

const mapStateToProps = (state, ownProps) => {
return {
callTaker: state.callTaker,
currentQuery: state.otp.currentQuery,
searches: state.otp.searches
}
}

const {
fetchQueries,
toggleCallHistory
} = callTakerActions

const mapDispatchToProps = { fetchQueries, toggleCallHistory }

export default connect(mapStateToProps, mapDispatchToProps)(FieldTripWindows)
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import CallTakerControls from './components/admin/call-taker-controls'
import CallTakerWindows from './components/admin/call-taker-windows'
import FieldTripWindows from './components/admin/field-trip-windows'

import DateTimeModal from './components/form/date-time-modal'
import DateTimePreview from './components/form/date-time-preview'
Expand Down Expand Up @@ -65,6 +66,7 @@ export {
DateTimePreview,
DefaultSearchForm,
ErrorMessage,
FieldTripWindows,
LocationField,
PlanTripButton,
SettingsPreview,
Expand Down
30 changes: 29 additions & 1 deletion lib/reducers/call-taker.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {getTimestamp} from '../util/state'
const { randId } = coreUtils.storage

const UPPER_RIGHT_CORNER = {x: 604, y: 53}
const LOWER_RIGHT_CORNER = {x: 604, y: 400}

const FETCH_STATUS = {
UNFETCHED: 0,
Expand All @@ -26,7 +27,14 @@ function createCallTakerReducer () {
data: []
}
},
fieldTrips: [],
fieldTrip: {
position: LOWER_RIGHT_CORNER,
requests: {
status: FETCH_STATUS.UNFETCHED,
data: []
},
visible: false,
},
session: null
}
return (state = initialState, action) => {
Expand Down Expand Up @@ -58,6 +66,21 @@ function createCallTakerReducer () {
callHistory: { calls: { $set: calls } }
})
}
case 'REQUESTING_FIELD_TRIPS': {
return update(state, {
fieldTrip: { requests: { status: { $set: FETCH_STATUS.FETCHING } } }
})
}
case 'RECEIVED_FIELD_TRIPS': {
const data = action.payload.fieldTrips
const requests = {
status: FETCH_STATUS.FETCHED,
data: data.sort((a, b) => moment(b.endTime) - moment(a.endTime))
}
return update(state, {
fieldTrip: { requests: { $set: requests } }
})
}
case 'RECEIVED_QUERIES': {
const {callId, queries} = action.payload
const {data} = state.callHistory.calls
Expand Down Expand Up @@ -95,6 +118,11 @@ function createCallTakerReducer () {
callHistory: { visible: { $set: !state.callHistory.visible } }
})
}
case 'TOGGLE_FIELD_TRIPS': {
return update(state, {
fieldTrip: { visible: { $set: !state.fieldTrip.visible } }
})
}
case 'END_CALL': {
return update(state, {
activeCall: { $set: null }
Expand Down

0 comments on commit a8160f3

Please sign in to comment.