diff --git a/docs/changelog.md b/docs/changelog.md index a1ff3c93..7e387996 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,12 @@ ## đź”– 0.3.0 (2025-09-04) - Mise Ă  jour de donnĂ©es et ajout calque vulnĂ©rabilitĂ© Ă  la chaleur +### ✨ feat: PossibilitĂ© d'ouvrir la carte sur un calque spĂ©cifique + +Le nom du calque est dĂ©sormais codĂ© dans l'url, ce qui permet de partager une vue spĂ©cifique de la carte, voilĂ  par ex. l'url centrĂ©e sur Lyon centre avec les donnĂ©es de vulnĂ©rabilitĂ© Ă  la chaleur : [carte.iarbre.fr/vulnerability/16/45.75773/4.85377](https://carte.iarbre.fr/vulnerability/16/45.75773/4.85377) + +→ Ticket [#183](https://github.com/TelesCoop/iarbre/issues/183) + ### 🛠️ enhance: DonnĂ©es d'occupation des sols - Ajout de nouvelles donnĂ©es : place PMR et d'autopartage. diff --git a/front/cypress/e2e/mapInteractions.cy.ts b/front/cypress/e2e/mapInteractions.cy.ts index 1fb48f38..5aa6d99e 100644 --- a/front/cypress/e2e/mapInteractions.cy.ts +++ b/front/cypress/e2e/mapInteractions.cy.ts @@ -4,7 +4,7 @@ import { DataType, DataTypeToLabel } from "../../src/utils/enum" describe("Map interactions", () => { beforeEach(() => { - cy.visit("/13/45.07126/5.5543") + cy.visit("/plantability/13/45.07126/5.5543") cy.get("@consoleInfo").should("have.been.calledWith", "cypress: map data loaded") }) @@ -21,6 +21,7 @@ describe("Map interactions", () => { cy.getBySel("plantability-score-label").should("exist") cy.mapSwitchLayer(DataType.LOCAL_CLIMATE_ZONES) // cf. issue #142 + cy.url().should("include", "/lcz/") cy.getBySel("map-legend-title").should("contain", DataTypeToLabel[DataType.LOCAL_CLIMATE_ZONES]) cy.mapHasNoPopup() cy.wait(200) // eslint-disable-line cypress/no-unnecessary-waiting @@ -30,7 +31,11 @@ describe("Map interactions", () => { cy.mapOpenPopup() // cf. issue #92 cy.mapSwitchLayer(DataType.VULNERABILITY) + cy.url().should("include", "/vulnerability/") cy.getBySel("map-legend-title").should("contain", DataTypeToLabel[DataType.VULNERABILITY]) cy.mapHasNoPopup() + + cy.visit("/lcz/13/45.07126/5.5543") + cy.getBySel("map-legend-title").should("contain", DataTypeToLabel[DataType.LOCAL_CLIMATE_ZONES]) }) }) diff --git a/front/src/components/map/MapComponent.vue b/front/src/components/map/MapComponent.vue index b4c8902c..1792333f 100644 --- a/front/src/components/map/MapComponent.vue +++ b/front/src/components/map/MapComponent.vue @@ -5,7 +5,8 @@ import { useRouter, useRoute } from "vue-router" import MapLegend from "@/components/map/legend/MapLegend.vue" import MapScorePopup from "@/components/map/popup/MapScorePopup.vue" import MapLayerSwitcher from "@/components/map/layerSwitcher/MapLayerSwitcher.vue" -import { Map } from "maplibre-gl" +import { updateMapRoute } from "@/utils/route" +import { DataType } from "@/utils/enum" const router = useRouter() const route = useRoute() @@ -17,18 +18,6 @@ const props = defineProps({ } }) -const updateRouteCoords = (map: Map) => { - const coords = map.getCenter() - router.replace({ - name: "mapWithCoords", - params: { - zoom: Math.round(map.getZoom()), - lng: Math.round(100000 * coords.lng) / 100000, - lat: Math.round(100000 * coords.lat) / 100000 - } - }) -} - const mapStore = useMapStore() onMounted(() => { @@ -36,16 +25,21 @@ onMounted(() => { if (route) { const mapInstance = mapStore.getMapInstance(props.mapId) - if (route.name === "mapWithCoords") { + if (route.name === "mapWithUrlParams") { const p = route.params mapInstance.jumpTo({ center: [parseFloat(p.lng as string), parseFloat(p.lat as string)], zoom: parseFloat(p.zoom as string) }) + mapInstance.on("load", () => { + mapStore.changeDataType(p.dataType as DataType) + }) } - mapInstance.on("moveend", () => updateRouteCoords(mapInstance)) - updateRouteCoords(mapInstance) + mapInstance.on("moveend", () => { + updateMapRoute(router, { map: mapInstance }) + }) + updateMapRoute(router, { map: mapInstance }) } }) diff --git a/front/src/components/map/layerSwitcher/LayerSwitcher.vue b/front/src/components/map/layerSwitcher/LayerSwitcher.vue index 6f9c8fcf..31e09180 100644 --- a/front/src/components/map/layerSwitcher/LayerSwitcher.vue +++ b/front/src/components/map/layerSwitcher/LayerSwitcher.vue @@ -2,14 +2,17 @@ import { useMapStore } from "@/stores/map" import { DataType, DataTypeToLabel } from "@/utils/enum" import { computed } from "vue" +import { updateMapRoute } from "@/utils/route" +import { useRouter } from "vue-router" const mapStore = useMapStore() +const router = useRouter() const selectedDataType = computed({ get: () => mapStore.selectedDataType, set: (value: DataType) => { - console.log("changeLayer 0.0") mapStore.changeDataType(value) + updateMapRoute(router, { dataType: mapStore.selectedDataType }) } }) diff --git a/front/src/router/index.ts b/front/src/router/index.ts index db4f2a6a..90ed9680 100644 --- a/front/src/router/index.ts +++ b/front/src/router/index.ts @@ -1,5 +1,6 @@ import { createRouter, createWebHistory } from "vue-router" import MapView from "@/views/MapView.vue" +import { DataType } from "@/utils/enum" const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -10,9 +11,24 @@ const router = createRouter({ component: MapView }, { - path: "/:zoom(\\d+)/:lat(\\d+.\\d+)/:lng(\\d+.\\d+)", - name: "mapWithCoords", + path: "/:dataType(plantability|lcz|vulnerability)/:zoom(\\d+)/:lat(\\d+.\\d+)/:lng(\\d+.\\d+)", + name: "mapWithUrlParams", component: MapView + }, + { + path: "/:zoom(\\d+)/:lat(\\d+\\.\\d+)/:lng(\\d+\\.\\d+)", + redirect: (to) => { + const { zoom, lat, lng } = to.params + return { + name: "mapWithUrlParams", + params: { + dataType: DataType.PLANTABILITY, + zoom, + lat, + lng + } + } + } } ] }) diff --git a/front/src/utils/route.ts b/front/src/utils/route.ts new file mode 100644 index 00000000..c088ada0 --- /dev/null +++ b/front/src/utils/route.ts @@ -0,0 +1,38 @@ +import { useRouter } from "vue-router" +import { useMapStore } from "@/stores/map" +import { Map } from "maplibre-gl" +import type { DataType } from "./enum" + +export function updateMapRoute( + router: ReturnType, + options: { + map?: Map + dataType?: DataType + } +) { + const mapStore = useMapStore() + + const route = router.currentRoute.value + + const { zoom, lat, lng } = options.map + ? { + zoom: Math.round(options.map.getZoom()), + lat: Math.round(100000 * options.map.getCenter().lat) / 100000, + lng: Math.round(100000 * options.map.getCenter().lng) / 100000 + } + : { + zoom: route.params.zoom, + lat: route.params.lat, + lng: route.params.lng + } + + router.replace({ + name: "mapWithUrlParams", + params: { + dataType: options.dataType || mapStore.selectedDataType, + zoom, + lat, + lng + } + }) +}