Skip to content

Commit 0d56e49

Browse files
authored
Merge pull request #29 from M3nin0/issue/geometry-store-revision
form: reviewing the Geometry Store concept and remove the EditableGeoJSONLayer
2 parents d61684c + 7710d98 commit 0d56e49

File tree

19 files changed

+440
-200
lines changed

19 files changed

+440
-200
lines changed

src/lib/base/event/DrawEventAssigner.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,16 @@ const assignMapDrawEvents = (mapContext, eventCallbackProvider) => {
103103
MapDrawEvents.onCut,
104104
DrawEventMethods.cut
105105
);
106+
107+
/**
108+
* Assigning `Leaflet.Map.layeradd` event
109+
* (for when the layers are reloaded from the formik in the map).
110+
*/
111+
mapContext.on('layeradd', ({ layer }) => {
112+
if (layer._map) {
113+
assignLayerDrawEvents(layer, eventCallbackProvider);
114+
}
115+
});
106116
};
107117

108118
export const DrawEventAssigner = {

src/lib/base/event/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@
77
*/
88

99
export * as DrawEventTypes from './DrawEventTypes';
10+
11+
export { useDrawEvents } from './useDrawEvents';
1012
export { DrawEventAssigner } from './DrawEventAssigner';
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* This file is part of GEO-Metadata-Previewer.
3+
* Copyright (C) 2022 GEO Secretariat.
4+
*
5+
* GEO-Metadata-Previewer is free software; you can redistribute it and/or modify it
6+
* under the terms of the MIT License; see LICENSE file for more details.
7+
*/
8+
9+
import React, { useEffect } from 'react';
10+
import PropTypes from 'prop-types';
11+
12+
import { useMap } from 'react-leaflet';
13+
import { DrawEventAssigner } from './DrawEventAssigner';
14+
15+
/**
16+
* Hook to enable the draw events in the map.
17+
*
18+
* @param {Object} eventsConfig Configuration object for the `DrawEventAssigner`.
19+
* @param {Function} onDefined Function callback called when all events are signed in the Leaflet map.
20+
* @returns {JSX.Element}
21+
*/
22+
export const useDrawEvents = (eventsConfig, onDefined) => {
23+
// hooks
24+
const mapContext = useMap();
25+
26+
useEffect(() => {
27+
// Defining the map level events (e.g., `pm:create` and `pm:cut`).
28+
29+
// Assigning create event.
30+
DrawEventAssigner.assignMapDrawEvents(mapContext, eventsConfig);
31+
32+
// Side effecting
33+
if (onDefined) {
34+
onDefined();
35+
}
36+
}, []); // avoiding re-rendering
37+
38+
return null;
39+
};
40+
41+
useDrawEvents.propTypes = {
42+
editorConfig: PropTypes.shape({
43+
onCreate: PropTypes.func,
44+
onCut: PropTypes.func,
45+
onEdit: PropTypes.func,
46+
onRemove: PropTypes.func,
47+
}).isRequired,
48+
onDefined: PropTypes.func,
49+
};
50+
51+
useDrawEvents.defaultProps = {
52+
editorConfig: {},
53+
onDefined: null,
54+
};

src/lib/base/geometry/mutators.js

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,54 @@ import _get from 'lodash/get';
1212
import _isEmpty from 'lodash/isEmpty';
1313
import _isNil from 'lodash/isNil';
1414

15+
/**
16+
* Generate the GeoJSON Geometry Object without using `multi` or `collection` types
17+
*
18+
* @param {Object} geometryObject GeoJSON Geometry object.
19+
*/
20+
const generateGeometryExploded = (geometryObject) => {
21+
// defining the types
22+
const typeRecursive = ['GeometryCollection'];
23+
24+
const typeUnique = ['Point', 'Polygon', 'LineString'];
25+
const typeMultiple = ['MultiPolygon', 'MultiPoint', 'MultiLineString'];
26+
27+
// auxiliary function
28+
const explodeGeometry = (geometry) => {
29+
const geometryType = _get(geometry, 'type');
30+
31+
if (typeUnique.includes(geometryType)) {
32+
return [geometry];
33+
}
34+
35+
if (typeMultiple.includes(geometryType)) {
36+
const geometryTypeUnique = geometryType.replace('Multi', '');
37+
const geometryCoordinates = _get(geometry, 'coordinates');
38+
39+
return geometryCoordinates.map((geometryCoordinate) => ({
40+
type: geometryTypeUnique,
41+
coordinates: geometryCoordinate,
42+
}));
43+
}
44+
45+
if (typeRecursive.includes(geometryType)) {
46+
return _get(geometryObject, 'geometries', []).map((geometry) =>
47+
explodeGeometry(geometry)
48+
);
49+
}
50+
};
51+
52+
return explodeGeometry(geometryObject).map((geometry) => {
53+
let geometryData = geometry;
54+
55+
if (Array.isArray(geometry)) {
56+
geometryData = geometryData[0];
57+
}
58+
59+
return generateGeoJSONFeature(geometryData);
60+
});
61+
};
62+
1563
/**
1664
* Generate a GeoJSON Geometry Object with the type based on
1765
* the content of the given geometries.
@@ -55,12 +103,12 @@ const generateGeoJSONGeometryObject = (geometries) => {
55103

56104
const generateGeometryObjectsFromFeatures = (featureData) => {
57105
// checking if is a feature or feature collection
58-
let extractedData = null;
106+
let extractedData = featureData;
59107
const featureType = _get(featureData, 'type');
60108

61109
if (featureType === 'Feature') {
62110
extractedData = [featureData];
63-
} else {
111+
} else if (featureType === 'FeatureCollection') {
64112
extractedData = featureData.features;
65113
}
66114

@@ -100,5 +148,6 @@ export const GeometryMutator = {
100148
generateGeoJSONGeometryObject,
101149
generateGeoJSONFeature,
102150
generateGeometryObjectsFromFeatures,
151+
generateGeometryExploded,
103152
isFeatureOrFeatureCollection,
104153
};

src/lib/components/form/fields/GeographicIdentifiersField.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export const GeographicIdentifiersField = ({
5454

5555
const prepareSuggest = (searchQuery) => {
5656
const limitTo = fieldState.limitTo;
57-
const prefix = limitTo === 'all' ? '' : `${limitTo}:`;
57+
const prefix = limitTo === 'all' ? '' : `${limitTo}::`;
5858

5959
return `${prefix}${searchQuery}`;
6060
};

src/lib/components/form/fields/GeometryField/GeometryField.js

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,18 @@ export const GeometryField = ({
6262
interactiveMapConfig,
6363
}) => {
6464
// States
65-
const [geometryStore, setGeometryStore] = useState(new GeometryStore());
6665
const [interactiveMapInitialized, setInteractiveMapInitialized] =
6766
useState(false);
6867
const [activatedBreadcrumb, setActivatedBreadcrumb] = useState('menu');
6968

69+
// Local store
70+
const geometryStore = new GeometryStore();
71+
7072
// Handlers
7173
const changeBreadcrumb = (breadcrumbName) =>
7274
setActivatedBreadcrumb(breadcrumbName);
7375

74-
const enableEmptyInteractiveMap = (formikProps) => () => {
76+
const enableEmptyInteractiveMap = () => {
7577
changeBreadcrumb('visualization');
7678
setInteractiveMapInitialized(true);
7779
};
@@ -82,15 +84,14 @@ export const GeometryField = ({
8284
};
8385

8486
const onDataLoadCallback = (formikProps) => {
85-
geometryStore.loadFormikProps(formikProps);
86-
8787
return (data) => {
88-
geometryStore.setGeometries(data);
88+
geometryStore.loadGeoJSON(data);
8989

9090
// Side effecting
91-
onDataLoad(data);
91+
changeBreadcrumb('visualization');
9292
setInteractiveMapInitialized(true);
93-
setActivatedBreadcrumb('visualization');
93+
94+
onDataLoad(data);
9495
};
9596
};
9697

@@ -109,9 +110,16 @@ export const GeometryField = ({
109110
return (
110111
<Field name={fieldPath}>
111112
{(formikProps) => {
113+
// Linking the geometry store with the formik storage
114+
geometryStore.loadFormikProps(formikProps);
115+
112116
// Checking if an initial values is defined.
113117
const initialValues = getIn(formikProps.form.values, fieldPath, {});
114118

119+
if (!_isEmpty(initialValues)) {
120+
enableEmptyInteractiveMap();
121+
}
122+
115123
return (
116124
<>
117125
{menu ? (
@@ -180,11 +188,10 @@ export const GeometryField = ({
180188
<Segment placeholder>
181189
{!menu ||
182190
(interactiveMapInitialized &&
183-
activatedBreadcrumb === 'visualization') ||
184-
!_isEmpty(initialValues) ? (
191+
activatedBreadcrumb === 'visualization') ? (
185192
<>
186193
<InteractiveMap
187-
formikProps={formikProps}
194+
geometryStore={geometryStore}
188195
{...interactiveMapConfig}
189196
/>
190197
</>
@@ -200,7 +207,7 @@ export const GeometryField = ({
200207
</Header>
201208
<Button
202209
content={i18next.t('Use')}
203-
onClick={enableEmptyInteractiveMap(formikProps)}
210+
onClick={enableEmptyInteractiveMap}
204211
/>
205212
</Grid.Column>
206213

0 commit comments

Comments
 (0)