Skip to content

Commit

Permalink
Merge pull request #283 from AgenceBio/fix/legendes-carte
Browse files Browse the repository at this point in the history
  • Loading branch information
thom4parisot authored Dec 18, 2023
2 parents d21e47d + 96e4d85 commit b498c03
Showing 16 changed files with 147 additions and 63 deletions.
4 changes: 1 addition & 3 deletions src/components/DesignSystem/AccordionGroup.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { afterEach, describe, expect, test, vi } from "vitest"
import { describe, expect, test } from "vitest"
import { defineComponent } from "vue"
import { mount } from "@vue/test-utils"

@@ -7,8 +7,6 @@ import AccordionGroup from "./AccordionGroup.vue"


describe("AccordionGroup", () => {
afterEach(() => vi.clearAllMocks())

test('we trigger an edit form', async () => {
const TestComponent = defineComponent({
components: { AccordionGroup, AccordionSection },
1 change: 0 additions & 1 deletion src/components/Features/FeatureGroup.test.js
Original file line number Diff line number Diff line change
@@ -26,7 +26,6 @@ describe("FeatureGroup", () => {
afterEach(() => {
document.body.outerHTML = ''
permissions.$reset()
vi.clearAllMocks()
})

test('properly renders a group', async () => {
Original file line number Diff line number Diff line change
@@ -51,7 +51,6 @@ describe("SingleItemCertificationBodyForm", () => {

afterEach(() => {
document.body.outerHTML = ''
vi.clearAllMocks()
})

test("we assign a certification state", async () => {
1 change: 0 additions & 1 deletion src/components/Features/Table.test.js
Original file line number Diff line number Diff line change
@@ -32,7 +32,6 @@ describe("Features Table", () => {

afterEach(() => {
document.body.outerHTML = ''
vi.clearAllMocks()
})

test("features are listed as 3 groups of 2 and 1 and 2 features (one being multi-crops)", () => {
23 changes: 15 additions & 8 deletions src/components/Map/FeaturesLayer.vue
Original file line number Diff line number Diff line change
@@ -24,29 +24,29 @@ export default {
type: Boolean,
default: false
},
showNumerosIlot: {
showNumerosIlots: {
type: Boolean,
default: false
},
style: {
type: Object,
default: ({ showNumeroIlots }) => ({
default: (props) => ({
layers: [
{
"id": "numeros-ilots",
"type": "symbol",
"source": "data",
"minzoom": 14,
"minzoom": 12,
"layout": {
"text-field": [
"case",
["has", "NUMERO_I"],
["concat", ["get", "NUMERO_I"], " - ", ["get", "NUMERO_P"]],
["concat", ["get", "NUMERO_I"], ".", ["get", "NUMERO_P"]],
"",
],
"text-font": ["Noto Sans Regular"],
"text-size": 12,
"visibility": showNumeroIlots ? "visible" : "none",
"visibility": props.showNumeroIlots ? "visible" : "none",
},
"paint": {
"text-color": "rgba(0, 0, 0, 1)",
@@ -63,9 +63,16 @@ export default {
const featureStore = useFeaturesStore()
const map = inject('map')

watch(() => props.showNumerosIlot, (showNumeroIlots) => {
map.value.setLayoutProperty('parcellaire-operateur/numeros-ilots', 'visibility', showNumeroIlots ? 'visible' : 'none')
})
watch(() => props.showNumerosIlots, (showNumeroIlots) => {
const visibility = showNumeroIlots ? 'visible' : 'none'

if (map.value.isStyleLoaded()) {
map.value.setLayoutProperty('parcellaire-operateur/numeros-ilots', 'visibility', visibility)
}
else {
map.value.once('load', () => map.value.setLayoutProperty('parcellaire-operateur/numeros-ilots', 'visibility', visibility))
}
}, { immediate: true })

if (props.interactive) {
featureStore.bindMaplibreFeatureState(map.value, 'parcellaire-operateur/data')
26 changes: 18 additions & 8 deletions src/components/Map/LayerSelector.vue
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ defineEmits(['update:fond', 'update:classification', 'update:cadastre', 'update:

<template>
<Teleport to=".maplibregl-ctrl-bottom-left">
<div class="container maplibregl-ctrl fr-mb-2w fr-ml-2w">
<div class="container maplibregl-ctrl">
<button
class="menu-toggle"
:class="{ 'menu-toggle--satellite': fond === 'satellite', 'menu-toggle--plan': fond === 'plan' }"
@@ -53,16 +53,19 @@ defineEmits(['update:fond', 'update:classification', 'update:cadastre', 'update:
<span>Satellite</span>
</button>
<h6>Calques</h6>
<button class="menu-entry" :class="{ 'active': classification }" @click="$emit('update:classification', !classification)">
<img src="@/assets/map/classification.jpg" alt="Couche classification" />
<span>Classification</span>
<button aria-label="Calque classification" class="menu-entry" :class="{ 'active': classification }" @click="$emit('update:classification', !classification)">
<img src="@/assets/map/classification.jpg" alt="" />
<span>
Classification
<small class="fr-hint-text">Voir la <a href="https://docs-cartobio.agencebio.org/agriculteurs.trices/annexes/legendes-de-la-carte" @click.stop target="_blank">méthode de classification</a></small>
</span>
</button>
<button class="menu-entry" :class="{ 'active': cadastre }" @click="$emit('update:cadastre', !cadastre)">
<img src="@/assets/map/cadastre.jpg" alt="Couche cadastre" />
<button aria-label="Calque numéros de cadastre" class="menu-entry" :class="{ 'active': cadastre }" @click="$emit('update:cadastre', !cadastre)">
<img src="@/assets/map/cadastre.jpg" alt="" />
<span>Numéros de cadastre</span>
</button>
<button class="menu-entry" :class="{ 'active': ilots }" @click="$emit('update:ilots', !ilots)">
<img src="../../assets/map/ilots.png" alt="Numéros d'îlots" />
<button aria-label="Calque " class="menu-entry" :class="{ 'active': ilots }" @click="$emit('update:ilots', !ilots)">
<img src="../../assets/map/ilots.png" alt="" />
<span>Numéros d'îlots (PAC)</span>
</button>
</div>
@@ -77,6 +80,7 @@ defineEmits(['update:fond', 'update:classification', 'update:cadastre', 'update:
gap: 1rem;
justify-content: center;
align-items: end;
margin: 1rem;
}
.menu-toggle {
@@ -134,6 +138,12 @@ defineEmits(['update:fond', 'update:classification', 'update:cadastre', 'update:
gap: 1rem;
font-size: 1rem;
margin-bottom: 0.5rem;
> span {
align-items: flex-start;
display: flex;
flex-direction: column;
}
}
.menu .menu-entry:hover {
42 changes: 42 additions & 0 deletions src/components/Map/MapContainer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { describe, expect, test, vi } from "vitest"

Check warning on line 1 in src/components/Map/MapContainer.test.js

GitHub Actions / deploy

'vi' is defined but never used

Check warning on line 1 in src/components/Map/MapContainer.test.js

GitHub Actions / deploy

'vi' is defined but never used

Check warning on line 1 in src/components/Map/MapContainer.test.js

GitHub Actions / tests

'vi' is defined but never used

Check warning on line 1 in src/components/Map/MapContainer.test.js

GitHub Actions / tests

'vi' is defined but never used
import { mount } from "@vue/test-utils"
import { NavigationControl, ScaleControl } from 'maplibre-gl'

import MapContainer from "./MapContainer.vue"

describe("MapContainer", () => {
test('we display navigation with no interactive elements', async () => {
const wrapper = mount(MapContainer, {

Check warning on line 9 in src/components/Map/MapContainer.test.js

GitHub Actions / deploy

'wrapper' is assigned a value but never used

Check warning on line 9 in src/components/Map/MapContainer.test.js

GitHub Actions / deploy

'wrapper' is assigned a value but never used

Check warning on line 9 in src/components/Map/MapContainer.test.js

GitHub Actions / tests

'wrapper' is assigned a value but never used

Check warning on line 9 in src/components/Map/MapContainer.test.js

GitHub Actions / tests

'wrapper' is assigned a value but never used
props: { controls: false }
})

expect(NavigationControl).toHaveBeenCalledTimes(0)
expect(ScaleControl).toHaveBeenCalledTimes(0)
})

test('we display navigation control, without attribution', async () => {
const wrapper = mount(MapContainer, {
props: { controls: true }
})

expect(NavigationControl).toHaveBeenCalledTimes(1)
expect(ScaleControl).toHaveBeenCalledTimes(0)

const customMenuSpy = wrapper.vm.map.addControl.mock.calls.at(1)
expect(customMenuSpy).toHaveProperty('0.onAdd')
expect(customMenuSpy).toHaveProperty('1', 'bottom-right')
})

test('we display navigation control and attribution', async () => {
const wrapper = mount(MapContainer, {
props: { showAttribution: true }
})

expect(NavigationControl).toHaveBeenCalledOnce()
expect(ScaleControl).toHaveBeenCalledOnce()

const attributionSpy = wrapper.vm.map.addControl.mock.calls.at(2)
expect(attributionSpy).toHaveProperty('0.onAdd')
expect(attributionSpy).toHaveProperty('1', 'bottom-right')
})
})
76 changes: 53 additions & 23 deletions src/components/Map/MapContainer.vue
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
<template>
<aside ref="mapContainer" class="maplibre-container">
<slot v-if="map" />
<div class="legend">
<slot name="legend" />
</div>
<slot name="credits" />
</aside>
</template>

<script setup>
import { onMounted, onUpdated, provide, ref, shallowRef, watch } from 'vue'
import { Map as MapLibre, NavigationControl } from 'maplibre-gl'
import { Map as MapLibre, NavigationControl, ScaleControl } from 'maplibre-gl'
const map = shallowRef(null)
const mapContainer = ref(null)
provide('map', map)
const props = defineProps({
showAttribution: {
type: Boolean,
default: false
},
bounds: Array,
controls: {
type: Boolean,
@@ -38,12 +38,14 @@ const emit = defineEmits(['zoom:change'])
onMounted(() => {
map.value = new MapLibre({
attributionControl: false,
container: mapContainer.value,
hash: false,
bounds: props.bounds,
padding: 50,
...props.options,
locale: {
'AttributionControl.ToggleAttribution': 'Déplier/replier les informations',
'NavigationControl.ResetBearing': 'Restaurer l’orientation au nord',
'NavigationControl.ZoomIn': 'Zoomer',
'NavigationControl.ZoomOut': 'Dézoomer',
@@ -55,12 +57,25 @@ onMounted(() => {
map.value.addControl({
onAdd: () => {
const el = document.createElement('div')
el.className = 'maplibregl-ctrl maplibregl-ctrl-group cartobio-controls fr-mb-1w'
el.className = 'maplibregl-ctrl maplibregl-ctrl-group cartobio-controls'
return el
}
}, 'bottom-right')
}
if (props.showAttribution) {
map.value.addControl({
onAdd: () => {
const el = document.createElement('div')
el.className = 'maplibregl-ctrl maplibregl-ctrl-attrib'
el.innerHTML = `<a href="" target="_blank">Sources des données et licences</a>`
return el
}
}, 'bottom-right')
map.value.addControl(new ScaleControl({ maxWidth: 80, unit: 'metric' }), 'bottom-right')
}
map.value.once('load', () => {
emit('zoom:change', map.value.getZoom())
})
@@ -87,14 +102,41 @@ defineExpose({
font: inherit;
}
.maplibregl-ctrl-bottom-left {
z-index: 10; /* has to be above maplibregl-ctrl-bottom-right to overlap it */
}
.maplibregl-ctrl-bottom-right {
bottom: 1.5rem;
right: 1.5rem;
display: grid;
grid-template-areas:
'null null custom-controls'
'null null group-controls'
'attribution scale scale';
gap: 1rem;
bottom: 1rem;
right: 1rem;
padding: 0;
}
.maplibregl-ctrl-bottom-right .maplibregl-ctrl-group {
margin: 0;
.maplibregl-ctrl {
margin: 0;
}
.maplibregl-ctrl-attrib {
background-color: hsla(0,0%,100%, .90);
font-size: 0.75rem;
grid-area: attribution;
}
.maplibregl-ctrl-scale {
grid-area: scale;
}
.maplibregl-ctrl-group {
grid-area: group-controls;
}
.cartobio-controls {
grid-area: custom-controls;
}
}
.legend > * {
@@ -103,10 +145,6 @@ defineExpose({
</style>

<style lang="postcss" scoped>
:deep(.maplibregl-ctrl-attrib) {
display: none;
}
:deep(.maplibregl-popup) {
position: absolute;
left: 0;
@@ -128,12 +166,4 @@ defineExpose({
.maplibre-container .maplibregl-canvas-container {
z-index: 0
}
.legend {
position: absolute;
height: 100%;
width: 100%;
z-index: 1;
pointer-events: none;
}
</style>
3 changes: 1 addition & 2 deletions src/components/OperatorSetup/index.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { afterEach, beforeAll, describe, it, expect, vi } from "vitest"
import { beforeAll, describe, it, expect } from "vitest"
import { mount, flushPromises } from "@vue/test-utils"
import { createPinia, setActivePinia } from "pinia"

@@ -27,7 +27,6 @@ describe("OperatorSetup", () => {
]
})
})
afterEach(() => vi.clearAllMocks())

it("should render only telepac tab if there is only telepac source in props", () => {
const wrapper = mount(OperatorSetup, {
6 changes: 3 additions & 3 deletions src/pages/certification/exploitations/[id]/index.vue
Original file line number Diff line number Diff line change
@@ -24,14 +24,14 @@ meta:
<div class="fr-col-6 fr-col--map" v-if="recordStore.isSetup">
<div class="sticky-map" :class="{ 'sticky-map--full-size': isMapFullSize }">
<div :class="{ 'full-size-map fr-card fr-card--shadow fr-p-2w': isMapFullSize }">
<MapContainer class="map" :class="{ 'map--full-size': isMapFullSize }" :mode="isMapFullSize ? 'fullsize' : 'compact'" :bounds="mapBounds" ref="mapRef">
<MapContainer class="map" :class="{ 'map--full-size': isMapFullSize }" :mode="isMapFullSize ? 'fullsize' : 'compact'" :bounds="mapBounds" :show-attribution="true" ref="mapRef">
<LayerSelector v-model:fond="fond" v-model:classification="showClassification" v-model:cadastre="showCadastre" v-model:ilots="showIlots" />
<GeojsonLayer v-if="fond === 'plan'" :style="baseStyle" name="base" :before="showCadastre ? 'cadastre' : showClassification ? 'surroundings' : 'parcellaire-operateur'" />
<GeojsonLayer v-if="fond === 'satellite'" :style="satelliteStyle" name="satellite" :before="showCadastre ? 'cadastre' : showClassification ? 'surroundings' : 'parcellaire-operateur'" />
<GeojsonLayer v-if="showCadastre" :style="cadastreStyle" name="cadastre" before="parcellaire-operateur" />
<GeojsonLayer v-if="showClassification" :style="surroundingsStyle" name="surroundings" before="parcellaire-operateur" />

<FeaturesLayer :show-numeros-ilot="showIlots" interactive />
<FeaturesLayer :show-numeros-ilots="showIlots" interactive />
<CustomControls @center="focusOnOriginalBbox" v-model:large="isMapFullSize" />
</MapContainer>
</div>
@@ -87,7 +87,7 @@ const mapRef = shallowRef(null);
const fond = ref('plan')
const showClassification = ref(false)
const showCadastre = ref(false)
const showIlots = ref(false)
const showIlots = ref(true)
const isMapFullSize = ref(false)
const validationRules = readonly({
4 changes: 2 additions & 2 deletions src/pages/exploitations/[id]/ajout-parcelle/dessin.vue
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ meta:
<GeojsonLayer v-if="showCadastre" :style="cadastreStyle" name="cadastre" before="parcellaire-operateur" />
<GeojsonLayer v-if="showClassification" :style="surroundingsStyle" name="surroundings" before="parcellaire-operateur" />

<FeaturesLayer :show-numeros-ilot="showIlots" />
<FeaturesLayer :show-numeros-ilots="showIlots" />
</MapContainer>
</div>
<div class="fr-col-3">
@@ -130,7 +130,7 @@ const map = ref(null) // MapContainer instance
const fond = ref('satellite')
const showClassification = ref(false)
const showCadastre = ref(false)
const showIlots = ref(false)
const showIlots = ref(true)
let draw // TerraDraw instance
/**
Loading

0 comments on commit b498c03

Please sign in to comment.