Fix page routing
This commit is contained in:
90
src/Spot.vue
90
src/Spot.vue
@@ -12,73 +12,85 @@ const aoRoutes = {
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hash: {},
|
hash: {page: '', items: []},
|
||||||
consts: this.spot.consts,
|
consts: this.spot.consts,
|
||||||
user: this.spot.vars('user')
|
user: this.spot.vars('user'),
|
||||||
|
routes: aoRoutes
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
|
hash: this.hash,
|
||||||
projects: this.spot.vars('projects'),
|
projects: this.spot.vars('projects'),
|
||||||
consts: this.consts,
|
consts: this.consts,
|
||||||
user: this.user
|
user: this.user
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
inject: ['spot'],
|
|
||||||
computed: {
|
computed: {
|
||||||
page() {
|
route() {
|
||||||
this.spot.vars('page', this.hash.page);
|
return this.routes[this.hash.page];
|
||||||
return aoRoutes[this.hash.page];
|
},
|
||||||
|
hashSnapshot() {
|
||||||
|
return JSON.stringify(this.hash);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
inject: ['spot'],
|
||||||
created() {
|
created() {
|
||||||
//User
|
//User
|
||||||
this.user.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || this.consts.default_timezone;
|
this.user.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || this.consts.default_timezone;
|
||||||
|
|
||||||
|
//Set initial page
|
||||||
|
let asInitHash = this.getHash();
|
||||||
|
if(!asInitHash.page) this.hash.page = this.spot.consts.default_page;
|
||||||
|
else this.hash = asInitHash;
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
window.addEventListener('hashchange', () => {this.onHashChange();});
|
//Catch browser hash change
|
||||||
var oEvent = new Event('hashchange');
|
window.addEventListener('hashchange', this.onHashChange);
|
||||||
window.dispatchEvent(oEvent);
|
|
||||||
},
|
},
|
||||||
methods: {
|
watch: {
|
||||||
_hash(hash, bReboot) {
|
hashSnapshot(jNewHash, jOldHash) {
|
||||||
bReboot = bReboot || false;
|
const asNewHash = JSON.parse(jNewHash);
|
||||||
if(!hash) return window.location.hash.slice(1);
|
const asOldHash = JSON.parse(jOldHash);
|
||||||
else window.location.hash = '#'+hash;
|
this.spot.vars('page', this.hash.page); //FIXME remove
|
||||||
|
|
||||||
if(bReboot) location.reload();
|
//Sync variable -> #hash
|
||||||
},
|
if(asNewHash != this.getHash()) {
|
||||||
onHashChange() {
|
this.setHash(asNewHash.page, asNewHash.items);
|
||||||
let asHash = this.getHash();
|
|
||||||
if(asHash.hash !='' && asHash.page != '') {
|
|
||||||
if(asHash.page == this.hash.page) this.spot.onSamePageMove(asHash);
|
|
||||||
this.hash = asHash;
|
|
||||||
}
|
}
|
||||||
else if(!this.hash.page) this.setHash(this.spot.consts.default_page);
|
|
||||||
},
|
|
||||||
getHash() {
|
|
||||||
let sHash = this._hash();
|
|
||||||
let asHash = sHash.split(this.spot.consts.hash_sep);
|
|
||||||
let sPage = asHash.shift() || '';
|
|
||||||
return {hash:sHash, page:sPage, items:asHash};
|
|
||||||
},
|
|
||||||
setHash(sPage, asItems, bReboot) {
|
|
||||||
bReboot = bReboot || false;
|
|
||||||
sPage = sPage || '';
|
|
||||||
asItems = asItems || [];
|
|
||||||
if(typeof asItems == 'string') asItems = [asItems];
|
|
||||||
|
|
||||||
if(sPage != '') {
|
//Same Page change
|
||||||
let sItems = (asItems.length > 0)?this.spot.consts.hash_sep+asItems.join(this.spot.consts.hash_sep):'';
|
if(asNewHash != asOldHash && asNewHash.page == asOldHash.page) {
|
||||||
this._hash(sPage+sItems, bReboot);
|
this.spot.onSamePageMove(asNewHash, asOldHash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onHashChange() { //Sync #hash -> variable
|
||||||
|
let asHash = this.getHash();
|
||||||
|
if(asHash != this.hash) this.hash = asHash;
|
||||||
|
this.spot.vars('page', this.hash.page); //FIXME remove
|
||||||
|
},
|
||||||
|
getHash() {
|
||||||
|
let sHash = window.location.hash.slice(1);
|
||||||
|
let asHash = sHash.split(this.spot.consts.hash_sep);
|
||||||
|
let sPage = asHash.shift() || '';
|
||||||
|
return {page: sPage, items: asHash};
|
||||||
|
},
|
||||||
|
setHash(sPage = '', asItems = []) {
|
||||||
|
if(typeof asItems == 'string') asItems = [asItems];
|
||||||
|
const sItems = (asItems.length > 0)?(this.spot.consts.hash_sep + asItems.join(this.spot.consts.hash_sep)):'';
|
||||||
|
window.location.hash = '#' + sPage + sItems;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
window.removeEventListener('hashchange', this.onHashChange)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<component :is="page" />
|
<component :is="route" />
|
||||||
</div>
|
</div>
|
||||||
<div id="mobile"></div>
|
<div id="mobile"></div>
|
||||||
</template>
|
</template>
|
||||||
@@ -2,15 +2,13 @@
|
|||||||
import 'maplibre-gl/dist/maplibre-gl.css';
|
import 'maplibre-gl/dist/maplibre-gl.css';
|
||||||
import { Map, NavigationControl, Marker, LngLatBounds, LngLat, Popup } from 'maplibre-gl';
|
import { Map, NavigationControl, Marker, LngLatBounds, LngLat, Popup } from 'maplibre-gl';
|
||||||
import { createApp, defineComponent, nextTick, ref, defineCustomElement, provide, inject } from 'vue';
|
import { createApp, defineComponent, nextTick, ref, defineCustomElement, provide, inject } from 'vue';
|
||||||
import simplebar from 'simplebar-vue';
|
import Simplebar from 'simplebar-vue';
|
||||||
|
|
||||||
import autosize from 'autosize';
|
import autosize from 'autosize';
|
||||||
import mousewheel from 'jquery-mousewheel';
|
import mousewheel from 'jquery-mousewheel';
|
||||||
import waitforimages from 'jquery.waitforimages';
|
import waitforimages from 'jquery.waitforimages';
|
||||||
import lightbox from '../scripts/lightbox.js';
|
import lightbox from '../scripts/lightbox.js';
|
||||||
|
|
||||||
//import SimpleBar from 'simplebar';
|
|
||||||
|
|
||||||
import SpotIcon from './spotIcon.vue';
|
import SpotIcon from './spotIcon.vue';
|
||||||
import SpotButton from './spotButton.vue';
|
import SpotButton from './spotButton.vue';
|
||||||
import ProjectPost from './projectPost.vue';
|
import ProjectPost from './projectPost.vue';
|
||||||
@@ -22,7 +20,7 @@ export default {
|
|||||||
SpotButton,
|
SpotButton,
|
||||||
ProjectPost,
|
ProjectPost,
|
||||||
ProjectPopup,
|
ProjectPopup,
|
||||||
simplebar
|
Simplebar
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -35,7 +33,6 @@ export default {
|
|||||||
settingsPanelOpen: false,
|
settingsPanelOpen: false,
|
||||||
markerSize: {width: 32, height: 32},
|
markerSize: {width: 32, height: 32},
|
||||||
currProject: {},
|
currProject: {},
|
||||||
currProjectCodeName: null,
|
|
||||||
modeHisto: false,
|
modeHisto: false,
|
||||||
posts: [],
|
posts: [],
|
||||||
nlFeedbacks: [],
|
nlFeedbacks: [],
|
||||||
@@ -76,14 +73,11 @@ export default {
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
baseMap(sNewBaseMap, sOldBaseMap) {
|
baseMap(sNewBaseMap, sOldBaseMap) {
|
||||||
if(sOldBaseMap) this.map.setLayoutProperty(sOldBaseMap, 'visibility', 'none');
|
if(this.map.isStyleLoaded()) {
|
||||||
if(sNewBaseMap) this.map.setLayoutProperty(sNewBaseMap, 'visibility', 'visible');
|
if(sOldBaseMap) this.map.setLayoutProperty(sOldBaseMap, 'visibility', 'none');
|
||||||
|
if(sNewBaseMap) this.map.setLayoutProperty(sNewBaseMap, 'visibility', 'visible');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
currProjectCodeName(sNewCodeName, sOldCodeName) {
|
|
||||||
//this.toggleSettingsPanel(false);
|
|
||||||
if(this.$parent.hash.items.length==0) this.$parent.setHash(this.$parent.hash.page, [sNewCodeName]);
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
@@ -96,7 +90,10 @@ export default {
|
|||||||
project: this
|
project: this
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
inject: ['spot', 'projects', 'user'],
|
inject: ['spot', 'hash', 'projects', 'user'],
|
||||||
|
beforeMount() {
|
||||||
|
if(this.$parent.hash.items.length == 0) this.$parent.hash.items[0] = this.spot.vars('default_project_codename');
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.spot.addPage('project', {
|
this.spot.addPage('project', {
|
||||||
onResize: () => {
|
onResize: () => {
|
||||||
@@ -108,15 +105,25 @@ export default {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
},
|
},
|
||||||
|
onSamePageMove: (asNewHash, asOldHash) => {
|
||||||
|
//this.toggleSettingsPanel(false);
|
||||||
|
//this.quit();
|
||||||
|
|
||||||
|
//Check for project change
|
||||||
|
if(asNewHash.items[0] != asOldHash.items[0]) {
|
||||||
|
console.log('Project change: '+(asOldHash.items[0])+' ->', asNewHash.items[0]);
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
},
|
||||||
onQuitPage: () => {
|
onQuitPage: () => {
|
||||||
this.setFeedUpdateTimer(-1);
|
this.quit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.currProjectCodeName = (this.$parent.hash.items.length==0)?this.spot.vars('default_project_codename'):this.$parent.hash.items[0];
|
this.init();
|
||||||
},
|
},
|
||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
this.setFeedUpdateTimer(-1);
|
this.quit();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
@@ -126,8 +133,14 @@ export default {
|
|||||||
this.initFeed();
|
this.initFeed();
|
||||||
this.initMap();
|
this.initMap();
|
||||||
},
|
},
|
||||||
|
quit() {
|
||||||
|
lightbox.end();
|
||||||
|
this.$refs.feedSimpleBar.scrollElement.removeEventListener('scroll', (oEvent) => {this.onFeedScroll(oEvent);});
|
||||||
|
this.setFeedUpdateTimer(-1);
|
||||||
|
this.map.remove();
|
||||||
|
},
|
||||||
initProject() {
|
initProject() {
|
||||||
this.currProject = this.projects[this.currProjectCodeName];
|
this.currProject = this.projects[this.$parent.hash.items[0]];
|
||||||
this.modeHisto = (this.currProject.mode == this.spot.consts.modes.histo);
|
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.feed = {loading:false, updatable:true, outOfData:false, refIdFirst:0, refIdLast:0, firstChunk:true};
|
||||||
this.posts = [];
|
this.posts = [];
|
||||||
@@ -178,7 +191,7 @@ export default {
|
|||||||
this.messages = aoMarkers.messages;
|
this.messages = aoMarkers.messages;
|
||||||
this.lastUpdate = aoMarkers.last_update;
|
this.lastUpdate = aoMarkers.last_update;
|
||||||
|
|
||||||
console.log(this.baseMaps);
|
//console.log(this.baseMaps);
|
||||||
|
|
||||||
//Base maps (raster tiles)
|
//Base maps (raster tiles)
|
||||||
let asSources = {};
|
let asSources = {};
|
||||||
@@ -574,12 +587,12 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-sections">
|
<div class="settings-sections">
|
||||||
<simplebar id="settings-sections-scrollbox">
|
<Simplebar id="settings-sections-scrollbox">
|
||||||
<div class="settings-section">
|
<div class="settings-section">
|
||||||
<h1><SpotIcon :icon="'project'" :classes="'fa-fw'" :text="spot.lang('hikes')" /></h1>
|
<h1><SpotIcon :icon="'project'" :classes="'fa-fw'" :text="spot.lang('hikes')" /></h1>
|
||||||
<div class="settings-section-body">
|
<div class="settings-section-body">
|
||||||
<div class="radio" v-for="project in projects">
|
<div class="radio" v-for="project in projects">
|
||||||
<input type="radio" :id="project.id" :value="project.codename" v-model="currProjectCodeName" />
|
<input type="radio" :id="project.id" :value="project.codename" v-model="$parent.hash.items[0]" />
|
||||||
<label :for="project.id">
|
<label :for="project.id">
|
||||||
<span>{{ project.name }}</span>
|
<span>{{ project.name }}</span>
|
||||||
<a class="download" :href="project.gpxfilepath" :title="spot.lang('track_download')" @click.stop="()=>{}">
|
<a class="download" :href="project.gpxfilepath" :title="spot.lang('track_download')" @click.stop="()=>{}">
|
||||||
@@ -614,7 +627,7 @@ export default {
|
|||||||
<a class="button" href="#admin"><SpotIcon :icon="'config'" :text="spot.lang('admin_config')" /></a>
|
<a class="button" href="#admin"><SpotIcon :icon="'config'" :text="spot.lang('admin_config')" /></a>
|
||||||
<a class="button" href="#upload"><SpotIcon :icon="'upload'" :text="spot.lang('admin_upload')" /></a>
|
<a class="button" href="#upload"><SpotIcon :icon="'upload'" :text="spot.lang('admin_upload')" /></a>
|
||||||
</div>
|
</div>
|
||||||
</simplebar>
|
</Simplebar>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-footer">
|
<div class="settings-footer">
|
||||||
<a href="https://git.lutran.fr/franzz/spot" :title="spot.lang('credits_git')" target="_blank" rel="noopener">
|
<a href="https://git.lutran.fr/franzz/spot" :title="spot.lang('credits_git')" target="_blank" rel="noopener">
|
||||||
@@ -635,7 +648,7 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="feed" class="map-container map-container-right" ref="feed">
|
<div id="feed" class="map-container map-container-right" ref="feed">
|
||||||
<simplebar id="feed-panel" class="map-panel" ref="feedSimpleBar">
|
<Simplebar id="feed-panel" class="map-panel" ref="feedSimpleBar">
|
||||||
<div id="feed-header">
|
<div id="feed-header">
|
||||||
<ProjectPost v-if="modeHisto" :options="{type: 'archived', headerless: true}" />
|
<ProjectPost v-if="modeHisto" :options="{type: 'archived', headerless: true}" />
|
||||||
<ProjectPost v-else :options="{type: 'poster', relative_time: spot.lang('post_new_message')}" />
|
<ProjectPost v-else :options="{type: 'poster', relative_time: spot.lang('post_new_message')}" />
|
||||||
@@ -646,7 +659,7 @@ export default {
|
|||||||
<div id="feed-footer" v-if="feed.loading">
|
<div id="feed-footer" v-if="feed.loading">
|
||||||
<ProjectPost :options="{type: 'loading', headerless: true}" />
|
<ProjectPost :options="{type: 'loading', headerless: true}" />
|
||||||
</div>
|
</div>
|
||||||
</simplebar>
|
</Simplebar>
|
||||||
<div :class="'map-control map-control-icon feed-control map-control-'+(mobile?'bottom':'top')" @click="toggleFeedPanel">
|
<div :class="'map-control map-control-icon feed-control map-control-'+(mobile?'bottom':'top')" @click="toggleFeedPanel">
|
||||||
<SpotIcon :icon="feedPanelOpen?'next':'post'" />
|
<SpotIcon :icon="feedPanelOpen?'next':'post'" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export default {
|
|||||||
(position) => {
|
(position) => {
|
||||||
this.logs.push('Sending position...');
|
this.logs.push('Sending position...');
|
||||||
this.spot.get2('add_position', {'latitude':position.coords.latitude, 'longitude':position.coords.longitude, 'timestamp':Math.round(position.timestamp / 1000)})
|
this.spot.get2('add_position', {'latitude':position.coords.latitude, 'longitude':position.coords.longitude, 'timestamp':Math.round(position.timestamp / 1000)})
|
||||||
.then((asData) => {this.logs.push('Position sent');})
|
.then((asData) => {this.logs.push(self.lang(sMsgId));})
|
||||||
.catch((sMsgId) => {this.logs.push(self.lang(sMsgId));});
|
.catch((sMsgId) => {this.logs.push(self.lang(sMsgId));});
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
|||||||
@@ -195,9 +195,9 @@ export default class Spot {
|
|||||||
else console.log('no init for the page: '+asHash.page);
|
else console.log('no init for the page: '+asHash.page);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSamePageMove(asHash) {
|
onSamePageMove(asNewHash, asOldHash) {
|
||||||
let sPage = this.vars('page');
|
let sPage = this.vars('page');
|
||||||
return (this.pages[sPage] && this.pages[sPage].onSamePageMove)?this.pages[sPage].onSamePageMove(asHash):false;
|
return (this.pages[sPage] && this.pages[sPage].onSamePageMove)?this.pages[sPage].onSamePageMove(asNewHash, asOldHash):false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onQuitPage() {
|
onQuitPage() {
|
||||||
|
|||||||
Reference in New Issue
Block a user