Let user pick a location manually, fix for #3.
This commit is contained in:
parent
a67462fab0
commit
edadbd6393
114
src/components/AddressInput.vue
Normal file
114
src/components/AddressInput.vue
Normal file
@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<v-combobox
|
||||
:loading="loading"
|
||||
required
|
||||
:items="items"
|
||||
:search-input.sync="search"
|
||||
:filter="filter"
|
||||
v-model="select"
|
||||
:label="label"
|
||||
:hint="hint"
|
||||
persistent-hint
|
||||
clearable
|
||||
append-icon="my_location"
|
||||
:rules="rules"
|
||||
v-on:input="onInputHandler"
|
||||
></v-combobox>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import fetch from 'isomorphic-fetch';
|
||||
|
||||
const API_ENDPOINT = 'https://api-adresse.data.gouv.fr/search/';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
label: String,
|
||||
hint: String,
|
||||
onInput: Function,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
APIItems: [],
|
||||
search: null,
|
||||
select: null,
|
||||
selectedItem: null,
|
||||
rules: [
|
||||
this.checkValue,
|
||||
],
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
search(value) {
|
||||
if (value) {
|
||||
this.queryAPI(value);
|
||||
} else {
|
||||
this.APIItems = [];
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
checkValue() {
|
||||
return (this.selectedItem != null) || 'Invalid selection';
|
||||
},
|
||||
queryAPI(value) {
|
||||
this.loading = true;
|
||||
|
||||
fetch(`${API_ENDPOINT}?q=${value}`)
|
||||
.then(response => response.json())
|
||||
.then(data => data.features)
|
||||
.then((data) => {
|
||||
this.loading = false;
|
||||
this.APIItems = [];
|
||||
data.forEach(
|
||||
item => this.APIItems.push(item),
|
||||
);
|
||||
this.APIItems.sort((a, b) => (b.properties.score - a.properties.score));
|
||||
this.APIItems = Array.concat([], this.APIItems);
|
||||
});
|
||||
},
|
||||
onInputHandler(value) {
|
||||
if (!value) {
|
||||
this.APIItems = [];
|
||||
} else {
|
||||
// Check against location string
|
||||
const APIItem = this.APIItems.find(item => (
|
||||
item.properties && item.properties.label === value),
|
||||
);
|
||||
if (APIItem) {
|
||||
this.selectedItem = {
|
||||
latlng: {
|
||||
lat: APIItem.geometry.coordinates[1],
|
||||
lng: APIItem.geometry.coordinates[0],
|
||||
},
|
||||
label: APIItem.properties.label,
|
||||
};
|
||||
this.onInput(this.selectedItem);
|
||||
return;
|
||||
}
|
||||
|
||||
// No matched position
|
||||
this.selectedItem = null;
|
||||
}
|
||||
},
|
||||
filter(items) {
|
||||
// No filtering, already handled by the API endpoint.
|
||||
return items;
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
items() {
|
||||
if (this.APIItems.length > 0) {
|
||||
return this.APIItems.map((item) => {
|
||||
if (item.properties) {
|
||||
return item.properties.label;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
return [];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
@ -2,7 +2,7 @@
|
||||
export default {
|
||||
about: {
|
||||
availableReportsTitle: 'The available reports so far are:',
|
||||
geolocationDescription: 'As of current version, your precise geolocation is handled within your device and never sent from it to any external service. The map background is downloaded on demand from <a href="https://carto.com/location-data-services/basemaps/">Carto.com</a> and they have then access to an estimate of the displayed position.',
|
||||
geolocationDescription: 'As of current version, your precise geolocation is handled within your device and never sent from it to any external service. The map background is downloaded on demand from <a href="https://carto.com/location-data-services/basemaps/">Carto.com</a> and they have then access to an estimate of the displayed position. If you refuse to share your geolocation, you can still pick a location manually but you will miss some geolocation dependent features.',
|
||||
license: 'It is released under an <a href="https://opensource.org/licenses/MIT">MIT license</a> (<a href="https://framagit.org/phyks/cyclassist">source code</a>). Icons are based on creations from Wikimedia and Vecteezy. The map background is using tiles from <a href="https://carto.com/location-data-services/basemaps/">Carto.com</a>, thanks to <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors</a> and <a href="http://leafletjs.com/">Leaflet</a>. Collected reports are available under <a href="https://opendatacommons.org/licenses/odbl/">ODbL license</a>.',
|
||||
summary: 'This app lets you track and share issues with bike lanes.',
|
||||
usage: 'How to use',
|
||||
|
@ -2,7 +2,7 @@
|
||||
export default {
|
||||
about: {
|
||||
availableReportsTitle: "Les signalements disponibles pour l'instant sont :",
|
||||
geolocationDescription: "Dans la version actuelle, votre position est traitée directement par votre appareil et n'est jamais envoyée à un service externe. Le fond de carte est téléchargé à la demande depuis <a href='https://carto.com/location-data-services/basemaps/'>Carto.com</a> et ils ont donc accès à une estimation de la position affichée.",
|
||||
geolocationDescription: "Dans la version actuelle, votre position est traitée directement par votre appareil et n'est jamais envoyée à un service externe. Le fond de carte est téléchargé à la demande depuis <a href='https://carto.com/location-data-services/basemaps/'>Carto.com</a> et ils ont donc accès à une estimation de la position affichée. Si vous refusez le partage de votre géolocalisation, vous pourrez saisir une adresse manuellement à la place mais vous perdrez les fonctionnalités avancées qui reposent sur la géolocalisation.",
|
||||
license: "Le code source est sous <a href='https://opensource.org/licenses/MIT'>licence MIT license</a> (<a href='https://framagit.org/phyks/cyclassist'>code source</a>). Les icones sont basées sur des travaux de Wikimedia et Vecteezy. Les tuiles de fond de carte proviennent de chez <a href='https://carto.com/location-data-services/basemaps/'>Carto.com</a>, grace aux <a href='https://www.openstreetmap.org/copyright'>contributeurs OpenStreetMap</a> et à <a href='http://leafletjs.com/'>Leaflet</a>. Les signalements sont disponibles sous <a href='https://opendatacommons.org/licenses/odbl/'>licence ODbL</a>.",
|
||||
summary: 'Cette application vous permet de signaler et de partager des problèmes avec les itinéraires cyclables.',
|
||||
usage: 'Utilisation',
|
||||
|
@ -21,12 +21,16 @@
|
||||
</v-btn>
|
||||
<ReportDialog v-model="dialog" :lat="reportLat" :lng="reportLng"></ReportDialog>
|
||||
</v-flex>
|
||||
<v-flex xs12 fill-height v-else class="pa-3">
|
||||
<v-flex xs12 sm6 offset-sm3 md4 offset-md4 fill-height v-else class="pa-3">
|
||||
<template v-if="error">
|
||||
<p class="text-xs-center">{{ error }}</p>
|
||||
<p class="text-xs-center">
|
||||
<v-btn role="button" color="blue" dark @click="initializePositionWatching">Retry</v-btn>
|
||||
</p>
|
||||
<p>or</p>
|
||||
<p>
|
||||
<AddressInput label="pick a location manually" :onInput="onManualLocationPicker" v-model="manualLocation"></AddressInput>
|
||||
</p>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p class="text-xs-center">{{ $t('geolocation.fetching') }}</p>
|
||||
@ -39,6 +43,7 @@
|
||||
<script>
|
||||
import NoSleep from 'nosleep.js';
|
||||
|
||||
import AddressInput from '@/components/AddressInput.vue';
|
||||
import Map from '@/components/Map.vue';
|
||||
import ReportCard from '@/components/ReportCard.vue';
|
||||
import ReportDialog from '@/components/ReportDialog/index.vue';
|
||||
@ -47,6 +52,7 @@ import { distance, mockLocation } from '@/tools';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
AddressInput,
|
||||
Map,
|
||||
ReportCard,
|
||||
ReportDialog,
|
||||
@ -85,6 +91,7 @@ export default {
|
||||
error: null,
|
||||
heading: null,
|
||||
latLng: null,
|
||||
manualLocation: null,
|
||||
noSleep: null,
|
||||
positionHistory: [],
|
||||
reportLat: null,
|
||||
@ -181,6 +188,9 @@ export default {
|
||||
this.dialog = false;
|
||||
}
|
||||
},
|
||||
onManualLocationPicker(value) {
|
||||
this.latLng = [value.latlng.lat, value.latlng.lng];
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.setNoSleep();
|
||||
|
@ -29,7 +29,7 @@
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
|
||||
<v-btn :disabled="!hasGeolocationPermission" role="button" round color="green" dark @click="step += 1">{{ $t('intro.next') }}</v-btn>
|
||||
<v-btn role="button" round color="green" dark @click="step += 1">{{ $t('intro.next') }}</v-btn>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<v-layout row wrap class="text-xs-center blue lighten-2" v-if="step == 3">
|
||||
|
Loading…
Reference in New Issue
Block a user