Files
livetrail/src/components/Project.vue
T
franzz a70f6fe64c
Deploy Livetrail / deploy (push) Successful in 17s
Remove lightbox legacy html tags
2026-09-09 17:46:38 +02:00

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>