Switch to maxminddb for user location.

This commit is contained in:
Edward Betts 2021-07-06 17:24:14 +02:00
parent 792bfa176d
commit f60aa70472
3 changed files with 126 additions and 32 deletions

View file

@ -48,6 +48,15 @@
</span>
</button>
<div class="alert alert-primary alert-map" role="alert" v-if="area_too_big">
Zoom in to see Wikidata items on the map.
</div>
<div class="alert alert-primary alert-map text-center" role="alert" v-if="!area_too_big && this.too_many_items">
Found {{ this.item_count }} Wikidata items, too many to show on the map.<br>
Zoom in to see them.
</div>
<div id="edit-count" class="p-2" v-if="upload_state === undefined && edits.length">
<span>edits: {{ edits.length }}</span>
<button class="btn btn-primary btn-sm ms-2" @click="close_item(); view_edits=true">
@ -172,8 +181,8 @@
<table class="table table-sm table-hover">
<tbody>
<tr v-for="osm in edit.osm" class="osm-candidate">
<td class="text-end text-nowrap">
{{ osm.distance.toFixed(0) }}m
<td class="text-end">
<span class="text-nowrap">{{ osm.distance.toFixed(0) }}m</span><br>
<a
:href="'https://www.openstreetmap.org/' + osm.identifier"
target="_blank"
@ -352,7 +361,13 @@
</div>
<div v-if="current_item.nearby && current_item.nearby.length">
<strong>Possible OSM matches</strong><br>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="show-tags" v-model="show_tags">
<label class="form-check-label" for="show-tags">show tags</label>
</div>
<table class="table table-sm table-hover" @mouseleave="this.current_osm = undefined">
<tbody>
<tr
@ -361,10 +376,8 @@
:class="{ 'table-primary': osm.selected }"
@mouseenter="this.current_osm=osm"
@click="select_osm(current_item, osm)">
<td>
<input class="form-check-input" type="checkbox" v-model="osm.selected"/>
</td>
<td class="text-end text-nowrap">
<td class="text-nowrap">
<input class="form-check-input" type="checkbox" v-model="osm.selected" v-if="username" />
{{ osm.distance.toFixed(0) }}m
<a
:href="'https://www.openstreetmap.org/' + osm.identifier"
@ -397,6 +410,27 @@
<br>part of: {{ osm.part_of.join("; ") }}
</span>
<span v-if="osm.tags.ele">
<br>elevation: {{ osm.tags.ele }} m
</span>
<span v-if="osm.area && osm.area > 1000 * 1000">
<br>area: {{ (osm.area / (1000 * 1000)).toFixed(1) }} km²
</span>
<span v-if="osm.tags.wikidata">
<br>Wikidata tag:
<a :href="`https://wikidata.org/wiki/${osm.tags.wikidata}`">{{ osm.tags.wikidata }}</a>
</span>
<div class="card" v-if="show_tags">
<div class="card-body tag-card-body">
<span class="badge bg-secondary float-end">tags</span>
<div class="card-text" v-for="(value, key) of osm.tags">
<strong>{{ key }}</strong>:
{{ value.replace(/;/g, '; ') }}
</div>
</div>
</div>
</td>
</tr>
</tbody>
@ -460,6 +494,7 @@ export default {
startLat: Number,
startLon: Number,
startZoom: Number,
startRadius: Number,
username: String,
},
data() {
@ -500,9 +535,20 @@ export default {
changeset_id: undefined,
upload_state: undefined,
upload_progress: 0,
show_tags: false,
flag_show_hover_isa: false,
debug: false,
map_area: undefined,
item_count: undefined,
};
},
computed: {
area_too_big() {
return this.map_area > 1000 * 1000 * 1000;
},
too_many_items() {
return this.item_count > 400;
},
loading() {
return this.osm_loading || this.wikidata_loading;
},
@ -610,29 +656,39 @@ export default {
item.markers.forEach((marker) => {
var coords = marker.getLatLng();
var circle = L.circle(coords, { radius: 20, color: "orange" }).addTo(this.map);
var circle = L.circleMarker(coords, { radius: 20, color: "orange" }).addTo(this.map);
this.selected_circles.push(circle);
});
},
hover_isa(highlight_isa) {
// if (!this.flag_show_hover_isa) return;
this.drop_hover_circles();
for(const item of Object.values(this.selected_items)) {
var opacity = 0.9;
// var opacity = 0.9;
if (highlight_isa) {
var match = item.wikidata.isa_list.some(isa => isa == highlight_isa.qid);
opacity = match ? 1 : 0.2;
// opacity = match ? 1 : 0.2;
if (match) {
this.add_hover_circles(item);
}
}
this.set_item_opacity(item, opacity);
// this.set_item_opacity(item, opacity);
}
}
},
methods: {
bounds_area(bounds) {
var width = bounds.getSouthWest().distanceTo(bounds.getSouthEast());
var height = bounds.getSouthWest().distanceTo(bounds.getNorthWest());
return width * height;
},
bounds_param() {
return 'bounds=' + this.map.getBounds().toBBoxString();
},
close_edit_list() {
this.view_edits = false;
if (this.upload_state == 'done') {
@ -797,7 +853,7 @@ export default {
add_hover_circles(item) {
item.markers.forEach((marker) => {
var coords = marker.getLatLng();
var circle = L.circle(coords, { radius: 20 }).addTo(this.map);
var circle = L.circleMarker(coords, { radius: 20 }).addTo(this.map);
this.hover_circles.push(circle);
});
},
@ -946,10 +1002,10 @@ export default {
}
this.items = {};
clear_isa();
this.clear_isa();
},
load_wikidata_items() {
load_wikidata_items(bounds) {
this.load_button_pressed = true;
this.wikidata_loaded = false;
this.osm_loaded = false;
@ -958,8 +1014,7 @@ export default {
this.wikidata_loading = true;
this.osm_loading = true;
var bounds = this.map.getBounds();
bounds ||= this.map.getBounds();
var items_url = this.api_base_url + "/api/1/items";
var osm_objects_url = this.api_base_url + "/api/1/osm";
@ -1011,16 +1066,20 @@ export default {
this.hits = [];
});
},
auto_load() {
auto_load(bounds) {
console.log('auto_load');
var count_url = this.api_base_url + "/api/1/count";
var bounds = this.map.getBounds();
bounds ||= this.map.getBounds();
this.map_area = this.bounds_area(bounds);
if (this.area_too_big) {
this.item_count = undefined;
if (this.items) this.clear_items();
return;
}
var params = { bounds: bounds.toBBoxString() };
axios.get(count_url, { params: params }).then((response) => {
var count = response.data.count;
if (count < 1000) {
this.load_wikidata_items();
}
this.item_count = response.data.count;
if (!this.too_many_items) this.load_wikidata_items(bounds);
});
},
run_search() {
@ -1119,15 +1178,16 @@ export default {
var lat = this.startLat ?? 52.19679;
var lon = this.startLon ?? 0.15224;
this.center = [lat, lon];
this.zoom = this.startZoom || 16;
this.zoom = this.startZoom;
},
mounted() {
this.$nextTick(function () {
var options = {
center: this.center,
zoom: this.zoom,
zoom: this.zoom || 16,
};
var map = L.map("map", options);
var osm_url = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
var tile_url = "https://tile-c.openstreetmap.fr/hot/{z}/{x}/{y}.png";
@ -1136,14 +1196,23 @@ export default {
});
osm.addTo(map);
var bounds;
if (this.startRadius) {
console.log('radius:', this.startRadius);
var bounds = L.latLng(this.center).toBounds(this.startRadius * 2000);
map.fitBounds(bounds);
} else {
bounds = map.getBounds();
}
map.on("moveend", this.map_moved);
this.map = map;
this.detail_qid = this.qid_from_url();
if (this.detail_qid) {
this.load_wikidata_items();
this.load_wikidata_items(bounds);
} else {
this.auto_load();
this.auto_load(bounds);
}
});
@ -1174,6 +1243,13 @@ export default {
transform: translate(-50%, 0);
}
.alert-map {
position: absolute;
bottom: 2rem;
left: 67.5%;
transform: translate(-50%, 0);
}
#edit-count {
position: absolute;
top: 77px;
@ -1205,4 +1281,8 @@ export default {
width: 35%;
}
.tag-card-body {
padding: 0.5rem 0.5rem;
}
</style>

View file

@ -21,6 +21,7 @@
startLat: {{ lat }},
startLon: {{ lon }},
startZoom: {{ zoom }},
startRadius: {{ radius | tojson }},
username: {{ username | tojson }},
};

View file

@ -12,6 +12,7 @@ import flask_login
import json
import GeoIP
import re
import maxminddb
srid = 4326
re_point = re.compile(r'^POINT\((.+) (.+)\)$')
@ -24,6 +25,7 @@ login_manager = flask_login.LoginManager(app)
login_manager.login_view = 'login_route'
osm_api_base = 'https://api.openstreetmap.org/api/0.6'
maxminddb_reader = maxminddb.open_database(app.config["GEOLITE2"])
DB_URL = "postgresql:///matcher"
database.init_db(DB_URL)
@ -72,11 +74,14 @@ def check_for_tagged_qid(qid):
def geoip_user_record():
gi = GeoIP.open(app.config["GEOIP_DATA"], GeoIP.GEOIP_STANDARD)
remote_ip = request.remote_addr
remote_ip = request.get('ip', request.remote_addr)
return gi.record_by_addr(remote_ip)
def get_user_location():
remote_ip = request.args.get('ip', request.remote_addr)
return maxminddb_reader.get(remote_ip)["location"]
gir = geoip_user_record()
return (gir["latitude"], gir["longitude"]) if gir else None
@ -167,14 +172,15 @@ def old_map_location(zoom, lat, lng):
@app.route("/map")
def map_start_page():
location = get_user_location()
lat, lon = location
loc = get_user_location()
return redirect(url_for(
'map_location',
lat=f'{loc["latitude"]:.5f}',
lon=f'{loc["longitude"]:.5f}',
zoom=16,
lat=f'{lat:.5f}',
lon=f'{lon:.5f}',
radius=loc["accuracy_radius"],
ip=request.args.get('ip'),
))
@app.route("/map/<int:zoom>/<float(signed=True):lat>/<float(signed=True):lon>")
@ -182,7 +188,14 @@ def map_location(zoom, lat, lon):
user = flask_login.current_user
username = user.username if user.is_authenticated else None
return render_template("map.html", zoom=zoom, lat=lat, lon=lon, username=username)
return render_template(
"map.html",
zoom=zoom,
lat=lat,
lon=lon,
radius=request.args.get('radius'),
username=username
)
@app.route("/old_map")