@@ -2,6 +2,8 @@ import L from "leaflet";
22import { useEffect , useState } from "react" ;
33import { FormattedMessage } from "react-intl" ;
44import { MapContainer , TileLayer , useMap } from "react-leaflet" ;
5+ import { getType } from "@turf/invariant" ;
6+ import { isFeature , isFeatureCollection } from "geojson-validation" ;
57import SvgSymbol from "../../SvgSymbol/SvgSymbol" ;
68import messages from "./Messages" ;
79import BoundsSelector from "./components/BoundsSelector" ;
@@ -190,33 +192,11 @@ const CustomPriorityBoundsField = (props) => {
190192 }
191193 } ;
192194
193- // Validate GeoJSON structure
194- const validateGeoJSON = ( geoJson ) => {
195- if ( ! geoJson || typeof geoJson !== "object" ) {
196- return { valid : false , error : "Invalid JSON format" } ;
197- }
198-
199- if ( ! Array . isArray ( geoJson . features ) ) {
200- return { valid : false , error : "Features must be an array" } ;
201- }
202-
203- const polygonFeatures = geoJson . features . filter (
204- ( feature ) =>
205- feature . type === "Feature" && feature . geometry && feature . geometry . type === "Polygon" ,
206- ) ;
207-
208- if ( polygonFeatures . length === 0 ) {
209- return { valid : false , error : "No valid Polygon features found" } ;
210- }
211-
212- return { valid : true , features : polygonFeatures } ;
213- } ;
214195
215196 // Handle file upload
216197 const handleFileUpload = async ( file ) => {
217198 setUploadFeedback ( null ) ;
218199
219- // Check file type
220200 const validExtensions = [ ".json" , ".geojson" ] ;
221201 const fileExtension = file . name . toLowerCase ( ) . substring ( file . name . lastIndexOf ( "." ) ) ;
222202
@@ -228,48 +208,44 @@ const CustomPriorityBoundsField = (props) => {
228208 try {
229209 const text = await file . text ( ) ;
230210 const geoJson = JSON . parse ( text ) ;
231-
232- const validation = validateGeoJSON ( geoJson ) ;
233- if ( ! validation . valid ) {
234- setUploadFeedback ( {
235- type : "error" ,
236- message : messages . invalidGeoJSON ,
237- details : validation . error ,
238- } ) ;
239- return ;
211+
212+ if ( ! isFeature ( geoJson ) && ! isFeatureCollection ( geoJson ) ) {
213+ throw new Error ( "Input must be a valid GeoJSON Feature or FeatureCollection" ) ;
214+ }
215+
216+ const features = getType ( geoJson ) === "Feature" ? [ geoJson ] : geoJson . features || [ ] ;
217+
218+ const polygonFeatures = features . filter (
219+ ( feature ) =>
220+ feature . type === "Feature" &&
221+ feature . geometry &&
222+ feature . geometry . type === "Polygon"
223+ ) ;
224+
225+ if ( polygonFeatures . length === 0 ) {
226+ throw new Error ( "No valid Polygon features found" ) ;
240227 }
241228
242- // Convert GeoJSON features to the format expected by the component
243- const convertedFeatures = validation . features . map ( ( feature ) => ( {
244- type : "Feature" ,
245- geometry : feature . geometry ,
246- properties : feature . properties || { } ,
247- } ) ) ;
248-
249- // Merge with existing data or replace
250- const newData = [ ...formData , ...convertedFeatures ] ;
229+ const newData = [ ...formData , ...polygonFeatures ] ;
251230 handleChange ( newData ) ;
252231
253232 setUploadFeedback ( {
254233 type : "success" ,
255234 message : messages . uploadSuccess ,
256- count : convertedFeatures . length ,
235+ count : polygonFeatures . length ,
257236 } ) ;
258237
259- // Show map if not already visible
260238 if ( ! isMapVisible ) {
261239 setIsMapVisible ( true ) ;
262240 }
263241
264- // Reset zoom flag to trigger auto-zoom to new polygons
265242 setHasZoomed ( false ) ;
266243
267- // Clear feedback after 3 seconds
268244 setTimeout ( ( ) => setUploadFeedback ( null ) , 3000 ) ;
269245 } catch ( error ) {
270246 setUploadFeedback ( {
271247 type : "error" ,
272- message : messages . uploadError ,
248+ message : messages . invalidGeoJSON ,
273249 details : error . message ,
274250 } ) ;
275251 }
@@ -363,8 +339,7 @@ const CustomPriorityBoundsField = (props) => {
363339 className = "mr-absolute mr-z-50 mr-text-white mr-text-sm"
364340 >
365341 < pre className = "mr-text-gray-300" >
366- < FormattedMessage { ...messages . geoJSONFormatInfo } /> :
367- { `\n{"features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[lng,lat],[lng,lat],...]]}}]}` }
342+ < FormattedMessage { ...messages . geoJSONFormatInfo } />
368343 </ pre >
369344 </ div >
370345 ) }
0 commit comments