Skip to content

Commit

Permalink
feat: add zoom to selection button
Browse files Browse the repository at this point in the history
Closes #243
  • Loading branch information
stdavis committed Nov 29, 2024
1 parent 4b3936e commit 2266a12
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 45 deletions.
54 changes: 16 additions & 38 deletions src/components/Filter.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Extent from '@arcgis/core/geometry/Extent';
import FeatureLayer from '@arcgis/core/layers/FeatureLayer';
import FeatureEffect from '@arcgis/core/layers/support/FeatureEffect';
import FeatureFilter from '@arcgis/core/layers/support/FeatureFilter';
import { useEffect, useRef } from 'react';
Expand All @@ -17,51 +16,30 @@ import { getStationQuery } from './queryHelpers';
const emptyDefinition = '1=0';

export default function Filter(): JSX.Element {
const { addLayers, mapView } = useMap();
const stationsLayer = useRef<FeatureLayer>();
const { stationsLayer, mapView } = useMap();
const { filter } = useFilter();
const initialized = useRef(false);

const { selectedStationIds, setSelectedStationIds } = useSelection();
useEffect(() => {
if (!mapView || !addLayers || initialized.current) {
if (!mapView || !stationsLayer) {
return;
}

stationsLayer.current = new FeatureLayer({
url: config.urls.stations,
definitionExpression: emptyDefinition,
outFields: [config.fieldNames.STATION_ID],
renderer: {
// @ts-expect-error - accessor has issues with TS
type: 'simple',
symbol: {
type: 'simple-marker',
color: '#DD5623',
outline: {
color: [0, 0, 0],
width: 1,
},
size: 12,
},
},
});

addLayers([stationsLayer.current]);

mapView.on('pointer-move', (event) => {
mapView.hitTest(event, { include: stationsLayer.current as FeatureLayer }).then((response) => {
mapView.hitTest(event, { include: stationsLayer }).then((response) => {
if (response.results.length > 0) {
mapView.container.style.cursor = 'pointer';
} else {
mapView.container.style.cursor = 'default';
}
});
});

mapView.on('click', (event) => {
mapView
.hitTest(event, {
include: stationsLayer.current as FeatureLayer,
include: stationsLayer,
})
.then((response) => {
if (response.results.length > 0) {
Expand Down Expand Up @@ -89,26 +67,26 @@ export default function Filter(): JSX.Element {
});

initialized.current = true;
}, [addLayers, mapView, setSelectedStationIds]);
}, [mapView, setSelectedStationIds, stationsLayer]);

useEffect(() => {
if (!stationsLayer.current) {
if (!stationsLayer) {
return;
}

if (Object.keys(filter).length > 0) {
const newQuery = getStationQuery(Object.values(filter));
console.log('new station query:', newQuery);
stationsLayer.current.definitionExpression = newQuery;
stationsLayer.definitionExpression = newQuery;
} else {
stationsLayer.current.definitionExpression = emptyDefinition;
stationsLayer.definitionExpression = emptyDefinition;
}

setSelectedStationIds(new Set());

stationsLayer.current
stationsLayer
.queryExtent({
where: stationsLayer.current.definitionExpression,
where: stationsLayer.definitionExpression,
})
.then((result) => {
if (mapView) {
Expand All @@ -129,26 +107,26 @@ export default function Filter(): JSX.Element {
}
}
});
}, [filter, mapView, setSelectedStationIds]);
}, [filter, mapView, setSelectedStationIds, stationsLayer]);

useEffect(() => {
if (!stationsLayer.current) {
if (!stationsLayer) {
return;
}

if (selectedStationIds.size === 0) {
// @ts-expect-error null is a valid value
stationsLayer.current.featureEffect = null;
stationsLayer.featureEffect = null;
} else {
const where = `${config.fieldNames.STATION_ID} IN ('${Array.from(selectedStationIds).join("','")}')`;
stationsLayer.current.featureEffect = new FeatureEffect({
stationsLayer.featureEffect = new FeatureEffect({
filter: new FeatureFilter({
where,
}),
excludedEffect: 'opacity(50%)',
});
}
}, [selectedStationIds]);
}, [selectedStationIds, stationsLayer]);

return (
<>
Expand Down
37 changes: 31 additions & 6 deletions src/components/ResultsGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { RowSelectionState, Updater } from '@tanstack/react-table';
import { Button, Spinner, Tab, TabList, TabPanel, Tabs, useFirebaseAuth } from '@ugrc/utah-design-system';
import { User } from 'firebase/auth';
import ky from 'ky';
import { SearchIcon, SquareXIcon } from 'lucide-react';
import config from '../config';
import { useFilter } from './contexts/FilterProvider';
import { useSelection } from './contexts/SelectionProvider';
import Download from './Download';
import { useMap } from './hooks';
import { getGridQuery, removeIrrelevantWhiteSpace } from './queryHelpers';
import { Table } from './Table';
import { getEventIdsForDownload, getResultOidsFromStationIds, getStationIdsFromResultRows } from './utils';
Expand Down Expand Up @@ -184,6 +186,7 @@ const columns = [

export default function ResultsGrid() {
const { filter } = useFilter();
const { stationsLayer, mapView } = useMap();

const { currentUser } = useFirebaseAuth();
const gridQuery = getGridQuery(Object.values(filter));
Expand Down Expand Up @@ -219,23 +222,45 @@ export default function ResultsGrid() {
setSelectedStationIds(getStationIdsFromResultRows(data, new Set(Object.keys(newSelection))));
}

const onZoomToSelection = () => {
if (!mapView || !stationsLayer) {
return;
}

stationsLayer
.queryExtent({
where: `${config.fieldNames.STATION_ID} IN ('${Array.from(selectedStationIds).join("','")}')`,
})
.then((result) => {
// handle if only a single feature was selected
if (result.count === 1) {
mapView.goTo({ target: result.extent.center, zoom: 12 });
} else {
mapView.goTo(result.extent);
}
});
};

return (
<>
<span className="absolute right-12 top-2 z-10 self-center">
Records: <strong>{data?.length}</strong>
<span className="absolute right-12 top-2 z-10 flex items-center gap-1 self-center">
Results: <strong>{data?.length}</strong>
{selectedStationIds.size > 0 && (
<span>
<>
{' '}
| Selected: <strong>{Object.keys(rowSelection).length}</strong>
<Button
variant="secondary"
size="extraSmall"
onPress={() => setSelectedStationIds(new Set())}
className="ml-2"
aria-label="clear selection"
>
Clear Selection
<SquareXIcon size={16} />
</Button>
<Button variant="secondary" size="extraSmall" onPress={onZoomToSelection} aria-label="zoom to selection">
<SearchIcon size={16} />
</Button>
</span>
</>
)}
</span>
<Tabs aria-label="results panel" className="h-full pt-1">
Expand Down
30 changes: 29 additions & 1 deletion src/components/contexts/MapProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import Graphic from '@arcgis/core/Graphic';
import FeatureLayer from '@arcgis/core/layers/FeatureLayer';
import MapView from '@arcgis/core/views/MapView';
import { useGraphicManager } from '@ugrc/utilities/hooks';
import PropTypes from 'prop-types';
import { createContext, ReactNode, useState } from 'react';
import { createContext, ReactNode, useRef, useState } from 'react';
import config from '../../config';

export const MapContext = createContext<{
mapView: MapView | null;
setMapView: (mapView: MapView) => void;
placeGraphic: (graphic: Graphic | Graphic[] | null) => void;
zoom: (geometry: __esri.GoToTarget2D) => void;
addLayers: (layers: __esri.Layer[]) => void;
stationsLayer: __esri.FeatureLayer | undefined;
} | null>(null);

export const MapProvider = ({ children }: { children: ReactNode }) => {
Expand Down Expand Up @@ -46,6 +49,30 @@ export const MapProvider = ({ children }: { children: ReactNode }) => {
mapView.map.addMany(layers);
};

const stationsLayer = useRef<FeatureLayer>();
if (mapView && !stationsLayer.current) {
stationsLayer.current = new FeatureLayer({
url: config.urls.stations,
definitionExpression: '1=0',
outFields: [config.fieldNames.STATION_ID],
renderer: {
// @ts-expect-error - accessor has issues with TS
type: 'simple',
symbol: {
type: 'simple-marker',
color: '#DD5623',
outline: {
color: [0, 0, 0],
width: 1,
},
size: 12,
},
},
});

addLayers([stationsLayer.current]);
}

return (
<MapContext.Provider
value={{
Expand All @@ -54,6 +81,7 @@ export const MapProvider = ({ children }: { children: ReactNode }) => {
placeGraphic,
zoom,
addLayers,
stationsLayer: stationsLayer.current,
}}
>
{children}
Expand Down

0 comments on commit 2266a12

Please sign in to comment.