Skip to content

Commit

Permalink
Refactor selecting feature to be a hook
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanfranklin committed Nov 19, 2024
1 parent f183a6c commit 8587705
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 31 deletions.
20 changes: 5 additions & 15 deletions react/src/components/FeatureFileTree/FeatureFileTree.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useCallback, useState, useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { Tree } from 'antd';
import type { DataNode } from 'antd/es/tree';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
Expand All @@ -11,7 +10,7 @@ import { useResizeDetector } from 'react-resize-detector';
import { Button } from '@tacc/core-components';
import { featureCollectionToFileNodeArray } from '@hazmapper/utils/featureTreeUtils';
import { FeatureCollection, FeatureFileNode } from '@hazmapper/types';
import { useDeleteFeature } from '@hazmapper/hooks';
import { useDeleteFeature, useFeatureSelection } from '@hazmapper/hooks';
import { FeatureIcon } from '@hazmapper/components/FeatureIcon';
import styles from './FeatureFileTree.module.css';

Expand Down Expand Up @@ -48,17 +47,13 @@ const FeatureFileTree: React.FC<FeatureFileTreeProps> = ({
projectId,
}) => {
const { mutate: deleteFeature, isLoading } = useDeleteFeature();
const location = useLocation();
const navigate = useNavigate();
const { selectedFeatureId, setSelectedFeature } = useFeatureSelection();

const { height, ref } = useResizeDetector();

const [expanded, setExpanded] = useState<string[]>([]);
const [treeData, setTreeData] = useState<TreeDataNode[]>([]);

const searchParams = new URLSearchParams(location.search);
const selectedFeature = searchParams.get('selectedFeature');

useEffect(() => {
const fileNodeArray = featureCollectionToFileNodeArray(featureCollection);

Expand Down Expand Up @@ -120,7 +115,8 @@ const FeatureFileTree: React.FC<FeatureFileTreeProps> = ({

const titleRender = (node: TreeDataNode) => {
const featureNode = node.featureNode as FeatureFileNode;
const isSelected = selectedFeature === node.key && !featureNode.isDirectory;
const isSelected =
!featureNode.isDirectory && selectedFeatureId === Number(node.key);
const isExpanded = expanded.includes(node.key);

const toggleNode = (e: React.MouseEvent | React.KeyboardEvent) => {
Expand All @@ -135,13 +131,7 @@ const FeatureFileTree: React.FC<FeatureFileTreeProps> = ({
} else {
e.stopPropagation();

const newSearchParams = new URLSearchParams(searchParams);
if (selectedFeature === node.key) {
newSearchParams.delete('selectedFeature');
} else {
newSearchParams.set('selectedFeature', node.key);
}
navigate({ search: newSearchParams.toString() }, { replace: true });
setSelectedFeature(Number(node.key));
}
};

Expand Down
4 changes: 2 additions & 2 deletions react/src/components/Map/Map.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import { render } from '@testing-library/react';
import { renderInTest } from '@hazmapper/test/testUtil';
import Map from './Map';
import { tileServerLayers } from '../../__fixtures__/tileServerLayerFixture';
import { featureCollection } from '../../__fixtures__/featuresFixture';

test('renders map', () => {
const { getByText } = render(
const { getByText } = renderInTest(
<Map baseLayers={tileServerLayers} featureCollection={featureCollection} />
);
expect(getByText(/Map/)).toBeDefined();
Expand Down
19 changes: 5 additions & 14 deletions react/src/components/Map/Map.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useMemo, useCallback } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import {
MapContainer,
ZoomControl,
Expand All @@ -22,6 +21,7 @@ import {
Feature,
getFeatureType,
} from '@hazmapper/types';
import { useFeatureSelection } from '@hazmapper/hooks';
import { MAP_CONFIG } from './config';
import FitBoundsHandler from './FitBoundsHandler';
import { calculatePointCloudMarkerPosition } from './utils';
Expand All @@ -30,7 +30,7 @@ interface LeafletMapProps {
/**
* Tile servers used as base layers of map
*/
baseLayers: TileServerLayer[];
baseLayers?: TileServerLayer[];

/**
* Features of map
Expand Down Expand Up @@ -67,24 +67,15 @@ const LeafletMap: React.FC<LeafletMapProps> = ({
baseLayers = [],
featureCollection,
}) => {
const navigate = useNavigate();
const location = useLocation();
const searchParams = new URLSearchParams(location.search);
const selectedFeature = searchParams.get('selectedFeature');
const { selectedFeatureId, setSelectedFeature } = useFeatureSelection();

const handleFeatureClick = useCallback(
(feature: any) => {
const newSearchParams = new URLSearchParams(searchParams);
if (selectedFeature === feature.id) {
newSearchParams.delete('selectedFeature');
} else {
newSearchParams.set('selectedFeature', feature.id);
}
navigate({ search: newSearchParams.toString() }, { replace: true });
setSelectedFeature(feature.id);

//TODO handle clicking on streetview https://tacc-main.atlassian.net/browse/WG-392
},
[navigate]
[selectedFeatureId]
);

const activeBaseLayers = useMemo(
Expand Down
1 change: 1 addition & 0 deletions react/src/hooks/features/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { useDeleteFeature } from './useDeleteFeature';
export { useFeatures } from './useFeatures';
export { useFeatureSelection } from './useFeatureSelection';
45 changes: 45 additions & 0 deletions react/src/hooks/features/useFeatureSelection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useCallback } from 'react';
import { useNavigate, useLocation, useSearchParams } from 'react-router-dom';

const SELECTED_FEATURE_PARAM = 'selectedFeature';

interface UseFeatureSelectionReturn {
selectedFeatureId: number | null;
setSelectedFeature: (featureId: number) => void;
}

export function useFeatureSelection(): UseFeatureSelectionReturn {
const navigate = useNavigate();
const location = useLocation();
const [searchParams] = useSearchParams();

const selectedFeatureId = searchParams.get(SELECTED_FEATURE_PARAM)
? Number(searchParams.get(SELECTED_FEATURE_PARAM))
: null;

const setSelectedFeature = useCallback(
(featureId: number) => {
const newSearchParams = new URLSearchParams(searchParams);

if (selectedFeatureId === Number(featureId)) {
newSearchParams.delete(SELECTED_FEATURE_PARAM);
} else {
newSearchParams.set(SELECTED_FEATURE_PARAM, String(featureId));
}

navigate(
{
pathname: location.pathname,
search: newSearchParams.toString(),
},
{ replace: true }
);
},
[navigate, location.pathname, searchParams, selectedFeatureId]
);

return {
selectedFeatureId,
setSelectedFeature,
};
}

0 comments on commit 8587705

Please sign in to comment.