diff --git a/app/scripts/components/common/map/controls/aoi/atoms.ts b/app/scripts/components/common/map/controls/aoi/atoms.ts index 2d49280d9..0b85f5710 100644 --- a/app/scripts/components/common/map/controls/aoi/atoms.ts +++ b/app/scripts/components/common/map/controls/aoi/atoms.ts @@ -66,3 +66,7 @@ export const aoisDeleteAtom = atom(null, (get, set, ids: string[]) => { ); set(aoisSerialized, encodeAois(newFeatures)); }); + +export const aoiDeleteAllAtom = atom(null, (get, set) => { + set(aoisSerialized, encodeAois([])); +}); \ No newline at end of file diff --git a/app/scripts/components/common/map/controls/aoi/custom-aoi-control.tsx b/app/scripts/components/common/map/controls/aoi/custom-aoi-control.tsx index 0618def36..0734bc146 100644 --- a/app/scripts/components/common/map/controls/aoi/custom-aoi-control.tsx +++ b/app/scripts/components/common/map/controls/aoi/custom-aoi-control.tsx @@ -4,8 +4,9 @@ import { CollecticonUpload2 } from '@devseed-ui/collecticons'; import { Button, createButtonStyles } from '@devseed-ui/button'; import styled from 'styled-components'; import { themeVal } from '@devseed-ui/theme-provider'; +import useMaps from '../../hooks/use-maps'; import useThemedControl from '../hooks/use-themed-control'; -import CustomAoIModal from '../custom-aoi-modal'; +import CustomAoIModal from './custom-aoi-modal'; const SelectorButton = styled(Button)` &&& { @@ -20,12 +21,18 @@ const SelectorButton = styled(Button)` } `; -interface CustomAoIProps { - onConfirm: (features: Feature[]) => void; -} - -function CustomAoI({ onConfirm }: CustomAoIProps) { +function CustomAoI({ map }: { map: any }) { const [aoiModalRevealed, setAoIModalRevealed] = useState(false); + + const onConfirm = (features: Feature[]) => { + const mbDraw = map?._drawControl; + setAoIModalRevealed(false); + if (!mbDraw) return; + mbDraw.add({ + type: 'FeatureCollection', + features + }); + }; return ( <> setAoIModalRevealed(true)}> @@ -40,8 +47,9 @@ function CustomAoI({ onConfirm }: CustomAoIProps) { ); } -export default function CustomAoIControl(props: CustomAoIProps) { - useThemedControl(() => , { +export default function CustomAoIControl() { + const { main } = useMaps(); + useThemedControl(() => , { position: 'top-left' }); return null; diff --git a/app/scripts/components/common/map/controls/custom-aoi-modal.tsx b/app/scripts/components/common/map/controls/aoi/custom-aoi-modal.tsx similarity index 98% rename from app/scripts/components/common/map/controls/custom-aoi-modal.tsx rename to app/scripts/components/common/map/controls/aoi/custom-aoi-modal.tsx index b387440e3..013d467be 100644 --- a/app/scripts/components/common/map/controls/custom-aoi-modal.tsx +++ b/app/scripts/components/common/map/controls/aoi/custom-aoi-modal.tsx @@ -19,7 +19,7 @@ import { CollecticonCircleTick, CollecticonCircleInformation } from '@devseed-ui/collecticons'; -import useCustomAoI, { acceptExtensions } from './hooks/use-custom-aoi'; +import useCustomAoI, { acceptExtensions } from '../hooks/use-custom-aoi'; import { variableGlsp, variableProseVSpace } from '$styles/variable-utils'; const UploadFileModalFooter = styled(ModalFooter)` diff --git a/app/scripts/components/common/map/controls/aoi/index.tsx b/app/scripts/components/common/map/controls/aoi/index.tsx index 66dd6f471..cbf0f4499 100644 --- a/app/scripts/components/common/map/controls/aoi/index.tsx +++ b/app/scripts/components/common/map/controls/aoi/index.tsx @@ -1,17 +1,13 @@ -import React, { useEffect } from 'react'; +import React 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 = { - customFeatures: Feature[]; -} & MapboxDraw.DrawOptions; +type DrawControlProps = MapboxDraw.DrawOptions; const Css = createGlobalStyle` .mapbox-gl-draw_trash { @@ -23,26 +19,17 @@ const Css = createGlobalStyle` export default function DrawControl(props: DrawControlProps) { const control = useRef(); const aoisFeatures = useAtomValue(aoisFeaturesAtom); - const { customFeatures } = props; + const areSelectedFeatures = aoisFeatures.some((f) => f.selected); 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( () => { control.current = new MapboxDraw(props); return control.current; }, ({ map }: { map: any }) => { + map._drawControl = control.current; map.on('draw.create', onUpdate); map.on('draw.update', onUpdate); map.on('draw.delete', onDelete); @@ -65,5 +52,5 @@ export default function DrawControl(props: DrawControlProps) { } ); - return aoisFeatures.length ? null : ; + return areSelectedFeatures ? null : ; } diff --git a/app/scripts/components/common/map/controls/aoi/reset-aoi-control.tsx b/app/scripts/components/common/map/controls/aoi/reset-aoi-control.tsx new file mode 100644 index 000000000..47067af02 --- /dev/null +++ b/app/scripts/components/common/map/controls/aoi/reset-aoi-control.tsx @@ -0,0 +1,57 @@ +import React, { useCallback } from 'react'; +import { CollecticonArrowLoop } from '@devseed-ui/collecticons'; +import { Button } from '@devseed-ui/button'; +import styled from 'styled-components'; +import { useAtomValue, useSetAtom } from 'jotai'; +import { themeVal } from '@devseed-ui/theme-provider'; +import useThemedControl from '../hooks/use-themed-control'; +import useMaps from '../../hooks/use-maps'; +import { aoiDeleteAllAtom, aoisFeaturesAtom } from './atoms'; + +const SelectorButton = styled(Button)` + &&& { + background-color: ${themeVal('color.surface')}; + + &:hover { + background-color: ${themeVal('color.surface')}; + } + } +`; + +function ResetAoI({ map }: { map: any }) { + const aoiDeleteAll = useSetAtom(aoiDeleteAllAtom); + const aoisFeatures = useAtomValue(aoisFeaturesAtom); + + const onReset = useCallback(() => { + const mbDraw = map?._drawControl; + if (!mbDraw) return; + mbDraw.deleteAll(); + aoiDeleteAll(); + }, [map, aoiDeleteAll]); + + return ( + <> + + + + + ); +} + +export default function ResetAoIControl() { + const { main } = useMaps(); + useThemedControl( + () => { + return ; + }, + { + position: 'top-left' + } + ); + return null; +} diff --git a/app/scripts/components/common/map/hooks/use-maps.ts b/app/scripts/components/common/map/hooks/use-maps.ts index 3433fa1b8..0ab679a5d 100644 --- a/app/scripts/components/common/map/hooks/use-maps.ts +++ b/app/scripts/components/common/map/hooks/use-maps.ts @@ -18,6 +18,6 @@ export default function useMaps() { return { main, compared, - current + current, }; } diff --git a/app/scripts/components/exploration/components/map/index.tsx b/app/scripts/components/exploration/components/map/index.tsx index 307d092af..3810ba3fd 100644 --- a/app/scripts/components/exploration/components/map/index.tsx +++ b/app/scripts/components/exploration/components/map/index.tsx @@ -1,6 +1,5 @@ import React, { useState } from 'react'; import { useAtomValue } from 'jotai'; -import { Feature, Polygon } from 'geojson'; import { useStacMetadataOnDatasets } from '../../hooks/use-stac-metadata-datasets'; import { selectedCompareDateAtom, selectedDateAtom, timelineDatasetsAtom } from '../../atoms/atoms'; @@ -20,8 +19,8 @@ import MapOptionsControl from '$components/common/map/controls/map-options'; import { projectionDefault } from '$components/common/map/controls/map-options/projections'; 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 ResetAoIControl from '$components/common/map/controls/aoi/reset-aoi-control'; export function ExplorationMap() { const [projection, setProjection] = useState(projectionDefault); @@ -53,16 +52,6 @@ export function ExplorationMap() { .slice() .reverse(); - const { update } = useAois(); - - const [customAoIFeatures, setCustomAoIFeatures] = useState< - Feature[] - >([]); - const onCustomAoIConfirm = (features: Feature[]) => { - update(features); - setCustomAoIFeatures(features); - }; - return ( {/* Map layers */} @@ -90,9 +79,9 @@ export function ExplorationMap() { trash: true } as any } - customFeatures={customAoIFeatures} /> - + +