Skip to content

Commit c54b3a2

Browse files
first attempt at implementing new location groups
1 parent de5f50d commit c54b3a2

File tree

9 files changed

+118
-5
lines changed

9 files changed

+118
-5
lines changed

gtfs.yml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,16 @@
11621162
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."
11631163

11641164
# FIXME: helpContent is lifted from https://github.com/MobilityData/gtfs-flex/blob/master/spec/reference.md
1165+
- id: locationgroupstop
1166+
flex: true
1167+
name: location_group_stops.txt
1168+
fields:
1169+
- name: "location_group_id"
1170+
required: true
1171+
inputType: TEXT
1172+
- name: "stop_id"
1173+
required: true
1174+
inputType: GTFS_ID
11651175
- id: locationgroup
11661176
flex: true
11671177
name: location_groups.txt
@@ -1177,4 +1187,12 @@
11771187
required: false
11781188
inputType: TEXT
11791189
columnWidth: 12
1180-
helpContent: "Name of the location group. Must be defined either once, or exhaustively for a single location_group_id."
1190+
helpContent: "Name of the location group. Must be defined either once, or exhaustively for a single location_group_id."
1191+
extraFields:
1192+
- name: "stop_id"
1193+
required: false
1194+
inputType: GTFS_STOP_OR_LOCATION_LIST
1195+
columnWidth: 12
1196+
helpContent: "Identifies a stop or location belonging to the location group."
1197+
activeComponentOverride: "locationgroupstop"
1198+

lib/editor/actions/active.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
removeEditorLock
3131
} from './editor'
3232
import {saveTripPattern} from './tripPattern'
33-
import { saveLocation } from './location'
33+
import { saveLocation, saveLocationGroup } from './location'
3434

3535
export const clearGtfsContent = createVoidPayloadAction('CLEAR_GTFSEDITOR_CONTENT')
3636
export const receivedNewEntity = createAction(
@@ -373,6 +373,8 @@ export function saveActiveGtfsEntity (
373373
return dispatch(saveTripPattern(feedId, (entity: any)))
374374
case 'location':
375375
return dispatch(saveLocation(feedId, (entity: any), refetch))
376+
case 'locationgroup':
377+
return dispatch(saveLocationGroup(feedId, (entity: any), refetch))
376378
default:
377379
// Default method for agencies, stops, routes, fares, calendars.
378380
// Trip patterns and feed info are handled above. Trips are handled in

lib/editor/actions/editor.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,10 @@ export function fetchBaseGtfs ({
482482
location_group_id
483483
location_group_name
484484
}
485+
location_group_stops {
486+
location_group_id
487+
stop_id
488+
}
485489
feed_info {
486490
id
487491
feed_id

lib/editor/actions/location.js

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,74 @@ import {getMapFromGtfsStrategy, entityIsNew} from '../util/objects'
44
import { getEditorNamespace } from '../util/gtfs'
55
import {fetchGTFSEntities} from '../../manager/actions/versions'
66
import type {dispatchFn, getStateFn} from '../../types/reducers'
7-
import type {GtfsLocation} from '../../types'
7+
import type {GtfsLocationGroup} from '../../types'
88

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

11+
export function saveLocationGroup (
12+
feedId: ?string,
13+
locationGroup: GtfsLocationGroup,
14+
refetch: ?boolean = true
15+
) {
16+
return function (dispatch: dispatchFn, getState: getStateFn) {
17+
if (!feedId || !locationGroup) {
18+
return
19+
}
20+
// dispatch(savingActiveLocation()) //Update this?
21+
22+
const notNew = !entityIsNew(locationGroup) // Checks if id is -2 or undefined
23+
const method = notNew ? 'put' : 'post'
24+
const idParam = notNew ? `/${locationGroup.id || ''}` : ''
25+
const {sessionId} = getState().editor.data.lock
26+
27+
const mappingStrategy = getMapFromGtfsStrategy('locationGroup')
28+
const data = mappingStrategy(locationGroup)
29+
30+
const locationGroupUrl = `/api/editor/secure/locationgroup${idParam}?feedId=${feedId}&sessionId=${sessionId || ''}`
31+
const locationGroupStopsUrl = `/api/editor/secure/locationgroupstop${idParam}?feedId=${feedId}&sessionId=${sessionId || ''}`
32+
33+
dispatch(secureFetch(locationGroupStopsUrl, method, data))
34+
.then(res => res.json())
35+
.then(savedEntity => {
36+
dispatch(savedGtfsEntity())
37+
const namespace = getEditorNamespace(feedId, getState())
38+
// Refetch entity and replace in store
39+
if (refetch) {
40+
dispatch(fetchGTFSEntities({
41+
namespace,
42+
id: savedEntity.id,
43+
type: 'locationgroupstop',
44+
editor: true,
45+
replaceNew: !notNew
46+
}))
47+
} else {
48+
// Push new entity into store.
49+
dispatch(receivedNewEntity({component: 'locationgroupstop', entity: savedEntity}))
50+
}
51+
})
52+
return dispatch(secureFetch(locationGroupUrl, method, data))
53+
.then(res => res.json())
54+
.then(savedEntity => {
55+
dispatch(savedGtfsEntity())
56+
const namespace = getEditorNamespace(feedId, getState())
57+
// Refetch entity and replace in store
58+
if (refetch) {
59+
dispatch(fetchGTFSEntities({
60+
namespace,
61+
id: savedEntity.id,
62+
type: 'locationgroup',
63+
editor: true,
64+
replaceNew: !notNew
65+
}))
66+
} else {
67+
// Push new entity into store.
68+
dispatch(receivedNewEntity({component: 'locationgroup', entity: savedEntity}))
69+
Promise.resolve(savedEntity)
70+
}
71+
})
72+
}
73+
}
74+
1175
export function saveLocation (
1276
feedId: ?string,
1377
location: GtfsLocation,

lib/editor/components/EditorInput.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,14 @@ export default class EditorInput extends React.Component<Props> {
6767
*/
6868
_processFieldChange = (val: any) => {
6969
const {
70-
activeComponent,
7170
activeEntity,
7271
field,
7372
onChange,
7473
updateActiveGtfsEntity
7574
} = this.props
7675
onChange && onChange(val)
76+
const activeComponent = field.activeComponentOverride || this.props.activeComponent
77+
7778
updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
7879
component: activeComponent,
7980
entity: activeEntity,

lib/editor/components/EntityDetails.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ export default class EntityDetails extends Component<Props, State> {
162162
<div>
163163
<Form>
164164
{/* Editor Inputs */}
165-
{renderDefault && currentTable.fields
165+
{renderDefault && [...currentTable.fields, ...(currentTable.extraFields || [])]
166166
.map((field, i) => (
167167
<div
168168
key={`${activeComponent}-${activeEntity.id || ''}-${i}`}
@@ -180,6 +180,7 @@ export default class EntityDetails extends Component<Props, State> {
180180
</Form>
181181
</div>
182182
)
183+
183184
}
184185
</div>
185186
</div>

lib/editor/reducers/data.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ const data = (state: DataState = defaultState, action: Action): DataState => {
7070
console.warn(`No feed info found. Adding feed info with null values.`)
7171
feed.feed_info.push(generateNullProps('feedinfo'))
7272
}
73+
74+
if (feed.location_group_stops && feed.location_group_stops.length === 1 && feed.location_group_stops[0].stop_id) {
75+
feed.location_groups[0].stop_id = feed.location_group_stops[0].stop_id.split(',')
76+
}
77+
7378
return update(state, {
7479
tables: {$set: feed},
7580
status: {$set: {baseFetched: true}}
@@ -266,6 +271,10 @@ const data = (state: DataState = defaultState, action: Action): DataState => {
266271
const {component, editor} = action.payload
267272
const {data} = action.payload
268273

274+
if (data && data.feed.location_group_stops && data.feed.location_group_stops.length === 1 && data.feed.location_group_stops[0].stop_id) {
275+
data.feed.location_groups[0].stop_id = data.feed.location_group_stops[0].stop_id.split(',')
276+
}
277+
269278
if (!editor) {
270279
// Ignore entity fetches if not for the editor (i.e., fetching entities
271280
// for viewing validation result details).

lib/gtfs/util/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ export function getGraphQLFieldsForEntity (type: string, editor: boolean = false
182182
${shapeFields}
183183
}
184184
`
185+
case 'location_group_stop':
186+
return patternLocationGroupFields
185187
default:
186188
return fields
187189
}
@@ -218,6 +220,8 @@ export function getEntityGraphQLRoot (type: string): string {
218220
return 'locations'
219221
case 'locationgroup':
220222
return 'location_groups'
223+
case 'locationgroupstop':
224+
return 'location_group_stops'
221225
default:
222226
return ''
223227
}

lib/manager/actions/versions.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,15 @@ export function fetchGTFSEntities ({
276276
if (!graphQLRoot || !entityIdField) {
277277
console.warn(`No graphql table or filter field for ${type}`)
278278
}
279+
// Location groups are split across two tables, so we need to manually fetch the second
280+
// set here
281+
const locationGroupSupplementalFields = graphQLRoot === 'location_groups' ? `
282+
location_group_stops (limit: -1, id: $id) {
283+
id
284+
location_group_id
285+
stop_id
286+
}
287+
` : ''
279288
const fields = getGraphQLFieldsForEntity(type, editor)
280289
// If fetching for the editor, query on id which is an Int
281290
const query = `
@@ -288,6 +297,7 @@ export function fetchGTFSEntities ({
288297
id
289298
${fields}
290299
}
300+
${locationGroupSupplementalFields}
291301
}
292302
}
293303
`

0 commit comments

Comments
 (0)