diff --git a/src/components/project.vue b/src/components/project.vue index 2814545..6e98b58 100644 --- a/src/components/project.vue +++ b/src/components/project.vue @@ -28,6 +28,8 @@ export default { return { server: this.spot.consts.server, feed: {loading:false, updatable:true, outOfData:false, refIdFirst:0, refIdLast:0, firstChunk:true}, + refreshRate: 60, + lastUpdate: { unix_time: 0, relative_time: '', formatted_time: ''}, feedPanelOpen: false, feedSimpleBar: null, settingsPanelOpen: false, @@ -108,11 +110,17 @@ export default { this.spot.tmp('elev').resize({width:this.getElevWidth()}); } */ + }, + onQuitPage: () => { + this.setFeedUpdateTimer(-1); } }); this.currProjectCodeName = (this.$parent.hash.items.length==0)?this.spot.vars('default_project_codename'):this.$parent.hash.items[0]; }, + beforeUnmount() { + this.setFeedUpdateTimer(-1); + }, methods: { init() { let bFirstLoad = (typeof this.currProject.codename == 'undefined'); @@ -155,10 +163,15 @@ export default { //Add post Event handling //TODO + //Get first posts batch await this.getNextFeed(); + this.$refs.feedSimpleBar.scrollElement.scrollTop = 0; //Scroll to post if(this.$parent.hash.items.length == 3) this.findPost({type: this.$parent.hash.items[1], id: this.$parent.hash.items[2]}); + + //Start auto-update + if(!this.modeHisto) this.setFeedUpdateTimer(this.refreshRate); }, async initMap() { //Get Map Info @@ -166,6 +179,7 @@ export default { this.baseMap = null; this.baseMaps = aoMarkers.maps; this.messages = aoMarkers.messages; + this.lastUpdate = aoMarkers.last_update; //Base maps (raster tiles) let asSources = {}; @@ -233,34 +247,20 @@ export default { }); //Markers - let aoMarkerSource = {type:'geojson', data:{type: 'FeatureCollection', features:[]}}; - for(const oMsg of this.messages) { - aoMarkerSource.data.features.push({ - 'type': 'Feature', - 'properties': { - ...oMsg, - ...{'description': ''} - }, - 'geometry': { - 'type': 'Point', - 'coordinates': [oMsg.longitude, oMsg.latitude] - } - }); - } - this.map.addSource('markers', aoMarkerSource); - const image = await this.map.loadImage('images/footprint_mapbox.png'); - this.map.addImage('markerIcon', image.data); + this.map.addImage('markerIcon', (await this.map.loadImage('images/footprint_mapbox.png')).data); + this.map.addSource('markers', { + type:'geojson', + data: { + type: 'FeatureCollection', + features: this.convertMsgToFeatures(this.messages) + } + }); this.map.addLayer({ 'id': 'markers', 'type': 'symbol', 'source': 'markers', - 'layout': { - //'icon-anchor': 'bottom', - 'icon-image': 'markerIcon' - //'icon-overlap': 'always' - } + 'layout': {'icon-image': 'markerIcon'} }); - this.map.on('click', 'markers', (e) => { this.openMarkerPopup(e.features[0]); }); @@ -311,6 +311,78 @@ export default { //Legend }, + convertMsgToFeatures(oMsg) { + return oMsg.map(oMsg => ({ + 'type': 'Feature', + 'geometry': { + 'type': 'Point', + 'coordinates': [oMsg.longitude, oMsg.latitude] + }, + 'properties': { + ...oMsg, + ...{'description': ''} + } + })); + }, + async getNextFeed() { + 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.currProject.id, id: this.feed.refIdLast}); + let iPostCount = Object.keys(aoData.feed).length; + + //Update pointers + this.feed.outOfData = (iPostCount < this.spot.consts.chunk_size); + if(iPostCount > 0) { + this.feed.refIdLast = aoData.ref_id_last; + if(this.feed.firstChunk) this.feed.refIdFirst = aoData.ref_id_first; + } + + //Add posts + this.posts.push(...aoData.feed); + + this.feed.loading = false; + this.feed.firstChunk = false; + } + + return true; + }, + onFeedScroll(oEvent) { + //FIXME remove jquery dependency + var $Box = $(oEvent.currentTarget); + var $BoxContent = $Box.find('.simplebar-content'); + if(($Box.scrollTop() + $(window).height()) / $BoxContent.height() >= 0.8) this.getNextFeed(); + }, + setFeedUpdateTimer(iSeconds) { + if(typeof this.feedTimer != 'undefined') clearTimeout(this.feedTimer); + if(iSeconds >= 0) this.feedTimer = setTimeout(this.checkNewFeed, iSeconds * 1000); + }, + async checkNewFeed() { + let aoData = await this.spot.get2('new_feed', {id_project: this.currProject.id, id: this.feed.refIdFirst}); + + if(Object.keys(aoData.feed).length > 0) { + //Update pointer + this.feed.refIdFirst = aoData.ref_id_first; + + //Add new posts + this.posts.unshift(...aoData.feed); + } + + //Add new Markers + if(Object.keys(aoData.messages).length > 0) { + const oMarkerSource = this.map.getSource('markers'); + oMarkerSource.setData({ + type: 'FeatureCollection', + features: [...oMarkerSource._data.features, ...this.convertMsgToFeatures(aoData.messages)] + }); + } + + //Message Last Update + this.lastUpdate = aoData.last_update; + + //Reschedule + this.setFeedUpdateTimer(this.refreshRate); + }, openMarkerPopup(oFeature) { this.closeMarkerPopup(); @@ -389,34 +461,6 @@ export default { rel: 'noreferrer noopener' }).text(asInfo.lat_dms+' '+asInfo.lon_dms); }, - async getNextFeed() { - 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.currProject.id, id: this.feed.refIdLast}); - let iPostCount = Object.keys(aoData.feed).length; - this.feed.loading = false; - this.feed.firstChunk = false; - - //Update pointers - this.feed.outOfData = (iPostCount < this.spot.consts.chunk_size); - if(iPostCount > 0) { - this.feed.refIdLast = aoData.ref_id_last; - if(this.feed.firstChunk) this.feed.refIdFirst = aoData.ref_id_first; - } - - //Add posts - this.posts.push(...aoData.feed); - } - - return true; - }, - onFeedScroll(oEvent) { - //FIXME remove jquery dependency - var $Box = $(oEvent.currentTarget); - var $BoxContent = $Box.find('.simplebar-content'); - if(($Box.scrollTop() + $(window).height()) / $BoxContent.height() >= 0.8) this.getNextFeed(); - }, async manageSubs() { var regexEmail = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; if(!regexEmail.test(this.user.email)) this.nlFeedbacks.push({type:'error', 'msg':this.spot.lang('nl_invalid_email')}); @@ -526,7 +570,9 @@ export default {

{{ spot.lang('last_update')+' '+lastUpdate.relative_time }}