Skip to content

Commit

Permalink
feat: add buffered point and polyline options to shape filter
Browse files Browse the repository at this point in the history
Closes #697
  • Loading branch information
stdavis committed Nov 20, 2024
1 parent 5ac19c4 commit ba37afd
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 121 deletions.
47 changes: 0 additions & 47 deletions src/components/search-wizard/filters/Buffer.jsx

This file was deleted.

64 changes: 64 additions & 0 deletions src/components/search-wizard/filters/Buffer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { buffer } from '@arcgis/core/geometry/geometryEngine';
import { isLoaded, load, project } from '@arcgis/core/geometry/projection';
import PropTypes from 'prop-types';
import { useEffect, useState } from 'react';
import Input from '../../../utah-design-system/Input';
import Geometry from '@arcgis/core/geometry/Geometry';

type BufferProps = {
className?: string;
// eslint-disable-next-line no-unused-vars
onChange: (value: Geometry) => void;
inputGeometry: Geometry | null;
allowZero?: boolean;
};
export default function Buffer({
className,
onChange,
inputGeometry,
allowZero,
}: BufferProps) {
const [bufferMiles, setBufferMiles] = useState(allowZero ? 0 : 0.1);

useEffect(() => {
const giddyUp = async () => {
if (inputGeometry) {
let geometry = inputGeometry.clone();
if (allowZero && bufferMiles === 0) {
onChange(geometry);
} else {
if (geometry.spatialReference.wkid === 4326) {
if (!isLoaded()) {
await load();
}
geometry = (await project(geometry, { wkid: 26912 })) as Geometry;
}
onChange(buffer(geometry, bufferMiles, 'miles') as Geometry);
}
} else {
onChange(null);
}
};
giddyUp();
}, [allowZero, bufferMiles, inputGeometry, onChange]);

const invalidBuffer = allowZero ? false : bufferMiles < 0.1;

return (
<Input
className={className}
label={allowZero ? 'Buffer (miles)' : 'Buffer (miles, min: 0.1)'}
value={bufferMiles}
onChange={setBufferMiles}
invalid={invalidBuffer}
message={invalidBuffer ? 'Buffer must be at least 0.1 miles.' : null}
type="number"
/>
);
}

Buffer.propTypes = {
className: PropTypes.string,
onChange: PropTypes.func.isRequired,
inputGeometry: PropTypes.object,
};
73 changes: 0 additions & 73 deletions src/components/search-wizard/filters/Shape.jsx

This file was deleted.

106 changes: 106 additions & 0 deletions src/components/search-wizard/filters/Shape.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import GraphicsLayer from '@arcgis/core/layers/GraphicsLayer';
import Sketch from '@arcgis/core/widgets/Sketch';
import PropTypes from 'prop-types';
import { useEffect, useState } from 'react';
import useMap from '../../../contexts/useMap';
import Buffer from './Buffer';
import Geometry from '@arcgis/core/geometry/Geometry';

type ShapeProps = {
// eslint-disable-next-line no-unused-vars
send: (value: {
type: string;
filter?: {
geometry: Geometry | null;
name: string;
};
}) => void;
};

export default function Shape({ send }: ShapeProps) {
const { mapView } = useMap();
const [bufferGeometry, setBufferGeometry] = useState<Geometry | null>(null);
const [sketchGeometry, setSketchGeometry] = useState<Geometry | null>(null);

useEffect(() => {
if (!mapView) return;

const layer = new GraphicsLayer();
mapView.map.add(layer);
const sketch = new Sketch({
availableCreateTools: [
'polygon',
'rectangle',
'circle',
'point',
'polyline',
],
creationMode: 'single',
layer,
layout: 'vertical',
view: mapView,
visibleElements: {
selectionTools: {
'rectangle-selection': false,
'lasso-selection': false,
},
settingsMenu: false,
},
});

sketch.create('polygon');

sketch.on('create', (event) => {
if (event.state === 'start') {
layer.removeAll();
} else if (event.state === 'complete') {
setSketchGeometry(event.graphic.geometry);
}
});

mapView.ui.add(sketch, 'top-right');

return () => {
if (sketch) {
sketch.destroy();
}
if (sketch && mapView?.ui) {
mapView.ui.remove(sketch);
}
if (layer && mapView.map) {
mapView.map.remove(layer);
}
};
}, [mapView, send]);

useEffect(() => {
send({
type: 'SET_FILTER',
filter: {
geometry: bufferGeometry,
name: 'User-drawn Shape',
},
});
}, [bufferGeometry, send]);

const bufferGeometryTypes = ['point', 'polyline'];

return (
<>
<p>Use the toolbar on the map to draw a shape.</p>
<p>Click once to create a new vertex.</p>
<p>Double-click to finish the shape.</p>
<Buffer
onChange={setBufferGeometry}
inputGeometry={sketchGeometry}
allowZero={!bufferGeometryTypes.includes(sketchGeometry?.type)}
/>
{/* buffer to make sure user can scroll far enough to see the entire select filter type dropdown */}
<div className="h-28" />
</>
);
}

Shape.propTypes = {
send: PropTypes.func.isRequired,
};
2 changes: 1 addition & 1 deletion src/components/search-wizard/filters/StreetAddress.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import appConfig from '../../../app-config.js';
import Sherlock, {
LocatorSuggestProvider,
} from '../../../utah-design-system/Sherlock.jsx';
import Buffer from './Buffer.jsx';
import Buffer from './Buffer';

export default function StreetAddress({ send }) {
const [sherlockConfig, setSherlockConfig] = useState(null);
Expand Down
8 changes: 8 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,11 @@ body {
.esri-view .esri-view-surface--inset-outline:focus::after {
@apply outline-none;
}

/* make sketch toolbar look nicer */
.esri-sketch__panel .esri-sketch__section {
margin-left: 0;
margin-right: 0;
padding-top: 0;
padding-bottom: 0;
}

0 comments on commit ba37afd

Please sign in to comment.