Skip to content

Commit

Permalink
Merge pull request #148 from Geoportail-Luxembourg/GSLUX-705_modify_f…
Browse files Browse the repository at this point in the history
…eature_rebased2

Gslux 705 modify feature selection and sync between map and UI
  • Loading branch information
mki-c2c authored Sep 4, 2024
2 parents f04b2d3 + 3aa96bf commit c36fcb4
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 99 deletions.
42 changes: 16 additions & 26 deletions src/components/draw/draw-panel-features.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { onMounted, Ref, ref, watch } from 'vue'
import { onMounted } from 'vue'
import { storeToRefs } from 'pinia'
import { getUid } from 'ol/util'
import useSortable from '@/composables/sortable'
import { useDrawStore } from '@/stores/draw.store'
Expand All @@ -9,35 +10,24 @@ import { DrawnFeature } from '@/services/draw/drawn-feature'
import FeatureItem from './feature-item.vue'
const drawStore = useDrawStore()
const { drawnFeatures: features, featureEditionDocked } = storeToRefs(drawStore)
const currentOpenedFeature: Ref<number | undefined> = ref(undefined)
const currentEditingFeature: Ref<number | undefined> = ref(undefined)
function onToggleFeatureSub(featureId: number, isOpen: boolean) {
const {
activeFeatureId,
editingFeatureId,
drawnFeatures: features,
featureEditionDocked,
} = storeToRefs(drawStore)
function onToggleFeatureSub(featureId: String, isOpen: boolean) {
// Only one feature details is displayed at once
currentOpenedFeature.value = isOpen ? featureId : undefined
currentEditingFeature.value = undefined
activeFeatureId.value = isOpen ? featureId : undefined
editingFeatureId.value = undefined
}
function onToggleFeatureEdit(featureId: number, isEditing: boolean) {
currentEditingFeature.value = isEditing ? featureId : undefined
function onToggleFeatureEdit(featureId: String, isEditing: boolean) {
editingFeatureId.value = isEditing ? featureId : undefined
// TODO: continue...
}
watch(
features,
(newFeatures, oldFeatures) => {
// Last added feature is unfold by default
if (oldFeatures === undefined || newFeatures.length > oldFeatures.length) {
const currentFeature =
newFeatures[oldFeatures === undefined ? 0 : newFeatures.length - 1]
currentOpenedFeature.value = currentEditingFeature.value =
currentFeature.id
}
},
{ immediate: true }
)
onMounted(() => {
useSortable(<HTMLElement>document.querySelector('.sortable-features'))
})
Expand All @@ -52,8 +42,8 @@ onMounted(() => {
>
<FeatureItem
:isDocked="featureEditionDocked"
:isEditing="currentEditingFeature === feature.id"
:isOpen="currentOpenedFeature === feature.id"
:isEditing="editingFeatureId === getUid(feature)"
:isOpen="activeFeatureId === getUid(feature)"
:feature="<DrawnFeature>feature"
@toggleFeatureSub="onToggleFeatureSub"
@toggleFeatureEdit="onToggleFeatureEdit"
Expand Down
7 changes: 7 additions & 0 deletions src/components/draw/feature-edit-style-label.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script setup lang="ts"></script>

<template>
<slot name="color"></slot>
<slot name="size"></slot>
<slot name="angle"></slot>
</template>
25 changes: 5 additions & 20 deletions src/components/draw/feature-edit-style.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import FeatureEditStyleCircle from './feature-edit-style-circle.vue'
import FeatureEditStylePoint from './feature-edit-style-point.vue'
import FeatureEditStyleLine from './feature-edit-style-line.vue'
import FeatureEditStylePolygon from './feature-edit-style-polygon.vue'
import FeatureEditStyleLabel from './feature-edit-style-label.vue'
const { t } = useTranslation()
const props = defineProps<{
Expand All @@ -19,28 +20,12 @@ const styleComponents = {
FeatureEditStyleLine,
FeatureEditStylePoint,
FeatureEditStylePolygon,
FeatureEditStyleLabel,
}
const currentStyleComponent = computed(() => {
const featureType = props.feature.featureType
if (featureType === 'drawnPoint') {
return 'FeatureEditStylePoint'
}
if (featureType === 'drawnCircle') {
return 'FeatureEditStyleCircle'
}
if (featureType === 'drawnLine') {
return 'FeatureEditStyleLine'
}
if (featureType === 'drawnPolygon') {
return 'FeatureEditStylePolygon'
}
return undefined
})
const currentStyleComponent = computed(() =>
props.feature.featureType.replace('drawn', 'FeatureEditStyle')
)
function onClickChangeOrientation() {}
</script>
Expand Down
5 changes: 3 additions & 2 deletions src/components/draw/feature-item.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script setup lang="ts">
import { getUid } from 'ol/util'
import { DrawnFeature } from '@/services/draw/drawn-feature'
import FeatureSubContent from './feature-sub-content.vue'
Expand Down Expand Up @@ -26,11 +27,11 @@ const emit = defineEmits([
])
function onToggleFeatureSub() {
emit('toggleFeatureSub', props.feature.id, !props.isOpen)
emit('toggleFeatureSub', getUid(props.feature), !props.isOpen)
}
function onToggleEditFeature() {
emit('toggleFeatureEdit', props.feature.id, !props.isEditing)
emit('toggleFeatureEdit', getUid(props.feature), !props.isEditing)
alert('TODO: Toggle edition mode')
}
Expand Down
56 changes: 56 additions & 0 deletions src/composables/draw/draw-select.composable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { watch } from 'vue'
import { storeToRefs } from 'pinia'

import useMap from '@/composables/map/map.composable'
import { listen } from 'ol/events'
import * as olArray from 'ol/array.js'
import { getUid } from 'ol/util'
import { useDrawStore } from '@/stores/draw.store'
import { useAppStore } from '@/stores/app.store'

export default function useDrawSelect() {
const map = useMap().getOlMap()
const appStore = useAppStore()
const { activeFeatureId, drawnFeatures } = storeToRefs(useDrawStore())

listen(map, 'click', event => handleClick(event))

watch(activeFeatureId, (newId, oldId) => {
drawnFeatures.value
.filter(f => getUid(f) == oldId)
.forEach(oldFeature => {
oldFeature.selected = false
oldFeature.changed()
})
drawnFeatures.value
.filter(f => getUid(f) == newId)
.forEach(newFeature => {
newFeature.selected = true
newFeature.changed()
})
})

const handleClick = function (event: any) {
const pixel = event.pixel

const feature = map.forEachFeatureAtPixel(
pixel,
feature => {
const featureMatch = olArray.includes(drawnFeatures.value, feature)
if (featureMatch) {
appStore.toggleMyMapsOpen(true)
activeFeatureId.value = getUid(feature)

return
}
},
{
hitTolerance: 5,
}
)

if (feature) {
return
}
}
}
2 changes: 2 additions & 0 deletions src/composables/draw/drawn-features.composable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ export default function useDrawnFeatures() {
// if (curLineStringCooridnates.length < 2) {
// return
// }

// TODO remove duplicate geometry end point ?
// const prevCoord =
// curLineStringCooridnates[curLineStringCooridnates.length - 1]
// const antePrevCoord =
Expand Down
4 changes: 0 additions & 4 deletions src/services/draw/drawn-feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ export class DrawnFeature extends Feature {
featureStyle: DrawnFeatureStyle
map = useMap().getOlMap()

testMyClass() {
console.log('test')
}

toProperties() {
return {
angle: this.featureStyle.angle,
Expand Down
12 changes: 0 additions & 12 deletions src/services/state-persistor/state-persistor-features.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
import featureHash from './utils/FeatureHash'
import { DrawnFeature } from '@/services/draw/drawn-feature'

// const drawnFeatureToFeature = function (
// drawnFeature: DrawnFeature
// ): Feature<Geometry> {
// const olFeature = drawnFeature.olFeature
// olFeature.set('name', drawnFeature.label)
// return olFeature
// }

class StorageFeaturesMapper {
featuresToUrl(features: DrawnFeature[] | null): string {
if (!features) return ''
// const featureArray = features.map(f => drawnFeatureToFeature(f))
const featuresToEncode = features.filter(feature => !feature.map_id)
// todo: implement and call encoding
// featuresToEncode.forEach(f => featureHash.setShortProperties(f))
// for now just transmit name
featuresToEncode.forEach(f => f.set('name', f.label))
return featuresToEncode.length > 0
? featureHash.writeFeatures(featuresToEncode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { storageHelper } from './storage/storage.helper'
import { storageFeaturesMapper } from './state-persistor-features.mapper'
import { useDrawStore } from '@/stores/draw.store'
import { DrawnFeature } from '@/services/draw/drawn-feature'
import useDrawSelect from '@/composables/draw/draw-select.composable'

class StatePersistorFeaturesService implements StatePersistorService {
bootstrap() {
Expand Down Expand Up @@ -35,6 +36,8 @@ class StatePersistorFeaturesService implements StatePersistorService {

restore() {
const { drawnFeatures } = storeToRefs(useDrawStore())
// initialise map listeners for feature selection
useDrawSelect()

const features = storageHelper.getValue(
SP_KEY_FEATURES,
Expand Down
3 changes: 1 addition & 2 deletions src/services/state-persistor/utils/FeatureHash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class FeatureHash extends TextFeature {
id: Math.floor(Math.random() * Date.now()),
label: name,
description,
editable: true,
editable: false,
display_order: defaultOrder,
selected: false,
map_id: undefined, // ??? TODO : check use of this param
Expand All @@ -307,7 +307,6 @@ class FeatureHash extends TextFeature {
}
)
convertCircleToPolygon(drawnFeature, featureType)
drawnFeature.testMyClass()
return drawnFeature

// TODO check defaults:
Expand Down
32 changes: 0 additions & 32 deletions src/stores/draw.store.model.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { Feature } from 'ol'
import { Geometry } from 'ol/geom'

export type DrawStateActive =
| undefined
| 'drawPoint'
Expand Down Expand Up @@ -32,32 +29,3 @@ export interface DrawnFeatureStyle {
size: number
// isCircle: boolean,
}

// export interface DrawnFeatureStyle {
// angle: number
// color: string
// // description: string,
// stroke: number
// // isLabel: boolean,
// linestyle: string
// // name: string,
// opacity: number
// showOrientation: boolean
// shape: string
// size: number
// // isCircle: boolean,
// }

export interface DrawnFeature {
// TODO: to improve
id: number
label: string
description: string
editable: boolean
selected: boolean
map_id: number
saving: boolean
featureType: DrawnFeatureType
featureStyle: DrawnFeatureStyle
olFeature: Feature<Geometry>
}
9 changes: 8 additions & 1 deletion src/stores/draw.store.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { ref, Ref } from 'vue'

import { getUid } from 'ol/util'
import { DrawStateActive } from './draw.store.model'
import { DrawnFeature } from '@/services/draw/drawn-feature'

export const useDrawStore = defineStore('draw', () => {
const activeFeatureId: Ref<String | undefined> = ref(undefined)
const editingFeatureId: Ref<String | undefined> = ref(undefined)
const drawStateActive = ref<DrawStateActive>(undefined)
// no immutable changes on drawnFeatures in functions bellow,
// but keep same Collection for sync with ol source (map)
Expand All @@ -21,6 +24,8 @@ export const useDrawStore = defineStore('draw', () => {

function addDrawnFeature(feature: DrawnFeature) {
drawnFeatures.value = [...drawnFeatures.value, feature]
activeFeatureId.value = getUid(feature)
editingFeatureId.value = getUid(feature)
}

function setDrawnFeatures(features: DrawnFeature[]) {
Expand All @@ -34,6 +39,8 @@ export const useDrawStore = defineStore('draw', () => {
}

return {
activeFeatureId,
editingFeatureId,
drawStateActive,
drawnFeatures,
featureEditionDocked,
Expand Down

0 comments on commit c36fcb4

Please sign in to comment.