Skip to content
Snippets Groups Projects
Commit df39c4bf authored by Timothee P's avatar Timothee P :sunflower:
Browse files

geocoder increase limit, add coordinates, improve behavior & style

parent 0c4edfea
No related branches found
No related tags found
1 merge request!617REDMINE_ISSUE-17474 | Ajouter un geocodeur ETALAB sur les cartes
<template>
<div
:class="{ expanded: isExpanded }"
class="geocoder-container"
id="geocoder-container"
:class="{ isExpanded }"
>
<button
class="button-geocoder"
@click="isExpanded = !isExpanded"
@click="toggleGeocoder"
>
<i class="search icon" />
</button>
<Multiselect
v-if="isExpanded"
ref="multiselect"
v-model="selection"
class="expanded-geocoder"
:options="addresses"
:options-limit="5"
:options-limit="limit"
:allow-empty="true"
track-by="label"
label="label"
......@@ -31,6 +32,7 @@
:preserve-search="true"
@search-change="search"
@select="select"
@open="retrievePreviousPlaces"
@close="close"
>
<template
......@@ -76,14 +78,18 @@ const apiAdressAxios = axios.create({
baseURL: 'https://api-adresse.data.gouv.fr',
withCredentials: false,
});
export default {
name: 'Geocoder',
components: {
Multiselect
},
data() {
return {
loading: false,
limit: 10,
selection: null,
text: null,
selectedAddress: null,
......@@ -93,19 +99,36 @@ export default {
isExpanded: false
};
},
mounted() {
this.addressTextChange = new Subject();
this.addressTextChange.pipe(debounceTime(200)).subscribe((res) => this.getAddresses(res));
},
methods: {
toggleGeocoder() {
this.isExpanded = !this.isExpanded;
if (this.isExpanded) {
this.retrievePreviousPlaces();
this.$nextTick(()=> this.$refs.multiselect.activate());
}
},
getAddresses(query){
const limit = 5;
apiAdressAxios.get(`https://api-adresse.data.gouv.fr/search/?q=${query}&limit=${limit}`)
if (query.length < 3) {
this.addresses = [];
return;
}
const coords = mapService.getMapCenter();
let url = `https://api-adresse.data.gouv.fr/search/?q=${query}&limit=${this.limit}`;
if (coords) url += `&lon=${coords[0]}&lat=${coords[1]}`;
apiAdressAxios.get(url)
.then((retour) => {
this.resultats = retour.data.features;
this.addresses = retour.data.features.map(x=>x.properties);
});
},
selectAddresse(event) {
this.selectedAddress = event;
if (this.selectedAddress !== null && this.selectedAddress.geometry) {
......@@ -122,27 +145,59 @@ export default {
mapService.zoomTo(this.selectedAddress.geometry.coordinates, zoomlevel);
// On ajoute un point pour localiser la ville
mapService.addOverlay(this.selectedAddress.geometry.coordinates);
this.setLocalstorageSelectedAdress(this.selectedAddress);
}
},
search(text) {
this.text = text;
this.addressTextChange.next(this.text);
},
select(e) {
this.selectAddresse(this.resultats.find(x=>x.properties.label === e.label));
this.$emit('select', e);
},
close() {
this.$emit('close', this.selection);
}
},
setLocalstorageSelectedAdress(newAdress) {
let selectedAdresses = JSON.parse(localStorage.getItem('geocontrib-selected-adresses'));
selectedAdresses = Array.isArray(selectedAdresses) ? selectedAdresses : [];
selectedAdresses = [ newAdress, ...selectedAdresses ];
const uniqueLabels = [...new Set(selectedAdresses.map(el => el.properties.label))];
const uniqueAdresses = uniqueLabels.map((label) => {
return selectedAdresses.find(adress => adress.properties.label === label);
});
localStorage.setItem(
'geocontrib-selected-adresses',
JSON.stringify(uniqueAdresses.slice(0, 5))
);
},
getLocalstorageSelectedAdress() {
return JSON.parse(localStorage.getItem('geocontrib-selected-adresses')) || [];
},
retrievePreviousPlaces() {
const previousAdresses = this.getLocalstorageSelectedAdress();
if (previousAdresses.length > 0) {
this.addresses = previousAdresses.map(x=>x.properties);
this.resultats = previousAdresses;
}
},
}
};
</script>
<style scoped lang="less">
.geocoder-container {
<style lang="less">
#geocoder-container {
position: absolute;
right: 0.5em;
right: 6px;
// each button have (more or less depends on borders) .5em space between
// zoom buttons are 60px high, geolocation and full screen button is 34px high with borders
top: calc(1.6em + 60px + 34px + 34px);
......@@ -151,7 +206,7 @@ export default {
border: 2px solid rgba(0,0,0,.2);
background-clip: padding-box;
padding: 0;
border-radius: 2px;
border-radius: 4px;
display: flex;
.button-geocoder {
......@@ -161,8 +216,8 @@ export default {
text-align: center;
background-color: #fff;
color: rgb(39, 39, 39);
width: 28px;
height: 28px;
width: 30px;
height: 30px;
font: 700 18px Lucida Console,Monaco,monospace;
border-radius: 2px;
line-height: 1.15;
......@@ -180,21 +235,57 @@ export default {
.expanded-geocoder {
max-width: 400px;
}
}
.expanded {
.button-geocoder {
height: 40px;
color: rgb(99, 99, 99);
&&.isExpanded {
.button-geocoder {
height: 41px;
color: rgb(99, 99, 99);
border-radius: 2px 0 0 2px;
}
}
}
#marker {
width: 20px;
height: 20px;
border: 1px solid rgb(136, 66, 0);
border-radius: 10px;
background-color: rgb(201, 114, 15);
opacity: 0.7;
#marker {
width: 20px;
height: 20px;
border: 1px solid rgb(136, 66, 0);
border-radius: 10px;
background-color: rgb(201, 114, 15);
opacity: 0.7;
}
// /* keep placeholder width when opening dropdown */
.multiselect {
min-width: 208px;
}
/* keep font-weight from overide of semantic classes */
.multiselect__placeholder, .multiselect__content, .multiselect__tags {
font-weight: initial !important;
}
/* keep placeholder eigth */
.multiselect .multiselect__placeholder {
margin-bottom: 9px !important;
padding-top: 1px;
}
/* keep placeholder height when opening dropdown without selection */
input.multiselect__input {
padding: 3px 0 0 0 !important;
}
/* keep placeholder height when opening dropdown with already a value selected */
.multiselect__tags .multiselect__single {
padding: 1px 0 0 0 !important;
margin-bottom: 9px;
}
.multiselect__tags {
border: 0 !important;
min-height: 41px !important;
}
.multiselect input {
line-height: 1em !important;
padding: 0 !important;
}
.multiselect__content-wrapper {
border: 2px solid rgba(0,0,0,.2);
}
}
</style>
\ No newline at end of file
......@@ -51,7 +51,7 @@ button.button-geolocation {
width: 30px;
height: 30px;
font: 700 18px Lucida Console,Monaco,monospace;
border-radius: 4px;
border-radius: 2px;
line-height: 1.15;
cursor: pointer;
}
......
......@@ -714,6 +714,14 @@ const mapService = {
stopEvent: false
});
this.map.addOverlay(marker);
},
getMapCenter() {
const location = this.map.getView().getCenter();
if (location) {
return transform(location, 'EPSG:3857', 'EPSG:4326');
}
return null;
}
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment