Skip to content

Commit

Permalink
first attempt at implementing new location groups
Browse files Browse the repository at this point in the history
  • Loading branch information
miles-grant-ibigroup committed May 17, 2024
1 parent de5f50d commit c54b3a2
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 5 deletions.
20 changes: 19 additions & 1 deletion gtfs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,16 @@
helpContent: "The stop_url field contains the URL of a web page about a particular location. This should be different from the agency_url and the route_url fields."

# FIXME: helpContent is lifted from https://github.com/MobilityData/gtfs-flex/blob/master/spec/reference.md
- id: locationgroupstop
flex: true
name: location_group_stops.txt
fields:
- name: "location_group_id"
required: true
inputType: TEXT
- name: "stop_id"
required: true
inputType: GTFS_ID
- id: locationgroup
flex: true
name: location_groups.txt
Expand All @@ -1177,4 +1187,12 @@
required: false
inputType: TEXT
columnWidth: 12
helpContent: "Name of the location group. Must be defined either once, or exhaustively for a single location_group_id."
helpContent: "Name of the location group. Must be defined either once, or exhaustively for a single location_group_id."
extraFields:
- name: "stop_id"
required: false
inputType: GTFS_STOP_OR_LOCATION_LIST
columnWidth: 12
helpContent: "Identifies a stop or location belonging to the location group."
activeComponentOverride: "locationgroupstop"

4 changes: 3 additions & 1 deletion lib/editor/actions/active.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
removeEditorLock
} from './editor'
import {saveTripPattern} from './tripPattern'
import { saveLocation } from './location'
import { saveLocation, saveLocationGroup } from './location'

export const clearGtfsContent = createVoidPayloadAction('CLEAR_GTFSEDITOR_CONTENT')
export const receivedNewEntity = createAction(
Expand Down Expand Up @@ -373,6 +373,8 @@ export function saveActiveGtfsEntity (
return dispatch(saveTripPattern(feedId, (entity: any)))
case 'location':
return dispatch(saveLocation(feedId, (entity: any), refetch))
case 'locationgroup':
return dispatch(saveLocationGroup(feedId, (entity: any), refetch))
default:
// Default method for agencies, stops, routes, fares, calendars.
// Trip patterns and feed info are handled above. Trips are handled in
Expand Down
4 changes: 4 additions & 0 deletions lib/editor/actions/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,10 @@ export function fetchBaseGtfs ({
location_group_id
location_group_name
}
location_group_stops {
location_group_id
stop_id
}
feed_info {
id
feed_id
Expand Down
66 changes: 65 additions & 1 deletion lib/editor/actions/location.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,74 @@ import {getMapFromGtfsStrategy, entityIsNew} from '../util/objects'
import { getEditorNamespace } from '../util/gtfs'
import {fetchGTFSEntities} from '../../manager/actions/versions'
import type {dispatchFn, getStateFn} from '../../types/reducers'
import type {GtfsLocation} from '../../types'
import type {GtfsLocationGroup} from '../../types'

import { receivedNewEntity, savedGtfsEntity } from './active'

export function saveLocationGroup (
feedId: ?string,
locationGroup: GtfsLocationGroup,
refetch: ?boolean = true
) {
return function (dispatch: dispatchFn, getState: getStateFn) {
if (!feedId || !locationGroup) {
return
}
// dispatch(savingActiveLocation()) //Update this?

const notNew = !entityIsNew(locationGroup) // Checks if id is -2 or undefined
const method = notNew ? 'put' : 'post'
const idParam = notNew ? `/${locationGroup.id || ''}` : ''
const {sessionId} = getState().editor.data.lock

const mappingStrategy = getMapFromGtfsStrategy('locationGroup')
const data = mappingStrategy(locationGroup)

const locationGroupUrl = `/api/editor/secure/locationgroup${idParam}?feedId=${feedId}&sessionId=${sessionId || ''}`
const locationGroupStopsUrl = `/api/editor/secure/locationgroupstop${idParam}?feedId=${feedId}&sessionId=${sessionId || ''}`

dispatch(secureFetch(locationGroupStopsUrl, method, data))
.then(res => res.json())
.then(savedEntity => {
dispatch(savedGtfsEntity())
const namespace = getEditorNamespace(feedId, getState())
// Refetch entity and replace in store
if (refetch) {
dispatch(fetchGTFSEntities({
namespace,
id: savedEntity.id,
type: 'locationgroupstop',
editor: true,
replaceNew: !notNew
}))
} else {
// Push new entity into store.
dispatch(receivedNewEntity({component: 'locationgroupstop', entity: savedEntity}))
}
})
return dispatch(secureFetch(locationGroupUrl, method, data))
.then(res => res.json())
.then(savedEntity => {
dispatch(savedGtfsEntity())
const namespace = getEditorNamespace(feedId, getState())
// Refetch entity and replace in store
if (refetch) {
dispatch(fetchGTFSEntities({
namespace,
id: savedEntity.id,
type: 'locationgroup',
editor: true,
replaceNew: !notNew
}))
} else {
// Push new entity into store.
dispatch(receivedNewEntity({component: 'locationgroup', entity: savedEntity}))
Promise.resolve(savedEntity)
}
})
}
}

export function saveLocation (
feedId: ?string,
location: GtfsLocation,
Expand Down
3 changes: 2 additions & 1 deletion lib/editor/components/EditorInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,14 @@ export default class EditorInput extends React.Component<Props> {
*/
_processFieldChange = (val: any) => {
const {
activeComponent,
activeEntity,
field,
onChange,
updateActiveGtfsEntity
} = this.props
onChange && onChange(val)
const activeComponent = field.activeComponentOverride || this.props.activeComponent

updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
component: activeComponent,
entity: activeEntity,
Expand Down
3 changes: 2 additions & 1 deletion lib/editor/components/EntityDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export default class EntityDetails extends Component<Props, State> {
<div>
<Form>
{/* Editor Inputs */}
{renderDefault && currentTable.fields
{renderDefault && [...currentTable.fields, ...(currentTable.extraFields || [])]
.map((field, i) => (
<div
key={`${activeComponent}-${activeEntity.id || ''}-${i}`}
Expand All @@ -180,6 +180,7 @@ export default class EntityDetails extends Component<Props, State> {
</Form>
</div>
)

}
</div>
</div>
Expand Down
9 changes: 9 additions & 0 deletions lib/editor/reducers/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ const data = (state: DataState = defaultState, action: Action): DataState => {
console.warn(`No feed info found. Adding feed info with null values.`)
feed.feed_info.push(generateNullProps('feedinfo'))
}

if (feed.location_group_stops && feed.location_group_stops.length === 1 && feed.location_group_stops[0].stop_id) {
feed.location_groups[0].stop_id = feed.location_group_stops[0].stop_id.split(',')
}

return update(state, {
tables: {$set: feed},
status: {$set: {baseFetched: true}}
Expand Down Expand Up @@ -266,6 +271,10 @@ const data = (state: DataState = defaultState, action: Action): DataState => {
const {component, editor} = action.payload
const {data} = action.payload

if (data && data.feed.location_group_stops && data.feed.location_group_stops.length === 1 && data.feed.location_group_stops[0].stop_id) {
data.feed.location_groups[0].stop_id = data.feed.location_group_stops[0].stop_id.split(',')
}

if (!editor) {
// Ignore entity fetches if not for the editor (i.e., fetching entities
// for viewing validation result details).
Expand Down
4 changes: 4 additions & 0 deletions lib/gtfs/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ export function getGraphQLFieldsForEntity (type: string, editor: boolean = false
${shapeFields}
}
`
case 'location_group_stop':
return patternLocationGroupFields
default:
return fields
}
Expand Down Expand Up @@ -218,6 +220,8 @@ export function getEntityGraphQLRoot (type: string): string {
return 'locations'
case 'locationgroup':
return 'location_groups'
case 'locationgroupstop':
return 'location_group_stops'
default:
return ''
}
Expand Down
10 changes: 10 additions & 0 deletions lib/manager/actions/versions.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,15 @@ export function fetchGTFSEntities ({
if (!graphQLRoot || !entityIdField) {
console.warn(`No graphql table or filter field for ${type}`)
}
// Location groups are split across two tables, so we need to manually fetch the second
// set here
const locationGroupSupplementalFields = graphQLRoot === 'location_groups' ? `
location_group_stops (limit: -1, id: $id) {
id
location_group_id
stop_id
}
` : ''
const fields = getGraphQLFieldsForEntity(type, editor)
// If fetching for the editor, query on id which is an Int
const query = `
Expand All @@ -288,6 +297,7 @@ export function fetchGTFSEntities ({
id
${fields}
}
${locationGroupSupplementalFields}
}
}
`
Expand Down

0 comments on commit c54b3a2

Please sign in to comment.