Skip to content

Commit

Permalink
Merge pull request #140 from developmentseed/fix/add-layers-panel
Browse files Browse the repository at this point in the history
Reinstate layers panel
  • Loading branch information
LanesGood committed Mar 8, 2024
2 parents 57fa286 + 92ad349 commit 7d4da3e
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 181 deletions.
4 changes: 2 additions & 2 deletions app/assets/scripts/components/explore/explore.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { useApiLimits } from '../../context/global';
import { useSessionStatus } from '../../context/explore';
import { sessionModes } from '../../context/explore/session-status';
import { useParams } from 'react-router-dom';
import LayersPanel from './layers-panel';
// import LayersPanel from './layers-panel';

const ExploreBody = styled(InpageBody)`
display: grid;
Expand Down Expand Up @@ -75,7 +75,7 @@ function Explore() {
<ExploreCarto id='welcome-trigger'>
<Map />
</ExploreCarto>
<LayersPanel parentId='layer-control' className='padded' />
{/* <LayersPanel parentId='layer-control' className='padded' /> */}
<SecPanel />
</ExploreBody>
{steps && !isLoading && <Tour steps={steps} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@ import React, { useState, useEffect, useRef } from 'react';
import T from 'prop-types';
import styled, { css } from 'styled-components';
import { Button } from '@devseed-ui/button';
import InfoButton from '../../components/common/info-button';
import InfoButton from '../common/info-button';
import { Heading } from '@devseed-ui/typography';
import { themeVal, glsp } from '@devseed-ui/theme-provider';
import InputRange from 'react-input-range';
import { Accordion, AccordionFold as BaseFold } from '@devseed-ui/accordion';
import throttle from 'lodash.throttle';
import { useMapLayers, useUserLayers, useMapRef } from '../../context/map';
import { useMapState, useShortcutState } from '../../context/explore';
import { actions as shortcutActions } from '../../context/explore/shortcuts';
import { useCheckpoint } from '../../context/checkpoint';
import { round } from '../../utils/format';

export const LayersPanelInner = styled.div`
Expand Down Expand Up @@ -200,27 +196,14 @@ Category.propTypes = {
onVisibilityToggle: T.func,
};

function LayersPanel(props) {
const { className, parentId } = props;

const { mapState, mapModes } = useMapState();
const disabled = mapState.mode === mapModes.EDIT_AOI_MODE;

const { userLayers: baseUserLayers, setUserLayers } = useUserLayers();
const { shortcutState, dispatchShortcutState } = useShortcutState();

const userLayers = {
...baseUserLayers,
predictions: {
...baseUserLayers.predictions,
opacity: shortcutState.predictionLayerOpacity,
},
};

const { mapLayers } = useMapLayers();
const { mapRef } = useMapRef();
const { currentCheckpoint } = useCheckpoint();

function LayersPanel({
className,
parentId,
mapRef,
active,
mapLayers,
setMapLayers,
}) {
const [position, setPosition] = useState({});

const parentNodeQuery = document.getElementById(parentId);
Expand All @@ -230,16 +213,6 @@ function LayersPanel(props) {
parentNode.current = parentNodeQuery;
}, [parentNodeQuery]);

useEffect(() => {
setUserLayers({
...userLayers,
retrainingSamples: {
...userLayers.retrainingSamples,
active: currentCheckpoint && currentCheckpoint.retrain_geoms,
},
});
}, [currentCheckpoint && currentCheckpoint.retrain_geoms]);

useEffect(() => {
function updatePosition() {
if (parentNode.current) {
Expand All @@ -254,81 +227,58 @@ function LayersPanel(props) {
return () => mapRef && observer.unobserve(mapRef.getContainer());
}, [mapRef, parentNode]);

useEffect(() => {
parentNode.current = parentNodeQuery;
}, [parentNodeQuery]);

if (!parentNode) {
return null;
}

return (
<LayersPanelInner
className={className}
show={!disabled && shortcutState.layerTray}
show={active}
style={{
top: position.top || 0,
left: position.right || 0,
zIndex: 500,
}}
data-cy='layers-panel'
>
<Accordion
className={className}
allowMultiple
foldCount={2}
initialState={[true, true]}
foldCount={1}
initialState={[true]}
>
{
({ checkExpanded, setExpanded }) => (
<>
<Category
checkExpanded={() => checkExpanded(0)}
setExpanded={(v) => setExpanded(0, v)}
category='User Layers'
layers={userLayers}
onSliderChange={(layer, value) => {
setUserLayers({
...userLayers,
[layer.id]: {
...layer,
opacity: value,
visible: value > 0,
},
});

if (layer.id === 'predictions') {
dispatchShortcutState({
type: shortcutActions.UPDATE,
data: {
predictionLayerOpacity: value,
},
});
}
}}
onVisibilityToggle={(layer) => {
setUserLayers({
...userLayers,
[layer.id]: {
...layer,
visible: !layer.visible,
},
});
}}
/>

<Category
checkExpanded={() => checkExpanded(1)}
setExpanded={(v) => setExpanded(1, v)}
category='Map Layers'
layers={mapLayers}
onSliderChange={(layer, value) => {
layer.layer.setOpacity(value);
}}
onVisibilityToggle={(layer, value, sliderValue) => {
if (value) {
layer.layer.setOpacity(sliderValue);
} else {
layer.layer.setOpacity(0);
}
}}
/>
</>
<Category
checkExpanded={() => checkExpanded(1)}
setExpanded={(v) => setExpanded(1, v)}
category='Map Layers'
layers={mapLayers}
onSliderChange={(layer, value) => {
setMapLayers({
...mapLayers,
[layer.id]: {
...layer,
opacity: value,
visible: value > 0,
},
});
}}
onVisibilityToggle={(layer) => {
setMapLayers({
...mapLayers,
[layer.id]: {
...layer,
visible: !layer.visible,
},
});
}}
/>
)
/* eslint-disable-next-line react/jsx-curly-newline */
}
Expand All @@ -340,6 +290,10 @@ function LayersPanel(props) {
LayersPanel.propTypes = {
className: T.string,
parentId: T.string.isRequired,
active: T.bool,
mapLayers: T.object,
mapRef: T.object,
setMapLayers: T.func,
};

export default LayersPanel;
89 changes: 73 additions & 16 deletions app/assets/scripts/components/project/map/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
useMapEvent,
} from 'react-leaflet';

import LayersPanel from '../layers-panel';
import GenericControl from '../../common/map/generic-control';
import {
MAX_BASE_MAP_ZOOM_LEVEL,
BaseMapLayer,
Expand All @@ -29,16 +31,28 @@ import { RETRAIN_MAP_MODES } from '../../../fsm/project/constants';
import FreehandDrawControl from './freehand-draw-control';
import PolygonDrawControl from './polygon-draw-control';
import selectors from '../../../fsm/project/selectors';
import {
BOUNDS_PADDING,
MOSAIC_LAYER_OPACITY,
} from '../../common/map/constants';
import { BOUNDS_PADDING } from '../../common/map/constants';
import { getMosaicTileUrl } from '../../../utils/mosaics';

const center = [19.22819, -99.995841];
const zoom = 12;

const DEFAULT_PREDICTION_LAYER_OPACITY = 0.7;
const INITIAL_MAP_LAYERS = {
mosaic: {
id: 'mosaic',
name: 'Mosaic',
opacity: 1,
visible: true,
active: true,
},
predictions: {
id: 'predictions',
name: 'Prediction Results',
opacity: 1,
visible: true,
active: true,
},
};

const Container = styled.div`
height: 100%;
Expand Down Expand Up @@ -86,9 +100,8 @@ function Map() {

// Local state
const [mapRef, setMapRef] = useState();
const [predictionsOpacity, setPredictionsOpacity] = useState(
DEFAULT_PREDICTION_LAYER_OPACITY
);
const [mapLayers, setMapLayers] = useState(INITIAL_MAP_LAYERS);
const [showLayersControl, setShowLayersControl] = useState(false);

// FSM listeners
const actorRef = ProjectMachineContext.useActorRef();
Expand All @@ -111,7 +124,6 @@ function Map() {
const currentTilejson = ProjectMachineContext.useSelector(
selectors.currentTilejson
);

const currentMosaic = ProjectMachineContext.useSelector(
selectors.currentMosaic
);
Expand Down Expand Up @@ -164,16 +176,40 @@ function Map() {

if (e.key === 'a') {
// On "a" key press, reduce opacity to zero
setPredictionsOpacity(0);
setMapLayers((prev) => ({
...prev,
predictions: {
...prev.predictions,
opacity: 0,
},
}));
} else if (e.key === 's') {
// On "s" key press, reduce opacity by 10%
setPredictionsOpacity((prev) => prev - 0.1);
setMapLayers((prev) => ({
...prev,
predictions: {
...prev.predictions,
opacity: prev.predictions.opacity - 0.1,
},
}));
} else if (e.key === 'd') {
// On "d" key press, increase opacity by 10%
setPredictionsOpacity((prev) => prev + 0.1);
setMapLayers((prev) => ({
...prev,
predictions: {
...prev.predictions,
opacity: prev.predictions.opacity + 0.1,
},
}));
} else if (e.key === 'f') {
// On "f" key press, increase opacity to 100%
setPredictionsOpacity(1);
setMapLayers((prev) => ({
...prev,
predictions: {
...prev.predictions,
opacity: 1,
},
}));
} else if (e.key === ' ' || e.code === 'Space') {
// On space keypress, pan map to current aoi bounds
const aoiShape = currentAoiShape;
Expand Down Expand Up @@ -352,7 +388,7 @@ function Map() {
<TileLayer
key={mosaicTileUrl}
url={mosaicTileUrl}
opacity={MOSAIC_LAYER_OPACITY}
opacity={mapLayers.mosaic.visible ? mapLayers.mosaic.opacity : 0}
/>
)}

Expand All @@ -365,7 +401,9 @@ function Map() {
value: `Bearer ${apiToken}`,
},
]}
opacity={predictionsOpacity}
opacity={
mapLayers.predictions.visible ? mapLayers.predictions.opacity : 0
}
/>
)}

Expand All @@ -377,15 +415,34 @@ function Map() {
key={p.key}
url={p.image}
bounds={p.bounds}
opacity={predictionsOpacity}
opacity={
mapLayers.predictions.visible
? mapLayers.predictions.opacity
: 0
}
/>
))}
<FeatureGroup>
<GeoCoder />
{currentAoiShape && <CenterMap aoiRef={currentAoiShape} />}
<GenericControl
id='layer-control'
onClick={(e) => {
e.stopPropagation();
setShowLayersControl(!showLayersControl);
}}
/>
</FeatureGroup>
<ScaleControl />
</MapContainer>
<LayersPanel
mapRef={mapRef}
parentId='layer-control'
className='padded'
active={showLayersControl}
mapLayers={mapLayers}
setMapLayers={setMapLayers}
/>
</SizeAwareElement>
);
}
Expand Down
3 changes: 2 additions & 1 deletion app/assets/scripts/components/share-map/layers-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import T from 'prop-types';
import throttle from 'lodash.throttle';

import { Category, LayersPanelInner } from '../explore/layers-panel';
import { Category, LayersPanelInner } from '../project/layers-panel';
import { Accordion } from '@devseed-ui/accordion';

function LayersPanel({
Expand Down Expand Up @@ -42,6 +42,7 @@ function LayersPanel({
style={{
top: position.top || 0,
left: position.right || 0,
zIndex: 500,
}}
show={active}
data-cy='share-map-layers-panel'
Expand Down
Loading

0 comments on commit 7d4da3e

Please sign in to comment.