Merge branch 'explore-locateme' into 'master'
restore locate me button in search form See merge request framasoft/mobilizon!578
This commit is contained in:
commit
4ff4514fd7
|
@ -1,8 +1,10 @@
|
|||
<template>
|
||||
<div class="address-autocomplete">
|
||||
<b-field expanded>
|
||||
<b-autocomplete
|
||||
:data="addressData"
|
||||
v-model="queryText"
|
||||
:placeholder="placeholder || $t('e.g. 10 Rue Jangot')"
|
||||
:placeholder="$t('e.g. 10 Rue Jangot')"
|
||||
field="fullName"
|
||||
:loading="isFetching"
|
||||
@typing="fetchAsyncData"
|
||||
|
@ -16,18 +18,34 @@
|
|||
><br />
|
||||
<small>{{ option.poiInfos.alternativeName }}</small>
|
||||
</template>
|
||||
<template slot="empty">
|
||||
<span v-if="isFetching">{{ $t("Searching…") }}</span>
|
||||
<div v-else-if="queryText.length >= 3" class="is-enabled">
|
||||
<span>{{ $t('No results for "{queryText}"') }}</span>
|
||||
<span>{{
|
||||
$t("You can try another search term or drag and drop the marker on the map", {
|
||||
queryText,
|
||||
})
|
||||
}}</span>
|
||||
</div>
|
||||
</template>
|
||||
</b-autocomplete>
|
||||
</b-field>
|
||||
<b-field v-if="isSecureContext()">
|
||||
<b-button type="is-text" v-if="!gettingLocation" icon-right="target" @click="locateMe">{{
|
||||
$t("Use my location")
|
||||
}}</b-button>
|
||||
<span v-else>{{ $t("Getting location") }}</span>
|
||||
</b-field>
|
||||
<!--
|
||||
<div v-if="selected && selected.geom" class="control">
|
||||
<b-checkbox @input="togglemap" />
|
||||
<label class="label">{{ $t("Show map") }}</label>
|
||||
</div>
|
||||
|
||||
<div class="map" v-if="showmap && selected && selected.geom">
|
||||
<map-leaflet
|
||||
:coords="selected.geom"
|
||||
:marker="{
|
||||
text: [selected.poiInfos.name, selected.poiInfos.alternativeName],
|
||||
icon: selected.poiInfos.poiIcon.icon,
|
||||
}"
|
||||
:updateDraggableMarkerCallback="reverseGeoCode"
|
||||
:options="{ zoom: mapDefaultZoom }"
|
||||
:readOnly="false"
|
||||
/>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
|
||||
|
@ -39,6 +57,9 @@ import { CONFIG } from "../../graphql/config";
|
|||
import { IConfig } from "../../types/config.model";
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
"map-leaflet": () => import(/* webpackChunkName: "map" */ "@/components/Map.vue"),
|
||||
},
|
||||
apollo: {
|
||||
config: CONFIG,
|
||||
},
|
||||
|
@ -46,8 +67,6 @@ import { IConfig } from "../../types/config.model";
|
|||
export default class AddressAutoComplete extends Vue {
|
||||
@Prop({ required: true }) value!: IAddress;
|
||||
|
||||
@Prop({ required: false }) placeholder!: string;
|
||||
|
||||
addressData: IAddress[] = [];
|
||||
|
||||
selected: IAddress = new Address();
|
||||
|
@ -56,19 +75,31 @@ export default class AddressAutoComplete extends Vue {
|
|||
|
||||
queryText: string = (this.value && new Address(this.value).fullName) || "";
|
||||
|
||||
addressModalActive = false;
|
||||
|
||||
showmap = false;
|
||||
|
||||
private gettingLocation = false;
|
||||
|
||||
private location!: Position;
|
||||
|
||||
private gettingLocationError: any;
|
||||
|
||||
private mapDefaultZoom = 15;
|
||||
|
||||
config!: IConfig;
|
||||
|
||||
fetchAsyncData!: Function;
|
||||
|
||||
// We put this in data because of issues like
|
||||
// https://github.com/vuejs/vue-class-component/issues/263
|
||||
data() {
|
||||
data(): Record<string, unknown> {
|
||||
return {
|
||||
fetchAsyncData: debounce(this.asyncData, 200),
|
||||
};
|
||||
}
|
||||
|
||||
async asyncData(query: string) {
|
||||
async asyncData(query: string): Promise<void> {
|
||||
if (!query.length) {
|
||||
this.addressData = [];
|
||||
this.selected = new Address();
|
||||
|
@ -95,7 +126,7 @@ export default class AddressAutoComplete extends Vue {
|
|||
}
|
||||
|
||||
@Watch("config")
|
||||
watchConfig(config: IConfig) {
|
||||
watchConfig(config: IConfig): void {
|
||||
if (!config.geocoding.autocomplete) {
|
||||
// If autocomplete is disabled, we put a larger debounce value
|
||||
// so that we don't request with incomplete address
|
||||
|
@ -104,18 +135,97 @@ export default class AddressAutoComplete extends Vue {
|
|||
}
|
||||
|
||||
@Watch("value")
|
||||
updateEditing() {
|
||||
updateEditing(): void {
|
||||
if (!(this.value && this.value.id)) return;
|
||||
this.selected = this.value;
|
||||
const address = new Address(this.selected);
|
||||
this.queryText = `${address.poiInfos.name} ${address.poiInfos.alternativeName}`;
|
||||
}
|
||||
|
||||
updateSelected(option: IAddress) {
|
||||
updateSelected(option: IAddress): void {
|
||||
if (option == null) return;
|
||||
this.selected = option;
|
||||
this.$emit("input", this.selected);
|
||||
}
|
||||
|
||||
resetPopup(): void {
|
||||
this.selected = new Address();
|
||||
}
|
||||
|
||||
openNewAddressModal(): void {
|
||||
this.resetPopup();
|
||||
this.addressModalActive = true;
|
||||
}
|
||||
|
||||
togglemap(): void {
|
||||
this.showmap = !this.showmap;
|
||||
}
|
||||
|
||||
async reverseGeoCode(e: LatLng, zoom: number): Promise<void> {
|
||||
// If the position has been updated through autocomplete selection, no need to geocode it!
|
||||
if (this.checkCurrentPosition(e)) return;
|
||||
const result = await this.$apollo.query({
|
||||
query: REVERSE_GEOCODE,
|
||||
variables: {
|
||||
latitude: e.lat,
|
||||
longitude: e.lng,
|
||||
zoom,
|
||||
locale: this.$i18n.locale,
|
||||
},
|
||||
});
|
||||
|
||||
this.addressData = result.data.reverseGeocode.map((address: IAddress) => new Address(address));
|
||||
const defaultAddress = new Address(this.addressData[0]);
|
||||
this.selected = defaultAddress;
|
||||
this.$emit("input", this.selected);
|
||||
this.queryText = `${defaultAddress.poiInfos.name} ${defaultAddress.poiInfos.alternativeName}`;
|
||||
}
|
||||
|
||||
checkCurrentPosition(e: LatLng): boolean {
|
||||
if (!this.selected || !this.selected.geom) return false;
|
||||
const lat = parseFloat(this.selected.geom.split(";")[1]);
|
||||
const lon = parseFloat(this.selected.geom.split(";")[0]);
|
||||
|
||||
return e.lat === lat && e.lng === lon;
|
||||
}
|
||||
|
||||
async locateMe(): Promise<void> {
|
||||
this.gettingLocation = true;
|
||||
try {
|
||||
this.location = await AddressAutoComplete.getLocation();
|
||||
this.mapDefaultZoom = 12;
|
||||
this.reverseGeoCode(
|
||||
new LatLng(this.location.coords.latitude, this.location.coords.longitude),
|
||||
12
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.gettingLocationError = e.message;
|
||||
}
|
||||
this.gettingLocation = false;
|
||||
}
|
||||
|
||||
static async getLocation(): Promise<Position> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!("geolocation" in navigator)) {
|
||||
reject(new Error("Geolocation is not available."));
|
||||
}
|
||||
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(pos) => {
|
||||
resolve(pos);
|
||||
},
|
||||
(err) => {
|
||||
reject(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
isSecureContext(): boolean {
|
||||
return window.isSecureContext;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
|
|
@ -376,6 +376,7 @@
|
|||
"Update event {name}": "Update event {name}",
|
||||
"Update my event": "Update my event",
|
||||
"Updated": "Updated",
|
||||
"Use my location": "Use my location",
|
||||
"Username": "Username",
|
||||
"Users": "Users",
|
||||
"View a reply": "|View one reply|View {totalReplies} replies",
|
||||
|
|
|
@ -689,6 +689,7 @@
|
|||
"Update my event": "Mettre à jour mon évènement",
|
||||
"Update post": "Mettre à jour le billet",
|
||||
"Updated": "Mis à jour",
|
||||
"Use my location": "Utiliser ma position",
|
||||
"User": "Utilisateur·ice",
|
||||
"Username": "Pseudo",
|
||||
"Users": "Utilisateur⋅ice⋅s",
|
||||
|
|
Loading…
Reference in a new issue