11import clone from 'lodash.clonedeep'
2- import { browserHistory } from 'react-router'
2+ import { browserHistory } from 'react-router'
33import { createAction } from 'redux-actions'
44
55import { ENTITY } from '../constants'
66import { fetchGTFSEntities } from '../../manager/actions/versions'
7- import { secureFetch } from '../../common/actions'
8- import { saveFeedInfo } from './feedInfo'
7+ import { secureFetch } from '../../common/actions'
98import { saveTripPattern } from './tripPattern'
10- import { getGtfsTable , createGtfsEntity , fetchBaseGtfs } from './editor'
11- import { isValidComponent , getEditorNamespace , getTableById , subComponentList , subSubComponentList } from '../util/gtfs'
12- import { getMapFromGtfsStrategy , entityIsNew } from '../util/objects'
9+ import { newGtfsEntity , fetchBaseGtfs } from './editor'
10+ import { isValidComponent , getEditorNamespace , getTableById , subComponentList , subSubComponentList } from '../util/gtfs'
11+ import { getMapFromGtfsStrategy , entityIsNew } from '../util/objects'
1312
1413export function updateEditSetting ( setting , value , activePattern ) {
1514 return {
@@ -20,6 +19,7 @@ export function updateEditSetting (setting, value, activePattern) {
2019 }
2120}
2221
22+ export const clearGtfsContent = createAction ( 'CLEAR_GTFSEDITOR_CONTENT' )
2323const settingActiveGtfsEntity = createAction ( 'SETTING_ACTIVE_GTFS_ENTITY' )
2424
2525export function enterTimetableEditor ( ) {
@@ -72,19 +72,23 @@ export function setActiveGtfsEntity (feedSourceId, component, entityId, subCompo
7272 // stop editing geometry if currently editing
7373 dispatch ( updateEditSetting ( 'editGeometry' , false , null ) )
7474 }
75- if ( entityId === ENTITY . NEW_ID && ( ! activeTable || activeTable . findIndex ( e => e . id === ENTITY . NEW_ID ) === - 1 ) ) {
76- // Create new GTFS entity if id is ENTITY.NEW_ID and no ENTITY.NEW_ID entity exists in table
77- dispatch ( createGtfsEntity ( feedSourceId , component ) )
75+ if (
76+ entityId === ENTITY . NEW_ID &&
77+ ( ! activeTable || activeTable . findIndex ( e => e . id === ENTITY . NEW_ID ) === - 1 )
78+ ) {
79+ // Create new GTFS entity if id is ENTITY.NEW_ID and no ENTITY.NEW_ID
80+ // entity exists in table
81+ dispatch ( newGtfsEntity ( feedSourceId , component ) )
7882 }
7983 const url = constructEditorURL ( feedSourceId , component , entityId , subComponent , subEntityId , subSubComponent , subSubEntityId )
8084 const { locationBeforeTransitions} = getState ( ) . routing
8185 const pathname = locationBeforeTransitions && locationBeforeTransitions . pathname
8286 if ( ! locationBeforeTransitions || ! pathname || pathname !== url ) {
83- // console.log('updating url', url, pathname, pathItems )
87+ console . log ( 'updating url' , url , pathname )
8488 browserHistory . push ( url )
8589 }
8690 const activeEntity = component === 'feedinfo'
87- ? clone ( activeTable )
91+ ? clone ( activeTable ) [ 0 ]
8892 : activeTable && entityId
8993 ? clone ( activeTable . find ( e => e . id === entityId ) )
9094 : null
@@ -122,35 +126,24 @@ export function setActiveGtfsEntity (feedSourceId, component, entityId, subCompo
122126 subSubComponent,
123127 subSubEntityId
124128 } ) )
125- if ( activeSubEntity && component === 'route' ) {
126- dispatch ( setActiveTripPattern ( activeSubEntity ) )
127- }
128- }
129- }
130-
131- function setActiveTripPattern ( pattern ) {
132- return function ( dispatch , getState ) {
133- // const {data} = getState().editor
134- // const stops = getTableById(data.tables, 'stop')
135- // const patternStops = getStopsForPattern(pattern, stops)
136- // const activeColumns = getTimetableColumns(pattern, patternStops)
137- // dispatch(settingActiveTripPattern({pattern, columns, patternStops}))
138129 }
139130}
140131
141132function constructEditorURL ( feedSourceId , component , entityId , subComponent , subEntityId , subSubComponent , subSubEntityId ) {
142- const pathItems = [ 'feed' , feedSourceId , 'edit' , component , entityId , subComponent , subEntityId , subSubComponent , subSubEntityId ] . filter ( item => item )
133+ const pathItems = [ 'feed' , feedSourceId , 'edit' , component , entityId , subComponent , subEntityId , subSubComponent , subSubEntityId ]
134+ // Filter out any null or undefined items
135+ . filter ( item => item )
143136 let url = '/' + pathItems . join ( '/' )
144- // ensure component is valid
145137 if ( component && ! isValidComponent ( component ) ) {
138+ // If component is not valid, go to editor root.
146139 console . warn ( `"${ component } " is not a valid URL component path` )
147140 url = `/feed/${ feedSourceId } /edit/`
148141 } else if ( subComponent && subComponentList . indexOf ( subComponent ) === - 1 ) {
149- // ensure subComponent is valid
142+ // If subComponent is not valid, go to active entity
150143 console . warn ( `"${ subComponent } " is not a valid URL subComponent path` )
151144 url = `/feed/${ feedSourceId } /edit/${ component } /${ entityId } /`
152145 } else if ( subSubComponent && subSubComponentList . indexOf ( subSubComponent ) === - 1 ) {
153- // ensure subSubComponent is valid
146+ // If subSubComponent is not valid, go to sub entity
154147 console . warn ( `"${ subSubComponent } " is not a valid URL subSubComponent path` )
155148 url = `/feed/${ feedSourceId } /edit/${ component } /${ entityId } /${ subComponent } /${ subEntityId } /`
156149 }
@@ -173,11 +166,6 @@ export function saveActiveGtfsEntity (component, optionalEntity) {
173166 entity = optionalEntity || active . subEntity // route.tripPatterns.find(p => p.id === patternId)
174167 saveStrategy = saveTripPattern
175168 break
176- // FIXME
177- case 'feedinfo' :
178- feedId = entity . id || active . feedSourceId
179- saveStrategy = saveFeedInfo
180- break
181169 default :
182170 // Default method for agencies, stops, routes, fares, calendars.
183171 // Trip patterns and feed info are handled above. Trips are handled in
@@ -190,6 +178,15 @@ export function saveActiveGtfsEntity (component, optionalEntity) {
190178 }
191179}
192180
181+ /**
182+ * Generic method for saving an entity using REST endpoint. The only entity
183+ * types with unique save methods are trip patterns and trips (handled in timetable
184+ * actions).
185+ *
186+ * This method determines the URL from entity type (component), maps the entity
187+ * data into the required format (primarily updates fields to snake_case), and
188+ * after performing PUT request re-fetches the entity.
189+ */
193190export function saveEntity ( feedId , entity , component ) {
194191 return function ( dispatch , getState ) {
195192 const notNew = ! entityIsNew ( entity )
@@ -201,24 +198,16 @@ export function saveEntity (feedId, entity, component) {
201198 const data = mappingStrategy ( entity )
202199 return dispatch ( secureFetch ( url , method , data ) )
203200 . then ( res => res . json ( ) )
204- . then ( e => {
205- // FIXME: Instead of getting new table, should we receive entity and send
206- // to reducer? For example:
207- // dispatch(receiveStop({feedId, stop: newStop}))
208- // if (stopId === ENTITY.NEW_ID) {
209- // // Only set active if stop.id === ENTITY.NEW_ID.
210- // // If id is undefined, do not set active entity
211- // dispatch(deletingStop(feedId, stop))
212- // dispatch(setActiveGtfsEntity(feedId, 'stop', `${newStop.id}`))
213- // }
214- return dispatch ( getGtfsTable ( component , feedId ) )
215- . then ( entities => {
216- if ( entity . id === ENTITY . NEW_ID ) {
217- // If we just created a new entity, update active entity with
218- // it's server-created id.
219- return dispatch ( setActiveGtfsEntity ( feedId , component , e . id ) )
220- }
221- } )
201+ . then ( savedEntity => {
202+ const namespace = getEditorNamespace ( feedId , getState ( ) )
203+ // Refetch entity and replace in store
204+ dispatch ( fetchGTFSEntities ( {
205+ namespace,
206+ id : savedEntity . id ,
207+ type : component ,
208+ editor : true ,
209+ replaceNew : ! notNew
210+ } ) )
222211 } )
223212 }
224213}
@@ -231,22 +220,26 @@ export const deletingEntity = createAction('DELETING_ENTITY')
231220export function deleteGtfsEntity ( feedId , component , entityId , routeId ) {
232221 return function ( dispatch , getState ) {
233222 const namespace = getEditorNamespace ( feedId , getState ( ) )
234- dispatch ( deletingEntity ( { namespace, feedId, component, entityId} ) )
223+ dispatch ( deletingEntity ( { namespace, feedId, component, entityId, routeId } ) )
235224 if ( entityId === ENTITY . NEW_ID ) {
236225 // Entity is new/unsaved. Overwrite current table with existing entities.
237226 // FIXME: we should just remove the ENTITY.NEW_ID entity from the store. This is a
238227 // waste of network traffic (especially for large feeds)
239228 return dispatch ( fetchBaseGtfs ( { namespace, component} ) )
240229 }
241- const entityPath = component === 'trippattern' ? 'pattern' : component
230+ const entityPath = component === 'trippattern'
231+ ? 'pattern'
232+ : component === 'fare' ? 'fareattribute' : component
242233 const url = `/api/editor/secure/${ entityPath } /${ entityId } ?feedId=${ feedId } `
243234 return dispatch ( secureFetch ( url , 'delete' ) )
244235 . then ( response => response . json ( ) )
245236 . then ( json => {
246237 if ( component === 'trippattern' && routeId ) {
238+ console . log ( 'fetching trip patterns' )
247239 // Replace trip patterns for route
248- dispatch ( fetchGTFSEntities ( { namespace, id : routeId , type : component , editor : true } ) )
240+ return dispatch ( fetchGTFSEntities ( { namespace, id : routeId , type : 'route' , editor : true } ) )
249241 } else {
242+ console . log ( 'fetching base gtfs' )
250243 // Replace entire table
251244 return dispatch ( fetchBaseGtfs ( { namespace, component} ) )
252245 }
@@ -270,9 +263,3 @@ export function resetActiveGtfsEntity (entity, component) {
270263 component
271264 }
272265}
273-
274- export function clearGtfsContent ( ) {
275- return {
276- type : 'CLEAR_GTFSEDITOR_CONTENT'
277- }
278- }
0 commit comments