|  | @@ -1,21 +1,135 @@
 | 
	
		
			
				|  |  | -import React, { Component } from 'react';
 | 
	
		
			
				|  |  | -import './App.css';
 | 
	
		
			
				|  |  | +import React, { Component } from 'react'
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import './App.css'
 | 
	
		
			
				|  |  | +import Map from 'pigeon-maps'
 | 
	
		
			
				|  |  | +import Marker from 'pigeon-marker'
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  import Tables from './Tables';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -class App extends Component {
 | 
	
		
			
				|  |  | -  constructor(props){
 | 
	
		
			
				|  |  | -    super(props);
 | 
	
		
			
				|  |  | +// please change this if you take some code from here.
 | 
	
		
			
				|  |  | +// otherwise the demo page will run out of credits and that would be very sad :(
 | 
	
		
			
				|  |  | +const MAPBOX_ACCESS_TOKEN = 'pk.eyJ1IjoicGlnZW9uLW1hcHMiLCJhIjoiY2l3eW01Y2E2MDA4dzJ6cWh5dG9pYWlwdiJ9.cvdCf-7PymM1Y3xp5j71NQ'
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const mapbox = (mapboxId, accessToken) => (x, y, z, dpr) => {
 | 
	
		
			
				|  |  | +  return `https://api.mapbox.com/styles/v1/mapbox/${mapboxId}/tiles/256/${z}/${x}/${y}${dpr >= 2 ? '@2x' : ''}?access_token=${accessToken}`
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const providers = {
 | 
	
		
			
				|  |  | +  osm: (x, y, z) => {
 | 
	
		
			
				|  |  | +    const s = String.fromCharCode(97 + (x + y + z) % 3)
 | 
	
		
			
				|  |  | +    return `https://${s}.tile.openstreetmap.org/${z}/${x}/${y}.png`
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  wikimedia: (x, y, z, dpr) => {
 | 
	
		
			
				|  |  | +    return `https://maps.wikimedia.org/osm-intl/${z}/${x}/${y}${dpr >= 2 ? '@2x' : ''}.png`
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  stamen: (x, y, z, dpr) => {
 | 
	
		
			
				|  |  | +    return `https://stamen-tiles.a.ssl.fastly.net/terrain/${z}/${x}/${y}${dpr >= 2 ? '@2x' : ''}.jpg`
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  streets: mapbox('streets-v10', MAPBOX_ACCESS_TOKEN),
 | 
	
		
			
				|  |  | +  satellite: mapbox('satellite-streets-v10', MAPBOX_ACCESS_TOKEN),
 | 
	
		
			
				|  |  | +  outdoors: mapbox('outdoors-v10', MAPBOX_ACCESS_TOKEN),
 | 
	
		
			
				|  |  | +  light: mapbox('light-v9', MAPBOX_ACCESS_TOKEN),
 | 
	
		
			
				|  |  | +  dark: mapbox('dark-v9', MAPBOX_ACCESS_TOKEN)
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const markers = {
 | 
	
		
			
				|  |  | +  Bernie: [[50.879, 4.6997], 13],
 | 
	
		
			
				|  |  | +  Martin: [[48.1542144, 13.9952128], 13],
 | 
	
		
			
				|  |  | +  Simon: [[50.85050, 4.35149], 11],
 | 
	
		
			
				|  |  | +  Lukas: [[51.0514, 3.7103], 12],
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const lng2tile = (lon, zoom) => (lon + 180) / 360 * Math.pow(2, zoom)
 | 
	
		
			
				|  |  | +const lat2tile = (lat, zoom) => (1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function isMapBox (provider) {
 | 
	
		
			
				|  |  | +  return provider === 'streets' || provider === 'satellite' || provider === 'outdoors' || provider === 'light' || provider === 'dark'
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const MapboxAttribution = () => (
 | 
	
		
			
				|  |  | +  <span className='map-attribution'>
 | 
	
		
			
				|  |  | +    <span>© <a href='https://www.mapbox.com/about/maps/'>Mapbox</a></span>{' | '}
 | 
	
		
			
				|  |  | +    <span>© <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a></span>{' | '}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  </span>
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const StamenAttribution = () => (
 | 
	
		
			
				|  |  | +  <span className='map-attribution'>
 | 
	
		
			
				|  |  | +    Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.
 | 
	
		
			
				|  |  | +  </span>
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const WikimediaAttribution = () => (
 | 
	
		
			
				|  |  | +  <span className='map-attribution'>
 | 
	
		
			
				|  |  | +    Map tiles by <a href='https://foundation.wikimedia.org/w/index.php?title=Maps_Terms_of_Use#Where_does_the_map_data_come_from.3F'>Wikimedia</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>
 | 
	
		
			
				|  |  | +  </span>
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export default class App extends Component {
 | 
	
		
			
				|  |  | +  constructor (props) {
 | 
	
		
			
				|  |  | +    super(props)
 | 
	
		
			
				|  |  |      this.apiUrl = "http://alpaga.hammerle.me:9876";
 | 
	
		
			
				|  |  |      this.name = null;
 | 
	
		
			
				|  |  | +         
 | 
	
		
			
				|  |  |      this.state = {
 | 
	
		
			
				|  |  | -      persons: []
 | 
	
		
			
				|  |  | +	  persons: [],
 | 
	
		
			
				|  |  | +      center: [48.1665, 14.0223], //start pos
 | 
	
		
			
				|  |  | +      zoom: 12,
 | 
	
		
			
				|  |  | +      provider: 'osm',
 | 
	
		
			
				|  |  | +      metaWheelZoom: false,
 | 
	
		
			
				|  |  | +      twoFingerDrag: false,
 | 
	
		
			
				|  |  | +      animate: true,
 | 
	
		
			
				|  |  | +      animating: false,
 | 
	
		
			
				|  |  | +      zoomSnap: true,
 | 
	
		
			
				|  |  | +      mouseEvents: true,
 | 
	
		
			
				|  |  | +      touchEvents: true,
 | 
	
		
			
				|  |  | +      minZoom: 1,
 | 
	
		
			
				|  |  | +      maxZoom: 18,
 | 
	
		
			
				|  |  | +      dragAnchor: [48.1665, 14.0223]
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | -    this.componentDidMount = this.componentDidMount.bind(this)
 | 
	
		
			
				|  |  | +	this.componentDidMount = this.componentDidMount.bind(this)
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // is called once when loading the page
 | 
	
		
			
				|  |  | +  zoomIn = () => {
 | 
	
		
			
				|  |  | +    this.setState({
 | 
	
		
			
				|  |  | +      zoom: Math.min(this.state.zoom + 1, 18)
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  zoomOut = () => {
 | 
	
		
			
				|  |  | +    this.setState({
 | 
	
		
			
				|  |  | +      zoom: Math.max(this.state.zoom - 1, 1)
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  handleBoundsChange = ({ center, zoom, bounds, initial }) => {
 | 
	
		
			
				|  |  | +    if (initial) {
 | 
	
		
			
				|  |  | +      console.log('Got initial bounds: ', bounds)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    this.setState({ center, zoom })
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  handleClick = ({ event, latLng, pixel }) => {
 | 
	
		
			
				|  |  | +    console.log('Map clicked!', latLng, pixel)
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  handleMarkerClick = ({ event, payload, anchor }) => {
 | 
	
		
			
				|  |  | +    console.log(`Marker #${payload} clicked at: `, anchor)
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  handleAnimationStart = () => {
 | 
	
		
			
				|  |  | +    this.setState({ animating: true })
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  handleAnimationStop = () => {
 | 
	
		
			
				|  |  | +    this.setState({ animating: false })
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// is called once when loading the page
 | 
	
		
			
				|  |  |    componentDidMount() {
 | 
	
		
			
				|  |  |      this.reloadLocations();
 | 
	
		
			
				|  |  |      setInterval(this.updateLocation, 4000);
 | 
	
	
		
			
				|  | @@ -50,13 +164,69 @@ class App extends Component {
 | 
	
		
			
				|  |  |        navigator.geolocation.getCurrentPosition(this.receivedPosition);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  render (){
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  render () {
 | 
	
		
			
				|  |  | +    const { center, zoom, provider, animate, metaWheelZoom, twoFingerDrag, zoomSnap, mouseEvents, touchEvents, animating, minZoom, maxZoom } = this.state
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      return (
 | 
	
		
			
				|  |  | -      <div id="wrapper">
 | 
	
		
			
				|  |  | -        <Tables persons={this.state.persons}/>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +      <div style={{textAlign: 'center', marginTop: 50, marginLeft: 0}}>
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        <div style={{maxWidth: 400, margin: '0 auto'}}>
 | 
	
		
			
				|  |  | +          <Map
 | 
	
		
			
				|  |  | +            limitBounds='edge'
 | 
	
		
			
				|  |  | +            center={center}
 | 
	
		
			
				|  |  | +            zoom={zoom}
 | 
	
		
			
				|  |  | +            provider={providers[provider]}
 | 
	
		
			
				|  |  | +            dprs={[1, 2]}
 | 
	
		
			
				|  |  | +            onBoundsChanged={this.handleBoundsChange}
 | 
	
		
			
				|  |  | +            onClick={this.handleClick}
 | 
	
		
			
				|  |  | +            onAnimationStart={this.handleAnimationStart}
 | 
	
		
			
				|  |  | +            onAnimationStop={this.handleAnimationStop}
 | 
	
		
			
				|  |  | +            animate={animate}
 | 
	
		
			
				|  |  | +            metaWheelZoom={metaWheelZoom}
 | 
	
		
			
				|  |  | +            twoFingerDrag={twoFingerDrag}
 | 
	
		
			
				|  |  | +            zoomSnap={zoomSnap}
 | 
	
		
			
				|  |  | +            mouseEvents={mouseEvents}
 | 
	
		
			
				|  |  | +            touchEvents={touchEvents}
 | 
	
		
			
				|  |  | +            minZoom={minZoom}
 | 
	
		
			
				|  |  | +            maxZoom={maxZoom}
 | 
	
		
			
				|  |  | +            attribution={
 | 
	
		
			
				|  |  | +              isMapBox(provider)
 | 
	
		
			
				|  |  | +                ? <MapboxAttribution />
 | 
	
		
			
				|  |  | +                : provider === 'stamen'
 | 
	
		
			
				|  |  | +                  ? <StamenAttribution />
 | 
	
		
			
				|  |  | +                  : provider === 'wikimedia'
 | 
	
		
			
				|  |  | +                    ? <WikimediaAttribution />
 | 
	
		
			
				|  |  | +                    : null}
 | 
	
		
			
				|  |  | +            defaultWidth={400}
 | 
	
		
			
				|  |  | +            height={200}
 | 
	
		
			
				|  |  | +            boxClassname="pigeon-filters">
 | 
	
		
			
				|  |  | +			
 | 
	
		
			
				|  |  | +            {Object.keys(markers).map(key => (
 | 
	
		
			
				|  |  | +              <Marker key={key} anchor={markers[key][0]} payload={key} onClick={this.handleMarkerClick} />
 | 
	
		
			
				|  |  | +            ))}
 | 
	
		
			
				|  |  | +			
 | 
	
		
			
				|  |  | +            {isMapBox(provider) && <span className='mapbox-wordmark' />}
 | 
	
		
			
				|  |  | +          </Map>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          {' '}
 | 
	
		
			
				|  |  | +          {Math.round(center[0] * 10000) / 10000} ({lat2tile(center[0], zoom)})
 | 
	
		
			
				|  |  | +          {' x '}
 | 
	
		
			
				|  |  | +          {Math.round(center[1] * 10000) / 10000} ({lng2tile(center[1], zoom)})
 | 
	
		
			
				|  |  | +          {' @ '}
 | 
	
		
			
				|  |  | +          {Math.round(zoom * 100) / 100}
 | 
	
		
			
				|  |  | +          {' - '}
 | 
	
		
			
				|  |  | +          {animating ? 'animating' : 'stopped'}
 | 
	
		
			
				|  |  | +		  
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        <div>	
 | 
	
		
			
				|  |  |          <button
 | 
	
		
			
				|  |  |              onClick={ () => {
 | 
	
		
			
				|  |  |                this.name = "Bernie";
 | 
	
	
		
			
				|  | @@ -74,10 +244,13 @@ class App extends Component {
 | 
	
		
			
				|  |  |                this.name = "Lukas";
 | 
	
		
			
				|  |  |              }}> Lukas </button>
 | 
	
		
			
				|  |  |        </div>
 | 
	
		
			
				|  |  | -  );
 | 
	
		
			
				|  |  | +	    
 | 
	
		
			
				|  |  | +	  
 | 
	
		
			
				|  |  | +	   <div id="wrapper">
 | 
	
		
			
				|  |  | +        <Tables persons={this.state.persons}/>
 | 
	
		
			
				|  |  | +       </div>
 | 
	
		
			
				|  |  | +       </div>
 | 
	
		
			
				|  |  | +	  
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -export default App;
 |