Pick project from globe
This commit is contained in:
2
config/db/update_v23_to_v24.sql
Normal file
2
config/db/update_v23_to_v24.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE projects ADD latitude DECIMAL(8,6) AFTER name;
|
||||||
|
ALTER TABLE projects ADD longitude DECIMAL(9,6) AFTER latitude;
|
||||||
@@ -29,7 +29,10 @@ class Converter extends PhpObject {
|
|||||||
$oGeoJson->sortOffTracks();
|
$oGeoJson->sortOffTracks();
|
||||||
$oGeoJson->saveFile();
|
$oGeoJson->saveFile();
|
||||||
|
|
||||||
return $oGpx->getLog().'<br />'.$oGeoJson->getLog();
|
return [
|
||||||
|
'logs' => $oGpx->getLog().'<br />'.$oGeoJson->getLog(),
|
||||||
|
'center' => $oGeoJson->getCenter()
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isGeoJsonValid($sCodeName) {
|
public static function isGeoJsonValid($sCodeName) {
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ class GeoJson extends Geo {
|
|||||||
if($bSimplify) $this->addNotice('Total: '.$iGlobalInvalidPointCount.'/'.$iGlobalPointCount.' points removed ('.round($iGlobalInvalidPointCount / $iGlobalPointCount * 100, 1).'%)');
|
if($bSimplify) $this->addNotice('Total: '.$iGlobalInvalidPointCount.'/'.$iGlobalPointCount.' points removed ('.round($iGlobalInvalidPointCount / $iGlobalPointCount * 100, 1).'%)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function sortOffTracks() {
|
public function sortOffTracks() {
|
||||||
$this->addNotice('Sorting off-tracks');
|
$this->addNotice('Sorting off-tracks');
|
||||||
|
|
||||||
@@ -155,7 +154,19 @@ class GeoJson extends Geo {
|
|||||||
$this->asTracks = array_values($asTracks);
|
$this->asTracks = array_values($asTracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function parseOptions($sComment){
|
public function getCenter() {
|
||||||
|
$asCoords = array();
|
||||||
|
$asMainTracks = array_filter($this->asTracks, function ($astrack) {return $astrack['properties']['type'] == 'main';});
|
||||||
|
foreach($asMainTracks as $asMainTrack) {
|
||||||
|
foreach($asMainTrack['geometry']['coordinates'] as $aiCoords) {
|
||||||
|
$asCoords[] = $aiCoords;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $asCoords[(int) floor(count($asCoords) / 2)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseOptions($sComment) {
|
||||||
$sComment = strip_tags(html_entity_decode($sComment));
|
$sComment = strip_tags(html_entity_decode($sComment));
|
||||||
$asOptions = array(self::OPT_SIMPLE=>'');
|
$asOptions = array(self::OPT_SIMPLE=>'');
|
||||||
foreach(explode("\n", $sComment) as $sLine) {
|
foreach(explode("\n", $sComment) as $sLine) {
|
||||||
|
|||||||
@@ -126,6 +126,8 @@ class Project extends PhpObject {
|
|||||||
Db::getId(self::PROJ_TABLE)." AS id",
|
Db::getId(self::PROJ_TABLE)." AS id",
|
||||||
'codename',
|
'codename',
|
||||||
'name',
|
'name',
|
||||||
|
'latitude',
|
||||||
|
'longitude',
|
||||||
'active_from',
|
'active_from',
|
||||||
'active_to',
|
'active_to',
|
||||||
"IF(NOW() BETWEEN active_from AND active_to, 1, IF(NOW() < active_from, 0, 2)) AS mode"
|
"IF(NOW() BETWEEN active_from AND active_to, 1, IF(NOW() < active_from, 0, 2)) AS mode"
|
||||||
@@ -147,12 +149,16 @@ class Project extends PhpObject {
|
|||||||
$asProject['gpxfilepath'] = Spot::addTimestampToFilePath(Gpx::getDistFilePath($sCodeName));
|
$asProject['gpxfilepath'] = Spot::addTimestampToFilePath(Gpx::getDistFilePath($sCodeName));
|
||||||
$asProject['codename'] = $sCodeName;
|
$asProject['codename'] = $sCodeName;
|
||||||
$asProject['default'] = ($sCodeName == $sDefaultProjectCodeName);
|
$asProject['default'] = ($sCodeName == $sDefaultProjectCodeName);
|
||||||
|
//$asProject['center'] = [$asProject['latitude'], $asProject['longitude']];
|
||||||
}
|
}
|
||||||
return $bSpecificProj?$asProject:$asProjects;
|
return $bSpecificProj?$asProject:$asProjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getGeoJson() {
|
public function getGeoJson() {
|
||||||
if($this->sCodeName != '' && !Converter::isGeoJsonValid($this->sCodeName)) Converter::convertToGeoJson($this->sCodeName);
|
if($this->sCodeName != '' && !Converter::isGeoJsonValid($this->sCodeName)){
|
||||||
|
$aiCenter = Converter::convertToGeoJson($this->sCodeName)['center'];
|
||||||
|
$this->oDb->updateRow(self::PROJ_TABLE, $this->iProjectId, ['latitude' => $aiCenter[1], 'longitude' => $aiCenter[0]]);
|
||||||
|
}
|
||||||
|
|
||||||
return json_decode(file_get_contents(GeoJson::getDistFilePath($this->sCodeName)), true);
|
return json_decode(file_get_contents(GeoJson::getDistFilePath($this->sCodeName)), true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,12 +173,13 @@ class Spot extends Main
|
|||||||
|
|
||||||
return parent::getMainPage(
|
return parent::getMainPage(
|
||||||
array(
|
array(
|
||||||
'projects' => $this->oProject->getProjects(),
|
'projects' => $this->oProject->getProjects(),
|
||||||
'user' => $this->oUser->getUserInfo(),
|
'user' => $this->oUser->getUserInfo(),
|
||||||
'consts' => array(
|
'consts' => array(
|
||||||
'modes' => Project::MODES,
|
'modes' => Project::MODES,
|
||||||
'clearances' => User::CLEARANCES,
|
'clearances' => User::CLEARANCES,
|
||||||
'default_timezone' => Settings::TIMEZONE,
|
'default_timezone' => Settings::TIMEZONE,
|
||||||
|
'default_maps' => $this->oMap->getProjectMaps(-1),
|
||||||
'chunk_size' => self::FEED_CHUNK_SIZE,
|
'chunk_size' => self::FEED_CHUNK_SIZE,
|
||||||
'hash_sep' => '-',
|
'hash_sep' => '-',
|
||||||
'title' => 'Spotty',
|
'title' => 'Spotty',
|
||||||
@@ -823,7 +824,7 @@ class Spot extends Main
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function buildGeoJSON($sCodeName) {
|
public function buildGeoJSON($sCodeName) {
|
||||||
return Converter::convertToGeoJson($sCodeName);
|
return Converter::convertToGeoJson($sCodeName)['logs'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function decToDms($dValue, $sType) {
|
public static function decToDms($dValue, $sType) {
|
||||||
|
|||||||
@@ -29,12 +29,13 @@ export default {
|
|||||||
track: null,
|
track: null,
|
||||||
markers: [],
|
markers: [],
|
||||||
markerProps: {
|
markerProps: {
|
||||||
|
project: {mainClasses: 'project', iconMain: 'marker', iconSub: 'project'},
|
||||||
image: {mainClasses: 'media', iconMain: 'marker', iconSub: 'image'},
|
image: {mainClasses: 'media', iconMain: 'marker', iconSub: 'image'},
|
||||||
video: {mainClasses: 'media', iconMain: 'marker', iconSub: 'video'},
|
video: {mainClasses: 'media', iconMain: 'marker', iconSub: 'video'},
|
||||||
message: {mainClasses: 'message', iconMain: 'marker', iconSub: 'footprint', iconSubTransform: 'rotate-270'}
|
message: {mainClasses: 'message', iconMain: 'marker', iconSub: 'footprint', iconSubTransform: 'rotate-270'}
|
||||||
},
|
},
|
||||||
currProject: {},
|
currProject: null,
|
||||||
modeHisto: false,
|
modeHisto: null,
|
||||||
posts: [],
|
posts: [],
|
||||||
baseMaps: {},
|
baseMaps: {},
|
||||||
baseMap: null,
|
baseMap: null,
|
||||||
@@ -63,8 +64,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
'hash.items.0'(newProjectCodename, oldProjectCodename) {
|
'hash.items.0'(newProjectCodename, oldProjectCodename) {
|
||||||
if(newProjectCodename && newProjectCodename != oldProjectCodename) {
|
if(newProjectCodename != oldProjectCodename) {
|
||||||
this.hash.items = [newProjectCodename];
|
this.hash.items = newProjectCodename?[newProjectCodename]:[];
|
||||||
this.toggleSettingsPanel(false, 'none');
|
this.toggleSettingsPanel(false, 'none');
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
@@ -82,9 +83,6 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
inject: ['api', 'lang', 'hash', 'projects', 'user', 'consts', 'isMobile'],
|
inject: ['api', 'lang', 'hash', 'projects', 'user', 'consts', 'isMobile'],
|
||||||
beforeMount() {
|
|
||||||
if(this.hash.items.length == 0) this.hash.items[0] = this.projects.getDefaultCodeName();
|
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init();
|
this.init();
|
||||||
},
|
},
|
||||||
@@ -93,35 +91,47 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async init() {
|
async init() {
|
||||||
this.initProject();
|
|
||||||
this.initLightbox();
|
this.initLightbox();
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
this.initFeed(),
|
|
||||||
this.initMap()
|
|
||||||
]);
|
|
||||||
|
|
||||||
//Direct link post action
|
|
||||||
if(this.hash.items.length == 3) await this.findPost(this.hash.items[1], this.hash.items[2]);
|
|
||||||
},
|
|
||||||
quit() {
|
|
||||||
this.lightbox.end();
|
|
||||||
this.$refs.feedSimpleBar.scrollElement.removeEventListener('scroll', this.onFeedScroll);
|
|
||||||
this.setFeedUpdateTimer(-1);
|
|
||||||
this.map.remove();
|
|
||||||
},
|
|
||||||
initProject() {
|
|
||||||
this.currProject = this.projects[this.hash.items[0]];
|
|
||||||
this.modeHisto = (this.currProject.mode == this.consts.modes.histo);
|
|
||||||
this.feed = {loading:false, updatable:true, outOfData:false, refIdFirst:0, refIdLast:0, firstChunk:true};
|
|
||||||
this.posts = [];
|
|
||||||
//this.baseMap = null;
|
|
||||||
this.baseMaps = {};
|
|
||||||
this.hikes.colors = {
|
this.hikes.colors = {
|
||||||
'main': this.getStyleProperty('--track-main'),
|
'main': this.getStyleProperty('--track-main'),
|
||||||
'off-track': this.getStyleProperty('--track-off-track'),
|
'off-track': this.getStyleProperty('--track-off-track'),
|
||||||
'hitchhiking': this.getStyleProperty('--track-hitchhiking')
|
'hitchhiking': this.getStyleProperty('--track-hitchhiking')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(!this.hash.items[0] || !this.projects[this.hash.items[0]]) await this.initProjectOverview();
|
||||||
|
else await this.initProject();
|
||||||
|
},
|
||||||
|
quit() {
|
||||||
|
this.lightbox.end();
|
||||||
|
this.$refs.feedSimpleBar?.scrollElement.removeEventListener('scroll', this.onFeedScroll);
|
||||||
|
this.setFeedUpdateTimer(-1);
|
||||||
|
this.map.remove();
|
||||||
|
},
|
||||||
|
async initProjectOverview() {
|
||||||
|
this.setFeedUpdateTimer(-1);
|
||||||
|
this.currProject = null;
|
||||||
|
this.modeHisto = null;
|
||||||
|
this.feed = {loading:false, updatable:true, outOfData:false, refIdFirst:0, refIdLast:0, firstChunk:true};
|
||||||
|
this.posts = [];
|
||||||
|
this.baseMaps = this.consts.default_maps;
|
||||||
|
|
||||||
|
await this.initMapOverview();
|
||||||
|
},
|
||||||
|
async initProject() {
|
||||||
|
this.setFeedUpdateTimer(-1);
|
||||||
|
this.currProject = this.projects[this.hash.items[0]];
|
||||||
|
this.modeHisto = (this.currProject.mode == this.consts.modes.histo);
|
||||||
|
this.feed = {loading:false, updatable:true, outOfData:false, refIdFirst:0, refIdLast:0, firstChunk:true};
|
||||||
|
this.posts = [];
|
||||||
|
this.baseMaps = {};
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
this.initFeed(),
|
||||||
|
this.initMapProject()
|
||||||
|
]);
|
||||||
|
|
||||||
|
//Direct link post action
|
||||||
|
if(this.hash.items.length == 3) await this.findPost(this.hash.items[1], this.hash.items[2]);
|
||||||
},
|
},
|
||||||
initLightbox() {
|
initLightbox() {
|
||||||
if(!this.lightbox) {
|
if(!this.lightbox) {
|
||||||
@@ -149,7 +159,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async initFeed() {
|
async initFeed() {
|
||||||
|
await this.$nextTick();
|
||||||
|
|
||||||
//Simplebar event
|
//Simplebar event
|
||||||
|
this.$refs.feedSimpleBar?.scrollElement.removeEventListener('scroll', this.onFeedScroll);
|
||||||
this.$refs.feedSimpleBar?.scrollElement.addEventListener('scroll', this.onFeedScroll);
|
this.$refs.feedSimpleBar?.scrollElement.addEventListener('scroll', this.onFeedScroll);
|
||||||
|
|
||||||
//Mobile Touchscreen Events
|
//Mobile Touchscreen Events
|
||||||
@@ -162,12 +175,12 @@ export default {
|
|||||||
|
|
||||||
//Get first posts batch
|
//Get first posts batch
|
||||||
await this.getNextFeed();
|
await this.getNextFeed();
|
||||||
this.$refs.feedSimpleBar.scrollElement.scrollTop = 0;
|
if(this.$refs.feedSimpleBar) this.$refs.feedSimpleBar.scrollElement.scrollTop = 0;
|
||||||
|
|
||||||
//Start auto-update
|
//Start auto-update
|
||||||
if(!this.modeHisto) this.setFeedUpdateTimer(this.refreshRate);
|
if(!this.modeHisto) this.setFeedUpdateTimer(this.refreshRate);
|
||||||
},
|
},
|
||||||
async initMap() {
|
async initMapProject() {
|
||||||
//Start async calls
|
//Start async calls
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -181,7 +194,51 @@ export default {
|
|||||||
this.api.get('geojson', {id_project: this.currProject.id})
|
this.api.get('geojson', {id_project: this.currProject.id})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
//Build Map
|
await this.initMapBase({
|
||||||
|
setCamera: () => {
|
||||||
|
this.map.fitBounds(this.getInitialMapBounds(), {
|
||||||
|
padding: 20,
|
||||||
|
animate: false,
|
||||||
|
maxZoom: 15
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addMarkers: () => {
|
||||||
|
this.addTrack(this.track);
|
||||||
|
this.markers.forEach(oMarker => this.addMarker(oMarker));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async initMapOverview() {
|
||||||
|
await this.initMapBase({
|
||||||
|
setCamera: () => {
|
||||||
|
//Center on default project
|
||||||
|
const oDefaultProject = this.projects.getDefaultProject();
|
||||||
|
|
||||||
|
//Adapt zoom to see whole planet
|
||||||
|
const $Canvas = this.map.getCanvas();
|
||||||
|
const iTargetRadius = Math.min($Canvas.clientWidth, $Canvas.clientHeight) / 2;
|
||||||
|
const iWorldSize = iTargetRadius * 2 * Math.PI * Math.cos(oDefaultProject.latitude * Math.PI / 180);
|
||||||
|
|
||||||
|
this.map.jumpTo({
|
||||||
|
center: new LngLat(oDefaultProject.longitude, oDefaultProject.latitude),
|
||||||
|
zoom: Math.log2(iWorldSize / this.map.transform.tileSize)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addMarkers: () => {
|
||||||
|
for(const asProject of Object.values(this.projects)) {
|
||||||
|
this.addMarker({
|
||||||
|
subtype: 'project',
|
||||||
|
longitude: asProject.longitude,
|
||||||
|
latitude: asProject.latitude,
|
||||||
|
opacityWhenCovered: 0.3
|
||||||
|
}, () => {
|
||||||
|
this.hash.items = [asProject.codename];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async initMapBase({setCamera, addMarkers}) {
|
||||||
if(this.map) this.map.remove();
|
if(this.map) this.map.remove();
|
||||||
this.map = new Map({
|
this.map = new Map({
|
||||||
container: 'map',
|
container: 'map',
|
||||||
@@ -200,16 +257,10 @@ export default {
|
|||||||
},
|
},
|
||||||
attributionControl: false
|
attributionControl: false
|
||||||
});
|
});
|
||||||
this.updateMapPadding();
|
|
||||||
this.map.fitBounds(this.getInitialMapBounds(), {
|
|
||||||
padding: 20,
|
|
||||||
animate: false,
|
|
||||||
maxZoom: 15
|
|
||||||
});
|
|
||||||
this.map.addControl(new ScaleControl({unit: 'metric'}), 'bottom-right');
|
|
||||||
|
|
||||||
//Get default basemap
|
this.updateMapPadding();
|
||||||
this.baseMap = this.baseMaps.find((asBM) => asBM.default_map)?.codename ?? null;
|
setCamera();
|
||||||
|
this.map.addControl(new ScaleControl({unit: 'metric'}), 'bottom-right');
|
||||||
|
|
||||||
//Force wait for load event
|
//Force wait for load event
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
@@ -218,6 +269,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Base maps (raster tiles)
|
//Base maps (raster tiles)
|
||||||
|
this.baseMap = this.baseMaps.find((asBM) => asBM.default_map)?.codename ?? null;
|
||||||
for(const asBaseMap of this.baseMaps) {
|
for(const asBaseMap of this.baseMaps) {
|
||||||
this.map.addSource(asBaseMap.codename, {
|
this.map.addSource(asBaseMap.codename, {
|
||||||
type: 'raster',
|
type: 'raster',
|
||||||
@@ -234,13 +286,7 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add track
|
addMarkers();
|
||||||
this.addTrack(this.track);
|
|
||||||
|
|
||||||
//Add Markers
|
|
||||||
this.markers.forEach(oMarker => this.addMarker(oMarker));
|
|
||||||
|
|
||||||
//Force wait for idle event
|
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
if(this.map.loaded() && this.map.areTilesLoaded()) resolve();
|
if(this.map.loaded() && this.map.areTilesLoaded()) resolve();
|
||||||
else this.map.once('idle', resolve);
|
else this.map.once('idle', resolve);
|
||||||
@@ -300,18 +346,19 @@ export default {
|
|||||||
options: this.projects.getTrackInfo(oEvent.features[0], this.track, this.lang),
|
options: this.projects.getTrackInfo(oEvent.features[0], this.track, this.lang),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
addMarker(oMarker) {
|
addMarker(oMarker, fClickCallback=null) {
|
||||||
const $Marker = document.createElement('div');
|
const $Marker = document.createElement('div');
|
||||||
createApp(SpotIconStack, this.markerProps[oMarker.subtype]).mount($Marker);
|
createApp(SpotIconStack, this.markerProps[oMarker.subtype]).mount($Marker);
|
||||||
|
|
||||||
new Marker({element: $Marker, anchor: 'bottom', opacityWhenCovered: 0})
|
new Marker({element: $Marker, anchor: 'bottom', opacityWhenCovered: oMarker.opacityWhenCovered ?? 0})
|
||||||
.setLngLat([oMarker.longitude, oMarker.latitude])
|
.setLngLat([oMarker.longitude, oMarker.latitude])
|
||||||
.addTo(this.map)
|
.addTo(this.map)
|
||||||
.getElement()
|
.getElement()
|
||||||
.addEventListener('click', (oEvent) => {
|
.addEventListener('click', (oEvent) => {
|
||||||
oEvent.preventDefault();
|
oEvent.preventDefault();
|
||||||
oEvent.stopPropagation();
|
oEvent.stopPropagation();
|
||||||
this.openMarkerPopup(oMarker.id, oMarker.type);
|
if(fClickCallback) fClickCallback(oEvent, oMarker);
|
||||||
|
else this.openMarkerPopup(oMarker.id, oMarker.type);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
openMarkerPopup(iMarkerId, sMarkerType) {
|
openMarkerPopup(iMarkerId, sMarkerType) {
|
||||||
@@ -574,7 +621,7 @@ export default {
|
|||||||
<div id="settings-panel" class="map-panel">
|
<div id="settings-panel" class="map-panel">
|
||||||
<div class="settings-header">
|
<div class="settings-header">
|
||||||
<div class="logo"><img width="289" height="72" src="images/logo_black.png" alt="Spotty" /></div>
|
<div class="logo"><img width="289" height="72" src="images/logo_black.png" alt="Spotty" /></div>
|
||||||
<div id="last_update" v-if="this.currProject.mode == this.consts.modes.blog && lastUpdate.unix_time > 0">
|
<div id="last_update" v-if="this.currProject && this.currProject.mode == this.consts.modes.blog && lastUpdate.unix_time > 0">
|
||||||
<p><span><img src="images/spot-logo-only.svg" alt="" /></span><abbr :title="lastUpdate.formatted_time">{{ lang.get('feed.last_update')+' '+lastUpdate.relative_time }}</abbr></p>
|
<p><span><img src="images/spot-logo-only.svg" alt="" /></span><abbr :title="lastUpdate.formatted_time">{{ lang.get('feed.last_update')+' '+lastUpdate.relative_time }}</abbr></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -625,18 +672,18 @@ export default {
|
|||||||
<div :class="'map-control map-control-icon settings-control map-control-'+(isMobile()?'bottom':'top')" @click="toggleSettingsPanel">
|
<div :class="'map-control map-control-icon settings-control map-control-'+(isMobile()?'bottom':'top')" @click="toggleSettingsPanel">
|
||||||
<SpotIcon :icon="settingsPanelOpen?'prev':'menu'" />
|
<SpotIcon :icon="settingsPanelOpen?'prev':'menu'" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!isMobile()" id="legend" class="map-control settings-control map-control-bottom">
|
<div v-if="currProject && !isMobile()" id="legend" class="map-control settings-control map-control-bottom">
|
||||||
<div v-for="(color, hikeType) in hikes.colors" class="track">
|
<div v-for="(color, hikeType) in hikes.colors" class="track">
|
||||||
<span class="line" :style="'background-color:'+color+'; height:'+hikes.width+'px;'"></span>
|
<span class="line" :style="'background-color:'+color+'; height:'+hikes.width+'px;'"></span>
|
||||||
<span class="desc">{{ lang.get('track.'+hikeType) }}</span>
|
<span class="desc">{{ lang.get('track.'+hikeType) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="title" :class="'map-control settings-control map-control-'+(isMobile()?'bottom':'top')">
|
<div v-if="currProject" id="title" :class="'map-control settings-control map-control-'+(isMobile()?'bottom':'top')">
|
||||||
<span>{{ currProject.name }}</span>
|
<span>{{ currProject.name }}</span>
|
||||||
</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 v-if="currProject" 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: lang.get('post.new_message')}" />
|
<ProjectPost v-else :options="{type: 'poster', relative_time: lang.get('post.new_message')}" />
|
||||||
@@ -648,7 +695,7 @@ export default {
|
|||||||
<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-'+(isMobile()?'bottom':'top')" @click="toggleFeedPanel">
|
<div v-if="currProject" :class="'map-control map-control-icon feed-control map-control-'+(isMobile()?'bottom':'top')" @click="toggleFeedPanel">
|
||||||
<SpotIcon :icon="feedPanelOpen?'next':'post'" />
|
<SpotIcon :icon="feedPanelOpen?'next':'post'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ export default class Projects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getDefaultProject() {
|
getDefaultProject() {
|
||||||
const sCodeName = this.getDefaultCodeName();
|
|
||||||
return this[this.getDefaultCodeName()];
|
return this[this.getDefaultCodeName()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
filter: drop-shadow(0px 1px 1px color.$over-img-shadow);
|
filter: drop-shadow(0px 1px 1px color.$over-img-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.message {
|
&.message, &.project {
|
||||||
.main {
|
.main {
|
||||||
color: color.$message-flashy;
|
color: color.$message-flashy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,10 @@
|
|||||||
margin-left: var.$text-spacing;
|
margin-left: var.$text-spacing;
|
||||||
@extend .clickable;
|
@extend .clickable;
|
||||||
@include common.no-text-overflow();
|
@include common.no-text-overflow();
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: color.$default-hover;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.download {
|
.download {
|
||||||
|
|||||||
Reference in New Issue
Block a user