Skip to content

Commit 15bc8b2

Browse files
committed
fix(pattern): improve styling of pattern stop list and scroll bars
fixes #151
1 parent bbe0425 commit 15bc8b2

12 files changed

+309
-191
lines changed

lib/editor/components/EditorInput.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export default class EditorInput extends Component {
170170
<div style={{marginBottom: '10px'}}>Drop {activeComponent} image here, or click to select image to upload.</div>
171171
{activeEntity && activeEntity[field.name]
172172
? <img
173-
alt='agency branding'
173+
alt={field.name}
174174
className='img-responsive'
175175
src={activeEntity[field.name]} />
176176
: null

lib/editor/components/EntityDetails.js

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,16 @@ export default class EntityDetails extends Component {
3535
offset: PropTypes.number,
3636
tableData: PropTypes.object,
3737
entityEdited: PropTypes.bool,
38-
subComponent: PropTypes.string
38+
subComponent: PropTypes.string,
39+
validationErrors: PropTypes.array
3940
}
4041

4142
state = {}
4243

44+
_hasValidationIssue = field => {
45+
return this.props.validationErrors.find(e => e.field === field.name)
46+
}
47+
4348
_toggleFareRules = (editFareRules) => this.setState({editFareRules})
4449

4550
render () {
@@ -84,53 +89,52 @@ export default class EntityDetails extends Component {
8489
)
8590
}
8691
const {zones, zoneOptions} = getZones(getTableById(tableData, 'stop'), activeEntity)
87-
const rowIndex = 0
8892
const currentTable = getEditorTable(activeComponent)
89-
const renderDefault = subComponent !== 'trippattern' && !this.state.editFareRules && activeComponent !== 'scheduleexception'
90-
const inputs = renderDefault && currentTable.fields.map((field, colIndex) => (
91-
<EditorInput
92-
field={field}
93-
currentValue={activeEntity[field.name]}
94-
key={`${rowIndex}-${colIndex}`}
95-
approveGtfsDisabled={approveGtfsDisabled}
96-
zoneOptions={zoneOptions}
97-
isNotValid={validationErrors.find(e => e.field === field.name)}
98-
{...this.props} />
99-
))
100-
const detailsBody = (
101-
<div
102-
className='entity-details-body'
103-
style={{height: '80%', overflowY: 'scroll'}}>
104-
{/* Render relevant form based on entity type */}
105-
{subComponent === 'trippattern'
106-
? <ActiveTripPatternList
107-
showConfirmModal={showConfirmModal} />
108-
: this.state.editFareRules && activeEntity
109-
? <FareRulesForm
110-
zones={zones}
111-
zoneOptions={zoneOptions}
112-
{...this.props} />
113-
: activeComponent === 'scheduleexception'
114-
? <ScheduleExceptionForm {...this.props} />
115-
: <div>
116-
<Form>
117-
{inputs}
118-
</Form>
119-
</div>
120-
}
121-
</div>
122-
)
93+
// Render the default form if not viewing trip patterns, schedule exceptions,
94+
// or fare rules.
95+
const renderDefault = subComponent !== 'trippattern' &&
96+
!this.state.editFareRules &&
97+
activeComponent !== 'scheduleexception'
12398
return (
12499
<div style={panelStyle}>
125-
<div
126-
className='entity-details'
127-
style={{height: '100%'}}>
100+
<div className='entity-details'>
128101
<EntityDetailsHeader
129102
validationErrors={validationErrors}
130103
editFareRules={this.state.editFareRules}
131104
toggleEditFareRules={this._toggleFareRules}
132105
{...this.props} />
133-
{detailsBody}
106+
{/* Entity Details Body */}
107+
<div className='entity-details-body'>
108+
{/* Render relevant form based on entity type */}
109+
{subComponent === 'trippattern'
110+
? <ActiveTripPatternList
111+
showConfirmModal={showConfirmModal} />
112+
: this.state.editFareRules && activeEntity
113+
? <FareRulesForm
114+
zones={zones}
115+
zoneOptions={zoneOptions}
116+
{...this.props} />
117+
: activeComponent === 'scheduleexception'
118+
? <ScheduleExceptionForm {...this.props} />
119+
: <div>
120+
<Form>
121+
{/* Editor Inputs */}
122+
{renderDefault && currentTable.fields
123+
.map((field, i) => (
124+
<EditorInput
125+
field={field}
126+
currentValue={activeEntity[field.name]}
127+
key={`${activeComponent}-${activeEntity.id}-${i}`}
128+
approveGtfsDisabled={approveGtfsDisabled}
129+
zoneOptions={zoneOptions}
130+
isNotValid={this._hasValidationIssue(field)}
131+
{...this.props} />
132+
))
133+
}
134+
</Form>
135+
</div>
136+
}
137+
</div>
134138
</div>
135139
</div>
136140
)

lib/editor/components/EntityDetailsHeader.js

Lines changed: 91 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Icon from '@conveyal/woonerf/components/icon'
22
import React, {Component, PropTypes} from 'react'
33
import {Badge, Button, ButtonGroup, Tooltip, OverlayTrigger, Nav, NavItem} from 'react-bootstrap'
44

5-
import {getEntityBounds, getEntityName, getTableById} from '../util/gtfs'
5+
import {getEntityBounds, getEntityName} from '../util/gtfs'
66
import {entityIsNew} from '../util/objects'
77
import {GTFS_ICONS} from '../util/ui'
88

@@ -20,7 +20,6 @@ export default class EntityDetailsHeader extends Component {
2020
setActiveEntity: PropTypes.func,
2121
subEntity: PropTypes.number,
2222
subComponent: PropTypes.string,
23-
tableData: PropTypes.object,
2423
toggleEditFareRules: PropTypes.func,
2524
updateMapSetting: PropTypes.func,
2625
validationErrors: PropTypes.array
@@ -61,14 +60,26 @@ export default class EntityDetailsHeader extends Component {
6160
_showFareRules = () => this.props.toggleEditFareRules(true)
6261

6362
_showRoute = () => {
64-
const {activeComponent, activeEntity, feedSource, setActiveEntity, subComponent} = this.props
63+
const {
64+
activeComponent,
65+
activeEntity,
66+
feedSource,
67+
setActiveEntity,
68+
subComponent
69+
} = this.props
6570
if (subComponent === 'trippattern') {
6671
setActiveEntity(feedSource.id, activeComponent, activeEntity)
6772
}
6873
}
6974

7075
_showTripPatterns = () => {
71-
const {activeComponent, activeEntity, feedSource, setActiveEntity, subComponent} = this.props
76+
const {
77+
activeComponent,
78+
activeEntity,
79+
feedSource,
80+
setActiveEntity,
81+
subComponent
82+
} = this.props
7283
if (subComponent !== 'trippattern') {
7384
setActiveEntity(feedSource.id, activeComponent, activeEntity, 'trippattern')
7485
}
@@ -83,7 +94,6 @@ export default class EntityDetailsHeader extends Component {
8394
mapState,
8495
subComponent,
8596
subEntityId,
86-
tableData,
8797
validationErrors
8898
} = this.props
8999
const validationTooltip = (
@@ -93,28 +103,28 @@ export default class EntityDetailsHeader extends Component {
93103
))}
94104
</Tooltip>
95105
)
96-
const entityName = activeComponent === 'feedinfo' ? 'Feed Info' : getEntityName(activeEntity)
106+
const hasErrors = validationErrors.length > 0
107+
const entityName = activeComponent === 'feedinfo'
108+
? 'Feed Info'
109+
: getEntityName(activeEntity)
97110
const icon = GTFS_ICONS.find(i => i.id === activeComponent)
98-
const zoomDisabled = activeEntity && !subComponent ? mapState.target === activeEntity.id : mapState.target === subEntityId
111+
const zoomDisabled = activeEntity && !subComponent
112+
? mapState.target === activeEntity.id
113+
: mapState.target === subEntityId
99114
const iconName = icon ? icon.icon : null
100115
const nameWidth = activeComponent === 'stop' || activeComponent === 'route'
101-
? '130px'
102-
: '170px'
103-
const entityNameStyle = {
104-
width: nameWidth,
105-
paddingTop: '8px',
106-
display: 'inline-block',
107-
textOverflow: 'ellipsis',
108-
whiteSpace: 'nowrap',
109-
overflow: 'hidden'
110-
}
116+
? '176px'
117+
: '210px'
111118
return (
112-
<div style={{height: '100px'}}>
113-
<h5 style={{width: '100%', marginBottom: '0px'}}>
119+
<div className='entity-details-header'>
120+
<h5 className='entity-details-heading'>
114121
{/* Zoom, undo, and save buttons */}
115122
<ButtonGroup className='pull-right'>
116123
{activeComponent === 'stop' || activeComponent === 'route'
117-
? <OverlayTrigger rootClose placement='bottom' overlay={<Tooltip id='tooltip'>Zoom to {activeComponent}</Tooltip>}>
124+
? <OverlayTrigger
125+
rootClose
126+
placement='bottom'
127+
overlay={<Tooltip id='tooltip'>Zoom to {activeComponent}</Tooltip>}>
118128
<Button
119129
bsSize='small'
120130
disabled={zoomDisabled}
@@ -124,62 +134,72 @@ export default class EntityDetailsHeader extends Component {
124134
</OverlayTrigger>
125135
: null
126136
}
127-
<OverlayTrigger rootClose placement='bottom' overlay={<Tooltip id='tooltip'>Undo changes</Tooltip>}>
137+
<OverlayTrigger
138+
rootClose
139+
placement='bottom'
140+
overlay={<Tooltip id='tooltip'>Undo changes</Tooltip>}>
128141
<Button
129142
bsSize='small'
130143
disabled={!entityEdited}
131144
onClick={this._onClickUndo}>
132145
<Icon type='undo' />
133146
</Button>
134147
</OverlayTrigger>
135-
<OverlayTrigger rootClose placement='bottom' overlay={<Tooltip id='tooltip'>Save changes</Tooltip>}>
148+
<OverlayTrigger
149+
rootClose
150+
placement='bottom'
151+
overlay={<Tooltip id='tooltip'>Save changes</Tooltip>}>
136152
<Button
137153
bsSize='small'
138-
disabled={!entityEdited || validationErrors.length > 0}
154+
disabled={!entityEdited || hasErrors}
139155
onClick={this._onClickSave}>
140156
<Icon type='floppy-o' />
141157
</Button>
142158
</OverlayTrigger>
143159
</ButtonGroup>
144-
{/* Entity Icon */}
145-
<span style={{position: 'relative', top: '-4px'}}>
146-
{activeComponent === 'route' && activeEntity
147-
? <span className='fa-stack'>
148-
<Icon type='square' style={{color: `#${activeEntity.route_color ? activeEntity.route_color : 'fff'}`}} className='fa-stack-2x' />
149-
<Icon type='bus' style={{color: `#${activeEntity.route_text_color ? activeEntity.route_text_color : '000'}`}} className='fa-stack-1x' />
150-
</span>
151-
: iconName
152-
? <span className='fa-stack'>
153-
<Icon type='square' className='fa-stack-2x' />
154-
<Icon type={iconName} className='fa-inverse fa-stack-1x' />
155-
</span>
156-
// schedule exception icon if no icon found
157-
: <span className='fa-stack'>
158-
<Icon type='calendar' className='fa-stack-1x' />
159-
<Icon type='ban' className='text-danger fa-stack-2x' />
160-
</span>
161-
}
162-
</span>
163-
{' '}
164-
{/* Entity name */}
165-
<span
166-
title={entityName}
167-
style={entityNameStyle}>
168-
{entityName}
160+
<span className='entity-details-title' style={{width: nameWidth}}>
161+
{/* Entity Icon */}
162+
<span style={{position: 'relative', top: '-4px'}}>
163+
{activeComponent === 'route'
164+
? <span className='fa-stack'>
165+
<Icon
166+
type='square'
167+
style={{color: `#${activeEntity.route_color || 'fff'}`}}
168+
className='fa-stack-2x' />
169+
<Icon
170+
type='bus'
171+
style={{color: `#${activeEntity.route_text_color || '000'}`}}
172+
className='fa-stack-1x' />
173+
</span>
174+
: iconName
175+
? <span className='fa-stack'>
176+
<Icon type='square' className='fa-stack-2x' />
177+
<Icon type={iconName} className='fa-inverse fa-stack-1x' />
178+
</span>
179+
// schedule exception icon if no icon found
180+
: <span className='fa-stack'>
181+
<Icon type='calendar' className='fa-stack-1x' />
182+
<Icon type='ban' className='text-danger fa-stack-2x' />
183+
</span>
184+
}
185+
</span>
186+
{' '}
187+
{/* Entity name */}
188+
<span
189+
title={entityName}
190+
className='entity-details-name'>
191+
{entityName}
192+
</span>
169193
</span>
170194
</h5>
171-
{/* FIXME: check for null feed info needs to be fixed */}
172-
{!getTableById(tableData, activeComponent, false) && activeComponent === 'feedinfo'
173-
? <small>Complete feed info to begin editing GTFS.</small>
174-
: null
175-
}
176195
{/* Validation issues */}
177196
<p style={{marginBottom: '2px'}}>
178197
<small style={{marginTop: '3px'}} className='pull-right'>
179198
<em className='text-muted'>* denotes required field</em>
180199
</small>
181-
<small className={`${validationErrors.length > 0 ? ' text-danger' : ' text-success'}`}>
182-
{validationErrors.length > 0
200+
<small
201+
className={`${hasErrors ? ' text-danger' : ' text-success'}`}>
202+
{hasErrors
183203
? <span>
184204
<Icon type='times-circle' />
185205
{' '}
@@ -217,22 +237,22 @@ export default class EntityDetailsHeader extends Component {
217237
</OverlayTrigger>
218238
</Nav>
219239
: activeComponent === 'fare'
220-
? <Nav style={{marginBottom: '5px'}} bsStyle='pills' justified>
221-
<NavItem
222-
eventKey={'fare'}
223-
active={!editFareRules}
224-
onClick={this._showFareAttributes}>
225-
Attributes
226-
</NavItem>
227-
<NavItem
228-
eventKey={'rules'}
229-
disabled={!activeEntity || entityIsNew(activeEntity)}
230-
active={editFareRules}
231-
onClick={this._showFareRules}>
232-
Rules
233-
</NavItem>
234-
</Nav>
235-
: null
240+
? <Nav style={{marginBottom: '5px'}} bsStyle='pills' justified>
241+
<NavItem
242+
eventKey={'fare'}
243+
active={!editFareRules}
244+
onClick={this._showFareAttributes}>
245+
Attributes
246+
</NavItem>
247+
<NavItem
248+
eventKey={'rules'}
249+
disabled={!activeEntity || entityIsNew(activeEntity)}
250+
active={editFareRules}
251+
onClick={this._showFareRules}>
252+
Rules
253+
</NavItem>
254+
</Nav>
255+
: null
236256
}
237257
</div>
238258
)

lib/editor/components/EntityList.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ export default class EntityList extends Component {
141141
headerHeight={20}
142142
rowHeight={25}
143143
style={{outline: 'none'}}
144+
className='EntityList'
144145
scrollToIndex={activeIndex}
145146
sortBy={sort.key}
146147
sortDirection={sort.direction}

lib/editor/components/GtfsEditor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ export default class GtfsEditor extends Component {
224224
getGtfsEntityIndex={this._getGtfsEntityIndex} />
225225
: null
226226
return (
227-
<div>
227+
<div className='GtfsEditor'>
228228
<Title>{this.getEditorTitle()}</Title>
229229
<EditorSidebar
230230
activeComponent={activeComponent}

0 commit comments

Comments
 (0)