Add edit preview
This commit is contained in:
parent
bfd0012eb5
commit
fc26c906a1
252
frontend/App.vue
252
frontend/App.vue
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
<div id="map">
|
<div id="map">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button ref="btn" id="load-btn" type="button" class="btn btn-primary btn-lg" @click="load_wikidata_items">
|
<button ref="btn" id="load-btn" type="button" class="btn btn-primary btn-lg" @click="load_wikidata_items">
|
||||||
<span v-if="!loading">
|
<span v-if="!loading">
|
||||||
Load Wikidata items
|
Load Wikidata items
|
||||||
|
@ -47,23 +48,135 @@
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div v-if="current_item && wd_item.image_list.length" class="modal fade" id="imageModal" tabindex="-1">
|
<div id="edit-count" class="p-2" v-if="edits.length">
|
||||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
<span>edits: {{ edits.length }}</span>
|
||||||
<div class="modal-content">
|
<button class="btn btn-primary btn-sm ms-2" @click="close_item(); view_edits=true">
|
||||||
<div class="modal-header">
|
<i class="fa fa-upload"></i> save
|
||||||
<h5 class="modal-title">Image from Wikidata</h5>
|
</button>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
<div v-if="current_item && wd_item.image_list.length" class="modal fade" id="imageModal" tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Image from Wikidata</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
<img class="img-fluid" :src="api_base_url + '/commons/' + wd_item.image_list[0]">
|
<img class="img-fluid" :src="api_base_url + '/commons/' + wd_item.image_list[0]">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="sidebar">
|
<div id="sidebar">
|
||||||
|
<div v-if="view_edits" class="p-2">
|
||||||
|
<div class="h3">
|
||||||
|
Upload to OpenStreetMap
|
||||||
|
<button type="button" class="btn-close float-end" @click="view_edits=false"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="!current_item">
|
<div class="card w-100 bg-light">
|
||||||
|
<div class="card-body">
|
||||||
|
<form>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="changesetComment" class="form-label">Changeset comment</label>
|
||||||
|
<input type="text" class="form-control" id="changesetComment" :value="changeset_comment">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Upload tags</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div class="card my-2 w-100" v-for="edit in edits_grouped_by_qid">
|
||||||
|
<div class="card-body">
|
||||||
|
<h4 class="card-title">
|
||||||
|
<a :href="qid_url(edit.qid)" target="_blank">
|
||||||
|
{{ edit.wikidata.label }}
|
||||||
|
</a> ({{ edit.qid }})
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<p class="card-text">
|
||||||
|
|
||||||
|
<span v-if="edit.wikidata.description">
|
||||||
|
<strong>description</strong><br/>
|
||||||
|
{{ edit.wikidata.description }}<br/>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<strong>item type</strong><br/>
|
||||||
|
<span
|
||||||
|
v-bind:key="`isa-${edit.qid}-${isa_qid}`"
|
||||||
|
v-for="isa_qid in edit.wikidata.isa_list">
|
||||||
|
<a :href="qid_url(isa_qid)" target="_blank">{{isa_labels[isa_qid]}}</a> ({{isa_qid}})
|
||||||
|
<br/>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span v-if="edit.wikidata.street_address.length">
|
||||||
|
<strong>street address</strong><br/>
|
||||||
|
{{ edit.wikidata.street_address[0] }}<br/>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<strong>OSM matches</strong>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<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
|
||||||
|
<a
|
||||||
|
:href="'https://www.openstreetmap.org/' + osm.identifier"
|
||||||
|
target="_blank"
|
||||||
|
@click.stop><i class="fa fa-map-o"></i></a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ osm.name || "no name" }}
|
||||||
|
<span v-for="(p, index) in osm.presets">
|
||||||
|
<span v-if="index != 0">, </span>
|
||||||
|
<a
|
||||||
|
:href="'http://wiki.openstreetmap.org/wiki/' + p.tag_or_key"
|
||||||
|
class="osm-wiki-link"
|
||||||
|
target="_blank"
|
||||||
|
@click.stop>{{p.name}} <i class="fa fa-external-link"></i></a>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span v-if="osm.address">
|
||||||
|
<br>street address: {{ osm.address }}
|
||||||
|
</span>
|
||||||
|
<span v-else-if="osm.tags['addr:street']">
|
||||||
|
<br>street: {{ osm.tags['addr:street'] }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span v-if="osm.address_list.length">
|
||||||
|
<br>address nodes: {{ osm.address_list.join("; ") }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span v-if="osm.part_of">
|
||||||
|
<br>part of: {{ osm.part_of.join("; ") }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<span v-if="osm.selected">
|
||||||
|
add tag: <span class="badge bg-success">wikidata={{ edit.qid }}</span>
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
remove tag: <span class="badge bg-danger">wikidata={{ edit.qid }}</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="!current_item && !view_edits">
|
||||||
|
|
||||||
<div class="card m-2">
|
<div class="card m-2">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
@ -88,7 +201,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card m-2" v-if="isa_list.length">
|
|
||||||
|
<div class="card m-2" v-if="!view_edits && isa_list.length">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="h5 card-title">OSM/Wikidata link status</div>
|
<div class="h5 card-title">OSM/Wikidata link status</div>
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
|
@ -110,7 +224,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card m-2" v-if="isa_list.length" id="isa-card">
|
<div class="card m-2" v-if="!view_edits && isa_list.length" id="isa-card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="h5 card-title">item types</div>
|
<div class="h5 card-title">item types</div>
|
||||||
<div><a href="#" @click.prevent="isa_tick_all">show all</a></div>
|
<div><a href="#" @click.prevent="isa_tick_all">show all</a></div>
|
||||||
|
@ -155,14 +269,17 @@
|
||||||
<br>{{wd_item.street_address[0]}}
|
<br>{{wd_item.street_address[0]}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</div><div class="col">
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
|
||||||
<span v-if="current_item.tag_or_key_list && current_item.tag_or_key_list.length">
|
<div v-if="current_item.tag_or_key_list && current_item.tag_or_key_list.length">
|
||||||
<strong>OSM tags/keys to search for</strong>
|
<strong>OSM tags/keys to search for</strong><br/>
|
||||||
<span v-for="v in current_item.tag_or_key_list">
|
{{ current_item.tag_or_key_list.length }} tags/keys to consider
|
||||||
<br>{{ v }}
|
<a href="#" @click="show_tag_or_key_list = !show_tag_or_key_list">show/hide</a><br/>
|
||||||
</span>
|
<div v-if="show_tag_or_key_list">
|
||||||
</span>
|
<div v-for="v in current_item.tag_or_key_list">{{ v }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<span v-if="wd_item.image_list.length">
|
<span v-if="wd_item.image_list.length">
|
||||||
<a href="#" data-bs-toggle="modal" data-bs-target="#imageModal">
|
<a href="#" data-bs-toggle="modal" data-bs-target="#imageModal">
|
||||||
|
@ -184,10 +301,18 @@
|
||||||
<tr
|
<tr
|
||||||
v-for="osm in current_item.nearby"
|
v-for="osm in current_item.nearby"
|
||||||
class="osm-candidate"
|
class="osm-candidate"
|
||||||
@mouseenter="this.current_osm=osm">
|
: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-end text-nowrap">
|
||||||
{{ osm.distance.toFixed(0) }}m
|
{{ osm.distance.toFixed(0) }}m
|
||||||
<a :href="'https://www.openstreetmap.org/' + osm.identifier" target="_blank"><i class="fa fa-map-o"></i></a>
|
<a
|
||||||
|
:href="'https://www.openstreetmap.org/' + osm.identifier"
|
||||||
|
target="_blank"
|
||||||
|
@click.stop><i class="fa fa-map-o"></i></a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ osm.name || "no name" }}
|
{{ osm.name || "no name" }}
|
||||||
|
@ -297,6 +422,10 @@ export default {
|
||||||
selected_circles: [],
|
selected_circles: [],
|
||||||
hover_isa: undefined,
|
hover_isa: undefined,
|
||||||
detail_qid: undefined,
|
detail_qid: undefined,
|
||||||
|
show_tag_or_key_list: undefined,
|
||||||
|
edits: [],
|
||||||
|
view_edits: false,
|
||||||
|
changeset_comment: "Add wikidata tag",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -340,7 +469,29 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
},
|
||||||
|
edits_grouped_by_qid() {
|
||||||
|
var qid_order = [];
|
||||||
|
var edit_lookup = {};
|
||||||
|
|
||||||
|
this.edits.forEach((edit) => {
|
||||||
|
var qid = edit.item.qid;
|
||||||
|
|
||||||
|
if (!edit_lookup[qid]) {
|
||||||
|
qid_order.push(qid);
|
||||||
|
console.log(edit.item);
|
||||||
|
edit_lookup[qid] = {
|
||||||
|
'qid': qid,
|
||||||
|
'wikidata': edit.item.wikidata,
|
||||||
|
'osm': [],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
edit_lookup[qid].osm.push(edit.osm);
|
||||||
|
});
|
||||||
|
|
||||||
|
return qid_order.map((qid) => edit_lookup[qid]);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
selected_items(new_items, old_items) {
|
selected_items(new_items, old_items) {
|
||||||
|
@ -404,6 +555,28 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
edit_list_index(item, osm) {
|
||||||
|
var index = -1;
|
||||||
|
for (var i = 0; i < this.edits.length; i++) {
|
||||||
|
var edit = this.edits[i];
|
||||||
|
if (edit.item.qid == item.qid &&
|
||||||
|
edit.osm.identifier == osm.identifier) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
},
|
||||||
|
select_osm(item, osm) {
|
||||||
|
osm.selected = !osm.selected;
|
||||||
|
var index = this.edit_list_index(item, osm);
|
||||||
|
|
||||||
|
if (index == -1) {
|
||||||
|
this.edits.push({'item': item, 'osm': osm});
|
||||||
|
} else {
|
||||||
|
this.edits.splice(index, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
qid_from_url() {
|
qid_from_url() {
|
||||||
const queryString = window.location.search;
|
const queryString = window.location.search;
|
||||||
const urlParams = new URLSearchParams(queryString);
|
const urlParams = new URLSearchParams(queryString);
|
||||||
|
@ -495,9 +668,11 @@ export default {
|
||||||
},
|
},
|
||||||
open_item(qid) {
|
open_item(qid) {
|
||||||
var item = this.items[qid];
|
var item = this.items[qid];
|
||||||
|
this.view_edits = false;
|
||||||
this.current_osm = undefined;
|
this.current_osm = undefined;
|
||||||
this.current_item = item;
|
this.current_item = item;
|
||||||
this.update_map_path();
|
this.update_map_path();
|
||||||
|
this.hover_isa = undefined;
|
||||||
|
|
||||||
if (item.detail_requested !== undefined) return;
|
if (item.detail_requested !== undefined) return;
|
||||||
item.detail_requested = true;
|
item.detail_requested = true;
|
||||||
|
@ -514,7 +689,20 @@ export default {
|
||||||
|
|
||||||
axios.get(item_osm_candidates_url, { params: params }).then((response) => {
|
axios.get(item_osm_candidates_url, { params: params }).then((response) => {
|
||||||
var qid = response.data.qid;
|
var qid = response.data.qid;
|
||||||
this.items[qid].nearby = response.data.nearby;
|
var item = this.items[qid];
|
||||||
|
var osm_identifiers = []
|
||||||
|
|
||||||
|
if (item.osm) {
|
||||||
|
item.osm.forEach((osm) => { osm_identifiers.push(osm.identifier); });
|
||||||
|
}
|
||||||
|
|
||||||
|
item.nearby = response.data.nearby;
|
||||||
|
item.nearby.forEach((osm) => {
|
||||||
|
osm.selected = osm_identifiers.includes(osm.identifier);
|
||||||
|
if (this.edits.length && this.edit_list_index(item, osm) != -1) {
|
||||||
|
osm.selected = !osm.selected;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
close_item() {
|
close_item() {
|
||||||
|
@ -545,7 +733,7 @@ export default {
|
||||||
process_wikidata_items(load_items) {
|
process_wikidata_items(load_items) {
|
||||||
load_items.forEach(item => {
|
load_items.forEach(item => {
|
||||||
var qid = item.qid;
|
var qid = item.qid;
|
||||||
this.items[qid] ||= {};
|
this.items[qid] ||= {'qid': qid};
|
||||||
if (this.items[qid].wikidata) return;
|
if (this.items[qid].wikidata) return;
|
||||||
this.items[qid].wikidata = item;
|
this.items[qid].wikidata = item;
|
||||||
var group = this.items[qid].group ||= L.featureGroup();
|
var group = this.items[qid].group ||= L.featureGroup();
|
||||||
|
@ -607,12 +795,13 @@ export default {
|
||||||
this.wikidata_loading = false;
|
this.wikidata_loading = false;
|
||||||
|
|
||||||
this.check_for_missing();
|
this.check_for_missing();
|
||||||
|
this.hits = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
axios.get(osm_objects_url, { params: params }).then((response) => {
|
axios.get(osm_objects_url, { params: params }).then((response) => {
|
||||||
response.data.objects.forEach((osm) => {
|
response.data.objects.forEach((osm) => {
|
||||||
var qid = osm.wikidata;
|
var qid = osm.wikidata;
|
||||||
this.items[qid] ||= {};
|
this.items[qid] ||= {'qid': qid};
|
||||||
this.items[qid].osm ||= [];
|
this.items[qid].osm ||= [];
|
||||||
this.items[qid].osm.push(osm);
|
this.items[qid].osm.push(osm);
|
||||||
var group = this.items[qid].group ||= L.featureGroup();
|
var group = this.items[qid].group ||= L.featureGroup();
|
||||||
|
@ -798,6 +987,13 @@ export default {
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#edit-count {
|
||||||
|
position: absolute;
|
||||||
|
top: 77px;
|
||||||
|
right: 80px;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
#search {
|
#search {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
Loading…
Reference in a new issue