diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts index 07fd1e821ba..c49ceff5a22 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts @@ -557,8 +557,12 @@ export class MapEventProcessor extends AbstractEventProcessor { * @param {string} layerPath - The path of the layer to get. * @returns {TypeOrderedLayerInfo | undefined} The ordered layer info. */ - static getMapOrderedLayerInfoForLayer(mapId: string, layerPath: string): TypeOrderedLayerInfo | undefined { - return this.getMapStateProtected(mapId).orderedLayerInfo.find((orderedLayerInfo) => orderedLayerInfo.layerPath === layerPath); + static findMapLayerFromOrderedInfo( + mapId: string, + layerPath: string, + orderedLayerInfo: TypeOrderedLayerInfo[] = this.getMapStateProtected(mapId).orderedLayerInfo + ): TypeOrderedLayerInfo | undefined { + return orderedLayerInfo.find((layer) => layer.layerPath === layerPath); } /** @@ -568,14 +572,12 @@ export class MapEventProcessor extends AbstractEventProcessor { * @param {TypeOrderedLayerInfo[]} orderedLayerInfo - The array of ordered layer info to search, default is current ordered layer info. * @returns {TypeOrderedLayerInfo[] | undefined} The ordered layer info of the layer and its children. */ - static getMapLayerAndChildrenOrderedInfo( + static findMapLayerAndChildrenFromOrderedInfo( mapId: string, layerPath: string, orderedLayerInfo: TypeOrderedLayerInfo[] = this.getMapStateProtected(mapId).orderedLayerInfo ): TypeOrderedLayerInfo[] { - return orderedLayerInfo.filter( - (info: TypeOrderedLayerInfo) => info.layerPath.startsWith(`${layerPath}/`) || info.layerPath === layerPath - ); + return orderedLayerInfo.filter((layer) => layer.layerPath.startsWith(`${layerPath}/`) || layer.layerPath === layerPath); } static getMapIndexFromOrderedLayerInfo(mapId: string, layerPath: string): number { @@ -771,7 +773,7 @@ export class MapEventProcessor extends AbstractEventProcessor { : (geoviewLayerConfig as TypeLayerEntryConfig).layerPath; const pathToSearch = layerPathToReplace || layerPath; const index = this.getMapIndexFromOrderedLayerInfo(mapId, pathToSearch); - const replacedLayers = this.getMapLayerAndChildrenOrderedInfo(mapId, pathToSearch); + const replacedLayers = this.findMapLayerAndChildrenFromOrderedInfo(mapId, pathToSearch); const newOrderedLayerInfo = LayerApi.generateArrayOfLayerOrderInfo(geoviewLayerConfig); orderedLayerInfo.splice(index, replacedLayers.length, ...newOrderedLayerInfo); @@ -1090,7 +1092,7 @@ export class MapEventProcessor extends AbstractEventProcessor { ): TypeLayerEntryConfig { // Get needed info const layerEntryConfig = MapEventProcessor.getMapViewerLayerAPI(mapId).getLayerEntryConfig(layerPath); - const orderedLayerInfo = MapEventProcessor.getMapOrderedLayerInfoForLayer(mapId, layerPath); + const orderedLayerInfo = MapEventProcessor.findMapLayerFromOrderedInfo(mapId, layerPath); const legendLayerInfo = LegendEventProcessor.getLegendLayerInfo(mapId, layerPath); // Get original layerEntryConfig from map config @@ -1171,7 +1173,7 @@ export class MapEventProcessor extends AbstractEventProcessor { const layerEntryConfig = MapEventProcessor.getMapViewerLayerAPI(mapId).getLayerEntryConfig(layerPath)!; const { geoviewLayerConfig } = layerEntryConfig; - const orderedLayerInfo = MapEventProcessor.getMapOrderedLayerInfoForLayer(mapId, layerPath); + const orderedLayerInfo = MapEventProcessor.findMapLayerFromOrderedInfo(mapId, layerPath); const legendLayerInfo = LegendEventProcessor.getLegendLayerInfo(mapId, layerPath); // Check if the layer is a geocore layers diff --git a/packages/geoview-core/src/core/components/attribution/attribution.tsx b/packages/geoview-core/src/core/components/attribution/attribution.tsx index c0a5bc58a55..b8085d5a9ac 100644 --- a/packages/geoview-core/src/core/components/attribution/attribution.tsx +++ b/packages/geoview-core/src/core/components/attribution/attribution.tsx @@ -58,7 +58,7 @@ export const Attribution = memo(function Attribution(): JSX.Element { }; // Memoize values - const attributionContent = useMemo( + const memoAttributionContent = useMemo( () => mapAttribution.map((attribution) => {attribution}), [mapAttribution] ); @@ -96,7 +96,7 @@ export const Attribution = memo(function Attribution(): JSX.Element { }} onClose={handleClosePopover} > - {attributionContent} + {memoAttributionContent} ); diff --git a/packages/geoview-core/src/core/components/common/layer-icon.tsx b/packages/geoview-core/src/core/components/common/layer-icon.tsx index 57d82c1d3f2..6a24d73c951 100644 --- a/packages/geoview-core/src/core/components/common/layer-icon.tsx +++ b/packages/geoview-core/src/core/components/common/layer-icon.tsx @@ -10,7 +10,7 @@ import { LayerListEntry } from '.'; export interface TypeIconStackProps { layerPath: string; onIconClick?: () => void; - onStackIconClick?: (e: React.KeyboardEvent) => void; + onStackIconClick?: (event: React.KeyboardEvent) => void; } interface LayerIconProps { diff --git a/packages/geoview-core/src/core/components/common/layer-list.tsx b/packages/geoview-core/src/core/components/common/layer-list.tsx index 3b63210ad7e..f32daeddf86 100644 --- a/packages/geoview-core/src/core/components/common/layer-list.tsx +++ b/packages/geoview-core/src/core/components/common/layer-list.tsx @@ -6,6 +6,7 @@ import { Box, List, ListItem, ListItemButton, Paper, Tooltip, Typography } from import { TypeFeatureInfoEntry, TypeQueryStatus, TypeLayerStatus } from '@/geo/map/map-schema-types'; import { getSxClasses } from './layer-list-style'; import { LayerIcon } from './layer-icon'; +import { logger } from '@/core/utils/logger'; export interface LayerListEntry { content?: string | ReactNode; @@ -87,12 +88,15 @@ export const LayerListItem = memo(function LayerListItem({ id, isSelected, layer * Handle layer click when mouse enter is pressed. */ const handleLayerKeyDown = useCallback( - (e: React.KeyboardEvent, selectedLayer: LayerListEntry): void => { - if (e.key === 'Enter' && !isDisabled) { + (event: React.KeyboardEvent, selectedLayer: LayerListEntry): void => { + // Log + logger.logTraceUseCallback('LAYER-LIST - handleLayerKeyDown'); + + if (event.key === 'Enter' && !isDisabled) { onListItemClick(selectedLayer); // NOTE: did this, bcz when enter is clicked, tab component `handleClick` function is fired, // to avoid this we have do prevent default so that it doesn't probagate to the parent elements. - e.preventDefault(); + event.preventDefault(); } }, [isDisabled, onListItemClick] diff --git a/packages/geoview-core/src/core/components/details/feature-info-table.tsx b/packages/geoview-core/src/core/components/details/feature-info-table.tsx index d757d375891..b2f618d0b99 100644 --- a/packages/geoview-core/src/core/components/details/feature-info-table.tsx +++ b/packages/geoview-core/src/core/components/details/feature-info-table.tsx @@ -75,8 +75,8 @@ export const FeatureItem = memo(function FeatureItem({ src={item} tabIndex={0} onClick={() => onInitLightBox(featureInfoItem.value as string, featureInfoItem.alias, index)} - onKeyDown={(e: React.KeyboardEvent) => { - if (e.key === 'Enter') { + onKeyDown={(event: React.KeyboardEvent) => { + if (event.key === 'Enter') { onInitLightBox(featureInfoItem.value as string, `${index}_${featureInfoItem.alias}`, index); } }} diff --git a/packages/geoview-core/src/core/components/details/feature-info.tsx b/packages/geoview-core/src/core/components/details/feature-info.tsx index f2549e7ddcf..3111cfba023 100644 --- a/packages/geoview-core/src/core/components/details/feature-info.tsx +++ b/packages/geoview-core/src/core/components/details/feature-info.tsx @@ -21,8 +21,8 @@ interface FeatureHeaderProps { name: string; hasGeometry: boolean; checked: boolean; - onCheckChange: (e: React.ChangeEvent) => void; - onZoomIn: (e: React.MouseEvent) => void; + onCheckChange: (event: React.ChangeEvent) => void; + onZoomIn: (event: React.MouseEvent) => void; } // Constants outside component to prevent recreating every render @@ -128,8 +128,8 @@ export function FeatureInfo({ feature }: FeatureInfoProps): JSX.Element | null { // Event Handlers const handleFeatureSelectedChange = useCallback( - (e: React.ChangeEvent): void => { - e.stopPropagation(); + (event: React.ChangeEvent): void => { + event.stopPropagation(); if (!feature) return; if (!checked) { @@ -142,8 +142,8 @@ export function FeatureInfo({ feature }: FeatureInfoProps): JSX.Element | null { ); const handleZoomIn = useCallback( - (e: React.MouseEvent): void => { - e.stopPropagation(); + (event: React.MouseEvent): void => { + event.stopPropagation(); if (!featureData?.extent) return; const center = getCenter(featureData.extent); diff --git a/packages/geoview-core/src/core/components/layers/layers-panel.tsx b/packages/geoview-core/src/core/components/layers/layers-panel.tsx index e25b356ef58..9700a0bdffd 100644 --- a/packages/geoview-core/src/core/components/layers/layers-panel.tsx +++ b/packages/geoview-core/src/core/components/layers/layers-panel.tsx @@ -10,7 +10,6 @@ import { ResponsiveGridLayout, ResponsiveGridLayoutExposedMethods } from '@/core import { Typography } from '@/ui/typography/typography'; import { TypeContainerBox } from '@/core/types/global-types'; import { useUIStoreActions } from '@/core/stores/store-interface-and-intial-values/ui-state'; -import { TypeLegendLayer } from './types'; interface TypeLayersPanel { containerType?: TypeContainerBox; @@ -30,11 +29,11 @@ export function LayersPanel({ containerType }: TypeLayersPanel): JSX.Element { const responsiveLayoutRef = useRef(null); - const showLayerDetailsPanel = (layer: TypeLegendLayer): void => { + const showLayerDetailsPanel = (layerId: string): void => { responsiveLayoutRef.current?.setIsRightPanelVisible(true); responsiveLayoutRef.current?.setRightPanelFocus(); // set the focus item when layer item clicked. - setSelectedFooterLayerListItemId(`${layer.layerId}`); + setSelectedFooterLayerListItemId(`${layerId}`); }; const leftPanel = (): JSX.Element => { diff --git a/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx b/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx index 50d22fc9b2d..957233e105e 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx @@ -1,13 +1,15 @@ import { useEffect, useState, KeyboardEvent } from 'react'; import { Box, CircularProgressBase, DeleteOutlineIcon, IconButton, UndoIcon } from '@/ui'; -import { TypeLegendLayer } from '@/core/components/layers/types'; import { useLayerStoreActions } from '@/core/stores/store-interface-and-intial-values/layer-state'; -import { useMapStoreActions } from '@/core/stores/store-interface-and-intial-values/map-state'; -import { logger } from '@/core/utils/logger'; +import { useMapStoreActions, useSelectorLayerVisibility } from '@/core/stores/store-interface-and-intial-values/map-state'; import { useUIStoreActions } from '@/core/stores/store-interface-and-intial-values/ui-state'; +import { useGeoViewMapId } from '@/core/stores/geoview-store'; +import { logger } from '@/core/utils/logger'; interface DeleteUndoButtonProps { - layer: TypeLegendLayer; + layerPath: string; + layerId: string; + layerRemovable: boolean; } interface UndoButtonProps { @@ -48,24 +50,26 @@ export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element { // Log logger.logTraceRender('components/layers/left-panel/delete-undo-button/DeleteUndoButton'); - const { layer } = props; + const { layerPath, layerId, layerRemovable } = props; const [progress, setProgress] = useState(10); const [inUndoState, setInUndoState] = useState(false); // get store actions + const mapId = useGeoViewMapId(); const { deleteLayer, setLayerDeleteInProgress, getLayerDeleteInProgress } = useLayerStoreActions(); - const { getVisibilityFromOrderedLayerInfo, setOrToggleLayerVisibility } = useMapStoreActions(); + const { setOrToggleLayerVisibility } = useMapStoreActions(); const { setSelectedFooterLayerListItemId } = useUIStoreActions(); + const isVisible = useSelectorLayerVisibility(mapId, layerPath); const handleDeleteClick = (): void => { - if (getVisibilityFromOrderedLayerInfo(layer.layerPath)) setOrToggleLayerVisibility(layer.layerPath); + if (isVisible) setOrToggleLayerVisibility(layerPath); setInUndoState(true); setLayerDeleteInProgress(true); }; const handleUndoClick = (): void => { - setOrToggleLayerVisibility(layer.layerPath); + setOrToggleLayerVisibility(layerPath); setInUndoState(false); setLayerDeleteInProgress(false); }; @@ -74,7 +78,7 @@ export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element { if (e.key === 'Enter') { e.preventDefault(); handleDeleteClick(); - setSelectedFooterLayerListItemId(layer.layerId); + setSelectedFooterLayerListItemId(layerId); } }; @@ -98,7 +102,7 @@ export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element { useEffect(() => { if (progress === 100) { - deleteLayer(layer.layerPath); + deleteLayer(layerPath); setInUndoState(false); } return undefined; @@ -119,7 +123,7 @@ export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element { }, [inUndoState]); // Never hide the remove icon, so user can remove forever loading/processing layers. - if (!inUndoState && layer.controls?.remove !== false && !getLayerDeleteInProgress()) { + if (!inUndoState && layerRemovable && !getLayerDeleteInProgress()) { return ( handleDeleteKeyDown(e)}> diff --git a/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx b/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx index a193722cad0..d0f8f1b9dc2 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx @@ -3,7 +3,7 @@ import { useTheme } from '@mui/material/styles'; import { SingleLayer } from './single-layer'; import { getSxClasses } from './left-panel-styles'; import { Box } from '@/ui'; -import { useGeoViewMapId, useLayerStoreActions, useMapStoreActions } from '@/core/stores'; +import { useGeoViewMapId, useLayerStoreActions, useSelectorLayerPathOrder } from '@/core/stores'; import { logger } from '@/core/utils/logger'; import { TypeLegendLayer } from '@/core/components/layers/types'; import { TABS } from '@/core/utils/constant'; @@ -11,7 +11,7 @@ import { TABS } from '@/core/utils/constant'; interface LayerListProps { depth: number; layersList: TypeLegendLayer[]; - showLayerDetailsPanel: (layer: TypeLegendLayer) => void; + showLayerDetailsPanel: (layerId: string) => void; isLayoutEnlarged: boolean; } @@ -23,12 +23,15 @@ export function LayersList({ layersList, showLayerDetailsPanel, isLayoutEnlarged const sxClasses = useMemo(() => getSxClasses(theme), [theme]); const mapId = useGeoViewMapId(); - const { getIndexFromOrderedLayerInfo } = useMapStoreActions(); + const layerPathOrder = useSelectorLayerPathOrder(); const { sortLegendLayersChildren } = useLayerStoreActions(); - const sortedLayers = layersList.sort((a, b) => - getIndexFromOrderedLayerInfo(a.layerPath) > getIndexFromOrderedLayerInfo(b.layerPath) ? 1 : -1 - ); + const sortedLayers = layersList.sort((a, b) => { + return layerPathOrder.indexOf(a.layerPath) - layerPathOrder.indexOf(b.layerPath); + }); + + // TODO: Check - This sort should likely happen elsewhere than in a rendering component + // TO.DOCONT: (the fact that the rendering component exists or not in the ui shouldn't have to do with the order state from store) sortLegendLayersChildren(sortedLayers); const textToSlug = (text: string): string => { diff --git a/packages/geoview-core/src/core/components/layers/left-panel/left-panel.tsx b/packages/geoview-core/src/core/components/layers/left-panel/left-panel.tsx index c586ac2a034..4d329febc7f 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/left-panel.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/left-panel.tsx @@ -5,10 +5,9 @@ import { useDebounceLayerLegendLayers } from '@/core/components/legend/hooks/use import { LayersList } from './layers-list'; import { AddNewLayer } from './add-new-layer/add-new-layer'; import { logger } from '@/core/utils/logger'; -import { TypeLegendLayer } from '@/core/components/layers/types'; interface LeftPanelProps { - showLayerDetailsPanel: (layer: TypeLegendLayer) => void; + showLayerDetailsPanel: (layerId: string) => void; isLayoutEnlarged: boolean; } diff --git a/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx b/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx index 0eca67534b9..d4a699a4243 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import _ from 'lodash'; import { animated, useSpring } from '@react-spring/web'; @@ -25,7 +25,11 @@ import { useLayerSelectedLayerPath, useSelectedLayerSortingArrowId, } from '@/core/stores/store-interface-and-intial-values/layer-state'; -import { useMapStoreActions } from '@/core/stores/store-interface-and-intial-values/map-state'; +import { + useMapStoreActions, + useSelectorLayerLegendCollapsed, + useSelectorLayerVisibility, +} from '@/core/stores/store-interface-and-intial-values/map-state'; import { DeleteUndoButton } from './delete-undo-button'; import { LayersList } from './layers-list'; import { LayerIcon } from '@/core/components/common/layer-icon'; @@ -39,7 +43,7 @@ import { useUISelectedFooterLayerListItemId } from '@/core/stores/store-interfac interface SingleLayerProps { layer: TypeLegendLayer; depth: number; - showLayerDetailsPanel: (layer: TypeLegendLayer) => void; + showLayerDetailsPanel: (layerId: string) => void; index: number; isFirst: boolean; isLast: boolean; @@ -56,19 +60,13 @@ export function SingleLayer({ isLayoutEnlarged, }: SingleLayerProps): JSX.Element { // Log - logger.logTraceRender('components/layers/left-panel/single-layer'); + logger.logTraceRender('components/layers/left-panel/single-layer', layer.layerPath); const { t } = useTranslation(); // Get store states const { setSelectedLayerPath, setSelectedLayerSortingArrowId } = useLayerStoreActions(); - const { - getVisibilityFromOrderedLayerInfo, - setOrToggleLayerVisibility, - getLegendCollapsedFromOrderedLayerInfo, - setLegendCollapsed, - reorderLayer, - } = useMapStoreActions(); + const { setOrToggleLayerVisibility, setLegendCollapsed, reorderLayer } = useMapStoreActions(); const mapId = useGeoViewMapId(); const selectedLayerPath = useLayerSelectedLayerPath(); @@ -79,28 +77,44 @@ export function SingleLayer({ useDataTableStoreActions(); - const legendExpanded = !getLegendCollapsedFromOrderedLayerInfo(layer.layerPath); + const isVisible = useSelectorLayerVisibility(mapId, layer.layerPath); + const legendExpanded = !useSelectorLayerLegendCollapsed(mapId, layer.layerPath); + + const listItemSpring = useSpring({ + delay: index * 150 + (depth * 150) / 2, + from: { opacity: 0.1 }, + to: { opacity: 1 }, + }); // if any of the child layers is selected return true - const isLayerChildSelected = (startingLayer: TypeLegendLayer): boolean => { - if (displayState !== 'view') { - return false; - } - if (startingLayer.children && startingLayer.children.length > 0) { - if (startingLayer.children.filter((child) => child.layerPath === selectedLayerPath).length > 0) { - return true; + const isLayerChildSelected = useCallback( + (startingLayer: TypeLegendLayer): boolean => { + // Log + logger.logTraceUseCallback('SINGLE-LAYER - isLayerChildSelected'); + + if (displayState !== 'view') { + return false; } + if (startingLayer.children && startingLayer.children.length > 0) { + if (startingLayer.children.filter((child) => child.layerPath === selectedLayerPath).length > 0) { + return true; + } - return _.some(startingLayer.children, (child) => isLayerChildSelected(child)); - } - return false; - }; + return _.some(startingLayer.children, (child) => isLayerChildSelected(child)); + } + return false; + }, + [displayState, selectedLayerPath] + ); const layerChildIsSelected = isLayerChildSelected(layer); const layerIsSelected = layer.layerPath === selectedLayerPath && displayState === 'view'; // returns true if any of the layer children has visibility of false - const layerHasDisabledVisibility = (startingLayer: TypeLegendLayer): boolean => { + const layerHasDisabledVisibility = useCallback((startingLayer: TypeLegendLayer): boolean => { + // Log + logger.logTraceUseCallback('SINGLE-LAYER - layerHasDisabledVisibility'); + if (startingLayer.controls?.visibility === false) { return true; } @@ -110,12 +124,90 @@ export function SingleLayer({ } return childrenHasAlways; - }; + }, []); const isLayerAlwaysVisible = layerHasDisabledVisibility(layer); + /** + * Handle expand/shrink of layer groups. + */ + const handleExpandGroupClick = useCallback((): void => { + // Log + logger.logTraceUseCallback('SINGLE-LAYER - handleExpandGroupClick'); + + // Set legend collapse value + setLegendCollapsed(layer.layerPath); + }, [layer.layerPath, setLegendCollapsed]); + + const handleLayerClick = useCallback((): void => { + // Log + logger.logTraceUseCallback('SINGLE-LAYER - handleLayerClick'); + + // Only clickable if the layer status is processed or loaded + if (!['processed', 'loaded'].includes(layer.layerStatus!)) { + return; + } + + // Set selected layer path + setSelectedLayerPath(layer.layerPath); + showLayerDetailsPanel?.(layer.layerId); + }, [layer.layerPath, layer.layerId, layer.layerStatus, setSelectedLayerPath, showLayerDetailsPanel]); + + const handleListItemKeyDown = useCallback( + (event: React.KeyboardEvent) => { + // Log + logger.logTraceUseCallback('SINGLE-LAYER - handleListItemKeyDown'); + + // If clicked enter key + if (event.key === 'Enter' && event.currentTarget === event.target) { + // Redirect + handleLayerClick(); + } + }, + [handleLayerClick] + ); + + const handleIconButtonUpKeyDown = useCallback( + (event: React.KeyboardEvent) => { + // Log + logger.logTraceUseCallback('SINGLE-LAYER - handleIconButtonUpKeyDown'); + + if (event.key === 'Enter') { + setSelectedLayerSortingArrowId(`${mapId}-${layer.layerPath}-up-order`); + reorderLayer(layer.layerPath, -1); + event.preventDefault(); + } + }, + [layer.layerPath, mapId, reorderLayer, setSelectedLayerSortingArrowId] + ); + + const handleIconButtonDownKeyDown = useCallback( + (event: React.KeyboardEvent) => { + // Log + logger.logTraceUseCallback('SINGLE-LAYER - handleIconButtonDownKeyDown'); + + if (event.key === 'Enter') { + setSelectedLayerSortingArrowId(`${mapId}-${layer.layerPath}-down-order`); + reorderLayer(layer.layerPath, 1); + event.preventDefault(); + } + }, + [layer.layerPath, mapId, reorderLayer, setSelectedLayerSortingArrowId] + ); + + const handleToggleVisibility = useCallback((): void => { + // Log + logger.logTraceUseCallback('SINGLE-LAYER - handleToggleVisibility'); + + // Toggle visibility + setOrToggleLayerVisibility(layer.layerPath); + }, [layer.layerPath, setOrToggleLayerVisibility]); + // Get layer description - const getLayerDescription = (): JSX.Element | string | null => { + const memoLayerDescription = useMemo((): JSX.Element | string | null => { + // Log + logger.logTraceUseMemo('SINGLE-LAYER - memoLayerDescription'); + if (layer.layerStatus === 'error') { return t('legend.layerError'); } @@ -145,34 +237,15 @@ export function SingleLayer({ ); } return itemsLengthDesc; - }; - - /** - * Handle expand/shrink of layer groups. - */ - const handleExpandGroupClick = (): void => { - setLegendCollapsed(layer.layerPath); - }; - - const handleLayerClick = (): void => { - // Only clickable if the layer status is processed or loaded - if (!['processed', 'loaded'].includes(layer.layerStatus!)) { - return; - } + }, [datatableSettings, layer.children.length, layer.items, layer.layerPath, layer.layerStatus, t]); - setSelectedLayerPath(layer.layerPath); - if (showLayerDetailsPanel) { - showLayerDetailsPanel(layer); - } - }; - - const handleToggleVisibility = (): void => { - setOrToggleLayerVisibility(layer.layerPath); - }; + // Memoize the EditModeButtons component section + const memoEditModeButtons = useMemo((): JSX.Element | null => { + // Log + logger.logTraceUseMemo('SINGLE-LAYER - memoEditModeButtons', layer.layerPath); - function renderEditModeButtons(): JSX.Element | null { if (displayState === 'remove') { - return ; + return ; } if (displayState === 'order') { return ( @@ -194,14 +267,8 @@ export function SingleLayer({ disabled={isFirst} edge="end" size="small" + onKeyDown={handleIconButtonUpKeyDown} onClick={() => reorderLayer(layer.layerPath, -1)} - onKeyDown={(e) => { - if (e.key === 'Enter') { - setSelectedLayerSortingArrowId(`${mapId}-${layer.layerPath}-up-order`); - reorderLayer(layer.layerPath, -1); - e.preventDefault(); - } - }} > @@ -210,13 +277,7 @@ export function SingleLayer({ disabled={isLast} edge="end" size="small" - onKeyDown={(e) => { - if (e.key === 'Enter') { - setSelectedLayerSortingArrowId(`${mapId}-${layer.layerPath}-down-order`); - reorderLayer(layer.layerPath, 1); - e.preventDefault(); - } - }} + onKeyDown={handleIconButtonDownKeyDown} onClick={() => reorderLayer(layer.layerPath, 1)} > @@ -225,14 +286,30 @@ export function SingleLayer({ ); } return null; - } + }, [ + displayState, + handleIconButtonDownKeyDown, + handleIconButtonUpKeyDown, + isFirst, + isLast, + layer.children?.length, + layer.controls?.remove, + layer.layerId, + layer.layerPath, + mapId, + reorderLayer, + ]); + + // Memoize the MoreLayerButtons component section + const memoMoreLayerButtons = useMemo((): JSX.Element | null => { + // Log + logger.logTraceUseMemo('SINGLE-LAYER - memoMoreLayerButtons', layer.layerPath); - function renderMoreLayerButtons(): JSX.Element | null { if (layer.layerStatus === 'processing' || layer.layerStatus === 'loading' || displayState !== 'view') { return null; } if (layer.layerStatus === 'error') { - return ; + return ; } if (isLayerAlwaysVisible) { @@ -244,22 +321,26 @@ export function SingleLayer({ } return ( - handleToggleVisibility()} - tooltip="layers.toggleVisibility" - className="buttonOutline" - > - {(() => { - if (!getVisibilityFromOrderedLayerInfo(layer.layerPath)) return ; - return ; - })()} + + {isVisible ? : } ); - } + }, [ + displayState, + handleToggleVisibility, + isLayerAlwaysVisible, + isVisible, + layer.controls?.remove, + layer.layerId, + layer.layerPath, + layer.layerStatus, + ]); + + // Memoize the arrow buttons component section + const memoArrowButtons = useMemo((): JSX.Element | null => { + // Log + logger.logTraceUseMemo('SINGLE-LAYER - memoArrowButtons'); - function renderArrowButtons(): JSX.Element | null { if (layer.children?.length) { return ( { + // Log + logger.logTraceUseMemo('SINGLE-LAYER - memoCollapse', layer.children); - function renderCollapsible(): JSX.Element | null { if (!(layer.children && layer.children.length)) { return null; } @@ -293,9 +378,13 @@ export function SingleLayer({ /> ); - } + }, [depth, isLayoutEnlarged, layer.children, legendExpanded, showLayerDetailsPanel]); + + // Memoize the container class section + const memoContainerClass = useMemo(() => { + // Log + logger.logTraceUseMemo('SINGLE-LAYER - memoContainerClass'); - function getContainerClass(): string { const result: string[] = ['layer-panel ', layer.layerStatus ?? '']; if (depth === 0) { @@ -312,15 +401,12 @@ export function SingleLayer({ } return result.join(' '); - } - - const listItemSpring = useSpring({ - delay: index * 150 + (depth * 150) / 2, - from: { opacity: 0.1 }, - to: { opacity: 1 }, - }); + }, [depth, layer.layerStatus, layerChildIsSelected, layerIsSelected, legendExpanded]); useEffect(() => { + // Log + logger.logTraceUseEffect('SINGLE-LAYER - selectedLayerSortingArrowId'); + // Manually set the focus after sorting is done. if (selectedLayerSortingArrowId.length) { const elem = document.getElementById(selectedLayerSortingArrowId) as HTMLButtonElement; @@ -337,6 +423,9 @@ export function SingleLayer({ }, [selectedLayerSortingArrowId]); useEffect(() => { + // Log + logger.logTraceUseEffect('SINGLE-LAYER - displayState, selectedFooterLayerListItemId'); + // set the focus to first layer, after layer has been deleted. if (displayState === 'remove' && selectedFooterLayerListItemId.length) { const firstLayer = document.getElementById('layers-left-panel'); @@ -350,15 +439,9 @@ export function SingleLayer({ const AnimatedPaper = animated(Paper); return ( - + - e.key === 'Enter' && e.currentTarget === e.target && handleLayerClick()} - > + {!isLayoutEnlarged && ( - {renderMoreLayerButtons()} - {renderArrowButtons()} - {renderEditModeButtons()} + {memoMoreLayerButtons} + {memoArrowButtons} + {memoEditModeButtons} )} - {renderCollapsible()} + {memoCollapse} ); } diff --git a/packages/geoview-core/src/core/components/legend/legend-layer-ctrl.tsx b/packages/geoview-core/src/core/components/legend/legend-layer-ctrl.tsx index 9e7f37abfd3..14d81f43418 100644 --- a/packages/geoview-core/src/core/components/legend/legend-layer-ctrl.tsx +++ b/packages/geoview-core/src/core/components/legend/legend-layer-ctrl.tsx @@ -17,16 +17,17 @@ import { TypeLegendItem, TypeLegendLayer } from '@/core/components/layers/types' import { useMapStoreActions } from '@/core/stores/'; import { getSxClasses } from './legend-styles'; import { logger } from '@/core/utils/logger'; +import { TypeLayerControls } from '@/api/config/types/map-schema-types'; interface SecondaryControlsProps { layer: TypeLegendLayer; - visibility: boolean; // Visibility come from store ordered layer info array + isVisible: boolean; // Visibility come from store ordered layer info array } type ControlActions = { - handleToggleVisibility: (e: React.MouseEvent) => void; - handleHighlightLayer: (e: React.MouseEvent) => void; - handleZoomTo: (e: React.MouseEvent) => void; + handleToggleVisibility: (event: React.MouseEvent) => void; + handleHighlightLayer: (event: React.MouseEvent) => void; + handleZoomTo: (event: React.MouseEvent) => void; }; // Constant style outside of render @@ -41,16 +42,16 @@ const useControlActions = (layerPath: string): ControlActions => { return useMemo( () => ({ - handleToggleVisibility: (e: React.MouseEvent): void => { - e.stopPropagation(); + handleToggleVisibility: (event: React.MouseEvent): void => { + event.stopPropagation(); setOrToggleLayerVisibility(layerPath); }, - handleHighlightLayer: (e: React.MouseEvent): void => { - e.stopPropagation(); + handleHighlightLayer: (event: React.MouseEvent): void => { + event.stopPropagation(); setHighlightLayer(layerPath); }, - handleZoomTo: (e: React.MouseEvent): void => { - e.stopPropagation(); + handleZoomTo: (event: React.MouseEvent): void => { + event.stopPropagation(); zoomToLayerExtent(layerPath).catch((error) => { logger.logPromiseFailed('in zoomToLayerExtent in legend-layer.handleZoomTo', error); }); @@ -79,9 +80,13 @@ const useSubtitle = (children: TypeLegendLayer[], items: TypeLegendItem[]): stri }; // SecondaryControls component (no memo to force re render from layers panel modifications) -export function SecondaryControls({ layer, visibility }: SecondaryControlsProps): JSX.Element { +export function SecondaryControls({ layer, isVisible }: SecondaryControlsProps): JSX.Element { + // Extract constant from layer prop + const { layerPath, layerStatus, items, children } = layer; + const layerControls: TypeLayerControls | undefined = layer.controls; + // Log - logger.logTraceRender('components/legend/legend-layer-ctrl'); + logger.logTraceRender('components/legend/legend-layer-ctrl', layerPath, isVisible); // Hooks const theme = useTheme(); @@ -91,13 +96,10 @@ export function SecondaryControls({ layer, visibility }: SecondaryControlsProps) const highlightedLayer = useLayerHighlightedLayer(); // Is button disabled? - const isLayerVisible = layer.controls?.visibility ?? false; - - // Extract constant from layer prop - const { layerStatus, items, children } = layer; + const isLayerVisibleCapable = layerControls?.visibility ?? false; // Component helper - const controls = useControlActions(layer.layerPath); + const controls = useControlActions(layerPath); const subTitle = useSubtitle(children, items); if (!['processed', 'loaded'].includes(layerStatus || 'error')) { @@ -113,12 +115,12 @@ export function SecondaryControls({ layer, visibility }: SecondaryControlsProps) tooltip="layers.toggleVisibility" className="buttonOutline" onClick={controls.handleToggleVisibility} - disabled={!isLayerVisible} + disabled={!isLayerVisibleCapable} > - {visibility ? : } + {isVisible ? : } - {highlightedLayer === layer.layerPath ? : } + {highlightedLayer === layerPath ? : } diff --git a/packages/geoview-core/src/core/components/legend/legend-layer.tsx b/packages/geoview-core/src/core/components/legend/legend-layer.tsx index e9eb7e10d36..b0d32cc6b85 100644 --- a/packages/geoview-core/src/core/components/legend/legend-layer.tsx +++ b/packages/geoview-core/src/core/components/legend/legend-layer.tsx @@ -1,8 +1,14 @@ -import { memo, useCallback, useMemo, useState } from 'react'; +import { memo, useCallback, useMemo } from 'react'; import { useTheme } from '@mui/material'; import { Box, ListItem, Tooltip, ListItemText, IconButton, KeyboardArrowDownIcon, KeyboardArrowUpIcon } from '@/ui'; import { TypeLegendLayer } from '@/core/components/layers/types'; -import { useLayerStoreActions, useMapStoreActions } from '@/core/stores/'; +import { + useGeoViewMapId, + useLayerStoreActions, + useMapStoreActions, + useSelectorLayerLegendCollapsed, + useSelectorLayerVisibility, +} from '@/core/stores/'; import { useLightBox } from '@/core/components/common'; import { LayerIcon } from '../common/layer-icon'; import { SecondaryControls } from './legend-layer-ctrl'; @@ -18,7 +24,7 @@ interface LegendLayerHeaderProps { layer: TypeLegendLayer; isCollapsed: boolean; isVisible: boolean; - onExpandClick: (e: React.MouseEvent) => void; + onExpandClick: (event: React.MouseEvent) => void; } // Constant style outside of render @@ -39,7 +45,7 @@ const LegendLayerHeader = memo( primary={layer.layerName} className="layerTitle" disableTypography - secondary={} + secondary={} /> {(layer.children?.length > 1 || layer.items?.length > 1) && ( @@ -62,15 +68,14 @@ export function LegendLayer({ layer }: LegendLayerProps): JSX.Element { const sxClasses = useMemo(() => getSxClasses(theme), [theme]); // Stores + const mapId = useGeoViewMapId(); const { initLightBox, LightBoxComponent } = useLightBox(); - const { getLegendCollapsedFromOrderedLayerInfo, getVisibilityFromOrderedLayerInfo, setLegendCollapsed } = useMapStoreActions(); + const { setLegendCollapsed } = useMapStoreActions(); const { getLayerStatus } = useLayerStoreActions(); - const isVisible = getVisibilityFromOrderedLayerInfo(layer.layerPath); + const isVisible = useSelectorLayerVisibility(mapId, layer.layerPath); + const isCollapsed = useSelectorLayerLegendCollapsed(mapId, layer.layerPath); const layerStatus = getLayerStatus(layer.layerPath); - // State - const [isCollapsed, setIsCollapsed] = useState(getLegendCollapsedFromOrderedLayerInfo(layer.layerPath)); - // Create a new layer object with updated status (no useMemo to ensure updates in inner child) const currentLayer = { ...layer, @@ -81,15 +86,14 @@ export function LegendLayer({ layer }: LegendLayerProps): JSX.Element { }; const handleExpandGroupClick = useCallback( - (e: React.MouseEvent): void => { + (event: React.MouseEvent): void => { // Log - logger.logTraceUseCallback('LEGEND_LAYER - handleExpandGroupClick', layer.layerPath); + logger.logTraceUseCallback('LEGEND-LAYER - handleExpandGroupClick', layer.layerPath); - e.stopPropagation(); - setIsCollapsed(!getLegendCollapsedFromOrderedLayerInfo(layer.layerPath)); + event.stopPropagation(); setLegendCollapsed(layer.layerPath); // store value }, - [getLegendCollapsedFromOrderedLayerInfo, layer.layerPath, setLegendCollapsed] + [layer.layerPath, setLegendCollapsed] ); return ( diff --git a/packages/geoview-core/src/core/stores/state-api.ts b/packages/geoview-core/src/core/stores/state-api.ts index 6ad32cb2760..e1db798f4da 100644 --- a/packages/geoview-core/src/core/stores/state-api.ts +++ b/packages/geoview-core/src/core/stores/state-api.ts @@ -114,7 +114,7 @@ export class StateApi { let startingIndex = -1; for (let i = 0; i < orderedLayers.length; i++) if (orderedLayers[i].layerPath === layerPath) startingIndex = i; const layerInfo = orderedLayers[startingIndex]; - const movedLayers = MapEventProcessor.getMapLayerAndChildrenOrderedInfo(mapId, layerPath, orderedLayers); + const movedLayers = MapEventProcessor.findMapLayerAndChildrenFromOrderedInfo(mapId, layerPath, orderedLayers); orderedLayers.splice(startingIndex, movedLayers.length); let nextIndex = startingIndex; const pathLength = layerInfo.layerPath.split('/').length; diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts index 065eabcb4ac..1c6827ecf2e 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts @@ -344,17 +344,20 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay * Sets the selected layer path. * @param {string} layerPath - The layer path to set as selected. */ - setSelectedLayerPath: (layerPath: string): void => { + setSelectedLayerPath: (layerPath: string | null): void => { + let theLayerPath: string | null = layerPath; + if (layerPath && layerPath.length === 0) theLayerPath = null; const curLayers = get().layerState.legendLayers; - const layer = LegendEventProcessor.findLayerByPath(curLayers, layerPath); + const layer = LegendEventProcessor.findLayerByPath(curLayers, layerPath || ''); set({ layerState: { ...get().layerState, - selectedLayerPath: layerPath, + selectedLayerPath: theLayerPath, selectedLayer: layer as TypeLegendLayer, }, }); }, + setSelectedLayerSortingArrowId: (arrowId: string) => { set({ layerState: { diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts index 4166aa4ca46..34394360d08 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts @@ -61,9 +61,6 @@ export interface IMapState { actions: { createBasemapFromOptions: (basemapOptions: TypeBasemapOptions) => Promise; getPixelFromCoordinate: (coord: Coordinate) => [number, number]; - getIndexFromOrderedLayerInfo: (layerPath: string) => number; - getLegendCollapsedFromOrderedLayerInfo: (layerPath: string) => boolean; - getVisibilityFromOrderedLayerInfo: (layerPath: string) => boolean; showClickMarker: (marker: TypeClickMarker) => void; hideClickMarker: () => void; highlightBBox: (extent: Extent, isLayerHighlight?: boolean) => void; @@ -222,36 +219,6 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt return MapEventProcessor.getPixelFromCoordinate(get().mapId, coord); }, - /** - * Retrieves the index from ordered layer information. - * @param {string} layerPath - The path of the layer. - * @returns {number} The index of the layer. - */ - getIndexFromOrderedLayerInfo: (layerPath: string): number => { - // Redirect to processor and return the result - return MapEventProcessor.getMapIndexFromOrderedLayerInfo(get().mapId, layerPath); - }, - - /** - * Retrieves the visibility from ordered layer information. - * @param {string} layerPath - The path of the layer. - * @returns {boolean} The visibility of the layer. - */ - getLegendCollapsedFromOrderedLayerInfo: (layerPath: string): boolean => { - // Redirect to processor and return the result - return MapEventProcessor.getMapLegendCollapsedFromOrderedLayerInfo(get().mapId, layerPath); - }, - - /** - * Retrieves the visibility from ordered layer information. - * @param {string} layerPath - The path of the layer. - * @returns {boolean} The visibility of the layer. - */ - getVisibilityFromOrderedLayerInfo: (layerPath: string): boolean => { - // Redirect to processor and return the result - return MapEventProcessor.getMapVisibilityFromOrderedLayerInfo(get().mapId, layerPath); - }, - /** * Shows a click marker. * @param {TypeClickMarker} marker - The click marker to show. @@ -912,7 +879,8 @@ export const useMapHoverFeatureInfo = (): TypeHoverFeatureInfo => useStore(useGe export const useMapLoaded = (): boolean => useStore(useGeoViewStore(), (state) => state.mapState.mapLoaded); export const useMapNorthArrow = (): boolean => useStore(useGeoViewStore(), (state) => state.mapState.northArrow); export const useMapNorthArrowElement = (): TypeNorthArrow => useStore(useGeoViewStore(), (state) => state.mapState.northArrowElement); -export const useMapOrderedLayerInfo = (): TypeOrderedLayerInfo[] => useStore(useGeoViewStore(), (state) => state.mapState.orderedLayerInfo); +// TODO: Clean up - Obsolete use to delete line when confirmed +// export const useMapOrderedLayerInfo = (): TypeOrderedLayerInfo[] => useStore(useGeoViewStore(), (state) => state.mapState.orderedLayerInfo); export const useMapOverviewMap = (): boolean => useStore(useGeoViewStore(), (state) => state.mapState.overviewMap); export const useMapOverviewMapHideZoom = (): number => useStore(useGeoViewStore(), (state) => state.mapState.overviewMapHideZoom); export const useMapPointerPosition = (): TypeMapMouseInfo | undefined => @@ -927,8 +895,30 @@ export const useMapVisibleLayers = (): string[] => useStore(useGeoViewStore(), ( export const useMapZoom = (): number => useStore(useGeoViewStore(), (state) => state.mapState.zoom); // Getter function for one-time access, there is no subcription to modification +// TODO: Check - Should likely be renamed/reviewed to be a "useMapPointerPosition" or moved elsewhere than here in map-state export const getMapPointerPosition = (mapId: string): TypeMapMouseInfo | undefined => getGeoViewStore(mapId).getState().mapState.pointerPosition; +export const useSelectorLayerVisibility = (mapId: string, layerPath: string): boolean => { + // Hook + const orderedLayerInfo = useStore(useGeoViewStore(), (state) => state.mapState.orderedLayerInfo); + // Redirect + return MapEventProcessor.findMapLayerFromOrderedInfo(mapId, layerPath, orderedLayerInfo)?.visible || false; +}; + +export const useSelectorLayerLegendCollapsed = (mapId: string, layerPath: string): boolean => { + // Hook + const orderedLayerInfo = useStore(useGeoViewStore(), (state) => state.mapState.orderedLayerInfo); + // Redirect + return MapEventProcessor.findMapLayerFromOrderedInfo(mapId, layerPath, orderedLayerInfo)?.legendCollapsed || false; +}; + +export const useSelectorLayerPathOrder = (): string[] => { + // Hook + const orderedLayerInfo = useStore(useGeoViewStore(), (state) => state.mapState.orderedLayerInfo); + // Redirect + return orderedLayerInfo.map((layer) => layer.layerPath); +}; + // Store Actions export const useMapStoreActions = (): MapActions => useStore(useGeoViewStore(), (state) => state.mapState.actions); diff --git a/packages/geoview-core/src/geo/layer/layer.ts b/packages/geoview-core/src/geo/layer/layer.ts index 9c9222ac829..a5b26bc25cd 100644 --- a/packages/geoview-core/src/geo/layer/layer.ts +++ b/packages/geoview-core/src/geo/layer/layer.ts @@ -465,7 +465,7 @@ export class LayerApi { ) { this.#printDuplicateGeoviewLayerConfigError(geoviewLayerConfigToCreate); // Remove geoCore ordered layer info placeholder - if (MapEventProcessor.getMapOrderedLayerInfoForLayer(this.getMapId(), geoviewLayerConfigToCreate.geoviewLayerId)) + if (MapEventProcessor.findMapLayerFromOrderedInfo(this.getMapId(), geoviewLayerConfigToCreate.geoviewLayerId)) MapEventProcessor.removeOrderedLayerInfo(this.getMapId(), geoviewLayerConfigToCreate.geoviewLayerId, false); return false; @@ -632,7 +632,7 @@ export class LayerApi { // TODO: Refactor - This should be dealt with the config classes and this line commented out, therefore, content of addGeoviewLayerStep2 becomes this addGeoviewLayer function. if (geoviewLayerConfig.geoviewLayerId in this.#geoviewLayers) { // Remove geoCore ordered layer info placeholder - if (MapEventProcessor.getMapOrderedLayerInfoForLayer(this.getMapId(), geoviewLayerConfig.geoviewLayerId)) + if (MapEventProcessor.findMapLayerFromOrderedInfo(this.getMapId(), geoviewLayerConfig.geoviewLayerId)) MapEventProcessor.removeOrderedLayerInfo(this.getMapId(), geoviewLayerConfig.geoviewLayerId, false); this.#printDuplicateGeoviewLayerConfigError(geoviewLayerConfig); @@ -1047,7 +1047,7 @@ export class LayerApi { const parentLayerIndex = MapEventProcessor.getMapIndexFromOrderedLayerInfo(this.getMapId(), parentLayerPath); // Get the number of layers - const numberOfLayers = MapEventProcessor.getMapLayerAndChildrenOrderedInfo(this.getMapId(), parentLayerPath).length; + const numberOfLayers = MapEventProcessor.findMapLayerAndChildrenFromOrderedInfo(this.getMapId(), parentLayerPath).length; // If the map index of the parent has been set if (parentLayerIndex !== -1) { @@ -1508,7 +1508,7 @@ export class LayerApi { const layerVisibility = MapEventProcessor.getMapVisibilityFromOrderedLayerInfo(this.getMapId(), layerPath); // Determine the outcome of the new visibility based on parameters const newVisibility = newValue !== undefined ? newValue : !layerVisibility; - const layerInfos = MapEventProcessor.getMapLayerAndChildrenOrderedInfo(this.getMapId(), layerPath, curOrderedLayerInfo); + const layerInfos = MapEventProcessor.findMapLayerAndChildrenFromOrderedInfo(this.getMapId(), layerPath, curOrderedLayerInfo); layerInfos.forEach((layerInfo: TypeOrderedLayerInfo) => { if (layerInfo) { diff --git a/packages/geoview-core/src/geo/layer/other/geocore.ts b/packages/geoview-core/src/geo/layer/other/geocore.ts index 5ce35f9ccce..53f7261d5b4 100644 --- a/packages/geoview-core/src/geo/layer/other/geocore.ts +++ b/packages/geoview-core/src/geo/layer/other/geocore.ts @@ -76,7 +76,7 @@ export class GeoCore { logger.logError(`Failed to get the GeoView layer from UUID ${uuid}`, error); // Remove geoCore ordered layer info placeholder - if (MapEventProcessor.getMapOrderedLayerInfoForLayer(this.#mapId, uuid)) + if (MapEventProcessor.findMapLayerFromOrderedInfo(this.#mapId, uuid)) MapEventProcessor.removeOrderedLayerInfo(this.#mapId, uuid, false); // TODO: find a more centralized way to trap error and display message diff --git a/packages/geoview-core/src/ui/accordion/accordion.tsx b/packages/geoview-core/src/ui/accordion/accordion.tsx index 1b6b8808db8..da7d3b28e7e 100644 --- a/packages/geoview-core/src/ui/accordion/accordion.tsx +++ b/packages/geoview-core/src/ui/accordion/accordion.tsx @@ -60,13 +60,13 @@ export function Accordion(props: AccordionProps): ReactNode { }; const handleTransitionEnd = useCallback( - (index: number) => (e: React.TransitionEvent) => { + (index: number) => (event: React.TransitionEvent) => { if (!expandedStates[index] && showLoadingIcon) { const updatedStates = [...transitionStates]; updatedStates[index] = true; setTransitionStates(updatedStates); - if (e.propertyName === 'height') { + if (event.propertyName === 'height') { const resetStates = [...transitionStates]; resetStates[index] = false; setTransitionStates(resetStates); diff --git a/packages/geoview-core/src/ui/list/checkbox-list/checkbox-list.tsx b/packages/geoview-core/src/ui/list/checkbox-list/checkbox-list.tsx index 13f75c40bbc..5682f78ed9a 100644 --- a/packages/geoview-core/src/ui/list/checkbox-list/checkbox-list.tsx +++ b/packages/geoview-core/src/ui/list/checkbox-list/checkbox-list.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useCallback } from 'react'; import { useTheme } from '@mui/material/styles'; import { Typography } from '@mui/material'; @@ -70,9 +70,9 @@ export function CheckboxList(props: CheckboxListProps): JSX.Element { * Helper function to stop propagation on click of the right-side content * @param e React.MouseEvent The mouse click event */ - const handleClickContent = (e: React.MouseEvent): void => { - e.stopPropagation(); - }; + const handleClickContent = useCallback((event: React.MouseEvent): void => { + event.stopPropagation(); + }, []); // Effect triggered when the checked values changes useEffect(() => { @@ -102,7 +102,7 @@ export function CheckboxList(props: CheckboxListProps): JSX.Element { {item.display} - handleClickContent(e)}> + {item.contentRight}