Skip to content

Commit

Permalink
Merge pull request #91 from conveyal/dev
Browse files Browse the repository at this point in the history
v0.5.0
  • Loading branch information
trevorgerhardt authored Nov 21, 2016
2 parents 30b8dad + ee84511 commit c3b80eb
Show file tree
Hide file tree
Showing 15 changed files with 390 additions and 333 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ After cloning the repository, run:
- `npm install`
- `npm start`

## Deploy

Once you see that TAUI is working properly with your static site data, deploy it to the S3 bucket specified in settings.yml with the following command (replacing the --config switch to point to default or wherever):

`mastarm deploy --config configurations/marseilles --minify --env production`

The AWS SDK for JS will detect and use the same AWS credentials you should have set up for AWSCLI. The deployment copies JS and CSS files into a sub-bucket called assets, but does not upload `index.html`. You need to edit `index.html` in the root of the TAUI repository to customize the page name, then upload it with `aws s3 cp index.html s3://mamp-static/index.html`.

`mastarm deploy` will not create the bucket or set its contents public. You need to ensure the bucket exists before running `mastarm deploy` and set all its contents public afterward using the S3 web console or CLI. You don’t need to set any permissions on the bucket itself.

If S3 reports “access denied” when you try to fetch a page over HTTP in your browser, this is often because an object you are requesting does not exist.

[npm-image]: https://img.shields.io/npm/v/@conveyal/taui.svg?maxAge=2592000&style=flat-square
[npm-url]: https://www.npmjs.com/package/@conveyal/taui
Expand Down
4 changes: 4 additions & 0 deletions configurations/default/messages.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Systems:
AccessTitle: Access to
BaseTitle: Proposed Transit
ComparisonTitle: Current Transit
TripsTitle: Example trips
TripsEmpty: No trips found!
BestTripTitle: Fastest trip
AlternateTripsTitle: Alternates
Waiting: waiting included
Faster: faster
NewTrip: New Trip
Geocoding:
Expand All @@ -13,6 +15,8 @@ Geocoding:
EndTitle: Traveling to
EndPlaceholder: End
PromptText: Type to search for an address
Log:
Title: Log
Map:
SetLocationPopup:
SetStart: Set start
Expand Down
1 change: 1 addition & 0 deletions configurations/default/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ cloudfront: EJKZ46R7IC1BB
entries:
- src/index.js:assets/index.js
- src/containers/indianapolis/style.css:assets/index.css
env: development
flyle: true
s3bucket: taui
serve: true
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
"description": "Isochrone & accessibility analysis",
"main": "src/index.js",
"scripts": {
"deploy": "mastarm deploy --env production --minify",
"prestart": "yarn",
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
"start": "mastarm build --serve src/index.js:assets/index.js src/containers/indianapolis/style.css:assets/index.css --flyle",
"start": "mastarm build",
"test": "mastarm lint"
},
"repository": {
Expand All @@ -28,7 +29,7 @@
},
"dependencies": {
"@conveyal/woonerf": "^0.2.1",
"browsochrones": "^0.9.0",
"browsochrones": "^0.9.1",
"color": "^0.11.1",
"debug": "^2.2.0",
"font-awesome": "^4.6.3",
Expand All @@ -54,7 +55,7 @@
"react-select-geocoder": "^0.2.1",
"redux": "^3.6.0",
"redux-actions": "^0.12.0",
"transitive-js": "^0.9.1"
"transitive-js": "^0.9.2"
},
"standard": {
"parser": "babel-eslint"
Expand Down
72 changes: 50 additions & 22 deletions src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ export const setOrigin = createAction('set origin', (origin) => {
return origin
})

export const setDestinationLabel = createAction('set destination label', (label) => {
setKeyTo('end', label)
return label
})

export const setOriginLabel = createAction('set origin label', (label) => {
setKeyTo('start', label)
return label
})

export const clearEnd = createAction('clear end', () => {
setKeyTo('end', null)
})
Expand Down Expand Up @@ -94,14 +104,15 @@ export function updateOrigin ({browsochrones, destinationLatlng, latlng, label,
)
} else {
actions.push(
setOrigin({latlng}),
addActionLogItem(`Finding start address for ${lonlng(latlng).toString()}`),
reverseGeocode({latlng})
.then(({features}) => {
if (!features || features.length < 1) return
const label = featureToLabel(features[0])
return [
addActionLogItem(`Set start address to: ${label}`),
setOrigin({label, latlng: lonlng(features[0].geometry.coordinates)})
setOriginLabel(label)
]
})
)
Expand All @@ -111,24 +122,24 @@ export function updateOrigin ({browsochrones, destinationLatlng, latlng, label,

const point = browsochrones.base.pixelToOriginPoint(Leaflet.CRS.EPSG3857.latLngToPoint(latlng, zoom), zoom)
if (browsochrones.base.pointInQueryBounds(point)) {
actions.push(
fetchBrowsochronesFor({
browsochrones: browsochrones.base,
destinationLatlng,
latlng,
name: 'base',
timeCutoff,
zoom
}),
fetchBrowsochronesFor({
actions.push(fetchBrowsochronesFor({
browsochrones: browsochrones.base,
destinationLatlng,
latlng,
name: 'base',
timeCutoff,
zoom
}))
if (browsochrones.comparison) {
actions.push(fetchBrowsochronesFor({
browsochrones: browsochrones.comparison,
destinationLatlng,
latlng,
name: 'comparison',
timeCutoff,
zoom
})
)
}))
}
} else {
console.log('point out of bounds') // TODO: Handle
}
Expand Down Expand Up @@ -156,7 +167,7 @@ function fetchBrowsochronesFor ({

return [
decrementWork(),
generateAccessiblityFor({browsochrones, name, timeCutoff}),
generateAccessiblityFor({browsochrones, latlng, name, timeCutoff}),
generateIsochroneFor({browsochrones, latlng, name, timeCutoff}),
destinationLatlng && generateDestinationDataFor({
browsochrones,
Expand All @@ -171,14 +182,19 @@ function fetchBrowsochronesFor ({
]
}

function generateAccessiblityFor ({browsochrones, name, timeCutoff}) {
const storedAccessibility = {}
const storedIsochrones = {}

function generateAccessiblityFor ({browsochrones, latlng, name, timeCutoff}) {
return [
incrementWork(),
addActionLogItem(`Generating accessibility surface for ${name}`),
(async () => {
const accessibility = {}
for (const grid of browsochrones.grids) {
accessibility[grid] = await browsochrones.getAccessibilityForGrid(grid, timeCutoff)
const key = `${name}-${lonlng.toString(latlng)}-${timeCutoff}-${grid}`
accessibility[grid] = storedAccessibility[key] || await browsochrones.getAccessibilityForGrid(grid, timeCutoff)
storedAccessibility[key] = accessibility[grid]
}
return [
setAccessibilityFor({accessibility, name}),
Expand All @@ -193,8 +209,10 @@ function generateIsochroneFor ({browsochrones, latlng, name, timeCutoff}) {
incrementWork(),
addActionLogItem(`Generating travel time isochrone for ${name}`),
(async () => {
const isochrone = await browsochrones.getIsochrone(timeCutoff)
isochrone.key = `${name}-${lonlng.toString(latlng)}-${timeCutoff}`
const key = `${name}-${lonlng.toString(latlng)}-${timeCutoff}`
const isochrone = storedIsochrones[key] || await browsochrones.getIsochrone(timeCutoff)
isochrone.key = key
storedIsochrones[key] = isochrone

return [
setIsochroneFor({isochrone, name}),
Expand All @@ -212,7 +230,10 @@ function generateDestinationDataFor ({browsochrones, fromLatlng, toLatlng, name,
const destinationPoint = browsochrones.pixelToOriginPoint(Leaflet.CRS.EPSG3857.latLngToPoint(toLatlng, zoom), zoom)
const data = await browsochrones.generateDestinationData({
from: fromLatlng || null,
to: destinationPoint
to: {
...toLatlng,
...destinationPoint
}
})
data.transitive.key = `${name}-${lonlng.toString(toLatlng)}`
return [
Expand All @@ -230,9 +251,12 @@ export function updateSelectedTimeCutoff ({browsochrones, latlng, timeCutoff}) {

if (browsochrones.base && browsochrones.base.isLoaded()) {
actions.push(generateIsochroneFor({browsochrones: browsochrones.base, latlng, name: 'base', timeCutoff}))
actions.push(generateAccessiblityFor({browsochrones: browsochrones.base, latlng, name: 'base', timeCutoff}))
}

if (browsochrones.comparison && browsochrones.comparison.isLoaded()) {
actions.push(generateIsochroneFor({browsochrones: browsochrones.comparison, latlng, name: 'comparison', timeCutoff}))
actions.push(generateAccessiblityFor({browsochrones: browsochrones.base, name: 'base', timeCutoff}))
actions.push(generateAccessiblityFor({browsochrones: browsochrones.comparison, name: 'comparison', timeCutoff}))
actions.push(generateAccessiblityFor({browsochrones: browsochrones.comparison, latlng, name: 'comparison', timeCutoff}))
}

return actions
Expand Down Expand Up @@ -266,13 +290,17 @@ export function updateDestination ({
actions.push(setDestination({label, latlng}))
} else {
actions.push(
setDestination({latlng}),
reverseGeocode({latlng})
.then(({features}) => setDestination({label: featureToLabel(features[0]), latlng: lonlng(features[0].geometry.coordinates)}))
.then(({features}) => setDestinationLabel(featureToLabel(features[0])))
)
}

if (browsochrones.base && browsochrones.base.isLoaded()) {
actions.push(generateDestinationDataFor({browsochrones: browsochrones.base, fromLatlng, toLatlng: latlng, name: 'base', zoom}))
}

if (browsochrones.comparison && browsochrones.comparison.isLoaded()) {
actions.push(generateDestinationDataFor({browsochrones: browsochrones.comparison, fromLatlng, toLatlng: latlng, name: 'comparison', zoom}))
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/log-item/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
.LogItem-createdAt {
opacity: 0.75;
margin-right: 0.5rem;
vertical-align: middle;;
vertical-align: middle;
}
22 changes: 11 additions & 11 deletions src/components/route-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ function TripDiff ({
: oldTravelTime - travelTime
const diff = parseInt((nume / oldTravelTime * 100).toFixed(1))

if (oldTravelTime === 255) return <span className='increase'>{messages.NewTrip} <Icon type='star' /></span>
else if (actualDiff > 0) return <span className='pull-right decrease'><strong>{diff}</strong>%<Icon type='level-up' /></span>
else return <span className='pull-right increase'><strong>{diff * -1}</strong>%<Icon className='fa-rotate-180' type='level-up' /></span>
if (oldTravelTime === 255) return <span className='increase'>{messages.NewTrip} <Icon type='star' /><br /></span>
else if (actualDiff > 0) return <span className='pull-right decrease'><strong>{diff}</strong>%<Icon type='level-up' /><br /></span>
else return <span className='pull-right increase'><strong>{diff * -1}</strong>%<Icon className='fa-rotate-180' type='level-up' /><br /></span>
}

function renderJourneys ({ oldTravelTime, transitiveData, travelTime, waitTime }) {
Expand Down Expand Up @@ -102,8 +102,7 @@ function renderJourneys ({ oldTravelTime, transitiveData, travelTime, waitTime }
const alternateTrips = alternateTripSegments.map((segments, jindex) => {
return (
<div className='Trip' key={`journey-${jindex}`}>
<span className='CardIndex'>#{jindex + 1}</span>
{segments}
<span className='CardIndex'>{jindex + 1}.</span>{segments}
</div>
)
})
Expand All @@ -117,8 +116,8 @@ function renderJourneys ({ oldTravelTime, transitiveData, travelTime, waitTime }
<TripDiff
oldTravelTime={oldTravelTime}
travelTime={travelTime}
/>}<br />
includes <strong>{waitTime}</strong> {messages.Units.Mins} waiting <br />
/>}
<strong>{waitTime}</strong> {messages.Units.Mins} {messages.Systems.Waiting}<br />
</div>
</div>
{alternateTrips.length > 0 &&
Expand Down Expand Up @@ -146,7 +145,7 @@ function extractRelevantTransitiveInfo ({
const pid = s.pattern_id || s.patterns[0].pattern_id
const seg = {}
const route = findRouteForPattern({id: pid, patterns, routes})
const color = route.route_color ? Color(`#${route.route_color}`) : Color(s.color)
const color = route.route_color ? Color(`#${route.route_color}`) : Color('#0b2b40')
seg.name = toCapitalCase(route.route_short_name)

if (s.patterns && s.patterns.length > 0) {
Expand Down Expand Up @@ -180,13 +179,14 @@ function MetricIcon ({
}) {
const lc = name.toLowerCase()
if (lc.indexOf('job') !== -1) return <Icon type='building' />
if (lc.indexOf('worker') !== -1) return <Icon type='child' />
if (lc.indexOf('worker') !== -1 || lc.indexOf('population') !== -1) return <Icon type='child' />
return <span />
}

function showAccess (keys, base) {
return (
<div className='CardAccess'>
<div className='heading'>Access to</div>
<div className='heading'>{messages.Systems.AccessTitle}</div>
{keys.map((k, i) => <div className='Metric' key={k}><MetricIcon name={k} /><strong> {(base[k] | 0).toLocaleString()} </strong> {toSpaceCase(k)}</div>)}
</div>
)
Expand All @@ -209,7 +209,7 @@ function AccessDiffPercentage ({
function showDiff (keys, base, comparison) {
return (
<div className='CardAccess'>
<div className='heading'>Access to</div>
<div className='heading'>{messages.Systems.AccessTitle}</div>
{keys.map((key, i) => {
return (
<div className='Metric' key={key}>
Expand Down
2 changes: 1 addition & 1 deletion src/containers/indianapolis/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default class Form extends DeepEqual {
type='range'
min={10}
max={120}
step={10}
step={5}
/>
</div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/containers/indianapolis/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Indianapolis extends Component {
timeCutoff: PropTypes.shape({
selected: PropTypes.number
}),
ui: PropTypes.object,
ui: PropTypes.object.isRequired,
zoom: PropTypes.number
}

Expand Down Expand Up @@ -231,9 +231,9 @@ class Indianapolis extends Component {
{messages.Systems.ComparisonTitle}
</RouteCard>
}
{actionLog && actionLog.length > 0 &&
{ui.showLog && actionLog && actionLog.length > 0 &&
<div className='Card'>
<div className='CardTitle'>Log</div>
<div className='CardTitle'>{messages.Log.Title}</div>
<Log
items={this.props.actionLog}
/>
Expand Down
16 changes: 15 additions & 1 deletion src/containers/indianapolis/map.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import {Browser} from 'leaflet'
import {mapbox} from 'mapbox.js'
import React, {PropTypes} from 'react'
import {GeoJson, Map as LeafletMap, Marker, Popup, TileLayer} from 'react-leaflet'
import {GeoJson, Map as LeafletMap, Marker, Popup, TileLayer, ZoomControl} from 'react-leaflet'

import DeepEqual from '../../components/deep-equal'
import Icon from '../../components/icon'
import messages from '../../utils/messages'
import TransitiveLayer from '../../components/transitive-map-layer'
import transitiveStyle from './transitive-style'

const startIcon = mapbox.marker.icon({
'marker-size': 'large',
'marker-symbol': 'star',
'marker-color': '#4269a4'
})
const endIcon = mapbox.marker.icon({
'marker-color': '#ff8c00'
})

export default class Map extends DeepEqual {
static propTypes = {
centerCoordinates: PropTypes.arrayOf(PropTypes.number),
Expand Down Expand Up @@ -87,7 +97,10 @@ export default class Map extends DeepEqual {
zoom={zoom}
onClick={this._onMapClick}
onZoom={onZoom}
preferCanvas
zoomControl={false}
>
<ZoomControl position='topright' />
<TileLayer
url={Browser.retina && process.env.LEAFLET_RETINA_URL ? process.env.LEAFLET_RETINA_URL : process.env.LEAFLET_TILE_URL}
attribution={process.env.LEAFLET_ATTRIBUTION}
Expand All @@ -97,6 +110,7 @@ export default class Map extends DeepEqual {
return (
<Marker
draggable
icon={index === 0 ? startIcon : endIcon}
key={`marker-${index}`}
{...m}
>
Expand Down
Loading

0 comments on commit c3b80eb

Please sign in to comment.