-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dd602b0
commit 0fa5b04
Showing
4 changed files
with
535 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
This demonstrates the usage of the WfsSearch. | ||
|
||
```jsx | ||
const React = require('react'); | ||
const OlMap = require('ol/map').default; | ||
const OlView = require('ol/view').default; | ||
const OlLayerTile = require('ol/layer/tile').default; | ||
const OlSourceOsm = require('ol/source/osm').default; | ||
const OlProj = require('ol/proj').default; | ||
|
||
class WfsSearchExample extends React.Component { | ||
|
||
constructor(props) { | ||
|
||
super(props); | ||
|
||
this.mapDivId = `map-${Math.random()}`; | ||
|
||
this.map = new OlMap({ | ||
layers: [ | ||
new OlLayerTile({ | ||
name: 'OSM', | ||
source: new OlSourceOsm() | ||
}) | ||
], | ||
view: new OlView({ | ||
center: OlProj.fromLonLat([37.40570, 8.81566]), | ||
zoom: 4 | ||
}) | ||
}); | ||
} | ||
|
||
componentDidMount() { | ||
this.map.setTarget(this.mapDivId); | ||
} | ||
|
||
render() { | ||
return( | ||
<div> | ||
<div className="example-block"> | ||
<label>The WfsSerach<br /> | ||
<WfsSearch | ||
baseUrl='https://ahocevar.com/geoserver/wfs' | ||
searchAttributes={['natural', 'name']} | ||
map={this.map} | ||
style={{ | ||
width: '80%' | ||
}} | ||
/> | ||
</label> | ||
</div> | ||
<div | ||
id={this.mapDivId} | ||
style={{ | ||
height: '400px' | ||
}} | ||
/> | ||
</div> | ||
) | ||
} | ||
} | ||
|
||
<WfsSearchExample /> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,290 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { | ||
AutoComplete, | ||
} from 'antd'; | ||
const Option = AutoComplete.Option; | ||
|
||
import Logger from '../../Util/Logger'; | ||
import UrlUtil from '../../Util/UrlUtil/UrlUtil'; | ||
import olProj from 'ol/proj'; | ||
import OlMap from 'ol/map'; | ||
|
||
/** | ||
* The WfsSearch. | ||
* | ||
* @class WfsSearch | ||
* @extends React.Component | ||
*/ | ||
export class WfsSearch extends React.Component { | ||
|
||
/** | ||
* The className added to this component. | ||
* @type {String} | ||
* @private | ||
*/ | ||
className = 'react-geo-wfssearch' | ||
|
||
static propTypes = { | ||
className: PropTypes.string, | ||
/** | ||
* The base URL. | ||
* @type {String} | ||
*/ | ||
baseUrl: PropTypes.string.isRequired, | ||
/** | ||
* The list of attributes that should be searched through. | ||
*/ | ||
searchAttributes: PropTypes.arrayOf(PropTypes.string).isRequired, | ||
/** | ||
* The namespace URI used for features. Required. | ||
*/ | ||
featureNS: PropTypes.string.isRequired, | ||
/** | ||
* The prefix for the feature namespace. Required. | ||
*/ | ||
featurePrefix: PropTypes.string.isRequired, | ||
/** | ||
* The feature type names. Required. | ||
*/ | ||
featureTypes: PropTypes.arrayOf(PropTypes.string).isRequired, | ||
/** | ||
* SRS name. No srsName attribute will be set on geometries when this is not | ||
* provided. | ||
*/ | ||
srsName: PropTypes.string, | ||
/** | ||
* Ther output format of the response. | ||
*/ | ||
outputFormat: PropTypes.string, | ||
/** | ||
* Maximum number of features to fetch. | ||
*/ | ||
maxFeatures: PropTypes.number, | ||
/** | ||
* Geometry name to use in a BBOX filter. | ||
*/ | ||
geometryName: PropTypes.string, | ||
/** | ||
* Optional list of property names to serialize. | ||
*/ | ||
propertyNames: PropTypes.arrayOf(PropTypes.string), | ||
/** | ||
* Wheather to use paging or not. | ||
*/ | ||
paging: PropTypes.bool, | ||
/** | ||
* Start index to use for WFS paging. This is a WFS 2.0 feature backported | ||
* to WFS 1.1.0 by some Web Feature Services. | ||
*/ | ||
pagingStartIndex: PropTypes.number, | ||
/** | ||
* Number of features to retrieve when paging. This is a WFS 2.0 feature | ||
* backported to WFS 1.1.0 by some Web Feature Services. Please note that | ||
* some Web Feature Services have repurposed maxfeatures instead. | ||
*/ | ||
pagingCount: PropTypes.number, | ||
/** | ||
* Filter condition. See http://openlayers.org/en/latest/apidoc/ol.format.filter.html | ||
* for more information. | ||
*/ | ||
filter: PropTypes.object, | ||
/** | ||
* The ol.map where the map will zoom to. | ||
* | ||
* @type {Object} | ||
*/ | ||
map: PropTypes.instanceOf(OlMap).isRequired, | ||
/** | ||
* The minimal amount of characters entered in the input to start a search. | ||
* @type {Number} | ||
*/ | ||
minChars: PropTypes.number, | ||
/** | ||
* A render function which gets called with the selected item as it is | ||
* returned by the server. It must return an `AutoComplete.Option`. | ||
* | ||
* @type {function} | ||
*/ | ||
renderOption: PropTypes.func, | ||
/** | ||
* An onSelect function which gets called with the selected item as it is | ||
* returned by nominatim. | ||
* @type {function} | ||
*/ | ||
onSelect: PropTypes.func | ||
} | ||
|
||
static defaultProps = { | ||
paging: true, | ||
pagingStartIndex: 0, | ||
pagingCount: 20, | ||
srsName: 'EPSG:3857', | ||
outputFormat: 'application/json', | ||
minChars: 3, | ||
/** | ||
* Create an AutoComplete.Option from the given data. | ||
* | ||
* @param {Object} item The tuple as an object. | ||
* @return {AutoComplete.Option} The returned option | ||
*/ | ||
renderOption: (item) => { | ||
return ( | ||
<Option key={item.place_id}> | ||
{item.display_name} | ||
</Option> | ||
); | ||
}, | ||
/** | ||
* The default onSelect method if no onSelect prop is given. It zooms to the | ||
* selected item. | ||
* | ||
* @param {object} selected The selected item as it is returned by nominatim. | ||
*/ | ||
onSelect: (selected, olMap) => { | ||
if (selected && selected.boundingbox) { | ||
const olView = olMap.getView(); | ||
debugger | ||
|
||
extent = extent.map(function(coord) { | ||
return parseFloat(coord); | ||
}); | ||
|
||
extent = olProj.transformExtent(extent, 'EPSG:4326', | ||
olView.getProjection().getCode()); | ||
|
||
olView.fit(extent, { | ||
duration: 500 | ||
}); | ||
} | ||
}, | ||
style: { | ||
width: 200 | ||
} | ||
} | ||
|
||
/** | ||
* Create the WfsSearch. | ||
* | ||
* @param {Object} props The initial props. | ||
* @constructs WfsSearch | ||
*/ | ||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
searchTerm: '', | ||
dataSource: [] | ||
}; | ||
this.onUpdateInput = this.onUpdateInput.bind(this); | ||
this.onMenuItemSelected = this.onMenuItemSelected.bind(this); | ||
} | ||
|
||
/** | ||
* Called if the input of the AutoComplete is being updated. It sets the | ||
* current inputValue as searchTerm and starts a search if the inputValue has | ||
* a length of at least `this.props.minChars` (default 3). | ||
* | ||
* @param {String|undefined} inputValue The inputValue. Undefined if clear btn | ||
* is pressed. | ||
*/ | ||
onUpdateInput(inputValue) { | ||
this.setState({ | ||
dataSource: [] | ||
}); | ||
|
||
this.setState({ | ||
searchTerm: inputValue || '' | ||
}, () => { | ||
if (this.state.searchTerm.length >= this.props.minChars) { | ||
this.doSearch(); | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Perform the search. | ||
*/ | ||
doSearch() { | ||
this.state.searchTerm; | ||
|
||
const featureRequest = new ol.format.WFS().writeGetFeature(this.props.options); | ||
const getRequestParams = UrlUtil.objectToRequestString(baseParams); | ||
|
||
fetch(`${this.props.baseUrl}${getRequestParams}`) | ||
.then(response => response.json()) | ||
.then(this.onFetchSuccess.bind(this)) | ||
.catch(this.onFetchError.bind(this)); | ||
} | ||
|
||
/** | ||
* This function gets called on success of the nominatim fetch. | ||
* It sets the response as dataSource. | ||
* | ||
* @param {Array<object>} response The found features. | ||
*/ | ||
onFetchSuccess(response) { | ||
this.setState({ | ||
dataSource: response | ||
}); | ||
} | ||
|
||
/** | ||
* This function gets called when the nomintim fetch returns an error. | ||
* It logs the error to the console. | ||
* | ||
* @param {String} error The errorstring. | ||
*/ | ||
onFetchError(error) { | ||
Logger.error(`Error while requesting Nominatim: ${error}`); | ||
} | ||
|
||
/** | ||
* The function describes what to do when an item is selected. | ||
* | ||
* @param {value} key The key of the selected option. | ||
*/ | ||
onMenuItemSelected(key) { | ||
const selected = this.state.dataSource.filter(i => i.place_id === key)[0]; | ||
this.props.onSelect(selected, this.props.map); | ||
} | ||
|
||
/** | ||
* The render function. | ||
*/ | ||
render() { | ||
const { | ||
className, | ||
nominatimBaseUrl, | ||
format, | ||
viewbox, | ||
bounded, | ||
polygon_geojson, | ||
addressdetails, | ||
limit, | ||
countrycodes, | ||
map, | ||
onSelect, | ||
renderOption, | ||
...passThroughProps | ||
} = this.props; | ||
|
||
const finalClassName = className | ||
? `${className} ${this.className}` | ||
: this.className; | ||
|
||
return ( | ||
<AutoComplete | ||
className={finalClassName} | ||
allowClear={true} | ||
placeholder="Ortsname, Straßenname, Stadtteilname, POI usw." | ||
dataSource={this.state.dataSource.map(renderOption.bind(this))} | ||
optionLabelProp="display_name" | ||
onChange={this.onUpdateInput} | ||
onSelect={this.onMenuItemSelected} | ||
{...passThroughProps} | ||
/> | ||
); | ||
} | ||
} | ||
|
||
export default WfsSearch; |
Oops, something went wrong.