diff --git a/gtfs.yml b/gtfs.yml index bb59940f3..4348c4c25 100644 --- a/gtfs.yml +++ b/gtfs.yml @@ -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 @@ -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" + diff --git a/lib/editor/actions/active.js b/lib/editor/actions/active.js index 12c9925a3..ed2437653 100644 --- a/lib/editor/actions/active.js +++ b/lib/editor/actions/active.js @@ -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( @@ -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 diff --git a/lib/editor/actions/editor.js b/lib/editor/actions/editor.js index dd55830b8..1482c67d0 100644 --- a/lib/editor/actions/editor.js +++ b/lib/editor/actions/editor.js @@ -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})) } @@ -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 diff --git a/lib/editor/actions/location.js b/lib/editor/actions/location.js index 9266005d9..aa0338466 100644 --- a/lib/editor/actions/location.js +++ b/lib/editor/actions/location.js @@ -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, diff --git a/lib/editor/actions/map/stopStrategies.js b/lib/editor/actions/map/stopStrategies.js index 7958cd8ec..205e6c848 100644 --- a/lib/editor/actions/map/stopStrategies.js +++ b/lib/editor/actions/map/stopStrategies.js @@ -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) @@ -259,7 +259,7 @@ 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) { @@ -267,7 +267,7 @@ export function addStopToPattern (pattern: Pattern, stop: GtfsStop | GtfsLocatio // 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 @@ -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 diff --git a/lib/editor/actions/trip.js b/lib/editor/actions/trip.js index 11e556657..00262fc6f 100644 --- a/lib/editor/actions/trip.js +++ b/lib/editor/actions/trip.js @@ -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 } } } diff --git a/lib/editor/actions/tripPattern.js b/lib/editor/actions/tripPattern.js index faa802f1e..d4182e6a9 100644 --- a/lib/editor/actions/tripPattern.js +++ b/lib/editor/actions/tripPattern.js @@ -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 } } ) ) @@ -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 diff --git a/lib/editor/components/EditorInput.js b/lib/editor/components/EditorInput.js index 63e4737f9..20efcc149 100644 --- a/lib/editor/components/EditorInput.js +++ b/lib/editor/components/EditorInput.js @@ -67,13 +67,14 @@ export default class EditorInput extends React.Component { */ _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, diff --git a/lib/editor/components/EntityDetails.js b/lib/editor/components/EntityDetails.js index 5c2bba806..2884c5490 100644 --- a/lib/editor/components/EntityDetails.js +++ b/lib/editor/components/EntityDetails.js @@ -162,7 +162,7 @@ export default class EntityDetails extends Component {
{/* Editor Inputs */} - {renderDefault && currentTable.fields + {renderDefault && [...currentTable.fields, ...(currentTable.extraFields || [])] .map((field, i) => (
{
) + }
diff --git a/lib/editor/components/GtfsEditor.js b/lib/editor/components/GtfsEditor.js index 8cca8097d..92c891e93 100644 --- a/lib/editor/components/GtfsEditor.js +++ b/lib/editor/components/GtfsEditor.js @@ -54,10 +54,10 @@ type Props = ContainerProps & { activeEntity: Entity, activeEntityId: number, activePattern: Pattern, - activePatternLocationGroups: Array, activePatternLocations: Array, activePatternStops: Array, activeSubSubEntity: string, + activepatternLocationGroupStops: Array, addStopAtIntersection: typeof stopStrategiesActions.addStopAtIntersection, addStopAtInterval: typeof stopStrategiesActions.addStopAtIntersection, addStopAtPoint: typeof stopStrategiesActions.addStopAtPoint, diff --git a/lib/editor/components/map/EditorMap.js b/lib/editor/components/map/EditorMap.js index 1965fde8b..f9a6ac2ce 100644 --- a/lib/editor/components/map/EditorMap.js +++ b/lib/editor/components/map/EditorMap.js @@ -42,9 +42,9 @@ type Props = { activeEntity: Entity, activeEntityId: number, activePattern: Pattern, - activePatternLocationGroups: Array, activePatternLocations: Array, activePatternStops: Array, + activepatternLocationGroupStops: Array, addStopAtIntersection: typeof stopStrategiesActions.addStopAtIntersection, addStopAtInterval: typeof stopStrategiesActions.addStopAtInterval, addStopAtPoint: typeof stopStrategiesActions.addStopAtPoint, @@ -336,7 +336,7 @@ export default class EditorMap extends Component { /> , activePatternLocations: Array, activePatternStops: Array, + activepatternLocationGroupStops: Array, addStopToPattern: typeof stopStrategiesActions.addStopToPattern, controlPoints: Array, editSettings: EditSettingsState, @@ -41,7 +41,7 @@ export default class PatternStopsLayer extends Component { render () { const { activePattern, - activePatternLocationGroups, + activepatternLocationGroupStops, activePatternLocations, activePatternStops, addStopToPattern, @@ -60,12 +60,12 @@ export default class PatternStopsLayer extends Component { 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 = [] @@ -85,10 +85,10 @@ export default class PatternStopsLayer extends Component { 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 (
- {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) => { @@ -103,7 +103,7 @@ export default class PatternStopsLayer extends Component { } 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 @@ -114,9 +114,9 @@ export default class PatternStopsLayer extends Component { {...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} @@ -129,10 +129,10 @@ export default class PatternStopsLayer extends Component { {...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} /> diff --git a/lib/editor/components/pattern/CalculateDefaultTimesForm.js b/lib/editor/components/pattern/CalculateDefaultTimesForm.js index a6a6950a6..13b821927 100644 --- a/lib/editor/components/pattern/CalculateDefaultTimesForm.js +++ b/lib/editor/components/pattern/CalculateDefaultTimesForm.js @@ -86,7 +86,7 @@ export default class CalculateDefaultTimesForm extends Component { } } } - updatePatternStops(activePattern, [...activePattern.patternLocations, ...activePattern.patternLocationGroups, ...patternStops]) + updatePatternStops(activePattern, [...activePattern.patternLocations, ...activePattern.patternLocationGroupStops, ...patternStops]) saveActiveGtfsEntity('trippattern') } diff --git a/lib/editor/components/pattern/PatternStopCard.js b/lib/editor/components/pattern/PatternStopCard.js index 28d50c570..165f54260 100644 --- a/lib/editor/components/pattern/PatternStopCard.js +++ b/lib/editor/components/pattern/PatternStopCard.js @@ -75,10 +75,6 @@ type State = { flexDefaultZoneTime: number, initialDwellTime: number, initialTravelTime: number, - meanDurationFactor: number, - meanDurationOffset: number, - safeDurationFactor: number, - safeDurationOffset: number, update: boolean } @@ -320,14 +316,6 @@ class PatternStopContents extends Component { flexDefaultZoneTime: patternStop.flexDefaultZoneTime, // $FlowFixMe flow doesn't like our "type check" flexDefaultTravelTime: patternStop.flexDefaultTravelTime, - // $FlowFixMe flow doesn't like our "type check" - meanDurationFactor: patternStop.meanDurationFactor, - // $FlowFixMe flow doesn't like our "type check" - meanDurationOffset: patternStop.meanDurationOffset, - // $FlowFixMe flow doesn't like our "type check" - safeDurationFactor: patternStop.safeDurationFactor, - // $FlowFixMe flow doesn't like our "type check" - safeDurationOffset: patternStop.safeDurationOffset, update: false }) } @@ -635,6 +623,23 @@ class PatternStopContents extends Component { const locationRows = feedSource.flexUIFeaturesEnabled && (
+ + + + {patternStopCardMessages('PatternStopContents.timepoint')} + + + + + + @@ -662,54 +667,6 @@ class PatternStopContents extends Component { {this._renderPickupDropOffTypes(true)} - - - - {patternStopCardMessages('PatternStopContents.meanDurationFactor')} - - - - - - {patternStopCardMessages('PatternStopContents.meanDurationOffset')} - - - - - - - - {patternStopCardMessages('PatternStopCardMessages.safeDurationFactor')} - - - - - - {patternStopCardMessages('PatternStopCardMessages.safeDurationOffset')} - - - - {bookingRuleRow}
) @@ -718,43 +675,7 @@ class PatternStopContents extends Component { if (active) { innerDiv = (
- - - - {patternStopCardMessages('PatternStopContents.timepoint')} - - - - - - {isStop ? stopRows : locationRows} - - - - - {patternStopCardMessages('PatternStopContents.stopHeadsignText')} - - - - - {!activePatternHasLocations(activePattern) && }
) diff --git a/lib/editor/components/pattern/PatternStopsPanel.js b/lib/editor/components/pattern/PatternStopsPanel.js index 1c29cdda9..5d2f3515f 100644 --- a/lib/editor/components/pattern/PatternStopsPanel.js +++ b/lib/editor/components/pattern/PatternStopsPanel.js @@ -112,10 +112,10 @@ export default class PatternStopsPanel extends Component { const {patternStopCandidate} = this.state const patternHasStops = (activePattern.patternStops && activePattern.patternStops.length > 0) || (activePattern.patternLocations && - activePattern.patternLocations.length > 0) || (activePattern.patternLocationGroups && - activePattern.patternLocationGroups.length > 0) + activePattern.patternLocations.length > 0) || (activePattern.patternLocationGroupStops && + activePattern.patternLocationGroupStops.length > 0) - const patternHaltCount = (activePattern.patternStops.length || 0) + (activePattern.patternLocations.length || 0) + (activePattern.patternLocationGroups.length || 0) + const patternHaltCount = (activePattern.patternStops.length || 0) + (activePattern.patternLocations.length || 0) + (activePattern.patternLocationGroupStops.length || 0) return (
{ render () { const {active, pattern} = this.props - const {name, patternLocations, patternLocationGroups, patternStops} = pattern + const {name, patternLocations, patternLocationGroupStops, patternStops} = pattern const rowStyle = { paddingTop: 5, paddingBottom: 5 @@ -161,11 +161,11 @@ class PatternRow extends Component { } let patternName = '[Unnamed]' if (name) { - const showStopCount = patternStops || patternLocations || patternLocationGroups + const showStopCount = patternStops || patternLocations || patternLocationGroupStops const stopCount = showStopCount ? ( (patternStops ? patternStops.length : 0) + (patternLocations ? patternLocations.length : 0) + - (patternLocationGroups ? patternLocationGroups.length : 0) + (patternLocationGroupStops ? patternLocationGroupStops.length : 0) ) : 0 patternName = `${`${name.length > 29 ? name.substr(0, 29) + '…' diff --git a/lib/editor/components/pattern/TripPatternListControls.js b/lib/editor/components/pattern/TripPatternListControls.js index 9dfe1cf52..0f6153c00 100644 --- a/lib/editor/components/pattern/TripPatternListControls.js +++ b/lib/editor/components/pattern/TripPatternListControls.js @@ -53,7 +53,7 @@ export default class TripPatternListControls extends Component { directionId: null, patternStops: [], patternLocations: [], - patternLocationGroups: [], + patternLocationGroupStops: [], name: 'New Pattern', // FIXME should we be using some other method to generate ID? patternId: generateUID(), diff --git a/lib/editor/components/pattern/TripPatternViewer.js b/lib/editor/components/pattern/TripPatternViewer.js index ec3c15e85..444bc40ae 100644 --- a/lib/editor/components/pattern/TripPatternViewer.js +++ b/lib/editor/components/pattern/TripPatternViewer.js @@ -37,7 +37,7 @@ export default class TripPatternViewer extends Component { if (!activePattern) return null activePattern.patternLocations = activePattern.patternLocations.map(pl => { return {...pl, id: `${pl.locationId}${pl.stopSequence}`} }) - activePattern.patternLocationGroups = activePattern.patternLocationGroups.map(plg => { return {...plg, id: `${plg.locationGroupId}${plg.stopSequence}`} }) + activePattern.patternLocationGroupStops = activePattern.patternLocationGroupStops.map(plg => { return {...plg, id: `${plg.locationGroupId}${plg.stopSequence}`} }) activePattern.patternStops = activePattern.patternStops.map(ps => { return {...ps, id: `${ps.stopId}${ps.stopSequence}`} }) return (
diff --git a/lib/editor/components/timetable/TimetableEditor.js b/lib/editor/components/timetable/TimetableEditor.js index ab9950f6c..1f13cb946 100644 --- a/lib/editor/components/timetable/TimetableEditor.js +++ b/lib/editor/components/timetable/TimetableEditor.js @@ -247,11 +247,6 @@ export default class TimetableEditor extends Component { objectPath.set(newRow, `stopTimes.${i}.timepoint`, halt.timepoint || 0) objectPath.set(newRow, `stopTimes.${i}.stopHeadsign`, halt.stopHeadsign) objectPath.set(newRow, `stopTimes.${i}.shapeDistTraveled`, halt.shapeDistTraveled) - // set some new flex fields (null for traditional stops) - objectPath.set(newRow, `stopTimes.${i}.meanDurationFactor`, halt.meanDurationFactor || null) - objectPath.set(newRow, `stopTimes.${i}.meanDurationOffset`, halt.meanDurationOffset || null) - objectPath.set(newRow, `stopTimes.${i}.safeDurationFactor`, halt.safeDurationFactor || null) - objectPath.set(newRow, `stopTimes.${i}.safeDurationOffset`, halt.safeDurationOffset || null) // Use pattern stop index to set stop sequence. Stop sequences should all // be zero-based and incrementing in the editor, but in the case that // they're not (e.g., due to a bad import) simply default to the index. diff --git a/lib/editor/containers/ActiveGtfsEditor.js b/lib/editor/containers/ActiveGtfsEditor.js index 1ae462341..98542d854 100644 --- a/lib/editor/containers/ActiveGtfsEditor.js +++ b/lib/editor/containers/ActiveGtfsEditor.js @@ -48,7 +48,7 @@ import { } from '../actions/editor' import {createSnapshot, loadFeedVersionForEditing} from '../actions/snapshots' import {findProjectByFeedSource} from '../../manager/util' -import {getActivePatternLocations, getActivePatternLocationGroups, getActivePatternStops, getControlPoints, getValidationErrors} from '../selectors' +import {getActivePatternLocations, getActivepatternLocationGroupStops, getActivePatternStops, getControlPoints, getValidationErrors} from '../selectors' import {getTableById, getIdsFromParams} from '../util/gtfs' import type {AppState, RouterProps} from '../../types/reducers' @@ -101,14 +101,14 @@ const mapStateToProps = (state: AppState, ownProps: Props) => { const feedIsLocked = !state.editor.data.lock.sessionId const activePatternStops = getActivePatternStops(state) const activePatternLocations = getActivePatternLocations(state) - const activePatternLocationGroups = getActivePatternLocationGroups(state) + const activepatternLocationGroupStops = getActivepatternLocationGroupStops(state) return { activeComponent, activeEntity, activeEntityId, activePattern, activePatternLocations, - activePatternLocationGroups, + activepatternLocationGroupStops, activePatternStops, activeSubSubEntity, controlPoints, diff --git a/lib/editor/reducers/data.js b/lib/editor/reducers/data.js index cf258f9b0..b3e7a274f 100644 --- a/lib/editor/reducers/data.js +++ b/lib/editor/reducers/data.js @@ -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}} @@ -266,8 +271,8 @@ const data = (state: DataState = defaultState, action: Action): DataState => { const {component, editor} = action.payload const {data} = action.payload - if (data.feed.location_groups && data.feed.location_groups.length === 1 && data.feed.location_groups[0].location_id) { - data.feed.location_groups[0].location_id = data.feed.location_groups[0].location_id.split(',') + 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) { diff --git a/lib/editor/selectors/index.js b/lib/editor/selectors/index.js index 6a30d827e..8a804a07e 100644 --- a/lib/editor/selectors/index.js +++ b/lib/editor/selectors/index.js @@ -162,17 +162,17 @@ export const getActivePatternLocations = createSelector( return patternLocations } ) -export const getActivePatternLocationGroups = createSelector( +export const getActivepatternLocationGroupStops = createSelector( [ getActivePattern, getLocationGroups ], (pattern, locationGroups) => { - if (!pattern || !locationGroups || !pattern.patternLocationGroups) return null - const patternLocationGroups = pattern.patternLocationGroups.map(pl => { + if (!pattern || !locationGroups || !pattern.patternLocationGroupStops) return null + const patternLocationGroupStops = pattern.patternLocationGroupStops.map(pl => { return locationGroups.find(lg => lg.location_group_id === pl.locationGroupId) }) - return patternLocationGroups + return patternLocationGroupStops } ) export const getActivePatternTripCount = createSelector( diff --git a/lib/editor/util/location.js b/lib/editor/util/location.js index 0f234783e..e4ae11752 100644 --- a/lib/editor/util/location.js +++ b/lib/editor/util/location.js @@ -45,7 +45,7 @@ export const patternHaltIsStop = ( // $FlowFixMe Flow doesn't understand type check patternStopOrLocation.hasOwnProperty('stopId') ? patternStopOrLocation : undefined -export const activePatternHasLocations = (pattern: Pattern) => pattern.patternLocations.length > 0 || pattern.patternLocationGroups.length > 0 +export const activePatternHasLocations = (pattern: Pattern) => pattern.patternLocations.length > 0 || pattern.patternLocationGroupStops.length > 0 export const getLayerCoords = (isPolygon: boolean, coordSet: any) => isPolygon ? coordSet[0].map(convertLatLngToArray) : coordSet.map(convertLatLngToArray) diff --git a/lib/editor/util/map.js b/lib/editor/util/map.js index 47d7df9aa..bc11529cc 100644 --- a/lib/editor/util/map.js +++ b/lib/editor/util/map.js @@ -785,12 +785,8 @@ export function stopToPatternStop ( id: generateUID(), // $FlowFixMe Flow doesn't appreciate our type check above locationGroupId: stop.location_group_id, - meanDurationFactor: 0, - meanDurationOffset: 0, pickupBookingRuleId: null, pickupType: 2, - safeDurationFactor: 0, - safeDurationOffset: 0, stopHeadsign: '', stopSequence, timepoint: null @@ -807,12 +803,8 @@ export function stopToPatternStop ( id: generateUID(), // $FlowFixMe Flow doesn't appreciate our type check above locationId: stop.location_id, - meanDurationFactor: 0, - meanDurationOffset: 0, pickupBookingRuleId: null, pickupType: 2, - safeDurationFactor: 0, - safeDurationOffset: 0, stopHeadsign: '', stopSequence, timepoint: null diff --git a/lib/editor/util/validation/validation.js b/lib/editor/util/validation/validation.js index fa9cfb400..772b997fa 100644 --- a/lib/editor/util/validation/validation.js +++ b/lib/editor/util/validation/validation.js @@ -9,7 +9,8 @@ import type {EditorTables} from '../../types/reducers' import { getComponentMessages } from '../../../common/util/config' import {getTableById} from '../gtfs' -import type {validationIssue, EditorValidationIssue} from './common' +import type {EditorValidationIssue} from './common' +import {validationIssue} from './common' import {validateBookingRule} from './bookingRuleValidation' import { EXCEPTION_EXEMPLARS } from '..' diff --git a/lib/gtfs/util/index.js b/lib/gtfs/util/index.js index 9b3219ba2..83aadc681 100644 --- a/lib/gtfs/util/index.js +++ b/lib/gtfs/util/index.js @@ -103,14 +103,10 @@ export function getGraphQLFieldsForEntity (type: string, editor: boolean = false drop_off_booking_rule_id flex_default_travel_time flex_default_zone_time - mean_duration_factor - mean_duration_offset - safe_duration_factor - safe_duration_offset stop_headsign }` - const patternLocationGroupFields = `pattern_location_groups (limit: -1) { + const patternLocationGroupFields = `pattern_location_group_stops (limit: -1) { id location_group_id stop_sequence @@ -123,10 +119,6 @@ export function getGraphQLFieldsForEntity (type: string, editor: boolean = false drop_off_booking_rule_id flex_default_travel_time flex_default_zone_time - mean_duration_factor - mean_duration_offset - safe_duration_factor - safe_duration_offset stop_headsign }` @@ -190,6 +182,8 @@ export function getGraphQLFieldsForEntity (type: string, editor: boolean = false ${shapeFields} } ` + case 'location_group_stop': + return patternLocationGroupFields default: return fields } @@ -226,6 +220,8 @@ export function getEntityGraphQLRoot (type: string): string { return 'locations' case 'locationgroup': return 'location_groups' + case 'locationgroupstop': + return 'location_group_stops' default: return '' } @@ -280,13 +276,13 @@ export function getEntityTableString (type: string): string { export function mergePatternHalts ( patternStops: Array, patternLocations: Array, - patternLocationGroups: Array + patternLocationGroupStops: Array ): Array { - return [...patternLocations, ...patternLocationGroups, ...patternStops] + return [...patternLocations, ...patternLocationGroupStops, ...patternStops] .sort((a, b) => a.stopSequence - b.stopSequence) } export function mergePatternHaltsOfPattern (pattern: Pattern) { - return mergePatternHalts(pattern.patternStops, pattern.patternLocations, pattern.patternLocationGroups) + return mergePatternHalts(pattern.patternStops, pattern.patternLocations, pattern.patternLocationGroupStops) } /** diff --git a/lib/manager/actions/versions.js b/lib/manager/actions/versions.js index fe0bc9d35..75dd8bd4a 100644 --- a/lib/manager/actions/versions.js +++ b/lib/manager/actions/versions.js @@ -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 = ` @@ -288,6 +297,7 @@ export function fetchGTFSEntities ({ id ${fields} } + ${locationGroupSupplementalFields} } } ` diff --git a/lib/types/index.js b/lib/types/index.js index 4935789b7..9c0a144e7 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -634,12 +634,8 @@ export type PatternLocation = { flexDefaultZoneTime: number, id?: string | number, locationId: string, - meanDurationFactor?: ?number, - meanDurationOffset?: ?number, pickupBookingRuleId?: ?string, pickupType?: number, - safeDurationFactor?: ?number, - safeDurationOffset?: ?number, stopHeadsign?: string, stopSequence: number, timepoint?: ?number @@ -654,12 +650,8 @@ export type PatternLocationGroup = { flexDefaultZoneTime: number, id: string | number, locationGroupId: string, - meanDurationFactor?: ?number, - meanDurationOffset?: ?number, pickupBookingRuleId?: ?string, pickupType?: number, - safeDurationFactor?: ?number, - safeDurationOffset?: ?number, stopHeadsign: ?string, stopSequence: number, timepoint?: ?number @@ -684,7 +676,7 @@ export type Pattern = {| id: number, name: string, patternId: string, - patternLocationGroups: Array, + patternLocationGroupStops: Array, patternLocations: Array, patternStops: Array, routeId: string, @@ -1010,11 +1002,7 @@ export type StopTime = { dropOffBookingRuleId?: string, endPickupDropOffWindow?: number, id: number, - meanDurationFactor?: number, - meanDurationOffset?: number, pickupBookingRuleId?: string, - safeDurationFactor?: number, - safeDurationOffset?: number, shapeDistTraveled?: number, shape_dist_traveled: number, startPickupDropOffWindow?: number, diff --git a/lib/types/reducers.js b/lib/types/reducers.js index c65019ea0..3214dccbc 100644 --- a/lib/types/reducers.js +++ b/lib/types/reducers.js @@ -156,7 +156,6 @@ export type EditorTables = { location_groups: Array<{ location_group_id: string, location_group_name: string, - location_id: string }>, locations: Array<{ id: number,