import L from 'leaflet'
import Vue from 'vue'
import { getVehicleIconHTML } from '@/services/vehicle-service.js'
import { getPolylineFromLinestring } from '@/utils/map.js'
import { generateShortId } from '@/utils/crypto.js'
const R = require('ramda')
/**
* Used by Location module (Real-time) to render real-time results in the map (Vehicle markers).
* @param {*} item Wrapper on top of location item (main results) that includes a Leaflet icon.
* @returns
*/
export function createMarkerFromRealtimeItem(item = {}) {
function getChronoStatusClassName(value) {
return (
{
Travail: 'working',
Repos: 'resting',
Conduite: 'driving',
Dispo: 'available',
}[value] || value
)
}
let degValue = item.cap < 0 ? 360 - item.cap : item.cap
return Object.freeze({
latlng: [item.lat, item.lng],
normalizedItem: item,
item: {
...item.raw,
normalizedItem: R.omit(['raw'], item),
},
icon: L.divIcon({
className: 'realtime__marker',
html: `<div class="marker__content">
<div>
<img class="marker_icon"
data-api-cap="${item.cap}"
data-computed-degrees="${degValue}"
style="transform:translate(-50%, -50%) rotate(${
degValue // > 180 ? 270 : 90
}deg)"
src="./lib/realtimeMap/assets/picto_pins/Pin.svg">
${getVehicleIconHTML(item.vehicleCategoryClassName, {
flipHorizontally: degValue > 180,
})}
<img class="marker__contact_icon"
style="background-color:${item.vehicleStatusColor}"
src="./lib/realtimeMap/assets/picto_status/Contact.svg" />
${
item.driverChronoEnabled
? `
<div
class="marker__chrono_icon ${getChronoStatusClassName(
item.driverChornoStatusOriginal
)}"
></div>
`
: ``
}
</div>
<p class="marker__label">
${item.vehicleName}
</p >
</div>
`,
}),
})
}
/**
* Wrapper for Leaflet polyline (Array of LatLng)
*
* @param {*} item
* @param {*} singleLinestring
* @param {*} options
* @returns
*/
export function createSinglePolylineEntity(
item,
singleLinestring = '',
options = {}
) {
return {
id: item.id || generateShortId('id_'),
...(item.number ? { stepNumber: item.number } : {}),
smoothFactor: 0.5,
weight: parseInt(process.env.VUE_APP_LOCATION_MAP_POLYLINE_WEIGHT) || 5,
type: item.type || options.type || 'trip_history', //trip_history, circuit_execution (will draw arrows)
polyline: getPolylineFromLinestring(singleLinestring),
color: item.color || options.color || '#0b72b5', //couleur
}
}
/**
* Used by:
* Location - Real-time - Circuit
* Location - Circuit tab
* Location - History tab
* Diagnostics
* Converts Array of items containing a linestring property (APV2 format) into an array of polylines (Format accepted by LeafletMap wrapper)
* The linestring property can be either an string or an array (multiple linestrings) (#31781)
* @param {String} linestrings Array of LatLng I.g: "lat1 lng1, lat2 lng2"
* @returns
*/
export function linestringsToPolylines(array, options = {}) {
let polylineEntities = []
array.forEach((item) => {
let singleLinestringOrArray = item[options.key || 'linestring'] || ''
if (singleLinestringOrArray instanceof Array) {
singleLinestringOrArray.forEach((singleLinestring) => {
polylineEntities.push(
createSinglePolylineEntity(
item,
singleLinestring.linestring !== undefined
? singleLinestring.linestring
: singleLinestring,
{
...options,
color: singleLinestring.color || options.color || null,
}
)
)
})
} else {
let singleLinestring = singleLinestringOrArray
polylineEntities.push(
createSinglePolylineEntity(item, singleLinestring, options)
)
}
})
return polylineEntities
.filter((item) => item.polyline.length !== 0)
.map((item) => {
if (options.transform) {
item = options.transform(item)
}
return item
})
}
export default {
methods: {
/**
* Used by Location circuit tab
* Used by Reference circuit feature
* Used by Location (main search)
* Used by Location history tab
*/
linestringsToPolylines,
/**
* Used by Location module
* Used by NearbyVehicles feature
*/
createMarkerFromRealtimeItem,
/**
* Used by Leaflet wrapper to generate popups using VueJS components.
* @param {*} geometry
* @param {*} componentDefinitionOrPromise
* @param {*} options
*/
bindLeafletPopupComponent(
geometry,
componentDefinitionOrPromise,
options = {}
) {
let id = generateShortId('popup_')
geometry.bindPopup(`<div id="${id}" style="${options.style || ''}">
</div>`)
let instance
geometry.on('popupclose', () => {
instance && instance.$destroy()
})
geometry.on('popupopen', () => {
const componentDefinition =
typeof componentDefinitionOrPromise !== 'object'
? {
name: 'LeafletPopupWrapper',
components: {
Popup: componentDefinitionOrPromise,
},
template: `<Popup :geometry="geometry" />`,
computed: {
geometry() {
return geometry
},
},
}
: componentDefinitionOrPromise
const VueComponentClass = Vue.extend(componentDefinition)
instance = new VueComponentClass({
parent: options.parent || null,
})
instance.$mount()
const popupWrapper = document.querySelector(`#${id}`)
if (popupWrapper) {
popupWrapper.appendChild(instance.$el)
} else {
Vue.$log.warn(
`bindLeafletPopupComponent::Couldn't find the popup wrapper #${id}`
)
}
})
},
},
}
Source