Skip to content

Commit

Permalink
feat: Allow to edit features on any layer using a features service (c…
Browse files Browse the repository at this point in the history
…loses #1036)
  • Loading branch information
claustres committed Jan 3, 2025
1 parent 314836d commit af8400f
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 24 deletions.
4 changes: 2 additions & 2 deletions map/client/components/KFeatureEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default {
async onFeatureEdited (updatedFeature) {
// Save in DB or in memory
if (this.layer._id) {
await this.kActivity.editFeaturesProperties(updatedFeature)
await this.kActivity.editFeaturesProperties(updatedFeature, this.layer)
} else {
await this.$api.getService(this.service).patch(updatedFeature._id, _.pick(updatedFeature, ['properties']))
}
Expand All @@ -80,7 +80,7 @@ export default {
// If not injected load it
if (this.layerName) this.layer = this.kActivity.getLayerByName(this.layerName)
else this.layer = await this.$api.getService('catalog').get(this.layerId)
this.service = _.get(this.layer, '_id') ? 'features' : 'features-edition'
this.service = _.get(this.layer, '_id') ? _.get(this.layer, 'service') : 'features-edition'
},
setup (props) {
return {
Expand Down
12 changes: 6 additions & 6 deletions map/client/mixins/map/mixin.edit-layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export const editLayers = {
}
} else {
// Listen to layer changes
const featuresService = this.$api.getService('features')
const featuresService = this.$api.getService(this.editedLayer.service)
featuresService.on('created', this.onEditedFeaturesCreated)
featuresService.on('patched', this.onEditedFeaturesUpdated)
featuresService.on('removed', this.onEditedFeaturesRemoved)
Expand Down Expand Up @@ -248,7 +248,7 @@ export const editLayers = {
await Promise.all(features.map((f) => service.remove(f._id)))
} else {
// Clear listeners to layer changes
const featuresService = this.$api.getService('features')
const featuresService = this.$api.getService(this.editedLayer.service)
featuresService.off('created', this.onEditedFeaturesCreated)
featuresService.off('patched', this.onEditedFeaturesUpdated)
featuresService.off('removed', this.onEditedFeaturesRemoved)
Expand Down Expand Up @@ -314,7 +314,7 @@ export const editLayers = {
_.set(geoJson, idProp, idValue)
// Save changes to DB, we use the layer DB ID as layer ID on features
if (this.editedLayer._id) {
geoJson = await this.createFeatures(geoJson, this.editedLayer._id)
geoJson = await this.createFeatures(geoJson, this.editedLayer)
} else {
// Generate in memory service _id as string to match what's done with mongo
geoJson._id = idValue
Expand All @@ -336,7 +336,7 @@ export const editLayers = {
// Avoid reentrance from realtime events as also raised when we are the initiator
if (this.updatedFeature && this.updatedFeature._id === geoJson._id) return
if (this.editedLayer._id) {
await this.editFeaturesGeometry(geoJson)
await this.editFeaturesGeometry(geoJson, this.editedLayer)
} else {
const features = geoJson.type === 'FeatureCollection' ? geoJson.features : [geoJson]
const service = this.$api.getService('features-edition')
Expand Down Expand Up @@ -364,7 +364,7 @@ export const editLayers = {
if (this.removedFeature && this.removedFeature._id === geoJson._id) return

if (this.editedLayer._id) {
await this.removeFeatures(geoJson)
await this.removeFeatures(geoJson, this.editedLayer)
} else {
const features = geoJson.type === 'FeatureCollection' ? geoJson.features : [geoJson]
const service = this.$api.getService('features-edition')
Expand Down Expand Up @@ -393,7 +393,7 @@ export const editLayers = {
}).onOk(async () => {
const parentLeafletLayer = this.getLeafletLayerByName(layer.name)
if (!parentLeafletLayer) return
await this.removeFeatures(feature)
await this.removeFeatures(feature, layer)
parentLeafletLayer.removeLayer(leafletLayer)
})
},
Expand Down
28 changes: 14 additions & 14 deletions map/client/utils/utils.features.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,17 +308,17 @@ export function checkFeatures (geoJson, options = {
return { kinks: kinksFeatures }
}

export async function createFeatures (geoJson, layerId, chunkSize = 5000, processCallback) {
if (!layerId) return
export async function createFeatures (geoJson, layer, chunkSize = 5000, processCallback) {
if (!layer) return
const features = (geoJson.type === 'FeatureCollection' ? geoJson.features : [geoJson])
features.forEach(feature => {
// Remove any temporary ID as we will use the one from MongoDB
delete feature._id
feature.layer = layerId
feature.layer = layer._id
})
// Single edition mode
if (features.length === 1) {
const feature = await api.getService('features').create(features[0])
const feature = await api.getService(layer.service).create(features[0])
return feature
} else {
// Create chunks to avoid reaching some limits (upload size, timeout, etc.)
Expand Down Expand Up @@ -352,47 +352,47 @@ export async function createFeatures (geoJson, layerId, chunkSize = 5000, proces
}
// Write the chunks
for (let i = 0; i < chunks.length; i++) {
await api.getService('features').create(chunks[i])
await api.getService(layer.service).create(chunks[i])
if (typeof processCallback === 'function') await processCallback(i, chunks[i])
}
}
}

export async function editFeaturesGeometry (geoJson) {
export async function editFeaturesGeometry (geoJson, layer) {
const features = (geoJson.type === 'FeatureCollection' ? geoJson.features : [geoJson])
const updatedFeatures = []
for (let i = 0; i < features.length; i++) {
const feature = features[i]
if (feature._id) {
const updatedFeature = await api.getService('features').patch(feature._id, _.pick(feature, ['geometry']))
const updatedFeature = await api.getService(layer.service).patch(feature._id, _.pick(feature, ['geometry']))
updatedFeatures.push(updatedFeature)
}
}
return (geoJson.type === 'FeatureCollection' ? Object.assign(geoJson, { features: updatedFeatures }) : updatedFeatures)
}

export async function editFeaturesProperties (geoJson) {
export async function editFeaturesProperties (geoJson, layer) {
const features = (geoJson.type === 'FeatureCollection' ? geoJson.features : [geoJson])
const updatedFeatures = []
for (let i = 0; i < features.length; i++) {
const feature = features[i]
if (feature._id) {
const updatedFeature = await api.getService('features').patch(feature._id, _.pick(feature, ['properties']))
const updatedFeature = await api.getService(layer.service).patch(feature._id, _.pick(feature, ['properties']))
updatedFeatures.push(updatedFeature)
}
}
return (geoJson.type === 'FeatureCollection' ? Object.assign(geoJson, { features: updatedFeatures }) : updatedFeatures)
}

export async function removeFeatures (geoJsonOrLayerId) {
export async function removeFeatures (geoJson, layer) {
// Remove all features of a given layer
if (typeof geoJsonOrLayerId === 'string') {
await api.getService('features').remove(null, { query: { layer: geoJsonOrLayerId } })
if (!geoJson) {
await api.getService(layer.service).remove(null, { query: { layer: layer._id } })
} else {
const features = (geoJsonOrLayerId.type === 'FeatureCollection' ? geoJsonOrLayerId.features : [geoJsonOrLayerId])
const features = (geoJson.type === 'FeatureCollection' ? geoJson.features : [geoJson])
for (let i = 0; i < features.length; i++) {
const feature = features[i]
if (feature._id) await api.getService('features').remove(feature._id)
if (feature._id) await api.getService(layer.service).remove(feature._id)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions map/client/utils/utils.layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ export async function saveGeoJsonLayer (layer, geoJson, chunkSize = 5000) {
.create(_.omit(layer, InternalLayerProperties))
let nbFeatures = 0
// We use the generated DB ID as layer ID on features
await createFeatures(geoJson, createdLayer._id, chunkSize, (i, chunk) => {
await createFeatures(geoJson, createdLayer, chunkSize, (i, chunk) => {
// Update saving message according to new chunk data
nbFeatures += chunk.length
Loading.show({
Expand Down Expand Up @@ -486,7 +486,7 @@ export async function removeLayer (layer) {
if (layer._id) {
// If persistent feature layer remove features as well
if (isFeatureLayer(layer)) {
await removeFeatures(layer._id)
await removeFeatures(null, layer)
}
await api.getService('catalog').remove(layer._id)
}
Expand Down

0 comments on commit af8400f

Please sign in to comment.