From f2d7da7af7bc39b4e9f1075ddd13a1c191c55527 Mon Sep 17 00:00:00 2001 From: Laurent GAY Date: Wed, 6 Nov 2024 12:58:02 +0100 Subject: [PATCH] #1492: add distance value in selector + add with filter in search page --- src/components/Home/SearchFields.vue | 129 ++++++++--------------- src/i18n/en_US.json | 1 + src/i18n/fr_FR.json | 1 + src/utils/location.ts | 72 ++++++------- src/views/HomeView.vue | 78 +++++++++++--- src/views/SearchView.vue | 149 +++++---------------------- 6 files changed, 162 insertions(+), 268 deletions(-) diff --git a/src/components/Home/SearchFields.vue b/src/components/Home/SearchFields.vue index 58551fd9e..ea3b24eeb 100644 --- a/src/components/Home/SearchFields.vue +++ b/src/components/Home/SearchFields.vue @@ -21,20 +21,17 @@ /> (); -const location = computed({ +const address = computed({ get(): IAddress | null { - if (props.location) { - return props.location; + console.debug("-- get address --", props); + if (props.address) { + return props.address; } if (props.fromLocalStorage) { - return getLocationFromLocal(); + return getAddressFromLocal(); } return null; }, - set(newLocation: IAddress | null) { - emit("update:location", newLocation); + set(newAddress: IAddress | null) { + emit("update:address", newAddress); if (props.fromLocalStorage) { - storeLocationInLocal(newLocation); + storeAddressInLocal(newAddress); } }, }); @@ -122,75 +120,31 @@ const distance = computed({ }, }); -const distanceList = computed(() => { - return [ - { - distance: 5, - label: t( - "{number} kilometers", - { - number: 5, - }, - 5 - ), - }, - { - distance: 10, - label: t( - "{number} kilometers", - { - number: 10, - }, - 10 - ), - }, - { - distance: 25, - label: t( - "{number} kilometers", - { - number: 25, - }, - 25 - ), - }, - { - distance: 50, - label: t( - "{number} kilometers", - { - number: 50, - }, - 50 - ), - }, - { - distance: 100, - label: t( - "{number} kilometers", - { - number: 100, - }, - 100 - ), - }, - { - distance: 150, - label: t( - "{number} kilometers", - { - number: 150, - }, - 150 - ), - }, - ]; +const distanceText = computed(() => { + return distance.value + " km"; }); -console.debug("initial", distance.value, search.value, location.value); +const distanceList = computed(() => { + const distances = []; + [5, 10, 25, 50, 100, 150].forEach((value) => { + distances.push({ + distance: value, + label: t( + "{number} kilometers", + { + number: value, + }, + value + ), + }); + }); + return distances; +}); -const modelValueUpdate = (newlocation: IAddress | null) => { - emit("update:location", newlocation); +console.debug("initial", distance.value, search.value, address.value); + +const modelValueUpdate = (newaddress: IAddress | null) => { + emit("update:address", newaddress); }; const submit = () => { @@ -205,10 +159,9 @@ const submit = () => { if (search.value != "") { search_query.search = search.value; } - if (location.value) { - const { lat, lon } = addressToLocation(location.value); - search_query.locationName = - location.value.locality ?? location.value.region; + if (address.value) { + const { lat, lon } = addressToLocation(address.value); + search_query.locationName = address.value.locality ?? address.value.region; search_query.lat = lat; search_query.lon = lon; if (distance.value != null) { diff --git a/src/i18n/en_US.json b/src/i18n/en_US.json index 3b688f59b..452369e91 100644 --- a/src/i18n/en_US.json +++ b/src/i18n/en_US.json @@ -1360,6 +1360,7 @@ "Keyword, event title, group name, etc.": "Keyword, event title, group name, etc.", "Go!": "Go!", "Explore!": "Explore!", + "Select distance": "Select distance", "Join {instance}, a Mobilizon instance": "Join {instance}, a Mobilizon instance", "Open user menu": "Open user menu", "Open main menu": "Open main menu", diff --git a/src/i18n/fr_FR.json b/src/i18n/fr_FR.json index b6edb8399..0fb9ca01a 100644 --- a/src/i18n/fr_FR.json +++ b/src/i18n/fr_FR.json @@ -1028,6 +1028,7 @@ "Select a radius": "Sélectionnez un rayon", "Select a timezone": "Selectionnez un fuseau horaire", "Select all resources": "Sélectionner toutes les ressources", + "Select distance": "Sélectionner la distance", "Select languages": "Choisissez une langue", "Select the activities for which you wish to receive an email or a push notification.": "Sélectionnez les activités pour lesquelles vous souhaitez recevoir un email ou une notification push.", "Select this resource": "Sélectionner cette ressource", diff --git a/src/utils/location.ts b/src/utils/location.ts index 6dc17cf8b..b87707172 100644 --- a/src/utils/location.ts +++ b/src/utils/location.ts @@ -9,9 +9,19 @@ const GEOHASH_DEPTH = 9; // put enough accuracy, radius will be used anyway export const addressToLocation = ( address: IAddress ): LocationType | undefined => { - if (!address.geom) return undefined; + if (!address.geom) + return { + lon: undefined, + lat: undefined, + name: undefined, + }; const arr = address.geom.split(";"); - if (arr.length < 2) return undefined; + if (arr.length < 2) + return { + lon: undefined, + lat: undefined, + name: undefined, + }; return { lon: parseFloat(arr[0]), lat: parseFloat(arr[1]), @@ -19,6 +29,17 @@ export const addressToLocation = ( }; }; +export const locationToAddress = (location: LocationType): IAddress | null => { + if (location.lon && location.lat) { + const new_add = new Address(); + new_add.geom = location.lon.toString() + ";" + location.lat.toString(); + new_add.description = location.name || ""; + console.debug("locationToAddress", location, new_add); + return new_add; + } + return null; +}; + export const coordsToGeoHash = ( lat: number | undefined, lon: number | undefined, @@ -38,44 +59,24 @@ export const geoHashToCoords = ( return latitude && longitude ? { latitude, longitude } : undefined; }; -export const storeLocationInLocal = (location: IAddress | null): undefined => { - if (location) { - window.localStorage.setItem("location", JSON.stringify(location)); +export const storeAddressInLocal = (address: IAddress | null): undefined => { + if (address) { + window.localStorage.setItem("address", JSON.stringify(address)); } else { - window.localStorage.removeItem("location"); + window.localStorage.removeItem("address"); } }; -export const getLocationFromLocal = (): IAddress | null => { - const locationString = window.localStorage.getItem("location"); - if (!locationString) { +export const getAddressFromLocal = (): IAddress | null => { + const addressString = window.localStorage.getItem("address"); + if (!addressString) { return null; } - const location = JSON.parse(locationString) as IAddress; - if (!location.description || !location.geom) { + const address = JSON.parse(addressString) as IAddress; + if (!address.description || !address.geom) { return null; } - return location; -}; - -export const storeRadiusInLocal = (radius: number | null): undefined => { - if (radius) { - window.localStorage.setItem("radius", radius.toString()); - } else { - window.localStorage.removeItem("radius"); - } -}; - -export const getRadiusFromLocal = (): IAddress | null => { - const locationString = window.localStorage.getItem("location"); - if (!locationString) { - return null; - } - const location = JSON.parse(locationString) as IAddress; - if (!location.description || !location.geom) { - return null; - } - return location; + return address; }; export const storeUserLocationAndRadiusFromUserSettings = ( @@ -84,18 +85,13 @@ export const storeUserLocationAndRadiusFromUserSettings = ( if (location) { const latlon = geoHashToCoords(location.geohash); if (latlon) { - storeLocationInLocal({ + storeAddressInLocal({ ...new Address(), geom: `${latlon.longitude};${latlon.latitude}`, description: location.name || "", type: "administrative", }); } - if (location.range) { - storeRadiusInLocal(location.range); - } else { - console.debug("user has not set a radius"); - } } else { console.debug("user has not set a location"); } diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 74d46735b..2ce33e3dc 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -28,11 +28,12 @@ @@ -185,7 +186,13 @@ import CategoriesPreview from "@/components/Home/CategoriesPreview.vue"; import UnloggedIntroduction from "@/components/Home/UnloggedIntroduction.vue"; import SearchFields from "@/components/Home/SearchFields.vue"; import { useHead } from "@unhead/vue"; -import { addressToLocation, geoHashToCoords } from "@/utils/location"; +import { + addressToLocation, + geoHashToCoords, + getAddressFromLocal, + locationToAddress, + storeAddressInLocal, +} from "@/utils/location"; import { useServerProvidedLocation } from "@/composition/apollo/config"; import { ABOUT } from "@/graphql/config"; import { IConfig } from "@/types/config.model"; @@ -238,13 +245,14 @@ const currentUserParticipations = computed( () => loggedUser.value?.participations.elements ); -const location = ref(null); +const increated = ref(0); +const address = ref(null); const search = ref(""); -const noLocation = ref(false); +const noAddress = ref(false); const current_distance = ref(null); -watch(location, (newLoc, oldLoc) => - console.debug("LOCATION UPDATED from", { ...oldLoc }, " to ", { ...newLoc }) +watch(address, (newAdd, oldAdd) => + console.debug("ADDRESS UPDATED from", { ...oldAdd }, " to ", { ...newAdd }) ); const isToday = (date: string): boolean => { @@ -401,13 +409,13 @@ const { result: reverseGeocodeResult } = useQuery<{ })); const userSettingsLocation = computed(() => { - const address = reverseGeocodeResult.value?.reverseGeocode[0]; - const placeName = address?.locality ?? address?.region ?? address?.country; + const location = reverseGeocodeResult.value?.reverseGeocode[0]; + const placeName = location?.locality ?? location?.region ?? location?.country; return { lat: coords.value?.latitude, lon: coords.value?.longitude, name: placeName, - picture: address?.pictureInfo, + picture: location?.pictureInfo, isIPLocation: coords.value?.isIPLocation, }; }); @@ -433,16 +441,20 @@ const currentUserLocation = computed(() => { const userLocation = computed(() => { console.debug("new userLocation"); - if (noLocation.value) { + if (noAddress.value) { return { lon: null, lat: null, name: null, }; } - if (location.value) { + if (address.value) { console.debug("userLocation is typed location"); - return addressToLocation(location.value); + return addressToLocation(address.value); + } + const local_address = getAddressFromLocal(); + if (local_address) { + return addressToLocation(local_address); } if ( !userSettingsLocation.value || @@ -454,9 +466,36 @@ const userLocation = computed(() => { return userSettingsLocation.value; }); +const userAddress = computed({ + get(): IAddress | null { + if (noAddress.value) { + return null; + } + if (address.value) { + return address.value; + } + const local_address = getAddressFromLocal(); + if (local_address) { + return local_address; + } + if ( + !userSettingsLocation.value || + (userSettingsLocation.value?.isIPLocation && + currentUserLocation.value?.name) + ) { + return locationToAddress(currentUserLocation.value); + } + return locationToAddress(userSettingsLocation.value); + }, + set(newAddress: IAddress | null) { + address.value = newAddress; + noAddress.value = newAddress == null; + }, +}); + const distance = computed({ get(): number | null { - if (noLocation.value || !userLocation.value?.name) { + if (noAddress.value || !userLocation.value?.name) { return null; } else if (current_distance.value == null) { return userLocation.value?.isIPLocation ? 150 : 25; @@ -528,8 +567,13 @@ const performGeoLocation = () => { ); }; -const updateLocation = (newlocation: IAddress | null) => { - noLocation.value = newlocation == null; +const updateAddress = (newAddress: IAddress | null) => { + if (address.value?.geom != newAddress?.geom || newAddress == null) { + increated.value += 1; + storeAddressInLocal(newAddress); + } + address.value = newAddress; + noAddress.value = newAddress == null; }; /** diff --git a/src/views/SearchView.vue b/src/views/SearchView.vue index 37d242361..5907ba402 100644 --- a/src/views/SearchView.vue +++ b/src/views/SearchView.vue @@ -3,8 +3,9 @@ @@ -155,43 +156,6 @@ - - - - - (null); +const addressName = useRouteQuery("locationName", null); +const address = ref(null); -watch(location, (newLocation) => { - console.debug("location change", newLocation); - if (newLocation?.geom) { - latitude.value = parseFloat(newLocation?.geom.split(";")[1]); - longitude.value = parseFloat(newLocation?.geom.split(";")[0]); - locationName.value = newLocation?.description; - console.debug("set location", [ +watch(address, (newAddress: IAddress) => { + console.debug("address change", newAddress); + if (newAddress?.geom) { + latitude.value = parseFloat(newAddress?.geom.split(";")[1]); + longitude.value = parseFloat(newAddress?.geom.split(";")[0]); + addressName.value = newAddress?.description; + console.debug("set address", [ latitude.value, longitude.value, - locationName.value, + addressName.value, ]); } else { - console.debug("location emptied"); + console.debug("address emptied"); latitude.value = undefined; longitude.value = undefined; - locationName.value = null; + addressName.value = null; } }); @@ -759,9 +723,6 @@ const groupPage = useRouteQuery("groupPage", 1, integerTransformer); const latitude = useRouteQuery("lat", undefined, floatTransformer); const longitude = useRouteQuery("lon", undefined, floatTransformer); -// TODO -// This should be updated with getRadiusFromLocal if we want to use user's -// preferences const distance = useRouteQuery("distance", "10_km"); const when = useRouteQuery("when", "any"); const contentType = useRouteQuery( @@ -946,75 +907,6 @@ const contentTypeMapping = computed(() => { } }); -const eventDistance = computed(() => { - return [ - { - id: "anywhere", - label: t("Any distance"), - }, - { - id: "5_km", - label: t( - "{number} kilometers", - { - number: 5, - }, - 5 - ), - }, - { - id: "10_km", - label: t( - "{number} kilometers", - { - number: 10, - }, - 10 - ), - }, - { - id: "25_km", - label: t( - "{number} kilometers", - { - number: 25, - }, - 25 - ), - }, - { - id: "50_km", - label: t( - "{number} kilometers", - { - number: 50, - }, - 50 - ), - }, - { - id: "100_km", - label: t( - "{number} kilometers", - { - number: 100, - }, - 100 - ), - }, - { - id: "150_km", - label: t( - "{number} kilometers", - { - number: 150, - }, - 150 - ), - }, - ]; -}); - const eventStatuses = computed(() => { return [ { @@ -1049,7 +941,14 @@ const geoHashLocation = computed(() => coordsToGeoHash(latitude.value, longitude.value) ); -const radius = computed(() => Number.parseInt(distance.value.slice(0, -3))); +const radius = computed({ + get(): number | null { + return Number.parseInt(distance.value.slice(0, -3)); + }, + set(newRadius: number) { + distance.value = newRadius.toString() + "_km"; + }, +}); const longEvents = computed(() => { if (contentType.value === ContentType.EVENTS) {