From bb8a430af97ee66c9846fbff79196754ec196564 Mon Sep 17 00:00:00 2001 From: Rashmi Date: Tue, 23 Apr 2019 12:08:24 -0400 Subject: [PATCH 01/30] fixes "Invalid status code" error --- api/image.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/image.js b/api/image.js index 73563ec..2770c50 100644 --- a/api/image.js +++ b/api/image.js @@ -21,7 +21,7 @@ module.exports = function(app) { } else { res.sendFile(`${process.cwd()}/static/images/profile/${size}/${id}.jpg`, err => { - if (err) res.status(err.status); + if (err && err.status) res.status(err.status); res.end(); }); } From bdb5d31709da1e2ec7d924d278cd40d9953d9266 Mon Sep 17 00:00:00 2001 From: Rashmi Date: Tue, 23 Apr 2019 12:19:21 -0400 Subject: [PATCH 02/30] fixes disclaimer text based on the profile - and cleans all commented (old) code for health center data --- .../accessToCare/HealthCenterDemographics.jsx | 81 ++----------------- 1 file changed, 5 insertions(+), 76 deletions(-) diff --git a/app/pages/Profile/sections/accessToCare/HealthCenterDemographics.jsx b/app/pages/Profile/sections/accessToCare/HealthCenterDemographics.jsx index 37a3d5c..a65fb87 100644 --- a/app/pages/Profile/sections/accessToCare/HealthCenterDemographics.jsx +++ b/app/pages/Profile/sections/accessToCare/HealthCenterDemographics.jsx @@ -4,14 +4,12 @@ import {connect} from "react-redux"; import {nest} from "d3-collection"; import {Pie} from "d3plus-react"; import {formatAbbreviate} from "d3plus-format"; -// import axios from "axios"; import {fetchData, SectionColumns, SectionTitle} from "@datawheel/canon-core"; import Contact from "components/Contact"; import Disclaimer from "components/Disclaimer"; import Stat from "components/Stat"; -// import zipcodes from "utils/zipcodes"; import {updateSource} from "utils/helper"; import SourceGroup from "components/SourceGroup"; import Options from "components/Options"; @@ -19,7 +17,6 @@ import Options from "components/Options"; const formatRaceNames = d => d.replace("Health Center Patients", ""); const lowerCaseRaceName = d => d.trim() === "Black" || d.trim() === "White" ? d.toLowerCase() : d; const formatPercentage = d => `${formatAbbreviate(d * 100)}%`; -// const formatDropdownName = d => d === "Health Centers" ? "Number of Health Centers" : d; const formatRaceAndEthnicityData = raceAndEthnicityData => { // Add RaceType property to raceAndEthnicityData so that each race type can have individual object. @@ -54,29 +51,9 @@ class HealthCenterDemographics extends SectionColumns { this.state = {sources: []}; } - // constructor(props) { - // super(props); - // this.state = { - // healthCenterData: this.props.healthCenterData, - // dropdownValue: "Health Centers" - // }; - // } - - // Handler function for dropdown onChange event. - // handleChange = event => { - // this.setState({dropdownValue: event.target.value}); - // axios.get(`/api/data?measures=${event.target.value}&drilldowns=Zip&Year=latest`) - // .then(resp => this.setState({healthCenterData: resp.data})); - // } - render() { const {meta, raceAndEthnicityData, raceAndEthnicityZipLevelData} = this.props; const isZipLevelDataAvailable = raceAndEthnicityZipLevelData.data.length !== 0; - // const {healthCenterData, dropdownValue} = this.state; - // const dropdownList = ["Health Centers", "Health Center Penetration", "Low-Income Health Center Penetration", "Uninsured Health Center Penetration"]; - - // Get the current dropdown value data for latest year. - // const topRecentYearDropdownValueData = healthCenterData.data.sort((a, b) => b[dropdownValue] - a[dropdownValue])[0]; const recentYearData = formatRaceAndEthnicityData(raceAndEthnicityData).sort((a, b) => b[b.RaceType] - a[a.RaceType]); const topMostRaceData = recentYearData[0]; @@ -95,40 +72,13 @@ class HealthCenterDemographics extends SectionColumns { Health Center Demographics
- {/* Create a dropdown list. */} - {/* */} - {/* Show top stats for each dropdown choice. */} - {/* {isHealthCentersSelected - ?
- -

In {topRecentYearDropdownValueData.Year}, the zip code in Wayne County with the most {dropdownValue} was {topRecentYearDropdownValueData.Zip} ({topRecentYearDropdownValueData[dropdownValue]} health centers).

-

The following map shows the total number of health centers for all zip codes in Wayne County.

-
- :
- -

In {topRecentYearDropdownValueData.Year}, the zip code in Wayne County with the most {dropdownValue.toLowerCase()} was {topRecentYearDropdownValueData.Zip} ({formatPercentage(topRecentYearDropdownValueData[dropdownValue])}).

-

The following map shows the share of {dropdownValue.toLowerCase()} for all zip codes in Wayne County.

-
- } */} - - {(!isZipLevelDataAvailable && meta.name !== "") && + {(!isZipLevelDataAvailable && meta.level !== "county" && meta.name !== "") && Data is shown for Wayne County } + { + meta.level === "tract" && isZipLevelDataAvailable && + Data is shown for zip {raceAndEthnicityZipLevelData.data[0].Geography} + } {isZipLevelDataAvailable ? - - {/* Draw Geomap to show health center count for each zip code in the Wayne county */} - {/* d["ID Zip"].slice(7), - colorScale: dropdownValue, - colorScaleConfig: { - axisConfig: {tickFormat: isHealthCentersSelected ? d => d : d => formatPercentage(d)} - }, - label: d => d.Zip, - height: 400, - time: "Year", - tooltipConfig: isHealthCentersSelected ? {tbody: [["Year", d => d.Year], ["Health Centers", d => d[dropdownValue]]]} : {tbody: [["Year", d => d.Year], ["Visitor", dropdownValue], ["Share", d => formatPercentage(d[dropdownValue])]]}, - topojson: "/topojson/zipcodes.json", - topojsonFilter: d => zipcodes.includes(d.properties.ZCTA5CE10), - topojsonId: d => d.properties.ZCTA5CE10 - }} - dataFormat={resp => resp.data} - /> */} ); } @@ -212,14 +143,12 @@ HealthCenterDemographics.defaultProps = { }; HealthCenterDemographics.need = [ - // fetchData("healthCenterData", "/api/data?measures=Health Centers&drilldowns=Zip&Year=latest"), fetchData("raceAndEthnicityData", "/api/data?measures=Non-white Health Center Patients,Hispanic Health Center Patients,Black Health Center Patients,Asian Health Center Patients,American Indian/Alaska Native Health Center Patients&Year=latest"), fetchData("raceAndEthnicityZipLevelData", "/api/data?measures=Non-white Health Center Patients,Hispanic Health Center Patients,Black Health Center Patients,Asian Health Center Patients,American Indian/Alaska Native Health Center Patients&Geography=&Year=latest") ]; const mapStateToProps = state => ({ meta: state.data.meta, - // healthCenterData: state.data.healthCenterData, raceAndEthnicityData: state.data.raceAndEthnicityData, raceAndEthnicityZipLevelData: state.data.raceAndEthnicityZipLevelData }); From d3cf126db60c9472cad420c89e8ac035a4f6a7a0 Mon Sep 17 00:00:00 2001 From: Dave Landry Date: Tue, 23 Apr 2019 12:40:33 -0400 Subject: [PATCH 03/30] updates caching script to retry after timeouts --- scripts/cache.js | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/scripts/cache.js b/scripts/cache.js index 7257907..8896b58 100644 --- a/scripts/cache.js +++ b/scripts/cache.js @@ -5,6 +5,11 @@ const axios = require("axios"); const domain = "https://data.authorityhealth.org/"; const levels = ["county", "place", "zip", "tract"]; +const message = { + 200: "success!", + 502: "timeout, will try again later" +}; + /** */ async function run() { @@ -17,16 +22,30 @@ async function run() { else return b.zvalue - a.zvalue; }); - for (let i = 0; i < attrs.length; i++) { - const {id, name} = attrs[i]; + /** */ + async function hitServer(attr) { + const {id, name} = attr; console.log(""); console.log(name); const url = `${domain}profile/${id}`; console.log(url); - const resp = await axios.get(url); - console.log(resp.status); + const resp = await axios({url, method: "GET", timeout: 1000 * 60 * 5}) // 5 minute timeout + .catch(() => ({status: 502})); + console.log(`${resp.status} - ${message[resp.status]}`); + return resp; + } + + let secondPass = attrs; + while (secondPass.length) { + const list = secondPass.slice(); + secondPass = []; + for (let i = 0; i < list.length; i++) { + const resp = await hitServer(list[i]); + if (resp.status === 502) secondPass.push(list[i]); + } } + } run(); From f409d6a7841212e27fd14abe488fd566d15dadd9 Mon Sep 17 00:00:00 2001 From: Rashmi Date: Tue, 23 Apr 2019 15:53:21 -0400 Subject: [PATCH 04/30] fixes some of the stats and values when the population is 0 or when the data is not available --- app/pages/Profile/sections/about/Introduction.jsx | 14 +++++++------- .../accessToCare/HealthInsuranceCoverage.jsx | 2 +- .../builtSocialEnvironment/Homeownership.jsx | 1 + .../Profile/sections/economy/WageDistribution.jsx | 5 +++-- .../Profile/sections/education/StudentPoverty.jsx | 2 +- .../Profile/sections/foodAccess/FoodStamps.jsx | 2 +- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/pages/Profile/sections/about/Introduction.jsx b/app/pages/Profile/sections/about/Introduction.jsx index bf8fae7..4a54c0c 100644 --- a/app/pages/Profile/sections/about/Introduction.jsx +++ b/app/pages/Profile/sections/about/Introduction.jsx @@ -15,12 +15,12 @@ import styles from "style.yml"; import "./Introduction.css"; const formatRaceName = d => { - d = d.replace("Alone", "").replace("Black", "black").replace("White", "white").replace("Asian", "asian"); + d = d.replace("Alone", "").replace("Black", "black").replace("White", "white").replace("Asian", "asian").trim(); if (d.trim() === "Some Other Race") return d.toLowerCase(); if (d.trim() === "Two or More Races") return d.toLowerCase(); return d; }; -const formatEthnicityName = d => d.replace("Not Hispanic or Latino", "non-Hispanic").replace("or Latino", ""); +const formatEthnicityName = d => d.replace("Not Hispanic or Latino", "non-Hispanic").replace("or Latino", "").trim(); const formatRankSuffix = d => { if (d % 10 === 1 && d !== 11) return `${d}st`; @@ -112,7 +112,7 @@ class Introduction extends SectionColumns { const total = currentLevelOverallCoverage[0]["Population by Insurance Coverage"] + currentLevelOverallCoverage[1]["Population by Insurance Coverage"]; const topOverallCoverage = currentLevelOverallCoverage.filter(d => d["Health Insurance Coverage Status"] === "With Health Insurance Coverage")[0]; - topOverallCoverage.share = topOverallCoverage["Population by Insurance Coverage"] / total * 100; + topOverallCoverage.share = total !== 0 ? topOverallCoverage["Population by Insurance Coverage"] / total * 100 : 0; // Filter zips for Geomap based on the profile you are on. let filteredZips = []; @@ -126,7 +126,7 @@ class Introduction extends SectionColumns {

{level === "zip" ? `Zip code ${population[0].Geography}` : population[0].Geography} has a population of {formatAbbreviate(population[0].Population)} people{meta.level === "county" ? "" : which makes it the {formatRankSuffix(currentLocationRankData.populationRank)} largest of {rankData.length} {formatLevelNames(meta.level)} in Wayne County} {}, with the life expectancy of {lifeExpectancyAvailable ? formatAbbreviate(lifeExpectancy[0]["Life Expectancy"]) : "N/A"} {lifeExpectancyAvailable ? onCityOrZipLevel ? (in {lifeExpectancy[0].Geography}) : "" : ""}. - The most common age group for male is {populationByAgeAndGenderAvailable ? getTopMaleData.Age.toLowerCase() : "N/A"} and for female it is {populationByAgeAndGenderAvailable ? getTopFemaleData.Age.toLowerCase() : "N/A"}. + The most common age group for male is {populationByAgeAndGenderAvailable && population[0].Population !== 0 ? getTopMaleData.Age.toLowerCase() : "N/A"} and for female it is {populationByAgeAndGenderAvailable && population[0].Population !== 0 ? getTopFemaleData.Age.toLowerCase() : "N/A"}. Between {population[population.length - 1].Year} and {population[0].Year} the population of {population[0].Geography} {populationGrowth < 0 ? "reduced" : "increased"} from {formatAbbreviate(population[population.length - 1].Population)} to {formatAbbreviate(population[0].Population)}, {} {populationGrowth < 0 ? "a decline" : "an increase"} of {populationGrowth < 0 ? `${populationGrowth * -1}%` : isNaN(populationGrowth) ? "N/A" : `${populationGrowth}%`}.

@@ -166,7 +166,7 @@ class Introduction extends SectionColumns { { const findOverallCoverage = data => { const total = data[0]["Population by Insurance Coverage"] + data[1]["Population by Insurance Coverage"]; const filteredData = data.filter(d => d["Health Insurance Coverage Status"] === "With Health Insurance Coverage")[0]; - filteredData.share = filteredData["Population by Insurance Coverage"] / total * 100; + filteredData.share = total !== 0 ? filteredData["Population by Insurance Coverage"] / total * 100 : 0; return filteredData; }; diff --git a/app/pages/Profile/sections/builtSocialEnvironment/Homeownership.jsx b/app/pages/Profile/sections/builtSocialEnvironment/Homeownership.jsx index e59c853..6efc68c 100644 --- a/app/pages/Profile/sections/builtSocialEnvironment/Homeownership.jsx +++ b/app/pages/Profile/sections/builtSocialEnvironment/Homeownership.jsx @@ -119,6 +119,7 @@ class Homeownership extends SectionColumns { title="Median property value" year={medianHousingValueForCurrentProfileAvailable ? topMedianHousingUnitsValueForProfile.Year : ""} value={medianHousingValueForCurrentProfileAvailable ? `$${commas(topMedianHousingUnitsValueForProfile["Property Value"])}` : "N/A"} + qualifier={medianHousingValueForCurrentProfileAvailable ? `in ${topMedianHousingUnitsValueForProfile.Geography}` : `in ${meta.name}`} /> 1 ? "N/A" : wageGinidata[0]["Wage GINI"]; return ( @@ -50,9 +51,9 @@ class WageDistribution extends SectionColumns { - {wageGinidataAvailable ?

In {wageGinidata[0].Year}, the income inequality in {wageGinidata[0].Geography} was {wageGinidata[0]["Wage GINI"]}, using the GINI coefficient. The GINI index measures the extent to which the distribution of income among individuals or households within an economy deviates from a perfectly equal distribution. Values range from 0 to 1, with 0 being perfect equality (every household earns equal income), and 1 being absolute inequality (one household earns all the income).

: ""} + {wageGinidataAvailable ?

In {wageGinidata[0].Year}, the income inequality in {wageGinidata[0].Geography} was {wageGini}, using the GINI coefficient. The GINI index measures the extent to which the distribution of income among individuals or households within an economy deviates from a perfectly equal distribution. Values range from 0 to 1, with 0 being perfect equality (every household earns equal income), and 1 being absolute inequality (one household earns all the income).

: ""} {wageDistributionDataAvailable ?

The following chart shows the household income buckets and share for each bucket in {wageDistributionData[0].Geography}.

: ""} diff --git a/app/pages/Profile/sections/education/StudentPoverty.jsx b/app/pages/Profile/sections/education/StudentPoverty.jsx index db90f37..7c68eac 100644 --- a/app/pages/Profile/sections/education/StudentPoverty.jsx +++ b/app/pages/Profile/sections/education/StudentPoverty.jsx @@ -53,7 +53,7 @@ const findEnrolledInSchoolPercentage = data => { group.values.forEach(d => total !== 0 ? d.enrolledShare = d["Poverty by Schooling"] / total * 100 : d.enrolledShare = 0); }); const notEnrolledInSchool = data.filter(d => d["ID Level of School"] === 7); - return 100 - notEnrolledInSchool[0].enrolledShare - notEnrolledInSchool[1].enrolledShare; + return notEnrolledInSchool[0].enrolledShare === 0 && notEnrolledInSchool[1].enrolledShare === 0 ? 0 : 100 - notEnrolledInSchool[0].enrolledShare - notEnrolledInSchool[1].enrolledShare; }; class StudentPoverty extends SectionColumns { diff --git a/app/pages/Profile/sections/foodAccess/FoodStamps.jsx b/app/pages/Profile/sections/foodAccess/FoodStamps.jsx index 74f21f7..17b111f 100644 --- a/app/pages/Profile/sections/foodAccess/FoodStamps.jsx +++ b/app/pages/Profile/sections/foodAccess/FoodStamps.jsx @@ -61,7 +61,7 @@ class FoodStamps extends SectionColumns { const publicAssistanceDataAvailable = publicAssistanceData.length !== 0; const topPublicAssistanceData = formatPublicAssistanceData(publicAssistanceData)[0]; const currentYearPopulation = population.filter(d => d.Year === topPublicAssistanceData.Year)[0]; - const shareOfPopulationWithFoodStamps = formatPercentage(topPublicAssistanceData.total / currentYearPopulation.Population * 100); + const shareOfPopulationWithFoodStamps = currentYearPopulation.Population !== 0 ? formatPercentage(topPublicAssistanceData.total / currentYearPopulation.Population * 100) : `${0}%`; // Get latest year SNAP and WIC authorized stores data const snapWicArr = ["SNAP", "WIC"]; From 6171ef0dde2964f29a5aef42fbf17c7723670d6f Mon Sep 17 00:00:00 2001 From: Dave Landry Date: Tue, 23 Apr 2019 16:16:03 -0400 Subject: [PATCH 05/30] fixes vizbuilder tooltip underneath header --- app/css/d3plus.css | 1 + 1 file changed, 1 insertion(+) diff --git a/app/css/d3plus.css b/app/css/d3plus.css index 3712c10..717894b 100644 --- a/app/css/d3plus.css +++ b/app/css/d3plus.css @@ -107,6 +107,7 @@ tooltip ----------------------------------- */ .d3plus-tooltip { + z-index: 21; & .d3plus-tooltip-title { color: var(--dark-3); font-family: var(--body-font); From c3e8b97673417ba242714d12a832a781e4d4b8a7 Mon Sep 17 00:00:00 2001 From: Dave Landry Date: Tue, 23 Apr 2019 16:16:18 -0400 Subject: [PATCH 06/30] fixes vizbuilder padding and spline cutoff --- app/pages/Visualize/Visualize.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/pages/Visualize/Visualize.css b/app/pages/Visualize/Visualize.css index 1626f7a..f32e54d 100644 --- a/app/pages/Visualize/Visualize.css +++ b/app/pages/Visualize/Visualize.css @@ -231,6 +231,12 @@ &:only-child { height: calc(100vh - var(--nav-height) - var(--gutter-md) - var(--gutter-md)); } + & .wrapper { + margin: 15px; + & .viz > svg { + overflow: visible; + } + } } } } From 989cda397f4a9d21ff632c9a55f7a04cbc3c6337 Mon Sep 17 00:00:00 2001 From: Rashmi Date: Tue, 23 Apr 2019 16:21:05 -0400 Subject: [PATCH 07/30] corrects age stats and text for locations with 0 population --- .../accessToCare/HealthInsuranceCoverage.jsx | 6 +++--- app/pages/Profile/sections/economy/Poverty.jsx | 6 +++--- .../sections/specialPopulation/DisabilityStatus.jsx | 4 ++-- .../VisionAndAuditoryDisabilities.jsx | 12 ++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx b/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx index 271806b..628fa22 100644 --- a/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx +++ b/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx @@ -135,13 +135,13 @@ class HealthInsuranceCoverage extends SectionColumns { if (coverageDataAvailable) { const recentYearCoverageData = formatCoverageData(coverageData.data); const femaleCoverageData = recentYearCoverageData.filter(d => d.Sex === "Female").sort((a, b) => b.share - a.share); - topFemaleAgeGroup = rangeFormatter(femaleCoverageData[0].Age); topFemaleShare = formatPercentage(femaleCoverageData[0].share); + topFemaleAgeGroup = femaleCoverageData[0].share !== 0 ? rangeFormatter(femaleCoverageData[0].Age) : "N/A"; maleCoverageData = recentYearCoverageData.filter(d => d.Sex === "Male").sort((a, b) => b.share - a.share); - topMaleAgeGroup = rangeFormatter(maleCoverageData[0].Age); - ageGroupYear = maleCoverageData[0].Year; topMaleShare = formatPercentage(maleCoverageData[0].share); + topMaleAgeGroup = maleCoverageData[0].share !== 0 ? rangeFormatter(maleCoverageData[0].Age) : "N/A"; + ageGroupYear = maleCoverageData[0].Year; geoId = maleCoverageData[0]["ID Geography"]; geography = femaleCoverageData[0].Geography; } diff --git a/app/pages/Profile/sections/economy/Poverty.jsx b/app/pages/Profile/sections/economy/Poverty.jsx index 419bc5c..d98b421 100644 --- a/app/pages/Profile/sections/economy/Poverty.jsx +++ b/app/pages/Profile/sections/economy/Poverty.jsx @@ -100,13 +100,13 @@ class Poverty extends SectionColumns { { title: "Female", year: povertyByAgeAndGenderAvailable ? topFemalePovertyData.Year : "", - value: povertyByAgeAndGenderAvailable ? `${rangeFormatter(topFemalePovertyData.Age)} Years` : "N/A", + value: povertyByAgeAndGenderAvailable && topFemalePovertyData.share !== 0 ? `${rangeFormatter(topFemalePovertyData.Age)} Years` : "N/A", qualifier: povertyByAgeAndGenderAvailable ? `${formatPopulation(topFemalePovertyData.share)} of the female population in ${topFemalePovertyData.Geography}` : "" }, { title: "Male", year: povertyByAgeAndGenderAvailable ? topMalePovertyData.Year : "", - value: povertyByAgeAndGenderAvailable ? `${rangeFormatter(topMalePovertyData.Age)} Years` : "N/A", + value: povertyByAgeAndGenderAvailable && topFemalePovertyData.share !== 0 ? `${rangeFormatter(topMalePovertyData.Age)} Years` : "N/A", qualifier: povertyByAgeAndGenderAvailable ? `${formatPopulation(topMalePovertyData.share)} of the male population in ${topMalePovertyData.Geography}` : "", color: "terra-cotta" } @@ -128,7 +128,7 @@ class Poverty extends SectionColumns { : null } - {povertyByAgeAndGenderAvailable ?

In {topMalePovertyData.Year}, most common male age in poverty was {topMalePovertyData.Age.toLowerCase()} ({formatPopulation(topMalePovertyData.share)} of the male population) while most common female age was {topFemalePovertyData.Age.toLowerCase()} ({formatPopulation(topFemalePovertyData.share)} of the female population) in {topFemalePovertyData.Geography}.

: ""} + {povertyByAgeAndGenderAvailable ?

In {topMalePovertyData.Year}, most common male age in poverty was {povertyByAgeAndGenderAvailable && topMalePovertyData.share !== 0 ? topMalePovertyData.Age.toLowerCase() : "N/A"} ({formatPopulation(topMalePovertyData.share)} of the male population) while most common female age was {povertyByAgeAndGenderAvailable && topFemalePovertyData.share !== 0 ? topFemalePovertyData.Age.toLowerCase() : "N/A"} ({formatPopulation(topFemalePovertyData.share)} of the female population) in {topFemalePovertyData.Geography}.

: ""} {povertyByRaceAvailable ?

In {topPovertyByRace.Year}, the majority race in poverty was {topPovertyByRace.Race} ({formatPopulation(topPovertyByRace.share)} of the total population in {topPovertyByRace.Geography}).

: ""} diff --git a/app/pages/Profile/sections/specialPopulation/DisabilityStatus.jsx b/app/pages/Profile/sections/specialPopulation/DisabilityStatus.jsx index 8e3aed5..11877ee 100644 --- a/app/pages/Profile/sections/specialPopulation/DisabilityStatus.jsx +++ b/app/pages/Profile/sections/specialPopulation/DisabilityStatus.jsx @@ -78,11 +78,11 @@ class DisabilityStatus extends SectionColumns { {/* Write short paragraph describing stats and barchart. */} - {disabilityStatusAvailable ?

In {topDisabilityStatus.Year}, the most common disabled age group was {rangeFormatter(topDisabilityStatus.Age)} years making up {formatPopulation(topDisabilityStatus.share)} of all disabled citizens within this age group in {topDisabilityStatus.Geography}.

: ""} + {disabilityStatusAvailable ?

In {topDisabilityStatus.Year}, the most common disabled age group was {topDisabilityStatus.share !== 0 ? rangeFormatter(topDisabilityStatus.Age) : "N/A"} years making up {formatPopulation(topDisabilityStatus.share)} of all disabled citizens within this age group in {topDisabilityStatus.Geography}.

: ""} {healthCoverageTypeAvailable ?

The chart here shows the health coverage breakdown of the disabled population by age in {filteredHealthCoverageType[0].Geography}.

: ""} diff --git a/app/pages/Profile/sections/specialPopulation/VisionAndAuditoryDisabilities.jsx b/app/pages/Profile/sections/specialPopulation/VisionAndAuditoryDisabilities.jsx index 3642468..93e93a4 100644 --- a/app/pages/Profile/sections/specialPopulation/VisionAndAuditoryDisabilities.jsx +++ b/app/pages/Profile/sections/specialPopulation/VisionAndAuditoryDisabilities.jsx @@ -172,13 +172,13 @@ class VisionAndAuditoryDisabilities extends SectionColumns { { title: "Female", year: visionDisabilityDataAvailable ? topFemaleVisionDisabilityData.Year : "", - value: visionDisabilityDataAvailable ? rangeFormatter(topFemaleVisionDisabilityData.Age) : "N/A", + value: visionDisabilityDataAvailable && topFemaleVisionDisabilityData.share !== 0 ? rangeFormatter(topFemaleVisionDisabilityData.Age) : "N/A", qualifier: visionDisabilityDataAvailable ? `${formatPercentage(topFemaleVisionDisabilityData.share)} of the population in ${topFemaleVisionDisabilityData.Geography}` : "" }, { title: "Male", year: visionDisabilityDataAvailable ? topMaleVisionDisabilityData.Year : "N/A", - value: visionDisabilityDataAvailable ? rangeFormatter(topMaleVisionDisabilityData.Age) : "N/A", + value: visionDisabilityDataAvailable && topMaleVisionDisabilityData.share !== 0 ? rangeFormatter(topMaleVisionDisabilityData.Age) : "N/A", qualifier: visionDisabilityDataAvailable ? `${formatPercentage(topMaleVisionDisabilityData.share)} of the population in ${topMaleVisionDisabilityData.Geography}` : "", color: "terra-cotta" } @@ -199,13 +199,13 @@ class VisionAndAuditoryDisabilities extends SectionColumns { { title: "Female", year: hearingDisabilityDataAvailable ? topFemaleHearingDisabilityData.Year : "", - value: hearingDisabilityDataAvailable ? rangeFormatter(topFemaleHearingDisabilityData.Age) : "N/A", + value: hearingDisabilityDataAvailable && topFemaleHearingDisabilityData.share !== 0 ? rangeFormatter(topFemaleHearingDisabilityData.Age) : "N/A", qualifier: hearingDisabilityDataAvailable ? `${formatPercentage(topFemaleHearingDisabilityData.share)} of the population in ${topFemaleHearingDisabilityData.Geography}` : "" }, { title: "Male", year: hearingDisabilityDataAvailable ? topMaleHearingDisabilityData.Year : "", - value: hearingDisabilityDataAvailable ? rangeFormatter(topMaleHearingDisabilityData.Age) : "N/A", + value: hearingDisabilityDataAvailable && topMaleHearingDisabilityData.share !== 0 ? rangeFormatter(topMaleHearingDisabilityData.Age) : "N/A", qualifier: hearingDisabilityDataAvailable ? `${formatPercentage(topMaleHearingDisabilityData.share)} of the population in ${topMaleHearingDisabilityData.Geography}` : "", color: "terra-cotta" } @@ -223,12 +223,12 @@ class VisionAndAuditoryDisabilities extends SectionColumns { {isVisionDisabilitySelected ?

{visionDisabilityDataAvailable ? In {topMaleVisionDisabilityData.Year}, the age groups most likely to have vision disability in { } - {topMaleVisionDisabilityData.Geography} were {rangeFormatter(topMaleVisionDisabilityData.Age)} years for men and {rangeFormatter(topFemaleVisionDisabilityData.Age)} { } + {topMaleVisionDisabilityData.Geography} were {topMaleVisionDisabilityData.share !== 0 ? rangeFormatter(topMaleVisionDisabilityData.Age) : "N/A"} years for men and {topFemaleVisionDisabilityData.share !== 0 ? rangeFormatter(topFemaleVisionDisabilityData.Age) : "N/A"} { } years for women. : ""}

:

{hearingDisabilityDataAvailable ? In {topMaleHearingDisabilityData.Year}, the age groups most likely to have hearing disability in { } - {topMaleHearingDisabilityData.Geography} were {rangeFormatter(topMaleHearingDisabilityData.Age)} years for men and {rangeFormatter(topFemaleHearingDisabilityData.Age)} { } + {topMaleHearingDisabilityData.Geography} were {topMaleHearingDisabilityData.share !== 0 ? rangeFormatter(topMaleHearingDisabilityData.Age) : "N/A"} years for men and {topFemaleHearingDisabilityData.share !== 0 ? rangeFormatter(topFemaleHearingDisabilityData.Age) : "N/A"} { } years for women. : ""}

} From 0932836fd1a94755186057ebcf6cea2a8af0e4ed Mon Sep 17 00:00:00 2001 From: Rashmi Date: Tue, 23 Apr 2019 17:03:25 -0400 Subject: [PATCH 08/30] adds glossary to describe the 7 factors involved in the score --- app/pages/Profile/sections/about/Introduction.jsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/pages/Profile/sections/about/Introduction.jsx b/app/pages/Profile/sections/about/Introduction.jsx index 4a54c0c..b7fa90d 100644 --- a/app/pages/Profile/sections/about/Introduction.jsx +++ b/app/pages/Profile/sections/about/Introduction.jsx @@ -8,12 +8,24 @@ import {Geomap, Treemap} from "d3plus-react"; import {fetchData, SectionColumns, SectionTitle} from "@datawheel/canon-core"; import growthCalculator from "utils/growthCalculator"; +import Glossary from "components/Glossary"; import zipcodes from "utils/zipcodes"; import Stat from "components/Stat"; import styles from "style.yml"; import "./Introduction.css"; +const definitions = [ + {term: "The Distressed Communities Index (DCI) combines seven complementary economic indicators into a single holistic and comparative measure of community well-being. The seven component metrics of the DCI are", definition: ""}, + {term: "1. No high school diploma", definition: "Percent of the 25+ population without a high school diploma or equivalent."}, + {term: "2. Housing vacancy rate", definition: "Percent of habitable housing that is unoccupied, excluding properties that are for seasonal, recreational, or occasional use."}, + {term: "3. Adults not working", definition: "Percent of the prime-age population (25-64) not currently in work."}, + {term: "4. Poverty rate", definition: "Percent of the population living under the poverty line."}, + {term: "5. Median income ratio", definition: "Median household income as a percent of the state’s median household income (to account for cost of living differences across states)."}, + {term: "6. Change in employment", definition: "Percent change in the number of jobs."}, + {term: "7. Change in establishments", definition: "Percent change in the number of business establishments."} +]; + const formatRaceName = d => { d = d.replace("Alone", "").replace("Black", "black").replace("White", "white").replace("Asian", "asian").trim(); if (d.trim() === "Some Other Race") return d.toLowerCase(); @@ -195,6 +207,7 @@ class Introduction extends SectionColumns { }} dataFormat={resp => resp.data} /> + From 4a8b0b4e4fe08a493288531c568272f2b5498adc Mon Sep 17 00:00:00 2001 From: Rashmi Date: Tue, 23 Apr 2019 17:03:53 -0400 Subject: [PATCH 09/30] adds comment for totalShare in HouseholdIncomeFromPublicAssistance --- .../sections/economy/HouseholdIncomeFromPublicAssistance.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/pages/Profile/sections/economy/HouseholdIncomeFromPublicAssistance.jsx b/app/pages/Profile/sections/economy/HouseholdIncomeFromPublicAssistance.jsx index cd5d355..ed863cb 100644 --- a/app/pages/Profile/sections/economy/HouseholdIncomeFromPublicAssistance.jsx +++ b/app/pages/Profile/sections/economy/HouseholdIncomeFromPublicAssistance.jsx @@ -33,6 +33,8 @@ const formatHouseholdSnapData = householdSnapData => { group.values.forEach(d => total !== 0 ? d.share = d["SNAP Receipts"] / total * 100 : d.share = 0); }); const filterSnapRecievedData = householdSnapData.filter(d => d["ID Snap Receipt"] === 0); + + // We need to find totalShare for each group to show stats for top most group. nest() .key(d => d["ID Number of workers"]) .entries(filterSnapRecievedData) @@ -116,7 +118,7 @@ class HouseholdIncomeFromPublicAssistance extends SectionColumns { slug={this.props.slug} data={ `/api/data?measures=SNAP Receipts&drilldowns=Snap Receipt,Family type,Number of workers&Geography=${meta.id}&Year=all` } title="Chart of Household Income From Public Assistance" /> - + {householdSnapDataAvailable ? this.viz = comp } config={{ data: `/api/data?measures=SNAP Receipts&drilldowns=Snap Receipt,Family type,Number of workers&Geography=${meta.id}&Year=all`, From 1052b131448ac06fedb91c340b5aeb619c6b08cc Mon Sep 17 00:00:00 2001 From: James Ferrell Date: Tue, 23 Apr 2019 17:22:21 -0400 Subject: [PATCH 10/30] updates wayne county logo; closes #49 --- app/components/Footer.css | 6 ++++-- app/components/Footer.jsx | 2 +- .../logos/wayne-county-seal-mustard.png | Bin 4208 -> 0 bytes .../logos/wayne-county-seal-pacific.png | Bin 4173 -> 16542 bytes .../logos/wayne-county-seal-pacific.svg | 1 + .../logos/wayne-county-seal-pacific@2x.png | Bin 13534 -> 0 bytes 6 files changed, 6 insertions(+), 3 deletions(-) delete mode 100644 static/images/logos/wayne-county-seal-mustard.png create mode 100644 static/images/logos/wayne-county-seal-pacific.svg delete mode 100644 static/images/logos/wayne-county-seal-pacific@2x.png diff --git a/app/components/Footer.css b/app/components/Footer.css index 156fe4f..1ac7f4b 100644 --- a/app/components/Footer.css +++ b/app/components/Footer.css @@ -77,7 +77,9 @@ /* scale down logos a bit on small screens */ & .footer-logo-img { - max-width: 40vw; - max-height: 12vw; + max-width: 8rem; /* fallback */ + max-width: calc(7rem + 1.5vw); + max-height: 3rem; /* fallback */ + max-height: calc(1.75rem + 1.5vw); } } diff --git a/app/components/Footer.jsx b/app/components/Footer.jsx index 9d70b34..2b0a15c 100644 --- a/app/components/Footer.jsx +++ b/app/components/Footer.jsx @@ -59,7 +59,7 @@ export default class Footer extends Component { title: "Wayne County, Michigan", link: "http://waynecounty.com/", src: "wayne-county-seal", - svg: false + svg: true }, { title: "Datawheel", diff --git a/static/images/logos/wayne-county-seal-mustard.png b/static/images/logos/wayne-county-seal-mustard.png deleted file mode 100644 index dc68147d00c2db847ce7acb6d35a5688e1f59e8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4208 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 VatU;y)v*8o002ovPDHLkV1gE)ToC{O literal 4173 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 diff --git a/static/images/logos/wayne-county-seal-pacific@2x.png b/static/images/logos/wayne-county-seal-pacific@2x.png deleted file mode 100644 index 5575e124d40b0601a395bea251c4a7b1d5292854..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13534 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 z znK*MO9?PBl$B#W3t54oXNe26?$?2tJTX8#nczd>YZSObdKDfO(oP4IheY4$7z(1mPg zbGvy3`mQf2mo>qYw{9wn{oO6n_!A8>l=GESZhw35?ibGHLjJE3S1$BzD`pJAAm=DJ z0|3pz0HO_uEZA`~HYp_-k?=njZ1@JHpIIs!<5KKSG@8HyZdP1Wi$Nl zpT9XQ4g>vDn^YL%G*>tLmu77?x@n(p3OT)M_jEF_Wlisj8ePw!fB7OL8-#E0Lj{2D#Gc@S#rCMk@v&6YD2@ ztdJV_f`UILks*R+#&Dz%JZ6{k9nXrJ_N2S*4(1NlPG$Jh8$2YPDheA<4(f-GLnHOi zZc;&n)aYi%rk2M0^9fHfMhMzM%|N!bXM@A{#ANTe&MhaODW+4dqb!G0vyg<~gsLLcM1gAb z!{%Nb8qgBJ{NouYJ>4UW0hUN*Q|WX`MmD#=1CSj*GmNxO^o9rhsNW>R#HY8G`qVH0 zfQ)fv00nc5CG2DXDBQTO&_pH#0I)3iQ<-l4G%!CnVF^I40gSc`5l1bUA!d~RsqM)A YUmhqd0ey1@R{#J207*qoM6N<$f;={!5&!@I From 4b0d638ad3ec52199156f5294a24e9bc8868cc21 Mon Sep 17 00:00:00 2001 From: Rashmi Date: Wed, 24 Apr 2019 11:16:10 -0400 Subject: [PATCH 11/30] adds react-helmet to get page titles in the browser tab; closes #58 --- app/pages/Profile/Profile.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/pages/Profile/Profile.jsx b/app/pages/Profile/Profile.jsx index 599023b..0c2722d 100644 --- a/app/pages/Profile/Profile.jsx +++ b/app/pages/Profile/Profile.jsx @@ -1,5 +1,6 @@ import React, {Component} from "react"; import {connect} from "react-redux"; +import {Helmet} from "react-helmet"; import {Icon} from "@blueprintjs/core"; import {fetchData, TopicTitle} from "@datawheel/canon-core"; import ProfileHeader from "./components/ProfileHeader"; @@ -60,6 +61,8 @@ class Profile extends Component { return (
+ + Date: Wed, 24 Apr 2019 13:00:17 -0400 Subject: [PATCH 12/30] removes old intro side-by-side stats code --- api/stats.js | 56 ++++------------------------------------------ app/utils/stats.js | 33 --------------------------- cache/stats.js | 48 --------------------------------------- 3 files changed, 4 insertions(+), 133 deletions(-) delete mode 100644 app/utils/stats.js delete mode 100644 cache/stats.js diff --git a/api/stats.js b/api/stats.js index 0ded555..4f144a8 100644 --- a/api/stats.js +++ b/api/stats.js @@ -1,9 +1,5 @@ const axios = require("axios"); -const d3 = require("d3-scale"); -const {formatAbbreviate} = require("d3plus-format"); const {titleCase} = require("d3plus-text"); - -const formatters = require("../app/utils/formatters"); const {CANON_LOGICLAYER_CUBE} = process.env; const regionLookup = { @@ -90,7 +86,7 @@ const prefixMap = { "ZRX": "zip_region" }; -// groupBy function groups object by property. +/** groupBy function groups object by property. **/ function groupBy(objectArray, property) { return objectArray.reduce((acc, obj) => { const key = obj[property]; @@ -102,6 +98,7 @@ function groupBy(objectArray, property) { }, {}); } +/** find parent geography for current location **/ function findParentGeoLevels(groupedObj) { const result = []; // If groupedObj has zip level data, then check for the zip region as well. @@ -121,10 +118,6 @@ module.exports = function(app) { const {cache, db} = app.settings; - app.get("/api/topstats", async(req, res) => { - res.json(cache.stats); - }); - app.get("/api/stats/:id", async(req, res) => { const {id} = req.params; const levels = { @@ -147,48 +140,7 @@ module.exports = function(app) { // Select top most parent from multiple same level parents with max overlap_size. const geoLevels = findParentGeoLevels(groupedValues); - // Add current location ID at the beginning of the geoLevels array. - geoLevels.unshift(id); - const currentLocationMeasureData = {}; - const healthTopics = []; - const socialDeterminants = []; - - // cache.cube has all the measure and year data. To view data in browser go to the /api/cubes url. - const cubeYearData = cache.cube.years; - - // Check if measure data is available for locations in geoLevels array and set their rank. - Object.entries(cache.stats).forEach(statTopic => { - statTopic[1].forEach(d => { - const matchId = geoLevels.find(parentId => d.data.hasOwnProperty(parentId)); - const value = d.data[matchId]; - if (value !== undefined) { - const scale = d3.scaleLinear() - .domain(d.domain) - .range([-1, 0, 1]); - - const statData = { - measure: d.measure, - geoId: matchId, - rank: scale(value), - value: formatters.hasOwnProperty(d.measure) ? formatters[d.measure](formatAbbreviate(value)) : formatAbbreviate(value), - years: d.cube.startsWith("acs_yg") ? 5 : cubeYearData[d.cube].years.length, // if its a shared acs cube (which is not in Authority Health cubes), then set the years to 5. - latestYear: d.latestYear, - yearDimension: d.hasOwnProperty("yearDimension") ? true : false - }; - statTopic[0] === "healthTopics" ? healthTopics.push(statData) : socialDeterminants.push(statData); - } - }); - }); - - // Sort and slice each topStat data and add it to the currentLocationMeasureData. - currentLocationMeasureData.healthTopics = healthTopics.sort((a, b) => Math.abs(b.rank) - Math.abs(a.rank)); - currentLocationMeasureData.healthTopics = currentLocationMeasureData.healthTopics.length > 3 ? currentLocationMeasureData.healthTopics.slice(0, 3) : currentLocationMeasureData.healthTopics; - - currentLocationMeasureData.socialDeterminants = socialDeterminants.sort((a, b) => Math.abs(b.rank) - Math.abs(a.rank)).slice(0, 3); - currentLocationMeasureData.socialDeterminants = currentLocationMeasureData.socialDeterminants.length > 3 ? currentLocationMeasureData.socialDeterminants.slice(0, 3) : currentLocationMeasureData.socialDeterminants; - - currentLocationMeasureData.total = healthTopics.length + socialDeterminants.length; currentLocationMeasureData.locations = geoLevels; // Get all Place/Tract/Zip meta data which are in the Wayne County. @@ -197,13 +149,13 @@ module.exports = function(app) { const population = cache.pops; const medianIncome = cache.medianIncome; const currLevel = titleCase(prefixMap[id.slice(0, 3)]); - + const currentLevelLocations = allLocations.filter(d => d.hierarchy === currLevel); currentLevelLocations.forEach(location => { population.hasOwnProperty(location.id) ? location.population = population[location.id] : location.population = 0; medianIncome.hasOwnProperty(location.id) ? location.medianIncome = medianIncome[location.id] : location.medianIncome = 0; }); - + // Sort and rank loctions based on their population. currentLevelLocations.sort((a, b) => b.population - a.population); currentLevelLocations.forEach((d, i) => d.populationRank = i + 1); diff --git a/app/utils/stats.js b/app/utils/stats.js deleted file mode 100644 index 738169e..0000000 --- a/app/utils/stats.js +++ /dev/null @@ -1,33 +0,0 @@ -module.exports = { - healthTopics: [ - {measure: "Life Expectancy", depth: [["Tract", "County"], "Tract"], latestYear: "2015", cube: "NVSS - Life Expectancy", yearDimension: "End Year"}, - {measure: "Heart Disease", depth: ["County", "Zip Region"], latestYear: "2016", cube: "MiBRFS - All Years", yearDimension: "End Year"}, - {measure: "Coronary Heart Disease", depth: ["Place", "Tract"], latestYear: "2015", cube: "500 Cities"}, - {measure: "High Blood Pressure", depth: ["Place", "Tract"], latestYear: "2015", cube: "500 Cities"}, - {measure: "High Cholesterol", depth: ["Place", "Tract"], latestYear: "2015", cube: "500 Cities"}, - {measure: "COPD", depth: ["Place", "Tract"], latestYear: "2015", cube: "500 Cities"}, - {measure: "Current Asthma", depth: ["County", "Zip Region"], latestYear: "2016", cube: "MiBRFS - All Years", yearDimension: "End Year"}, - {measure: "Diabetes", depth: ["Place", "Tract"], latestYear: "2015", cube: "500 Cities"}, - {measure: "Obesity", depth: ["Place", "Tract"], latestYear: "2015", cube: "500 Cities"}, - {measure: "Ever Depressive", depth: ["County", "Zip Region"], latestYear: "2016", cube: "MiBRFS - All Years", yearDimension: "End Year"}, - {measure: "Poor Mental Health 14 Or More Days", depth: ["County", "Zip Region"], latestYear: "2016", cube: "MiBRFS - All Years", yearDimension: "End Year"}, - {measure: "Monthly Alcohol Consumption", depth: ["County", "Zip Region"], latestYear: "2016", cube: "MiBRFS - All Years", yearDimension: "End Year"}, - {measure: "Binge Drinking", depth: ["Place", "Tract"], latestYear: "2015", cube: "500 Cities"}, - {measure: "Current Smoking", depth: ["Place", "Tract"], latestYear: "2015", cube: "500 Cities"} - ], - socialDeterminants: [ - {measure: "Distress Score", depth: ["Zip"], latestYear: "2017", cube: "DCI"}, - {measure: "Poverty Rate", depth: ["Zip"], latestYear: "2017", cube: "DCI"}, - {measure: "High School Dropout Rate", depth: ["Zip"], latestYear: "2017", cube: "DCI"}, - {measure: "Wage GINI", depth: ["County", "Place", "Tract", "Zip"], latestYear: "2016", cube: "acs_yg_gini_5"}, - {measure: "Health Centers", depth: ["Zip"], latestYear: "2014", cube: "UDS Mapper - Heatlh Centers"}, - {measure: "Health Center Penetration", depth: ["Zip"], latestYear: "2014", cube: "UDS Mapper - Heatlh Centers"}, - {measure: "Low-Income Health Center Penetration", depth: ["Zip"], latestYear: "2014", cube: "UDS Mapper - Heatlh Centers"}, - {measure: "Uninsured Health Center Penetration", depth: ["Zip"], latestYear: "2014", cube: "UDS Mapper - Heatlh Centers"}, - {measure: "Socioeconomic Ranking", depth: [["Tract", "County"], "Tract"], latestYear: "2016", cube: "CDC - SVI"}, - {measure: "Household Composition and Disability Ranking", depth: [["Tract", "County"], "Tract"], latestYear: "2016", cube: "CDC - SVI"}, - {measure: "Minority Status and Language Ranking", depth: [["Tract", "County"], "Tract"], latestYear: "2016", cube: "CDC - SVI"}, - {measure: "Housing and Transportation Ranking", depth: [["Tract", "County"], "Tract"], latestYear: "2016", cube: "CDC - SVI"}, - {measure: "Overall Ranking", depth: [["Tract", "County"], "Tract"], latestYear: "2016", cube: "CDC - SVI"} - ] -}; diff --git a/cache/stats.js b/cache/stats.js deleted file mode 100644 index 3b81463..0000000 --- a/cache/stats.js +++ /dev/null @@ -1,48 +0,0 @@ -const {MultiClient} = require("mondrian-rest-client"); -const d3 = require("d3-array"); - -const {CANON_LOGICLAYER_CUBE} = process.env; -const statTopics = require("../app/utils/stats"); - -module.exports = async function() { - Object.entries(statTopics).forEach(statTopic => { - const client = new MultiClient([CANON_LOGICLAYER_CUBE, "https://acs-api.datausa.io/"]); - statTopic[1].forEach(async dataObj => { - const cut = dataObj.hasOwnProperty("yearDimension") ? `[End Year].[End Year].[End Year].&[${dataObj.latestYear}]` : `[Year].[Year].[Year].&[${dataObj.latestYear}]`; - const popQueries = dataObj.depth - .map(level => client.cube(dataObj.cube) - .then(c => { - if (level instanceof Array) { - const query = c.query - .drilldown("Geography", level[0], level[1]) - .measure(dataObj.measure) - .cut(cut); - return client.query(query, "jsonrecords"); - } - else { - const query = c.query - .drilldown("Geography", level, level) - .measure(dataObj.measure) - .cut(cut); - return client.query(query, "jsonrecords"); - } - }) - .then(resp => resp.data.data.reduce((acc, d) => { - acc[d[`ID ${level}`]] = d[dataObj.measure]; - return acc; - }, {})) - .catch(err => { - console.error(` 🌎 ${dataObj.measure} Error: ${err.message}`); - if (err.config) console.error(err.config.url); - })); - - const rawPops = await Promise.all(popQueries); - const pops = rawPops.reduce((obj, d) => (obj = Object.assign(obj, d), obj), {}); - const allValues = Object.values(pops); - const domain = [d3.min(allValues), d3.median(allValues), d3.max(allValues)]; - dataObj.data = pops; - dataObj.domain = domain; - }); - }); - return statTopics; -}; From f5b5aa4b4048c64903404787860dabeb756f4098 Mon Sep 17 00:00:00 2001 From: Rashmi Date: Thu, 25 Apr 2019 15:12:19 -0400 Subject: [PATCH 13/30] adds geography in the stats --- app/pages/Profile/sections/economy/WageDistribution.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/pages/Profile/sections/economy/WageDistribution.jsx b/app/pages/Profile/sections/economy/WageDistribution.jsx index 9a94a03..6d86ebf 100644 --- a/app/pages/Profile/sections/economy/WageDistribution.jsx +++ b/app/pages/Profile/sections/economy/WageDistribution.jsx @@ -52,6 +52,7 @@ class WageDistribution extends SectionColumns { title="Wage GINI" year={wageGinidataAvailable ? wageGinidata[0].Year : ""} value={wageGinidataAvailable ? wageGini : "N/A"} + qualifier={wageGinidataAvailable ? `in ${wageGinidata[0].Geography}` : ""} /> {wageGinidataAvailable ?

In {wageGinidata[0].Year}, the income inequality in {wageGinidata[0].Geography} was {wageGini}, using the GINI coefficient. The GINI index measures the extent to which the distribution of income among individuals or households within an economy deviates from a perfectly equal distribution. Values range from 0 to 1, with 0 being perfect equality (every household earns equal income), and 1 being absolute inequality (one household earns all the income).

: ""} {wageDistributionDataAvailable ?

The following chart shows the household income buckets and share for each bucket in {wageDistributionData[0].Geography}.

: ""} From e720a07351cfe287b09bea50e8343829066f59c7 Mon Sep 17 00:00:00 2001 From: Rashmi Date: Thu, 25 Apr 2019 16:30:59 -0400 Subject: [PATCH 14/30] adds tooltip definition for census tract and zip regions in the intro stats --- app/pages/Profile/sections/about/Introduction.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/pages/Profile/sections/about/Introduction.jsx b/app/pages/Profile/sections/about/Introduction.jsx index b7fa90d..bb31560 100644 --- a/app/pages/Profile/sections/about/Introduction.jsx +++ b/app/pages/Profile/sections/about/Introduction.jsx @@ -7,6 +7,8 @@ import {formatAbbreviate} from "d3plus-format"; import {Geomap, Treemap} from "d3plus-react"; import {fetchData, SectionColumns, SectionTitle} from "@datawheel/canon-core"; +import ZipRegionDefinition from "components/ZipRegionDefinition"; +import CensusTractDefinition from "components/CensusTractDefinition"; import growthCalculator from "utils/growthCalculator"; import Glossary from "components/Glossary"; import zipcodes from "utils/zipcodes"; @@ -175,7 +177,6 @@ class Introduction extends SectionColumns {
- in Wayne County

} /> in {meta.level === "county" || meta.level === "tract" ? "Wayne County" : meta.name}

} /> in Wayne County

} /> Date: Mon, 29 Apr 2019 10:32:53 -0400 Subject: [PATCH 15/30] updates vizbuilder to use cedar API --- app/pages/Visualize/Visualize.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/pages/Visualize/Visualize.jsx b/app/pages/Visualize/Visualize.jsx index b03a39e..2139dc3 100644 --- a/app/pages/Visualize/Visualize.jsx +++ b/app/pages/Visualize/Visualize.jsx @@ -9,7 +9,7 @@ export default class Visualize extends React.Component { return
Date: Mon, 29 Apr 2019 14:57:12 -0400 Subject: [PATCH 16/30] tweaks mobile layout --- app/components/Footer.css | 8 +++++++- app/components/MainNav.css | 5 +++++ app/components/ProfileTile.css | 5 +++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/components/Footer.css b/app/components/Footer.css index 1ac7f4b..a623864 100644 --- a/app/components/Footer.css +++ b/app/components/Footer.css @@ -75,11 +75,17 @@ } } - /* scale down logos a bit on small screens */ + /* keep logo sizes in check */ & .footer-logo-img { max-width: 8rem; /* fallback */ max-width: calc(7rem + 1.5vw); max-height: 3rem; /* fallback */ max-height: calc(1.75rem + 1.5vw); + + /* shrink logos on small screens */ + @mixin max-xs { + max-width: calc(5rem + 1.5vw); + max-height: calc(1.25rem + 1.5vw); + } } } diff --git a/app/components/MainNav.css b/app/components/MainNav.css index aec4bad..af5484d 100644 --- a/app/components/MainNav.css +++ b/app/components/MainNav.css @@ -29,6 +29,10 @@ right: 8px; margin-left: calc(0 - var(--gutter-xs)); /* offset padding */ + /* shrink logo on small screens */ + @mixin max-sm { width: 8rem; } + @mixin max-xs { width: 7rem; } + /* BETA */ &:after { @mixin min-xs { @@ -42,6 +46,7 @@ /* positioning */ position: absolute; top: 35px; + margin-top: -7px; right: -20px; } /* fudge into place on bigger screens */ diff --git a/app/components/ProfileTile.css b/app/components/ProfileTile.css index 9158843..5de4f50 100644 --- a/app/components/ProfileTile.css +++ b/app/components/ProfileTile.css @@ -14,6 +14,11 @@ border-radius: var(--radius-sm); box-shadow: 0 0.1rem 1rem color(var(--black) a(0.5)); + /* increase click target on small screen stacked layout */ + @mixin max-sm { + padding-top: 25% !important; + } + /* overlay */ &:after { /* sizing & positioning */ From 81d5fd36d7481f919777e92626fe58607048812d Mon Sep 17 00:00:00 2001 From: James Ferrell Date: Mon, 29 Apr 2019 15:07:48 -0400 Subject: [PATCH 17/30] adjusts text-right utility on small screens --- app/css/utilities.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/css/utilities.css b/app/css/utilities.css index fccaa20..33520eb 100644 --- a/app/css/utilities.css +++ b/app/css/utilities.css @@ -9,7 +9,11 @@ typography text-align: left; } .u-text-right { - text-align: right; + text-align: left; + + @add-mixin min-sm { + text-align: right; + } } .u-text-center { text-align: center; From a0d4c9c8632e9f69a5d6021f5b4338e0926bceb4 Mon Sep 17 00:00:00 2001 From: James Ferrell Date: Mon, 29 Apr 2019 15:09:01 -0400 Subject: [PATCH 18/30] adds default visualization height; seemingly closes #53 --- app/d3plus.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/d3plus.js b/app/d3plus.js index 53c1a51..fc74062 100644 --- a/app/d3plus.js +++ b/app/d3plus.js @@ -218,6 +218,8 @@ export default { fontFamily: () => typeface, fontSize: () => fontSizeSm }, + // default visualization height + height: 400, // axis defaults (see line 8) xConfig: axisConfig, yConfig: axisConfig From 8ac13b6a50a050147172fc621ff7e3b080c7f137 Mon Sep 17 00:00:00 2001 From: James Ferrell Date: Mon, 29 Apr 2019 16:51:57 -0400 Subject: [PATCH 19/30] adds select menu SubNav for small screens --- app/components/Subnav.css | 25 +++++++++++++++++++- app/components/Subnav.jsx | 49 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/app/components/Subnav.css b/app/components/Subnav.css index e6754ab..4956c9f 100644 --- a/app/components/Subnav.css +++ b/app/components/Subnav.css @@ -7,7 +7,8 @@ height: var(--nav-height); z-index: 2; /* in front of section titles */ } -.subnav-list { +.subnav-list, +.subnav-select-label { /* layout */ @add-mixin centered-container; padding-top: 0; @@ -61,3 +62,25 @@ display: inline-block; } } + +/* select menu (small screens only) */ +.subnav-select-label { + line-height: 1.4rem; + top: 0.7rem; +} + +.subnav-select-text { + flex: 1 0 auto; + margin-right: 0.75em; + top: 0.25em; + color: var(--light-3); + + /* hide label on small screens */ + @mixin max-xxs { + @mixin visually-hidden; + } +} + +.subnav-select { + color: var(--white); +} diff --git a/app/components/Subnav.jsx b/app/components/Subnav.jsx index 2e75bc5..f536693 100644 --- a/app/components/Subnav.jsx +++ b/app/components/Subnav.jsx @@ -1,14 +1,38 @@ import React, {Component} from "react"; +import PropTypes from "prop-types"; import {Icon} from "@blueprintjs/core"; import {AnchorLink} from "@datawheel/canon-core"; import {PROFILE_SECTIONS} from "utils/consts.js"; import "./Subnav.css"; -export default class Subnav extends Component { +class Subnav extends Component { + constructor() { + super(); + this.state = { + currentSection: "home" + }; + } + + selectSection(e) { + const {router} = this.context; + const hash = e.target.value; + router.push({ + ...router.location, + state: "HASH", + hash: `#${hash}` + }); + this.setState({currentSection: hash}); + + // this.context.router.replace(`/profile/16000US2622000#${e.target.value}`); + } + render() { + const {currentSection} = this.state; + return ( ); } } + +Subnav.contextTypes = { + router: PropTypes.object +}; + +export default Subnav; From 5f7a851d7849e00616d24c4a102a1ab865364a0b Mon Sep 17 00:00:00 2001 From: James Ferrell Date: Mon, 29 Apr 2019 17:30:28 -0400 Subject: [PATCH 20/30] adds introduction to subnav --- app/components/Subnav.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/components/Subnav.jsx b/app/components/Subnav.jsx index f536693..9c1017f 100644 --- a/app/components/Subnav.jsx +++ b/app/components/Subnav.jsx @@ -9,7 +9,7 @@ class Subnav extends Component { constructor() { super(); this.state = { - currentSection: "home" + currentSection: "Introduction" }; } @@ -50,6 +50,9 @@ class Subnav extends Component { onChange={e => this.selectSection(e)} value={currentSection} > + {PROFILE_SECTIONS.map(section =>
diff --git a/app/style.yml b/app/style.yml index bd77a6f..fad96ee 100644 --- a/app/style.yml +++ b/app/style.yml @@ -124,14 +124,23 @@ color-Violent crime: "#D45D59" "color-American Indian or Alaska Native": "#6F59D4" "color-% American Indian/Alaska Native": "#6F59D4" "color-Asian": "#8842A6" +"color-Asian Alone": "#8842A6" "color-Black": "#A64281" "color-% Black": "#A64281" +"color-Black or African American": "#A64281" +"color-Black or African American Alone": "#A64281" "color-Hispanic ethnicity": "#D45D59" "color-% Hispanic": "#D45D59" "color-White": "#CF7A1F" "color-% White": "#CF7A1F" +"color-White Alone": "#CF7A1F" "color-Hawaiian or Pacific Islander": "#C99C20" +"color-American Indian & Alaska Native Alone": "#C99C20" +"color-Native Hawaiian & Other Pacific Islander Alone": "#BFA112" "color-Multiracial": "#B5A604" +"color-Two or More Races": "#B5A604" +"color-Some Other Race Alone": "#A09F06" + # health center demographics "color-American Indian/Alaska Native Health Center Patients": "#6F59D4" From 82424814531495c43c79283d8b9ba08b224f6db7 Mon Sep 17 00:00:00 2001 From: James Ferrell Date: Tue, 30 Apr 2019 17:18:26 -0400 Subject: [PATCH 24/30] defines air quality days colors --- app/d3plus.js | 9 ++++++--- app/pages/Profile/sections/about/Introduction.jsx | 10 ++++++++-- .../sections/naturalEnvironment/AirQuality.jsx | 13 ++++++++++--- app/style.yml | 15 +++++++++++++++ 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/app/d3plus.js b/app/d3plus.js index 8058968..9a19523 100644 --- a/app/d3plus.js +++ b/app/d3plus.js @@ -27,6 +27,7 @@ const groupings = [ "Family type", "Period of Service", "Type of Crime", + "Pollutant", // Health center demographics "American Indian/Alaska Native Health Center Patients", "Black Health Center Patients", @@ -36,13 +37,15 @@ const groupings = [ // smoking status "Smoking Status Current", "Smoking Status Former", - "Smoking Status Never" + "Smoking Status Never", + // air quality + "Category" // air quality days ]; /** function to lookup & assign color scheme */ function colorLogic(d) { - - // console.log(d["Period of Service"]); + // console.log(grouping, d[grouping]); + // styles[`color-${d[grouping]}`] ? console.log(styles[`color-${d[grouping]}`]) : null; // lookup grouping color schemes in style.yml for (const grouping of groupings) { diff --git a/app/pages/Profile/sections/about/Introduction.jsx b/app/pages/Profile/sections/about/Introduction.jsx index 86ec6ef..f4b1d1c 100644 --- a/app/pages/Profile/sections/about/Introduction.jsx +++ b/app/pages/Profile/sections/about/Introduction.jsx @@ -170,11 +170,17 @@ class Introduction extends SectionColumns { height: 250, sum: "Hispanic Population", groupBy: ["Race", "Ethnicity"], - label: d => `${d.Race instanceof Array ? "Other Races" : d.Race.replace("Alone", "")}${d.Ethnicity instanceof Array ? "" : ` (${formatEthnicityName(d.Ethnicity)})` }`, + label: d => `${ d.Race instanceof Array + ? "Other Races" + : d.Race.replace("Alone", "") + }${ d.Ethnicity instanceof Array + ? "" + : ` (${formatEthnicityName(d.Ethnicity)})` + }`, time: "Year", tooltipConfig: {tbody: [["Year", d => d.Year], ["Share", d => formatPercentage(d.share)], [titleCase(meta.level), d => d.Geography]]} }} - dataFormat={ resp => formatRaceAndEthnicityData(resp.data) } + dataFormat={ resp => formatRaceAndEthnicityData(resp.data)[0] } />
diff --git a/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx b/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx index 8471fd2..bd3618c 100644 --- a/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx +++ b/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx @@ -182,19 +182,25 @@ class AirQuality extends SectionColumns { data={ `/api/data?measures=Air Quality Days&drilldowns=Category&Geography=${meta.id}&Year=all` } title="Chart of Air Quality Days" /> } + + {/* Lineplot to show air quality days over the years. */} {dropdownValue === "Air Quality Days" && this.viz = comp} config={{ data: `/api/data?measures=Air Quality Days&drilldowns=Category&Geography=${meta.id}&Year=all`, groupBy: "Category", height: 400, - label: d => `${titleCase(d.Category)}`, + label: d => titleCase(d.Category), x: "Category", y: "Air Quality Days", time: "Year", xSort: (a, b) => a["ID Category"] - b["ID Category"], xConfig: { - tickFormat: d => titleCase(formatAirQualityDaysName(d)) + tickFormat: d => titleCase(formatAirQualityDaysName(d)), + // hide vertical grid lines + gridConfig: { + opacity: 0 + } }, yConfig: { tickFormat: d => titleCase(d), @@ -208,6 +214,7 @@ class AirQuality extends SectionColumns { dataFormat={resp => { this.setState({sources: updateSource(resp.source, this.state.sources)}); const data = resp.data.filter(d => d.Year !== "2018"); + console.log(data); return data; }} />} @@ -227,7 +234,6 @@ class AirQuality extends SectionColumns { data: `/api/data?measures=Air Pollutant Days&drilldowns=Pollutant&Geography=${meta.id}&Year=all`, discrete: "x", height: 400, - legend: false, groupBy: "Pollutant", x: "Year", y: "Air Pollutant Days", @@ -239,6 +245,7 @@ class AirQuality extends SectionColumns { dataFormat={resp => { this.setState({sources: updateSource(resp.source, this.state.sources)}); const data = resp.data.filter(d => d.Year !== "2018"); + // console.log(data); return data; }} />} diff --git a/app/style.yml b/app/style.yml index fad96ee..9e2c7e2 100644 --- a/app/style.yml +++ b/app/style.yml @@ -223,3 +223,18 @@ color-Violent crime: "#D45D59" "color-Gulf War (1990s)": "#A64281" "color-Gulf War (2001-)": "#D45D59" "color-Other": "#869299" + +# air quality +"color-CO": "#5673CC" +"color-NO2": "#6F59D4" +"color-Ozone": "#8842A6" +"color-PM10": "#A64281" +"color-PM2.5": "#D45D59" +"color-SO2": "#CF7A1F" + +"color-hazardous days": "#D45D59" +"color-very unhealthy days": "#CF7A1F" +"color-unhealthy days": "#C99C20" +"color-unhealthy for sensitive groups days": "#B5A604" +"color-moderate days": "#8B9909" +"color-good days": "#53A355" From 5813264b92936b6d29d3fc8f5b31f0fb13245fa4 Mon Sep 17 00:00:00 2001 From: James Ferrell Date: Tue, 30 Apr 2019 17:52:30 -0400 Subject: [PATCH 25/30] assigns more colors --- app/d3plus.js | 1 + app/style.yml | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/app/d3plus.js b/app/d3plus.js index 9a19523..8c1d948 100644 --- a/app/d3plus.js +++ b/app/d3plus.js @@ -28,6 +28,7 @@ const groupings = [ "Period of Service", "Type of Crime", "Pollutant", + "Travel Time", // Health center demographics "American Indian/Alaska Native Health Center Patients", "Black Health Center Patients", diff --git a/app/style.yml b/app/style.yml index 9e2c7e2..3b93955 100644 --- a/app/style.yml +++ b/app/style.yml @@ -123,6 +123,7 @@ color-Violent crime: "#D45D59" # ethnicity "color-American Indian or Alaska Native": "#6F59D4" "color-% American Indian/Alaska Native": "#6F59D4" +"color-Native American": "#6F59D4" "color-Asian": "#8842A6" "color-Asian Alone": "#8842A6" "color-Black": "#A64281" @@ -130,16 +131,20 @@ color-Violent crime: "#D45D59" "color-Black or African American": "#A64281" "color-Black or African American Alone": "#A64281" "color-Hispanic ethnicity": "#D45D59" +"color-Hispanic": "#D45D59" "color-% Hispanic": "#D45D59" "color-White": "#CF7A1F" "color-% White": "#CF7A1F" "color-White Alone": "#CF7A1F" +"color-White Non-Hispanic": "#CC8B1F" "color-Hawaiian or Pacific Islander": "#C99C20" +"color-Pacific Islander": "#C99C20" "color-American Indian & Alaska Native Alone": "#C99C20" "color-Native Hawaiian & Other Pacific Islander Alone": "#BFA112" "color-Multiracial": "#B5A604" "color-Two or More Races": "#B5A604" -"color-Some Other Race Alone": "#A09F06" +"color-Two or More": "#B5A604" +"color-Some Other Race Alone": "#869299" # health center demographics @@ -238,3 +243,17 @@ color-Violent crime: "#D45D59" "color-unhealthy for sensitive groups days": "#B5A604" "color-moderate days": "#8B9909" "color-good days": "#53A355" + +# transportaiton +"color-< 5 Minutes": "#53A355" +"color-5-9 Minutes": "#6F9E2F" +"color-10-14 Minutes": "#8B9909" +"color-15-19 Minutes": "#A09F06" +"color-20-24 Minutes": "#B5A604" +"color-25-29 Minutes": "#BFA112" +"color-30-34 Minutes": "#C99C20" +"color-35-39 Minutes": "#CC8B1F" +"color-40-44 Minutes": "#CF7A1F" +"color-45-59 Minutes": "#D07032" +"color-60-89 Minutes": "#D26645" +"color-90+ Minutes": "#D45D59" From 41195d0bc08d2f33f256c570a6cb24679e325da3 Mon Sep 17 00:00:00 2001 From: James Ferrell Date: Wed, 1 May 2019 16:43:28 -0400 Subject: [PATCH 26/30] adjusts FoodInsecurity layout; closes #50 --- app/css/layout.css | 3 +++ .../sections/foodAccess/FoodInsecurity.jsx | 22 ++++++++----------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/app/css/layout.css b/app/css/layout.css index 8de6e91..cf887df 100644 --- a/app/css/layout.css +++ b/app/css/layout.css @@ -217,12 +217,15 @@ layout /* override canon typography */ & article { + margin: 0; font-family: inherit; color: inherit; /* style direct child paragraphs only */ & > p { @add-mixin font-sm; + width: 42em; + max-width: 100%; margin-bottom: 0.75em; /* override blueprint */ &:last-child { diff --git a/app/pages/Profile/sections/foodAccess/FoodInsecurity.jsx b/app/pages/Profile/sections/foodAccess/FoodInsecurity.jsx index 6d176f6..e2d44fa 100644 --- a/app/pages/Profile/sections/foodAccess/FoodInsecurity.jsx +++ b/app/pages/Profile/sections/foodAccess/FoodInsecurity.jsx @@ -31,7 +31,7 @@ class FoodInsecurity extends SectionColumns { return (
- +
Food Insecurity
{!isInsecurityRateDataAvailableForCurrentGeography && @@ -43,21 +43,17 @@ class FoodInsecurity extends SectionColumns { value={`${childInsecurity["Food Insecurity Rate"]}%`} qualifier={`of the children in ${location}`} /> +

In {childInsecurity.Year}, {childInsecurity["Food Insecurity Rate"]}% of the children and {adultInsecurityRate}% of the adults in {location} had food insecurity.

-

Food insecurity refers to USDA’s measure of lack of access, at times, to enough food for an active, healthy life for all household members and limited or uncertain availability of nutritionally adequate foods.

- +

Food insecurity refers to USDA’s measure of lack of access, at times, to enough food for an active, healthy life for all household members and limited or uncertain availability of nutritionally adequate foods.

- - - {/* added empty div for proper alignment of above text */} -
- +
); } From c39acd1feb0b09aa2dc8edcffb3b46b2b36377ff Mon Sep 17 00:00:00 2001 From: Rashmi Date: Wed, 8 May 2019 07:22:39 -0700 Subject: [PATCH 27/30] AH printout corrections - suggested by Dave --- .../Profile/sections/about/Introduction.jsx | 11 +++++----- .../accessToCare/HealthCenterDemographics.jsx | 13 +++++++----- .../accessToCare/HealthInsuranceCoverage.jsx | 2 +- .../builtSocialEnvironment/Homeownership.jsx | 6 +++--- .../builtSocialEnvironment/Rentals.jsx | 6 +++--- .../builtSocialEnvironment/Transportation.jsx | 2 +- .../ViolentAndPropertyCrimes.jsx | 2 +- .../sections/economy/DistressScore.jsx | 2 +- .../HouseholdIncomeFromPublicAssistance.jsx | 6 +++--- .../Profile/sections/economy/Poverty.jsx | 10 ++++----- .../Profile/sections/economy/Unemployment.jsx | 6 +++--- .../sections/education/DropoutRate.jsx | 2 +- .../education/EducationalAttainment.jsx | 10 ++++----- .../sections/education/ReadingAssessment.jsx | 11 +++++----- .../sections/education/StudentPoverty.jsx | 4 ++-- .../sections/foodAccess/FoodAvailability.jsx | 6 +++--- .../sections/foodAccess/FoodStamps.jsx | 6 ++++-- .../foodAccess/StoreAccessByDemographic.jsx | 10 ++++----- .../healthBehaviors/PhysicalInactivity.jsx | 10 ++++----- .../healthBehaviors/PreventiveCare.jsx | 4 ++-- .../healthBehaviors/RiskyBehaviors.jsx | 4 ++-- .../CancerPrevalenceByDemographics.jsx | 4 +++- .../healthConditions/ObesityAndDiabetes.jsx | 11 +++++----- .../naturalEnvironment/AirQuality.jsx | 3 --- .../specialPopulation/DisabilityStatus.jsx | 7 +++---- .../sections/specialPopulation/Homeless.jsx | 8 +++---- .../sections/specialPopulation/Immigrants.jsx | 10 ++++----- .../specialPopulation/Incarceration.jsx | 2 +- .../sections/specialPopulation/Veterans.jsx | 5 +++-- .../VisionAndAuditoryDisabilities.jsx | 21 +++++++++---------- 30 files changed, 104 insertions(+), 100 deletions(-) diff --git a/app/pages/Profile/sections/about/Introduction.jsx b/app/pages/Profile/sections/about/Introduction.jsx index bb31560..f28ed3a 100644 --- a/app/pages/Profile/sections/about/Introduction.jsx +++ b/app/pages/Profile/sections/about/Introduction.jsx @@ -37,6 +37,7 @@ const formatRaceName = d => { const formatEthnicityName = d => d.replace("Not Hispanic or Latino", "non-Hispanic").replace("or Latino", "").trim(); const formatRankSuffix = d => { + if (d === 1) return ""; if (d % 10 === 1 && d !== 11) return `${d}st`; if (d % 10 === 2 && d !== 12) return `${d}nd`; if (d % 10 === 3 && d !== 13) return `${d}rd`; @@ -138,10 +139,10 @@ class Introduction extends SectionColumns { Introduction

- {level === "zip" ? `Zip code ${population[0].Geography}` : population[0].Geography} has a population of {formatAbbreviate(population[0].Population)} people{meta.level === "county" ? "" : which makes it the {formatRankSuffix(currentLocationRankData.populationRank)} largest of {rankData.length} {formatLevelNames(meta.level)} in Wayne County} - {}, with the life expectancy of {lifeExpectancyAvailable ? formatAbbreviate(lifeExpectancy[0]["Life Expectancy"]) : "N/A"} {lifeExpectancyAvailable ? onCityOrZipLevel ? (in {lifeExpectancy[0].Geography}) : "" : ""}. - The most common age group for male is {populationByAgeAndGenderAvailable && population[0].Population !== 0 ? getTopMaleData.Age.toLowerCase() : "N/A"} and for female it is {populationByAgeAndGenderAvailable && population[0].Population !== 0 ? getTopFemaleData.Age.toLowerCase() : "N/A"}. - Between {population[population.length - 1].Year} and {population[0].Year} the population of {population[0].Geography} {populationGrowth < 0 ? "reduced" : "increased"} from {formatAbbreviate(population[population.length - 1].Population)} to {formatAbbreviate(population[0].Population)}, + {level === "zip" ? `Zip code ${population[0].Geography}` : population[0].Geography} has a population of {formatAbbreviate(population[0].Population)} people{meta.level === "county" ? "" : which makes it the {formatRankSuffix(currentLocationRankData.populationRank)} largest of the {rankData.length} {formatLevelNames(meta.level)} in Wayne County} + {}, with an average life expectancy of {lifeExpectancyAvailable ? formatAbbreviate(lifeExpectancy[0]["Life Expectancy"]) : "N/A"} {lifeExpectancyAvailable ? onCityOrZipLevel ? (in {lifeExpectancy[0].Geography}) : "" : ""}. + The most common age group for men is {populationByAgeAndGenderAvailable && population[0].Population !== 0 ? getTopMaleData.Age.toLowerCase() : "N/A"} and for women it is {populationByAgeAndGenderAvailable && population[0].Population !== 0 ? getTopFemaleData.Age.toLowerCase() : "N/A"}. + Between {population[population.length - 1].Year} and {population[0].Year} the population of {population[0].Geography} {populationGrowth < 0 ? "decreased" : "increased"} from {formatAbbreviate(population[population.length - 1].Population)} to {formatAbbreviate(population[0].Population)}, {} {populationGrowth < 0 ? "a decline" : "an increase"} of {populationGrowth < 0 ? `${populationGrowth * -1}%` : isNaN(populationGrowth) ? "N/A" : `${populationGrowth}%`}.

{populationByRaceAndEthnicityAvailable @@ -149,7 +150,7 @@ class Introduction extends SectionColumns { {formatAbbreviate(topRaceAndEthnicity[0].share)}% of the population in {topRaceAndEthnicity[0].Geography} is {formatRaceName(topRaceAndEthnicity[0].Race)} ({formatEthnicityName(topRaceAndEthnicity[0].Ethnicity)}), followed by {formatAbbreviate(topRaceAndEthnicity[1].share)}% {formatRaceName(topRaceAndEthnicity[1].Race)} ({formatEthnicityName(topRaceAndEthnicity[1].Ethnicity)}).

: null} -

In {level === "zip" ? `Zip code ${currentLocationRankData.name}` : currentLocationRankData.name}, the median household income is {formatAbbreviate(currentLocationRankData.medianIncome)}{meta.level === "county" ? "." : , which ranks it at {formatRankSuffix(currentLocationRankData.medianIncomeRank)} largest of all {formatLevelNames(meta.level)} in Wayne County.}

+

In {level === "zip" ? `Zip code ${currentLocationRankData.name}` : currentLocationRankData.name}, the median household income is ${formatAbbreviate(currentLocationRankData.medianIncome)}{meta.level === "county" ? "." : , which ranks it as the {formatRankSuffix(currentLocationRankData.medianIncomeRank)} highest of all {formatLevelNames(meta.level)} in Wayne County.}

Social and economic factors, such as income, education, and access to health care, impact health outcomes for all Americans. For example, in many low income areas in the country, there are higher rates of chronic diseases, like high blood pressure and diabetes. The summary to the right highlights some of the social and health conditions for {population[0].Geography}.

diff --git a/app/pages/Profile/sections/accessToCare/HealthCenterDemographics.jsx b/app/pages/Profile/sections/accessToCare/HealthCenterDemographics.jsx index a65fb87..a460e26 100644 --- a/app/pages/Profile/sections/accessToCare/HealthCenterDemographics.jsx +++ b/app/pages/Profile/sections/accessToCare/HealthCenterDemographics.jsx @@ -82,17 +82,17 @@ class HealthCenterDemographics extends SectionColumns { {isZipLevelDataAvailable ? : null} {isZipLevelDataAvailable ?

In {topZipLevelData.Year}, {lowerCaseRaceName(formatRaceNames(topZipLevelData.RaceType))} residents of {`zip ${topZipLevelData.Geography}`} visited health centers more than any other race/ethnicity group that utilizes services offered by health centers ({formatPercentage(topZipLevelData[topZipLevelData.RaceType])} of the health center population), as compared to the {lowerCaseRaceName(formatRaceNames(topMostRaceData.RaceType))} residents in Wayne County ({formatPercentage(topMostRaceData[topMostRaceData.RaceType])} of the health center population).

@@ -125,7 +125,10 @@ class HealthCenterDemographics extends SectionColumns { fillOpacity: 1 } }, - tooltipConfig: {title: d => d.RaceType, tbody: [["Year", d => d.Year], ["Share", d => formatPercentage(d[d.RaceType])], ["Geography", d => isZipLevelDataAvailable ? d.Geography : "Wayne County"]]} + tooltipConfig: { + title: d => d.RaceType, + tbody: [["Year", d => d.Year], ["Share", d => formatPercentage(d[d.RaceType])], ["Geography", d => isZipLevelDataAvailable ? d.Geography : "Wayne County"]] + } }} dataFormat={resp => { this.setState({sources: updateSource(resp.source, this.state.sources)}); diff --git a/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx b/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx index 628fa22..6083a1b 100644 --- a/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx +++ b/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx @@ -158,7 +158,7 @@ class HealthInsuranceCoverage extends SectionColumns { }
-

{medianHousingValueForCurrentProfileAvailable ? In {topMedianHousingUnitsValueForProfile.Year}, the median property value in {topMedianHousingUnitsValueForProfile.Geography}, was ${commas(topMedianHousingUnitsValueForProfile["Property Value"])}. : ""}

-

{occupancyDataAvailable ? {formatAbbreviate(topOccupancyData.share)}% of households in {topOccupancyData.Geography} were occupied in {topOccupancyData.Year}. : ""}

-

The following map shows the median property value for in Wayne County.

+

{medianHousingValueForCurrentProfileAvailable ? In {topMedianHousingUnitsValueForProfile.Year}, the median property value in {topMedianHousingUnitsValueForProfile.Geography}, was ${commas(topMedianHousingUnitsValueForProfile["Property Value"])}. : ""} + {occupancyDataAvailable ? {formatAbbreviate(topOccupancyData.share)}% of the households in {topOccupancyData.Geography} were occupied as of {topOccupancyData.Year}. : ""}

+

The following map shows the median property value for the in {topOccupancyData.Geography}.

diff --git a/app/pages/Profile/sections/builtSocialEnvironment/Rentals.jsx b/app/pages/Profile/sections/builtSocialEnvironment/Rentals.jsx index b98dd36..458c4cb 100644 --- a/app/pages/Profile/sections/builtSocialEnvironment/Rentals.jsx +++ b/app/pages/Profile/sections/builtSocialEnvironment/Rentals.jsx @@ -73,9 +73,9 @@ class Rentals extends SectionColumns { value={utilitiesDataAvailable ? `${formatPercentage(recentYearNoExtraUtilitiesPercentage)}` : "N/A"} /> -

{rentAmountDataAvailable ? In {rentAmountData[0].Year}, the median price for a rental unit in {rentAmountData[0].Geography} was ${formatAbbreviate(rentAmountData[0]["Rent Amount"])}/month. This is a {growthRate < 0 ? formatPercentage(growthRate * -1) : formatPercentage(growthRate)} {growthRate < 0 ? "decline" : "increase"} from the previous year (${formatAbbreviate(rentAmountData[1]["Rent Amount"])}/month). : ""}

-

{utilitiesDataAvailable ? {formatPercentage(recentYearNoExtraUtilitiesPercentage)} of the rental properties in {utilitiesData[0].Geography} include utilities with the price of rent. : ""}

-

{rentersByIncomePercentageAvailable ? The average income bracket of renters in {topIncomeToPayMostRent.Geography} is {rangeFormatter(topIncomeToPayMostRent["Household Income"])}. : ""}

+

{rentAmountDataAvailable ? In {rentAmountData[0].Year}, the median price for a rental unit in {rentAmountData[0].Geography} was ${formatAbbreviate(rentAmountData[0]["Rent Amount"])}/month. This is a {growthRate < 0 ? formatPercentage(growthRate * -1) : formatPercentage(growthRate)} {growthRate < 0 ? "decline" : "increase"} from the previous year (${formatAbbreviate(rentAmountData[1]["Rent Amount"])}/month). : ""} + {utilitiesDataAvailable ? {formatPercentage(recentYearNoExtraUtilitiesPercentage)} of the rental properties in {utilitiesData[0].Geography} include utilities with the price of rent. : ""}

+

{rentersByIncomePercentageAvailable ? The average household income bracket of renters in {topIncomeToPayMostRent.Geography} is {rangeFormatter(topIncomeToPayMostRent["Household Income"])}. : ""}

diff --git a/app/pages/Profile/sections/builtSocialEnvironment/Transportation.jsx b/app/pages/Profile/sections/builtSocialEnvironment/Transportation.jsx index 62ec151..3aa1fc4 100644 --- a/app/pages/Profile/sections/builtSocialEnvironment/Transportation.jsx +++ b/app/pages/Profile/sections/builtSocialEnvironment/Transportation.jsx @@ -191,7 +191,7 @@ class Transportation extends SectionColumns { x: "Travel Time", y: "share", time: "Year", - title: d => `Distribution of Commute Time in ${d[0].Geography}`, + title: d => `Distribution of Commute Times in ${d[0].Geography}`, xSort: (a, b) => a["ID Travel Time"] - b["ID Travel Time"], xConfig: { tickFormat: d => d.replace("Minutes", "").trim(), diff --git a/app/pages/Profile/sections/builtSocialEnvironment/ViolentAndPropertyCrimes.jsx b/app/pages/Profile/sections/builtSocialEnvironment/ViolentAndPropertyCrimes.jsx index 2c59311..ccd82dc 100644 --- a/app/pages/Profile/sections/builtSocialEnvironment/ViolentAndPropertyCrimes.jsx +++ b/app/pages/Profile/sections/builtSocialEnvironment/ViolentAndPropertyCrimes.jsx @@ -83,7 +83,7 @@ class ViolentAndPropertyCrimes extends SectionColumns { qualifier={formatPercentage(topRecentYearViolentCrime.share)} theme="terra-cotta-dark" /> -

In {topRecentYearViolentCrime.Year}, the most common violent crime{isPlaceDataAvailable ? ` in ${topRecentYearViolentCrime.Geography}` : ""} was {topRecentYearViolentCrime.Crime.toLowerCase()} ({formatPercentage(topRecentYearViolentCrime.share)}), and the most common property crime was {topRecentYearPropertyCrime.Crime.toLowerCase()} ({formatPercentage(topRecentYearPropertyCrime.share)}).

+

In {topRecentYearViolentCrime.Year}, the most common property crime was {topRecentYearPropertyCrime.Crime.toLowerCase()} ({formatPercentage(topRecentYearPropertyCrime.share)}), and the most common violent crime{isPlaceDataAvailable ? ` in ${topRecentYearViolentCrime.Geography}` : ""} was {topRecentYearViolentCrime.Crime.toLowerCase()} ({formatPercentage(topRecentYearViolentCrime.share)}).

The following chart shows the distribution for the different types of property and violent crimes{isPlaceDataAvailable ? ` in ${topRecentYearViolentCrime.Geography}` : ""}.

diff --git a/app/pages/Profile/sections/economy/DistressScore.jsx b/app/pages/Profile/sections/economy/DistressScore.jsx index ab0840f..36b180f 100644 --- a/app/pages/Profile/sections/economy/DistressScore.jsx +++ b/app/pages/Profile/sections/economy/DistressScore.jsx @@ -57,7 +57,7 @@ class DistressScore extends SectionColumns { value={topDistressScoreData.Zip} qualifier={`(${formatAbbreviate(topDistressScoreData["Distress Score"])} percentile)`} /> -

In {topDistressScoreData.Year}, the maximum distress score was observed in the zip code {topDistressScoreData.Zip} with {formatAbbreviate(topDistressScoreData["Distress Score"])} percentile with 0 percentile being least distressed (desired outcome) and 100 percentile being most distressed (unfavorable outcome).

+

In {topDistressScoreData.Year}, the highest distress score was observed in the zip code {topDistressScoreData.Zip} ({formatAbbreviate(topDistressScoreData["Distress Score"])} percentile), 0 percentile would be the least distressed (desired outcome), and 100 percentile would be the most distressed (unfavorable outcome).

The following map shows the distress score percentile for each zip code in Wayne County.

diff --git a/app/pages/Profile/sections/economy/HouseholdIncomeFromPublicAssistance.jsx b/app/pages/Profile/sections/economy/HouseholdIncomeFromPublicAssistance.jsx index ed863cb..c7c69ef 100644 --- a/app/pages/Profile/sections/economy/HouseholdIncomeFromPublicAssistance.jsx +++ b/app/pages/Profile/sections/economy/HouseholdIncomeFromPublicAssistance.jsx @@ -91,7 +91,7 @@ class HouseholdIncomeFromPublicAssistance extends SectionColumns { title={"Population With Cash Public Assistance Or Food Stamps/SNAP"} year={publicAssistanceDataAvailable ? topPublicAssistanceData.Year : ""} value={publicAssistanceDataAvailable ? `${formatPercentage(topPublicAssistanceData.share)}` : "N/A"} - qualifier={publicAssistanceDataAvailable ? `of the population with food stamp in ${topPublicAssistanceData.Geography}` : "N/A"} + qualifier={publicAssistanceDataAvailable ? `of the population in ${topPublicAssistanceData.Geography}` : "N/A"} />

{publicAssistanceDataAvailable ? In {topPublicAssistanceData.Year}, {formatPercentage(topPublicAssistanceData.share)} of the population in {topPublicAssistanceData.Geography} got cash public assistance or food stamps. : ""} - {householdSnapDataAvailable ? The most common number of workers per household on public assistance was {topRecentYearHouseholdSnapData["Number of workers"].toLowerCase()} ({formatPercentage(topRecentYearHouseholdSnapData.totalShare)} of the population in {topRecentYearHouseholdSnapData.Geography}). : ""} + {householdSnapDataAvailable ? The most common number of workers per household on public assistance was {topRecentYearHouseholdSnapData["Number of workers"].toLowerCase()} ({formatPercentage(topRecentYearHouseholdSnapData.totalShare)} of the population in {topRecentYearHouseholdSnapData.Geography}). : ""}

- {householdSnapDataAvailable ?

The following chart shows the number of workers per household on public assistance.

: ""} + {householdSnapDataAvailable ?

The following chart shows the number of workers per household on public assistance broken down by family structure.

: ""} diff --git a/app/pages/Profile/sections/economy/Poverty.jsx b/app/pages/Profile/sections/economy/Poverty.jsx index d98b421..16d9314 100644 --- a/app/pages/Profile/sections/economy/Poverty.jsx +++ b/app/pages/Profile/sections/economy/Poverty.jsx @@ -113,14 +113,14 @@ class Poverty extends SectionColumns { ]} /> {immigrantsInPovertyAvailable && formatPopulation(immigrantsInPovertyData.share) !== "0%" ? In {topMalePovertyData.Year}, most common male age in poverty was {povertyByAgeAndGenderAvailable && topMalePovertyData.share !== 0 ? topMalePovertyData.Age.toLowerCase() : "N/A"} ({formatPopulation(topMalePovertyData.share)} of the male population) while most common female age was {povertyByAgeAndGenderAvailable && topFemalePovertyData.share !== 0 ? topFemalePovertyData.Age.toLowerCase() : "N/A"} ({formatPopulation(topFemalePovertyData.share)} of the female population) in {topFemalePovertyData.Geography}.

: ""} - {povertyByRaceAvailable ?

In {topPovertyByRace.Year}, the majority race in poverty was {topPovertyByRace.Race} ({formatPopulation(topPovertyByRace.share)} of the total population in {topPovertyByRace.Geography}).

: ""} + {povertyByAgeAndGenderAvailable ?

In {topMalePovertyData.Year}, the most common male age in poverty was {povertyByAgeAndGenderAvailable && topMalePovertyData.share !== 0 ? topMalePovertyData.Age.toLowerCase() : "N/A"} ({formatPopulation(topMalePovertyData.share)} of the male population) while the most common female age was {povertyByAgeAndGenderAvailable && topFemalePovertyData.share !== 0 ? topFemalePovertyData.Age.toLowerCase() : "N/A"} ({formatPopulation(topFemalePovertyData.share)} of the female population) in {topFemalePovertyData.Geography}.

: ""} + {povertyByRaceAvailable ?

In {topPovertyByRace.Year}, the most common race/ethnicity in poverty was {topPovertyByRace.Race} ({formatPopulation(topPovertyByRace.share)} of the total population in {topPovertyByRace.Geography}).

: ""} @@ -155,7 +155,7 @@ class Poverty extends SectionColumns { y: "Race", x: "share", time: "Year", - title: d => `Population in Poverty by Race in ${d[0].Geography}`, + title: d => `Population in Poverty by Race/Ethnicity in ${d[0].Geography}`, xConfig: { tickFormat: d => formatPopulation(d), title: "Share" diff --git a/app/pages/Profile/sections/economy/Unemployment.jsx b/app/pages/Profile/sections/economy/Unemployment.jsx index 4c785fd..ccbd26e 100644 --- a/app/pages/Profile/sections/economy/Unemployment.jsx +++ b/app/pages/Profile/sections/economy/Unemployment.jsx @@ -84,7 +84,7 @@ class Unemployment extends SectionColumns { Unemployment rate data is shown for {unemploymentRate.data[0].Geography} }

- {workExperienceAvailable ? In {getMaleFullTimeData[0].Year}, the percentage of the working population in {getMaleFullTimeData[0].Geography} that worked full-time was {formatPercentage(getMaleFullTimeData[0].share)} for men and {formatPercentage(getFemaleFullTimeData[0].share)} for women. : ""} + {workExperienceAvailable ? In {getMaleFullTimeData[0].Year}, the gender breakdown of the working population in {getMaleFullTimeData[0].Geography} that worked full-time was {formatPercentage(getMaleFullTimeData[0].share)} for men and {formatPercentage(getFemaleFullTimeData[0].share)} for women. : ""} {employmentStatusAvailable ? The most common unemployed age group for men was {getTopMaleUnemploymemtData.Age.toLowerCase()} ({formatPercentage(getTopMaleUnemploymemtData.share)}), and the most common female unemployed age group for women was {getTopFemaleUnemploymemtData.Age.toLowerCase()} ({formatPercentage(getTopFemaleUnemploymemtData.share)}). : ""} - {} In {recentYearUnemploymentRate.Year}, the overall unemploymemt rate in {recentYearUnemploymentRate.Geography} was {formatPercentage(recentYearUnemploymentRate["Unemployment Rate"])}. + {} In {recentYearUnemploymentRate.Year}, the overall unemployment rate in {recentYearUnemploymentRate.Geography} was {formatPercentage(recentYearUnemploymentRate["Unemployment Rate"])}.

diff --git a/app/pages/Profile/sections/education/DropoutRate.jsx b/app/pages/Profile/sections/education/DropoutRate.jsx index 6b9d8e0..3f25fd1 100644 --- a/app/pages/Profile/sections/education/DropoutRate.jsx +++ b/app/pages/Profile/sections/education/DropoutRate.jsx @@ -44,7 +44,7 @@ class DropoutRate extends SectionColumns { Data is shown at the zip level {/* Top stats about High School Dropout Rate. */} -

In {topFemaleData.Year}, the most common education level attained in {topFemaleData.Geography} by female was {formatLabels(topFemaleData["Educational Attainment"]).toLowerCase()} ({formatPopulation(topFemaleData.share)}) {} - and for male it was {formatLabels(topMaleData["Educational Attainment"]).toLowerCase()} ({formatPopulation(topMaleData.share)}).

-

The following chart shows educational attainment of male and female in {topMaleData.Geography}.

+

In {topFemaleData.Year}, the most common education level attained in {topFemaleData.Geography} by women was {formatLabels(topFemaleData["Educational Attainment"]).toLowerCase()} ({formatPopulation(topFemaleData.share)}) {} + and for men it was {formatLabels(topMaleData["Educational Attainment"]).toLowerCase()} ({formatPopulation(topMaleData.share)}).

+

The following chart shows educational attainment by gender in {topMaleData.Geography}.

@@ -114,10 +114,10 @@ class EducationalAttainment extends SectionColumns { x: "Educational Attainment", y: "share", time: "ID Year", + title: "Educational Attainment by Gender", xSort: (a, b) => a["ID Educational Attainment"] - b["ID Educational Attainment"], xConfig: { - tickFormat: d => formatLabels(d), - title: "Educational Attainment by Gender" + tickFormat: d => formatLabels(d) }, yConfig: { tickFormat: d => formatPopulation(d), diff --git a/app/pages/Profile/sections/education/ReadingAssessment.jsx b/app/pages/Profile/sections/education/ReadingAssessment.jsx index b11b6cb..62b6c56 100644 --- a/app/pages/Profile/sections/education/ReadingAssessment.jsx +++ b/app/pages/Profile/sections/education/ReadingAssessment.jsx @@ -154,7 +154,7 @@ class ReadingAssessment extends SectionColumns { {dropdownList.map(item => )} -

The following chart shows the average reading assessment score {isParentsEducationSelected ? "for 8th grade students" : ""} in Detroit {isOverallSelected ? "compared to Michigan and the United States" : isParentsEducationSelected ? `by their ${dropdownValue.toLowerCase()}` : `by ${dropdownValue === "ELL" || dropdownValue === "NSLP" ? dropdownValue : dropdownValue.toLowerCase()}`}.

+

The following chart shows the average reading assessment scores {isParentsEducationSelected ? "for 8th grade students" : ""} in Detroit {isOverallSelected ? "compared to Michigan and the United States" : isParentsEducationSelected ? `by their ${dropdownValue.toLowerCase()}` : `by ${dropdownValue === "ELL" || dropdownValue === "NSLP" ? dropdownValue : dropdownValue.toLowerCase()}`}.

{isParentsEducationSelected ? {/* fourth grade stats */} {/* eighth grade stats */} `${d}th Grade` }, y: isOverallSelected ? "Average Reading Score" : `Average Reading Score by ${dropdownValue}`, yConfig: { - title: `Average Reading Score by ${dropdownValue}` + title: isOverallSelected ? "Average Reading Score" : `Average Reading Score by ${dropdownValue}` }, groupPadding: 25, barPadding: 3, diff --git a/app/pages/Profile/sections/education/StudentPoverty.jsx b/app/pages/Profile/sections/education/StudentPoverty.jsx index 7c68eac..8cf479a 100644 --- a/app/pages/Profile/sections/education/StudentPoverty.jsx +++ b/app/pages/Profile/sections/education/StudentPoverty.jsx @@ -89,8 +89,8 @@ class StudentPoverty extends SectionColumns { value={formatPopulation(enrolledInSchoolPercentage)} qualifier={`of the population in ${topLevelOfSchoolData.Geography}`} /> -

In {topLevelOfSchoolData.Year}, the most common education level of students in {topLevelOfSchoolData.Geography} living in poverty were {topLevelOfSchoolData["Level of School"].toLowerCase()} ({formatPopulation(topLevelOfSchoolData.share)} of the population enrolled in this grade) and {formatPopulation(enrolledInSchoolPercentage)} of the total population was enrolled in school in {topLevelOfSchoolData.Geography}.

-

The following chart shows the level of school and the share of students in poverty that were enrolled in school.

+

In {topLevelOfSchoolData.Year}, the most common education level of students in {topLevelOfSchoolData.Geography} living in poverty were enrolled in {formatLabel(topLevelOfSchoolData["Level of School"]).toLowerCase()} ({formatPopulation(topLevelOfSchoolData.share)} of the population enrolled in this grade) and {formatPopulation(enrolledInSchoolPercentage)} of the total population was enrolled in school in {topLevelOfSchoolData.Geography}.

+

The following chart shows each level of school and the share of students in poverty that were enrolled.

diff --git a/app/pages/Profile/sections/foodAccess/FoodAvailability.jsx b/app/pages/Profile/sections/foodAccess/FoodAvailability.jsx index 659f80e..13e6f9b 100644 --- a/app/pages/Profile/sections/foodAccess/FoodAvailability.jsx +++ b/app/pages/Profile/sections/foodAccess/FoodAvailability.jsx @@ -71,13 +71,13 @@ class FoodAvailability extends SectionColumns { Data is shown for {topStore.Geography} } -

In {topStore.Year}, the most available food stores in {topStore.Geography} were {topStore["Sub-category"].toLowerCase()} ({commas(topStore["Number of Food Stores"])}) out of all food store types.

-

The chart here shows the share of fast-food restaurants, full-service restaurants, convenience stores, grocery stores, specialized food stores, supercenters and farmers market in {meta.name}.

+

In {topStore.Year}, the most common food store type available in {topStore.Geography} was {topStore["Sub-category"].toLowerCase()} ({commas(topStore["Number of Food Stores"])}).

+

The chart here shows the share of fast-food restaurants, full-service restaurants, convenience stores, grocery stores, specialized food stores, supercenters and farmers market in {topStore.Geography}.

diff --git a/app/pages/Profile/sections/foodAccess/FoodStamps.jsx b/app/pages/Profile/sections/foodAccess/FoodStamps.jsx index 17b111f..1692c16 100644 --- a/app/pages/Profile/sections/foodAccess/FoodStamps.jsx +++ b/app/pages/Profile/sections/foodAccess/FoodStamps.jsx @@ -128,9 +128,9 @@ class FoodStamps extends SectionColumns { } ]} /> -

The monthly average number of SNAP-authorized stores in {county} in {snapLatestYear} was {commas(snapLatestYearValue)} and there were {commas(wicLatestYearValue)} WIC-authorized stores in {wicLatestYear}.

+

The monthly average number of SNAP-authorized stores in {county} in {snapLatestYear} was {commas(snapLatestYearValue)}, and there were {commas(wicLatestYearValue)} WIC-authorized stores in {wicLatestYear}.

In {topPublicAssistanceData.Year}, {shareOfPopulationWithFoodStamps} of the population in {topPublicAssistanceData.Geography} had food stamps, out of which {formatPercentage(topPublicAssistanceData.share)} of the population were given food stamps in cash.

-

The chart here shows the share of population who gets food stamps in cash out of the population with food stamps.

+

The chart here shows the share of the population who gets food stamps in cash out of the population with food stamps.

@@ -150,6 +150,7 @@ class FoodStamps extends SectionColumns { data: `/api/data?measures=Food-Stamp Population&drilldowns=Public Assistance or Snap&Geography=${meta.id}&Year=all`, discrete: "x", height: 400, + baseline: 0, groupBy: "Public Assistance or Snap", x: "Year", y: "share", @@ -157,6 +158,7 @@ class FoodStamps extends SectionColumns { tickFormat: d => `${formatPercentage(d)}`, title: "Share" }, + title: "Food Stamp Population Using Cash Assistance", tooltipConfig: {tbody: [["Year", d => d.Year], ["Share", d => `${formatPercentage(d.share)}`], [titleCase(meta.level), d => d.Geography]]} }} dataFormat={resp => { diff --git a/app/pages/Profile/sections/foodAccess/StoreAccessByDemographic.jsx b/app/pages/Profile/sections/foodAccess/StoreAccessByDemographic.jsx index af8295c..2dd6a7c 100644 --- a/app/pages/Profile/sections/foodAccess/StoreAccessByDemographic.jsx +++ b/app/pages/Profile/sections/foodAccess/StoreAccessByDemographic.jsx @@ -77,15 +77,15 @@ class StoreAccessByDemographic extends SectionColumns { } {/* Show top stats for Age and Race groups based on the drilldown value. */} {/* Write a paragraph for top stats based on the dropdown choice. */} -

In {topFoodAccessData.Year}, {ageSelected ? `between children and seniors age groups, ${topFoodAccessData["Age Group"].toLowerCase()}` : topFoodAccessData["Race Group"].toLowerCase()} were the largest {ageSelected ? "age" : "race"} group ({ageSelected ? `${formatPercentage(topFoodAccessData["Low-Access to Food by Age"])} of all ${topFoodAccessData["Age Group"].toLowerCase()}` : `${formatPercentage(topFoodAccessData["Low-Access to Food by Race"])} of the population`}) in {topFoodAccessData.Geography} with low access to food stores.

+

In {topFoodAccessData.Year}, {ageSelected ? `between children and seniors, ${topFoodAccessData["Age Group"].toLowerCase()}` : topFoodAccessData["Race Group"].toLowerCase()} were the most at risk {ageSelected ? "age" : "race"} group for low access to food stores ({ageSelected ? `${formatPercentage(topFoodAccessData["Low-Access to Food by Age"])} of all ${topFoodAccessData["Age Group"].toLowerCase()}` : `${formatPercentage(topFoodAccessData["Low-Access to Food by Race"])} of the population`}) in {topFoodAccessData.Geography}.

Low access to healthy food is defined as being far from a supermarket, supercenter, or large grocery store.

-

The following map shows the low access rate for {dropdownValue.split(" ").length === 1 ? formatRaceText(dropdownValue).toLowerCase() : formatRaceText(dropdownValue)} with low access to food stores across all counties in Michigan.

+

The following map shows the rates for {dropdownValue.split(" ").length === 1 ? formatRaceText(dropdownValue).toLowerCase() : formatRaceText(dropdownValue)} with low access to food stores across all counties in Michigan.

@@ -115,7 +115,7 @@ class StoreAccessByDemographic extends SectionColumns { ticks: [] }, time: "Year", - title: d => `Low Access to Food Store in ${d[0].Geography}`, + title: d => `${ageSelected ? "Age Group Access" : "Race/Ethnicity Access"} in ${d[0].Geography}`, tooltipConfig: {tbody: [["Year", d => d.Year], ["Demographic", d => ageSelected ? `${d["Age Group"]}` : `${d["Race Group"]}`], ["Low-Access Rate", d => ageSelected ? formatPercentage(d["Low-Access to Food by Age"]) : formatPercentage(d["Low-Access to Food by Race"])], ["County", d => d.Geography]]} }} dataFormat={resp => { @@ -145,7 +145,7 @@ class StoreAccessByDemographic extends SectionColumns { }, label: d => d.County, time: "Year", - title: "Low Access to Food Store for Counties in Michigan", + title: `${dropdownValue} Access for Counties in Michigan`, tooltipConfig: {tbody: [["Year", d => d.Year], ["Demographic", dropdownValue], ["Low-Access Rate", d => ageSelected ? formatPercentage(d["Low-Access to Food by Age"]) : formatPercentage(d["Low-Access to Food by Race"])]]}, topojson: "/topojson/county.json", topojsonFilter: d => d.id.startsWith("05000US26") diff --git a/app/pages/Profile/sections/healthBehaviors/PhysicalInactivity.jsx b/app/pages/Profile/sections/healthBehaviors/PhysicalInactivity.jsx index 10b8c0a..8c3d742 100644 --- a/app/pages/Profile/sections/healthBehaviors/PhysicalInactivity.jsx +++ b/app/pages/Profile/sections/healthBehaviors/PhysicalInactivity.jsx @@ -1,6 +1,6 @@ import React from "react"; import {connect} from "react-redux"; -import {BarChart, Geomap} from "d3plus-react"; +import {Geomap} from "d3plus-react"; import {formatAbbreviate} from "d3plus-format"; import {fetchData, SectionColumns, SectionTitle} from "@datawheel/canon-core"; @@ -60,8 +60,8 @@ class PhysicalInactivity extends SectionColumns { Physical Inactivity
{!isPhysicalInactivityBySexAvailableForCurrentlocation - ? Data is shown for census tract level for four cities - : Data is shown at the census tract level for four cities + ? Data is shown at the census tract level for four cities + : null } -

In {topRecentYearData.Year}, {formatPercentage(topRecentYearData["Physical Inactivity"])} of the population of {topTractPlace !== undefined ? `, ${topTractPlace}` : ""} were physically inactive out of all census tracts in Detroit, Livonia, Dearborn and Westland.

+

In {topRecentYearData.Year}, {formatPercentage(topRecentYearData["Physical Inactivity"])} of the population of {topTractPlace !== undefined ? `, ${topTractPlace}` : ""} were physically inactive, the highest out of all census tracts in Detroit, Livonia, Dearborn and Westland.

In {topPhysicalInactivityFemaleData.Year}, {formatPercentage(topPhysicalInactivityMaleData["Age-Adjusted Physical Inactivity"])} of the male population and {formatPercentage(topPhysicalInactivityFemaleData["Age-Adjusted Physical Inactivity"])} of the female population in {} - {topPhysicalInactivityFemaleData.Geography} were physically inactive, as compared to {formatPercentage(stateLevelMaleData["Age-Adjusted Physical Inactivity"])} of the male and {formatPercentage(stateLevelFemaleData["Age-Adjusted Physical Inactivity"])} of the female population in Michigan overall.

+ {topPhysicalInactivityFemaleData.Geography} were physically inactive, as compared to {formatPercentage(stateLevelMaleData["Age-Adjusted Physical Inactivity"])} and {formatPercentage(stateLevelFemaleData["Age-Adjusted Physical Inactivity"])} in Michigan overall.

diff --git a/app/pages/Profile/sections/healthBehaviors/PreventiveCare.jsx b/app/pages/Profile/sections/healthBehaviors/PreventiveCare.jsx index f267552..c6dc409 100644 --- a/app/pages/Profile/sections/healthBehaviors/PreventiveCare.jsx +++ b/app/pages/Profile/sections/healthBehaviors/PreventiveCare.jsx @@ -142,8 +142,8 @@ class PreventiveCare extends SectionColumns { :

In {topDropdownData.Year}, {formatPercentage(topDropdownData[dropdownValue])} of the population of {topTractPlace !== undefined ? `, ${topTractPlace}` : ""} had {getArticle(dropdownValue)} {formatDropdownNames(dropdownValue).toLowerCase()} out of all tracts in Detroit, Livonia, Dearborn and Westland.

} {isPreventativeCareWeightedValueSelected - ?

The map here shows {formatDropdownNames(dropdownValue).toLowerCase()} for zip regions in Wayne County.

- :

The map here shows {formatDropdownNames(dropdownValue).toLowerCase()} for census tracts in Detroit, Livonia, Dearborn and Westland.

+ ?

The map here shows {formatDropdownNames(dropdownValue).toLowerCase()} rate for zip regions in Wayne County.

+ :

The map here shows {formatDropdownNames(dropdownValue).toLowerCase()} rate for census tracts in Detroit, Livonia, Dearborn and Westland.

} diff --git a/app/pages/Profile/sections/healthBehaviors/RiskyBehaviors.jsx b/app/pages/Profile/sections/healthBehaviors/RiskyBehaviors.jsx index d81b721..374c8d5 100644 --- a/app/pages/Profile/sections/healthBehaviors/RiskyBehaviors.jsx +++ b/app/pages/Profile/sections/healthBehaviors/RiskyBehaviors.jsx @@ -98,8 +98,8 @@ class RiskyBehaviors extends SectionColumns { qualifier={isSecondHandSmokeOrMonthlyAlcoholSelected ? `${formatPercentage(topSecondHandSmokeAndMonthlyAlcoholData[dropdownValue], true)} of the population of this zip region` : `${formatPercentage(topTractSmokingDrinkingData[dropdownValue])} of the population of this census tract`} /> {isSecondHandSmokeOrMonthlyAlcoholSelected - ?

In {topSecondHandSmokeAndMonthlyAlcoholData["End Year"]}, {formatPercentage(topSecondHandSmokeAndMonthlyAlcoholData[dropdownValue], true)} of the population of the {topSecondHandSmokeAndMonthlyAlcoholData["Zip Region"]} had the highest prevalence of {dropdownValue.toLowerCase()}, as compared to {formatPercentage(countyLevelData[0][dropdownValue], true)} overall for Wayne County.

- :

In {topTractSmokingDrinkingData.Year}, {formatPercentage(topTractSmokingDrinkingData[dropdownValue])} of the population of {topTractPlace !== undefined ? `, ${topTractPlace}` : ""} had the highest prevalence of {dropdownValue.toLowerCase()} out of census tracts in Detroit, Livonia, Dearborn and Westland.

+ ?

In {topSecondHandSmokeAndMonthlyAlcoholData["End Year"]}, {topSecondHandSmokeAndMonthlyAlcoholData["Zip Region"]} had the highest prevalence of {dropdownValue.toLowerCase()} ({formatPercentage(topSecondHandSmokeAndMonthlyAlcoholData[dropdownValue], true)} of the population), as compared to {formatPercentage(countyLevelData[0][dropdownValue], true)} overall for Wayne County.

+ :

In {topTractSmokingDrinkingData.Year}, {topTractPlace !== undefined ? `, ${topTractPlace}` : ""} had the highest prevalence of {dropdownValue.toLowerCase()} out of census tracts in Detroit, Livonia, Dearborn and Westland ({formatPercentage(topTractSmokingDrinkingData[dropdownValue])} of the population).

} diff --git a/app/pages/Profile/sections/healthConditions/CancerPrevalenceByDemographics.jsx b/app/pages/Profile/sections/healthConditions/CancerPrevalenceByDemographics.jsx index d5acc26..3e5237f 100644 --- a/app/pages/Profile/sections/healthConditions/CancerPrevalenceByDemographics.jsx +++ b/app/pages/Profile/sections/healthConditions/CancerPrevalenceByDemographics.jsx @@ -111,7 +111,7 @@ class CancerPrevalenceByDemographics extends SectionColumns {

In {occuranceByGender[0].Year}, the overall prevalence of cancer in the {occuranceByGender[0].MSA} for men and women was {formatAbbreviate(occuranceByGender[1]["Age-Adjusted Cancer Rate"])} and {formatAbbreviate(occuranceByGender[0]["Age-Adjusted Cancer Rate"])} per 100,000 people, respectively.

In {topOccuranceByRaceAndEthnicity.Year}, the race/ethnicity group in the {topOccuranceByRaceAndEthnicity.MSA} with the highest overall cancer rate was {topOccuranceByRaceAndEthnicity.Race} {topOccuranceByRaceAndEthnicity.Ethnicity} ({formatAbbreviate(topOccuranceByRaceAndEthnicity["Age-Adjusted Cancer Rate"])} per 100,000 people).

-

The following charts shows the occurrence rate per 100,000 people in {topOccuranceByRaceAndEthnicity.MSA} with gender breakdown and the race and Ethnicity breakdowns for {isItemsListEmpty ? topOccuranceByRaceAndEthnicity["Cancer Site"].toLowerCase() : "the selected cancer site(s)"}.

+

The following charts shows the occurrence rate per 100,000 people in {topOccuranceByRaceAndEthnicity.MSA} by gender and race/ethnicity for {isItemsListEmpty ? topOccuranceByRaceAndEthnicity["Cancer Site"].toLowerCase() : "the selected cancer site(s)"}.

@@ -137,6 +137,7 @@ class CancerPrevalenceByDemographics extends SectionColumns { x: "share", y: "Cancer Site", time: "Year", + title: "Gender Breakdown", xConfig: { tickFormat: d => formatPercentage(d), labelRotation: false @@ -184,6 +185,7 @@ class CancerPrevalenceByDemographics extends SectionColumns { label: d => `${d.Ethnicity} ${d.Race}`, x: "share", y: "Cancer Site", + title: "Race/Ethnicity Breakdown", time: "Year", xConfig: { tickFormat: d => formatPercentage(d), diff --git a/app/pages/Profile/sections/healthConditions/ObesityAndDiabetes.jsx b/app/pages/Profile/sections/healthConditions/ObesityAndDiabetes.jsx index 18a556a..a263f61 100644 --- a/app/pages/Profile/sections/healthConditions/ObesityAndDiabetes.jsx +++ b/app/pages/Profile/sections/healthConditions/ObesityAndDiabetes.jsx @@ -144,8 +144,8 @@ class ObesityAndDiabetes extends SectionColumns { {isBMIWeightedDataValueSelected - ? Data is shown for zip region level - : Data is shown for census tract level for four cities + ? Data is shown at the zip region level + : Data is shown at the census tract level for four cities } {/* Show top stats for the dropdown selected. */} @@ -229,8 +229,7 @@ class ObesityAndDiabetes extends SectionColumns { time: "ID Year", title: `${isDiabetesSelected ? "Diabetes" : "Obesity"} Rate by Gender in Wayne County`, xConfig: { - tickFormat: d => formatPercentage(d), - title: isDiabetesSelected ? "Diabetes Rate" : "Obesity Rate" + tickFormat: d => formatPercentage(d) }, yConfig: { barConfig: { @@ -275,7 +274,7 @@ class ObesityAndDiabetes extends SectionColumns { }, label: d => d["Zip Region"], time: "End Year", - title: `${dropdownValue} for Zip Regions in Wayne County`, + title: `${dropdownValue} by Zip Regions in Wayne County`, tooltipConfig: isHealthyWeightSelected ? {tbody: [["Year", d => d.Year], ["Condition", `${dropdownValue}`], ["Share", d => `${formatPercentage(d[dropdownValue], true)}`]]} : {tbody: [["Year", d => d.Year], ["Condition", `${dropdownValue}`], ["Prevalence", d => `${formatPercentage(d[dropdownValue], true)}`]]}, topojson: "/topojson/zipregions.json", @@ -302,7 +301,7 @@ class ObesityAndDiabetes extends SectionColumns { }, label: d => `${d.Tract}, ${tractToPlace[d["ID Tract"]]}`, time: "Year", - title: `${dropdownValue} for Census Tracts within Detroit, Livonia, Dearborn and Westland`, + title: `${dropdownValue} Prevalence by Census Tracts within Detroit, Livonia, Dearborn and Westland`, tooltipConfig: {tbody: [["Year", d => d.Year], ["Condition", `${dropdownValue}`], ["Prevalence", d => `${formatPercentage(d[dropdownValue])}`]]}, topojson: "/topojson/tract.json", topojsonId: d => d.id, diff --git a/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx b/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx index 8471fd2..69c9951 100644 --- a/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx +++ b/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx @@ -5,7 +5,6 @@ import {titleCase} from "d3plus-text"; import axios from "axios"; import {fetchData, SectionColumns, SectionTitle} from "@datawheel/canon-core"; -import {Classes, Tooltip} from "@blueprintjs/core"; import Contact from "components/Contact"; import Disclaimer from "components/Disclaimer"; @@ -35,8 +34,6 @@ const pollutantDefinitions = [ {term: "Sulphur Dioxide (S02)", definition: "Potential health effects from exposure to sulphur dioxide are - narrowing of the airways leading to wheezing, chest tightness and shortness of breath, more frequent asthma attacks in people with asthma and exacerbation of cardiovascular diseases."} ]; -const goodQualityDefinition =

Good quality air pertains to the degree which the air is clean, clear and free from pollutants such as smoke, dust and smog among other gaseous impurities in the air.

; - const formatAirQualityDaysName = d => d.replace(" days", ""); class AirQuality extends SectionColumns { diff --git a/app/pages/Profile/sections/specialPopulation/DisabilityStatus.jsx b/app/pages/Profile/sections/specialPopulation/DisabilityStatus.jsx index 11877ee..6072f5d 100644 --- a/app/pages/Profile/sections/specialPopulation/DisabilityStatus.jsx +++ b/app/pages/Profile/sections/specialPopulation/DisabilityStatus.jsx @@ -79,10 +79,10 @@ class DisabilityStatus extends SectionColumns { title="Largest age group with a disibility" year={disabilityStatusAvailable ? topDisabilityStatus.Year : ""} value={disabilityStatusAvailable && topDisabilityStatus.share !== 0 ? rangeFormatter(topDisabilityStatus.Age) : "N/A"} - qualifier={disabilityStatusAvailable ? `(${formatPopulation(topDisabilityStatus.share)})` : ""} + qualifier={disabilityStatusAvailable ? `(${formatPopulation(topDisabilityStatus.share)} of the population in ${topDisabilityStatus.Geography})` : ""} /> {/* Write short paragraph describing stats and barchart. */} - {disabilityStatusAvailable ?

In {topDisabilityStatus.Year}, the most common disabled age group was {topDisabilityStatus.share !== 0 ? rangeFormatter(topDisabilityStatus.Age) : "N/A"} years making up {formatPopulation(topDisabilityStatus.share)} of all disabled citizens within this age group in {topDisabilityStatus.Geography}.

: ""} + {disabilityStatusAvailable ?

In {topDisabilityStatus.Year}, the most common disabled age group was {topDisabilityStatus.share !== 0 ? rangeFormatter(topDisabilityStatus.Age) : "N/A"}, making up {formatPopulation(topDisabilityStatus.share)} of all citizens in {topDisabilityStatus.Geography}.

: ""} {healthCoverageTypeAvailable ?

The chart here shows the health coverage breakdown of the disabled population by age in {filteredHealthCoverageType[0].Geography}.

: ""} @@ -111,8 +111,7 @@ class DisabilityStatus extends SectionColumns { x: "share", time: "Year", yConfig: { - tickFormat: d => rangeFormatter(d), - title: "Age group" + tickFormat: d => rangeFormatter(d) }, xConfig: { tickFormat: d => formatPopulation(d) diff --git a/app/pages/Profile/sections/specialPopulation/Homeless.jsx b/app/pages/Profile/sections/specialPopulation/Homeless.jsx index 86320d7..ca23a0a 100644 --- a/app/pages/Profile/sections/specialPopulation/Homeless.jsx +++ b/app/pages/Profile/sections/specialPopulation/Homeless.jsx @@ -101,20 +101,20 @@ class Homeless extends SectionColumns { title={"Most common Sheltered demographic"} year={topShelteredHomelessCategory.Year} value={topShelteredHomelessCategory.Category} - qualifier={formatPercentage(topShelteredHomelessCategory.shelteredShare)} + qualifier={`${formatPercentage(topShelteredHomelessCategory.shelteredShare)} of sheltered population`} />

In {totalHomelessData.data[0].Year}, {formatPercentage(totalHomelessPopulation)} of the population in {totalHomelessData.data[0].Geography} was homeless. { } The most common sheltered demographic was {topShelteredHomelessCategory.Category.toLowerCase()} ({formatPercentage(topShelteredHomelessCategory.shelteredShare)}) { } - and unsheltered demographic was {topUnshelteredHomelessCategory.Category.toLowerCase()} ({formatPercentage(topUnshelteredHomelessCategory.unshelteredShare)}).

+ and the most common unsheltered demographic was {topUnshelteredHomelessCategory.Category.toLowerCase()} ({formatPercentage(topUnshelteredHomelessCategory.unshelteredShare)}).

-

Following charts shows different categories and types of sheltered and unsheltered homeless population in {totalHomelessData.data[0].Geography} and percentages for each one of them.

+

The following charts show the different categories and types of sheltered and unsheltered homeless population in {totalHomelessData.data[0].Geography}.

diff --git a/app/pages/Profile/sections/specialPopulation/Immigrants.jsx b/app/pages/Profile/sections/specialPopulation/Immigrants.jsx index 49892b7..311cc6a 100644 --- a/app/pages/Profile/sections/specialPopulation/Immigrants.jsx +++ b/app/pages/Profile/sections/specialPopulation/Immigrants.jsx @@ -90,9 +90,9 @@ const formatGeomapData = (data, meta, childrenTractIds, totalImmigrantsSelected }; const getGeomapTitle = (meta, dropdownValue) => { - if (meta.level === "county") return `City with most immigrtants ${dropdownValue === "Total Immigrants" ? "" : "in poverty"} in Wayne County`; - else if (meta.level === "tract") return `Census tract with most immigrants ${dropdownValue === "Total Immigrants" ? "" : "in poverty"} in Wayne County`; - else return `Census tract with most immigrants ${dropdownValue === "Total Immigrants" ? "" : "in poverty"} in ${meta.name}`; + if (meta.level === "county") return `The city with most immigrtants ${dropdownValue === "Total Immigrants" ? "" : "in poverty"} in Wayne County`; + else if (meta.level === "tract") return `The census tract with most immigrants ${dropdownValue === "Total Immigrants" ? "" : "in poverty"} in Wayne County`; + else return `The census tract with most immigrants ${dropdownValue === "Total Immigrants" ? "" : "in poverty"} in ${meta.name}`; }; const getGeomapQualifier = (data, meta) => { @@ -219,7 +219,7 @@ class Immigrants extends SectionColumns { :

In {USImmigrantsData.Year}, {formatPercentage(wayneCountyImmigrantsData.share)} of the population in Wayne County were immigrants, compared to {} {formatPercentage(michiganImmigrantsData.share)} in Michigan, and {formatPercentage(USImmigrantsData.share)} in the United States.

} -

{`${getGeomapTitle(meta, dropdownValue)} was ${formatGeomapLabel(topStats, meta, tractToPlace)} (${getGeomapQualifier(topStats, meta)}).`}

+

{`${getGeomapTitle(meta, dropdownValue)} was ${topStats.Geography} (${getGeomapQualifier(topStats, meta)}).`}

{immigrantsDataForCurrentLocationAvailable ?

The map here shows the {meta.level === "county" ? "cities" : "tracts"} in {meta.level === "county" || meta.level === "tracts" ? "Wayne County" : `${meta.name}`} by their percentage of immigrants.

: ""}
@@ -243,7 +243,7 @@ class Immigrants extends SectionColumns { :

In {wayneCountyImmigrantsData.Year}, {formatPercentage(wayneCountyImmigrantsData.share)} of the population in in Wayne County were immigrants in poverty, compared to {} {formatPercentage(michiganImmigrantsData.share)} in Michigan and {formatPercentage(USImmigrantsData.share)} in the United States.

} -

{`${getGeomapTitle(meta, dropdownValue)} was ${formatGeomapLabel(topStats, meta, tractToPlace)} (${getGeomapQualifier(topStats, meta)}).`}

+

{`${getGeomapTitle(meta, dropdownValue)} was ${topStats.Geography} (${getGeomapQualifier(topStats, meta)}).`}

{immigrantsDataForCurrentLocationAvailable ?

The map here shows the {meta.level === "county" ? "cities" : "tracts"} in {meta.level === "county" || meta.level === "tracts" ? "Wayne County" : `${meta.name}`} by their percentage of immigrants in poverty.

: ""}
} diff --git a/app/pages/Profile/sections/specialPopulation/Incarceration.jsx b/app/pages/Profile/sections/specialPopulation/Incarceration.jsx index 6fdaf72..398d2de 100644 --- a/app/pages/Profile/sections/specialPopulation/Incarceration.jsx +++ b/app/pages/Profile/sections/specialPopulation/Incarceration.jsx @@ -109,7 +109,7 @@ class Incarceration extends SectionColumns { value={`${formatName(topPunishmentData.Punishment)}`} qualifier={`(${formatPercentage(topPunishmentData.share)})`} /> -

In {topIncarcerationData.Year}, the most common crime in {topIncarcerationData.Geography} was {topOffenceData.Offense.toLowerCase()} ({formatPercentage(topOffenceData.share)}) and the most common punishment was {topPunishmentData.Punishment.toLowerCase()} ({formatPercentage(topPunishmentData.share)}).

+

In {topIncarcerationData.Year}, the most common crime in {topIncarcerationData.Geography} was {topOffenceData.Offense.toLowerCase()} ({formatPercentage(topOffenceData.share)}), and the most common punishment was {formatName(topPunishmentData.Punishment).toLowerCase()} ({formatPercentage(topPunishmentData.share)}).

This chart shows the percentages of punishments broken down by offense type for all convicted crimes in {topIncarcerationData.Geography}.

diff --git a/app/pages/Profile/sections/specialPopulation/Veterans.jsx b/app/pages/Profile/sections/specialPopulation/Veterans.jsx index 47d6460..e1047e3 100644 --- a/app/pages/Profile/sections/specialPopulation/Veterans.jsx +++ b/app/pages/Profile/sections/specialPopulation/Veterans.jsx @@ -111,9 +111,10 @@ class Veterans extends SectionColumns { qualifier={periodOfServiceAvailable ? `(${formatPercentage(topPeriodOfService.share)})` : ""} /> +

In {topEmploymentStatus.Year}, {veteransEmploymentStatusAvailable ? formatPercentage(topEmploymentStatus.share) : "N/A"} of the veteran population in {topEmploymentStatus.Geography} were unemployed, {} + while {veteransPovertyStatusAvailable ? formatPercentage(veteransPovertyStatus[0].share) : ""} were impoverished and {veteransDisabilityStatusAvailable ? formatPercentage(veteransDisabilityStatus[0].share) : "N/A"} were disabled.

{periodOfServiceAvailable ?

In {topPeriodOfService.Year}, the most common period of service for veterans in {topPeriodOfService.Geography} was {topPeriodOfService["Period of Service"]} ({formatPercentage(topPeriodOfService.share)}).

: ""} -

In {topEmploymentStatus.Year}, the unemployed veterans population of {topEmploymentStatus.Geography} was {veteransEmploymentStatusAvailable ? formatPercentage(topEmploymentStatus.share) : "N/A"}, while the impoverished population was {veteransPovertyStatusAvailable ? formatPercentage(veteransPovertyStatus[0].share) : ""} and the disabled veterans population was {veteransDisabilityStatusAvailable ? formatPercentage(veteransDisabilityStatus[0].share) : "N/A"}

- {periodOfServiceAvailable ?

The chart here shows the percentages of veterans that served in each period of service.

: ""} + {periodOfServiceAvailable ?

The chart here shows the percentages of veterans that served in the most common periods of service.

: ""} diff --git a/app/pages/Profile/sections/specialPopulation/VisionAndAuditoryDisabilities.jsx b/app/pages/Profile/sections/specialPopulation/VisionAndAuditoryDisabilities.jsx index 93e93a4..f88392d 100644 --- a/app/pages/Profile/sections/specialPopulation/VisionAndAuditoryDisabilities.jsx +++ b/app/pages/Profile/sections/specialPopulation/VisionAndAuditoryDisabilities.jsx @@ -79,9 +79,8 @@ const formatGeomapData = (data, meta, childrenTractIds, disability = "Vision") = }; const getGeomapTitle = (meta, disability) => { - if (meta.level === "county") return `City with most ${disability} disability in Wayne County`; - else if (meta.level === "tract") return `Census Tract with most ${disability} disability in Wayne County`; - else return `Census Tract with most ${disability} disability in ${meta.name}`; + if (meta.level === "county" || meta.level === "tract") return `Location with the highest ${disability} disability in Wayne County`; + else return `Location with the highest ${disability} disability in ${meta.name}`; }; const getGeomapQualifier = (data, meta) => { @@ -166,7 +165,7 @@ class VisionAndAuditoryDisabilities extends SectionColumns { {isVisionDisabilitySelected ?
:
- {visionDisabilityDataAvailable ? In {topMaleVisionDisabilityData.Year}, the age groups most likely to have vision disability in { } - {topMaleVisionDisabilityData.Geography} were {topMaleVisionDisabilityData.share !== 0 ? rangeFormatter(topMaleVisionDisabilityData.Age) : "N/A"} years for men and {topFemaleVisionDisabilityData.share !== 0 ? rangeFormatter(topFemaleVisionDisabilityData.Age) : "N/A"} { } - years for women. : ""} + {visionDisabilityDataAvailable ? In {topMaleVisionDisabilityData.Year}, the age groups most likely to have a vision disability in { } + {topMaleVisionDisabilityData.Geography} were {topFemaleVisionDisabilityData.share !== 0 ? rangeFormatter(topFemaleVisionDisabilityData.Age) : "N/A"} years for women and {topMaleVisionDisabilityData.share !== 0 ? rangeFormatter(topMaleVisionDisabilityData.Age) : "N/A"} { } + years for men. : ""}

:

- {hearingDisabilityDataAvailable ? In {topMaleHearingDisabilityData.Year}, the age groups most likely to have hearing disability in { } - {topMaleHearingDisabilityData.Geography} were {topMaleHearingDisabilityData.share !== 0 ? rangeFormatter(topMaleHearingDisabilityData.Age) : "N/A"} years for men and {topFemaleHearingDisabilityData.share !== 0 ? rangeFormatter(topFemaleHearingDisabilityData.Age) : "N/A"} { } - years for women. : ""} + {hearingDisabilityDataAvailable ? In {topMaleHearingDisabilityData.Year}, the age groups most likely to have a hearing disability in { } + {topMaleHearingDisabilityData.Geography} were {topFemaleHearingDisabilityData.share !== 0 ? rangeFormatter(topFemaleHearingDisabilityData.Age) : "N/A"} years for women and {topMaleHearingDisabilityData.share !== 0 ? rangeFormatter(topMaleHearingDisabilityData.Age) : "N/A"} { } + years for men. : ""}

} From a127941fab08bbe9f41c87cd5d5bf131907f5e7b Mon Sep 17 00:00:00 2001 From: James Ferrell Date: Thu, 9 May 2019 11:27:51 -0400 Subject: [PATCH 28/30] removes / renames empty divs --- app/css/layout.css | 4 +- .../accessToCare/HealthInsuranceCoverage.jsx | 52 +++++++-------- .../sections/education/ReadingAssessment.jsx | 2 +- .../healthBehaviors/RiskyBehaviors.jsx | 65 +++++++++---------- .../naturalEnvironment/AirQuality.jsx | 8 +-- .../VisionAndAuditoryDisabilities.jsx | 4 +- 6 files changed, 67 insertions(+), 68 deletions(-) diff --git a/app/css/layout.css b/app/css/layout.css index cf887df..8019ac6 100644 --- a/app/css/layout.css +++ b/app/css/layout.css @@ -222,7 +222,9 @@ layout color: inherit; /* style direct child paragraphs only */ - & > p { + /* TODO: replace with if updating react to v16 */ + & > p, + & > .article-inner-group > p { @add-mixin font-sm; width: 42em; max-width: 100%; diff --git a/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx b/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx index 6083a1b..3d52ca1 100644 --- a/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx +++ b/app/pages/Profile/sections/accessToCare/HealthInsuranceCoverage.jsx @@ -156,33 +156,31 @@ class HealthInsuranceCoverage extends SectionColumns { {!isCoverageDataAvailableForCurrentGeography && Data is shown for {coverageData.data[0].Geography} } -
- - -
+ + {meta.level !== "county" ?

In {nationCoverage.Year}, {formatPercentage(currentLevelCoverage.share)} of the population in {currentLevelCoverage.Geography} had health coverage, compared to {formatPercentage(countyCoverage.share)} in Wayne County, {formatPercentage(stateCoverage.share)} in Michigan and {formatPercentage(nationCoverage.share)} in the United States.

diff --git a/app/pages/Profile/sections/education/ReadingAssessment.jsx b/app/pages/Profile/sections/education/ReadingAssessment.jsx index 62b6c56..981dc9b 100644 --- a/app/pages/Profile/sections/education/ReadingAssessment.jsx +++ b/app/pages/Profile/sections/education/ReadingAssessment.jsx @@ -166,7 +166,7 @@ class ReadingAssessment extends SectionColumns { }))} /> - :
+ :
{/* fourth grade stats */} - this.viz1 = comp} config={{ - data: `/api/data?measures=Smoking Status Current,Smoking Status Former,Smoking Status Never&drilldowns=End Year&Geography=${id}`, // MiBRFS - All Years - height: 250, - value: d => d[d.SmokingType], - legend: false, - groupBy: "SmokingType", - label: d => { - const wordsArr = d.SmokingType.split(" "); - return `${wordsArr[2]}`; - }, - time: "End Year", - title: d => `Smoking Status in ${d[0].Geography}`, - shapeConfig: { - Path: { - fillOpacity: 1 + {dropdownValue === drugTypes[0] && + this.viz1 = comp} config={{ + data: `/api/data?measures=Smoking Status Current,Smoking Status Former,Smoking Status Never&drilldowns=End Year&Geography=${id}`, // MiBRFS - All Years + height: 250, + value: d => d[d.SmokingType], + legend: false, + groupBy: "SmokingType", + label: d => { + const wordsArr = d.SmokingType.split(" "); + return `${wordsArr[2]}`; + }, + time: "End Year", + title: d => `Smoking Status in ${d[0].Geography}`, + shapeConfig: { + Path: { + fillOpacity: 1 + } + }, + tooltipConfig: {tbody: [["Year", d => d["End Year"]], ["Prevalence", d => formatPercentage(d[d.SmokingType], true)], ["County", d => d.Geography]]} + }} + dataFormat={resp => { + const data = []; + resp.data.forEach(d => { + resp.source[0].measures.forEach(smokingType => { + if (d[smokingType] !== null) { + data.push(Object.assign({}, d, {SmokingType: smokingType})); } - }, - tooltipConfig: {tbody: [["Year", d => d["End Year"]], ["Prevalence", d => formatPercentage(d[d.SmokingType], true)], ["County", d => d.Geography]]} - }} - dataFormat={resp => { - const data = []; - resp.data.forEach(d => { - resp.source[0].measures.forEach(smokingType => { - if (d[smokingType] !== null) { - data.push(Object.assign({}, d, {SmokingType: smokingType})); - } - }); }); - this.setState({sources: updateSource(resp.source, this.state.sources)}); - return data; - }} - /> -
: null } + }); + this.setState({sources: updateSource(resp.source, this.state.sources)}); + return data; + }} + /> + }
diff --git a/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx b/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx index 3448982..ca24f78 100644 --- a/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx +++ b/app/pages/Profile/sections/naturalEnvironment/AirQuality.jsx @@ -117,7 +117,7 @@ class AirQuality extends SectionColumns { Data is shown for {airQualityDays.data[0].Geography} } {dropdownValue === "Air Quality Days" && -
+
} {dropdownValue === "Air Pollutants" && -
+
The glossary below gives further details about common air pollutants and their health effects.

} {dropdownValue === "Median Air Quality Index" && -
+
The glossary below explains air quality index (AQI) and different types of air quality with respect to AQI.

} {dropdownValue === "Unhealthy Air for Sensitive Groups" && -
+
{isVisionDisabilitySelected - ?
+ ?
- :
+ :
Date: Thu, 9 May 2019 11:40:46 -0400 Subject: [PATCH 29/30] lol fixes className for previous commit --- app/css/layout.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/css/layout.css b/app/css/layout.css index 8019ac6..1030056 100644 --- a/app/css/layout.css +++ b/app/css/layout.css @@ -224,7 +224,7 @@ layout /* style direct child paragraphs only */ /* TODO: replace with if updating react to v16 */ & > p, - & > .article-inner-group > p { + & > .article-inner-container > p { @add-mixin font-sm; width: 42em; max-width: 100%; From fd049ca88c0ce4f59dec719c49f339b2a39ae401 Mon Sep 17 00:00:00 2001 From: Rashmi Date: Thu, 9 May 2019 09:37:01 -0700 Subject: [PATCH 30/30] DistressScore - formats legend range scale --- app/pages/Profile/sections/economy/DistressScore.jsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/pages/Profile/sections/economy/DistressScore.jsx b/app/pages/Profile/sections/economy/DistressScore.jsx index 36b180f..f47ccd2 100644 --- a/app/pages/Profile/sections/economy/DistressScore.jsx +++ b/app/pages/Profile/sections/economy/DistressScore.jsx @@ -87,7 +87,16 @@ class DistressScore extends SectionColumns { styles["danger-light"], styles.danger, styles["danger-dark"] - ] + ], + legendConfig: { + // format range scale using formatAbbreviate function + label: d => { + const arr = d.id.split(" "); + const startRange = formatAbbreviate(parseFloat(arr[0])); + const endRange = formatAbbreviate(parseFloat(arr[2])); + return `${startRange} - ${endRange}`; + } + } }, height: 400, time: "Year",