Skip to content

Commit

Permalink
Fix #1123. Initial multiservice support for search (#1508)
Browse files Browse the repository at this point in the history
- Changed internal representation from nominatim to GeoJson
- Fixed #1507 Now Openlayers uses default style too
- Fixes #1505 Now the markers are correctly displaced
- The selector for layers with marker generate marker layers only inside the selector (still to remove loading from flat layer to get better performances)
- Initial support for WFS as external services
- Moved businness logic from UI into a new epic
  • Loading branch information
offtherailz authored Feb 27, 2017
1 parent 9db1d13 commit 8dc3380
Show file tree
Hide file tree
Showing 20 changed files with 600 additions and 89 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
"turf-bbox": "3.0.10",
"turf-buffer": "3.0.10",
"turf-intersect": "3.0.10",
"turf-point-on-surface": "3.0.10",
"turf-union": "3.0.10",
"url": "0.10.3",
"w3c-schemas": "1.3.1",
Expand Down
11 changes: 10 additions & 1 deletion web/client/actions/__tests__/search-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ var {
TEXT_SEARCH_LOADING,
TEXT_SEARCH_ERROR,
TEXT_SEARCH_STARTED,
TEXT_SEARCH_ITEM_SELECTED,
searchResultLoaded,
searchTextLoading,
searchResultError,
textSearch
textSearch,
selectSearchItem
} = require('../search');

describe('Test correctness of the search actions', () => {
Expand Down Expand Up @@ -49,5 +51,12 @@ describe('Test correctness of the search actions', () => {
expect(retval2.results).toEqual(testVal);
expect(retval2.append).toBe(true);
});
it('serch item selected', () => {
const retval = selectSearchItem("A", "B");
expect(retval).toExist();
expect(retval.type).toBe(TEXT_SEARCH_ITEM_SELECTED);
expect(retval.item).toEqual("A");
expect(retval.mapConfig).toBe("B");
});

});
25 changes: 20 additions & 5 deletions web/client/actions/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ const TEXT_SEARCH_TEXT_CHANGE = 'TEXT_SEARCH_TEXT_CHANGE';
const TEXT_SEARCH_LOADING = 'TEXT_SEARCH_LOADING';
const TEXT_SEARCH_ERROR = 'TEXT_SEARCH_ERROR';

function searchResultLoaded(results, append=false) {
const TEXT_SEARCH_ITEM_SELECTED = 'TEXT_SEARCH_ITEM_SELECTED';

function searchResultLoaded(results, append=false, services) {
return {
type: TEXT_SEARCH_RESULTS_LOADED,
results: results,
append: append
append: append,
services
};
}

Expand Down Expand Up @@ -64,11 +67,21 @@ function addMarker(itemPosition) {
};
}

function textSearch(searchText) {
function textSearch(searchText, {services = null} = {}) {
return {
type: TEXT_SEARCH_STARTED,
searchText
searchText,
services
};
}

function selectSearchItem(item, mapConfig) {
return {
type: TEXT_SEARCH_ITEM_SELECTED,
item,
mapConfig
};

}


Expand All @@ -82,12 +95,14 @@ module.exports = {
TEXT_SEARCH_RESET,
TEXT_SEARCH_ADD_MARKER,
TEXT_SEARCH_TEXT_CHANGE,
TEXT_SEARCH_ITEM_SELECTED,
searchTextLoading,
searchResultError,
searchResultLoaded,
textSearch,
resultsPurge,
resetSearch,
addMarker,
searchTextChanged
searchTextChanged,
selectSearchItem
};
8 changes: 4 additions & 4 deletions web/client/api/Nominatim.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ var axios = require('../libs/ajax');
const urlUtil = require('url');
const assign = require('object-assign');
const DEFAULT_URL = 'nominatim.openstreetmap.org';
const DEFAUTL_REVERSE_URL = 'nominatim.openstreetmap.org/reverse';
const DEFAULT_REVERSE_URL = 'nominatim.openstreetmap.org/reverse';
const defaultOptions = {
format: 'json',
bounded: 0,
addressdetails: 1
polygon_geojson: 1
};
/**
* API for local config
*/
const Api = {
geocode: function(text, options) {
var params = assign({q: text}, options || {}, defaultOptions);
var params = assign({q: text}, defaultOptions, options || {});
var url = urlUtil.format({
protocol: window.location.protocol,
host: DEFAULT_URL,
Expand All @@ -32,7 +32,7 @@ const Api = {
const params = assign({lat: coords.lat, lon: coords.lng}, options || {}, defaultOptions);
const url = urlUtil.format({
protocol: window.location.protocol,
host: DEFAUTL_REVERSE_URL,
host: DEFAULT_REVERSE_URL,
query: params
});
return axios.get(url);
Expand Down
28 changes: 16 additions & 12 deletions web/client/api/searchText.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
*/
const WFS = require('./WFS');
const assign = require('object-assign');


const GeoCodeUtils = require('../utils/GeoCodeUtils');
/*
const toNominatim = (fc) =>
fc.features && fc.features.map( (f) => ({
boundingbox: f.properties.bbox,
Expand All @@ -17,18 +17,22 @@ const toNominatim = (fc) =>
display_name: `${f.properties.STATE_NAME} (${f.properties.STATE_ABBR})`
}));

*/

module.exports = {
nominatim: (searchText) => require('./Nominatim').geocode(searchText).then( res => res.data),
nominatim: (searchText, {options = null} = {}) =>
require('./Nominatim')
.geocode(searchText, options)
.then( res => GeoCodeUtils.nominatimToGeoJson(res.data)),
wfs: (searchText, {url, typeName, queriableAttributes, outputFormat="application/json", predicate ="ILIKE", ...params }) => {
return WFS.getFeatureSimple(url,
assign({
maxFeatures: 10,
startIndex: 0,
typeName,
outputFormat,
cql_filter: queriableAttributes.map( attr => `${attr} ${predicate} '%${searchText}%'`).join(' OR ')
}, params)).then( response => toNominatim(response ));
return WFS
.getFeatureSimple(url, assign({
maxFeatures: 10,
startIndex: 0,
typeName,
outputFormat,
cql_filter: queriableAttributes.map( attr => `${attr} ${predicate} '%${searchText}%'`).join(' OR ')
}, params))
.then( response => response.features );
}
};
10 changes: 8 additions & 2 deletions web/client/components/map/leaflet/Feature.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,17 @@ var getPointLayer = function(pointToLayer, geojson, latlng, options) {
latlng,
{
icon: L.icon({
iconUrl: options.style.iconUrl
iconUrl: options.style.iconUrl,
shadowUrl: options.style.shadowUrl,
iconSize: options.style.iconSize,
shadowSize: options.style.shadowSize,
iconAnchor: options.style.iconAnchor,
shadowAnchor: options.style.shadowAnchor,
popupAnchor: options.style.popupAnchor
})
});
}
return new L.Marker(latlng);
return L.marker(latlng);
};

var geometryToLayer = function(geojson, options) {
Expand Down
1 change: 1 addition & 0 deletions web/client/components/map/leaflet/__tests__/Layer-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ describe('Leaflet layer', () => {
"visibility": true,
"name": "vector_sample",
"group": "sample",
"styleName": "marker",
"features": [
{ "type": "Feature",
"geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
Expand Down
130 changes: 130 additions & 0 deletions web/client/components/map/openlayers/__tests__/Layer-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,136 @@ describe('Openlayers layer', () => {
expect(map.getLayers().getLength()).toBe(1);
});

it('creates a vector layer with a given marker style', () => {
var options = {
styleName: "marker",
style: {
iconUrl: "test",
shadowUrl: "test"
},
crs: 'EPSG:4326',
features: {
'type': 'FeatureCollection',
'crs': {
'type': 'name',
'properties': {
'name': 'EPSG:4326'
}
},
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [13, 44]
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Polygon',
'coordinates': [[
[13, 43],
[15, 43],
[15, 44],
[13, 44]
]]
}
}
]
}
};
// create layers
var layer = ReactDOM.render(
<OpenlayersLayer type="vector"
options={options} map={map}/>, document.getElementById("container"));

expect(layer).toExist();
// count layers
expect(map.getLayers().getLength()).toBe(1);
});

it('creates a vector layer with a given point style', () => {
var options = {
style: {
type: "Point",
stroke: {
color: "blue",
width: 1
},
fill: {
color: "blue"
},
radius: 4
},
crs: 'EPSG:4326',
features: {
'type': 'FeatureCollection',
'crs': {
'type': 'name',
'properties': {
'name': 'EPSG:4326'
}
},
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [13, 44]
}
}
]
}
};
// create layers
var layer = ReactDOM.render(
<OpenlayersLayer type="vector"
options={options} map={map}/>, document.getElementById("container"));

expect(layer).toExist();
// count layers
expect(map.getLayers().getLength()).toBe(1);
});

it('vector layer with a given polygon style', () => {
var options = {
styleName: "Polygon",
crs: 'EPSG:4326',
features: {
'type': 'FeatureCollection',
'crs': {
'type': 'name',
'properties': {
'name': 'EPSG:4326'
}
},
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Polygon',
'coordinates': [[
[13, 43],
[15, 43],
[15, 44],
[13, 44]
]]
}
}
]
}
};
// create layers
var layer = ReactDOM.render(
<OpenlayersLayer type="vector"
options={options} map={map}/>, document.getElementById("container"));

expect(layer).toExist();
// count layers
expect(map.getLayers().getLength()).toBe(1);
});

it('change layer visibility for Google Layer', () => {
var google = {
maps: {
Expand Down
52 changes: 42 additions & 10 deletions web/client/components/map/openlayers/plugins/VectorLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,25 +142,57 @@ Layers.registerType('vector', {
};
}

if (options.style.iconUrl) {
style = {
image: new ol.style.Icon(({
anchor: [0.5, 1],
anchorXUnits: 'fraction',
anchorYUnits: 'fraction',
src: options.style.iconUrl
if (options.style.iconUrl ) {
let markerStyle = [new ol.style.Style({
image: new ol.style.Icon(({
anchor: options.iconAnchor || [0.5, 1],
anchorXUnits: ( options.iconAnchor || options.iconAnchor === 0) ? 'pixels' : 'fraction',
anchorYUnits: ( options.iconAnchor || options.iconAnchor === 0) ? 'pixels' : 'fraction',
src: options.style.iconUrl
}))
})];
if (options.style.shadowUrl) {
markerStyle = [new ol.style.Style({
image: new ol.style.Icon(({
anchor: [12, 41],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
src: options.style.shadowUrl || markerShadow
}))
}), markerStyle [0]];
}
style = (feature) => {
const type = feature.getGeometry().getType();
switch (type) {
case "Point":
case "MultiPoint":
return markerStyle;
default:
return styleFunction(feature);
}
};
} else {
style = new ol.style.Style(style);
}

style = new ol.style.Style(style);
}

return new ol.layer.Vector({
msId: options.id,
source: source,
zIndex: options.zIndex,
style: (options.styleName && !options.overrideOLStyle) ? () => {return defaultStyles[options.styleName]; } : style || styleFunction
style: (options.styleName && !options.overrideOLStyle) ? (feature) => {
if (options.styleName === "marker") {
const type = feature.getGeometry().getType();
switch (type) {
case "Point":
case "MultiPoint":
return defaultStyles.marker;
default:
break;
}
}
return defaultStyles[options.styleName];
} : style || styleFunction
});
},
update: (layer, newOptions, oldOptions) => {
Expand Down
Loading

0 comments on commit 8dc3380

Please sign in to comment.