Skip to content

Commit

Permalink
map settings pane content
Browse files Browse the repository at this point in the history
  • Loading branch information
nofurtherinformation committed Jul 31, 2024
1 parent 5d5c664 commit 2776e94
Show file tree
Hide file tree
Showing 20 changed files with 266 additions and 110 deletions.
8 changes: 3 additions & 5 deletions app/map/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Map from "components/Pages/Map"
import MapPageInner from "components/Pages/Map"
import { getMdxContent } from "hooks/useMdxContent"

export const metadata = {
Expand All @@ -7,12 +7,10 @@ export const metadata = {

export default async function MapPage() {
const pageInfo = await getMdxContent("page", "map.mdx")
// @ts-ignore
const contentSections = pageInfo.data.page.sections

return (
<>
<Map contentSections={contentSections} />
{/* @ts-ignore */}
<MapPageInner pageInfo={pageInfo} />
</>
)
}
8 changes: 5 additions & 3 deletions components/EnhancedMarkdown/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ export const MdTooltip: React.FC<{ tooltipKey?: string; body?: any }> = ({ toolt
if (!innerContent) return null

return (
<Tooltip explainer={""} open={open} defaultOpen={false} onOpenChange={handleToggleOpen} withArrow={true}>
<TinaMarkdown content={innerContent} />
</Tooltip>
<div className="inline">
<Tooltip explainer={""} open={open} defaultOpen={false} onOpenChange={handleToggleOpen} withArrow={true}>
<TinaMarkdown content={innerContent} />
</Tooltip>
</div>
)
}
10 changes: 9 additions & 1 deletion components/Legend/Legend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,15 @@ const HighlightLegend: React.FC<{ highlight?: string; value?: readonly any[]; co
background: `rgb(${color.join(",")}`,
}}
></span>
{highlight} ( &gt;{value}%){" "}
{highlight}{" "}
{!!(Array.isArray(value) && value.every((n) => !isNaN(n as number))) ? (
<>
{/* @ts-ignore */}
{+value[0] * 100}% - {+value[1] * 100}%{" "}
</>
) : (
<>( &gt;{value}%) </>
)}
</p>
)
}
2 changes: 1 addition & 1 deletion components/Map/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ export const Map: React.FC<MapProps> = ({ initialFilter, simpleMap = false, onCl
)}
</div>
<div className="relative flex size-full flex-row border-4">
{!simpleMap && <MapSettings contentSections={contentSections} />}
{!simpleMap && <MapSettings contentSections={contentSections as any} />}
<div ref={parentRef} className="relative size-full">
<GlMap
// hash={true}
Expand Down
59 changes: 46 additions & 13 deletions components/MapSettings/MapSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"
import React, { useMemo, useState } from "react"
import { TinaMarkdown } from "tinacms/dist/rich-text"
import CountyFilterSelector from "components/CountyFilterSelector"
import { EnhancedMarkdown } from "components/EnhancedMarkdown"
import { MapInfoSection } from "components/MapInfoSection/MapInfoSection"
import { StatefulHighlightColorPicker } from "components/StatefulControls/StatefulHighlightColorPicker"
import { StatefulHighlightForm } from "components/StatefulControls/StatefulMapFilterSlider"
Expand Down Expand Up @@ -36,12 +36,20 @@ const SettingsConfig: Array<{ label: string; icon: keyof typeof Icons }> = [
// icon: "Layers"
// }
]
const contentSectionTitles = ["topics"]
const contentSectionTitles = [
"topics",
"available data",
"market highlights",
"community highlights",
"highlight advanced",
"filter map",
]

const findContentSections = (contentSections: any[], titles: string[] = contentSectionTitles) => {
const entries: Record<string, React.ReactNode> = {}
for (const title of titles) {
const data: any = contentSections.find((section) => section.title === title)
entries[title] = data ? <TinaMarkdown content={data.body} /> : null
entries[title] = data ? <EnhancedMarkdown content={data.body} /> : null
}
return entries
}
Expand Down Expand Up @@ -70,7 +78,7 @@ export const MapSettings: React.FC<{ contentSections: any[] }> = ({ contentSecti

return (
<>
<div className={`h-full w-10 flex-none border-r-2 border-neutral-500 bg-white`}>
<div className={`h-full w-10 flex-none border-r-2 border-neutral-500 bg-white`} id="map-settings-ribbon">
{SettingsConfig.map((config, i) => (
<button
key={i}
Expand All @@ -83,7 +91,7 @@ export const MapSettings: React.FC<{ contentSections: any[] }> = ({ contentSecti
</button>
))}
</div>
<div className={`flex w-auto flex-none flex-col overflow-x-hidden bg-none`}>
<div className={`flex w-auto flex-none flex-col overflow-x-hidden bg-none`} id="map-settings-pane">
{!!clicked && (
<div
className={`${!!activeMenuSection ? "max-h-[50vh]" : "max-h-none"} h-full overflow-y-auto
Expand All @@ -95,7 +103,7 @@ export const MapSettings: React.FC<{ contentSections: any[] }> = ({ contentSecti
)}
{!!activeMenuSection?.length && (
<div
className={`relative flex h-full max-h-[50vh] overflow-y-auto ${
className={`relative flex h-full overflow-y-auto ${
activeMenuSection ? "w-96 border-r-2 border-neutral-500" : "w-0"
} flex-col`}
>
Expand All @@ -111,6 +119,7 @@ export const MapSettings: React.FC<{ contentSections: any[] }> = ({ contentSecti
)}
<MenuSection title="Topics" isActive={activeMenuSection === "Map Layers"}>
{sections["topics"]}
<br />
{Object.keys(columnGroups).map((group, i) => (
<MenuButton
key={i}
Expand All @@ -121,6 +130,8 @@ export const MapSettings: React.FC<{ contentSections: any[] }> = ({ contentSecti
))}
</MenuSection>
<MenuSection title="Available Data" isActive={activeMenuSection === "Map Layers"}>
{sections["available data"]}
<br />
{availableColumns.map((c, i) => (
<MenuButton key={i} onClick={() => handleSetColumn(c)} label={c} selected={currentColumn === c} />
))}
Expand All @@ -131,7 +142,10 @@ export const MapSettings: React.FC<{ contentSections: any[] }> = ({ contentSecti
title="Highlight areas on the map"
titleChildren={<Tooltip explainer={<>Choose a color</>}></Tooltip>}
>
<p>Communities and Socioeconomics</p>
<br />
{sections["community highlights"]}
<br />
<br />
{Object.keys(communityHighlightConfig).map((name, i) => (
<MenuButton
key={i}
Expand All @@ -142,8 +156,18 @@ export const MapSettings: React.FC<{ contentSections: any[] }> = ({ contentSecti
selected={highlight === name}
/>
))}
{highlightType === "community" && <StatefulHighlightForm />}
<p className="pt-8">Corporate Market Dominance</p>
{highlightType === "community" && (
<>
<br />
<br />
<StatefulHighlightForm />
</>
)}
<br />
<br />
{sections["market highlights"]}
<br />
<br />

{Object.keys(parentCompanyHighlightConfig).map((name, i) => (
<MenuButton
Expand All @@ -155,20 +179,29 @@ export const MapSettings: React.FC<{ contentSections: any[] }> = ({ contentSecti
selected={highlight === name}
/>
))}
{highlightType === "parent" && <StatefulHighlightForm />}
{highlightType === "parent" && (
<>
<br />
<br />
<StatefulHighlightForm />
</>
)}
<div className="mt-4 flex flex-row items-center gap-4">
<p className="text-xs">Choose Color (Advanced)</p>
{sections["highlight advanced"]}
<StatefulHighlightColorPicker />
</div>

{/* color picker */}
</MenuSection>
<MenuSection title="Filter Map" isActive={activeMenuSection === "Filter Map"}>
{sections["filter map"]}
<br />
<br />
<CountyFilterSelector handleSetFilter={handleSetFilter} currentFilter={filter} />
</MenuSection>
<MenuSection title="Map Colors" isActive={activeMenuSection === "Map Colors"}>
{/* <MenuSection title="Map Colors" isActive={activeMenuSection === "Map Colors"}>
fixed or relative [coming soon]
</MenuSection>
</MenuSection> */}
{/* <DropdownMenuDemo>
<div className="max-w-[100vw] p-4">
<p>Choose a topic</p>
Expand Down
5 changes: 5 additions & 0 deletions components/Pages/Map/Client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"use client"
import { Renderer } from "./Renderer"
import withClient from "../ClientPageWrapper"

export default withClient(Renderer)
4 changes: 3 additions & 1 deletion components/Pages/Map/Renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import React from "react"
// lazy load the map
const Map = dynamic(() => import("components/Map/Map"), { ssr: false })

export const Renderer: React.FC<{ contentSections: any }> = ({ contentSections }) => {
export const Renderer: React.FC<{ pageInfo: any }> = ({ pageInfo }) => {
const contentSections = pageInfo.data.page.sections

return (
<>
<Map contentSections={contentSections} />
Expand Down
4 changes: 3 additions & 1 deletion components/Pages/Map/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import IS_DEV from "utils/isDev"
import ClientRenderer from "./Client"
import { Renderer } from "./Renderer"

export default Renderer
export default IS_DEV ? ClientRenderer : Renderer
19 changes: 14 additions & 5 deletions components/StatefulControls/StatefulHighlightColorPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,30 @@ export const StatefulHighlightColorPicker = () => {
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
const dispatch = useAppDispatch()
const highlightColor = useAppSelector((state) => state.map.highlightColor)
const highlight = useAppSelector((state) => state.map.highlight)
const [highlightInner, setHighlightInner] = useState<any>("")

const highlightColorString = highlightColor
? `#${tinycolor({ r: highlightColor[0], g: highlightColor[1], b: highlightColor[2] }).toHex()}`
: "#000000"
const [innerValue, setInnerValue] = useState<string>(highlightColorString)

useEffect(() => {
timeoutRef.current && clearTimeout(timeoutRef.current)
timeoutRef.current = setTimeout(() => {
dispatch(setHighlightColor(innerValue))
}, 500)
if (highlightInner !== highlight) {
// external change
setHighlightInner(highlight)
setInnerValue(highlightColorString)
} else {
timeoutRef.current && clearTimeout(timeoutRef.current)
timeoutRef.current = setTimeout(() => {
dispatch(setHighlightColor(innerValue))
}, 500)
}
return () => {
timeoutRef.current && clearTimeout(timeoutRef.current)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [highlightColor])
}, [innerValue, highlight])

return (
<input type="color" value={innerValue} defaultValue={innerValue} onChange={(e) => setInnerValue(e.target.value)} />
Expand Down
2 changes: 1 addition & 1 deletion components/StatefulControls/StatefulMapFilterSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const StatefulHighlightForm = () => {

return (
<>
<p>Highlight: {highlight}</p>
<p className="text-xs font-bold uppercase">Highlight: {highlight}</p>
<SliderRange
value={innerValue}
min={highlightConfigValue.range[0]}
Expand Down
66 changes: 65 additions & 1 deletion public/content/page/map.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,70 @@
---
sections:
- title: filter map
body: >
Use the dropdown menu to filter the map to a particular state or county of
interest. While the dropdown is open, you may type on your keyboard to
quickly find your state or county.
>
Please note that the color scale of the map will change to reflect the
values relative to your filter, but may not be comparable across different
filters.
<Tooltip
body={<>
By default, whenever the map is filtered it will display values based on a quantile scale of equal counts of census tracts. Bivariate data options will show three equal count bins (terciles) on two dimensions (9 total bins/colors) and single variable options will show five equal count bins (quintiles).
</>}
/>
- title: highlight advanced
body: |
Advanced: Use the color picker below to change the highlight color
- title: community highlights
body: >
**Community Highlights:**
Use the buttons below to highlight areas with the available demographic or economic characteristics.
<Tooltip
body={<>
Data via Census American Community Survey (ACS) 2021 5-year estimates.
</>}
/>
Use the slider to change the range of estimated market share for that
community. Only one highlight may be active at a time.
- title: market highlights
body: >
**Market Highlights:** Use the buttons below to highlight areas where a
national brand is present in the local market. Use the slider to change
the range of estimated market share for that company.
<Tooltip
body={<>
Sales data are modeled estimates from Data Axle / InfoGroup ReferenceUSA. Stores include dollar stores, and general merchandise and warehouse stores sales have been adjusted based on category sales.
</>}
/>
- title: available data
body: |
The following data are available for this topic:
- title: topics
body: ''
body: |
Choose from the below data topics to see available map data.
<Tooltip
title="Bivariate maps"
body={<>
All maps use quantiles, or equal count groups of census tracts, to color the map.
Bivariate maps present two data sets together. The color scales combine to show where the two data variables intersect.
</>}
key="Bivariate maps"
/>
---

3 changes: 3 additions & 0 deletions styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ footer img {
}
.four-up h3 {
@apply text-2xl
}
#map-settings-pane p {
@apply inline text-sm
}
2 changes: 1 addition & 1 deletion tina/__generated__/_graphql.json

Large diffs are not rendered by default.

Loading

0 comments on commit 2776e94

Please sign in to comment.