From c43539b640d04054cefc8e7f503ad6111130435c Mon Sep 17 00:00:00 2001 From: Franzz Date: Tue, 19 May 2026 17:49:06 +0200 Subject: [PATCH] Add project popup --- i18n/en.json | 1 + i18n/es.json | 1 + i18n/fr.json | 1 + lib/Project.php | 3 -- src/components/project.vue | 83 ++++++++++++++++++++++----------- src/components/projectPopup.vue | 12 ++++- 6 files changed, 69 insertions(+), 32 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index e8779d0..a05cf99 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -106,6 +106,7 @@ "new_message": "New message" }, "project": { + "wip": "In progress", "code_name": "Code name", "end": "End", "hikes": "Hikes", diff --git a/i18n/es.json b/i18n/es.json index ad673de..f66e48e 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -106,6 +106,7 @@ "new_message": "Mensaje nuevo" }, "project": { + "wip": "En curso", "code_name": "Nombre clave", "end": "Fin", "hikes": "Senderos", diff --git a/i18n/fr.json b/i18n/fr.json index 098d2e6..ba63ece 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -106,6 +106,7 @@ "new_message": "Nouveau message" }, "project": { + "wip": "En cours", "code_name": "Nom de code", "end": "Arrivée", "hikes": "Randonnées", diff --git a/lib/Project.php b/lib/Project.php index 0ddad32..4d00f68 100644 --- a/lib/Project.php +++ b/lib/Project.php @@ -144,12 +144,9 @@ class Project extends PhpObject { case 2: $asProject['mode'] = self::MODE_HISTO; break; } $asProject['editable'] = $this->isModeEditable($asProject['mode']); - - //$asProject['geofilepath'] = Spot::addTimestampToFilePath(GeoJson::getDistFilePath($sCodeName)); $asProject['gpxfilepath'] = Spot::addTimestampToFilePath(Gpx::getDistFilePath($sCodeName)); $asProject['codename'] = $sCodeName; $asProject['default'] = ($sCodeName == $sDefaultProjectCodeName); - //$asProject['center'] = [$asProject['latitude'], $asProject['longitude']]; } return $bSpecificProj?$asProject:$asProjects; } diff --git a/src/components/project.vue b/src/components/project.vue index 6d62d30..04fee38 100644 --- a/src/components/project.vue +++ b/src/components/project.vue @@ -217,7 +217,10 @@ export default { }, addMarkers: () => { this.addTrack(this.track); - this.markers.forEach(oMarker => this.addMarker(oMarker)); + this.markers.forEach(oMarker => this.addMarker( + oMarker, + () => this.openMarkerPopup(oMarker.id, oMarker.type) + )); } }); }, @@ -239,14 +242,16 @@ export default { }, addMarkers: () => { for(const asProject of Object.values(this.projects)) { - this.addMarker({ - subtype: 'project', - longitude: asProject.longitude, - latitude: asProject.latitude, - opacityWhenCovered: 0.3 - }, () => { - this.hash.items = [asProject.codename]; - }); + this.addMarker( + { + type: 'project', + subtype: 'project', + ...asProject, + opacityWhenCovered: 0.3 + }, + () => {this.hash.items = [asProject.codename];}, + (oEvent, oProject) => {this.openProjectPopup(oProject);} + ); } } }); @@ -352,28 +357,14 @@ export default { this.map.on('mouseenter', 'track-hitbox', () => {this.map.getCanvas().style.cursor = 'pointer';}); this.map.on('mouseleave', 'track-hitbox', () => {this.map.getCanvas().style.cursor = '';}); }, - openTrackPopup(oEvent) { + openProjectPopup(oProject) { this.closePopup(); this.openPopup({ - lnglat: oEvent.lngLat, - options: this.projects.getTrackInfo(oEvent.features[0], this.track, this.lang), + lnglat: [oProject.longitude, oProject.latitude], + options: oProject, + offset: [0, -32] //FIXME }); }, - addMarker(oMarker, fClickCallback=null) { - const $Marker = document.createElement('div'); - createApp(SpotIconStack, this.markerProps[oMarker.subtype]).mount($Marker); - - new Marker({element: $Marker, anchor: 'bottom', opacityWhenCovered: oMarker.opacityWhenCovered ?? 0}) - .setLngLat([oMarker.longitude, oMarker.latitude]) - .addTo(this.map) - .getElement() - .addEventListener('click', (oEvent) => { - oEvent.preventDefault(); - oEvent.stopPropagation(); - if(fClickCallback) fClickCallback(oEvent, oMarker); - else this.openMarkerPopup(oMarker.id, oMarker.type); - }); - }, openMarkerPopup(iMarkerId, sMarkerType) { this.closePopup(); let oMarker = this.markers.find((oCandidate) => oCandidate.id == iMarkerId && oCandidate.type == sMarkerType); @@ -383,6 +374,13 @@ export default { offset: [0, -32] //FIXME }); }, + openTrackPopup(oEvent) { + this.closePopup(); + this.openPopup({ + lnglat: oEvent.lngLat, + options: this.projects.getTrackInfo(oEvent.features[0], this.track, this.lang), + }); + }, openPopup({lnglat, options={}, offset=[0, 0]} = {}) { const $Popup = document.createElement('div'); this.popup.element = new Popup({ @@ -414,6 +412,32 @@ export default { this.popup.element = null; } }, + addMarker(oMarker, fClickCallback=null, fHoverCallback=null) { + const $Marker = document.createElement('div'); + createApp(SpotIconStack, this.markerProps[oMarker.subtype]).mount($Marker); + + const $MarkerElement = new Marker({element: $Marker, anchor: 'bottom', opacityWhenCovered: oMarker.opacityWhenCovered ?? 0}) + .setLngLat([oMarker.longitude, oMarker.latitude]) + .addTo(this.map) + .getElement(); + + if(fClickCallback) { + $MarkerElement.addEventListener('click', (oEvent) => { + oEvent.preventDefault(); + oEvent.stopPropagation(); + fClickCallback(oEvent, oMarker); + }); + } + + if(fHoverCallback) { + $MarkerElement.addEventListener('mouseenter', (oEvent) => { + fHoverCallback(oEvent, oMarker); + }); + $MarkerElement.addEventListener('mouseleave', () => { + this.closePopup(); + }); + } + }, getInitialMapBounds() { let oBounds = new LngLatBounds(); let oHashMarker; @@ -527,7 +551,10 @@ export default { //Add new Markers if(aoMarkers.length > 0) { this.markers.push(...aoMarkers); - aoMarkers.forEach(oMarker => this.addMarker(oMarker)); + aoMarkers.forEach(oMarker => this.addMarker( + oMarker, + () => this.openMarkerPopup(oMarker.id, oMarker.type) + )); } //Message Last Update diff --git a/src/components/projectPopup.vue b/src/components/projectPopup.vue index df18b0f..ecf6b2a 100644 --- a/src/components/projectPopup.vue +++ b/src/components/projectPopup.vue @@ -17,6 +17,13 @@ export default { }, inject: ['lang', 'consts', 'isMobile'], computed: { + activeTimeInterval() { + if(this.options.mode == this.consts.modes.blog) return this.lang.get('project.wip'); + + const sYearFrom = this.options.active_from.substr(0, 4); + const sYearTo = this.options.active_to.substr(0, 4); + return (sYearFrom == sYearTo)?sYearFrom:(sYearFrom + '-' + sYearTo); + }, timeinfo() { return (this.options.type == 'media')? { @@ -45,7 +52,7 @@ export default {