diff --git a/js/src/components/Event/FullAddressAutoComplete.vue b/js/src/components/Event/FullAddressAutoComplete.vue
index a803c8ada..d0b95b19a 100644
--- a/js/src/components/Event/FullAddressAutoComplete.vue
+++ b/js/src/components/Event/FullAddressAutoComplete.vue
@@ -10,32 +10,24 @@
>
{{ actualLabel }}
- {{ t("Getting location") }}
-
+
+
+
+ {{ t("Details") }}
+
+
+
+
+
import("@/components/LeafletMap.vue")
);
@@ -139,29 +209,38 @@ const props = withDefaults(
hideSelected?: boolean;
placeholder?: string;
resultType?: AddressSearchType;
+ defaultCoords?: string;
}>(),
{
+ defaultCoords: "0;0",
labelClass: "",
- defaultText: "",
disabled: false,
hideMap: false,
hideSelected: false,
}
);
-// const addressModalActive = ref(false);
-
-const componentId = 0;
+const componentId = ref(0);
const emit = defineEmits(["update:modelValue"]);
const gettingLocationError = ref(null);
const gettingLocation = ref(false);
-const mapDefaultZoom = ref(15);
+const mapDefaultZoom = computed(() => {
+ if (selected.description) {
+ return 15;
+ }
+ return 5;
+});
const addressData = ref([]);
-const selected = ref(null);
+const defaultAddress = new Address();
+defaultAddress.geom = undefined;
+defaultAddress.id = undefined;
+const selected = reactive(defaultAddress);
+
+const detailsAddress = ref(false);
const isFetching = ref(false);
@@ -171,40 +250,45 @@ const placeholderWithDefault = computed(
() => props.placeholder ?? t("e.g. 10 Rue Jangot")
);
-// created(): void {
-// componentId += 1;
-// }
+onBeforeMount(() => {
+ componentId.value += 1;
+});
const id = computed((): string => {
- return `full-address-autocomplete-${componentId}`;
+ return `full-address-autocomplete-${componentId.value}`;
});
const modelValue = computed(() => props.modelValue);
watch(modelValue, () => {
- if (!modelValue.value) return;
- selected.value = modelValue.value;
+ console.debug("modelValue changed");
+ setSelected(modelValue.value);
});
-const updateSelected = (option: IAddress): void => {
- if (option == null) return;
- selected.value = option;
- emit("update:modelValue", selected.value);
+onMounted(() => {
+ setSelected(modelValue.value);
+});
+
+const setSelected = (newValue: IAddress | null) => {
+ if (!newValue) return;
+ console.debug("setting selected to model value");
+ Object.assign(selected, newValue);
};
-// const resetPopup = (): void => {
-// selected.value = new Address();
-// };
-
-// const openNewAddressModal = (): void => {
-// resetPopup();
-// addressModalActive.value = true;
-// };
+const saveManualAddress = (): void => {
+ console.debug("saving address");
+ selected.id = undefined;
+ selected.originId = undefined;
+ selected.url = undefined;
+ emit("update:modelValue", selected);
+ detailsAddress.value = false;
+};
const checkCurrentPosition = (e: LatLng): boolean => {
- if (!selected.value?.geom) return false;
- const lat = parseFloat(selected.value?.geom.split(";")[1]);
- const lon = parseFloat(selected.value?.geom.split(";")[0]);
+ console.debug("checkCurrentPosition");
+ if (!selected?.geom || !e) return false;
+ const lat = parseFloat(selected?.geom.split(";")[1]);
+ const lon = parseFloat(selected?.geom.split(";")[0]);
return e.lat === lat && e.lng === lon;
};
@@ -238,12 +322,11 @@ onAddressSearchResult((result) => {
isFetching.value = false;
});
-const searchQuery = ref("");
-
const asyncData = async (query: string): Promise => {
+ console.debug("Finding addresses");
if (!query.length) {
addressData.value = [];
- selected.value = new Address();
+ Object.assign(selected, defaultAddress);
return;
}
@@ -254,33 +337,39 @@ const asyncData = async (query: string): Promise => {
isFetching.value = true;
- searchQuery.value = query;
-
searchAddress(undefined, {
- query: searchQuery.value,
+ query,
locale: locale,
type: props.resultType,
});
};
-const queryText = computed({
+const selectedAddressText = computed(() => {
+ if (!selected) return undefined;
+ return addressFullName(selected);
+});
+
+const queryText = ref();
+
+const queryTextWithDefault = computed({
get() {
+ console.log("queryTextWithDefault 1", queryText.value);
+ console.log("queryTextWithDefault 2", selectedAddressText.value);
+ console.log("queryTextWithDefault 3", props.defaultText);
return (
- (selected.value ? addressFullName(selected.value) : props.defaultText) ??
- ""
+ queryText.value ?? selectedAddressText.value ?? props.defaultText ?? ""
);
},
- set(text) {
- if (text === "" && selected.value?.id) {
- console.debug("doing reset");
- resetAddress();
- }
+ set(newValue: string) {
+ queryText.value = newValue;
},
});
const resetAddress = (): void => {
+ console.debug("resetting address");
emit("update:modelValue", null);
- selected.value = new Address();
+ resetAddressAction(selected);
+ queryTextWithDefault.value = "";
};
const locateMe = async (): Promise => {
@@ -288,7 +377,7 @@ const locateMe = async (): Promise => {
gettingLocationError.value = null;
try {
const location = await getLocation();
- mapDefaultZoom.value = 12;
+ // mapDefaultZoom.value = 12;
reverseGeoCode(
new LatLng(location.coords.latitude, location.coords.longitude),
12
@@ -308,15 +397,26 @@ onReverseGeocodeResult((result) => {
addressData.value = data.reverseGeocode;
if (addressData.value.length > 0) {
- const defaultAddress = addressData.value[0];
- selected.value = defaultAddress;
- emit("update:modelValue", selected.value);
+ const foundAddress = addressData.value[0];
+ Object.assign(selected, foundAddress);
+ console.debug("reverse geocode succeded, setting new address");
+ queryTextWithDefault.value = addressFullName(foundAddress);
+ emit("update:modelValue", selected);
}
});
const reverseGeoCode = (e: LatLng, zoom: number) => {
+ console.debug("reverse geocode");
+
+ // If the details is opened, just update coords, don't reverse geocode
+ if (e && detailsAddress.value) {
+ selected.geom = `${e.lng};${e.lat}`;
+ console.debug("no reverse geocode, just setting new coords");
+ return;
+ }
+
// If the position has been updated through autocomplete selection, no need to geocode it!
- if (checkCurrentPosition(e)) return;
+ if (!e || checkCurrentPosition(e)) return;
loadReverseGeocode(undefined, {
latitude: e.lat,
@@ -358,6 +458,17 @@ const getLocation = async (): Promise => {
});
};
+const mapMarkerValue = computed(() => {
+ if (!selected.description) return undefined;
+ return {
+ text: [
+ addressToPoiInfos(selected).name,
+ addressToPoiInfos(selected).alternativeName,
+ ],
+ icon: addressToPoiInfos(selected).poiIcon.icon,
+ };
+});
+
const fieldErrors = computed(() => {
return gettingLocationError.value;
});
diff --git a/js/src/components/LeafletMap.vue b/js/src/components/LeafletMap.vue
index 8aa613dda..286ab43e0 100644
--- a/js/src/components/LeafletMap.vue
+++ b/js/src/components/LeafletMap.vue
@@ -21,10 +21,15 @@
-
+
@@ -63,6 +68,7 @@ import { useI18n } from "vue-i18n";
import Locatecontrol from "leaflet.locatecontrol";
import CrosshairsGps from "vue-material-design-icons/CrosshairsGps.vue";
import MapMarker from "vue-material-design-icons/MapMarker.vue";
+import { useDebounceFn } from "@vueuse/core";
const props = withDefaults(
defineProps<{
@@ -159,22 +165,25 @@ const mergedOptions = computed((): Record => {
});
const lat = computed((): number => {
- return Number.parseFloat(props.coords?.split(";")[1]);
+ return Number.parseFloat(props.coords?.split(";")[1] || "0");
});
const lon = computed((): number => {
- return Number.parseFloat(props.coords.split(";")[0]);
+ return Number.parseFloat(props.coords?.split(";")[0] || "0");
});
-const popupMultiLine = computed((): Array => {
+const popupMultiLine = computed((): Array | undefined => {
if (Array.isArray(props.marker?.text)) {
return props.marker?.text as string[];
}
- return [props.marker?.text];
+ if (props.marker?.text) {
+ return [props.marker?.text];
+ }
+ return undefined;
});
const clickMap = (event: LeafletMouseEvent): void => {
- updateDraggableMarkerPosition(event.latlng);
+ updateDraggableMarkerPositionDebounced(event.latlng);
};
const updateDraggableMarkerPosition = (e: LatLng): void => {
@@ -183,6 +192,10 @@ const updateDraggableMarkerPosition = (e: LatLng): void => {
}
};
+const updateDraggableMarkerPositionDebounced = useDebounceFn((e: LatLng) => {
+ updateDraggableMarkerPosition(e);
+}, 1000);
+
const updateZoom = (newZoom: number): void => {
zoom.value = newZoom;
};
@@ -211,4 +224,9 @@ div.map-container {
diff --git a/js/src/graphql/group.ts b/js/src/graphql/group.ts
index ea188955b..c68278b52 100644
--- a/js/src/graphql/group.ts
+++ b/js/src/graphql/group.ts
@@ -54,6 +54,50 @@ export const LIST_GROUPS = gql`
${ACTOR_FRAGMENT}
`;
+export const GROUP_VERY_BASIC_FIELDS_FRAGMENTS = gql`
+ fragment GroupVeryBasicFields on Group {
+ ...ActorFragment
+ suspended
+ visibility
+ openness
+ manuallyApprovesFollowers
+ physicalAddress {
+ description
+ street
+ locality
+ postalCode
+ region
+ country
+ geom
+ type
+ id
+ originId
+ url
+ }
+ avatar {
+ id
+ url
+ name
+ metadata {
+ width
+ height
+ blurhash
+ }
+ }
+ banner {
+ id
+ url
+ name
+ metadata {
+ width
+ height
+ blurhash
+ }
+ }
+ }
+ ${ACTOR_FRAGMENT}
+`;
+
export const GROUP_BASIC_FIELDS_FRAGMENTS = gql`
fragment GroupBasicFields on Group {
...ActorFragment
@@ -296,17 +340,10 @@ export const UPDATE_GROUP = gql`
physicalAddress: $physicalAddress
manuallyApprovesFollowers: $manuallyApprovesFollowers
) {
- ...ActorFragment
- visibility
- openness
- manuallyApprovesFollowers
- banner {
- id
- url
- }
+ ...GroupVeryBasicFields
}
}
- ${ACTOR_FRAGMENT}
+ ${GROUP_VERY_BASIC_FIELDS_FRAGMENTS}
`;
export const DELETE_GROUP = gql`
diff --git a/js/src/types/address.model.ts b/js/src/types/address.model.ts
index 4de385f12..580d7fda8 100644
--- a/js/src/types/address.model.ts
+++ b/js/src/types/address.model.ts
@@ -93,7 +93,10 @@ export function addressToPoiInfos(address: IAddress): IPoiInfo {
switch (addressType) {
case "house":
name = address.description;
- alternativeName = [address.postalCode, address.locality, address.country]
+ alternativeName = (
+ address.description !== address.street ? [address.street] : []
+ )
+ .concat([address.postalCode, address.locality, address.country])
.filter((zone) => zone)
.join(", ");
poiIcon = poiIcons.defaultAddress;
@@ -123,8 +126,11 @@ export function addressToPoiInfos(address: IAddress): IPoiInfo {
alternativeName = "";
if (address.street && address.street.trim()) {
alternativeName = `${address.street}`;
+ if (address.postalCode) {
+ alternativeName += `, ${address.postalCode}`;
+ }
if (address.locality) {
- alternativeName += ` (${address.locality})`;
+ alternativeName += `, ${address.locality}`;
}
} else if (address.locality && address.locality.trim()) {
alternativeName = `${address.locality}, ${address.region}, ${address.country}`;
@@ -158,3 +164,19 @@ export function addressFullName(address: IAddress): string {
}
return "";
}
+
+export function resetAddress(address: IAddress): void {
+ address.id = undefined;
+ address.description = "";
+ address.street = "";
+ address.locality = "";
+ address.postalCode = "";
+ address.region = "";
+ address.country = "";
+ address.type = "";
+ address.geom = undefined;
+ address.url = undefined;
+ address.originId = undefined;
+ address.timezone = undefined;
+ address.pictureInfo = undefined;
+}
diff --git a/js/src/views/Event/EditView.vue b/js/src/views/Event/EditView.vue
index cbe8791ee..7703d5c8f 100644
--- a/js/src/views/Event/EditView.vue
+++ b/js/src/views/Event/EditView.vue
@@ -612,59 +612,6 @@ const FullAddressAutoComplete = defineAsyncComponent(
() => import("@/components/Event/FullAddressAutoComplete.vue")
);
-// apollo: {
-// config: CONFIG_EDIT_EVENT,
-// event: {
-// query: FETCH_EVENT,
-// variables() {
-// return {
-// uuid: this.eventId,
-// };
-// },
-// update(data) {
-// let event = data.event;
-// if (this.isDuplicate) {
-// event = { ...event, organizerActor: this.currentActor };
-// }
-// return new EventModel(event);
-// },
-// skip() {
-// return !this.eventId;
-// },
-// },
-// person: {
-// query: PERSON_STATUS_GROUP,
-// fetchPolicy: "cache-and-network",
-// variables() {
-// return {
-// id: this.currentActor.id,
-// group: usernameWithDomain(this.event?.attributedTo),
-// };
-// },
-// skip() {
-// return (
-// !this.event?.attributedTo ||
-// !this.event?.attributedTo?.preferredUsername
-// );
-// },
-// },
-// group: {
-// query: FETCH_GROUP_PUBLIC,
-// fetchPolicy: "cache-and-network",
-// variables() {
-// return {
-// name: this.event?.attributedTo?.preferredUsername,
-// };
-// },
-// skip() {
-// return (
-// !this.event?.attributedTo ||
-// !this.event?.attributedTo?.preferredUsername
-// );
-// },
-// },
-// },
-
const { t } = useI18n({ useScope: "global" });
useHead({
@@ -689,7 +636,6 @@ const unmodifiedEvent = ref(new EventModel());
const pictureFile = ref(null);
-// const canPromote = ref(true);
const limitedPlaces = ref(false);
const showFixedNavbar = ref(true);
@@ -1051,6 +997,7 @@ const buildVariables = async () => {
res.picture = { mediaId: event.value?.picture.id };
}
}
+ console.debug("builded variables", res);
} catch (e) {
console.error(e);
}
diff --git a/js/src/views/Group/GroupSettings.vue b/js/src/views/Group/GroupSettings.vue
index 20fd776e4..7d7a57025 100644
--- a/js/src/views/Group/GroupSettings.vue
+++ b/js/src/views/Group/GroupSettings.vue
@@ -369,7 +369,10 @@ const currentAddress = computed({
},
set(address: IAddress) {
if (editableGroup.value) {
- editableGroup.value.physicalAddress = address;
+ editableGroup.value = {
+ ...editableGroup.value,
+ physicalAddress: address,
+ };
}
},
});