Skip to content

Commit 7aae916

Browse files
committed
refactor(validation): prevent MTC feed publication on blocking issues
1 parent a4830d1 commit 7aae916

File tree

7 files changed

+85
-12
lines changed

7 files changed

+85
-12
lines changed

lib/manager/actions/status.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ export function handleFinishedJob (job: ServerJob) {
144144
if (isExtensionEnabled('mtc')) {
145145
const firstDate = job.validationResult && job.validationResult.firstCalendarDate
146146
const now = moment().startOf('day')
147-
if (moment(firstDate).isAfter(now)) {
147+
if (firstDate && moment(firstDate).isAfter(now)) {
148148
dispatch(setStatusModal({
149149
title: 'Warning: Feed contains service for future dates only!',
150150
body: `Use the 'Merge' button to merge with the currently active feed version.`

lib/manager/actions/versions.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,19 @@ const requestingFeedVersionIsochrones = createVoidPayloadAction('REQUESTING_FEED
9797
const requestingValidationIssueCount = createVoidPayloadAction('REQUESTING_VALIDATION_ISSUE_COUNT')
9898

9999
// setActiveVersion used in components
100-
export const setActiveVersion = createAction(
100+
export const settingActiveVersion = createAction(
101101
'SET_ACTIVE_FEEDVERSION',
102102
(payload: FeedVersion) => payload
103103
)
104+
export function setActiveVersion (version: FeedVersion) {
105+
return function (dispatch: dispatchFn, getState: getStateFn) {
106+
// Dispatch action to set value in reducer.
107+
dispatch(settingActiveVersion(version))
108+
// Fetch validation issue count. NOTE: future version-specific data fetching
109+
// could also be triggered here.
110+
version && dispatch(fetchValidationIssueCount(version))
111+
}
112+
}
104113
const uploadingFeed = createVoidPayloadAction('UPLOADING_FEED')
105114

106115
export type VersionActions = ActionType<typeof deletingFeedVersion> |

lib/manager/components/validation/GtfsValidationViewer.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,22 @@
33
import Icon from '@conveyal/woonerf/components/icon'
44
import moment from 'moment'
55
import React, {Component} from 'react'
6-
import {Alert, ListGroup, Table, ListGroupItem, Panel, Col, Row} from 'react-bootstrap'
6+
import {
7+
Alert,
8+
Label,
9+
ListGroup,
10+
Table,
11+
ListGroupItem,
12+
Panel,
13+
Col,
14+
Row
15+
} from 'react-bootstrap'
716

817
import Loading from '../../../common/components/Loading'
918
import OptionButton from '../../../common/components/OptionButton'
19+
import {isExtensionEnabled} from '../../../common/util/config'
1020
import toSentenceCase from '../../../common/util/to-sentence-case'
11-
import {getTableFatalExceptions} from '../../util/version'
21+
import {BLOCKING_ERROR_TYPES, getTableFatalExceptions} from '../../util/version'
1222

1323
import ValidationErrorItem from './ValidationErrorItem'
1424

@@ -34,10 +44,6 @@ export default class GtfsValidationViewer extends Component<Props, State> {
3444
limit: DEFAULT_LIMIT
3545
}
3646

37-
componentWillMount () {
38-
this.props.fetchValidationIssueCount(this.props.version)
39-
}
40-
4147
componentWillReceiveProps (nextProps: Props) {
4248
if (
4349
this._validationHasErrors(this.props.validationResult) &&
@@ -127,6 +133,10 @@ export default class GtfsValidationViewer extends Component<Props, State> {
127133
if (e.entity_type !== firstError.entity_type) multiTyped = true
128134
})
129135
const tableType = category.type.indexOf('TABLE') !== -1
136+
// Check to see if this is a blocking issue (MTC-only) preventing
137+
// the version from being published.
138+
const isBlockingIssue = isExtensionEnabled('mtc') &&
139+
BLOCKING_ERROR_TYPES.indexOf(category.type) !== -1
130140
const includeEntityType = tableType || multiTyped
131141
return (
132142
<ListGroup key={index} fill>
@@ -140,6 +150,8 @@ export default class GtfsValidationViewer extends Component<Props, State> {
140150
<h4>
141151
<Icon type={errorTypeIsActive ? 'caret-down' : 'caret-right'} />
142152
{toSentenceCase(category.type.replace(/_/g, ' '))}
153+
{' '}
154+
{isBlockingIssue && <Label bsStyle='danger'>BLOCKING</Label>}
143155
<span className='pull-right text-warning'>
144156
<Icon type='exclamation-triangle' /> {category.count}
145157
</span>

lib/manager/components/version/FeedVersionDetails.js

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,20 @@
33
import Icon from '@conveyal/woonerf/components/icon'
44
import moment from 'moment'
55
import React, {Component} from 'react'
6-
import {Button, ButtonToolbar, DropdownButton, ListGroupItem, MenuItem} from 'react-bootstrap'
6+
import {
7+
Button,
8+
ButtonToolbar,
9+
DropdownButton,
10+
ListGroupItem,
11+
MenuItem
12+
} from 'react-bootstrap'
13+
import {Link} from 'react-router'
714
import area from 'turf-area'
815
import bboxPoly from 'turf-bbox-polygon'
916

1017
import * as versionsActions from '../../actions/versions'
1118
import {getConfigProperty, isExtensionEnabled} from '../../../common/util/config'
19+
import {BLOCKING_ERROR_TYPES} from '../../util/version'
1220
import VersionDateLabel from './VersionDateLabel'
1321

1422
import type {FeedVersion, Bounds, Feed} from '../../../types'
@@ -31,6 +39,16 @@ export default class FeedVersionDetails extends Component<Props> {
3139
return poly ? area(poly) : 0
3240
}
3341

42+
/**
43+
* Prevent publication if the error_counts object is missing (bad validation)
44+
* or if a blocking error type was found.
45+
*/
46+
_checkBlockingIssue = (version: FeedVersion) => {
47+
return !version.validationResult.error_counts ||
48+
!!(version.validationResult.error_counts
49+
.find(ec => BLOCKING_ERROR_TYPES.indexOf(ec.type) !== -1))
50+
}
51+
3452
_handleMergeVersion = (versionId: string) => {
3553
// For now, merging feeds only works for the MTC extension. It will fail
3654
// when the 'none' merge type is used.
@@ -59,7 +77,7 @@ export default class FeedVersionDetails extends Component<Props> {
5977
version.feedSource.id,
6078
'manage-feed'
6179
)
62-
80+
const hasBlockingIssue = this._checkBlockingIssue(version)
6381
return (
6482
<ListGroupItem>
6583
<h4>
@@ -85,7 +103,7 @@ export default class FeedVersionDetails extends Component<Props> {
85103
</DropdownButton>
86104
}
87105
<Button
88-
disabled={isPublished || processing || !userCanManageFeed}
106+
disabled={hasBlockingIssue || isPublished || processing || !userCanManageFeed}
89107
bsStyle={isPublished ? 'success' : 'warning'}
90108
onClick={this._onClickPublish}>
91109
{isPublished
@@ -105,6 +123,23 @@ export default class FeedVersionDetails extends Component<Props> {
105123
</span>
106124
{' '}
107125
<VersionDateLabel version={version} />
126+
{hasBlockingIssue &&
127+
<div
128+
className='text-danger'
129+
style={{
130+
position: 'absolute',
131+
bottom: '1px',
132+
right: '5px',
133+
fontSize: 'x-small'
134+
}}>
135+
Cannot publish version because it has a blocking issue.
136+
(See{' '}
137+
<Link
138+
to={`/feed/${feedSource.id}/version/${version.version}/issues`}>
139+
validation issues
140+
</Link>.)
141+
</div>
142+
}
108143
</h4>
109144
<p>
110145
{summary && summary.avgDailyRevenueTime

lib/manager/components/version/FeedVersionViewer.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ export type Props = {
5151
export default class FeedVersionViewer extends Component<Props> {
5252
messages = getComponentMessages('FeedVersionViewer')
5353

54+
componentWillMount () {
55+
const {fetchValidationIssueCount, version} = this.props
56+
version && fetchValidationIssueCount(version)
57+
}
58+
5459
render () {
5560
const {
5661
feedVersionIndex,

lib/manager/util/version.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,15 @@ export function versionHasExpired (version: FeedVersion): boolean {
3535
export function versionHasNotBegun (version: FeedVersion): boolean {
3636
return moment(version.validationResult.startDate).isAfter(moment())
3737
}
38+
39+
// Error types that should prevent publishing a feed version to MTC. These types
40+
// must correspond to those found at:
41+
// https://github.com/conveyal/gtfs-lib/blob/dev/src/main/java/com/conveyal/gtfs/error/NewGTFSErrorType.java
42+
export const BLOCKING_ERROR_TYPES = [
43+
'ILLEGAL_FIELD_VALUE',
44+
'TABLE_IN_SUBDIRECTORY',
45+
'WRONG_NUMBER_OF_FIELDS',
46+
'MISSING_COLUMN',
47+
'TABLE_MISSING_COLUMN_HEADERS',
48+
'REFERENTIAL_INTEGRITY'
49+
]

lib/types/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export type Route = {
5757
routeShortName: ?string,
5858
routeTextColor: string,
5959
routeUrl: string,
60-
status: string,
60+
status: string,
6161
wheelchairBoarding: string
6262
}
6363

0 commit comments

Comments
 (0)