Skip to content

Commit

Permalink
Merge pull request #349 from policy-design-lab/release-1.5.0
Browse files Browse the repository at this point in the history
Release 1.5.0
  • Loading branch information
pengyin-shan authored Dec 10, 2024
2 parents 93d23b8 + 3bb6ecd commit 76428ab
Show file tree
Hide file tree
Showing 14 changed files with 203 additions and 137 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [1.5.0] - 2024-12-10

### Changed
- Changed all 'grey' word of the site into 'gray' to accommodate US language practice [#341](https://github.com/policy-design-lab/pdl-frontend/issues/341)
- Changed comma-handled multi-practice selecting query to delimiter-handled query for EQIP and CSP total page selector [#344](https://github.com/policy-design-lab/pdl-frontend/issues/344)

### Fixed
- Fixed the bug where the map tips lagged in rendering HTML code and processing styles on the EQIP and CSO total page [#345](https://github.com/policy-design-lab/pdl-frontend/issues/345)

## [1.4.0] - 2024-11-26

### Added
Expand Down Expand Up @@ -310,6 +319,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Map data json [#12](https://github.com/policy-design-lab/pdl-frontend/issues/12)
- Final landing page changes for initial milestone [#15](https://github.com/policy-design-lab/pdl-frontend/issues/15)

[1.5.0]: https://github.com/policy-design-lab/pdl-frontend/compare/1.4.0...1.5.0
[1.4.0]: https://github.com/policy-design-lab/pdl-frontend/compare/1.3.0...1.4.0
[1.3.0]: https://github.com/policy-design-lab/pdl-frontend/compare/1.2.0...1.3.0
[1.2.0]: https://github.com/policy-design-lab/pdl-frontend/compare/1.1.0...1.2.0
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "policy-design-lab",
"version": "1.4.0",
"version": "1.5.0",
"description": "the front end of policy design lab",
"repository": "https://github.com/policy-design-lab/pdl-frontend",
"main": "src/app.tsx",
Expand Down
2 changes: 1 addition & 1 deletion src/components/acep/ACEPTotalMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ const titleElement = (attribute, year): JSX.Element => {
<strong>{attribute}</strong> Benefits from <strong>{year}</strong>
</Typography>{" "}
<Typography noWrap style={{ fontSize: "0.5em", color: "#AAA", textAlign: "center" }}>
<i>In any state that appears in grey, there is no available data</i>
<i>In any state that appears in gray, there is no available data</i>
</Typography>
</Box>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/crp/CRPTotalMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ const titleElement = (attribute, year): JSX.Element => {
<strong>{attribute}</strong> Benefits from <strong>{year}</strong>
</Typography>{" "}
<Typography noWrap style={{ fontSize: "0.5em", color: "#AAA", textAlign: "center" }}>
<i>In any state that appears in grey, there is no available data</i>
<i>In any state that appears in gray, there is no available data</i>
</Typography>
</Box>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/crp/CategoryMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ const titleElement = (attribute, year): JSX.Element => {
<strong>{attribute}</strong> Benefits from <strong>{year}</strong>
</Typography>{" "}
<Typography noWrap style={{ fontSize: "0.5em", color: "#AAA", textAlign: "center" }}>
<i>In any state that appears in grey, there is no available data</i>
<i>In any state that appears in gray, there is no available data</i>
</Typography>
</Box>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/csp/CategoryMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ const titleElement = (attribute, year): JSX.Element => {
<strong>{attribute}</strong> Benefits from <strong>{year}</strong>
</Typography>{" "}
<Typography noWrap style={{ fontSize: "0.5em", color: "#AAA", textAlign: "center" }}>
<i>In any state that appears in grey, there is no available data</i>
<i>In any state that appears in gray, there is no available data</i>
</Typography>
</Box>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/eqip/CategoryMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ const titleElement = (attribute, year): JSX.Element => {
<strong>{attribute}</strong> Benefits from <strong>{year}</strong>
</Typography>{" "}
<Typography noWrap style={{ fontSize: "0.5em", color: "#AAA", textAlign: "center" }}>
<i>In any state that appears in grey, there is no available data</i>
<i>In any state that appears in gray, there is no available data</i>
</Typography>
</Box>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/ira/IRADollarMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ const IRADollarMap = ({
thresholds.push(nonZeroData[adjustedIndex]);
}
const colorScale = d3.scaleThreshold().domain(thresholds).range(mapColor);
// For IRA, only if all practices are zero, the state will be colored as grey
// For IRA, only if all practices are zero, the state will be colored as gray
let zeroPoints = [];
statePerformance[year].forEach((state) => {
if (practices[0] === "Total") {
Expand Down
2 changes: 1 addition & 1 deletion src/components/ira/IRAPredictedMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ const IRAPredictedMap = ({
thresholds.push(nonZeroData[adjustedIndex]);
}
const colorScale = d3.scaleThreshold().domain(thresholds).range(mapColor);
// For IRA, only if all practices are zero, the state will be colored as grey
// For IRA, only if all practices are zero, the state will be colored as gray
let zeroPoints = [];
predictedPerformance[year].forEach((state) => {
if (practices[0] === "Total") {
Expand Down
2 changes: 1 addition & 1 deletion src/components/rcpp/RCPPTotalMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ const titleElement = (attribute, year): JSX.Element => {
<strong>{attribute}</strong> Benefits from <strong>{year}</strong>
</Typography>{" "}
<Typography noWrap style={{ fontSize: "0.5em", color: "#AAA", textAlign: "center" }}>
<i>In any state that appears in grey, there is no available data</i>
<i>In any state that appears in gray, there is no available data</i>
</Typography>
</Box>
);
Expand Down
4 changes: 2 additions & 2 deletions src/components/shared/DrawLegend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,15 @@ export default function DrawLegend({
.attr("class", "legendTextSide")
.attr("x", -1000)
.attr("y", -1000)
.text("In any state that appears in grey, there is no available data");
.text("In any state that appears in gray, there is no available data");
const middleBox = middleText.node().getBBox();
middleText.remove();
baseSVG
.append("text")
.attr("class", "legendTextSide")
.attr("x", (svgWidth + margin * 2) / 2 - middleBox.width / 2)
.attr("y", 80)
.text("In any state that appears in grey, there is no available data");
.text("In any state that appears in gray, there is no available data");
}
} else {
baseSVG.attr("height", 40);
Expand Down
160 changes: 101 additions & 59 deletions src/components/shared/titleii/TitleIIPracticeMap.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useMemo } from "react";
import { CircularProgress } from "@mui/material";
import { geoCentroid } from "d3-geo";
import { ComposableMap, Geographies, Geography, Marker, Annotation } from "react-simple-maps";
import ReactTooltip from "react-tooltip";
Expand Down Expand Up @@ -48,11 +49,22 @@ const MapChart = ({
year,
stateCodes,
colorScale,
selectedPractices
selectedPractices,
classes
}) => {
const classes = useStyles();
const handleMouseEnter = React.useCallback(
(geo, record) => {
const tooltipContent = computeTooltipContent(geo, record, selectedPractices, classes, getNationalTotal);
setReactTooltipContent(tooltipContent);
},
[selectedPractices, classes, getNationalTotal]
);
const handleMouseLeave = React.useCallback(() => {
setReactTooltipContent("");
}, []);

return (
<div data-tip="">
<div data-tip="" data-for="map-tooltip">
<ComposableMap projection="geoAlbersUsa">
<Geographies geography={geoUrl}>
{({ geographies }) => (
Expand All @@ -73,18 +85,8 @@ const MapChart = ({
<Geography
key={geo.rsmKey}
geography={geo}
onMouseEnter={() => {
const tooltipContent = computeTooltipContent(
geo,
record,
selectedPractices,
classes,
getNationalTotal
);
ReactTooltip.rebuild();
setReactTooltipContent(tooltipContent);
}}
onMouseLeave={() => setReactTooltipContent("")}
onMouseEnter={() => handleMouseEnter(geo, record)}
onMouseLeave={handleMouseLeave}
fill={colorScale(practiceTotal || 0) || "#D2D2D2"}
stroke="#FFF"
style={{
Expand Down Expand Up @@ -130,20 +132,6 @@ const MapChart = ({
</div>
);
};

function encodeQueryParams(params) {
return Object.entries(params)
.map(([key, value]) => {
const encodedValue = encodeURIComponent(value);
return `${key}=${encodedValue}`;
})
.join("&");
}

function buildURL(baseUrl, params) {
const encodedParams = encodeQueryParams(params);
return `${baseUrl}?${encodedParams}`;
}
const TitleIIPracticeMap = ({
programName,
initialStatePerformance,
Expand All @@ -158,6 +146,38 @@ const TitleIIPracticeMap = ({
const classes = useStyles();
const [selectedPractices, setSelectedPractices] = useState<string[]>(["All Practices"]);
const [isLoading, setIsLoading] = useState(false);
const [tooltipVisible, setTooltipVisible] = useState(false);
// help tooltip style to load without lag
React.useEffect(() => {
if (content) {
ReactTooltip.hide();
ReactTooltip.rebuild();
setTooltipVisible(true);
} else {
setTooltipVisible(false);
}
}, [content]);
React.useEffect(() => {
const style = document.createElement("style");
style.innerHTML = `
.__react_component_tooltip {
padding: 0 !important;
margin: 0 !important;
opacity: 1 !important;
}
.__react_component_tooltip.show {
opacity: 1 !important;
}
`;
document.head.appendChild(style);
return () => {
ReactTooltip.hide();
document.head.removeChild(style);
};
}, []);
const setTooltipContent = React.useCallback((newContent) => {
setContent(newContent);
}, []);

const practiceCategories = useMemo(() => {
return getPracticeCategories(practiceNames);
Expand All @@ -183,7 +203,7 @@ const TitleIIPracticeMap = ({
setStatePerformance(initialStatePerformance);
return;
}
const encodedCodes = selectedCodes.map((code) => encodeURIComponent(code)).join(",");
const encodedCodes = selectedCodes.map((code) => encodeURIComponent(code)).join("|");
const url = `${
config.apiUrl
}/titles/title-ii/programs/${programName.toLowerCase()}/state-distribution?practice_code=${encodedCodes}`;
Expand Down Expand Up @@ -214,11 +234,6 @@ const TitleIIPracticeMap = ({
}
fetchStatePerformanceData(newSelected);
};

React.useEffect(() => {
ReactTooltip.rebuild();
}, [statePerformance, selectedPractices]);

const practiceData = useMemo(() => {
return getPracticeData(statePerformance, year, selectedPractices);
}, [statePerformance, year, selectedPractices]);
Expand Down Expand Up @@ -247,6 +262,38 @@ const TitleIIPracticeMap = ({
}
fetchStatePerformanceData(newSelected);
};
const tooltipComponent = useMemo(
() => (
<ReactTooltip
id="map-tooltip"
className={`${classes.customized_tooltip} tooltip`}
backgroundColor={tooltipBkgColor}
effect="float"
html
getContent={() => (tooltipVisible ? content : null)}
overridePosition={({ left, top }, _e, _t, node) => {
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
if (!node) return { left, top };
const tooltipRect = node.getBoundingClientRect();

let updatedLeft = left;
let updatedTop = top;

if (left + tooltipRect.width > viewportWidth) {
updatedLeft = viewportWidth - tooltipRect.width - 10;
}
if (top + tooltipRect.height > viewportHeight) {
updatedTop = viewportHeight - tooltipRect.height - 10;
}

return { left: updatedLeft, top: updatedTop };
}}
/>
),
[classes, content, tooltipVisible]
);

const shouldShowLoading = isLoading && !selectedPractices.includes("All Practices");
const hasValidData = statePerformance && statePerformance[year] && statePerformance[year].length > 0;
if (!hasValidData && !shouldShowLoading) {
Expand Down Expand Up @@ -349,32 +396,27 @@ const TitleIIPracticeMap = ({

{shouldShowLoading ? (
<Box display="flex" justifyContent="center" mt={4}>
<Typography>Loading data...</Typography>
<CircularProgress />
</Box>
) : (
hasValidData && (
<MapChart
getNationalTotal={getNationalTotal}
setReactTooltipContent={setContent}
maxValue={maxValue}
allStates={allStates}
statePerformance={statePerformance}
year={year}
stateCodes={stateCodes}
colorScale={colorScale}
selectedPractices={selectedPractices}
/>
<>
<MapChart
getNationalTotal={getNationalTotal}
setReactTooltipContent={setTooltipContent}
maxValue={maxValue}
allStates={allStates}
statePerformance={statePerformance}
year={year}
stateCodes={stateCodes}
colorScale={colorScale}
selectedPractices={selectedPractices}
classes={classes}
/>
{tooltipComponent}
</>
)
)}
<div className="tooltip-container">
<ReactTooltip
className={`${classes.customized_tooltip} tooltip`}
backgroundColor={tooltipBkgColor}
html
>
{content}
</ReactTooltip>
</div>
</Box>
);
};
Expand All @@ -384,11 +426,11 @@ const titleElement = (programName, practices: string[], year: string): JSX.Eleme
return (
<Box>
<Typography variant="h6" textAlign="center">
<strong>{practiceLabel === "All Practices" ? `Total ${programName}` : practiceLabel}</strong> Benefits
from <strong>{year}</strong>
<strong>{practiceLabel === "All Practices" ? `Total ${programName}` : "Selected Practices"}</strong>{" "}
Benefits from <strong>{year}</strong>
</Typography>
<Typography style={{ fontSize: "0.5em", color: "#AAA", textAlign: "center" }}>
<i>Grey states indicate no available data</i>
<i>Gray states indicate no available data</i>
</Typography>
</Box>
);
Expand Down
Loading

0 comments on commit 76428ab

Please sign in to comment.