|
|
|
@ -1,4 +1,4 @@ |
|
|
|
|
import React, { useEffect, useContext } from 'react'; |
|
|
|
|
import React, { useEffect, useState } from 'react'; |
|
|
|
|
|
|
|
|
|
import Switch from '@material-ui/core/Switch'; |
|
|
|
|
import Box from '@material-ui/core/Box'; |
|
|
|
@ -21,9 +21,13 @@ import { MuiPickersUtilsProvider, DateTimePicker } from "@material-ui/pickers"; |
|
|
|
|
|
|
|
|
|
import DateFnsUtils from '@date-io/date-fns'; |
|
|
|
|
import { format } from 'date-fns'; |
|
|
|
|
import L from 'leaflet'; |
|
|
|
|
|
|
|
|
|
import { makeStyles } from '@material-ui/core/styles'; |
|
|
|
|
|
|
|
|
|
import { MapView, create_map } from './map.js'; |
|
|
|
|
import { SearchBar } from './searchbar.js'; |
|
|
|
|
|
|
|
|
|
import { |
|
|
|
|
filter_is_const_false, ConstFilter, LogicalOperatorFilter, MatchingFilter, |
|
|
|
|
ResultTypeEnum, LogicalOperatorEnum, MatchTypeEnum, NegationFilter, TimeFilterTypeEnum, |
|
|
|
@ -53,13 +57,75 @@ const useStyles = makeStyles(theme => ({ |
|
|
|
|
margined: { |
|
|
|
|
margin: "6px", |
|
|
|
|
}, |
|
|
|
|
mapcontainer: { |
|
|
|
|
width: "600px", |
|
|
|
|
}, |
|
|
|
|
})); |
|
|
|
|
|
|
|
|
|
export function EditLocationFilterExpression(props) { |
|
|
|
|
const { onChange, filter } = props; |
|
|
|
|
const [map, setMap] = useState(null); |
|
|
|
|
const [proposal, setProposal] = useState(filter.polygon); |
|
|
|
|
const [polyLayers, setPolyLayers] = useState([]); |
|
|
|
|
const classes = useStyles(); |
|
|
|
|
|
|
|
|
|
const _ = require('lodash'); |
|
|
|
|
|
|
|
|
|
function updateProposal(result) { |
|
|
|
|
// TODO: handle multi-polies
|
|
|
|
|
const polygon = result.geojson.coordinates[0].map(longlat => [ longlat[1], longlat[0] ]); |
|
|
|
|
|
|
|
|
|
// Show the polyline on the map
|
|
|
|
|
polyLayers.forEach(layer => { |
|
|
|
|
map.removeLayer(layer); |
|
|
|
|
}); |
|
|
|
|
var polyline = L.polyline(polygon, { color: 'blue' }).addTo(map); |
|
|
|
|
map.flyToBounds(polyline.getBounds()); |
|
|
|
|
setPolyLayers([polyline]); |
|
|
|
|
|
|
|
|
|
// Update the proposed polygon
|
|
|
|
|
console.log("Updated proposal:", result); |
|
|
|
|
setProposal(polygon); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function onSearch(query) { |
|
|
|
|
if (map == null) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fetch("http://nominatim.openstreetmap.org/search?polygon_geojson=1&polygon_threshold=0.001&format=json&limit=5&q=" + query) |
|
|
|
|
.then(res => res.json()) |
|
|
|
|
.then(jsonres => { |
|
|
|
|
//console.log("Nominatim result: ", jsonres);
|
|
|
|
|
if (Array.isArray(jsonres) && jsonres.length > 0) { |
|
|
|
|
updateProposal(jsonres[0]); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function handleUseProposal() { |
|
|
|
|
var new_filter = _.cloneDeep(filter); |
|
|
|
|
new_filter.polygon = proposal; |
|
|
|
|
onChange(new_filter); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This component is a bit tricky. MapView is not very React-y because it manages its
|
|
|
|
|
// own state inside (this is due to how Leaflet is integrated).
|
|
|
|
|
// We don't want to render a new MapView whenever our filter changes.
|
|
|
|
|
// Therefore we ensure that filter changes don't trigger a new MapView render.
|
|
|
|
|
return ( |
|
|
|
|
<Typography>TODO</Typography> |
|
|
|
|
<> |
|
|
|
|
<Box> |
|
|
|
|
<SearchBar onSubmit={onSearch} /> |
|
|
|
|
</Box> |
|
|
|
|
<Box className={classes.mapcontainer}> |
|
|
|
|
<MapView onMapChange={setMap}></MapView> |
|
|
|
|
</Box> |
|
|
|
|
<Box> |
|
|
|
|
<Button variant="contained" onClick={handleUseProposal}>Use shown boundary</Button> |
|
|
|
|
<Typography>Polygon with {filter.polygon.length} points.</Typography> |
|
|
|
|
</Box> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|