261 lines
7.2 KiB
Vue
261 lines
7.2 KiB
Vue
<script>
|
|
import Lightbox from '@components/Lightbox';
|
|
import ProjectMap, { BASE_MAP_PADDING } from '@components/ProjectMap';
|
|
import { getStyleProperty } from '@scripts/common';
|
|
|
|
import AppIcon from '@components/AppIcon';
|
|
import ProjectFeed from '@components/ProjectFeed';
|
|
import ProjectSettings from '@components/ProjectSettings';
|
|
|
|
export default {
|
|
components: {
|
|
AppIcon,
|
|
ProjectFeed,
|
|
ProjectSettings,
|
|
ProjectMap,
|
|
Lightbox
|
|
},
|
|
data() {
|
|
return {
|
|
panels: {
|
|
leftOpen: false,
|
|
rightOpen: false
|
|
},
|
|
feed: null,
|
|
settings: null,
|
|
project: null,
|
|
modeHisto: null,
|
|
baseMaps: [],
|
|
baseMap: null,
|
|
terrainEnabled: false,
|
|
mapInitializing: false,
|
|
hikes: {
|
|
colors: {},
|
|
width: null,
|
|
transitions: {
|
|
lineWidthTransition: {duration:null}
|
|
}
|
|
},
|
|
overview: {
|
|
id: 0,
|
|
codename: 'overview',
|
|
name: this.lang.get('project.overview')
|
|
},
|
|
};
|
|
},
|
|
computed: {
|
|
projectOptions() {
|
|
return [
|
|
this.overview,
|
|
...Object.values(this.projects)
|
|
];
|
|
}
|
|
},
|
|
watch: {
|
|
'hash.items.0'(newProjectCodename, oldProjectCodename) { //hash.items.0 = Project Code Name
|
|
if(newProjectCodename != oldProjectCodename) {
|
|
this.hash.items = [newProjectCodename]; //Force removal of direct link
|
|
this.settings.toggle(false, 0);
|
|
this.init();
|
|
}
|
|
}
|
|
},
|
|
provide() {
|
|
return {
|
|
map: {
|
|
panToBetweenPanels: this.panToBetweenPanels,
|
|
openMarkerPopup: (iMarkerId, sMarkerType) => this.$refs.mapCtrl.openMarkerPopup(iMarkerId, sMarkerType),
|
|
closePopup: () => this.$refs.mapCtrl.closePopup(),
|
|
isMarkerVisible: (oLngLat) => this.$refs.mapCtrl.isMarkerVisible(oLngLat),
|
|
findMarkerByMediaId: (iMediaId) => this.$refs.mapCtrl.findMarkerByMediaId(iMediaId)
|
|
},
|
|
lightbox: {
|
|
open: (iMediaId, sSource) => this.openLightbox(iMediaId, sSource)
|
|
},
|
|
project: this
|
|
};
|
|
},
|
|
inject: ['api', 'lang', 'hash', 'projects', 'consts', 'isMobile'],
|
|
mounted() {
|
|
//Starts default project init() through watcher
|
|
if(this.hash.items.length == 0) {
|
|
this.hash.items[0] = (this.projects.getDefaultProject().mode == this.consts.modes.blog)?this.projects.getDefaultCodeName():this.overview.codename;
|
|
}
|
|
else this.init();
|
|
},
|
|
beforeUnmount() {
|
|
this.$refs.lightbox.end(true);
|
|
this.$refs.mapCtrl.destroy();
|
|
},
|
|
methods: {
|
|
async init() {
|
|
this.hikes.colors = {
|
|
'main': getStyleProperty('--track-main'),
|
|
'off-track': getStyleProperty('--track-off-track'),
|
|
'hitchhiking': getStyleProperty('--track-hitchhiking')
|
|
};
|
|
this.hikes.width = parseFloat(getStyleProperty('--track-width'));
|
|
this.hikes.transitions.lineWidthTransition.duration = parseFloat(getStyleProperty('--trans-quick'));
|
|
|
|
//Reset values
|
|
this.project = null;
|
|
this.$refs.mapCtrl.removeMapContent();
|
|
|
|
//Build Map
|
|
this.mapInitializing = true;
|
|
if(this.hash.items[0] && this.projects[this.hash.items[0]]) await this.initProject(this.hash.items[0]);
|
|
else await this.initOverview();
|
|
this.mapInitializing = false;
|
|
},
|
|
async initOverview() {
|
|
this.modeHisto = true;
|
|
this.hash.items = [this.overview.codename];
|
|
this.feed.toggle(false, 0);
|
|
|
|
await this.initOverviewMap();
|
|
},
|
|
async initProject(sProjectCodeName) {
|
|
this.project = this.projects[sProjectCodeName];
|
|
this.modeHisto = (this.project.mode == this.consts.modes.histo);
|
|
|
|
await this.$nextTick();
|
|
const pMapReady = this.initProjectMap();
|
|
await this.feed.init(pMapReady);
|
|
},
|
|
openLightbox(iMediaId, sSource) {
|
|
const aoAlbum = (sSource == 'marker')
|
|
? (this.$refs.mapCtrl.findMarkerByMediaId(iMediaId)?.medias || [])
|
|
: this.feed.posts.filter((oPost) => oPost.type == 'media');
|
|
this.$refs.lightbox.open(aoAlbum, iMediaId, sSource);
|
|
},
|
|
async onLightboxMediaChange(oMedia) {
|
|
this.hash.items = [this.project.codename, 'media', oMedia.id];
|
|
if(oMedia.source == 'post') {
|
|
(await this.feed.findPost('media', oMedia.id))?.panMapToMarker();
|
|
if(!this.$refs.lightbox.hasMediaAfterCurrent()) {
|
|
await this.feed.getNextFeed();
|
|
this.$refs.lightbox.refreshAlbum(this.feed.posts.filter((oPost) => oPost.type == 'media'));
|
|
}
|
|
}
|
|
},
|
|
onLightboxClosing() {
|
|
this.hash.items = [this.hash.items[0]];
|
|
},
|
|
async initProjectMap() {
|
|
const [{maps: baseMaps, markers}, track] = await Promise.all([
|
|
this.api.get('markers', {id_project: this.project.id}),
|
|
this.api.getAsset(this.project.geofilepath)
|
|
]);
|
|
this.baseMaps = baseMaps;
|
|
|
|
await this.$refs.mapCtrl.initMap({
|
|
project: this.project,
|
|
hikes: this.hikes,
|
|
baseMaps,
|
|
markers,
|
|
track,
|
|
padding: this.getMapPadding()
|
|
});
|
|
},
|
|
async initOverviewMap() {
|
|
this.baseMaps = this.consts.default_maps;
|
|
const markers = Object.values(this.projects).map((asProject) => ({
|
|
type: 'project',
|
|
subtype: 'project',
|
|
...asProject,
|
|
opacityWhenCovered: 0.3
|
|
}));
|
|
|
|
await this.$refs.mapCtrl.initMap({
|
|
project: null,
|
|
hikes: this.hikes,
|
|
baseMaps: this.baseMaps,
|
|
markers,
|
|
track: null,
|
|
padding: this.getMapPadding()
|
|
});
|
|
},
|
|
addNewMarkers(aoMarkers) {
|
|
this.$refs.mapCtrl.addNewMarkers(aoMarkers);
|
|
},
|
|
panToBetweenPanels(oLngLat, iZoom, iAnimDuration=500) {
|
|
return this.$refs.mapCtrl.panTo(oLngLat, iZoom, this.getMapPadding(), iAnimDuration);
|
|
},
|
|
getMapPadding() {
|
|
let bIsMobile = this.isMobile();
|
|
return {
|
|
top: BASE_MAP_PADDING,
|
|
bottom: BASE_MAP_PADDING,
|
|
left: BASE_MAP_PADDING + ((!bIsMobile && this.panels.leftOpen && this.settings)?this.settings.getWidth():0),
|
|
right: BASE_MAP_PADDING + ((!bIsMobile && this.panels.rightOpen && this.feed)?this.feed.getWidth():0)
|
|
};
|
|
},
|
|
updateMapPadding(iDuration=0) {
|
|
this.$refs.mapCtrl.setPadding(this.getMapPadding(), iDuration);
|
|
},
|
|
onPanelToggle(sPanel, bNewValue, iAnimDuration=500) {
|
|
const sPanelKey = sPanel + 'Open';
|
|
let bOldValue = this.panels[sPanelKey];
|
|
this.panels[sPanelKey] = bNewValue;
|
|
|
|
if(bOldValue != bNewValue) {
|
|
//Adjust map center
|
|
if(!this.isMobile() && this.$refs.mapCtrl.map) this.updateMapPadding(iAnimDuration);
|
|
|
|
//Open Close panels
|
|
this.$el.classList.toggle('with-'+sPanel+'-panel');
|
|
}
|
|
},
|
|
setFeed(vPanel) {
|
|
this.feed = vPanel;
|
|
},
|
|
setSettings(vPanel) {
|
|
this.settings = vPanel;
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="projects">
|
|
<div id="space"></div>
|
|
<div id="submap">
|
|
<div class="loader">
|
|
<AppIcon :icon="'map'" :classes="'flicker'" width="fixed" />
|
|
</div>
|
|
</div>
|
|
<ProjectMap
|
|
ref="mapCtrl"
|
|
v-model:base-map="baseMap"
|
|
:terrain-enabled="terrainEnabled"
|
|
/>
|
|
<Lightbox
|
|
ref="lightbox"
|
|
:always-show-nav-on-touch-devices="true"
|
|
:position-from-top="0"
|
|
:has-video="true"
|
|
@media-change="onLightboxMediaChange"
|
|
@closing="onLightboxClosing"
|
|
/>
|
|
<ProjectSettings
|
|
:ref="setSettings"
|
|
:projects="projectOptions"
|
|
v-model:project-code-name="hash.items[0]"
|
|
:base-maps="baseMaps"
|
|
v-model:base-map="baseMap"
|
|
v-model:terrain-enabled="terrainEnabled"
|
|
:map-initializing="mapInitializing"
|
|
:hikes="hikes"
|
|
@toggle="(bIsOpen, iAnimDuration) => onPanelToggle('left', bIsOpen, iAnimDuration)"
|
|
/>
|
|
<ProjectFeed
|
|
:ref="setFeed"
|
|
:project="project"
|
|
:mode-histo="modeHisto"
|
|
@request-last-update="settings?.setLastUpdate"
|
|
@new-markers="addNewMarkers"
|
|
@toggle="(bIsOpen, iAnimDuration) => onPanelToggle('right', bIsOpen, iAnimDuration)"
|
|
/>
|
|
</div>
|
|
</template>
|