Let user pick a location manually, fix for #3.

This commit is contained in:
Lucas Verney 2018-07-17 22:49:00 +02:00
parent a67462fab0
commit edadbd6393
5 changed files with 128 additions and 4 deletions

View 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>

View File

@ -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',

View File

@ -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',

View File

@ -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();

View File

@ -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">