Skip to content

Commit

Permalink
Merge pull request #1506 from cphelefu/handling-layer-actions
Browse files Browse the repository at this point in the history
Handling layer actions (#1506)
  • Loading branch information
jolevesq authored Nov 21, 2023
2 parents 7d87269 + d5cae3e commit 0300c9a
Show file tree
Hide file tree
Showing 11 changed files with 267 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ export const getSxClasses = (theme: Theme) => ({
border: '2px solid #515BA5',
padding: '20px',
},
buttonDescriptionContainer: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center'
},
opacityMenu: {
display: 'flex',
alignItems: 'center',
Expand Down
42 changes: 38 additions & 4 deletions packages/geoview-core/src/core/components/layers/layers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { useEffect, useRef } from 'react';
import { useTheme } from '@mui/material/styles';
import { styled } from '@mui/material';
import { LegendItemsDetailsProps } from './types';
import { Box, Grid } from '@/ui';
import { Box, DeleteIcon, Grid, HandleIcon, IconButton, Paper } from '@/ui';
import { getSxClasses } from './layers-style';
import { useLegendHelpers } from './hooks/helpers';
import { LayersActions } from './left-panel/layers-actions';
import { LayersList } from './left-panel/layers-list';
import { LayerDetails } from './right-panel/layer-details';
import { useSelectedLayer } from '@/core/stores/store-interface-and-intial-values/layer-state';
import { useLayersDisplayState, useSelectedLayer } from '@/core/stores/store-interface-and-intial-values/layer-state';
import { AddNewLayer } from './left-panel/add-new-layer';

const Item = styled('div')(({ theme }) => ({
backgroundColor: theme.palette.mode === 'dark' ? '#262B32' : '#fff',
Expand All @@ -29,6 +30,7 @@ export function Layers(props: LegendItemsDetailsProps): JSX.Element {
const helpers = useLegendHelpers(mapId);

const selectedLayer = useSelectedLayer(); // get store value
const displayState = useLayersDisplayState();

useEffect(() => {
helpers.populateLegendStoreWithFakeData();
Expand All @@ -45,19 +47,51 @@ export function Layers(props: LegendItemsDetailsProps): JSX.Element {
return (
<div>
<LayersActions />
<LayersList />
{displayState === 'add' ? <AddNewLayer /> : <LayersList />}
</div>
);
};

const rightPanel = () => {
if (selectedLayer) {
if (selectedLayer && displayState === 'view') {
return (
<Item ref={layerDetailsRef}>
<LayerDetails layerDetails={selectedLayer} />
</Item>
);
}
if (displayState === 'remove') {
return (
<Paper sx={{ padding: '20px' }}>
<h3>Removing layers</h3>
<Box sx={sxClasses.rightPanel.buttonDescriptionContainer}>
<IconButton>
<DeleteIcon style={{ fill: '#a9a9a9' }} />
</IconButton>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Ipsum perspiciatis doloribus veritatis iste? Quae alias praesentium,
delectus reprehenderit itaque voluptatibus!
</p>
</Box>
</Paper>
);
}
if (displayState === 'order') {
return (
<Paper sx={{ padding: '20px' }}>
<h3>Re-ordering layers</h3>
<Box sx={sxClasses.rightPanel.buttonDescriptionContainer}>
<IconButton>
<HandleIcon style={{ fill: '#a9a9a9' }} />
</IconButton>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Praesentium animi, perferendis nemo quas sequi totam minima ad
labore.
</p>
</Box>
</Paper>
);
}

return null;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Paper } from '@/ui';

export function AddNewLayer(): JSX.Element {
return (
<Paper sx={{ padding: '20px', display: 'flex', flexDirection: 'column' }}>
<h3>This is the add new layer component</h3>
</Paper>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { useEffect, useState } from 'react';
import { Box, CircularProgressBase, DeleteOutlineIcon, IconButton, UndoIcon } from '@/ui';
import { TypeLegendLayer } from '../types';
import { useLayerStoreActions } from '@/core/stores/store-interface-and-intial-values/layer-state';

interface DeleteUndoButtonProps {
layer: TypeLegendLayer;
}

interface UndoButtonProps {
progressValue: number;
onUndo: () => void;
}

function UndoButtonWithProgress(props: UndoButtonProps): JSX.Element {
const { progressValue, onUndo } = props;
return (
<Box sx={{ position: 'relative', display: 'inline-flex' }} onClick={onUndo}>
<CircularProgressBase variant="determinate" size={40} value={progressValue} />
<Box
style={{
top: 0,
left: 0,
bottom: 0,
right: 0,
position: 'absolute',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<IconButton>
<UndoIcon />
</IconButton>
</Box>
</Box>
);
}

export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element {
const { layer } = props;

const [progress, setProgress] = useState(10);
const [inUndoState, setInUndoState] = useState(false);

// get store actions
const { deleteLayer } = useLayerStoreActions();

const handleDeleteClick = () => {
setInUndoState(true);
};

const handleUndoClick = () => {
setInUndoState(false);
};

useEffect(() => {
if (progress === 100) {
deleteLayer(layer.layerPath);
setInUndoState(false);
}
return undefined;
}, [progress]);

Check warning on line 63 in packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx

View workflow job for this annotation

GitHub Actions / Build demo files / build-geoview

React Hook useEffect has missing dependencies: 'deleteLayer' and 'layer.layerPath'. Either include them or remove the dependency array

useEffect(() => {
if (inUndoState) {
const timer = setInterval(() => {
setProgress((prevProgress) => (prevProgress >= 100 ? 0 : prevProgress + 5));
}, 250);
return () => {
clearInterval(timer);
};
}
setProgress(0);
return undefined;
}, [inUndoState]);

if (!inUndoState) {
return (
<IconButton onClick={handleDeleteClick}>
<DeleteOutlineIcon color="error" />
</IconButton>
);
}
return <UndoButtonWithProgress progressValue={progress} onUndo={handleUndoClick} />;
}
Original file line number Diff line number Diff line change
@@ -1,46 +1,54 @@
import { useTranslation } from 'react-i18next';
import { useTheme } from '@mui/material/styles';
import { Button } from '@mui/material';
import { Box, Typography, Stack, ExpandIcon, RemoveCircleOutlineIcon, AddCircleOutlineIcon } from '@/ui';
import { Box, Typography, AddCircleOutlineIcon, ButtonGroup, DeleteOutlineIcon, HandleIcon } from '@/ui';
import { getSxClasses } from '../layers-style';
import { useLayerStoreActions, useLayersDisplayState } from '@/core/stores/store-interface-and-intial-values/layer-state';
import { TypeLayersViewDisplayState } from '../types';

export function LayersActions(): JSX.Element {
const { t } = useTranslation<string>();

const theme = useTheme();
const sxClasses = getSxClasses(theme);

// access store
const displayState = useLayersDisplayState();
const { setDisplayState } = useLayerStoreActions();

const handleSetDisplayState = function (newState: TypeLayersViewDisplayState) {

Check warning on line 19 in packages/geoview-core/src/core/components/layers/left-panel/layers-actions.tsx

View workflow job for this annotation

GitHub Actions / Build demo files / build-geoview

Unexpected unnamed function
setDisplayState(newState);
};

return (
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '15px' }}>
<div>
<Typography sx={sxClasses.categoryTitle}>{t('general.layers')}</Typography>
</div>
<Stack style={{ alignItems: 'center', gap: '15px' }} direction="row">

<ButtonGroup size="small" variant="outlined" aria-label="outlined button group">
<Button
variant="contained"
size="small"
sx={{ backgroundColor: '#F4F5FF', borderRadius: '20px' }}
startIcon={<ExpandIcon fontSize="small" sx={{ color: '#515BA5' }} />}
variant={displayState === 'add' ? 'contained' : 'outlined'}
startIcon={<AddCircleOutlineIcon fontSize="small" />}
onClick={() => handleSetDisplayState('add')}
>
<Typography sx={sxClasses.legendButtonText}>{t('legend.re-arrange')}</Typography>
{t('general.add')}
</Button>
<Button
variant="contained"
size="small"
sx={{ backgroundColor: '#F4F5FF', borderRadius: '20px' }}
startIcon={<AddCircleOutlineIcon fontSize="small" sx={{ color: '#515BA5' }} />}
variant={displayState === 'order' ? 'contained' : 'outlined'}
startIcon={<HandleIcon fontSize="small" />}
onClick={() => handleSetDisplayState('order')}
>
<Typography sx={sxClasses.legendButtonText}>{t('general.add')}</Typography>
{t('legend.re-arrange')}
</Button>
<Button
variant="contained"
size="small"
sx={{ backgroundColor: '#F4F5FF', borderRadius: '20px' }}
startIcon={<RemoveCircleOutlineIcon fontSize="small" sx={{ color: '#515BA5' }} />}
variant={displayState === 'remove' ? 'contained' : 'outlined'}
startIcon={<DeleteOutlineIcon fontSize="small" />}
onClick={() => handleSetDisplayState('remove')}
>
<Typography sx={sxClasses.legendButtonText}>{t('general.remove')}</Typography>
{t('general.remove')}
</Button>
</Stack>
</ButtonGroup>
</Box>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,24 @@ import {
ListItemButton,
ListItemIcon,
ListItemText,
ListAltIcon,
Tooltip,
VisibilityOffOutlinedIcon,
VisibilityOutlinedIcon,
RestartAltIcon,
CircularProgressBase,
TableViewIcon,
HandleIcon,
} from '@/ui';
import { TypeLegendLayer } from '../types';
import { getSxClasses } from './layerslist-style';
import { useLayerStoreActions, useSelectedLayerPath } from '@/core/stores/store-interface-and-intial-values/layer-state';
import {
useLayerStoreActions,
useLayersDisplayState,
useSelectedLayerPath,
} from '@/core/stores/store-interface-and-intial-values/layer-state';
import { useDataTableStoreMapFilteredRecord } from '@/core/stores/store-interface-and-intial-values/data-table-state';
import { IconStack } from '../../icon-stack/icon-stack';
import { DeleteUndoButton } from './delete-undo-button';

interface SingleLayerProps {
layer: TypeLegendLayer;
Expand All @@ -44,9 +50,10 @@ export function SingleLayer(props: SingleLayerProps): JSX.Element {
const { toggleLayerVisibility, setSelectedLayerPath } = useLayerStoreActions(); // get store actions

const selectedLayerPath = useSelectedLayerPath(); // get store value
const displayState = useLayersDisplayState();
const mapFiltered = useDataTableStoreMapFilteredRecord();

const layerIsSelected = layer.layerPath === selectedLayerPath;
const layerIsSelected = layer.layerPath === selectedLayerPath && displayState === 'view';
const legendClass = layerIsSelected ? { ...sxClasses.layersList.selectedLayerItem } : null;

const [isGroupOpen, setGroupOpen] = useState(layerIsSelected);
Expand Down Expand Up @@ -99,6 +106,10 @@ export function SingleLayer(props: SingleLayerProps): JSX.Element {
console.log('reloading layer');

Check warning on line 106 in packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx

View workflow job for this annotation

GitHub Actions / Build demo files / build-geoview

Unexpected console statement
};

const handleReArrangeLayer = () => {
console.log('re-arrange layer');

Check warning on line 110 in packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx

View workflow job for this annotation

GitHub Actions / Build demo files / build-geoview

Unexpected console statement
};

// renders the layers children, if any
function renderChildren() {
if (!layer.children?.length) {
Expand All @@ -114,8 +125,22 @@ export function SingleLayer(props: SingleLayerProps): JSX.Element {
);
}

function renderEditModeButtons() {
if (displayState === 'remove') {
return <DeleteUndoButton layer={layer} />;
}
if (displayState === 'order') {
return (
<IconButton onClick={handleReArrangeLayer}>
<HandleIcon color="error" />
</IconButton>
);
}
return null;
}

function renderMoreLayerButtons() {
if (layer.layerStatus === 'loading') {
if (layer.layerStatus === 'loading' || displayState !== 'view') {
return null;
}
if (layer.layerStatus === 'error') {
Expand Down Expand Up @@ -147,7 +172,7 @@ export function SingleLayer(props: SingleLayerProps): JSX.Element {
</IconButton>
);
}
if (layer.items?.length) {
if (displayState === 'view' && layer.items?.length) {
return (
<IconButton onClick={handleLayerClick}>
<KeyboardArrowRightIcon />
Expand Down Expand Up @@ -193,7 +218,7 @@ export function SingleLayer(props: SingleLayerProps): JSX.Element {
}
return (
<IconButton color="success">
<ListAltIcon />
<IconStack layerPath={layer.layerPath} />
</IconButton>
);
}
Expand All @@ -209,6 +234,7 @@ export function SingleLayer(props: SingleLayerProps): JSX.Element {
<ListItemIcon style={{ justifyContent: 'right' }}>
{renderMoreLayerButtons()}
{renderArrowButtons()}
{renderEditModeButtons()}
</ListItemIcon>
</ListItemButton>
</ListItem>
Expand Down
2 changes: 2 additions & 0 deletions packages/geoview-core/src/core/components/layers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export interface TypeLegendItemDetailsProps {

/// //////////////////////////////////////////////////

export type TypeLayersViewDisplayState = 'remove' | 'add' | 'order' | 'view';

export type TypeLegendLayerIcon = {
iconType?: string;
iconImg?: string;
Expand Down
Loading

0 comments on commit 0300c9a

Please sign in to comment.