3
3
:nodes =" [root]"
4
4
node-key =" _id"
5
5
label-key =" label"
6
- children-key =" features "
7
- default-expand-all
6
+ children-key =" children "
7
+ v-model:expanded = " expandedNodes "
8
8
dense
9
9
>
10
10
<template v-slot :default-header =" prop " >
11
11
<!-- Layer rendering -->
12
12
<q-icon v-if =" prop.node.icon" :name =" prop.node.icon" />
13
- <KLayerItem v-if =" prop.node.name "
13
+ <KLayerItem v-if =" isLayerNode( prop.node) "
14
14
v-bind =" $props"
15
15
:togglable =" false"
16
16
:layer =" root"
17
17
/>
18
18
<!-- Features rendering -->
19
- <div v-else class =" row fit items-center q-pl-md q-pr-sm no-wrap" >
19
+ <div v-else-if = " prop.node.label " class =" row fit items-center q-pl-md q-pr-sm no-wrap" >
20
20
<div :class =" {
21
21
'text-primary': root.isVisible,
22
22
'text-grey-6': root.isDisabled || !root.isVisible
23
23
}"
24
24
>
25
- <span v-html =" prop.node.label || prop.node._id " />
25
+ <span v-html =" prop.node.label" />
26
26
</div >
27
- <q-space />
27
+ <q-space v-if = " isFeatureNode(prop.node) " />
28
28
<!-- Features actions -->
29
- <KPanel
29
+ <KPanel v-if = " isFeatureNode(prop.node) "
30
30
:id =" `${prop.node.label}-feature-actions`"
31
31
:content =" featureActions"
32
32
:context =" prop.node"
33
33
/>
34
34
</div >
35
35
</template >
36
+ <!-- Feature properties rendering -->
37
+ <template v-slot :default-body =" prop " >
38
+ <KView v-if =" isFeaturePropertiesNode(prop.node)"
39
+ class =" q-pa-md full-width"
40
+ :values =" prop.node"
41
+ :schema =" schema"
42
+ :separators =" true"
43
+ />
44
+ </template >
36
45
</q-tree >
37
46
</template >
38
47
@@ -43,6 +52,7 @@ import { ref, computed } from 'vue'
43
52
import { useRoute , useRouter } from ' vue-router'
44
53
import bbox from ' @turf/bbox'
45
54
import { Store , i18n } from ' ../../../../core/client'
55
+ import { KView } from ' ../../../../core/client/components'
46
56
import KLayerItem from ' ../catalog/KLayerItem.vue'
47
57
import { useCurrentActivity } from ' ../../composables/activity.js'
48
58
import { getFeatureId , getFeatureLabel } from ' ../../utils/utils.js'
@@ -60,6 +70,7 @@ const props = defineProps({
60
70
const route = useRoute ()
61
71
const router = useRouter ()
62
72
const { CurrentActivity } = useCurrentActivity ()
73
+ const expandedNodes = ref ([props .item .layer ._id ])
63
74
const editedFeatures = ref ([])
64
75
65
76
// Computed
@@ -125,19 +136,60 @@ const featureActions = computed(() => {
125
136
}]
126
137
}]
127
138
})
139
+ const schema = computed (() => {
140
+ let schema
141
+ // Is there any schema ?
142
+ if (_ .has (props .item .layer , ' schema.content' )) {
143
+ // As we update the schema does not alter the original one
144
+ schema = _ .cloneDeep (_ .get (props .item .layer , ' schema.content' ))
145
+ } else {
146
+ schema = generatePropertiesSchema (_ .get (props .item , ' features[0]' , {}), props .item .layer .name )
147
+ }
148
+ // Ensure schema is not empty
149
+ if (_ .isNil (schema) || _ .isEmpty (_ .get (schema, ' properties' , {}))) {
150
+ return
151
+ }
152
+ return schema
153
+ })
128
154
const root = computed (() => {
129
- const features = props .item .features .map (feature => Object .assign ({
130
- label: getFeatureLabel (feature, props .item .layer ),
131
- icon: (editedFeatures .value .contains (feature) ? ' las la-edit' : ' ' )
132
- }, feature))
155
+ const children = props .item .features .map (feature => Object .assign ({
156
+ icon: getIcon (feature),
157
+ label: getLabel (feature),
158
+ children: [Object .assign ({
159
+ icon: getIcon (feature .properties ),
160
+ label: getLabel (feature .properties )
161
+ }, feature .properties )] // Properties only for node displaying it
162
+ }, feature)) // Target feature is required as context for actions
163
+ // For each feature add a node containing
133
164
// Replace default layer actions with new ones
134
- const root = Object .assign ({
135
- icon: ( editedFeatures . value . length > 0 ? ' las la-edit ' : ' ' )
136
- }, _ . omit (props .item .layer , [ ' icon ' , ' actions ' ]), { actions : layerActions . value , features })
137
- return root
165
+ return Object .assign ({
166
+ icon: getIcon ( props . item . layer ),
167
+ label : getLabel (props .item .layer ),
168
+ }, _ . omit ( props . item . layer , [ ' icon ' , ' actions ' ]), { actions : layerActions . value , children })
138
169
})
139
170
140
171
// Functions
172
+ function isLayerNode (node ) {
173
+ return node .name
174
+ }
175
+ function isFeatureNode (node ) {
176
+ return node .properties
177
+ }
178
+ function isFeaturePropertiesNode (node ) {
179
+ return ! node .properties && ! isLayerNode (node)
180
+ }
181
+ function getIcon (node ) {
182
+ if (isLayerNode (node)) return (editedFeatures .value .length > 0 ? ' las la-edit' : ' ' )
183
+ if (isFeatureNode (node)) return (editedFeatures .value .contains (node) ? ' las la-edit' : ' ' )
184
+ if (isFeaturePropertiesNode (node)) return ' las la-address-card'
185
+ return ' '
186
+ }
187
+ function getLabel (node ) {
188
+ if (isLayerNode (node)) return node .label || node .name
189
+ if (isFeatureNode (node)) return getFeatureLabel (node, props .item .layer ) || getFeatureId (node, props .item .layer )
190
+ if (isFeaturePropertiesNode (node)) return i18n .t (' KSelectedLayerFeatures.FEATURE_PROPERTIES_LABEL' )
191
+ return ' '
192
+ }
141
193
function zoomToSelectedFeatures () {
142
194
CurrentActivity .value .zoomToBBox (bbox ({ type: ' FeatureCollection' , features: props .item .features }))
143
195
}
0 commit comments