0001-forms-sync-map-with-address-fields-27418.patch
tests/test_api.py | ||
---|---|---|
2384 | 2384 |
pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')) |
2385 | 2385 |
resp = get_app(pub).get('/api/reverse-geocoding?lat=0&lon=0') |
2386 | 2386 |
assert urlopen.call_args[0][0] == 'http://reverse.example.net/?param=value&format=json&addressdetails=1&lat=0&lon=0&accept-language=en' |
2387 | ||
2388 | ||
2389 |
def test_geocoding(pub): |
|
2390 |
with mock.patch('qommon.misc.urlopen') as urlopen: |
|
2391 |
urlopen.side_effect = lambda *args: StringIO(json.dumps([{'lat': 0, 'lon': 0}])) |
|
2392 |
get_app(pub).get('/api/geocoding', status=400) |
|
2393 |
resp = get_app(pub).get('/api/geocoding?q=test') |
|
2394 |
assert resp.content_type == 'application/json' |
|
2395 |
assert resp.body == json.dumps([{'lat': 0, 'lon': 0}]) |
|
2396 |
assert urlopen.call_args[0][0] == 'http://nominatim.openstreetmap.org/search?format=json&q=test&accept-language=en' |
|
2397 | ||
2398 |
pub.site_options.add_section('options') |
|
2399 |
pub.site_options.set('options', 'nominatim_key', 'KEY') |
|
2400 |
pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')) |
|
2401 |
resp = get_app(pub).get('/api/geocoding?q=test') |
|
2402 |
assert urlopen.call_args[0][0] == 'http://nominatim.openstreetmap.org/search?key=KEY&format=json&q=test&accept-language=en' |
|
2403 | ||
2404 |
pub.site_options.set('options', 'geocoding_service_url', 'http://reverse.example.net/?param=value') |
|
2405 |
pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')) |
|
2406 |
resp = get_app(pub).get('/api/geocoding?q=test') |
|
2407 |
assert urlopen.call_args[0][0] == 'http://reverse.example.net/?param=value&format=json&q=test&accept-language=en' |
wcs/api.py | ||
---|---|---|
810 | 810 |
url += '&accept-language=%s' % (get_publisher().get_site_language() or 'en') |
811 | 811 |
return HttpResponse(misc.urlopen(url).read(), content_type='application/json') |
812 | 812 | |
813 |
def geocoding(request, *args, **kwargs): |
|
814 |
if not 'q' in request.GET: |
|
815 |
return HttpResponseBadRequest() |
|
816 |
q = request.GET['q'] |
|
817 |
url = get_publisher().get_geocoding_service_url() |
|
818 |
if '?' in url: |
|
819 |
url += '&' |
|
820 |
else: |
|
821 |
url += '?' |
|
822 |
url += 'format=json&q=%s' % urllib.quote(q.encode('utf-8')) |
|
823 |
url += '&accept-language=%s' % (get_publisher().get_site_language() or 'en') |
|
824 |
return HttpResponse(misc.urlopen(url).read(), content_type='application/json') |
|
825 | ||
826 | ||
813 | 827 |
def validate_expression(request, *args, **kwargs): |
814 | 828 |
expression = request.GET.get('expression') |
815 | 829 |
hint = {'klass': None, 'msg': ''} |
wcs/qommon/form.py | ||
---|---|---|
2109 | 2109 |
self.readonly = kwargs.pop('readonly', False) |
2110 | 2110 |
self.map_attributes = {} |
2111 | 2111 |
self.map_attributes.update(get_publisher().get_map_attributes()) |
2112 |
self.sync_map_and_address_fields = get_publisher().has_site_option('sync-map-and-address-fields') |
|
2112 | 2113 |
for attribute in ('initial_zoom', 'min_zoom', 'max_zoom', 'init_with_geoloc'): |
2113 | 2114 |
if attribute in kwargs: |
2114 | 2115 |
self.map_attributes['data-' + attribute] = kwargs.pop(attribute) |
wcs/qommon/static/js/qommon.geolocation.js | ||
---|---|---|
26 | 26 | |
27 | 27 |
$(document).on('set-geolocation', function(event, coords) { |
28 | 28 |
$.getJSON(WCS_ROOT_URL + '/api/reverse-geocoding?lat=' + coords.lat + '&lon=' + coords.lng, function(data) { |
29 |
unset_sync_callback() |
|
29 | 30 |
geoloc_prefill('house', data.address.house_number); |
30 | 31 |
var street = data.address.road; |
31 | 32 |
if (!street && data.address.pedestrian) { |
... | ... | |
41 | 42 |
geoloc_prefill('postcode', data.address.postcode); |
42 | 43 |
geoloc_prefill('city', data.address.village || data.address.town || data.address.city || data.address.county); |
43 | 44 |
geoloc_prefill('country', data.address.country); |
45 |
set_sync_callback() |
|
44 | 46 |
}); |
45 | 47 |
}); |
46 | 48 |
if ($('.qommon-map').length == 0) { |
... | ... | |
62 | 64 |
); |
63 | 65 |
} |
64 | 66 |
} |
67 | ||
68 |
function set_sync_callback() { |
|
69 |
var $map = $('.qommon-map'); |
|
70 |
if (! $map.data('address-sync')) return; |
|
71 |
$('div[data-geolocation]').on('change', 'input[type=text], textarea, select', function(event) { |
|
72 |
var address = ''; |
|
73 |
$(['number-and-street', 'house', 'road', 'postcode', 'city', 'country']).each(function(idx, elem) { |
|
74 |
var part = $('div[data-geolocation="' + elem + '"]').find('input, textarea, select').val(); |
|
75 |
if (part) { |
|
76 |
address += part + ' '; |
|
77 |
if (elem == 'number-and-street' || elem == 'road' || elem == 'city') { |
|
78 |
address += ', '; |
|
79 |
} |
|
80 |
} |
|
81 |
}); |
|
82 |
$.getJSON(WCS_ROOT_URL + '/api/geocoding?q=' + address, function(data) { |
|
83 |
if (data && $(data).length > 0) { |
|
84 |
var coords = {lat: data[0].lat, lon: data[0].lon}; |
|
85 |
var map = $map[0].leaflet_map; |
|
86 |
map.flyTo(coords); |
|
87 |
if (map.marker === null) { |
|
88 |
map.marker = L.marker([0, 0]); |
|
89 |
map.marker.addTo(map); |
|
90 |
} |
|
91 |
map.marker.setLatLng(coords); |
|
92 |
} |
|
93 |
}); |
|
94 |
}); |
|
95 |
} |
|
96 |
function unset_sync_callback() { |
|
97 |
$('div[data-geolocation]').off('change', 'input[type=text], textarea, select'); |
|
98 |
} |
|
99 |
set_sync_callback(); |
|
65 | 100 |
}); |
wcs/qommon/templates/qommon/forms/widgets/map.html | ||
---|---|---|
4 | 4 |
<input type="hidden" name="{{widget.name}}$latlng" {% if widget.value %}value="{{widget.value}}"{% endif %}> |
5 | 5 |
<div id="map-{{widget.name}}" class="qommon-map" |
6 | 6 |
{% if widget.readonly %}data-readonly="true"{% endif %} |
7 |
{% if widget.sync_map_and_address_fields %}data-address-sync="true"{% endif %} |
|
7 | 8 |
{% for key, value in widget.map_attributes.items %}{{key}}="{{value}}" {% endfor %} |
8 | 9 |
{% if widget.initial_position %} |
9 | 10 |
data-init-lat="{{ widget.initial_position.lat }}" |
wcs/urls.py | ||
---|---|---|
27 | 27 |
url(r'^api/validate-condition$', api.validate_condition, name='api-validate-condition'), |
28 | 28 |
url(r'^api/validate-expression$', api.validate_expression, name='api-validate-expression'), |
29 | 29 |
url(r'^api/reverse-geocoding$', api.reverse_geocoding, name='api-reverse-geocoding'), |
30 |
url(r'^api/geocoding$', api.geocoding, name='api-geocoding'), |
|
30 | 31 | |
31 | 32 |
# provide django.contrib.auth view names for compatibility with |
32 | 33 |
# templates created for classic django applications. |
33 |
- |