diff --git a/src/components/project.vue b/src/components/project.vue index 95f4a1c..6526498 100644 --- a/src/components/project.vue +++ b/src/components/project.vue @@ -32,8 +32,8 @@ export default { feedSimpleBar: null, settingsPanelOpen: false, markerSize: {width: 32, height: 32}, - project: {}, - projectCodename: null, + currProject: {}, + currProjectCodeName: null, modeHisto: false, posts: [], nlFeedbacks: [], @@ -45,7 +45,8 @@ export default { hikes: { colors:{'main':'#00ff78', 'off-track':'#0000ff', 'hitchhiking':'#FF7814'}, width: 4 - } + }, + popup: null }; }, computed: { @@ -76,8 +77,8 @@ export default { if(sOldBaseMap) this.map.setLayoutProperty(sOldBaseMap, 'visibility', 'none'); if(sNewBaseMap) this.map.setLayoutProperty(sNewBaseMap, 'visibility', 'visible'); }, - projectCodename(sNewCodeName, sOldCodeName) { - //console.log('change in projectCodename: '+sNewCodeName); + currProjectCodeName(sNewCodeName, sOldCodeName) { + //console.log('change in currProjectCodeName: '+sNewCodeName); //this.toggleSettingsPanel(false); this.$parent.setHash(this.$parent.hash.page, [sNewCodeName]); this.init(); @@ -85,7 +86,14 @@ export default { }, provide() { return { - project: this.project + map: { + panTo: this.panTo, + openMarkerPopup: this.openMarkerPopup + }, + project: { + ...this.$data, + toggleFeedPanel: this.toggleFeedPanel + } }; }, inject: ['spot', 'projects', 'user'], @@ -102,19 +110,19 @@ export default { } }); - this.projectCodename = (this.$parent.hash.items.length==0)?this.spot.vars('default_project_codename'):this.$parent.hash.items[0]; + this.currProjectCodeName = (this.$parent.hash.items.length==0)?this.spot.vars('default_project_codename'):this.$parent.hash.items[0]; }, methods: { init() { - let bFirstLoad = (typeof this.project.codename == 'undefined'); + let bFirstLoad = (typeof this.currProject.codename == 'undefined'); this.initProject(); if(bFirstLoad) this.initLightbox(); this.initFeed(); this.initMap(); }, initProject() { - this.project = this.projects[this.projectCodename]; - this.modeHisto = (this.project.mode == this.spot.consts.modes.histo); + this.currProject = this.projects[this.currProjectCodeName]; + this.modeHisto = (this.currProject.mode == this.spot.consts.modes.histo); this.feed = {loading:false, updatable:true, outOfData:false, refIdFirst:0, refIdLast:0, firstChunk:true}; this.posts = []; //this.baseMap = null; @@ -153,7 +161,7 @@ export default { }, async initMap() { //Get Map Info - const aoMarkers = await this.spot.get2('markers', {id_project: this.project.id}); + const aoMarkers = await this.spot.get2('markers', {id_project: this.currProject.id}); this.baseMap = null; this.baseMaps = aoMarkers.maps; this.messages = aoMarkers.messages; @@ -194,7 +202,7 @@ export default { 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}); + const oTrack = await this.spot.get2('geojson', {id_project: this.currProject.id}); this.map.addSource('track', { 'type': 'geojson', 'data': oTrack @@ -237,38 +245,6 @@ export default { 'coordinates': [oMsg.longitude, oMsg.latitude] } }); - //Tooltip - /* - let $Tooltip = $($('
', {'class':'info-window'}) - .append($('

') - .addIcon('fa-message fa-lg', true) - .append($('').text(this.spot.lang('post_message')+' '+this.spot.lang('counter', oMsg.displayed_id))) - .append($('', {'class':'message-type'}).text('('+oMsg.type+')')) - ) - .append($('
', {'class':'separator'})) - .append($('

', {'class':'coordinates'}) - .addIcon('fa-coords fa-fw fa-lg', true) - .append(this.getGoogleMapsLink(oMsg)) - ) - .append($('

', {'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: $('

')[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('images/footprint_mapbox.png'); @@ -283,38 +259,16 @@ export default { //'icon-overlap': 'always' } }); - this.map.on("click", "markers", (e) => { - var oPopup = new Popup({ - anchor: 'bottom', - offset: [0, this.markerSize.height * -1], - closeButton: false - }) - .setHTML('') - .setLngLat(e.lngLat) - .addTo(this.map); - let rProp = ref(e.features[0].properties);console.log(rProp); - const vPopup = defineComponent({ - extends: ProjectPopup, - setup: () => { - //console.log(rProp.value.medias); - provide('options', rProp.value); - provide('spot', this.spot); - provide('project', this.project); - return {'options': rProp.value, 'medias': JSON.parse(rProp.value.medias || '""'), 'spot':this.spot, 'project':this.project}; - } - }); - nextTick(() => { - createApp(vPopup).mount("#popup"); - }); + this.map.on('click', 'markers', (e) => { + this.openMarkerPopup(e.features[0]); }); - //Centering map let bOpenFeedPanel = !this.mobile; let oBounds = new LngLatBounds(); if( - this.project.mode == this.spot.consts.modes.blog && + this.currProject.mode == this.spot.consts.modes.blog && this.messages.length > 0 && this.$parent.hash.items[2] != 'message' ) { @@ -352,14 +306,69 @@ export default { this.toggleFeedPanel(bOpenFeedPanel); }); - this.map.on('idle', () => { - - }); + this.map.on('idle', () => { }); //Legend - - + }, + openMarkerPopup(oFeature) { + if(this.popup) { + this.popup.unmount(); + this.popup = null; + } + //Convert ID Message to feature + if(typeof oFeature == 'number') { + const oMatchingFeatures = this.map.querySourceFeatures('markers', { + filter: ['==', ['get', 'id_message'], oFeature] + }); + + if(!oMatchingFeatures.length) { + console.warn('Marker not found: ', oFeature); + return; + } + else oFeature = oMatchingFeatures[0]; + } + + const $Popup = document.createElement('div'); + const oPopup = new Popup({ + anchor: 'bottom', + offset: [0, this.markerSize.height * -1], + closeButton: false + }) + .setDOMContent($Popup) + .setLngLat(oFeature.geometry.coordinates) + .setMaxWidth(300) + .addTo(this.map); + + const rProp = ref(oFeature.properties); + + const vPopup = defineComponent({ + extends: ProjectPopup, + setup: () => { + provide('spot', this.spot); + return { + options: rProp.value, + medias: JSON.parse(rProp.value.medias || '""'), + spot: this.spot, + project: this.currProject + }; + } + }); + + nextTick(() => { + this.popup = createApp(vPopup); + this.popup.mount($Popup); + }); + }, + panTo(oLngLat, iZoom, fCallback) { + const iXOffset = (this.settingsPanelOpen?getOuterWidth(this.$refs.settings):0) - (this.feedPanelOpen?getOuterWidth(this.$refs.feed):0); + this.map.easeTo({ + center: oLngLat, + zoom: iZoom, + offset: [iXOffset / 2, 0], + duration: 500 + }); + setTimeout(fCallback, 500); }, getGoogleMapsLink(asInfo) { return $('', { @@ -373,7 +382,7 @@ export default { if(!this.feed.outOfData && !this.feed.loading) { //Get next chunk this.feed.loading = true; - let aoData = await this.spot.get2('next_feed', {id_project: this.project.id, id: this.feed.refIdLast}); + let aoData = await this.spot.get2('next_feed', {id_project: this.currProject.id, id: this.feed.refIdLast}); let iPostCount = Object.keys(aoData.feed).length; this.feed.loading = false; this.feed.firstChunk = false; @@ -514,10 +523,10 @@ export default {

- {{ project.name }} + {{ currProject.name }}
diff --git a/src/components/projectPost.vue b/src/components/projectPost.vue index 4aa03f3..008bd83 100644 --- a/src/components/projectPost.vue +++ b/src/components/projectPost.vue @@ -4,6 +4,7 @@ import projectMediaLink from './projectMediaLink.vue'; import projectMapLink from './projectMapLink.vue'; import projectRelTime from './projectRelTime.vue'; + import { LngLat } from 'maplibre-gl'; import autosize from 'autosize'; @@ -48,14 +49,14 @@ return '#'+[asHash.page, asHash.items[0], this.options.type, this.options.id].join(this.spot.consts.hash_sep); }, modeHisto() { - return (this.project.mode==this.spot.consts.modes.histo); + return (this.project.currProject.mode==this.spot.consts.modes.histo); }, relTime() { return this.modeHisto?(this.options.formatted_time || '').substr(0, 10):this.options.relative_time; }, }, - inject: ['spot', 'project', 'user'], + inject: ['spot', 'project', 'user', 'map', 'project'], methods: { copyAnchor() { copyTextToClipboard(this.spot.consts.server+this.spot.hash()); @@ -67,23 +68,12 @@ }, 5000); }, panMapToMessage() { - //TODO - /* - var $Parent = $(oEvent.currentTarget).parent(); - var oMarker = this.spot.tmp(['markers', $Parent.data('id')]); - if(this.isMobile()) { - this.toggleFeedPanel(false, 'panToInstant'); - this.spot.tmp('map').setView(oMarker.getLatLng(), 15); - } - else { - var iOffset = (this.isFeedPanelOpen()?1:-1)*this.spot.tmp('$Feed').outerWidth(true)/2 - (this.isSettingsPanelOpen()?1:-1)*this.spot.tmp('$Settings').outerWidth(true)/2; - var iRatio = -1 * iOffset / $('body').outerWidth(true); - this.spot.tmp('map').setOffsetView(iRatio, oMarker.getLatLng(), 15); - } - - $Parent.data('clicked', true); - if(!oMarker.isPopupOpen()) oMarker.openPopup(); - */ + if(this.spot.isMobile()) this.project.toggleFeedPanel(false, 'panToInstant'); + this.map.panTo( + new LngLat(this.options.longitude, this.options.latitude), + 15, + () => {this.map.openMarkerPopup(this.options.id_message);} + ); }, openMarkerPopup() { //TODO