@rural-environmental-registry/map_component 1.2.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/handlers/measureToolsHandler.d.ts +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +15513 -14673
- package/dist/types/index.d.ts +119 -15
- package/dist/utils/layersConfigNormalizer.d.ts +16 -0
- package/dist/utils/menuHistory.d.ts +3 -3
- package/package.json +1 -1
- package/src/components/MapDPG.vue +90 -2
- package/src/components/fa-icon/FontAwesomeIcon.vue +35 -5
- package/src/components/map/LeafletMap.vue +3 -1
- package/src/components/menu/ChildMenu.vue +314 -27
- package/src/components/menu/LayerMenu.vue +233 -39
- package/src/components/menu/ParentMenu.vue +261 -27
- package/src/components/menu/SectionMenu.vue +512 -0
- package/src/handlers/mapToolsHandler.ts +3 -1
- package/src/handlers/measureToolsHandler.ts +36 -27
- package/src/handlers/toolsConstants.ts +1 -0
- package/src/index.ts +47 -0
- package/src/types/index.ts +150 -14
- package/src/utils/layersConfigNormalizer.ts +276 -0
- package/src/utils/menuHistory.ts +35 -19
|
@@ -8,21 +8,26 @@
|
|
|
8
8
|
<FontAwesomeIcon :iconName="iconButton" />
|
|
9
9
|
</ElButton>
|
|
10
10
|
<ElMenu
|
|
11
|
+
:key="menuOpenedsKey"
|
|
11
12
|
:class="customClasses.customMenu"
|
|
13
|
+
:default-openeds="defaultOpeneds"
|
|
12
14
|
mode="vertical"
|
|
15
|
+
@close="onGroupMenuClose"
|
|
16
|
+
@open="onGroupMenuOpen"
|
|
13
17
|
>
|
|
14
18
|
<div id="external-id-top-menu"></div>
|
|
15
|
-
<
|
|
16
|
-
v-
|
|
17
|
-
:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
<SectionMenu
|
|
20
|
+
v-if="normalizedSections.length"
|
|
21
|
+
:editingLayerKey="activeEditingLayerKey"
|
|
22
|
+
:persist="!!props.options?.persist"
|
|
23
|
+
:sections="normalizedSections"
|
|
24
|
+
:selectedSectionKey="resolvedSelectedSectionKey"
|
|
25
|
+
:visibilityMode="visibilityMode"
|
|
26
|
+
@onChildLayerToggle="onChildLayerChange"
|
|
27
|
+
@onGroupLayerToggle="onGroupLayerToggle"
|
|
28
|
+
@onLayerAction="onLayerAction"
|
|
29
|
+
@onSelectedSectionChange="onSelectedSectionChange"
|
|
30
|
+
/>
|
|
26
31
|
<div id="external-id-bottom-menu"></div>
|
|
27
32
|
</ElMenu>
|
|
28
33
|
</div>
|
|
@@ -33,9 +38,26 @@
|
|
|
33
38
|
import L from 'leaflet'
|
|
34
39
|
import { computed, nextTick, ref, watch } from 'vue'
|
|
35
40
|
import FontAwesomeIcon from '../fa-icon/FontAwesomeIcon.vue'
|
|
36
|
-
import
|
|
37
|
-
import {
|
|
38
|
-
|
|
41
|
+
import SectionMenu from './SectionMenu.vue'
|
|
42
|
+
import {
|
|
43
|
+
GroupLayerData,
|
|
44
|
+
LayerActionPayload,
|
|
45
|
+
LayerData,
|
|
46
|
+
LayersConfig,
|
|
47
|
+
LayersMenuConfig,
|
|
48
|
+
SectionEditStatePayload,
|
|
49
|
+
SectionSelectPayload
|
|
50
|
+
} from '../../types'
|
|
51
|
+
import {
|
|
52
|
+
normalizeLayersConfig,
|
|
53
|
+
shouldApplyMapOverlay
|
|
54
|
+
} from '../../utils/layersConfigNormalizer'
|
|
55
|
+
import {
|
|
56
|
+
resolveGroupCollapsedState,
|
|
57
|
+
resolveLayerActiveState,
|
|
58
|
+
setGroupCollapsedHistory,
|
|
59
|
+
shouldInitLayerOnMap
|
|
60
|
+
} from '../../utils/menuHistory.ts'
|
|
39
61
|
|
|
40
62
|
type MenuProps = {
|
|
41
63
|
layersConfig: LayersConfig
|
|
@@ -57,13 +79,112 @@
|
|
|
57
79
|
(e: 'stopLoading'): void
|
|
58
80
|
(e: 'onChildLayerToggle', data: LayerData): void
|
|
59
81
|
(e: 'onGroupLayerToggle', data: GroupLayerData): void
|
|
82
|
+
(e: 'onLayerAction', payload: LayerActionPayload): void
|
|
83
|
+
(e: 'onSectionEditStateChange', payload: SectionEditStatePayload): void
|
|
84
|
+
(e: 'onSelectedSectionChange', payload: SectionSelectPayload): void
|
|
60
85
|
}>()
|
|
61
86
|
|
|
62
87
|
const props = defineProps<MenuProps>()
|
|
63
88
|
|
|
64
|
-
const isMenuOpen = ref<boolean>(
|
|
89
|
+
const isMenuOpen = ref<boolean>(!!props.options?.defaultOpen)
|
|
65
90
|
const convertedLayers = ref<ConvertedLayers>({})
|
|
66
91
|
const convertedGeoJsonLayers = ref<ConvertedGeoJsonLayers>({})
|
|
92
|
+
const internalEditingLayerKey = ref<string | null>(null)
|
|
93
|
+
const internalSelectedSectionKey = ref<string | null>(null)
|
|
94
|
+
|
|
95
|
+
const normalizedSections = computed(() => normalizeLayersConfig(props.layersConfig))
|
|
96
|
+
|
|
97
|
+
const visibilityMode = computed(() => props.options?.visibilityMode ?? 'switch')
|
|
98
|
+
|
|
99
|
+
const isEditingControlled = computed(() => props.options?.editingLayerKey !== undefined)
|
|
100
|
+
|
|
101
|
+
const activeEditingLayerKey = computed(() => {
|
|
102
|
+
if (isEditingControlled.value) {
|
|
103
|
+
return props.options?.editingLayerKey ?? null
|
|
104
|
+
}
|
|
105
|
+
return internalEditingLayerKey.value
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
const isSectionSelectionControlled = computed(
|
|
109
|
+
() => props.options?.selectedSectionKey !== undefined
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
const activeSelectedSectionKey = computed(() => {
|
|
113
|
+
if (isSectionSelectionControlled.value) {
|
|
114
|
+
return props.options?.selectedSectionKey ?? null
|
|
115
|
+
}
|
|
116
|
+
return internalSelectedSectionKey.value
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
const resolvedSelectedSectionKey = computed((): string | null => {
|
|
120
|
+
const sections = normalizedSections.value
|
|
121
|
+
if (!sections.length) return null
|
|
122
|
+
|
|
123
|
+
const current = activeSelectedSectionKey.value
|
|
124
|
+
if (current && sections.some((section) => section.key === current)) {
|
|
125
|
+
return current
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return sections[0].key
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
watch(
|
|
132
|
+
normalizedSections,
|
|
133
|
+
(sections) => {
|
|
134
|
+
if (isSectionSelectionControlled.value) return
|
|
135
|
+
|
|
136
|
+
const current = internalSelectedSectionKey.value
|
|
137
|
+
if (current && sections.some((section) => section.key === current)) return
|
|
138
|
+
|
|
139
|
+
internalSelectedSectionKey.value = sections[0]?.key ?? null
|
|
140
|
+
},
|
|
141
|
+
{ immediate: true }
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
const defaultOpeneds = computed(() => {
|
|
145
|
+
const persist = !!props.options?.persist
|
|
146
|
+
const openeds: string[] = []
|
|
147
|
+
|
|
148
|
+
normalizedSections.value.forEach((section) => {
|
|
149
|
+
section.groups.forEach((group) => {
|
|
150
|
+
const collapsed =
|
|
151
|
+
group.collapsed !== undefined
|
|
152
|
+
? group.collapsed
|
|
153
|
+
: resolveGroupCollapsedState(group.key, undefined, persist)
|
|
154
|
+
if (!collapsed) openeds.push(group.key)
|
|
155
|
+
})
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
return openeds
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
const menuOpenedsKey = computed(() => {
|
|
162
|
+
const stepOpenKeys: string[] = []
|
|
163
|
+
normalizedSections.value.forEach((section) => {
|
|
164
|
+
section.groups.forEach((group) => {
|
|
165
|
+
if (group.collapsed === false && group.meta?.isCurrentStep) {
|
|
166
|
+
stepOpenKeys.push(group.key)
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
return stepOpenKeys.slice().sort().join('|') || 'none'
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
watch(
|
|
174
|
+
() => menuOpenedsKey.value,
|
|
175
|
+
() => {
|
|
176
|
+
if (!props.options?.persist) return
|
|
177
|
+
|
|
178
|
+
const openSet = new Set(defaultOpeneds.value)
|
|
179
|
+
normalizedSections.value.forEach((section) => {
|
|
180
|
+
section.groups.forEach((group) => {
|
|
181
|
+
if (group.collapsed === undefined) return
|
|
182
|
+
setGroupCollapsedHistory(group.key, !openSet.has(group.key))
|
|
183
|
+
})
|
|
184
|
+
})
|
|
185
|
+
},
|
|
186
|
+
{ flush: 'post' }
|
|
187
|
+
)
|
|
67
188
|
|
|
68
189
|
type CustomClasses = {
|
|
69
190
|
layerMenu: string
|
|
@@ -86,12 +207,69 @@
|
|
|
86
207
|
return isMenuOpen.value ? 'chevron-left' : 'chevron-right'
|
|
87
208
|
})
|
|
88
209
|
|
|
89
|
-
const
|
|
90
|
-
|
|
210
|
+
const findLayerContext = (
|
|
211
|
+
layerKey: string
|
|
212
|
+
): { sectionKey: string; layer: LayerData } | null => {
|
|
213
|
+
for (const section of normalizedSections.value) {
|
|
214
|
+
for (const group of section.groups) {
|
|
215
|
+
const layer = group.layers?.find((item) => item.key === layerKey)
|
|
216
|
+
if (layer) return { sectionKey: section.key, layer }
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return null
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const setEditingState = (sectionKey: string | null, layerKey: string | null): void => {
|
|
223
|
+
if (!isEditingControlled.value) {
|
|
224
|
+
internalEditingLayerKey.value = layerKey
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const context = layerKey ? findLayerContext(layerKey) : null
|
|
228
|
+
|
|
229
|
+
emit('onSectionEditStateChange', {
|
|
230
|
+
sectionKey,
|
|
231
|
+
layerKey,
|
|
232
|
+
layer: context?.layer ?? null
|
|
233
|
+
})
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const setSelectedSection = (sectionKey: string): void => {
|
|
237
|
+
if (!isSectionSelectionControlled.value) {
|
|
238
|
+
internalSelectedSectionKey.value = sectionKey
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
emit('onSelectedSectionChange', { sectionKey })
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const onSelectedSectionChange = (sectionKey: string): void => {
|
|
245
|
+
setSelectedSection(sectionKey)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const onGroupMenuOpen = (index: string): void => {
|
|
249
|
+
if (!props.options?.persist) return
|
|
250
|
+
setGroupCollapsedHistory(index, false)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const onGroupMenuClose = (index: string): void => {
|
|
254
|
+
if (!props.options?.persist) return
|
|
255
|
+
setGroupCollapsedHistory(index, true)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const applyLayerOverlay = (layer: LayerData): void => {
|
|
259
|
+
if (!shouldApplyMapOverlay(layer)) return
|
|
260
|
+
|
|
261
|
+
if (layer.geojson || layer.mapSource === 'geojson') {
|
|
262
|
+
handleGeoJsonLayer(layer)
|
|
263
|
+
return
|
|
264
|
+
}
|
|
91
265
|
|
|
92
266
|
handleWmsLayer(layer)
|
|
93
267
|
}
|
|
94
268
|
|
|
269
|
+
const onInitDefaultLayer = (layer: LayerData): void => {
|
|
270
|
+
applyLayerOverlay(layer)
|
|
271
|
+
}
|
|
272
|
+
|
|
95
273
|
const initializedLayerKeys = new Set<string>()
|
|
96
274
|
|
|
97
275
|
const initDefaultLayers = (): void => {
|
|
@@ -99,14 +277,17 @@
|
|
|
99
277
|
|
|
100
278
|
const persist = !!props.options?.persist
|
|
101
279
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
280
|
+
normalizedSections.value.forEach((section) => {
|
|
281
|
+
section.groups.forEach((group) => {
|
|
282
|
+
group.layers?.forEach((layer) => {
|
|
283
|
+
if (initializedLayerKeys.has(layer.key)) return
|
|
284
|
+
if (!shouldApplyMapOverlay(layer)) return
|
|
285
|
+
if (!shouldInitLayerOnMap(layer, persist)) return
|
|
286
|
+
|
|
287
|
+
const resolved = resolveLayerActiveState(layer, persist)
|
|
288
|
+
onInitDefaultLayer(resolved)
|
|
289
|
+
initializedLayerKeys.add(layer.key)
|
|
290
|
+
})
|
|
110
291
|
})
|
|
111
292
|
})
|
|
112
293
|
}
|
|
@@ -127,29 +308,43 @@
|
|
|
127
308
|
)
|
|
128
309
|
|
|
129
310
|
const onChildLayerChange = (layer: LayerData): void => {
|
|
130
|
-
|
|
131
|
-
handleGeoJsonLayer(layer)
|
|
132
|
-
} else {
|
|
133
|
-
handleWmsLayer(layer)
|
|
134
|
-
}
|
|
135
|
-
|
|
311
|
+
applyLayerOverlay(layer)
|
|
136
312
|
emit('onChildLayerToggle', layer)
|
|
137
313
|
}
|
|
138
314
|
|
|
139
315
|
const onGroupLayerToggle = (parent: GroupLayerData): void => {
|
|
140
316
|
parent.layers.forEach((childLayer: LayerData) => {
|
|
141
|
-
|
|
142
|
-
handleGeoJsonLayer(childLayer)
|
|
143
|
-
} else {
|
|
144
|
-
handleWmsLayer(childLayer)
|
|
145
|
-
}
|
|
317
|
+
applyLayerOverlay(childLayer)
|
|
146
318
|
})
|
|
147
319
|
|
|
148
320
|
emit('onGroupLayerToggle', parent)
|
|
149
321
|
}
|
|
150
322
|
|
|
323
|
+
const onLayerAction = (payload: LayerActionPayload): void => {
|
|
324
|
+
const isEditAction = payload.actionType === 'edit' || payload.actionKey === 'edit'
|
|
325
|
+
const isEditControlAction =
|
|
326
|
+
payload.source === 'edit-panel' &&
|
|
327
|
+
(payload.actionType === 'cancel' ||
|
|
328
|
+
payload.actionType === 'conclude' ||
|
|
329
|
+
payload.actionKey === 'cancel' ||
|
|
330
|
+
payload.actionKey === 'conclude')
|
|
331
|
+
|
|
332
|
+
if (isEditAction && payload.source === 'child-menu' && payload.layerKey) {
|
|
333
|
+
setEditingState(payload.sectionKey ?? null, payload.layerKey)
|
|
334
|
+
if (payload.sectionKey) {
|
|
335
|
+
setSelectedSection(payload.sectionKey)
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (isEditControlAction) {
|
|
340
|
+
setEditingState(null, null)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
emit('onLayerAction', payload)
|
|
344
|
+
}
|
|
345
|
+
|
|
151
346
|
const convertToWmsLayer = (layer: LayerData): L.TileLayer => {
|
|
152
|
-
const wmsLayer = L.tileLayer.wms(layer.baseUrl, {
|
|
347
|
+
const wmsLayer = L.tileLayer.wms(layer.baseUrl ?? '', {
|
|
153
348
|
layers: layer.layers,
|
|
154
349
|
format: layer.format || 'image/png',
|
|
155
350
|
transparent: layer.transparent
|
|
@@ -274,8 +469,7 @@
|
|
|
274
469
|
.layer-menu > .map-custom-menu {
|
|
275
470
|
box-shadow: var(--mapa-base-box-shadow);
|
|
276
471
|
padding: var(--mapa-size-base-10);
|
|
277
|
-
overflow-y:
|
|
278
|
-
scrollbar-width: none;
|
|
472
|
+
overflow-y: auto;
|
|
279
473
|
height: 100%;
|
|
280
474
|
}
|
|
281
475
|
|