• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geosolutions-it / MapStore2 / 19290640856

12 Nov 2025 08:09AM UTC coverage: 76.931% (+0.02%) from 76.911%
19290640856

push

github

web-flow
Fix #11479 Add validation and support for editing restrictions in attribute table (#11483)

* Fix #11479 Add validation and support for editing restrictions in attribute table

* fix eslint errors

* code refactor

* enhance validation and add unit tests

* update unit test

---------

Co-authored-by: Suren <dsuren1@gmail.com>

32178 of 49976 branches covered (64.39%)

134 of 158 new or added lines in 15 files covered. (84.81%)

3 existing lines in 2 files now uncovered.

40001 of 51996 relevant lines covered (76.93%)

37.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.29
/web/client/plugins/featuregrid/hooks/useFeatureValidation.js
1
/*
2
 * Copyright 2025, GeoSolutions Sas.
3
 * All rights reserved.
4
 *
5
 * This source code is licensed under the BSD-style license found in the
6
 * LICENSE file in the root directory of this source tree.
7
 */
8

9
import { useMemo } from 'react';
10
import Ajv from 'ajv';
11
import { applyAllChanges, isPrimaryKeyField } from '../../../utils/FeatureGridUtils';
12

13
const ajv = new Ajv({ allErrors: true });
1✔
14

15
// Cache compiled validators to avoid recompiling on every render
16
const validatorCache = new Map();
1✔
17

18
/**
19
 * Get or compile a validator for the given schema
20
 * @param {object} schema - The JSON schema to validate against
21
 * @returns {function} The compiled AJV validator function
22
 */
23
const getValidator = (schema) => {
1✔
24
    if (!schema) return null;
17✔
25

26
    const key = JSON.stringify(schema);
14✔
27
    if (validatorCache.has(key)) return validatorCache.get(key);
14✔
28
    try {
8✔
29
        const validate = ajv.compile(schema);
8✔
30
        validatorCache.set(key, validate);
8✔
31
        return validate;
8✔
32
    } catch (error) {
NEW
33
        console.error('Error compiling JSON schema validator:', error);
×
NEW
34
        return null;
×
35
    }
36
};
37

38
const useFeatureValidation = ({
1✔
39
    featurePropertiesJSONSchema,
40
    newFeatures,
41
    features,
42
    changes,
43
    primaryKeyAttributes = []
14✔
44
}) => {
45
    const validate = useMemo(() => getValidator(featurePropertiesJSONSchema), [featurePropertiesJSONSchema]);
18✔
46

47
    const allFeatures = useMemo(() => {
18✔
48
        return newFeatures && newFeatures.length > 0
17✔
49
            ? [...newFeatures, ...features]
50
            : features;
51
    }, [newFeatures, features]);
52

53
    const validationErrors = useMemo(() => {
18✔
54
        if (!validate || !featurePropertiesJSONSchema) {
18✔
55
            return {};
3✔
56
        }
57

58
        // Create default null properties
59
        const defaultNullProperties = featurePropertiesJSONSchema?.properties
15✔
60
            ? Object.fromEntries(Object.keys(featurePropertiesJSONSchema.properties).map(key => [key, null]))
21✔
61
            : {};
62

63
        return Object.fromEntries(
15✔
64
            allFeatures
65
                .map((feature) => {
66
                    const { id, properties } = applyAllChanges(feature, changes) || {};
18!
67
                    if (!id) return null;
18✔
68

69
                    const valid = validate({ ...defaultNullProperties, ...properties });
17✔
70
                    if (!valid) {
17✔
71
                        // Filter out primary key errors
72
                        const errors = (validate.errors || []).filter(error => {
12!
73
                            // Extract field name from instancePath (e.g., "/fid" -> "fid")
74
                            const path = error.instancePath || error.dataPath || '';
13!
75
                            const fieldName = path.replace(/^[./]/, '');
13✔
76
                            return !isPrimaryKeyField(fieldName, primaryKeyAttributes);
13✔
77
                        });
78

79
                        // Only include this feature if there are non-primary-key errors
80
                        if (errors.length > 0) {
12✔
81
                            return [id, { errors, changed: !!changes[id] || feature._new }];
11✔
82
                        }
83
                    }
84
                    return null;
6✔
85
                })
86
                .filter(value => value)
18✔
87
        );
88
    }, [validate, allFeatures, changes, featurePropertiesJSONSchema, primaryKeyAttributes]);
89

90
    return validationErrors;
18✔
91
};
92

93
export default useFeatureValidation;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc