From c01882f8677a9d02681df3446d7d28df1fe7727f Mon Sep 17 00:00:00 2001
From: mahmoud adel <58145645+mahmoudadel54@users.noreply.github.com>
Date: Wed, 6 Nov 2024 13:35:46 +0200
Subject: [PATCH] [Backport 2024.02.xx] - #10648: Issue editing multiple fields
in MapStore Attribute Table (#10651) (#10653)
* #10648: Issue editing multiple fields in MapStore Attribute Table (#10651)
* #10648: Issue editing multiple fields in MapStore Attribute Table
Description:
- edit in update wfs-t xml payload in case of multi-edit in each sigle row
- add unit test for 'savePendingFeatureGridChanges'
* #10648: move 'createChangesTransaction' util function from epics/featuregrid to FeatureGridUtils file and a unit test is added for it.
* #10648: handle unit test for 'savePendingFeatureGridChanges'
* #10648: edit jsdoc for util 'createChangesTransaction'
* #10648: fix FE test failure for - Issue editing multiple fields in MapStore Attribute Table (#10654)
* #10648: fix FE tests failure for savePendingFeatureGridChanges
* #10648: remove unit test of 'savePendingFeatureGridChanges'
---
web/client/epics/featuregrid.js | 12 +---
web/client/utils/FeatureGridUtils.js | 15 +++++
.../utils/__tests__/FeatureGridUtils-test.js | 57 ++++++++++++++++++-
3 files changed, 72 insertions(+), 12 deletions(-)
diff --git a/web/client/epics/featuregrid.js b/web/client/epics/featuregrid.js
index 16b9a27a94..a8738f19f9 100644
--- a/web/client/epics/featuregrid.js
+++ b/web/client/epics/featuregrid.js
@@ -11,8 +11,7 @@ import {get, head, isEmpty, find, castArray, includes, reduce} from 'lodash';
import { LOCATION_CHANGE } from 'connected-react-router';
import axios from '../libs/ajax';
import bbox from '@turf/bbox';
-import { fidFilter } from '../utils/ogc/Filter/filter';
-import { getDefaultFeatureProjection, getPagesToLoad, gridUpdateToQueryUpdate, updatePages } from '../utils/FeatureGridUtils';
+import { createChangesTransaction, getDefaultFeatureProjection, getPagesToLoad, gridUpdateToQueryUpdate, updatePages } from '../utils/FeatureGridUtils';
import assign from 'object-assign';
import {
@@ -232,15 +231,6 @@ const addPagination = (filterObj, pagination) => ({
pagination
});
-const createChangesTransaction = (changes, newFeatures, {insert, update, propertyChange, getPropertyName, transaction})=>
- transaction(
- newFeatures.map(f => insert(f)),
- Object.keys(changes).map( id =>
- Object.keys(changes[id]).map(name =>
- update([propertyChange(getPropertyName(name), changes[id][name]), fidFilter("ogc", id)])
- )
- )
- );
const createDeleteTransaction = (features, {transaction, deleteFeature}) => transaction(
features.map(deleteFeature)
);
diff --git a/web/client/utils/FeatureGridUtils.js b/web/client/utils/FeatureGridUtils.js
index b5406acd93..b35c34341f 100644
--- a/web/client/utils/FeatureGridUtils.js
+++ b/web/client/utils/FeatureGridUtils.js
@@ -18,6 +18,7 @@ import {
} from './ogc/WFS/base';
import { applyDefaultToLocalizedString } from '../components/I18N/LocalizedString';
+import { fidFilter } from './ogc/Filter/filter';
const getGeometryName = (describe) => get(findGeometryProperty(describe), "name");
const getPropertyName = (name, describe) => name === "geometry" ? getGeometryName(describe) : name;
@@ -392,3 +393,17 @@ export const supportsFeatureEditing = (layer) => includes(supportedEditLayerType
* @returns {boolean} flag
*/
export const areLayerFeaturesEditable = (layer) => !layer?.disableFeaturesEditing && supportsFeatureEditing(layer);
+/**
+ * Create wfs-t xml payload for insert/edit features in featuregrid
+ * @param {object} changes object that contains updates e.g: {LAYER_NAME.id: {"FIELD1": 55, "FIELD2":"edit 02"}}
+ * @param {object[]} newFeatures array of new inserted features
+ * @param {object} wfsutils object of wfs utils that includes insert/update/propertyChange/getPropertyName/transaction
+ * @returns {string} wfs-transaction xml payload
+ */
+export const createChangesTransaction = (changes, newFeatures, {insert, update, propertyChange, getPropertyName: getPropertyNameFunc, transaction})=>
+ transaction(
+ newFeatures.map(f => insert(f)),
+ Object.keys(changes).map( id =>{
+ return update(Object.keys(changes[id]).map(prop => propertyChange(getPropertyNameFunc(prop), changes[id][prop])), fidFilter("ogc", id));
+ })
+ );
diff --git a/web/client/utils/__tests__/FeatureGridUtils-test.js b/web/client/utils/__tests__/FeatureGridUtils-test.js
index 53f140dcd3..5609f2b76d 100644
--- a/web/client/utils/__tests__/FeatureGridUtils-test.js
+++ b/web/client/utils/__tests__/FeatureGridUtils-test.js
@@ -16,8 +16,10 @@ import {
getAttributesNames,
featureTypeToGridColumns,
supportsFeatureEditing,
- areLayerFeaturesEditable
+ areLayerFeaturesEditable,
+ createChangesTransaction
} from '../FeatureGridUtils';
+import requestBuilder from "../ogc/WFST/RequestBuilder";
describe('FeatureGridUtils', () => {
@@ -447,4 +449,57 @@ describe('FeatureGridUtils', () => {
expect(areLayerFeaturesEditable({type: "wmts"})).toBeFalsy();
});
});
+ describe('test featuregrid transactions utils', ()=>{
+ const describeFeatureType = {
+ "elementFormDefault": "qualified",
+ "targetNamespace": "http://localhost:8080/geoserver/mapstore",
+ "targetPrefix": "mapstore",
+ "featureTypes": [
+ {
+ "typeName": "TEST_LAYER",
+ "properties": [
+ {
+ "name": "Integer",
+ "maxOccurs": 1,
+ "minOccurs": 0,
+ "nillable": true,
+ "type": "xsd:int",
+ "localType": "int"
+ },
+ {
+ "name": "Long",
+ "maxOccurs": 1,
+ "minOccurs": 0,
+ "nillable": true,
+ "type": "xsd:int",
+ "localType": "int"
+ },
+ {
+ "name": "Point",
+ "maxOccurs": 1,
+ "minOccurs": 0,
+ "nillable": true,
+ "type": "gml:Point",
+ "localType": "Point"
+ }
+ ]
+ }
+ ]
+
+ };
+ it('test createChangesTransaction for single edit', (done) => {
+ const singleChanges = {"TEST_LAYER.13": { "Integer": 50}};
+ const transactionPayload = createChangesTransaction(singleChanges, [], requestBuilder(describeFeatureType));
+ const samplePayload = `Integer50`;
+ expect(transactionPayload).toEqual(samplePayload);
+ done();
+ });
+ it('test createChangesTransaction for multi-edit', (done) => {
+ const multiChanges = {"TEST_LAYER.13": { "Integer": 50, "Long": 55 }};
+ const transactionPayload = createChangesTransaction(multiChanges, [], requestBuilder(describeFeatureType));
+ const multieditPayload = `Integer50,Long55`;
+ expect(transactionPayload).toEqual(multieditPayload);
+ done();
+ });
+ });
});