Skip to content

Commit

Permalink
refactor(legend): Simplify the code and tweak performance
Browse files Browse the repository at this point in the history
Closes #2660
  • Loading branch information
jolevesq committed Dec 13, 2024
1 parent e669a5a commit 65f23d2
Show file tree
Hide file tree
Showing 5 changed files with 270 additions and 213 deletions.
12 changes: 0 additions & 12 deletions packages/geoview-core/public/configs/navigator/28-geocore.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,6 @@
{
"geoviewLayerType": "geoCore",
"geoviewLayerId": "ccc75c12-5acc-4a6a-959f-ef6f621147b9"
},
{
"geoviewLayerType": "geoCore",
"geoviewLayerId": "0fca08b5-e9d0-414b-a3c4-092ff9c5e326"
},
{
"geoviewLayerType": "geoCore",
"geoviewLayerId": "03ccfb5c-a06e-43e3-80fd-09d4f8f69703"
},
{
"geoviewLayerType": "geoCore",
"geoviewLayerId": "6433173f-bca8-44e6-be8e-3e8a19d3c299"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { useTheme } from '@mui/material';
import { memo } from 'react';
import { Box, Collapse, List } from '@/ui';
import { TypeLegendLayer } from '@/core/components/layers/types';
import { getSxClasses } from './legend-styles';
import { logger } from '@/core/utils/logger';
import { CV_CONST_LAYER_TYPES } from '@/api/config/types/config-constants';
import { ItemsList } from './legend-layer-items';

// Define component types and interfaces
type LegendLayerType = React.FC<{ layer: TypeLegendLayer }>;

interface CollapsibleContentProps {
layer: TypeLegendLayer;
legendExpanded: boolean;
initLightBox: (imgSrc: string, title: string, index: number, total: number) => void;
childLayers: TypeLegendLayer[];
items: TypeLegendLayer['items'];
LegendLayerComponent: LegendLayerType;
}

// CollapsibleContent component moved after LegendLayer
export const CollapsibleContent = memo(function CollapsibleContent({
layer,
legendExpanded,
initLightBox,
childLayers,
items,
LegendLayerComponent,
}: CollapsibleContentProps) {
logger.logDebug('legend1 collapsible', layer, childLayers, items);
const theme = useTheme();
const sxClasses = getSxClasses(theme);

if (layer.type === CV_CONST_LAYER_TYPES.WMS && layer.icons.length && layer.icons[0].iconImage && layer.icons[0].iconImage !== 'no data') {
const imgSrc = layer.icons[0].iconImage;
return (
<Collapse in={legendExpanded} sx={sxClasses.collapsibleContainer} timeout="auto">
<Box
component="img"
tabIndex={0}
src={imgSrc}
sx={{ maxWidth: '100%', cursor: 'pointer' }}
onClick={() => initLightBox(imgSrc, '', 0, 2)}
onKeyDown={(e) => (e.code === 'Space' || e.code === 'Enter' ? initLightBox(imgSrc, '', 0, 2) : null)}
/>
</Collapse>
);
}

// if (!(childLayers?.length > 1 || items?.length > 1)) {
// return null;
// }

// TODO: childslayers always empty... seems to be use for items
return (
<Collapse in={legendExpanded} sx={sxClasses.collapsibleContainer} timeout="auto">
{layer.children?.length > 0 && (
<List sx={{ width: '100%', padding: '20px', margin: '20px 0px' }}>
{layer.children
.filter((d) => !['error', 'processing'].includes(d.layerStatus ?? ''))
.map((item) => (
<LegendLayerComponent layer={item} key={item.layerPath} />
))}
</List>
)}
<ItemsList items={items} />
</Collapse>
);
});
111 changes: 111 additions & 0 deletions packages/geoview-core/src/core/components/legend/legend-layer-ctrl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { useTheme } from '@mui/material';
import { memo, useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
Box,
IconButton,
Stack,
VisibilityOutlinedIcon,
HighlightOutlinedIcon,
ZoomInSearchIcon,
Typography,
VisibilityOffOutlinedIcon,
HighlightIcon,
} from '@/ui';
import { useLayerHighlightedLayer, useLayerStoreActions } from '@/core/stores/store-interface-and-intial-values/layer-state';
import { TypeLegendLayer } from '@/core/components/layers/types';
import { useMapStoreActions } from '@/core/stores/';
import { getSxClasses } from './legend-styles';
import { logger } from '@/core/utils/logger';

interface SecondaryControlsProps {
layer: TypeLegendLayer;
layerStatus: string;
itemsLength: number;
childLayers: TypeLegendLayer[];
}

// SecondaryControls component
export const SecondaryControls = memo(function SecondaryControls({ layer, layerStatus, itemsLength, childLayers }: SecondaryControlsProps) {
logger.logDebug('legend1 - ctrl', layer, layerStatus, itemsLength, childLayers);
// Hooks
const { t } = useTranslation();
const theme = useTheme();
const sxClasses = getSxClasses(theme);

// Stores
const highlightedLayer = useLayerHighlightedLayer();
const { getVisibilityFromOrderedLayerInfo, setOrToggleLayerVisibility } = useMapStoreActions();
const { setHighlightLayer, zoomToLayerExtent } = useLayerStoreActions();

const [visibility, setVisibility] = useState(getVisibilityFromOrderedLayerInfo(layer.layerPath));
const isLayerVisible = layer.controls?.visibility ?? false;

// #region Handlers
const handleToggleVisibility = useCallback(
(e: React.MouseEvent<HTMLButtonElement>): void => {
e.stopPropagation();
setOrToggleLayerVisibility(layer.layerPath);
setVisibility(getVisibilityFromOrderedLayerInfo(layer.layerPath));
},
[layer.layerPath, setOrToggleLayerVisibility]

Check warning on line 51 in packages/geoview-core/src/core/components/legend/legend-layer-ctrl.tsx

View workflow job for this annotation

GitHub Actions / Build demo files / build-geoview

React Hook useCallback has a missing dependency: 'getVisibilityFromOrderedLayerInfo'. Either include it or remove the dependency array
);

const handleHighlightLayer = useCallback(
(e: React.MouseEvent<HTMLButtonElement>): void => {
e.stopPropagation();
setHighlightLayer(layer.layerPath);
},
[layer.layerPath, setHighlightLayer]
);

const handleZoomTo = useCallback(
(e: React.MouseEvent<HTMLButtonElement>): void => {
e.stopPropagation();
zoomToLayerExtent(layer.layerPath).catch((error) => {
logger.logPromiseFailed('in zoomToLayerExtent in legend-layer.handleZoomTo', error);
});
},
[layer.layerPath, zoomToLayerExtent]
);
// #endregion Handlers

if (!['processed', 'loaded'].includes(layerStatus)) {
return <Box />;
}

let subTitle = '';
if (childLayers.length) {
subTitle = t('legend.subLayersCount').replace('{count}', childLayers.length.toString());
} else if (itemsLength > 1) {
subTitle = t('legend.itemsCount').replace('{count}', itemsLength.toString()).replace('{totalCount}', itemsLength.toString());
}

return (
<Stack direction="row" alignItems="center" sx={sxClasses.layerStackIcons}>
{!!subTitle.length && <Typography fontSize={14}>{subTitle}</Typography>}
<Box>
<IconButton
edge="end"
tooltip="layers.toggleVisibility"
className="buttonOutline"
onClick={handleToggleVisibility}
disabled={!isLayerVisible}
>
{visibility ? <VisibilityOffOutlinedIcon /> : <VisibilityOutlinedIcon />}
</IconButton>
<IconButton
tooltip="legend.highlightLayer"
sx={{ marginTop: '-0.3125rem' }}
className="buttonOutline"
onClick={handleHighlightLayer}
>
{highlightedLayer === layer.layerPath ? <HighlightIcon /> : <HighlightOutlinedIcon />}
</IconButton>
<IconButton tooltip="legend.zoomTo" className="buttonOutline" onClick={handleZoomTo}>
<ZoomInSearchIcon />
</IconButton>
</Box>
</Stack>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useTheme } from '@mui/material';
import { memo } from 'react';
import { Box, ListItem, Tooltip, ListItemText, ListItemIcon, List, BrowserNotSupportedIcon } from '@/ui';
import { TypeLegendLayer } from '@/core/components/layers/types';
import { getSxClasses } from './legend-styles';
import { logger } from '@/core/utils/logger';

interface ItemsListProps {
items: TypeLegendLayer['items'];
}

// ItemsList component
export const ItemsList = memo(function ItemsList({ items }: ItemsListProps) {
logger.logDebug('legend1 item list', items);

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

if (!items?.length) {
return null;
}

return (
<List sx={sxClasses.subList}>
{items.map((item, index) => (
<ListItem key={`${item.icon}/${item.name}/${index}`} className={!item.isVisible ? 'unchecked' : 'checked'}>

Check failure on line 27 in packages/geoview-core/src/core/components/legend/legend-layer-items.tsx

View workflow job for this annotation

GitHub Actions / Build demo files / build-geoview

Do not use Array index in keys
<ListItemIcon>{item.icon ? <Box component="img" alt={item.name} src={item.icon} /> : <BrowserNotSupportedIcon />}</ListItemIcon>
<Tooltip title={item.name} placement="top" enterDelay={1000}>
<ListItemText primary={item.name} />
</Tooltip>
</ListItem>
))}
</List>
);
});
Loading

0 comments on commit 65f23d2

Please sign in to comment.