diff --git a/app/scripts/components/common/map/controls/aoi/index.tsx b/app/scripts/components/common/map/controls/aoi/index.tsx index 4e1d968c3..66dd6f471 100644 --- a/app/scripts/components/common/map/controls/aoi/index.tsx +++ b/app/scripts/components/common/map/controls/aoi/index.tsx @@ -1,16 +1,16 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import MapboxDraw from '@mapbox/mapbox-gl-draw'; import { createGlobalStyle } from 'styled-components'; import { useAtomValue } from 'jotai'; import { useRef } from 'react'; import { useControl } from 'react-map-gl'; +import { Feature, Polygon } from 'geojson'; +import useAois from '../hooks/use-aois'; import { aoisFeaturesAtom } from './atoms'; +import { encodeAois } from '$utils/polygon-url'; type DrawControlProps = { - onCreate?: (evt: { features: object[] }) => void; - onUpdate?: (evt: { features: object[]; action: string }) => void; - onDelete?: (evt: { features: object[] }) => void; - onSelectionChange?: (evt: { selectedFeatures: object[] }) => void; + customFeatures: Feature[]; } & MapboxDraw.DrawOptions; const Css = createGlobalStyle` @@ -23,6 +23,19 @@ const Css = createGlobalStyle` export default function DrawControl(props: DrawControlProps) { const control = useRef(); const aoisFeatures = useAtomValue(aoisFeaturesAtom); + const { customFeatures } = props; + + const { onUpdate, onDelete, onSelectionChange } = useAois(); + + const serializedCustomFeatures = encodeAois(customFeatures); + useEffect(() => { + if (!customFeatures.length) return; + control.current?.add({ + type: 'FeatureCollection', + features: customFeatures + }); + // Look at serialized version to only update when the features change + }, [serializedCustomFeatures]); useControl( () => { @@ -30,10 +43,10 @@ export default function DrawControl(props: DrawControlProps) { return control.current; }, ({ map }: { map: any }) => { - map.on('draw.create', props.onCreate); - map.on('draw.update', props.onUpdate); - map.on('draw.delete', props.onDelete); - map.on('draw.selectionchange', props.onSelectionChange); + map.on('draw.create', onUpdate); + map.on('draw.update', onUpdate); + map.on('draw.delete', onDelete); + map.on('draw.selectionchange', onSelectionChange); map.on('load', () => { control.current?.set({ type: 'FeatureCollection', @@ -42,10 +55,10 @@ export default function DrawControl(props: DrawControlProps) { }); }, ({ map }: { map: any }) => { - map.off('draw.create', props.onCreate); - map.off('draw.update', props.onUpdate); - map.off('draw.delete', props.onDelete); - map.off('draw.selectionchange', props.onSelectionChange); + map.off('draw.create', onUpdate); + map.off('draw.update', onUpdate); + map.off('draw.delete', onDelete); + map.off('draw.selectionchange', onSelectionChange); }, { position: 'top-left' diff --git a/app/scripts/components/common/map/controls/custom-aoi-modal.tsx b/app/scripts/components/common/map/controls/custom-aoi-modal.tsx index 449b1c701..b387440e3 100644 --- a/app/scripts/components/common/map/controls/custom-aoi-modal.tsx +++ b/app/scripts/components/common/map/controls/custom-aoi-modal.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useRef } from 'react'; import styled from 'styled-components'; -import { Feature, FeatureCollection, Polygon } from 'geojson'; +import { Feature, Polygon } from 'geojson'; import { Modal, ModalHeadline, ModalFooter } from '@devseed-ui/modal'; import { Heading, Subtitle } from '@devseed-ui/typography'; @@ -117,7 +117,6 @@ export default function CustomAoIModal({ fileInfo, reset } = useCustomAoI(); - console.log(features) const fileInputRef = useRef(null); const onUploadClick = useCallback(() => { diff --git a/app/scripts/components/common/map/controls/hooks/use-aois.ts b/app/scripts/components/common/map/controls/hooks/use-aois.ts index ece9a9e70..66668ef1f 100644 --- a/app/scripts/components/common/map/controls/hooks/use-aois.ts +++ b/app/scripts/components/common/map/controls/hooks/use-aois.ts @@ -2,7 +2,12 @@ import { useAtomValue, useSetAtom } from 'jotai'; import { useCallback } from 'react'; import { Feature, Polygon } from 'geojson'; import { toAoIid } from '../../utils'; -import { aoisDeleteAtom, aoisFeaturesAtom, aoisSetSelectedAtom, aoisUpdateGeometryAtom } from '../aoi/atoms'; +import { + aoisDeleteAtom, + aoisFeaturesAtom, + aoisSetSelectedAtom, + aoisUpdateGeometryAtom +} from '../aoi/atoms'; export default function useAois() { const features = useAtomValue(aoisFeaturesAtom); @@ -11,8 +16,8 @@ export default function useAois() { const update = useCallback( (features: Feature[]) => { aoisUpdateGeometry(features); - } - , [aoisUpdateGeometry] + }, + [aoisUpdateGeometry] ); const onUpdate = useCallback( (e) => { diff --git a/app/scripts/components/common/map/controls/hooks/use-custom-aoi.tsx b/app/scripts/components/common/map/controls/hooks/use-custom-aoi.tsx index eb2f34551..d3e0f194f 100644 --- a/app/scripts/components/common/map/controls/hooks/use-custom-aoi.tsx +++ b/app/scripts/components/common/map/controls/hooks/use-custom-aoi.tsx @@ -1,4 +1,4 @@ -import { Feature, FeatureCollection, MultiPolygon, Polygon } from 'geojson'; +import { Feature, MultiPolygon, Polygon } from 'geojson'; import { useCallback, useEffect, useRef, useState } from 'react'; import shp from 'shpjs'; import simplify from '@turf/simplify'; @@ -26,8 +26,7 @@ function useCustomAoI() { const [uploadFileError, setUploadFileError] = useState(null); const [uploadFileWarnings, setUploadFileWarnings] = useState([]); const reader = useRef(); - const [features, setFeatures] = - useState[] | null>(null); + const [features, setFeatures] = useState[] | null>(null); useEffect(() => { reader.current = new FileReader(); @@ -158,7 +157,7 @@ function useCustomAoI() { setUploadFileError(null); setFeatures( simplifiedFeatures.map((feat, i) => ({ - id: `aoi-${i}`, + id: `${new Date().getTime().toString().slice(-4)}${i}`, ...feat })) ); diff --git a/app/scripts/components/exploration/components/map/index.tsx b/app/scripts/components/exploration/components/map/index.tsx index 23a14d39c..67e66da79 100644 --- a/app/scripts/components/exploration/components/map/index.tsx +++ b/app/scripts/components/exploration/components/map/index.tsx @@ -1,6 +1,7 @@ import React, { useState } from 'react'; import { useAtomValue } from 'jotai'; import { addMonths } from 'date-fns'; +import { Feature, Polygon } from 'geojson'; import { useStacMetadataOnDatasets } from '../../hooks/use-stac-metadata-datasets'; import { selectedDateAtom, timelineDatasetsAtom } from '../../atoms/atoms'; @@ -9,7 +10,6 @@ import { TimelineDatasetSuccess } from '../../types.d.ts'; import { Layer } from './layer'; - import Map, { Compare } from '$components/common/map'; import { Basemap } from '$components/common/map/style-generators/basemap'; import GeocoderControl from '$components/common/map/controls/geocoder'; @@ -21,7 +21,6 @@ import { useBasemap } from '$components/common/map/controls/hooks/use-basemap'; import DrawControl from '$components/common/map/controls/aoi'; import useAois from '$components/common/map/controls/hooks/use-aois'; import CustomAoIControl from '$components/common/map/controls/aoi/custom-aoi-control'; -import { Feature, Polygon } from 'geojson'; export function ExplorationMap(props: { comparing: boolean }) { const [projection, setProjection] = useState(projectionDefault); @@ -50,10 +49,14 @@ export function ExplorationMap(props: { comparing: boolean }) { .slice() .reverse(); - const { update, onUpdate, onDelete, onSelectionChange } = useAois(); + const { update } = useAois(); + const [customAoIFeatures, setCustomAoIFeatures] = useState< + Feature[] + >([]); const onCustomAoIConfirm = (features: Feature[]) => { update(features); + setCustomAoIFeatures(features); }; return ( @@ -83,10 +86,7 @@ export function ExplorationMap(props: { comparing: boolean }) { trash: true } as any } - onCreate={onUpdate} - onUpdate={onUpdate} - onDelete={onDelete} - onSelectionChange={onSelectionChange} + customFeatures={customAoIFeatures} />