forms: sync map with address fields (#27418)
This commit is contained in:
parent
adb5b170ac
commit
1f0bea71a2
|
@ -2458,3 +2458,24 @@ def test_formdef_submit_structured(pub, local_user):
|
|||
}
|
||||
|
||||
data_class.wipe()
|
||||
|
||||
|
||||
def test_geocoding(pub):
|
||||
with mock.patch('qommon.misc.urlopen') as urlopen:
|
||||
urlopen.side_effect = lambda *args: StringIO(json.dumps([{'lat': 0, 'lon': 0}]))
|
||||
get_app(pub).get('/api/geocoding', status=400)
|
||||
resp = get_app(pub).get('/api/geocoding?q=test')
|
||||
assert resp.content_type == 'application/json'
|
||||
assert resp.body == json.dumps([{'lat': 0, 'lon': 0}])
|
||||
assert urlopen.call_args[0][0] == 'http://nominatim.openstreetmap.org/search?format=json&q=test&accept-language=en'
|
||||
|
||||
pub.site_options.add_section('options')
|
||||
pub.site_options.set('options', 'nominatim_key', 'KEY')
|
||||
pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w'))
|
||||
resp = get_app(pub).get('/api/geocoding?q=test')
|
||||
assert urlopen.call_args[0][0] == 'http://nominatim.openstreetmap.org/search?key=KEY&format=json&q=test&accept-language=en'
|
||||
|
||||
pub.site_options.set('options', 'geocoding_service_url', 'http://reverse.example.net/?param=value')
|
||||
pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w'))
|
||||
resp = get_app(pub).get('/api/geocoding?q=test')
|
||||
assert urlopen.call_args[0][0] == 'http://reverse.example.net/?param=value&format=json&q=test&accept-language=en'
|
||||
|
|
14
wcs/api.py
14
wcs/api.py
|
@ -817,6 +817,20 @@ def reverse_geocoding(request, *args, **kwargs):
|
|||
url += '&accept-language=%s' % (get_publisher().get_site_language() or 'en')
|
||||
return HttpResponse(misc.urlopen(url).read(), content_type='application/json')
|
||||
|
||||
def geocoding(request, *args, **kwargs):
|
||||
if not 'q' in request.GET:
|
||||
return HttpResponseBadRequest()
|
||||
q = request.GET['q']
|
||||
url = get_publisher().get_geocoding_service_url()
|
||||
if '?' in url:
|
||||
url += '&'
|
||||
else:
|
||||
url += '?'
|
||||
url += 'format=json&q=%s' % urllib.quote(q.encode('utf-8'))
|
||||
url += '&accept-language=%s' % (get_publisher().get_site_language() or 'en')
|
||||
return HttpResponse(misc.urlopen(url).read(), content_type='application/json')
|
||||
|
||||
|
||||
def validate_expression(request, *args, **kwargs):
|
||||
expression = request.GET.get('expression')
|
||||
hint = {'klass': None, 'msg': ''}
|
||||
|
|
|
@ -2108,6 +2108,7 @@ class MapWidget(CompositeWidget):
|
|||
self.readonly = kwargs.pop('readonly', False)
|
||||
self.map_attributes = {}
|
||||
self.map_attributes.update(get_publisher().get_map_attributes())
|
||||
self.sync_map_and_address_fields = get_publisher().has_site_option('sync-map-and-address-fields')
|
||||
for attribute in ('initial_zoom', 'min_zoom', 'max_zoom', 'init_with_geoloc'):
|
||||
if attribute in kwargs:
|
||||
self.map_attributes['data-' + attribute] = kwargs.pop(attribute)
|
||||
|
|
|
@ -26,6 +26,7 @@ function geoloc_prefill(element_type, element_value)
|
|||
|
||||
$(document).on('set-geolocation', function(event, coords) {
|
||||
$.getJSON(WCS_ROOT_URL + '/api/reverse-geocoding?lat=' + coords.lat + '&lon=' + coords.lng, function(data) {
|
||||
unset_sync_callback()
|
||||
geoloc_prefill('house', data.address.house_number);
|
||||
var street = data.address.road;
|
||||
if (!street && data.address.pedestrian) {
|
||||
|
@ -41,6 +42,7 @@ function geoloc_prefill(element_type, element_value)
|
|||
geoloc_prefill('postcode', data.address.postcode);
|
||||
geoloc_prefill('city', data.address.village || data.address.town || data.address.city || data.address.county);
|
||||
geoloc_prefill('country', data.address.country);
|
||||
set_sync_callback()
|
||||
});
|
||||
});
|
||||
if ($('.qommon-map').length == 0) {
|
||||
|
@ -62,4 +64,37 @@ function geoloc_prefill(element_type, element_value)
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
function set_sync_callback() {
|
||||
var $map = $('.qommon-map');
|
||||
if (! $map.data('address-sync')) return;
|
||||
$('div[data-geolocation]').on('change', 'input[type=text], textarea, select', function(event) {
|
||||
var address = '';
|
||||
$(['number-and-street', 'house', 'road', 'postcode', 'city', 'country']).each(function(idx, elem) {
|
||||
var part = $('div[data-geolocation="' + elem + '"]').find('input, textarea, select').val();
|
||||
if (part) {
|
||||
address += part + ' ';
|
||||
if (elem == 'number-and-street' || elem == 'road' || elem == 'city') {
|
||||
address += ', ';
|
||||
}
|
||||
}
|
||||
});
|
||||
$.getJSON(WCS_ROOT_URL + '/api/geocoding?q=' + address, function(data) {
|
||||
if (data && $(data).length > 0) {
|
||||
var coords = {lat: data[0].lat, lon: data[0].lon};
|
||||
var map = $map[0].leaflet_map;
|
||||
map.flyTo(coords);
|
||||
if (map.marker === null) {
|
||||
map.marker = L.marker([0, 0]);
|
||||
map.marker.addTo(map);
|
||||
}
|
||||
map.marker.setLatLng(coords);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
function unset_sync_callback() {
|
||||
$('div[data-geolocation]').off('change', 'input[type=text], textarea, select');
|
||||
}
|
||||
set_sync_callback();
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<input type="hidden" name="{{widget.name}}$latlng" {% if widget.value %}value="{{widget.value}}"{% endif %}>
|
||||
<div id="map-{{widget.name}}" class="qommon-map"
|
||||
{% if widget.readonly %}data-readonly="true"{% endif %}
|
||||
{% if widget.sync_map_and_address_fields %}data-address-sync="true"{% endif %}
|
||||
{% for key, value in widget.map_attributes.items %}{{key}}="{{value}}" {% endfor %}
|
||||
{% if widget.initial_position %}
|
||||
data-init-lat="{{ widget.initial_position.lat }}"
|
||||
|
|
|
@ -27,6 +27,7 @@ urlpatterns = [
|
|||
url(r'^api/validate-condition$', api.validate_condition, name='api-validate-condition'),
|
||||
url(r'^api/validate-expression$', api.validate_expression, name='api-validate-expression'),
|
||||
url(r'^api/reverse-geocoding$', api.reverse_geocoding, name='api-reverse-geocoding'),
|
||||
url(r'^api/geocoding$', api.geocoding, name='api-geocoding'),
|
||||
|
||||
# provide django.contrib.auth view names for compatibility with
|
||||
# templates created for classic django applications.
|
||||
|
|
Loading…
Reference in New Issue