diff --git a/package.json b/package.json index 8b9d40f..925c8e4 100644 --- a/package.json +++ b/package.json @@ -22,10 +22,11 @@ }, "devDependencies": { "@types/elasticsearch": "^5.0.17", + "@types/geojson": "^1.0.6", "@types/leaflet": "^1.2.0", - "@types/react-leaflet": "^1.1.4", "@types/node": "^8.0.34", "@types/react": "^16.0.10", - "@types/react-dom": "^16.0.1" + "@types/react-dom": "^16.0.1", + "@types/react-leaflet": "^1.1.4" } } diff --git a/src/App.tsx b/src/App.tsx index c165df0..168f95c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,7 +4,9 @@ import SearchBar from './Components/SearchBar'; import LunchMap from './Components/LunchMap'; import GeoSelector from './Components/GeoSelector'; import SearchService from './Services/SearchService'; +import { DistrictService } from './Services/districtService'; import './App.css'; +import { IDistrictResultSlim } from './FrontPage'; export interface ISearchParams { latitude: number; @@ -47,20 +49,27 @@ class App extends React.Component { this.searchService = new SearchService(); this.state = { results: [], - searchParams: {} + searchParams: {}, + districts: [], + district: {} }; + new DistrictService().loadDistricts( + (results: any) => { + this.setState({districts: results}); + } + ); } public render() { return (
- +
- +
@@ -90,9 +99,14 @@ class App extends React.Component { * - and restart search if necessary * - and also update this.state.results */ - private updateSearchParams = (searchParams: ISearchParams) => { + private updateSearchParams = (searchParams: ISearchParams, district?: IDistrictResultSlim) => { + + const newState: { searchParams: ISearchParams, district: null | IDistrictResultSlim } = { searchParams: searchParams, district: null }; - this.setState({ searchParams: searchParams }); + if (district) { + newState.district = district; + } + this.setState(newState); const searchHash = '' + searchParams.searchQuery + searchParams.latitude + searchParams.longitude + searchParams.category + searchParams.district; diff --git a/src/Components/LunchMap.tsx b/src/Components/LunchMap.tsx index fb3ee28..345cd2e 100644 --- a/src/Components/LunchMap.tsx +++ b/src/Components/LunchMap.tsx @@ -1,9 +1,10 @@ import * as React from 'react'; import { ISearchParams, ISearchResult } from '../App'; import { Map, Marker, Popup, TileLayer } from 'react-leaflet'; +import { IDistrictResultSlim } from '../Services/districtService'; // for custom markers -import { divIcon, Point } from 'leaflet'; +import { divIcon, Point, GeoJSON } from 'leaflet'; // for map positions import { LatLng } from 'leaflet'; @@ -14,6 +15,7 @@ interface ILunchMapProps { results: Array; updateHandler: any; searchParams: ISearchParams; + districtPolygon?: IDistrictResultSlim; } class LunchMap extends React.Component { @@ -22,6 +24,7 @@ class LunchMap extends React.Component { private mapRef: Map; private centerPosition: LatLng|null; private districtCenterPosition: LatLng|null; + private districtLayer: GeoJSON|null; render() { @@ -34,6 +37,7 @@ class LunchMap extends React.Component { } this.centerPosition = null; + const map = ( {this.mapRef = el; }}> @@ -83,6 +87,16 @@ class LunchMap extends React.Component { zoom, { animate: true, duration: 1} ); + + // update the Polygon of the currently selected district + if (this.props.districtPolygon) { + if (!this.districtLayer) { + this.districtLayer = new GeoJSON(this.props.districtPolygon.polygon) + .addTo(this.mapRef.leafletElement); + } + this.districtLayer.clearLayers(); + this.districtLayer.addData(this.props.districtPolygon.polygon); + } } /** diff --git a/src/Components/SearchBar.tsx b/src/Components/SearchBar.tsx index 5cf5745..de89584 100644 --- a/src/Components/SearchBar.tsx +++ b/src/Components/SearchBar.tsx @@ -1,9 +1,10 @@ import * as React from 'react'; import { ISearchParams } from '../App'; -import { DistrictService, IDistrictResultSlim } from '../Services/districtService'; +import { IDistrictResultSlim } from '../Services/districtService'; interface ISearchBarProps { results?: any; + districts: Array; updateHandler: any; searchParams: ISearchParams; } @@ -12,21 +13,13 @@ class SearchBar extends React.Component { constructor(props: ISearchBarProps) { super(props); - this.state = { - districts: [] - }; - new DistrictService().loadDistricts( - (results: any) => { - this.setState({districts: results}); - } - ); } render() { const DebounceInput = require('react-debounce-input'); - let districtList = this.state.districts.map((d: IDistrictResultSlim) => { + let districtList = this.props.districts.map((d: IDistrictResultSlim) => { return }); @@ -104,17 +97,19 @@ class SearchBar extends React.Component { let searchParams = this.props.searchParams; const district = event.currentTarget.value; searchParams.district = district; + let selectedDistrict; - if (this.state.districts) { + if (this.props.districts) { /*const { centerLat, centerLon } = this.state.districts.find((d:IDistrictResultSlim) => { return d.number === Number(district) });*/ - const found = this.state.districts.find((d:IDistrictResultSlim) => { return d.number === Number(district) }); + const found = this.props.districts.find((d:IDistrictResultSlim) => { return d.number === Number(district) }); if (found) { const { centerLat, centerLon } = found; searchParams.centerLat = Number(centerLat); searchParams.centerLon = Number(centerLon); + selectedDistrict = found; } } - this.props.updateHandler(searchParams); + this.props.updateHandler(searchParams, selectedDistrict); } private onTypeChange = (event: React.FormEvent) => { diff --git a/src/Services/districtService.ts b/src/Services/districtService.ts index ea62d25..a1ad0c8 100644 --- a/src/Services/districtService.ts +++ b/src/Services/districtService.ts @@ -1,7 +1,7 @@ - import * as Elasticsearch from 'elasticsearch'; +import { Polygon } from 'geojson'; -let client = new Elasticsearch.Client({ +const client = new Elasticsearch.Client({ host: 'https://elasticsearch.codeformuenster.org:443', log: 'trace' }); @@ -12,6 +12,7 @@ export interface IDistrictResultSlim { id: number; centerLat: number; centerLon: number; + polygon: Polygon; } /** @@ -28,7 +29,7 @@ export class DistrictService { index: 'stadtteile', body: { 'size' : 100, - '_source': [ 'properties', 'center' ] + '_source': [ 'properties', 'center', 'geometry' ] } }; @@ -45,13 +46,14 @@ export class DistrictService { if (body && body.hits) { console.log('hits', body.hits.total); const results = body.hits.hits; - for (const { _id, _source: { properties: district, center: { coordinates } } } of results) { + for (const { _id, _source: { properties: district, center: { coordinates }, geometry } } of results) { districts.push({ id: _id, name: district.Name, number: district.Nr, centerLat: coordinates[1], - centerLon: coordinates[0] + centerLon: coordinates[0], + polygon: geometry }); } }