Add track popups

This commit is contained in:
2025-05-03 11:56:04 +02:00
parent e878b159bf
commit 3571f93e41
6 changed files with 157 additions and 15 deletions

View File

@@ -8,7 +8,7 @@ class Settings
const DB_NAME = 'spot';
const DB_ENC = 'utf8mb4';
const TEXT_ENC = 'UTF-8';
const TIMEZONE = 'Europe/Paris';
const TIMEZONE = 'Europe/Zurich';
const MAIL_SERVER = '';
const MAIL_FROM = '';
const MAIL_USER = '';

View File

@@ -51,7 +51,6 @@ export default {
createElem(sType) {
this.spot.get2('admin_create', {type: sType})
.then((aoNewElemTypes) => {
console.log(aoNewElemTypes);
for(const [sType, aoNewElems] of Object.entries(aoNewElemTypes)) {
for(const [iKey, oNewElem] of Object.entries(aoNewElems)) {
oNewElem.type = sType;
@@ -60,7 +59,7 @@ export default {
}
}
})
.catch((sMsg) => {console.log(sMsg);this.spot.onFeedback('error', sMsg, {'create':sType});});
.catch((sMsg) => {this.spot.onFeedback('error', sMsg, {'create':sType});});
},
deleteElem(oElem) {
const asInputs = {

View File

@@ -1,7 +1,7 @@
<script>
import 'maplibre-gl/dist/maplibre-gl.css';
import { Map, NavigationControl, Marker, LngLatBounds, LngLat } from 'maplibre-gl';
import { Map, NavigationControl, Marker, LngLatBounds, LngLat, Popup } from 'maplibre-gl';
import { createApp, defineComponent, nextTick, ref, defineCustomElement, provide, inject } from 'vue';
import simplebar from 'simplebar-vue';
import autosize from 'autosize';
@@ -14,12 +14,14 @@ import lightbox from '../scripts/lightbox.js';
import SpotIcon from './spotIcon.vue';
import SpotButton from './spotButton.vue';
import ProjectPost from './projectPost.vue';
import ProjectPopup from './projectPopup.vue';
export default {
components: {
SpotIcon,
SpotButton,
ProjectPost,
ProjectPopup,
simplebar
},
data() {
@@ -73,7 +75,7 @@ export default {
watch: {
baseMap(sNewBaseMap, sOldBaseMap) {
if(sOldBaseMap) this.map.setLayoutProperty(sOldBaseMap, 'visibility', 'none');
this.map.setLayoutProperty(sNewBaseMap, 'visibility', 'visible');
if(sNewBaseMap) this.map.setLayoutProperty(sNewBaseMap, 'visibility', 'visible');
},
projectCodename(sNewCodeName, sOldCodeName) {
console.log('change in projectCodename: '+sNewCodeName);
@@ -158,6 +160,7 @@ export default {
async initMap() {
//Get Map Info
const aoMarkers = await this.spot.get2('markers', {id_project: this.project.id});
this.baseMap = null;
this.baseMaps = aoMarkers.maps;
this.messages = aoMarkers.messages;
@@ -193,7 +196,10 @@ export default {
});
this.map.once('load', async () => {
//Track
//Default Basemap
this.baseMap = this.baseMaps.filter((asBM) => asBM.default_map)[0].codename;
//Get track
const oTrack = await this.spot.get2('geojson', {id_project: this.project.id});
this.map.addSource('track', {
'type': 'geojson',
@@ -224,9 +230,91 @@ export default {
});
//Markers
let aoMarkerSource = {type:'geojson', data:{type: 'FeatureCollection', features: []}};
for(const oMsg of this.messages) {
new Marker().setLngLat(new LngLat(oMsg.longitude, oMsg.latitude)).addTo(this.map);
aoMarkerSource.data.features.push({
'type': 'Feature',
'properties': {
...oMsg,
...{'description': ''}
},
'geometry': {
'type': 'Point',
'coordinates': [oMsg.longitude, oMsg.latitude]
}
});
//Tooltip
/*
let $Tooltip = $($('<div>', {'class':'info-window'})
.append($('<h1>')
.addIcon('fa-message fa-lg', true)
.append($('<span>').text(this.spot.lang('post_message')+' '+this.spot.lang('counter', oMsg.displayed_id)))
.append($('<span>', {'class':'message-type'}).text('('+oMsg.type+')'))
)
.append($('<div>', {'class':'separator'}))
.append($('<p>', {'class':'coordinates'})
.addIcon('fa-coords fa-fw fa-lg', true)
.append(this.getGoogleMapsLink(oMsg))
)
.append($('<p>', {'class':'time'})
.addIcon('fa-time fa-fw fa-lg', true)
.append(oMsg.formatted_time+(this.project.mode==this.spot.consts.modes.blog?' ('+oMsg.relative_time+')':''))))[0];
const vTooltip = h(SpotIcon, {icon:'project', 'classes':'fa-fw', text:'hikes'});
//let vTooltip = h(SpotIcon, {icon:'project', 'classes':'fa-fw', text:'hikes'});
oPopup.setDOMContent(vTooltip);
new Marker({
element: $('<div style="width:'+this.markerSize.width+'px;height:'+this.markerSize.height+'px;"><span class="fa-stack"><i class="fa fa-message fa-stack-2x"></i><i class="fa fa-message-in fa-rotate-270 fa-stack-1x"></i></span></div>')[0],
anchor: 'bottom'
})
.setLngLat(new LngLat(oMsg.longitude, oMsg.latitude))
.setPopup(oPopup)
.addTo(this.map)
;
*/
}
this.map.addSource('markers', aoMarkerSource);
const image = await this.map.loadImage('https://maplibre.org/maplibre-gl-js/docs/assets/custom_marker.png');
this.map.addImage('markerIcon', image.data);
this.map.addLayer({
'id': 'markers',
'type': 'symbol',
'source': 'markers',
'layout': {
//'icon-anchor': 'bottom',
'icon-image': 'markerIcon'
//'icon-overlap': 'always'
}
});
this.map.on("click", "markers", (e) => {
var oPopup = new Popup({
anchor: 'bottom',
offset: [0, this.markerSize.height * -1],
closeButton: false
})
.setHTML('<div id="popup"></div>')
.setLngLat(e.lngLat)
.addTo(this.map);
let rProp = ref(e.features[0].properties);
const vPopup = defineComponent({
extends: ProjectPopup,
setup: () => {
console.log(rProp.value);
provide('options', rProp.value);
provide('spot', this.spot);
provide('project', this.project);
return {'options': rProp.value, 'spot':this.spot, 'project':this.project};
}
});
nextTick(() => {
createApp(vPopup).mount("#popup");
});
});
//Centering map
let bOpenFeedPanel = !this.mobile;
@@ -242,7 +330,6 @@ export default {
}
else {
//Fit to track
console.log('Fit to track');
for(const iFeatureId in oTrack.features) {
oBounds = oTrack.features[iFeatureId].geometry.coordinates.reduce(
(bounds, coord) => {
@@ -269,9 +356,6 @@ export default {
//Toggle only when map is ready, for the tilt effet
this.toggleFeedPanel(bOpenFeedPanel);
//Default Basemap
this.baseMap = this.baseMaps.filter((asBM)=>asBM.default_map)[0].codename;
});
this.map.on('idle', () => {
@@ -282,6 +366,14 @@ export default {
},
getGoogleMapsLink(asInfo) {
return $('<a>', {
href:'https://www.google.com/maps/place/'+asInfo.lat_dms+'+'+asInfo.lon_dms+'/@'+asInfo.latitude+','+asInfo.longitude+',10z',
title: this.spot.lang('see_on_google'),
target: '_blank',
rel: 'noreferrer noopener'
}).text(asInfo.lat_dms+' '+asInfo.lon_dms);
},
async getNextFeed() {
if(!this.feed.outOfData && !this.feed.loading) {

View File

@@ -0,0 +1,50 @@
<script>
import { options } from 'lightbox2';
import projectMapLink from './projectMapLink.vue';
import spotIcon from './spotIcon.vue';
import projectRelTime from './projectRelTime.vue';
export default {
components: {
spotIcon,
projectMapLink,
projectRelTime
},
//props: {
// options: Object,
//},
data() {
return {
}
},
//inject: ['options', 'spot', 'project'],
mounted() {
}
}
</script>
<template>
<div class="info-window">
<h1>
<spotIcon :icon="'message'" :classes="'fa-lg'" :text="spot.lang('post_message')+' '+spot.lang('counter', options.displayed_id)" />
<span class="message-type">({{ options.type }})</span>
</h1>
<div class="separator"></div>
<p class="coordinates">
<spotIcon :icon="'coords'" :classes="'fa-fw fa-lg'" :margin="true" />
<projectMapLink :options="options" />
</p>
<p class="time">
<spotIcon :icon="'time'" :classes="'fa-fw fa-lg'" :text="options.formatted_time" />
<span v-if="project.mode==spot.consts.modes.blog"> ({{ options.relative_time }})</span>
</p>
<p class="timezone" v-if="options.day_offset != '0'">
<spotIcon :icon="'timezone'" :classes="'fa-fw fa-lg'" :margin="true" />
<projectRelTime :localTime="options.formatted_time_local" :offset="options.day_offset" />
</p>
<p class="weather" v-if="options.weather_icon && options.weather_icon!='unknown'" :title="options.weather_cond==''?'':spot.lang(options.weather_cond)">
<spotIcon :icon="options.weather_icon" :classes="'fa-fw fa-lg'" :text="options.weather_temp+'°C'" />
</p>
</div>
</template>

View File

@@ -10,7 +10,8 @@ export default {
<template>
<span>
{{ localTime.substr(-5) }}
<sup v-if="offset != '0'" :title="offset+' '+spot.lang('unit_day')+' ('+localTime.substr(0, 5)+')'">{{ ' '+offset }}</sup>
<span>{{ localTime.substring(-5) }}</span>
<sup v-if="offset != '0'" :title="offset+' '+spot.lang('unit_day')+' ('+localTime.substring(0, 5)+')'">{{ ' '+offset }}</sup>
<span>&nbsp;{{ spot.lang('local_time', ' ').trim() }}</span>
</span>
</template>

View File

@@ -6,7 +6,7 @@
width: 100%;
/* Leaflet Popup */
.leaflet-popup-content {
.maplibregl-popup-content {
h1 {
font-size: 1.4em;