From 2d5955a202c9f25bb523a2e58c7f5316ad4a4e12 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Sun, 11 Jun 2023 14:05:02 +0200 Subject: [PATCH 1/2] implmenetation of a coordinate picker --- .../src/components/DetailsInfoSection.vue | 4 +- .../src/components/DetailsInteractiveMap.vue | 14 -- .../feedback/DetailsCoordinatePicker.vue | 121 +++++++++++++++++ .../{ => feedback}/DetailsFeedbackButton.vue | 0 .../components/feedback/EditRequestModal.vue | 41 ++++++ webclient/src/locales/de.yaml | 19 +++ webclient/src/locales/en.yaml | 6 + webclient/src/pages/view/[id].vue | 122 +++++++++++++++++- webclient/src/stores/global.ts | 8 ++ 9 files changed, 317 insertions(+), 18 deletions(-) create mode 100644 webclient/src/components/feedback/DetailsCoordinatePicker.vue rename webclient/src/components/{ => feedback}/DetailsFeedbackButton.vue (100%) create mode 100644 webclient/src/components/feedback/EditRequestModal.vue diff --git a/webclient/src/components/DetailsInfoSection.vue b/webclient/src/components/DetailsInfoSection.vue index c1dfb4feb..cf9f27eae 100644 --- a/webclient/src/components/DetailsInfoSection.vue +++ b/webclient/src/components/DetailsInfoSection.vue @@ -35,9 +35,7 @@ const state = useDetailsStore();
-
- {{ $t("view_view.msg.inaccurate_only_building.primary_msg") }}
-
+
+import { selectedMap, useDetailsStore } from "@/stores/details"; +import { Coord, useGlobalStore } from "@/stores/global"; +import { ref } from "vue"; +import { getLocalStorageWithExpiry, setLocalStorageWithExpiry } from "@/composables/storage"; +const state = useDetailsStore(); +const global = useGlobalStore(); +// The coordinate picker keeps backups of the subject and body +// in case someone writes a text and then after that clicks +// the set coordinate button in the feedback form. +// If we no backup has been made then, this would be lost after clicking confirm there. +const coord_picker = ref({ + backup_id: null as string | null, + subject_backup: null as string | null, + body_backup: null as string | null, + force_reopen: false, +}); +const emit = defineEmits<{ + (e: "openFeedbackForm", callback: EventListener): void; +}>(); + +function addLocationPicker() { + // If this is called from the feedback form using the edit coordinate + // button, we temporarily save the current subject and body, so it is + // not lost when being reopened + if (global.feedback.open) { + coord_picker.value.backup_id = state.data?.id || "undefined"; + coord_picker.value.subject_backup = global.feedback.subject; + coord_picker.value.body_backup = global.feedback.body; + coord_picker.value.force_reopen = true; // reopen after confirm + + global.temporarilyCloseFeedback(); + } + + state.map.selected = selectedMap.interactive; + + // Verify that there isn't already a marker (could happen if you click 'assign + // a location' multiple times from the 'missing accurate location' toast) + if (marker2.value === null) { + // Coordinates are either taken from the entry, or if there are already + // some in the localStorage use them + const currentEdits = getLocalStorageWithExpiry<{ [index: string]: Coord }>("feedback-coords", {}); + + const { coords } = currentEdits[state.data?.id || "undefined"] || state.data; + marker2.value = new Marker({ + draggable: true, + color: "#ff0000", + }); + if (coords.lat !== undefined && coords.lon !== undefined) + marker2.value.setLngLat([coords.lon, coords.lat]).addTo(map.value as Map); + } +} +function confirmLocationPicker() { + // add the current edits to the feedback + const currentEdits = getLocalStorageWithExpiry<{ [index: string]: Coord }>("feedback-coords", {}); + const location = marker2.value?.getLngLat(); + currentEdits[state.data?.id || "undefined"] = { + coords: { lat: location?.lat, lon: location?.lng }, + }; + // save to local storage with ttl of 12h (garbage-collected on next read) + setLocalStorageWithExpiry("feedback-coords", currentEdits, 12); + + marker2.value?.remove(); + marker2.value = null; + + // A feedback form is only opened when this is the only (and therefore + // first coordinate). If there are more coordinates we can assume + // someone is doing batch edits. They can then use the send button in + // the coordinate counter at the top of the page. + if (Object.keys(currentEdits).length === 1 || state.coord_picker.force_reopen) { + state.coord_picker.force_reopen = false; + emit("openFeedbackForm", () => addLocationPicker()); + } + + // The helptext (which says thet you can edit multiple coordinates in bulk) + // is also only shown if there is one edit. + if (Object.keys(currentEdits).length === 1) { + document.getElementById("feedback-coordinate-picker-helptext")?.classList.remove("d-none"); + } +} +function cancelLocationPicker() { + marker2.value?.remove(); + marker2.value = null; + + if (state.coord_picker.force_reopen) { + state.coord_picker.force_reopen = false; + emit("openFeedbackForm", () => addLocationPicker()); + } +} + + + diff --git a/webclient/src/components/DetailsFeedbackButton.vue b/webclient/src/components/feedback/DetailsFeedbackButton.vue similarity index 100% rename from webclient/src/components/DetailsFeedbackButton.vue rename to webclient/src/components/feedback/DetailsFeedbackButton.vue diff --git a/webclient/src/components/feedback/EditRequestModal.vue b/webclient/src/components/feedback/EditRequestModal.vue new file mode 100644 index 000000000..9ee27399b --- /dev/null +++ b/webclient/src/components/feedback/EditRequestModal.vue @@ -0,0 +1,41 @@ + + +