mirror of
https://github.com/pretix/pretix.git
synced 2026-04-24 23:32:33 +00:00
Geo fields: Allow overriding existing values (#1978)
This commit is contained in:
committed by
GitHub
parent
73e7d407cd
commit
1c81792cd7
@@ -0,0 +1,33 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load static %}
|
||||
|
||||
<div class="geodata-section">
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
{% include "pretixcontrol/event/fragment_geodata_autoupdate.html" %}
|
||||
<div class="form-group geodata-group"
|
||||
data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}"
|
||||
data-attrib="{{ global_settings.leaflet_tiles_attribution }}"
|
||||
data-icon="{% static "leaflet/images/marker-icon.png" %}"
|
||||
data-shadow="{% static "leaflet/images/marker-shadow.png" %}">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Geo coordinates" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lat layout="inline" %}
|
||||
{% if global_settings.opencagedata_apikey %}
|
||||
<p class="attrib">
|
||||
<a href="https://openstreetmap.org/" target="_blank">
|
||||
{% trans "Geocoding data © OpenStreetMap" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lon layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,8 @@
|
||||
{% load i18n %}
|
||||
|
||||
<span class="geodata-autoupdate">
|
||||
<span class="optional" data-notification="error" title="{% trans "Failed to retrieve geo coordinates" %}"><i class="fa fa-warning"></i></span>
|
||||
<span class="optional" data-notification="loading" title="{% trans "Retrieving geo coordinates …" %}"><i class="fa fa-cog fa-spin"></i></span>
|
||||
<span class="optional" data-notification="updated"><i class="fa fa-check"></i> {% trans "Geo coordinates updated" %}</span>
|
||||
<span class="optional" data-notification="confirm">New geo coordinates. <button type="button" data-action="update" class="btn btn-link text-nowrap">{% trans "Update map?" %}</button></span>
|
||||
</span>
|
||||
@@ -24,34 +24,7 @@
|
||||
{% endif %}
|
||||
{% bootstrap_field form.date_from layout="control" %}
|
||||
{% bootstrap_field form.date_to layout="control" %}
|
||||
<div class="geodata-section">
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="form-group geodata-group"
|
||||
data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}"
|
||||
data-attrib="{{ global_settings.leaflet_tiles_attribution }}"
|
||||
data-icon="{% static "leaflet/images/marker-icon.png" %}"
|
||||
data-shadow="{% static "leaflet/images/marker-shadow.png" %}">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Geo coordinates" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lat layout="inline" %}
|
||||
{% if global_settings.opencagedata_apikey %}
|
||||
<p class="attrib">
|
||||
<a href="https://openstreetmap.org/" target="_blank">
|
||||
{% trans "Geocoding data © OpenStreetMap" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lon layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "pretixcontrol/event/fragment_geodata.html" %}
|
||||
{% bootstrap_field form.date_admission layout="control" %}
|
||||
{% bootstrap_field form.currency layout="control" %}
|
||||
{% bootstrap_field sform.contact_mail layout="control" %}
|
||||
|
||||
@@ -39,30 +39,7 @@
|
||||
{% if form.date_to %}
|
||||
{% bootstrap_field form.date_to layout="control" %}
|
||||
{% endif %}
|
||||
<div class="geodata-section">
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="form-group geodata-group" data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}" data-attrib="{{ global_settings.leaflet_tiles_attribution }}" data-icon="{% static "leaflet/images/marker-icon.png" %}" data-shadow="{% static "leaflet/images/marker-shadow.png" %}">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Geo coordinates" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lat layout="inline" %}
|
||||
{% if global_settings.opencagedata_apikey %}
|
||||
<p class="attrib">
|
||||
<a href="https://openstreetmap.org/" target="_blank">
|
||||
{% trans "Geocoding data © OpenStreetMap" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lon layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "pretixcontrol/event/fragment_geodata.html" %}
|
||||
{% bootstrap_field form.currency layout="control" %}
|
||||
{% bootstrap_field form.tax_rate addon_after="%" layout="control" %}
|
||||
</fieldset>
|
||||
|
||||
@@ -384,30 +384,7 @@
|
||||
<legend>{% trans "General information" %}</legend>
|
||||
{% bootstrap_field form.name layout="control" %}
|
||||
{% bootstrap_field form.active layout="control" %}
|
||||
<div class="geodata-section">
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="form-group geodata-group" data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}" data-attrib="{{ global_settings.leaflet_tiles_attribution }}" data-icon="{% static "leaflet/images/marker-icon.png" %}" data-shadow="{% static "leaflet/images/marker-shadow.png" %}">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Geo coordinates" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lat layout="inline" %}
|
||||
{% if global_settings.opencagedata_apikey %}
|
||||
<p class="attrib">
|
||||
<a href="https://openstreetmap.org/" target="_blank">
|
||||
{% trans "Geocoding data © OpenStreetMap" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lon layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "pretixcontrol/event/fragment_geodata.html" %}
|
||||
{% bootstrap_field form.frontpage_text layout="control" %}
|
||||
{% bootstrap_field form.is_public layout="control" %}
|
||||
{% if meta_forms %}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
{% bootstrap_field form.active layout="bulkedit" %}
|
||||
<div class="geodata-section">
|
||||
{% bootstrap_field form.location layout="bulkedit" %}
|
||||
{% include "pretixcontrol/event/fragment_geodata_autoupdate.html" %}
|
||||
<div class="form-group geodata-group"
|
||||
data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}"
|
||||
data-attrib="{{ global_settings.leaflet_tiles_attribution }}"
|
||||
|
||||
@@ -25,30 +25,7 @@
|
||||
{% bootstrap_field form.active layout="control" %}
|
||||
{% bootstrap_field form.date_from layout="control" %}
|
||||
{% bootstrap_field form.date_to layout="control" %}
|
||||
<div class="geodata-section">
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="form-group geodata-group" data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}" data-attrib="{{ global_settings.leaflet_tiles_attribution }}" data-icon="{% static "leaflet/images/marker-icon.png" %}" data-shadow="{% static "leaflet/images/marker-shadow.png" %}">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Geo coordinates" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lat layout="inline" %}
|
||||
{% if global_settings.opencagedata_apikey %}
|
||||
<p class="attrib">
|
||||
<a href="https://openstreetmap.org/" target="_blank">
|
||||
{% trans "Geocoding data © OpenStreetMap" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lon layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "pretixcontrol/event/fragment_geodata.html" %}
|
||||
{% bootstrap_field form.date_admission layout="control" %}
|
||||
{% bootstrap_field form.frontpage_text layout="control" %}
|
||||
{% bootstrap_field form.is_public layout="control" %}
|
||||
|
||||
@@ -1,128 +1,160 @@
|
||||
/*globals $*/
|
||||
|
||||
$(function () {
|
||||
var j = 0;
|
||||
$(".geodata-section").each(function () {
|
||||
// Geocoding
|
||||
var $sec = $(this);
|
||||
var $inp = $(this).find("textarea[lang=en], input[lang=en]").first();
|
||||
if ($inp.length === 0) {
|
||||
$inp = $(this).find("textarea, input").first();
|
||||
function cleanup(l) {
|
||||
return $.trim(l.replace(/\n/g, ", "));
|
||||
}
|
||||
var timer, timer2;
|
||||
var touched = $sec.find("input[name$=geo_lat]").val() !== "";
|
||||
$(".geodata-section").each(function () {
|
||||
// Geocoding
|
||||
// detach notifications and append them to first label (should be from location)
|
||||
var $notifications = $(".geodata-autoupdate", this).detach().appendTo($("label", this).first());
|
||||
var $lat = $("input[name$=geo_lat]", this).first();
|
||||
var $lon = $("input[name$=geo_lon]", this).first();
|
||||
var lat;
|
||||
var lon;
|
||||
var $updateButton = $("[data-action=update]", this);
|
||||
var $location = $("textarea[lang=en], input[lang=en]", this).first();
|
||||
if (!$location.length) $location = $("textarea, input[type=text]", this).first();
|
||||
|
||||
function load() {
|
||||
window.clearTimeout(timer);
|
||||
var q = $.trim($inp.val().replace(/\n/g, ", "));
|
||||
if ((touched && $sec.find("input[name$=geo_lat]").val() !== "") || $.trim(q) === "") {
|
||||
return;
|
||||
}
|
||||
$sec.find(".col-md-1").html("<span class='fa fa-cog fa-spin'></span>");
|
||||
$.getJSON('/control/geocode/?q=' + encodeURIComponent(q), function (res) {
|
||||
var q2 = $.trim($inp.val().replace(/\n/g, ", "));
|
||||
if (q2 !== q) {
|
||||
return; // lost race
|
||||
if (!$lat.length || !$lon.length || !$location.length) {
|
||||
return;
|
||||
}
|
||||
if (res.results) {
|
||||
$sec.find("input[name$=geo_lat]").val(res.results[0].lat);
|
||||
$sec.find("input[name$=geo_lon]").val(res.results[0].lon);
|
||||
center(13);
|
||||
|
||||
var debounceLoad, debounceLatLonChange, delayUpdateDismissal;
|
||||
var touched = $lat.val() !== "";
|
||||
var xhr;
|
||||
var lastLocation = cleanup($location.val());
|
||||
|
||||
function load() {
|
||||
window.clearTimeout(debounceLoad);
|
||||
if (xhr) {
|
||||
xhr.abort();
|
||||
xhr = null;
|
||||
}
|
||||
|
||||
var q = cleanup($location.val());
|
||||
if (q === "" || q === lastLocation) return;
|
||||
|
||||
lastLocation = q;
|
||||
$notifications.attr("data-notify", "loading");
|
||||
|
||||
xhr = $.getJSON('/control/geocode/?q=' + encodeURIComponent(q), function (res) {
|
||||
if (!res.results || !res.results.length) {
|
||||
$notifications.attr("data-notify", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
lat = res.results[0].lat;
|
||||
lon = res.results[0].lon;
|
||||
if (touched) {
|
||||
$notifications.attr("data-notify", "confirm");
|
||||
}
|
||||
else {
|
||||
$notifications.attr("data-notify", "");
|
||||
$lat.val(lat);
|
||||
$lon.val(lon);
|
||||
center(13);
|
||||
}
|
||||
})
|
||||
}
|
||||
$sec.find(".col-md-1").html("");
|
||||
})
|
||||
}
|
||||
|
||||
$sec.find("input[name$=geo_lat], input[name$=geo_lon]").change(function () {
|
||||
touched = $sec.find("input[name$=geo_lat]").val() !== "";
|
||||
center(13);
|
||||
}).keyup(function () {
|
||||
if (timer2) {
|
||||
window.clearTimeout(timer2);
|
||||
}
|
||||
timer2 = window.setTimeout(center, 300);
|
||||
});
|
||||
$lat.add($lon).change(function () {
|
||||
if (this.value !== "") touched = true;
|
||||
center(13);
|
||||
}).keyup(function () {
|
||||
window.clearTimeout(debounceLatLonChange);
|
||||
debounceLatLonChange = window.setTimeout(center, 300);
|
||||
});
|
||||
|
||||
$inp.change(load);
|
||||
$inp.keyup(function () {
|
||||
if (timer) {
|
||||
window.clearTimeout(timer);
|
||||
}
|
||||
timer = window.setTimeout(load, 1000);
|
||||
});
|
||||
$location.change(load);
|
||||
$location.keyup(function () {
|
||||
window.clearTimeout(debounceLoad);
|
||||
debounceLoad = window.setTimeout(load, 1000);
|
||||
if ($notifications.attr("data-notify") == "confirm" && lastLocation !== cleanup(this.value)) $notifications.attr("data-notify", "");
|
||||
});
|
||||
|
||||
// Map
|
||||
var $grp = $sec.find(".geodata-group");
|
||||
var tiles = $grp.attr("data-tiles");
|
||||
var attrib = $grp.attr("data-attrib");
|
||||
if (tiles) {
|
||||
var $map = $("<div>");
|
||||
$grp.append($("<div>").addClass("col-md-9 col-md-offset-3").append($map));
|
||||
var map = L.map($map.get(0));
|
||||
L.tileLayer(tiles, {
|
||||
attribution: attrib,
|
||||
maxZoom: 18,
|
||||
}).addTo(map);
|
||||
var $lat = $sec.find("input[name$=geo_lat]");
|
||||
var $lon = $sec.find("input[name$=geo_lon]");
|
||||
$updateButton.click(function() {
|
||||
$lat.val(lat);
|
||||
$lon.val(lon).trigger("change");// change-event is needed by bulk-edit
|
||||
touched = false;
|
||||
center(13);
|
||||
$notifications.attr("data-notify", "updated");
|
||||
delayUpdateDismissal = window.setTimeout(function() {
|
||||
if ($notifications.attr("data-notify") == "updated") $notifications.attr("data-notify", "");
|
||||
}, 2500);
|
||||
});
|
||||
|
||||
function getpoint() {
|
||||
if ($lat.val() !== "" && $lon.val() !== "") {
|
||||
var p = [parseFloat($lat.val().replace(",", ".")), parseFloat($lon.val().replace(",", "."))];
|
||||
// Clip to valid ranges. Very invalid lon/lat values can even lead to browser crashes in leaflet apparently
|
||||
if (p[0] < -90) p[0] = -90
|
||||
if (p[0] > 90) p[0] = 90
|
||||
if (p[1] < -180) p[1] = -180
|
||||
if (p[1] > 180) p[1] = 180
|
||||
return p
|
||||
// Map
|
||||
var $grp = $(".geodata-group", this);
|
||||
var tiles = $grp.attr("data-tiles");
|
||||
var attrib = $grp.attr("data-attrib");
|
||||
if (tiles) {
|
||||
var $map = $("<div>");
|
||||
$grp.append($("<div>").addClass("col-md-9 col-md-offset-3").append($map));
|
||||
var map = L.map($map.get(0));
|
||||
L.tileLayer(tiles, {
|
||||
attribution: attrib,
|
||||
maxZoom: 18,
|
||||
}).addTo(map);
|
||||
|
||||
function getpoint() {
|
||||
if ($lat.val() !== "" && $lon.val() !== "") {
|
||||
var p = [parseFloat($lat.val().replace(",", ".")), parseFloat($lon.val().replace(",", "."))];
|
||||
// Clip to valid ranges. Very invalid lon/lat values can even lead to browser crashes in leaflet apparently
|
||||
if (p[0] < -90) p[0] = -90
|
||||
if (p[0] > 90) p[0] = 90
|
||||
if (p[1] < -180) p[1] = -180
|
||||
if (p[1] > 180) p[1] = 180
|
||||
return p
|
||||
} else {
|
||||
return [0.0, 0.0];
|
||||
}
|
||||
}
|
||||
|
||||
var marker = L.marker(getpoint(), {
|
||||
draggable: 'true',
|
||||
icon: L.icon({
|
||||
iconUrl: $grp.attr("data-icon"),
|
||||
shadowUrl: $grp.attr("data-shadow"),
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
tooltipAnchor: [16, -28],
|
||||
shadowSize: [41, 41]
|
||||
})
|
||||
});
|
||||
marker.addTo(map);
|
||||
marker.on("dragend", function (event) {
|
||||
var position = marker.getLatLng();
|
||||
marker.setLatLng(position, {
|
||||
draggable: 'true'
|
||||
}).bindPopup(position).update();
|
||||
$lat.val(position.lat.toFixed(7));
|
||||
$lon.val(position.lng.toFixed(7));
|
||||
touched = true;
|
||||
center(null);
|
||||
});
|
||||
|
||||
function center(zoom) {
|
||||
if ($lat.val() !== "" && $lon.val() !== "") {
|
||||
if (zoom) {
|
||||
map.setView(getpoint(), zoom);
|
||||
} else {
|
||||
map.panTo(getpoint());
|
||||
}
|
||||
marker.setLatLng(getpoint(), {
|
||||
draggable: 'true'
|
||||
}).bindPopup(getpoint()).update();
|
||||
} else {
|
||||
map.fitWorld();
|
||||
}
|
||||
}
|
||||
|
||||
center(13);
|
||||
} else {
|
||||
return [0.0, 0.0];
|
||||
function center(zoom) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var marker = L.marker(getpoint(), {
|
||||
draggable: 'true',
|
||||
icon: L.icon({
|
||||
iconUrl: $grp.attr("data-icon"),
|
||||
shadowUrl: $grp.attr("data-shadow"),
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
tooltipAnchor: [16, -28],
|
||||
shadowSize: [41, 41]
|
||||
})
|
||||
});
|
||||
marker.addTo(map);
|
||||
marker.on("dragend", function (event) {
|
||||
var position = marker.getLatLng();
|
||||
marker.setLatLng(position, {
|
||||
draggable: 'true'
|
||||
}).bindPopup(position).update();
|
||||
$lat.val(position.lat.toFixed(7));
|
||||
$lon.val(position.lng.toFixed(7));
|
||||
center(null);
|
||||
});
|
||||
|
||||
function center(zoom) {
|
||||
if ($lat.val() !== "" && $lon.val() !== "") {
|
||||
if (zoom) {
|
||||
map.setView(getpoint(), zoom);
|
||||
} else {
|
||||
map.panTo(getpoint());
|
||||
}
|
||||
marker.setLatLng(getpoint(), {
|
||||
draggable: 'true'
|
||||
}).bindPopup(getpoint()).update();
|
||||
} else {
|
||||
map.fitWorld();
|
||||
}
|
||||
}
|
||||
|
||||
center(13);
|
||||
} else {
|
||||
function center(zoom) {
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -241,6 +241,23 @@ div.mail-preview {
|
||||
input[type=number].short {
|
||||
width: 80px !important;
|
||||
}
|
||||
|
||||
.geodata-autoupdate {
|
||||
display: block;
|
||||
}
|
||||
.geodata-autoupdate .btn-link {
|
||||
padding: 0;
|
||||
}
|
||||
.geodata-autoupdate [data-notification] {
|
||||
display: none;
|
||||
}
|
||||
[data-notify=error] [data-notification=error],
|
||||
[data-notify=loading] [data-notification=loading],
|
||||
[data-notify=updated] [data-notification=updated],
|
||||
[data-notify=confirm] [data-notification=confirm] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.geodata-group {
|
||||
.form-group {
|
||||
margin: 0 0 10px 0;
|
||||
|
||||
Reference in New Issue
Block a user