Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Location group may 2024 #1015

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions 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 @@ -1178,9 +1188,11 @@
inputType: TEXT
columnWidth: 12
helpContent: "Name of the location group. Must be defined either once, or exhaustively for a single location_group_id."
# TODO: enable validation to match spec (only appear when appropriate)
- name: "location_id"
required: false
inputType: GTFS_STOP_OR_LOCATION_LIST
columnWidth: 12
helpContent: "Identifies a stop or location belonging to the location group."
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
7 changes: 5 additions & 2 deletions lib/editor/actions/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function getCloneProps (entityId: number, component: string, state: AppState) {
patternId: newPatternId,
shapeId: newShapeId,
shapePoints: pattern.shapePoints.map(sp => ({...sp, shapeId: newShapeId})),
patternLocationGroups: pattern.patternLocationGroups && pattern.patternLocationGroups.map(plg => ({...plg, patternId: newPatternId})),
patternLocationGroupStops: pattern.patternLocationGroupStops && pattern.patternLocationGroupStops.map(plg => ({...plg, patternId: newPatternId})),
patternLocations: pattern.patternLocations.map(pl => ({...pl, patternId: newPatternId})),
patternStops: pattern.patternStops.map(ps => ({...ps, patternId: newPatternId}))
}
Expand Down Expand Up @@ -480,9 +480,12 @@ export function fetchBaseGtfs ({
location_groups {
id
location_group_id
location_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
12 changes: 6 additions & 6 deletions lib/editor/actions/map/stopStrategies.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,17 +237,17 @@ export function addStopToPattern (pattern: Pattern, stop: GtfsStop | GtfsLocatio
const {data, editSettings} = getState().editor
const {avoidMotorways, followStreets} = editSettings.present
const {
patternLocationGroups: currentPatternLocationGroups,
patternLocationGroupStops: currentpatternLocationGroupStops,
patternLocations: currentPatternLocations,
patternStops: currentPatternStops,
shapePoints
} = pattern
const patternLocations = clone(currentPatternLocations)
const patternLocationGroups = clone(currentPatternLocationGroups)
const patternLocationGroupStops = clone(currentpatternLocationGroupStops)
const patternStops = clone(currentPatternStops)
const {controlPoints, patternSegments} = getControlPoints(getState())
const hasShapePoints = shapePoints && shapePoints.length > 1
let patternHalts = mergePatternHalts(patternStops, patternLocations, patternLocationGroups)
let patternHalts = mergePatternHalts(patternStops, patternLocations, patternLocationGroupStops)
const newStop = stopToPatternStop(
stop,
(typeof index === 'undefined' || index === null)
Expand All @@ -259,15 +259,15 @@ export function addStopToPattern (pattern: Pattern, stop: GtfsStop | GtfsLocatio
patternStops.push(patternHaltIsStop(newStop))
pattern.shapeId = generateUID()
}
if (patternHaltIsLocationGroup(newStop)) patternLocationGroups.push(patternHaltIsLocationGroup(newStop))
if (patternHaltIsLocationGroup(newStop)) patternLocationGroupStops.push(patternHaltIsLocationGroup(newStop))
if (patternHaltIsLocation(newStop)) patternLocations.push(patternHaltIsLocation(newStop))

if (typeof index === 'undefined' || index === null || index === patternHalts.length) {
// Checking for stop_lat and stop_lon is how we check if we are dealing with
// a stop or a location
if (hasShapePoints && !!stop.stop_lat && !!stop.stop_lon) {
// Push pattern stop to cloned list.
patternHalts = mergePatternHalts(patternStops, patternLocations, patternLocationGroups)
patternHalts = mergePatternHalts(patternStops, patternLocations, patternLocationGroupStops)

// console.log('extending pattern to new stop', stop)
// If a pattern shape already exists, extend it from the current end
Expand All @@ -289,7 +289,7 @@ export function addStopToPattern (pattern: Pattern, stop: GtfsStop | GtfsLocatio
})
} else {
// Push pattern location to cloned list.
patternHalts = mergePatternHalts(patternStops, patternLocations, patternLocationGroups)
patternHalts = mergePatternHalts(patternStops, patternLocations, patternLocationGroupStops)

dispatch(updatePatternStops(pattern, patternHalts))
// Only a stop should be checked, not a location
Expand Down
4 changes: 0 additions & 4 deletions lib/editor/actions/trip.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,6 @@ export function fetchTripsForCalendar (

pickupBookingRuleId: pickup_booking_rule_id
dropOffBookingRuleId: drop_off_booking_rule_id
meanDurationFactor: mean_duration_factor
meanDurationOffset: mean_duration_offset
safeDurationFactor: safe_duration_factor
safeDurationOffset: safe_duration_offset
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/editor/actions/tripPattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export function updatePatternStops (
{
component: 'trippattern',
entity: pattern,
props: { patternStops: stops, patternLocations: locations, patternLocationGroups: locationGroups }
props: { patternStops: stops, patternLocations: locations, patternLocationGroupStops: locationGroups }
}
)
)
Expand Down Expand Up @@ -216,7 +216,7 @@ export function saveTripPattern (feedId: ?string, tripPattern: Pattern) {
// $FlowFixMe FLEX TODO: this type check looks good, but flow is complaining? why?
tripPattern.patternLocations = patternHalts.filter(patternHaltIsLocation)
// $FlowFixMe FLEX TODO: this type check looks good, but flow is complaining? why?
tripPattern.patternLocationGroups = patternHalts.filter(patternHaltIsLocationGroup)
tripPattern.patternLocationGroupStops = patternHalts.filter(patternHaltIsLocationGroup)
if (!tripPattern.shapeId && tripPattern.shapePoints && tripPattern.shapePoints.length > 0) {
// If trip pattern has no shape ID (e.g., if the pattern was imported
// without shapes) but it does have shape points, generate a new shape ID
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
2 changes: 1 addition & 1 deletion lib/editor/components/GtfsEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ type Props = ContainerProps & {
activeEntity: Entity,
activeEntityId: number,
activePattern: Pattern,
activePatternLocationGroups: Array<GtfsLocation>,
activePatternLocations: Array<GtfsLocation>,
activePatternStops: Array<GtfsStop>,
activeSubSubEntity: string,
activepatternLocationGroupStops: Array<GtfsLocation>,
addStopAtIntersection: typeof stopStrategiesActions.addStopAtIntersection,
addStopAtInterval: typeof stopStrategiesActions.addStopAtIntersection,
addStopAtPoint: typeof stopStrategiesActions.addStopAtPoint,
Expand Down
4 changes: 2 additions & 2 deletions lib/editor/components/map/EditorMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ type Props = {
activeEntity: Entity,
activeEntityId: number,
activePattern: Pattern,
activePatternLocationGroups: Array<GtfsLocation>,
activePatternLocations: Array<GtfsLocation>,
activePatternStops: Array<GtfsStop>,
activepatternLocationGroupStops: Array<GtfsLocation>,
addStopAtIntersection: typeof stopStrategiesActions.addStopAtIntersection,
addStopAtInterval: typeof stopStrategiesActions.addStopAtInterval,
addStopAtPoint: typeof stopStrategiesActions.addStopAtPoint,
Expand Down Expand Up @@ -336,7 +336,7 @@ export default class EditorMap extends Component<Props, State> {
/>
<PatternStopsLayer
activePattern={activePattern}
activePatternLocationGroups={this.props.activePatternLocationGroups}
activepatternLocationGroupStops={this.props.activepatternLocationGroupStops}
activePatternLocations={this.props.activePatternLocations}
activePatternStops={this.props.activePatternStops}
addStopToPattern={addStopToPattern}
Expand Down
22 changes: 11 additions & 11 deletions lib/editor/components/map/PatternStopsLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import PatternLocationMarker from './PatternLocationMarker'

type Props = {
activePattern: Pattern,
activePatternLocationGroups: Array<GtfsLocation>,
activePatternLocations: Array<GtfsLocation>,
activePatternStops: Array<GtfsStop>,
activepatternLocationGroupStops: Array<GtfsLocation>,
addStopToPattern: typeof stopStrategiesActions.addStopToPattern,
controlPoints: Array<ControlPoint>,
editSettings: EditSettingsState,
Expand All @@ -41,7 +41,7 @@ export default class PatternStopsLayer extends Component<Props> {
render () {
const {
activePattern,
activePatternLocationGroups,
activepatternLocationGroupStops,
activePatternLocations,
activePatternStops,
addStopToPattern,
Expand All @@ -60,12 +60,12 @@ export default class PatternStopsLayer extends Component<Props> {
if (!activePatternStops || !activePattern || !editSettings.showStops) {
return null
}
const {patternLocations, patternLocationGroups, patternStops} = activePattern
const {patternLocations, patternLocationGroupStops, patternStops} = activePattern

const activeStopNotFound = activePatternStop &&
patternStops.findIndex(ps => ps.id === activePatternStop.id) === -1 &&
patternLocations.findIndex(pl => pl.id === activePatternStop.id) === -1 &&
patternLocationGroups.findIndex(plg => plg.id === activePatternStop.id) === -1
patternLocationGroupStops.findIndex(plg => plg.id === activePatternStop.id) === -1
let cpIndex = 0
let psIndex = 0
const patternStopsWithControlPointIndexes = []
Expand All @@ -85,10 +85,10 @@ export default class PatternStopsLayer extends Component<Props> {
if (cpIndex < patternStops.length) {
console.warn(`Fewer control points (${controlPoints.length}) than pattern stops (${patternStops.length})!`, controlPoints, patternStops)
}
const patternHalts = mergePatternHalts(patternStopsWithControlPointIndexes, patternLocations, patternLocationGroups)
const patternHalts = mergePatternHalts(patternStopsWithControlPointIndexes, patternLocations, patternLocationGroupStops)
return (
<div id='PatternStops'>
{activePatternLocationGroups.map((locationGroup, index) => {
{activepatternLocationGroupStops.map((locationGroup, index) => {
if (!locationGroup.location_id || locationGroup.location_id.length === 0) return null
const halts = typeof locationGroup.location_id === 'string' ? locationGroup.location_id.split(',') : locationGroup.location_id
const activeHalts = halts.reduce((acc, halt) => {
Expand All @@ -103,7 +103,7 @@ export default class PatternStopsLayer extends Component<Props> {
}

return acc
}, {stops: [], locations: [], id: patternLocationGroups[index].id})
}, {stops: [], locations: [], id: patternLocationGroupStops[index].id})
// Render stops and locations separately, but fix the index and patternStop
// to be a location group so that when you click it it opens the location group
// also, disable the buttons in the popup
Expand All @@ -114,9 +114,9 @@ export default class PatternStopsLayer extends Component<Props> {
{...otherProps}
active={activePatternStop.id === activeHalts.id || (activeStopNotFound && activePatternStop.index === index)}
addStopToPattern={addStopToPattern}
index={patternLocationGroups[index].stopSequence}
index={patternLocationGroupStops[index].stopSequence}
key={stop.id} // fallback to index if/when id changes
patternStop={patternLocationGroups[index]}
patternStop={patternLocationGroupStops[index]}
removeStopFromPattern={removeStopFromPattern}
setActiveStop={setActiveStop}
stop={stop}
Expand All @@ -129,10 +129,10 @@ export default class PatternStopsLayer extends Component<Props> {
{...otherProps}
active={activePatternStop.id === activeHalts.id || (activeStopNotFound && activePatternStop.index === index)}
addStopToPattern={addStopToPattern}
index={patternLocationGroups[index].stopSequence}
index={patternLocationGroupStops[index].stopSequence}
key={location.id} // fallback to index if/when id changes
location={location}
patternLocation={patternLocationGroups[index]}
patternLocation={patternLocationGroupStops[index]}
removeStopFromPattern={removeStopFromPattern}
setActiveStop={setActiveStop}
/>
Expand Down
2 changes: 1 addition & 1 deletion lib/editor/components/pattern/CalculateDefaultTimesForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export default class CalculateDefaultTimesForm extends Component<Props, State> {
}
}
}
updatePatternStops(activePattern, [...activePattern.patternLocations, ...activePattern.patternLocationGroups, ...patternStops])
updatePatternStops(activePattern, [...activePattern.patternLocations, ...activePattern.patternLocationGroupStops, ...patternStops])
saveActiveGtfsEntity('trippattern')
}

Expand Down
Loading
Loading