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>
|
||||
|
||||
<button ref="btn" id="load-btn" type="button" class="btn btn-primary btn-lg" @click="load_wikidata_items">
|
||||
<span v-if="!loading">
|
||||
Load Wikidata items
|
||||
|
@ -47,23 +48,135 @@
|
|||
</span>
|
||||
</button>
|
||||
|
||||
<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">
|
||||
<div id="edit-count" class="p-2" v-if="edits.length">
|
||||
<span>edits: {{ edits.length }}</span>
|
||||
<button class="btn btn-primary btn-sm ms-2" @click="close_item(); view_edits=true">
|
||||
<i class="fa fa-upload"></i> save
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<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]">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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-body">
|
||||
|
@ -88,7 +201,8 @@
|
|||
</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="h5 card-title">OSM/Wikidata link status</div>
|
||||
<div class="list-group">
|
||||
|
@ -110,7 +224,7 @@
|
|||
</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="h5 card-title">item types</div>
|
||||
<div><a href="#" @click.prevent="isa_tick_all">show all</a></div>
|
||||
|
@ -155,14 +269,17 @@
|
|||
<br>{{wd_item.street_address[0]}}
|
||||
</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">
|
||||
<strong>OSM tags/keys to search for</strong>
|
||||
<span v-for="v in current_item.tag_or_key_list">
|
||||
<br>{{ v }}
|
||||
</span>
|
||||
</span>
|
||||
<div v-if="current_item.tag_or_key_list && current_item.tag_or_key_list.length">
|
||||
<strong>OSM tags/keys to search for</strong><br/>
|
||||
{{ current_item.tag_or_key_list.length }} tags/keys to consider
|
||||
<a href="#" @click="show_tag_or_key_list = !show_tag_or_key_list">show/hide</a><br/>
|
||||
<div v-if="show_tag_or_key_list">
|
||||
<div v-for="v in current_item.tag_or_key_list">{{ v }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span v-if="wd_item.image_list.length">
|
||||
<a href="#" data-bs-toggle="modal" data-bs-target="#imageModal">
|
||||
|
@ -184,10 +301,18 @@
|
|||
<tr
|
||||
v-for="osm in current_item.nearby"
|
||||
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">
|
||||
{{ 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>
|
||||
{{ osm.name || "no name" }}
|
||||
|
@ -297,6 +422,10 @@ export default {
|
|||
selected_circles: [],
|
||||
hover_isa: undefined,
|
||||
detail_qid: undefined,
|
||||
show_tag_or_key_list: undefined,
|
||||
edits: [],
|
||||
view_edits: false,
|
||||
changeset_comment: "Add wikidata tag",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -340,7 +469,29 @@ export default {
|
|||
}
|
||||
}
|
||||
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: {
|
||||
selected_items(new_items, old_items) {
|
||||
|
@ -404,6 +555,28 @@ export default {
|
|||
}
|
||||
},
|
||||
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() {
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
|
@ -495,9 +668,11 @@ export default {
|
|||
},
|
||||
open_item(qid) {
|
||||
var item = this.items[qid];
|
||||
this.view_edits = false;
|
||||
this.current_osm = undefined;
|
||||
this.current_item = item;
|
||||
this.update_map_path();
|
||||
this.hover_isa = undefined;
|
||||
|
||||
if (item.detail_requested !== undefined) return;
|
||||
item.detail_requested = true;
|
||||
|
@ -514,7 +689,20 @@ export default {
|
|||
|
||||
axios.get(item_osm_candidates_url, { params: params }).then((response) => {
|
||||
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() {
|
||||
|
@ -545,7 +733,7 @@ export default {
|
|||
process_wikidata_items(load_items) {
|
||||
load_items.forEach(item => {
|
||||
var qid = item.qid;
|
||||
this.items[qid] ||= {};
|
||||
this.items[qid] ||= {'qid': qid};
|
||||
if (this.items[qid].wikidata) return;
|
||||
this.items[qid].wikidata = item;
|
||||
var group = this.items[qid].group ||= L.featureGroup();
|
||||
|
@ -607,12 +795,13 @@ export default {
|
|||
this.wikidata_loading = false;
|
||||
|
||||
this.check_for_missing();
|
||||
this.hits = [];
|
||||
});
|
||||
|
||||
axios.get(osm_objects_url, { params: params }).then((response) => {
|
||||
response.data.objects.forEach((osm) => {
|
||||
var qid = osm.wikidata;
|
||||
this.items[qid] ||= {};
|
||||
this.items[qid] ||= {'qid': qid};
|
||||
this.items[qid].osm ||= [];
|
||||
this.items[qid].osm.push(osm);
|
||||
var group = this.items[qid].group ||= L.featureGroup();
|
||||
|
@ -798,6 +987,13 @@ export default {
|
|||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
#edit-count {
|
||||
position: absolute;
|
||||
top: 77px;
|
||||
right: 80px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
#search {
|
||||
position: absolute;
|
||||
overflow: auto;
|
||||
|
|
Loading…
Reference in a new issue