Skip to content

Commit

Permalink
feat: enable identify
Browse files Browse the repository at this point in the history
  • Loading branch information
steveoh authored and stdavis committed Aug 14, 2024
1 parent 2ba1b63 commit 727214c
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 94 deletions.
20 changes: 13 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@
"@arcgis/core": "^4.30.9",
"@heroicons/react": "^2.1.5",
"@ugrc/layer-selector": "^6.2.7",
"@ugrc/utah-design-system": "^1.2.0",
"@ugrc/utah-design-system": "^1.2.1",
"firebase": "^10.12.4",
"ky": "^1.5.0",
"lodash.startcase": "^4.4.0",
"react": "^18.3.1",
"react-aria": "^3.34.1",
"react-aria-components": "^1.3.1",
Expand Down
18 changes: 8 additions & 10 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ import {
masqueradeProvider,
} from '@ugrc/utah-design-system';
import PropTypes from 'prop-types';
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useOverlayTrigger } from 'react-aria';
import { ErrorBoundary } from 'react-error-boundary';
import { useOverlayTriggerState } from 'react-stately';
import { MapContainer, Tip } from './components';
import { useAnalytics, useFirebaseApp } from './components/contexts';
import { useMap } from './components/hooks';
import { IdentifyInformation } from './components/Identify';
import config from './config';

const apiKey = import.meta.env.VITE_WEB_API;
Expand Down Expand Up @@ -58,6 +59,8 @@ const wkid = 26912;
export default function App() {
const app = useFirebaseApp();
const logEvent = useAnalytics();
const { zoom, placeGraphic } = useMap();
const [initialIdentifyLocation, setInitialIdentifyLocation] = useState();
const sideBarState = useOverlayTriggerState({ defaultOpen: true });
const sideBarTriggerProps = useOverlayTrigger(
{
Expand All @@ -74,8 +77,6 @@ export default function App() {
trayState,
);

const { zoom, placeGraphic } = useMap();

// initialize firebase performance metrics
useEffect(() => {
async function initPerformance() {
Expand Down Expand Up @@ -135,7 +136,7 @@ export default function App() {

const onClick = useCallback(
(event) => {
console.log('map click', event.mapPoint);
setInitialIdentifyLocation(event.mapPoint);
trayState.open(true);
},
[trayState],
Expand Down Expand Up @@ -178,20 +179,17 @@ export default function App() {
</Drawer>
<div className="relative flex flex-col flex-1 rounded">
<div className="relative flex-1 dark:rounded overflow-hidden">
<MapContainer />
<MapContainer onIdentifyClick={onClick} />
<Drawer
type="tray"
className="shadow-inner dark:shadow-white/20"
allowFullScreen
state={trayState}
{...trayTriggerProps}
>
<section className="px-6 pt-2 grid gap-2">
<section className="px-7 pt-2 grid gap-2">
<h2 className="text-center">What&#39;s there?</h2>
<p>
First, explore the map to find your desired location. Then, click on it to reveal additional details
about the area.
</p>
<IdentifyInformation apiKey={apiKey} location={initialIdentifyLocation} />
</section>
</Drawer>
</div>
Expand Down
29 changes: 29 additions & 0 deletions src/components/ExternalLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ReactNode } from 'react';

export const ExternalLink = ({ href, children }: { href: URL; children: ReactNode }) => (
<a
href={href}
target="_blank"
rel="noopener noreferrer nofollow"
className="inline-flex items-center gap-x-1 flex-wrap m-0"
>
{children}
<span aria-hidden="true">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="size-4"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"
></path>
</svg>
</span>
<span className="sr-only">opens in a new window</span>
</a>
);
196 changes: 120 additions & 76 deletions src/components/Identify.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import PropTypes from 'prop-types';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { isLoaded, load, project } from '@arcgis/core/geometry/projection';

import { toQueryString } from '@ugrc/utilities/src';

import { Label } from '@ugrc/utah-design-system';
import { toQueryString } from '@ugrc/utilities';
import ky from 'ky';
import './Identify.css';
import startCase from 'lodash.startcase';
import PropTypes from 'prop-types';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Text } from 'react-aria-components';
import { ExternalLink } from './ExternalLink';

const featureClassNames = {
counties: 'boundaries.county_boundaries',
Expand Down Expand Up @@ -50,7 +50,7 @@ const projectPoint = async (mapPoint, srid) => {
return project(mapPoint, { wkid: srid });
};

const IdentifyInformation = ({ apiKey, wkid = 3857, location }) => {
export const IdentifyInformation = ({ apiKey, wkid = 3857, location }) => {
const [spatial, setSpatial] = useState({
x: 0,
y: 0,
Expand Down Expand Up @@ -296,92 +296,136 @@ const IdentifyInformation = ({ apiKey, wkid = 3857, location }) => {
return () => controller.current?.abort();
}, [location, get, requests]);

if (!location) {
return (
<p>
First, explore the map to find your desired location. Then, click on it to reveal additional details about the
area.
</p>
);
}

return (
<dev className="identify">
<div>
<h4>What&apos;s here?</h4>
<hr />
</div>
<div>
<strong>Approximate Street Address</strong>
<p className="identify--muted">
<span className="d-block">{address}</span>
<a href={spatial.googleMapsLink} className="text-info" target="_blank" rel="noopener noreferrer">
<div className="grid grid-cols-2 lg:grid-cols-5 lg:gap-4 gap-10 mx-auto">
<div
className="flex flex-col gap-1 px-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded"
role="presentation"
>
<Label>Approximate Street Address</Label>
<Text className="block text-sm pl-1">
<Text className="block text-sm pl-1">{address}</Text>
<ExternalLink href={spatial.googleMapsLink} className="pl-1">
Google Street View
</a>
</p>
</ExternalLink>
</Text>
<Text className="text-xs block grow content-end">
Provided by{' '}
<ExternalLink href="https://gis.utah.gov/products/sgid/transportation/road-centerlines/">roads</ExternalLink>
</Text>
</div>
<div>
<strong>City</strong>
<p className="identify--muted">{city}</p>
<div
className="flex flex-col gap-1 px-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded"
role="presentation"
>
<Label>City</Label>
<Text className="block text-sm pl-1">{city}</Text>
<Text className="text-xs block grow content-end">
Provided by{' '}
<ExternalLink href="https://gis.utah.gov/products/sgid/boundaries/municipal/">
municipal boundaries
</ExternalLink>
</Text>
</div>
<div>
<strong>Zip Code</strong>
<p className="identify--muted">{zip}</p>
<div
className="flex flex-col gap-1 px-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded"
role="presentation"
>
<Label>Zip code</Label>
<Text className="block text-sm pl-1">{zip}</Text>
<Text className="text-xs block grow content-end">
Provided by{' '}
<ExternalLink href="https://gis.utah.gov/products/sgid/boundaries/zip-codes/">zip code areas</ExternalLink>
</Text>
</div>
<div>
<strong>County</strong>
<p className="identify--muted">{county}</p>
<div
className="flex flex-col gap-1 px-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded"
role="presentation"
>
<Label>County</Label>
<Text className="block text-sm pl-1">{startCase(county.toLowerCase())}</Text>
<Text className="text-xs block grow content-end">
Provided by{' '}
<ExternalLink href="https://gis.utah.gov/products/sgid/boundaries/county/">county boundaries</ExternalLink>
</Text>
</div>
<div>
<strong>UTM 12 NAD83 Coordinates</strong>
<p className="identify--muted">
{spatial.x}, {spatial.y} meters
</p>
<div
className="flex flex-col gap-1 px-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded"
role="presentation"
>
<Label>UTM 12 NAD83 coordinates</Label>
<Text className="block text-sm pl-1">
{spatial.x}, {spatial.y} m
</Text>
</div>
<div>
<strong>WGS84 Coordinates</strong>
<p className="identify--muted">
<div
className="flex flex-col gap-1 px-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded"
role="presentation"
>
<Label>WGS84 coordinates</Label>
<Text className="block text-sm pl-1">
{spatial.lat}, {spatial.lon}
</p>
</div>
<div>
<strong>Elevation Meters</strong>
<p className="identify--muted">{elevation.meters}</p>
</Text>
</div>
<div>
<strong>Elevation Feet</strong>
<p className="identify--muted">{elevation.feet}</p>
<div
className="flex flex-col gap-1 px-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded"
role="presentation"
>
<Label>Elevation</Label>
<Text className="block text-sm pl-1">{elevation.meters} m</Text>
<Text className="block text-sm pl-1">{elevation.feet} ft</Text>
<Text className="text-xs block grow content-end">
Provided by <ExternalLink href="https://elevation.nationalmap.gov/">The National Map</ExternalLink>
</Text>
</div>
<div>
<strong>Land Administration Category</strong>
<p className="identify--muted">{ownership}</p>
<div
className="flex flex-col gap-1 px-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded"
role="presentation"
>
<Label>Land administration category</Label>
<Text className="block text-sm pl-1">{ownership}</Text>
<Text className="text-xs block grow content-end">
Provided by{' '}
<ExternalLink href="https://gis.utah.gov/products/sgid/cadastre/land-ownership/">land ownership</ExternalLink>
</Text>
</div>
<div>
<strong>US National Grid</strong>
<p className="identify--muted">{grid}</p>
<div
className="flex flex-col gap-1 px-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded"
role="presentation"
>
<Label>US National Grid</Label>
<Text className="block text-sm pl-1">{grid}</Text>
<Text className="text-xs block grow content-end">
Provided by the{' '}
<ExternalLink href="https://gis.utah.gov/products/sgid/indices/national-grid-index/">
national grid
</ExternalLink>
</Text>
</div>
<div>
<strong>Imagery Flight Data</strong>
<p className="identify--muted">{flightDate.date && `${flightDate.resolution} on ${flightDate.date}`}</p>
<div
className="flex flex-col gap-1 px-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded"
role="presentation"
>
<Label>Imagery flight metadata</Label>
<Text className="block text-sm pl-1">
{flightDate.date && `${flightDate.resolution} on ${flightDate.date}`}
</Text>
</div>
</dev>
);
};

IdentifyInformation.propTypes = {
location: PropTypes.object,
};

const IdentifyContainer = function ({ show, children }) {
return (
<div className="identify__container side-bar side-bar--with-border side-bar--open">
<button type="button" className="identify__close" aria-label="Close" onClick={() => show(false)}>
<span aria-hidden="true">&times;</span>
</button>
{children}
</div>
);
};

IdentifyContainer.propTypes = {
show: PropTypes.func.isRequired,
children: PropTypes.node.isRequired,
};

export { IdentifyContainer, IdentifyInformation };

IdentifyInformation.propTypes = {
location: PropTypes.object,
apiKey: PropTypes.string.isRequired,
wkid: PropTypes.number,
};

0 comments on commit 727214c

Please sign in to comment.