115 lines
3.1 KiB
Vue
115 lines
3.1 KiB
Vue
<script>
|
|
import { defineAsyncComponent } from 'vue';
|
|
import Project from '@components/Project';
|
|
|
|
const aoRoutes = {
|
|
'project': Project, //Merge app.js and project.js calls to avoid extra http request on inital page
|
|
'admin': defineAsyncComponent(() => import('@components/Admin')),
|
|
'upload': defineAsyncComponent(() => import('@components/Upload'))
|
|
};
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
hash: {page: '', items: [], prev: {}},
|
|
consts: this.appConfig.consts,
|
|
mobile: false
|
|
};
|
|
},
|
|
provide() {
|
|
return {
|
|
hash: this.hash,
|
|
consts: this.consts,
|
|
isMobile: () => this.isMobile(),
|
|
getAnchor: this.getAnchor,
|
|
getPrevAnchor: () => this.getPrevAnchor(),
|
|
};
|
|
},
|
|
computed: {
|
|
route() {
|
|
return aoRoutes[this.hash.page];
|
|
},
|
|
hashSnapshot() {
|
|
const { prev, ...asHash } = this.hash;
|
|
return JSON.stringify(asHash);
|
|
}
|
|
},
|
|
inject: ['appConfig'],
|
|
created() {
|
|
this.mobileMediaQuery = window.matchMedia('only screen and (max-width: 800px)');
|
|
this.mobileMediaQuery.addEventListener('change', this.updateMobile);
|
|
this.updateMobile();
|
|
|
|
//Set initial page
|
|
this.setVarHash(this.validateRoute(this.getBrowserHash()));
|
|
},
|
|
mounted() {
|
|
//Catch browser hash change
|
|
window.addEventListener('hashchange', this.onBrowserHashChange);
|
|
},
|
|
watch: {
|
|
hashSnapshot(jNewHash, jOldHash) {
|
|
const asNewHash = this.validateRoute(JSON.parse(jNewHash));
|
|
|
|
//Sync variable -> #hash
|
|
if(asNewHash != this.getBrowserHash()) {
|
|
this.setBrowserHash(asNewHash.page, asNewHash.items);
|
|
}
|
|
|
|
//Store previous value
|
|
this.hash.prev = JSON.parse(jOldHash);
|
|
|
|
this.setPageTitle(asNewHash.page);
|
|
}
|
|
},
|
|
methods: {
|
|
isMobile() {
|
|
return this.mobile;
|
|
},
|
|
updateMobile() {
|
|
this.mobile = this.mobileMediaQuery.matches;
|
|
},
|
|
setPageTitle(sTitle) {
|
|
document.title = this.consts.title + ' - ' + sTitle.trim();
|
|
},
|
|
setVarHash(asHash) {
|
|
this.hash.page = asHash.page || '';
|
|
this.hash.items = Array.isArray(asHash.items) ? [...asHash.items.filter(n => n)] : [];
|
|
},
|
|
onBrowserHashChange() { //Sync #hash -> variable
|
|
let asHash = this.getBrowserHash();
|
|
if(asHash != this.hash) this.setVarHash(asHash);
|
|
},
|
|
getBrowserHash() {
|
|
let sHash = window.location.hash.slice(1);
|
|
let asHash = sHash.split(this.consts.hash_sep).filter(n => n);
|
|
let sPage = asHash.shift() || '';
|
|
return {page: sPage, items: asHash};
|
|
},
|
|
setBrowserHash(sPage = '', asItems = []) {
|
|
if(typeof asItems == 'string' && asItems != '') asItems = [asItems];
|
|
window.location.hash = this.getAnchor([sPage, ...asItems]);
|
|
},
|
|
getAnchor(asBreadCrumbs) {
|
|
return '#' + asBreadCrumbs.filter(Boolean).join(this.consts.hash_sep);
|
|
},
|
|
getPrevAnchor() {
|
|
return this.getAnchor([this.hash.prev.page, ...this.hash.prev.items]);
|
|
},
|
|
validateRoute(asHash) {
|
|
if(!Object.keys(aoRoutes).includes(asHash.page)) asHash.page = this.consts.default_page;
|
|
return asHash;
|
|
}
|
|
},
|
|
beforeUnmount() {
|
|
window.removeEventListener('hashchange', this.onBrowserHashChange);
|
|
this.mobileMediaQuery.removeEventListener('change', this.updateMobile);
|
|
}
|
|
};
|
|
</script>
|
|
<template>
|
|
<div id="main">
|
|
<component :is="route" />
|
|
</div>
|
|
</template>
|