client/src/MobicoopBundle/Resources/assets/js/components/utilities/MMap/MMap.vue
<template>
<v-row>
<v-col class="col-12">
<l-map
ref="mmap"
:zoom="zoom"
:center="center"
style="z-index:1; height:500px;"
>
<l-tile-layer
:url="url"
:attribution="attributionWithLinks"
/>
<!-- Markers in clusters -->
<v-marker-cluster
v-if="clusters"
:options="clusterOptions"
>
<m-marker
v-for="(point, index) in points"
:key="index"
:point="point"
:markers-draggable="markersDraggable"
@updateLatLng="updateLatLng"
@clickOnPoint="clickOnPoint(point)"
/>
</v-marker-cluster>
<!-- Only markers, no cluster -->
<m-marker
v-for="(point, index) in points"
v-else
:key="index"
:point="point"
:color="point.color"
:markers-draggable="markersDraggable"
:circle-marker="(point.circleMarker) ? point.circleMarker : false"
@updateLatLng="updateLatLng"
@clickOnPoint="clickOnPoint(point)"
/>
<v-dialog
v-if="selectedRelayPoint && selectedRelayPoint.misc && canSelectPoint"
v-model="dialog"
max-width="700"
>
<v-card
class="mx-auto"
max-width="700"
>
<v-img
height="150"
:src="$t('dialog.bannerUrl')"
/>
<v-card-title>
<v-row>
<v-col
cols="2"
class="mt-n12 pt-n12"
>
<v-avatar
color="white"
size="65"
>
<v-img
:src="selectedRelayPoint.icon.url"
height="50"
width="50"
contain
/>
</v-avatar>
</v-col>
<v-col justify="start">
<div class="secondary--text">
{{ $t('dialog.relayPointType.'+selectedRelayPoint.misc.type) }}
</div>
</v-col>
</v-row>
</v-card-title>
<v-card-text>
<v-row>
<v-col>
<div class="black--text text-h6">
{{ selectedRelayPoint.title }}
</div>
<div>{{ selectedRelayPoint.address.displayLabel[0] }}</div>
<div>{{ $t('dialog.latLng', {'lat': selectedRelayPoint.address.latitude, 'lng': selectedRelayPoint.address.longitude}) }}</div>
</v-col>
</v-row>
<v-row v-if="selectedRelayPoint.misc.description">
<v-col>
<div class="black--text text-h6">
{{ $t('dialog.moreInfos') }}
</div>
<div>
{{ selectedRelayPoint.misc.description }}
</div>
</v-col>
</v-row>
<v-row justify="start">
<v-col
v-if="selectedRelayPoint.misc.places"
cols="2"
>
<v-row
justify="center"
>
<v-icon color="secondary">
mdi-account-multiple
</v-icon>
</v-row>
<v-row
justify="center"
>
<div class="secondary--text text-center">
{{ $t('dialog.availableSpaces') }}
</div>
</v-row>
<v-row
justify="center"
>
<div>
{{ selectedRelayPoint.misc.places >= 0 ? selectedRelayPoint.misc.places : 0 }}
</div>
</v-row>
</v-col>
<v-col
v-if="selectedRelayPoint.misc.placesDisabled"
cols="2"
>
<v-row
justify="center"
>
<v-icon color="secondary">
mdi-wheelchair-accessibility
</v-icon>
</v-row>
<v-row
justify="center"
>
<div class="secondary--text text-center">
{{ $t('dialog.availableDisabledSpaces') }}
</div>
</v-row>
<v-row
justify="center"
>
<div>
{{ selectedRelayPoint.misc.placesDisabled >=0 ? selectedRelayPoint.misc.placesDisabled : 0 }}
</div>
</v-row>
</v-col>
<v-col
v-if="selectedRelayPoint.misc.free"
cols="2"
>
<v-row
justify="center"
>
<v-icon color="secondary">
mdi-currency-eur
</v-icon>
</v-row>
<v-row
justify="center"
>
<div class="secondary--text text-center">
{{ $t('dialog.free') }}
</div>
</v-row>
<v-row
justify="center"
>
<div>
{{ $t(selectedRelayPoint.misc.free) }}
</div>
</v-row>
</v-col>
<v-col
v-if="selectedRelayPoint.misc.private"
cols="2"
>
<v-row
justify="center"
>
<v-icon color="secondary">
mdi-shield-lock
</v-icon>
</v-row>
<v-row
justify="center"
>
<div class="secondary--text text-center">
{{ $t('dialog.private') }}
</div>
</v-row>
<v-row
justify="center"
>
<div>
{{ $t(selectedRelayPoint.misc.private) }}
</div>
</v-row>
</v-col>
<v-col
v-if="selectedRelayPoint.misc.secured"
cols="2"
>
<v-row
justify="center"
>
<v-icon color="secondary">
mdi-boom-gate
</v-icon>
</v-row>
<v-row
justify="center"
>
<div class="secondary--text text-center">
{{ $t('dialog.secured') }}
</div>
</v-row>
<v-row
justify="center"
>
<div>
{{ $t(selectedRelayPoint.misc.secured) }}
</div>
</v-row>
</v-col>
<v-col
v-if="selectedRelayPoint.misc.official"
cols="2"
>
<v-row
justify="center"
>
<v-icon color="secondary">
mdi-clipboard-check-outline
</v-icon>
</v-row>
<v-row
justify="center"
>
<div class="secondary--text text-center">
{{ $t('dialog.official') }}
</div>
</v-row>
<v-row
justify="center"
>
<div>
{{ $t(selectedRelayPoint.misc.official) }}
</div>
</v-row>
</v-col>
</v-row>
<v-row
class="mb-n6"
justify="center"
>
<div>
{{ $t('dialog.selectRelayPoint') }}
</div>
</v-row>
</v-card-text>
<v-card-actions class="justify-center">
<v-btn
width="120"
color="primary"
@click="selectRelayPointAsOrigin"
>
{{ $t('dialog.origin') }}
</v-btn>
<v-btn
width="120"
color="primary"
@click="selectRelayPointAsDestination"
>
{{ $t('dialog.destination') }}
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog
v-else-if="canSelectPoint"
v-model="dialog"
max-width="400"
>
<v-card>
<v-card-title class="text-h6 justify-center">
{{ $t('dialog.title') }}
</v-card-title>
<v-card-actions class="justify-center">
<v-btn
class="ml-8"
color="primary"
text
@click="selectRelayPointAsOrigin"
>
{{ $t('dialog.origin') }}
</v-btn>
<v-btn
color="primary"
text
@click="selectRelayPointAsDestination"
>
{{ $t('dialog.destination') }}
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<l-polyline
v-for="(way, i) in ways"
:key="'w'+i"
:lat-lngs="way.latLngs"
:color="(way.color!=='' && way.color !==undefined)?way.color:'blue'"
:dash-array="(way.dashArray) ? way.dashArray : ''"
@click="clickOnPolyline"
>
<l-tooltip v-if="way.title !==undefined && way.title!==''">
<p v-html="way.title" />
</l-tooltip>
<l-popup
v-if="way.desc !==undefined && way.desc!==''"
>
<p v-html="way.desc" />
</l-popup>
</l-polyline>
</l-map>
</v-col>
</v-row>
</template>
<script>
import L from "leaflet";
import maxios from "@utils/maxios";
import VMarkerCluster from 'vue2-leaflet-markercluster'
import MMarker from "@components/utilities/MMap/MMarker"
import {messages_en, messages_fr, messages_eu, messages_nl} from "@translations/components/utilities/MMap/MMap";
export default {
i18n: {
messages: {
'en': messages_en,
'nl': messages_nl,
'fr': messages_fr,
'eu':messages_eu
}
},
components: {
VMarkerCluster,
MMarker
},
props: {
provider: {
type: String,
default: "OpenStreetMap"
},
urlTiles: {
type: String,
default: "https://{s}.tile.osm.org/{z}/{x}/{y}.png"
},
providerKey: {
// unused for the moment
type: String,
default: ""
},
attributionCopyright: {
type: String,
default: '{"OpenStreetMap":"https://osm.org/copyright"}'
},
centerDefault: {
type: Array,
default: function(){return [];}
},
zoom: {
type: Number,
default: 13
},
typeMap: {
type: String,
default: ""
},
points: {
type: Array,
default: function(){return [];}
},
ways: {
type: Array,
default: function(){return [];}
},
markersDraggable: {
type: Boolean,
default: false
},
relayPoints: {
type: Boolean,
default: false
},
clusters: {
type: Boolean,
default: true
},
dashArray:{
type: String,
default: null
},
territoryId: {
type: String,
default: null
},
canSelectPoint: {
type: Boolean,
default: false
}
},
data() {
return {
center: L.latLng(this.centerDefault[0], this.centerDefault[1]),
url:this.urlTiles,
attribution:this.attributionCopyright,
markers:this.points,
dialog: false,
address: null,
clusterOptions: {},
territory: null,
selectedRelayPoint: null
};
},
computed: {
attributionWithLinks(){
let arrayAttribution = [];
let jsonAttribution = JSON.parse(this.attribution)
for(let contributor in jsonAttribution){
arrayAttribution.push("<a href='"+jsonAttribution[contributor]+"' title=''>"+contributor+"</a>");
}
return arrayAttribution.join(', ');
}
},
mounted() {
window.L = L;
if (this.territoryId) {
this.getTerritory();
}
},
methods: {
getTerritory() {
maxios
.post(`${this.$t("territory")}/${this.territoryId}`)
.then(res => {
this.territory = res.data;
if (this.territory.minLatitude && this.territory.maxLatitude && this.territory.minLongitude && this.territory.maxLongitude) {
this.territory.bounds = L.latLngBounds(L.latLng(this.territory.minLatitude,this.territory.minLongitude), L.latLng(this.territory.maxLatitude, this.territory.maxLongitude));
this.redrawMap();
}
})
.catch(err => console.error(err));
},
redrawMap: function() {
// To redraw the map (when you resize the div you have to redraw the map)
setTimeout(() => {
this.$refs.mmap.mapObject.invalidateSize();
// I'm using all points to set the boundaries
let bounds = [];
this.points.forEach((pointForBound, index) => {
bounds.push([pointForBound.latLng.lat,pointForBound.latLng.lng]);
});
if (bounds.length === 0 && this.territory && this.territory.bounds){
bounds.push(this.territory.bounds);
}
if (bounds.length > 0) {
this.$refs.mmap.mapObject.fitBounds(bounds);
}
}, 100);
},
updateLatLng(data){
// data contains a LatLng object.
this.$emit("updateLatLng",data);
},
clickOnPolyline(data){
// data contains a LatLng object.
this.$emit("clickOnPolyline",data);
},
clickOnPoint(point){
if (this.relayPoints) {
this.dialog = true;
this.address = point.address;
this.selectedRelayPoint = point;
}
},
selectRelayPointAsOrigin() {
if (this.relayPoints) {
this.$emit("SelectedAsOrigin",this.address);
this.address= null;
this.dialog= false;
}
},
selectRelayPointAsDestination() {
if (this.relayPoints) {
this.$emit("SelectedAsDestination",this.address);
this.address= null;
this.dialog= false;
}
}
}
};
</script>
<style lang="scss" scoped>
#description-tooltip{
width: auto;
max-width: 200px;
overflow:hidden;
text-overflow: ellipsis;
}
</style>