<template lang="pug">
.routing-form-wrapper
.routing-form-search(v-show="instructions.length===0")
RoutingCoordsForm(v-model="addresses")
FormBuilder(
v-model="formData"
:sections="sections"
has-valid-btn
:loading="isLoading"
:validBtnDisabled="!isSearchFormValid"
class="mt-2 form-builder-wrapper"
@valid="performRouting"
theme="theme-simpliciti"
)
template(v-slot:component_vehicle_feature="slotProps")
VehicleFeatureForm(v-model="slotProps.formData.vehicle")
template(v-slot:component_speed_ponderation="slotProps")
SpeedPonderationForm(v-model="slotProps.formData.speedPonderation")
RoutingList(v-show="instructions.length>0" :items="instructions"
:headerInformation="headerInformation"
@mode="switchViewMode"
@selectItem="item=>highlightRoutingInstructionPolyline(item.number)"
@deselectItem="item=>unhightlightRoutingInstructionPolyline(item.number)"
)
</template>
<script>
import FormBuilder from '@c/shared/Builders/FormBuilder.vue'
import VehicleFeatureForm from './VehicleFeatureForm.vue'
import SpeedPonderationForm from './SpeedPonderationForm.vue'
import RoutingCoordsForm from '@c/shared/geocoding/RoutingCoordsForm/RoutingCoordsForm.vue'
import geocodingMixin from '@c/shared/geocoding/geocoding-mixin.js'
import mapMixins from '@/mixins/simpliciti-map-mixin.js'
import RoutingList from './RoutingList.vue'
import { transportTypeOptions } from '@/services/geocoding-service.js'
/**
* @description Routing feature (Calcul d'itinéraire)
* Note: The Routing feature doesn't have a custom map but instead, it should use the map the user see at that moment.
* @requires SimplicitiMap Component should be present and alive in the DOM (For table results and markers)
* @example
* Test API:
* vue.$geocoding.routingGeocoding({coordinates:[[3.9060772,43.6028552],[4.1398221,43.5189621
]]}).then(console.warn)
* API response format: see routing-example.json
* @namespace components
* @category components
* @subcategory shared/geocoding/routing
* @module RoutingFeature
*/
export default {
name: 'RoutingFeature',
components: {
SpeedPonderationForm,
VehicleFeatureForm,
FormBuilder,
RoutingCoordsForm,
RoutingList,
},
mixins: [geocodingMixin, mapMixins],
provide() {
let self = this
return {
handleListBackButtonClick() {
self.markers = []
self.instructions = []
self.headerInformation = {}
self.instructionsCoordinates = []
self.addRoutingSearchMarkersToMap()
self.setSimplicitiMapBottomMenuVMComponent(null)
},
}
},
inject: {
mapToolboxContext: {
default: () => ({ setContentPanelVisible: () => {} }),
},
},
data() {
return {
viewMode: 'list',
isLoading: false,
addresses: [
{
key: 'start',
value: {},
},
{
key: 'end',
value: {},
},
],
instructionsCoordinates: [],
instructions: [],
markers: [],
headerInformation: {},
formData: {
no_ferries_routing: false,
routing_locomotion: false,
no_highways_routing: false,
short_routing: false,
no_tolls_routing: false,
transportType: 'car',
fastest: true,
vehicle: {},
speedPonderation: {},
},
sections: [
{
name: 'routing_start_section',
header: false,
collapsable: false,
rowsClass: 'mb-1',
rows: [
{
columns: [
{
label: 'transportType',
title: 'geocoding.routing.transportType',
type: 'select',
value: 'car',
options: transportTypeOptions,
},
],
},
{
columns: [
{
label: 'shortest',
title: 'geocoding.routing.shortest',
type: 'checkbox',
value: false,
},
{
label: 'fastest',
title: 'geocoding.routing.fastest',
type: 'checkbox',
value: true,
},
],
},
{
id: 'routing_checkbox_row_2',
columns: [
{
label: 'avoidMotorways',
title: 'geocoding.routing.avoidMotorways',
type: 'checkbox',
value: false,
},
{
label: 'avoidTolls',
title: 'geocoding.routing.avoidTolls',
type: 'checkbox',
value: false,
},
],
},
{
columns: [
{
label: 'avoidFerries',
title: 'geocoding.routing.avoidFerries',
type: 'checkbox',
value: false,
},
],
},
{
columns: [
{
label: 'vehicle_feature',
type: 'component',
disableFlyingLabel: true,
},
],
},
{
id: 'speed_ponderation_row',
columns: [
{
label: 'speed_ponderation',
type: 'component',
disableFlyingLabel: true,
},
],
},
],
},
],
}
},
computed: {
isSearchFormValid() {
return (
this.addresses.filter((a) => a.value && !!a.value.lat && !!a.value.lng)
.length >= 2
)
},
computedSections() {
return [
/* ...[{
name:"routing_from_section", header:false, collapsable:false,
rows: this.fromArray.map(item=>{
return {}
})
}],*/
...this.sections,
]
},
},
watch: {
addresses: {
handler() {
this.addRoutingSearchMarkersToMap()
},
deep: true,
immediate: true,
},
instructions: {
handler() {
this.addRoutingInstructionsPolylines([
//A base polyline will cover the entire trip (API response.linestring attribute)
...[
{
id: 'base',
coordinates: this.instructionsCoordinates,
},
],
...this.instructions,
])
},
},
markers: {
handler() {
this.addRoutingResultMarkers(this.markers)
},
},
},
mounted() {
this.mapClearMarkersFromLayer('routingSearchMarkers')
this.mapClearMarkersFromLayer('routingInstructionsPolylines')
this.mapClearMarkersFromLayer('routingResultsMarkers')
this.setSimplicitiMapBottomMenuVMComponent(null)
},
destroyed() {
this.mapClearMarkersFromLayer('routingSearchMarkers')
this.mapClearMarkersFromLayer('routingInstructionsPolylines')
this.mapClearMarkersFromLayer('routingResultsMarkers')
this.setSimplicitiMapBottomMenuVMComponent(null)
},
methods: {
setSimplicitiMapBottomMenuVMComponent(component) {
let vm = this.$map.getSimplicitiMapBottomMenuVM()
if (vm) {
vm.component = component
}
},
setSimplicitiMapBottomMenuVMFullScreen(isFullscreen) {
let vm = this.$map.getSimplicitiMapBottomMenuVM()
if (vm) {
vm.isFullscreen = isFullscreen
}
},
switchViewMode(mode) {
let self = this
self.viewMode = mode
if (['table', 'table_map'].includes(mode)) {
this.setSimplicitiMapBottomMenuVMComponent({
name: 'RoutingTableWrapper',
template: `<RoutingTable :items="items"
:headerText="headerText"
:mode="mode" @mode="switchViewMode"/>`,
components: {
RoutingTable: () =>
import('@c/shared/geocoding/RoutingFeature/RoutingTable.vue'),
},
computed: {
mode() {
return self.viewMode
},
items() {
return self.instructions
},
headerText() {
return `Durée : ${
self.headerInformation.duration || '...'
} Distance : ${
self.headerInformation.length || '...'
} Vitesse : ${self.headerInformation.speed || '...'}`
},
},
methods: {
switchViewMode(mode) {
self.switchViewMode(mode)
},
},
})
if (mode === 'table') {
this.setSimplicitiMapBottomMenuVMFullScreen(true)
} else {
this.setSimplicitiMapBottomMenuVMFullScreen(false)
}
this.mapToolboxContext.setContentPanelVisible(false)
} else {
this.mapToolboxContext.setContentPanelVisible(true)
this.setSimplicitiMapBottomMenuVMComponent(null)
}
},
async addRoutingSearchMarkersToMap() {
let markers = this.addresses
.filter(
(item) =>
Object.keys(item.value).length > 0 &&
!!item.value.lat &&
!!item.value.lng
)
.map((item) => item.value)
if (markers.length > 0) {
this.addRoutingSearchMarkers(markers)
} else {
this.mapClearMarkersFromLayer('routingSearchMarkers')
}
},
async performRouting(event) {
this.$loader.show()
let res = await this.$geocoding.routingGeocoding({
...this.formData,
coordinates: this.addresses
.filter((i) => i.value && !!i.value.lat && !!i.value.lng)
.map((i) => [i.value.lng, i.value.lat]),
})
this.instructionsCoordinates = res.instructionsCoordinates
this.instructions = res.instructions || []
this.markers = res.markers || []
this.headerInformation = {
length: res.lengthFormatted,
duration: res.durationFormatted,
speed: res.averageSpeedFormatted,
}
this.$loader.hide()
},
},
}
</script>
<style lang="scss" scoped>
.form-builder-wrapper {
font-size: 12px;
}
</style>
Source