@@ -15,6 +15,8 @@ export type EditorValidationIssue = {
1515 reason : string
1616}
1717
18+ const EMPTY_FIELD_REASON = 'Required field must not be empty'
19+
1820export function doesNotExist ( value : any ) : boolean {
1921 return value === '' || value === null || typeof value === 'undefined'
2022}
@@ -39,7 +41,6 @@ export function validate (
3941 const isOptionalAndEmpty = ! required && valueDoesNotExist
4042 const agencies = getTableById ( tableData , 'agency' )
4143 let locationType : ?number = null
42- let reason = 'Required field must not be empty'
4344
4445 // entity.locationtype is a string. Convert to number for conditinals later on.
4546 if ( entity && entity . location_type !== null ) {
@@ -52,13 +53,21 @@ export function validate (
5253 result : false | EditorValidationIssue
5354 }
5455
56+ /**
57+ * Construct an EditorValidationIssue for the field name and reason (defaults to
58+ * empty field message).
59+ */
60+ function validationIssue ( reason = EMPTY_FIELD_REASON , field = name ) {
61+ return { field, invalid : true , reason}
62+ }
63+
5564 /**
5665 * Checks whether value is a positive number
5766 */
5867 function checkPositiveNumber ( ) : CheckPositiveOutput {
5968 if ( isRequiredButEmpty ) {
6069 return {
61- result : { field : name , invalid : isRequiredButEmpty , reason }
70+ result : validationIssue ( )
6271 }
6372 } else if ( isOptionalAndEmpty ) {
6473 return {
@@ -70,14 +79,14 @@ export function validate (
7079 // make sure value is parseable to a number
7180 if ( isNaN ( num ) ) {
7281 return {
73- result : { field : name , invalid : true , reason : 'Field must be a valid number' }
82+ result : validationIssue ( 'Field must be a valid number' )
7483 }
7584 }
7685
7786 // make sure value is positive
7887 if ( num < 0 ) {
7988 return {
80- result : { field : name , invalid : true , reason : 'Field must be a positive number' }
89+ result : validationIssue ( 'Field must be a positive number' )
8190 }
8291 }
8392
@@ -112,21 +121,20 @@ export function validate (
112121 idList . length > 1 &&
113122 valueDoesNotExist
114123 ) {
115- reason = 'Identifier is required if more than one agency exists'
116- return { field : name , invalid : isRequiredButEmpty , reason}
124+ return validationIssue ( 'Identifier is required if more than one agency exists' )
117125 }
118126 if ( isRequiredButEmpty || isNotUnique ) {
127+ let reason
119128 if ( isNotUnique ) {
120129 reason = 'Identifier must be unique'
121130 }
122- return { field : name , invalid : isRequiredButEmpty || isNotUnique , reason}
131+ return validationIssue ( reason )
123132 } else {
124133 return false
125134 }
126135 case 'TEXT' :
127136 if ( name === 'stop_name' && locationType !== null && ( typeof locationType === 'number' && locationType <= 2 ) ) {
128- reason = 'Stop name is required for your current location type'
129- return { field : name , invalid : isOptionalAndEmpty , reason}
137+ return validationIssue ( 'Stop name is required for your current location type' )
130138 }
131139 if ( name === 'route_short_name' && ! value && entity && entity . route_long_name ) {
132140 return false
@@ -139,7 +147,7 @@ export function validate (
139147 return false
140148 } else {
141149 if ( isRequiredButEmpty ) {
142- return { field : name , invalid : isRequiredButEmpty , reason }
150+ return validationIssue ( )
143151 } else {
144152 return false
145153 }
@@ -150,82 +158,77 @@ export function validate (
150158 case 'GTFS_FARE' :
151159 case 'GTFS_SERVICE' :
152160 if ( isRequiredButEmpty ) {
153- return { field : name , invalid : isRequiredButEmpty , reason }
161+ return validationIssue ( )
154162 } else {
155163 return false
156164 }
157165 case 'URL' :
158166 const isNotUrl = value && ! validator . isURL ( value )
159167 if ( isRequiredButEmpty || isNotUrl ) {
168+ let reason
160169 if ( isNotUrl ) {
161170 reason = 'Field must contain valid URL.'
162171 }
163- return { field : name , invalid : isRequiredButEmpty || isNotUrl , reason}
172+ return validationIssue ( reason )
164173 } else {
165174 return false
166175 }
167176 case 'EMAIL' :
168177 const isNotEmail = value && ! validator . isEmail ( value )
169178 if ( isRequiredButEmpty || isNotEmail ) {
179+ let reason
170180 if ( isNotEmail ) {
171181 reason = 'Field must contain valid email address.'
172182 }
173- return { field : name , invalid : isRequiredButEmpty || isNotEmail , reason}
183+ return validationIssue ( reason )
174184 } else {
175185 return false
176186 }
177187 case 'GTFS_ZONE' :
178188 if ( isRequiredButEmpty ) {
179- return { field : name , invalid : isRequiredButEmpty , reason }
189+ return validationIssue ( )
180190 } else {
181191 return false
182192 }
183193 case 'TIMEZONE' :
184194 if ( isRequiredButEmpty ) {
185- return { field : name , invalid : isRequiredButEmpty , reason }
195+ return validationIssue ( )
186196 } else {
187197 return false
188198 }
189199 case 'LANGUAGE' :
190200 if ( isRequiredButEmpty ) {
191- return { field : name , invalid : isRequiredButEmpty , reason }
201+ return validationIssue ( )
192202 } else {
193203 return false
194204 }
195205 case 'LATITUDE' :
196206 const isNotLat = value > 90 || value < - 90
197207 if ( isNotLat ) {
198- reason = 'Field must be valid latitude.'
199- return { field : name , invalid : isNotLat , reason}
208+ return validationIssue ( name , 'Field must be valid latitude.' )
200209 }
201210 if ( isOptionalAndEmpty && locationType !== null && ( typeof locationType === 'number' && locationType <= 2 ) ) {
202- reason = 'Latitude and Longitude are required for your current location type'
203- return { field : name , invalid : isOptionalAndEmpty , reason}
211+ return validationIssue ( 'Latitude and Longitude are required for your current location type' )
204212 }
205213 return false
206214 case 'LONGITUDE' :
207215 const isNotLng = value > 180 || value < - 180
208216 if ( isNotLng ) {
209- reason = 'Field must be valid longitude.'
210- return { field : name , invalid : isOptionalAndEmpty || isNotLng , reason}
217+ return validationIssue ( 'Field must be valid longitude.' )
211218 }
212- if ( isOptionalAndEmpty && locationType !== null && ( typeof locationType === 'number' && locationType <= 2 ) ) {
213- reason = 'Latitude and Longitude are required for your current location type'
214- return { field : name , invalid : isOptionalAndEmpty || isNotLng , reason}
219+ if ( isOptionalAndEmpty && typeof locationType === 'number' && locationType <= 2 ) {
220+ return validationIssue ( 'Latitude and Longitude are required for your current location type' )
215221 }
216222 return false
217223 case 'TIME' :
218224 case 'NUMBER' :
219225 const isNotANumber = isNaN ( value )
220226 if ( isRequiredButEmpty || isNotANumber ) {
227+ let reason
221228 if ( isNotANumber ) {
222229 reason = 'Field must be valid number'
223230 }
224- return {
225- field : name ,
226- invalid : isRequiredButEmpty || isNotANumber ,
227- reason
228- }
231+ return validationIssue ( reason )
229232 } else {
230233 return false
231234 }
@@ -247,8 +250,7 @@ export function validate (
247250 }
248251 if ( ! hasService && name === 'monday' ) {
249252 // only add validation issue for one day of week (monday)
250- reason = 'Calendar must have service for at least one day'
251- return { field : name , invalid : isRequiredButEmpty , reason}
253+ return validationIssue ( 'Calendar must have service for at least one day' )
252254 }
253255 return false
254256 case 'DROPDOWN' :
@@ -257,7 +259,7 @@ export function validate (
257259 field . options &&
258260 field . options . findIndex ( o => o . value === '' ) === - 1
259261 ) {
260- return { field : name , invalid : isRequiredButEmpty , reason }
262+ return validationIssue ( )
261263 } else {
262264 return false
263265 }
@@ -267,11 +269,7 @@ export function validate (
267269 agencies . length > 1
268270 ) {
269271 if ( valueDoesNotExist ) {
270- return {
271- field : name ,
272- invalid : true ,
273- reason : 'Field must be populated for feeds with more than one agency.'
274- }
272+ return validationIssue ( 'Field must be populated for feeds with more than one agency.' )
275273 }
276274 }
277275 return false
@@ -300,18 +298,19 @@ export function validate (
300298 }
301299 }
302300 if ( ! value || value . length === 0 ) {
303- return { field : `dates` , invalid : true , reason }
301+ return validationIssue ( EMPTY_FIELD_REASON , 'dates' )
304302 }
305303 // check if date already exists in this or other exceptions
306304 for ( let i = 0 ; i < value . length ; i ++ ) {
305+ const dateItemName = `dates-${ i } `
307306 if ( dateMap [ value [ i ] ] && dateMap [ value [ i ] ] . length > 1 ) {
308307 // eslint-disable-next-line standard/computed-property-even-spacing
309- reason = `Date (${ value [
308+ const reason = `Date (${ value [
310309 i
311310 ] } ) cannot appear more than once for all exceptions`
312- return { field : `dates- ${ i } ` , invalid : true , reason }
311+ return validationIssue ( reason , dateItemName )
313312 } else if ( ! moment ( value [ i ] , 'YYYYMMDD' , true ) . isValid ( ) ) {
314- return { field : `dates- ${ i } ` , invalid : true , reason }
313+ return validationIssue ( EMPTY_FIELD_REASON , dateItemName )
315314 }
316315 }
317316 return false
@@ -331,7 +330,7 @@ export function validate (
331330 )
332331 )
333332 ) {
334- return { field : name , invalid : true , reason : 'Field must be a positive integer' }
333+ return validationIssue ( name , 'Field must be a positive integer' )
335334 }
336335 return false
337336 case 'POSITIVE_NUM' :
@@ -342,7 +341,7 @@ export function validate (
342341 case 'COLOR' :
343342 default :
344343 if ( isRequiredButEmpty ) {
345- return { field : name , invalid : isRequiredButEmpty , reason }
344+ return validationIssue ( )
346345 }
347346 return false
348347 }
0 commit comments